Das Modul insbesondere der TTS Button läuft bei mir nicht. Kann es sein, dass Google bereits wieder etwas am Service geändert hat oder bin ich zu doof das einzurichten.
Hier mein Beispiel:
– SONOS Text To Speech (TTS) - Give voice to your HC2 with SONOS wireless speakers
– Version 0.0.4 pre-release
– Copyright © 2014 Jean-Christophe Vermandé
selfId = fibaro:getSelfId();
ip = fibaro:get(selfId, ‘IPAddress’);
port = fibaro:get(selfId, ‘TCPPort’);
currentTransportState = “”;
lastTransportState = “”;
currentVolume = 0;
lastVolume = 0;
ttsVolumeIsDifferent = false;
urlencode = function(str)
if (str) then
str = string.gsub (str, “\n”, “\r\n”);
str = string.gsub (str, “([^%w ])”, function © return string.format ("%%%02X", string.byte©) end);
str = string.gsub (str, " ", “+”);
end
return str;
end
createRequestBody = function(action, schema, data)
return string.format("<u:%s xmlns:u="%s">%s</u:%s>", action, schema, data, action);
end
reponseCallback = function(fnc, args)
if (fnc == nil) then
return nil;
end
return fnc(args);
end
createSocket = function()
– Check IP and PORT before
if (ip == nil or port == nil) then
fibaro:debug(“You must configure IPAddress and TCPPort first”);
return;
end
local socket;
local status, err = pcall(function()
socket = Net.FTcpSocket(ip, port);
socket:setReadTimeout(1000);
end);
if (status ~= nil and status ~= true) then
fibaro:debug("socket status: " … tostring(status or ‘’));
end
if (err ~= nil) then
fibaro:debug("socket err: " … tostring(err or ‘’));
return;
end
return socket;
end
disposeSocket = function(socket)
if (socket ~= nil) then
socket:disconnect();
socket = nil;
return true;
end
return false;
end
sendSoapMessage = function(url, service, action, args, callback, retry)
local socket = createSocket();
if (socket == nil) then
return;
end
retry = retry or 0
– prepare data
local url = “POST " … url … " HTTP/1.1”;
local soapaction = “SOAPACTION: “” … service … “#” … action.name … “””;
local body = createRequestBody(action.name, action.service, tostring(args or “”));
local envelope = "<?xml version=“1.0” encoding=“utf-8”?><s:Envelope xmlns:s=“http://schemas.xmlsoap.org/soap/envelope/” s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body>" … body … “</s:Body></s:Envelope>”;
local ctl = "Content-Length: " … string.len(envelope);
local payload = url … “\r\n” … ctl … “\r\n” … soapaction … “\r\n” … “\r\n” … envelope;
– write data
local bytes, errorcode = socket:write(payload);
if (errorcode == 0) then
local state, errorcode = socket:read();
if (errorcode == 0) then
if (string.len(state or “”) > 0) then
– callback
if (callback ~= nil) then
reponseCallback(callback, state);
end
– dispose …
disposeSocket(socket);
return true;
else
fibaro:debug(“Error: Invalid response. response length: " … string.len(state or “”));
end
else
if (retry < 5) then
fibaro:debug(“retry #”…retry…” action: " … action.name);
return sendSoapMessage(url, service, action, args, callback, (retry + 1));
else
fibaro:debug("Error: Code returned “…tostring(errorcode or “”));
end
end
elseif (errorcode == 2) then
fibaro:debug(“Error: You must check your IP and PORT settings.”);
else
if (retry < 5) then
fibaro:debug(“retry #”…retry…” action: " … action.name);
return sendSoapMessage(url, service, action, args, callback, (retry + 1));
else
fibaro:debug("Error: Code returned "…tostring(errorcode or “”));
end
end
– dispose …
disposeSocket(socket);
– default response
return false;
end
stop = function()
return sendSoapMessage(
– control url
“/MediaRenderer/AVTransport/Control”,
– service type
“urn:schemas-upnp-org:service:AVTransport:1”,
– action
{ name = “Stop”, service = “urn:schemas-upnp-org:service:AVTransport:1” },
– soap body data (options)
“<InstanceID>0</InstanceID><Speed>1</Speed>”,
– callback (options)
function(response)
fibaro:debug(“stop sent”);
end);
end
unMute = function()
return sendSoapMessage(
– control url
“/MediaRenderer/RenderingControl/Control”,
– service type
“urn:schemas-upnp-org:service:RenderingControl:1”,
– action
{ name = “SetMute”, service = “urn:schemas-upnp-org:service:RenderingControl:1” },
– soap body data (options)
“<InstanceID>0</InstanceID><Channel>Master</Channel><DesiredMute>0</DesiredMute>”,
– callback (options)
function(response)
fibaro:debug(“unMute sent”);
end);
end
play = function(duration)
return sendSoapMessage(
– control url
“/MediaRenderer/AVTransport/Control”,
– service type
“urn:schemas-upnp-org:service:AVTransport:1”,
– action
{ name = “Play”, service = “urn:schemas-upnp-org:service:AVTransport:1” },
– soap body data (options)
“<InstanceID>0</InstanceID><Speed>1</Speed>”,
– callback (options)
function(response)
if (duration ~= nil) then
fibaro:debug(“play sent for " … duration … " seconds”);
fibaro:sleep(duration);
stop();
else
fibaro:debug(“play sent”);
local n = 0;
currentTransportState = “TRANSITIONING”;
while (currentTransportState == “TRANSITIONING”) do
if (n > 10) then break end;
getTransportState();
fibaro:debug(currentTransportState);
fibaro:sleep(5000);
n = n + 1;
end
local i = 0;
currentTransportState = “PLAYING”;
while (currentTransportState == “PLAYING”) do
if (i > 10) then break end;
getTransportState();
fibaro:debug(currentTransportState);
fibaro:sleep(2000);
i = i + 1;
end
fibaro:sleep(1000);
stop();
end
– update volume with value before tts if different
if (ttsVolumeIsDifferent == true) then
setVolume(lastVolume);
ttsVolumeIsDifferent = false;
end
end);
end
setVolume = function(value)
return sendSoapMessage(
– control url
“/MediaRenderer/RenderingControl/Control”,
– service type
“urn:schemas-upnp-org:service:RenderingControl:1”,
– action
{ name = “SetVolume”, service = “urn:schemas-upnp-org:service:RenderingControl:1” },
– soap body data (options)
“<InstanceID>0</InstanceID><Channel>Master</Channel><DesiredVolume>” … tostring(value) … “</DesiredVolume>”,
– callback (options)
function(response)
fibaro:debug("Volume set: " … value);
end);
end
getVolume = function()
fibaro:log(“Get volume, please wait…”);
return sendSoapMessage(
– control url
“/MediaRenderer/RenderingControl/Control”,
– service type
“urn:schemas-upnp-org:service:AVTransport:1”,
– action
{ name = “GetVolume”, service = “urn:schemas-upnp-org:service:RenderingControl:1” },
– soap body data (options)
“<InstanceID>0</InstanceID><Channel>Master</Channel>”,
– callback (options)
function(response)
currentVolume = tonumber(response:match("<CurrentVolume>(.+)</CurrentVolume>") or 0);
end);
end
getTransportState = function()
return sendSoapMessage(
– control url
“/MediaRenderer/AVTransport/Control”,
– service type
“urn:schemas-upnp-org:service:AVTransport:1”,
– action
{ name = “GetTransportInfo”, service = “urn:schemas-upnp-org:service:AVTransport:1” },
– soap body data (options)
“<InstanceID>0</InstanceID>”,
– callback (options)
function(response)
currentTransportState = response:match("<CurrentTransportState>(.+)</CurrentTransportState>") or “”;
end);
end
playTTS = function(lng, message, duration, volume)
return sendSoapMessage(
– control url
“/MediaRenderer/AVTransport/Control”,
– service type
“urn:schemas-upnp-org:service:AVTransport:1”,
– action
{ name = “SetAVTransportURI”, service = “urn:schemas-upnp-org:service:AVTransport:1” },
– soap body data (options)
fibaro:debug(“tts start”);
“<InstanceID>0</InstanceID>,<CurrentURI>x-rincon-mp3radio://translate.google.com/translate_tts?client=t”… “&a” … “mp;tl=”… lng … “&a” … “mp;q=” … urlencode(message) … “</CurrentURI>,<CurrentURIMetaData></CurrentURIMetaData>”,
fibaro:debug(“tts end”);
– callback (options)
function(response)
– retrieve current transport state
getTransportState();
lastTransportState = currentTransportState;
– unmute before
unMute();
– retrieve volume
getVolume();
lastVolume = currentVolume;
– set tts volume if <> with current
if (volume ~= nil and volume ~= currentVolume) then
setVolume(volume);
ttsVolumeIsDifferent = true;
end
– play tts
fibaro:debug("tts: " … message);
if (duration ~= nil) then
play(duration);
else
play();
end
end);
end
playTTS(“de”, fibaro:getGlobalValue(“SONOS_TTS”), nil, 80);
Funktionierende URL im Browser: http://translate.google.com/translate_tts?client=t&tl=de&q=Willkommen+zu+Hause
Die Sonos Software gibt mir jeweils einen Fehler aus (siehe Anhang).
Danke für Eure Hilfe.
Gruss