18 апреля 2016 г.

Скрипт LUA уведомляющий о статусах батареек в Fibaro HC2

Довелось настраивать изделие для домашней автоматизации от Fibaro под незатейливым названием Home Center 2.
Суть: имеется несколько десятков беспроводных датчиков и исполнительных устройств (димеры, термостаты Danfoss). Проблема возникла когда сели батарейки в термостатах - уведомления на почту стали приходить строго каждые 30 минут, что порядком напрягало. Полазив по настройкам выяснилось следующие особенности:
  • можно отключить уведомления о севших батарейках сняв соотв. галочку у каждого из термостатов
  • изменение интервала пробуждения (по умолчанию 900 секунд) ни к чему не приводило
  • не было возможности настроить уведомление о севших батарейках одним списком, а не индивидуально по каждому устройству

Решение всех этих проблем есть в скрипте:


--[[ 
%% properties 
%% globals 
--]] 

local minBatteryLevel = 15
local maxID = 3000


Debug = function ( color, message )
  fibaro:debug(string.format('<span style="color:%s;">%s</span>', color, message))
end

while true do
    local timeNow = os.date('*t') 
    local weekday = timeNow['wday'] 
    local hour = timeNow['hour']
    local minute = timeNow['min']
    
    Debug('gray', 'Script OK...')
  
if(hour == 12)then
    
        local mailText = ""
        local mailHeader = "Перечень устройств в которых необходимо заменить батареи:\n====================\n"
        local countDeadBatterys = 0;
        local message = ""
    
        for id = 1, maxID do 
           local batteryLevel = fibaro:get(id, 'batteryLevel') 
           if batteryLevel ~= nil then 
              local room = fibaro:getRoomNameByDeviceID(id) 
              if not(room == "unassigned") then
                local deviceType = fibaro:getType(id)
                if (deviceType == 'com.fibaro.FGFS101' or 
                    deviceType == 'com.fibaro.remoteSwitch' or 
                    deviceType == 'com.fibaro.doorLock' or 
                    deviceType == 'com.fibaro.FGMS001' or 
                    deviceType == 'com.fibaro.windowSensor' or  
                    deviceType == 'com.fibaro.doorSensor' or 
                    deviceType == 'com.fibaro.binarySwitch' or 
                    deviceType == 'com.fibaro.FGSS001' or
                    deviceType == 'com.fibaro.motionSensor' or
                    deviceType == 'com.fibaro.heatDetector' or
                    deviceType == 'com.fibaro.lightSensor' or
                    deviceType == 'com.fibaro.humiditySensor' or
                    deviceType == 'com.fibaro.thermostatDanfoss' or
                    deviceType == 'com.fibaro.smokeSensor') then
                
                    if(deviceType == 'com.fibaro.thermostatDanfoss' and
                       batteryLevel == "255") then
         --у термостатов Danfoss при полностью севшей батарее выдает значение 255
                            batteryLevel = "0"            
                    end
                
                    local name = fibaro:getName(id) 
                            
                    if tonumber(batteryLevel) <= minBatteryLevel then
                        local message = name.." (id="..id..") в "..room.." / уровень батареи: "..batteryLevel.." %"
                        Debug( 'red', message)
                        mailText = mailText..message.."\n"
                        countDeadBatterys = countDeadBatterys+1
                    else
                        Debug( 'green', name.." (id="..id..") в "..room.." / уровень батареи: "..batteryLevel.." %")
                    end
                
                    --[[
                    --попытка разбудить не отвечающие устройства
                    local status = fibaro:getValue(id, 'dead')          
                    if status >= "1" then           
                      fibaro:debug(day.."/"..month..":"..id..' умер '..name..":"..room); 
                      fibaro:wakeUpDeadDevice(id) 
                      fibaro:sleep(5000) --check again in 5 sec 
                      status = fibaro:getValue(id, 'dead')
                      if status >= "1" then
                        fibaro:debug('Не отвечает - умер. Показания батареи неверные!') 
                      else
                        fibaro:debug('После пробуждения - OK '..name) 
                      end 
                    end ]]--
                
                else
                  --fibaro:debug(deviceType)
                end
              end 
            end 
          end
           
        if countDeadBatterys > 0 then 
            mailText = mailHeader..mailText            mailText mailText.."====================\n"..string.format("Всего устройств с севшими батарейками: %d\n", countDeadBatterys)
            fibaro:call(2, 'sendEmail', 'Статус батарей HC2', mailText) 
            Debug('yellow', "Письмо с сообщением о севших батареях отправлено")
        else
            Debug('blue', "Нет информации о севших батареях в устройствах")
        end
  fibaro:sleep(60*60000) --delay 60 minutes 
  end
  fibaro:sleep(15*60000) --repeat every 15 minute
end

Данный скрипт каждые 15 минут проверяет статусы батареек всех беспроводных устройств и если имеются устройства заряд у которых меньше 15% - формирует список и отправляет его каждый день в 12 часов на почту администратору системы.
В цикле так же имеется кусок закомментированного кода, который проверяет спящие устройства и пытается их разбудить. По необходимости его можно раскомментировать.