Bonjour à tous,
Une mauvaise toux m'a cloué à la maison toute la journée.
Je me suis dès lors occupé en me lançant dans la création d'un "virtual device" réalisant une liaison entre : mon radio-réveil,un bon vieux MusiPal et ma toute nouvelle HC2.
L’objectif était :
De récupérer les alarmes du réveil pour en extraire le nombre de minutes avant la prochaine sonnerie et de le stocker dans une variable locale. Ce qui permettrait de lancer ensuite des scènes (ex:10min avant le chauffage électrique, 15min le café ...). D'écrire sur l'écran du radio/réveil un texte avec les raisons d'une alarme détectée sur l'HC2. De jouer un MP3 à distance (je n'y suis pour l'instant pas arrivé, si quelq'un à un episte à suivre !)
C'est là mon tout premier programme en LUA et il faut dire que la bête n'est pas facile à dompter (surtout avec le cerveau embrumé ;-)). Mais pourquoi donc n'ont-ils pas choisi chez Fibaro le Python, Java, ...???
Enfin tout retour de correction et/ou amélioration serait vraiment le bienvenu (et apprécié!)
local selfId = fibaro:getSelfId();
local Myip = fibaro:get(selfId, "IPAddress");
local Myport = fibaro:get(selfId, "TCPPort");
local urlGetState = "/admin/cgi-bin/state.cgi?fav=0";
local urlSentMsg = "/admin/cgi-bin/ipc_send?show_list%20";
local urlConfirmMsg = "/admin/cgi-bin/ipc_send?menu_collapse";
local urlPowerUp = "/admin/cgi-bin/ipc_send?power_up";
local urlPowerDown = "/admin/cgi-bin/ipc_send?power_down";
local urlChangeVolume = "/admin/cgi-bin/admin.cgi?f=volume_set&v=";
local urlPlayPause = "/admin/cgi-bin/admin.cgi?f=play_pause";
local urlSetFavorite = "/admin/cgi-bin/admin.cgi?f=favorites&n=../favorites.html&a=p&i=";
local urlSetAlarm = "/admin/cgi-bin/admin.cgi?f=wakeup_timer&type_4=1&hour_4=12&minute_4=12&apply=Apply"
HC2 = Net.FHttp(Myip);
HC2:setBasicAuthentication("admin", "xxxx");
response, status, errorCode = HC2:GET("/admin/cgi-bin/state.cgi?fav=0")
-----------------------------------------------------------------------------------------
-- LUA only XmlParser from Alexander Makeev / modifié
-----------------------------------------------------------------------------------------
XmlParser = {};
function XmlParser:FromXmlString(value)
value = string.gsub(value, "([%x]+)%;",
function(h)
return string.char(tonumber(h, 16))
end);
value = string.gsub(value, "([0-9]+)%;",
function(h)
return string.char(tonumber(h, 10))
end);
value = string.gsub(value, "&", "&");
value = string.gsub(value, "'", "'");
value = string.gsub(value, ">", ">");
value = string.gsub(value, "<", "<");
return value;
end
function XmlParser:ParseArgs(s)
local arg = {}
string.gsub(s, "(%w+)=([\"'])(.-)%2", function (w, _, a)
arg[w] = self:FromXmlString(a);
end)
return arg
end
function XmlParser:ParseXmlText(xmlText)
local stack = {}
local top = {Name=nil,Value=nil,Attributes={},ChildNodes={}}
table.insert(stack, top)
local ni,c,label,xarg, empty
local i, j = 1, 1
while true do
ni,j,c,label,xarg, empty = string.find(xmlText, "<(%/?)([%w:]+)(.-)(%/?)>", i)
if not ni then break end
local text = string.sub(xmlText, i, ni-1);
if not string.find(text, "^%s*$") then
top.Value=(top.Value or "")..self:FromXmlString(text);
end
if empty == "/" then -- empty element tag
table.insert(top.ChildNodes, {Name=label,Value=nil,Attributes=self:ParseArgs(xarg),ChildNodes={}})
elseif c == "" then -- start tag
top = {Name=label, Value=nil, Attributes=self:ParseArgs(xarg), ChildNodes={}}
table.insert(stack, top) -- new level
--log("openTag ="..top.Name);
else -- end tag
local toclose = table.remove(stack) -- remove top
--log("closeTag="..toclose.Name);
top = stack[#stack]
if #stack < 1 then
error("XmlParser: nothing to close with "..label)
end
if toclose.Name ~= label then
error("XmlParser: trying to close "..toclose.Name.." with "..label)
end
table.insert(top.ChildNodes, toclose)
end
i = j+1
end
local text = string.sub(xmlText, i);
if not string.find(text, "^%s*$") then
stack[#stack].Value=(stack[#stack].Value or "")..self:FromXmlString(text);
end
if #stack > 1 then
error("XmlParser: unclosed "..stack[stack.n].Name)
end
return stack[1].ChildNodes[1];
end
-- main loop if answer is ok
fibaro:log(status)
if tonumber(status) == 200 and tonumber(errorCode) == 0 then
if (response ~= nil) then
local xmlTree=XmlParser:ParseXmlText(response)
for i,xmlNode in pairs(xmlTree.ChildNodes) do
if(xmlNode.Name=="alarms") then
AlarmNextF=os.time{year=2030, month=01, day=01, hour=00, min=00, sec=00}
for i,subXmlNode in pairs(xmlNode.ChildNodes) do
if(subXmlNode.Name=="alarm") then
for i,subsubXmlNode in pairs(subXmlNode.ChildNodes) do
if (subsubXmlNode.Name=="time") then
Alarmtime=subsubXmlNode.Value
elseif (subsubXmlNode.Name=="type") then
Alarmtype=subsubXmlNode.Value
end
end
pos=string.find(Alarmtime, ":")
AlarmTimeH=string.sub(Alarmtime,1,pos-1)
AlarmTimeM=string.sub(Alarmtime,pos+1)
if(Alarmtype=="0") then --
--Alarmtype==0 disable
elseif (Alarmtype=="1") or (Alarmtype=="3") or (Alarmtype=="2") then --une fois,All day or workday
AlarmNext = os.date("*t")
AlarmNext.hour=AlarmTimeH
AlarmNext.min=AlarmTimeM
AlarmNext.sec=AlarmTimeM
if (os.difftime(os.time(),os.time(AlarmNext)) ) > 0 then --alarme déjà passée
AlarmNext.day = AlarmNext.day + 1
end
if (Alarmtype=="2") then --workday
if (AlarmNext.wday ==1 ) then
AlarmNext.day = AlarmNext.day + 1 ;
elseif (AlarmNext.wday ==7 ) then
AlarmNext.day = AlarmNext.day + 2 ;
end
end
if (os.time(AlarmNext) < AlarmNextF) then AlarmNextF = os.time(AlarmNext) end
--print(os.date("%c", os.time(AlarmNext)))
else --dimanche(4) to samedi10)
AlarmWeekDay=Alarmtype-3
AlarmNext = os.date("*t")
AlarmNext.hour=AlarmTimeH
AlarmNext.min=AlarmTimeM
AlarmNext.sec=AlarmTimeM
if (AlarmNext.wday==AlarmWeekDay) then
if (os.difftime(os.time(),os.time(AlarmNext)) ) > 0 then --alarme déjà passée
AlarmNext.day = AlarmNext.day + 7
end
else
if (AlarmNext.wday>AlarmWeekDay) then
AlarmNext.day = AlarmNext.day + (7-(AlarmNext.wday-AlarmWeekDay))
else
AlarmNext.day = AlarmNext.day + (AlarmWeekDay-AlarmNext.wday)
end
end
if (os.time(AlarmNext) < AlarmNextF) then AlarmNextF=os.time(AlarmNext) end
-- print(os.date("%c", os.time(AlarmNext)))
end
end
end -- end Alarmes
if (os.date("%Y",AlarmNextF)==2030) then -- pas de réveil
else
a=os.date("%M")
b=4
MyPie=( a - math.floor(a/b)*
if (MyPie == 0) then MyPieTxT= ">"
elseif (MyPie == 1) then MyPieTxT= "V"
elseif (MyPie == 2) then MyPieTxT= "<"
elseif (MyPie == 3) then MyPieTxT= "A"
end
fibaro:call(selfId,"setProperty","ui.Label1.value",MyPieTxT .. " " .. os.date("%H", AlarmNextF) .. ":" .. os.date("%M", AlarmNextF) .. " " .. os.date("%a", AlarmNextF) .. " " .. os.date("%d", AlarmNextF) .. "-" .. os.date("%m", AlarmNextF) )
fibaro:debug("Alarme:" .. MyPieTxT .. " " .. os.date("%H", AlarmNextF) .. ":" .. os.date("%M", AlarmNextF) .. " " .. os.date("%a", AlarmNextF) .. " " .. os.date("%d", AlarmNextF) .. "-" .. os.date("%m", AlarmNextF) )
local MusicPalTimeRest=math.floor(os.difftime(AlarmNextF, os.time())/60)
--if fibaro:existsGlobalValue("MusicPalTimeRest")==false then
--fibaro:createGlobalValue("MusicPalTimeRest","MusicPalTimeRest");
--else
fibaro:setGlobal("MusicPalTimeRest",MusicPalTimeRest )
--end
end
end --for
end
else
fibaro:debug('Error : Can not connect to Web server, empty response')
end
else
fibaro:debug('Error : Can not connect to Web server, status='..status..', errorCode='..errorCode)
end
-- Wait 60s
fibaro:sleep(60*1000)
NB: ne pas oublier de créer la variable "MusicPalTimeRest", je ne suis pas parvenu à le faire via code ??? Si qlq'un sait comment faire ?
et voici une exemple de bouton play/pause
local selfId = fibaro:getSelfId();
local Myip = fibaro:get(selfId, "IPAddress");
local urlPowerUp = "/admin/cgi-bin/ipc_send?power_up";
local urlPlayPause = "/admin/cgi-bin/admin.cgi?f=play_pause";
HC2 = Net.FHttp(Myip)
HC2:setBasicAuthentication("admin", "xxxx");
local response = HC2:GET(urlPowerUp)
local response = HC2:GET(urlPlayPause)
Et voici un exemple de réalisation.
J'espère que ce partage pourra être utile à d'autres.
Bà v
Jacky