Aller au contenu
leji1

Liaison Entre Un Radio/réveil Musicpal & Hc2

Recommended Posts

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 :

 

  1. 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é ...).
  2. D'écrire sur l'écran du radio/réveil un texte avec les raisons d'une alarme détectée sur l'HC2.
  3. 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.

 

02.08.2015-21.12.png

 

J'espère que ce partage pourra être utile à  d'autres.

Bà v

 

Jacky

Partager ce message


Lien à poster
Partager sur d’autres sites

×