Hallo,
ich habe mal wieder ein paar Änderungen am Script vorgenommen, aber die sind fast nur kosmetischer Natur. Dabei wurde die Ausgabe für die
E-Mail und das Debug-Fenster optimiert. Die Ausgabe der Bereiche (Sections) habe ich von 4 auf 2 Stellen gekürzt. Wer da mehr braucht kann
dies in Zeile 99 (letzte Ziffer) abändern.
Changelog für Version 1.1.5
– Ausgabe für Debug Fenster optimiert
– Kleinere Codeoptimierungen
--[[
%% autostart
%% properties
%% globals
--]]
-- file: Batterystatus.lua
-- version: 1.1.5, released on 18.02.2018
-- purpose: This script checks the batteries and sends reports via
-- email. Since version 0.6.1 and higher: The script also performs a check on
-- non battery devices and reports all devices marked as dead by HC2.
-- The batterie status is checked daily and several reports per week can be
-- emailed.
-- Due to some limitations in the HC2 with FW less then 4.130, only 980
-- characters per per e-mail could be sent.
-- For batteries that are almost empty, or a dead device is recognized,
-- a push and/or telegram messages will be sent immediately.
-- Also the status of lastBreached can be checked, so you can easely identify
-- devices whose battery may have been empty for a longer time.
-- If you have added new devices or sections, you should restart the script.
-- A manual check is possible at any time. Simply press the Start button.
-- Copyleft Mar-2017 - 2018 {jeep} siio-forum
local sourceTrigger = fibaro:getSourceTrigger();
local version = "1.1.5"
local oldnodeId = nil ;
-- The variables below can be changed by user.
local subject = "Battery and device status";
local userIDs = {2} -- mailuser ids
local devpEmail = 25 -- devices per email
local maildays = {1,4,6} -- 1=Sunday, 2=Monday, 3=Tuesday ...7=Saturday
local pushactiv = false; -- true - sendpush notification
local teleactiv = true; -- true - send message via telegram
local phoneID = {303} -- phone IDs for push notification
local checktime = "19:15" -- At this time the script is triggerd
local full = 100 --between 50 and 100 the battery status is assumed to be good
local warning = 50 --between 30 and 50 battery is running low
local critical = 30 --below 30 battery status is asumed as critical
local empty = 255 --probably a completely empty battery
local nBreacheds= 24 --not Breached since nn hours
local checklBreached = true; -- should lastBreached be checked
local checkSection = true; -- if false, the section is not output.
local Debug = function ( color, message )
fibaro:debug(string.format('<%s style="color:%s;">%s', "span", color, message, "span"))
end
local function contains(days, val)
for i=1,#days do
if days[i] == val then
return true
end
end
return false
end
local function sendPush(text)
if (phoneID[1] ~= nil) then
for i=1, #phoneID do
if phoneID[i] ~= nil then
fibaro:call(phoneID[i],'sendPush', text)
end
end
end
end
local function sendMail(userIDs,subject,status,m)
local subject = subject..'-'..m
if (userIDs[1] ~= nil) then
for m=1, #userIDs do
if userIDs[m] ~= nil then
fibaro:call(userIDs[m], "sendEmail", subject, status)
end
end
status = ' ';
print('Mail Nr. '..m.. ' sent.')
end
end
local function checklastBreached(uxtimeStamp, lbreached)
local xseconds = (uxtimeStamp - lbreached)
local xtime = (xseconds /60) / 60
local xhours = math.floor(xtime)
return xhours
end
local function formatString(name, room)
local slength = string.len(name) + string.len(room)
local dlength = 35 - slength
local dots = string.rep ("-", dlength)
return dots
end
local function getSectionNamebyID(values, sectionNr, sectiontab)
if checkSection then
for i=1, values do
section = sectiontab[i].id
if section == sectionNr then
return string.sub(sectiontab[i].name,1,2)..','
end
end
end
return ''
end
local sym ={warn='?', ok='✔️', empty='❓', crit='⛔️', err='❌' }
local sectiontab = api.get("/sections")
local values = #sectiontab
local devices = fibaro:getDevicesId({visible = true, enabled = true, isPlugin =false })
local function checkBatteries()
local uxtimeStamp = os.time(dt);
local status = '';
local vstatus = '';
local bstatus = '';
local stathtml= '';
local n = 0; -- battery device counter
local v = 0; -- non battery device counter
local m = 0; -- mail counter
local x = 0; -- other devices
Debug('withe', os.date('%c')..', Version: '.. version );
for id = 1, #devices do
local batteryLevel = fibaro:get(devices[id], 'batteryLevel')
local nodeId = fibaro:get(devices[id], 'nodeId')
local isdead = fibaro:get(devices[id], 'dead')
if batteryLevel ~= nil and nodeId ~= nil and batteryLevel ~= '' then
local name = fibaro:getName(devices[id])
if oldnodeId ~= nodeId then
local room = fibaro:getRoomNameByDeviceID(devices[id])
local sectionID = fibaro:getSectionID(devices[id])
local lbreached = fibaro:get(devices[id], 'lastBreached')
local sname = getSectionNamebyID(values, sectionID, sectiontab)
if not(room == "unassigned") then
n = n+1
if tonumber(batteryLevel) >= warning and tonumber(batteryLevel) <= full then
local dots = formatString(name, room)
local statusOK = string.format("%s) %s %s, im Raum %s hat %s %s %% %s", n, sname, name, room, dots, batteryLevel, sym.ok)
local htmlOK = "<pre>" .. string.format("%s) %s %s, im Raum %s hat %s %s %% %s", n, sname, name, room, dots, batteryLevel, sym.ok) .."</pre>"
Debug('green', statusOK)
stathtml = stathtml .. htmlOK
status = status .. statusOK ..'\n'
elseif
tonumber(batteryLevel) >= critical and tonumber(batteryLevel) <= warning then
local dots = formatString(name, room)
local statuswarn = string.format("%s) %s %s, im Raum %s hat %s %s %% %s", n, sname, name, room, dots, batteryLevel, sym.warn)
local htmlWarn = "<pre>" .. string.format("%s) %s %s, im Raum %s hat %s %s %% %s", n, sname, name, room, dots, batteryLevel, sym.warn).."</pre>"
Debug('yellow', statuswarn)
stathtml = stathtml .. htmlWarn
status = status .. statuswarn ..'\n'
elseif
tonumber(batteryLevel) < critical then
local dots = formatString(name, room)
local statuscritical = string.format("%s) %s %s, im Raum %s hat %s %s %% %s", n, sname, name, room, dots, batteryLevel, sym.crit)
local htmlCrit = "<pre>".. string.format("%s) %s %s, im Raum %s hat %s %s %% %s", n, sname, name, room, dots, batteryLevel, sym.crit).."</pre>"
Debug('red', statuscritical)
stathtml = stathtml .. htmlCrit
if pushactiv then
sendPush(statuscritical)
end
status = status .. statuscritical ..'\n'
elseif
tonumber(batteryLevel) > full or tonumber(batteryLevel) == empty then
local dots = formatString(name, room)
local statusempty = string.format("%s) %s %s, im Raum %s hat %s %s %% %s", n, sname, name, room, dots, batteryLevel, sym.empty)
local htmlempty = "<pre>"..string.format("%s) %s %s, im Raum %s hat %s %s %% %s", n, sname, name, room, dots, batteryLevel, sym.empty).."</pre>"
stathtml = stathtml .. htmlempty
Debug('red', statusempty)
if pushactiv then
sendPush(statusempty)
end
status = status .. statusempty..'\n';
end
if tonumber(isdead) == 1 then
local dots = formatString(name, room)
local statusdead = string.format("%s) %s %s, im Raum %s ist tot. %s %s", n, sname, name, room, dots, sym.err)
local htmldead = "<pre>"..string.format("%s) %s %s, im Raum %s ist tot. %s %s", n, sname, name, room, dots, sym.err).."</pre>"
Debug('red', statusdead)
status = status .. statusdead .. '\n';
stathtml = stathtml .. htmldead
vstatus = vstatus .. statusdead .. '\n';
sendPush(statusdead)
-- if teleactiv then --Telegram sender
-- fibaro:setGlobal('telegram_text', name.. ' is dead! '.. os.date('%c'))
-- fibaro:startScene(61)
-- end
end
if lbreached ~= nil and checklBreached and tonumber(lbreached) > 0 then
local xhours = checklastBreached(uxtimeStamp, lbreached)
if xhours > nBreacheds then
local sname = getSectionNamebyID(values, sectionID, sectiontab)
bstatus = bstatus ..sname..' '.. name ..' ('..room..') not breached since: ' ..xhours.. ' hours.\n'
end
end
if (n % devpEmail == 0) and oldNodeId == nodeID then
if contains(maildays, weekday) then
m = m+1
sendMail(userIDs,subject,status,m)
--fibaro:debug(status)
status = ' '
fibaro:sleep(500)
end
end
end
end
oldnodeId = nodeId
else
local dtype = fibaro:getType(devices[id])
if (dtype == 'virtual_device') or (dtype == 'HC_user') or (dtype == 'iOS_device') then
x = x+1
else
v = v+1
local name = fibaro:getName(devices[id])
local room = fibaro:getRoomNameByDeviceID(devices[id])
if tonumber(isdead) == 1 then
local dots = formatString(name, room)
local sectionID = fibaro:getSectionID(devices[id])
local sname = getSectionNamebyID(values, sectionID, sectiontab)
local statusdead = string.format("%s %s, im Raum %s ist tot! ----%s %s", sname, name, room, dots, sym.err)
local htmldead = "<pre>"..string.format("%s %s, im Raum %s ist tot! ----%s %s", sname, name, room, dots, sym.err).."</pre>"
Debug('red', statusdead)
vstatus = vstatus .. statusdead .. '\n';
stathtml = stathtml .. htmldead
sendPush(statusdead)
end
end
end
fibaro:sleep(100)
end --for
if (vstatus == '') then vstatus = "No dead device found.\n" end
status = status .. 'Checked at: ' .. os.date('%c') ..'\n'
status = status ..n.. ' battery devices were checked.\n'
vstatus = vstatus ..v.. ' non battery devices checked.'
separator = '------------------------------------------------------------'
Debug('withe', os.date('%c'));
Debug('withe', separator)
Debug('lightgreen', stathtml)
Debug('cyan', '------------ Summary of dead devices. -------------')
Debug('withe', vstatus)
Debug('withe', separator)
Debug('cyan', '----- Summary of devices not breached for a period of time. -----')
Debug('withe', bstatus)
Debug('withe', "There are " .. x .." other devices, such as plugins, virtual devices, etc.")
status = status..separator..'\n'..vstatus..'\n'
status = status..separator..'\n'..bstatus..'\n'..os.date('%c')
if contains(maildays, weekday) then
m = m+1
sendMail(userIDs,subject,status,m)
status = ' ';
end
end -- function
function main()
local currentDate = os.date("*t");
local currenthour = string.format("%02d", currentDate.hour) .. ":" .. string.format("%02d", currentDate.min)
weekday = currentDate.wday
local startSource = fibaro:getSourceTrigger();
if currenthour == checktime then
checkBatteries()
end
setTimeout(main, 60*1000)
end
if (sourceTrigger["type"] == "autostart") then
main()
else
local currentDate = os.date("*t");
local startSource = fibaro:getSourceTrigger();
weekday = currentDate.wday
if (startSource["type"] == "other") then
checkBatteries()
end
end