@pblacky,
Hier ist die HC3-Version. Nachdem ich gesehen habe wie grauenvoll die Mails aussehen, habe ich mit der Portierung erstmal aufgehört. Aber die Debug Ausgabe kann man noch gebrauchen.
-- Trigger auf Gateway-start ändern
--[[
file : Battery&devicestatus.lua
version : 0.1.0 - DE, released on Jun.2020
Copyright: Mar-2017 - 2021 {jwi}
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.
This is very important to identify your dead devices.
A manual check is possible at any time. Simply press the Start button.
For more information, please read the attached PDF.
--]]
--local sourceTrigger = fibaro.getSourceTrigger();
local version = "0.1.0 - DE"
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,2,3,4,5,6,7} -- 1=Sunday, 2=Monday, 3=Tuesday ...7=Saturday
local pushactiv = true; -- true - sendpush notification
local teleactiv = false; -- true - send message via telegram
local phoneID = {22,} -- phone IDs for push notification
local checktime = "19:25" -- At this time the script is triggerd
local dtformat = '%d %b. %Y - %X' --Datumsformat
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 onlySummaryM = false; -- send only a summary email if true
local debugout = false -- | true | false
local htmlout = false -- | true | false
local sortout = true -- | true | false
--
local function printf(...) fibaro.debug(tag, string.format(...)) end
local Debug = function ( color, message )
fibaro.debug(string.format('<%s style="font-family:Courier New;font-size:12px;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
function printf(fmt, ...)
print(string.format(fmt, ...))
end
local function sendPush(text)
if (phoneID[1] ~= nil) then
for i=1, #phoneID do
if phoneID[i] ~= nil then
fibaro.alert("push", {22}, text) --phoneID[i]
-- fibaro.call(phoneID[i],'sendPush', text)
end
end
end
end
local function sendMail(userIDs,subject,mstat,m)
local subject = subject..'-'..m
if (userIDs[1] ~= nil) then
for u=1, #userIDs do
if userIDs[u] ~= nil then
fibaro.call(userIDs[u], "sendEmail", subject, mstat)
fibaro.alert("email",{2},mstat)
-- fibaro.alert("email",{48},mstat)
end
end
mstat = ' ';
if debugout then Debug('green','Mail Nr. '..m.. ' sent.') end
end
end
local function checklastBreached(uxtimeStamp, lbreached)
local xseconds = (uxtimeStamp - lbreached)
local xtime = (xseconds /60) / 60
return math.floor(xtime)
end
local function formatString(dname, room)
local slength = string.len(dname) + string.len(room)
local dlength = 30 - slength
return string.rep ("-", dlength)
end
local function getSNamebyID(sectionID)
if checkSection then
if sectionID == nil or sectionID == "unassigned" then return ' ' end
if tonumber(sectionID) > 0 then
local section = api.get("/sections/" .. tostring(sectionID))
return string.sub(tostring(section.name),1, 2)..','
end
end
return ''
end
local function validate(phoneID)
local ios = api.get('/iosDevices')
local nID = 0
for n = 1,#phoneID do
for _,i in pairs(ios) do
if phoneID[n] == i.id then
nID = nID+1
end
end --for
end --for
if #phoneID ~= nID then fibaro.warning('phoneID','Hinweis - unbekannte phoneID entdeckt, bitte korrigieren!\n<font color=yellow>Oder Sie können keine Push-Meldungen empfangen.') end
end
local function createlink(id)
local devID = id
local linkID = string.format(
"<a href=\"../devices/configuration.html?id=%u#bookmark-advanced\" target=\"_blank\""..
"style=\"display:inline;color:Cyan\">%u</a>",id,id )
return devID, linkID
end
local function checkhc2()
local info = api.get("/settings/info")
FW = info.softVersion
local date = info.serverStatus
local daysfrom = (os.time() - date) / (24 * 60 * 60)
local wholedays = math.floor(daysfrom)
return os.date('%d-%m-%Y %H:%M:%S', date)..', ('..wholedays..') Tage'
end
local fontcol = "<font color=orange>"
local fontcolred = "<font color=red>"
local sym ={warn='🔔', ok='✔️', empty='❓', crit='⛔️', err='❌' }
local sectiontab = api.get("/sections")
local values = #sectiontab
--
local function checkallDevices()
-- print('Start checckalldevices')
local devices_all = api.get('/devices/?enabled=true&visible=true&isPlugin=false');
--print(devices_all)
local uxtimeStamp = os.time(dt);
local mstat = '';
local vstatus = '';
local bstatus = '';
local bstatm = '';
local vstatm = '---------------~= Zusammenfassung der Überprüfung. =~----------------\r\n';
local stathtml= "<pre><span style='border:1px solid grey'>"..'Nr |id |Sec| Geräte Name | Raum Name ------------ ----- |Wert% |Sym ' .. "</span></pre>";
local tdev = {};
local n = 0; -- battery device counter
local v = 0; -- non battery device counter
local m = 0; -- mail counter
local x = 0; -- other devices
local nb= 0;
local b_full,b_low,b_warn,b_empty = 0,0,0,0
Debug('cyan', os.date(dtformat)..', Version: '.. version );
validate(phoneID)
Debug('skyblue', 'Daten werden aufbereitet...')
if debugout then Debug('green', "<span style='border:1px solid grey'>"..'Nr |Sec| Geräte Name | Raum Name ------------ ----- |Wert% |Sym ' .. "</span>" ) end
for id = 1, #devices_all do
--print('for id')
if(devices_all[id].properties.batteryLevel ~= nil) then
--print('ist batterie')
batteryLevel = devices_all[id].properties.batteryLevel;
--print(batteryLevel)
else
batteryLevel = nil;
end
if(devices_all[id].properties.nodeId ~= nil) then
nodeId = devices_all[id].properties.nodeId;
--print(nodeId)
else
nodeId = nil;
end
if(devices_all[id].properties.dead ~= nil) then
if(devices_all[id].properties.dead == false) then
--print('isdead ist false')
isdead = 0;
else
isdead = 1;
end
else
isdead = nil;
end
-- print(isdead)
local devID, linkID = createlink(devices_all[id].id )
if(tonumber(devices_all[id].roomID) == 0) then
room = 'unassigned';
sectionID = 'unassigned';
else
room = fibaro.getRoomNameByDeviceID(devices_all[id].id)
sectionID = tonumber(fibaro.getSectionID(devices_all[id].id))
end
-- print(room)
-- print(sectionID)
if batteryLevel ~= nil and nodeId ~= nil and batteryLevel ~= '' then
dname = devices_all[id].name
-- print(dname)
if oldnodeId ~= nodeId then -- alt lbreached = fibaro.get(devices[id], 'lastBreached')
if(devices_all[id].properties.dead ~= nil) then
lbreached = devices_all[id].properties.lastBreached;
else
lbreached = nil;
end
local sname = getSNamebyID(sectionID)
--if not(room == "unassigned") then
n = string.format('%02d',n+1)
if tonumber(batteryLevel) >= warning and tonumber(batteryLevel) <= full then
local dots = formatString(dname, room)
local tableOK = string.format("%s %s, im Raum %s hat %s %s %% %s", sname, dname, room, dots, batteryLevel, sym.ok)
local statusOK = n..') ' ..tableOK
local htmlOK = "<pre>"..n..') '.. linkID..' '..tableOK .. "</pre>"
if debugout then Debug('green', statusOK) end
stathtml = stathtml .. htmlOK;b_full = b_full+1
mstat = mstat .. statusOK ..'\n'
table.insert(tdev, tableOK )
elseif
tonumber(batteryLevel) >= critical and tonumber(batteryLevel) <= warning then
local dots = formatString(dname, room)
local tablewarn = string.format("%s %s, im Raum %s hat %s %s %% %s", sname, dname, room, dots, batteryLevel, sym.warn)
local statuswarn = n..') '..tablewarn
local htmlWarn = "<pre>" ..n..') '..linkID..' '.. tablewarn .. "</pre>"
if debugout then Debug('yellow', statuswarn) end
stathtml = stathtml .. htmlWarn;b_low = b_low+1
mstat = mstat .. statuswarn ..'\n'
table.insert(tdev, tablewarn )
elseif
tonumber(batteryLevel) < critical then
local dots = formatString(dname, room)
local tablecrit = string.format("%s %s, im Raum %s hat %s %s %% %s", sname, dname, room, dots, batteryLevel, sym.crit)
local statuscrit= n..') '.. tablecrit
local htmlcrit = "<pre>"..n..') '..linkID..' '.. tablecrit .. "</pre>"
if debugout then Debug('red', statuscrit) end
stathtml = stathtml .. htmlcrit;b_warn = b_warn+1
if pushactiv then
sendPush(statuscrit)
end
mstat = mstat .. statuscrit ..'\n'
table.insert(tdev, tablecrit )
elseif
tonumber(batteryLevel) > full or tonumber(batteryLevel) == empty then
local dots = formatString(dname, room)
local tableempty = string.format("%s %s, im Raum %s hat %s %s %% %s", sname, dname, room, dots, batteryLevel, sym.empty)
local statusempty = n..') ' .. tableempty
local htmlempty = "<pre>"..n..') '.. linkID..' '..tableempty .. "</pre>"
stathtml = stathtml .. htmlempty;b_empty = b_empty+1
if debugout then Debug('red', statusempty) end
if pushactiv then
sendPush(statusempty)
end
mstat = mstat .. statusempty..'\n';
table.insert(tdev, tableempty )
end
if tonumber(isdead) == 1 then
local dots = formatString(dname, room)
local tabledead = string.format("%s %s, im Raum %s ist tot. %s %s", sname, dname, room, dots, sym.err)
local statusv = string.format("%s %s %s | room %s is dead! ----%s %s", linkID, sname, dname, room, dots, sym.err)
local statusdead = n..') '.. tabledead
local htmldead = "<pre>"..n..') '..linkID.. ' '..tabledead .. "</pre>"
if debugout then Debug('red', statusdead) end
mstat = mstat .. statusdead .. '\n';
stathtml = stathtml .. htmldead
vstatus = vstatus ..fontcolred..n..') '..linkID..' '..tabledead .. '\n';
vstatm = vstatm ..n..') '.. devID ..' '.. tabledead..'\n';
sendPush(statusdead)
table.insert(tdev, tabledead )
if teleactiv then --Telegram sender
fibaro.setGlobal('telegram_text', dname.. ' is dead! '.. os.date('%c'))
fibaro.startScene(61)
end
end
-- [[ Check last breached time ]]
if lbreached ~= nil and checklBreached and tonumber(lbreached) > 0 then
local xhours = checklastBreached(uxtimeStamp, lbreached)
if xhours > nBreacheds then
local sname = getSNamebyID(sectionID)
if xhours >= 72 then -- laenger als 3 Tage
timestr = string.format('%.2f',xhours / 24)..' Tagen.'
else
timestr = tostring(xhours) .. ' Stunden.'
end
bstatus = bstatus ..fontcol .. sname ..' '.. dname ..' ('..room..') nicht ausgelöst seit: ' ..timestr.. '\n'
bstatm = bstatm .. sname ..' '.. dname ..' ('..room..') nicht ausgelöst seit: ' ..timestr.. '\n'
nb = nb+1
end
end
if lbreached ~= nil and checklBreached and tonumber(lbreached) == 0 then
bstatus = bstatus ..fontcol.. sname ..' '.. dname ..' ('..room..') noch nie ausgelöst.\n'
bstatm = bstatm .. sname ..' '.. dname ..' ('..room..') noch nie ausgelöst.\n'
nb = nb+1
end
if (n % devpEmail == 0) and oldNodeId == nodeID then
if contains(maildays, weekday) and onlySummaryM == false then
m = m+1
sendMail(userIDs,subject,mstat,m)
mstat = ' '
fibaro.sleep(500)
end
end
--end
end
oldnodeId = nodeId
else -- [[ device is non battery device ]]
if(devices_all[id].type ~= nil) then
dtype = devices_all[id].type;
else
dtype = nil;
end
if (dtype == 'virtual_device') or (dtype == 'HC_user') or (dtype == 'iOS_device') then
x = x+1
else
v = v+1
local dname = devices_all[id].name
if(tonumber(devices_all[id].roomID) == 0) then
room = 'unassigned';
else
room = fibaro.getRoomNameByDeviceID(devices_all[id].id)
end
if (isdead ~= nil and tonumber(isdead) == 1) then
local dots = formatString(dname, room)
local sectionID = fibaro.getSectionID(devices_all[id].id)
local sname = getSNamebyID(sectionID)
local statusdead = string.format("%s %s, im Raum %s ist tot! --%s %s", sname, dname, room, dots, sym.err)
local statusv = string.format("nb)%s %s %s, im Raum %s ist tot! --%s %s", linkID, sname, dname, room, dots, sym.err)
local htmldead = "<pre>nb) "..string.format("%s %s %s im Raum %s ist tot! --%s %s", linkID, sname, dname, room, dots, sym.err).."</pre>"
mstat = mstat .. statusdead .. '\n';
vstatm = vstatm..'nb) '.. devID..' '..sname..' '..dname..' im Raum'..room..' ist tot'.. ' '..sym.err..'\n';
table.insert(tdev, statusdead )
if debugout then Debug('red', statusdead) end
vstatus = vstatus .. fontcolred.. statusv .. '\n';
stathtml = stathtml .. htmldead
sendPush(statusdead)
end
end
end
fibaro.sleep(80)
end --for
-- [[ data output and last mail send ]]
if sortout then
print('')
table.sort(tdev)
table.insert(tdev, 1, "<span style='border:1px solid grey'>"..'Sec| Geräte Name | Raum Name - - - - - - - - - - |Wert% |Sym.' .. "</span>")
Debug('skyblue', '--- Sortierte Ausgabe nach Bereichen ---')
for i,j in ipairs(tdev) do
print(j)
-- Debug('skyblue',j)
end
end
--end sending battery status----------------------------------
if contains(maildays, weekday) and onlySummaryM == false then
m = m+1
sendMail(userIDs,subject,mstat,m)
mstat = ' ';
end
--end sending battery status----------------------------------
if ( not checklBreached) then bstatus = "Der 'last breached status' wurde nicht gecheckt. \n" end
if (vstatus == '') then
vstatus = vstatus .."\nKeine toten Geräte gefunden.\n"
vstatm = vstatm .. vstatus
end
hc2runtime = "HC3 läuft seit: " .. checkhc2().. ' mit FW: '.. FW
vstatus = vstatus ..fontcol.. n .. ' Batterie Geräte wurden gecheckt.\n'
vstatus = vstatus ..fontcol.. 'Davon: '..b_full..' Voll, '..b_low.. ' Medium, '..b_warn..' Schwach, '..b_empty..' Leer\n'
vstatus = vstatus ..fontcol.. 'Alle nicht Batterie Geräte gecheckt.'
b_stat = n .. ' Batterie Geräte wurden gecheckt.\n'
b_stat = b_stat..'Davon: '..b_full..' Voll, '..b_low.. ' Medium, '..b_warn..' Schwach, '..b_empty..' Leer'
bstatus = bstatus ..fontcolred..'Anzahl: '..nb..' <- Behalten sie diesen Wert im Auge.'
separator = '-----------------------------------------------------------------'
if htmlout then Debug('lightgreen', stathtml) end
Debug('cyan', '-------------~= Zusammenfassung der Überprüfung. =~--------------')
Debug('orange', vstatus)
Debug('cyan', separator)
Debug('cyan', '--- Geräte deren Status "not breached" seit längerem besteht. ---')
Debug('orange', bstatus)
print( hc2runtime )
Debug('cyan', "Geräte geprüft am: ".. os.date(dtformat))
mstat = vstatm..b_stat..'\n'
mstat = mstat..separator..'\n'..bstatm
mstat = mstat..'Anzahl: '..nb.. ' <- Behalten sie diesen Wert im Auge.\n'
mstat = mstat .. hc2runtime .. '\n \rGeprüft am: '..os.date(dtformat)..' Ver.: '..version
if contains(maildays, weekday) then
m = m+1
sendMail(userIDs,subject,mstat,m)
mstat = ' ';
end
end -- function
function main()
-- print("Main Start")
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
checkallDevices()
end
fibaro.setTimeout(60*1000,main)
end
if (sourceTrigger["type"] == "se-start") then
main()
else
if (sourceTrigger["type"] == "user") then
print('User start')
local currentDate = os.date("*t");
weekday = currentDate.wday
checkallDevices()
end
end
main()
Die Debug Ausgabe sieht so aus:
[09.02.2021] [12:01:11] [DEBUG] [SCENE2]: User start
[09.02.2021] [12:01:18] [DEBUG] [SCENE2]:
[09.02.2021] [12:01:18] [DEBUG] [SCENE2]: Sec| Geräte Name | Raum Name - - - - - - - |Wert% |Sym.
[09.02.2021] [12:01:18] [DEBUG] [SCENE2]: AU, RFID Reader2, im Raum Garage hat ------ 100 %
[09.02.2021] [12:01:18] [DEBUG] [SCENE2]: AU, Sensative LUX, im Raum Terrasse hat — 100 %
[09.02.2021] [12:01:18] [DEBUG] [SCENE2]: EG, RFIDReader1, im Raum Toilette hat ------- 100 %
[09.02.2021] [12:01:18] [DEBUG] [SCENE2]: UG, Aeotec Motion, im Raum Büro hat ------ – 100 %
[09.02.2021] [12:01:18] [DEBUG] [SCENE2]: UG, BM Waschküche, im Raum Waschküche hat- 96 %
[09.02.2021] [12:01:18] [DEBUG] [SCENE2]: UG, CO Sensor, im Raum Waschküche hat — 100 %
[09.02.2021] [12:01:18] [DEBUG] [SCENE2]: UG, DoorWindow1, im Raum Büro hat ----------- 65 %
[09.02.2021] [12:01:18] [DEBUG] [SCENE2]: UG, Keyfob, im Raum Büro hat ------------------- 72 %
[09.02.2021] [12:01:18] [DEBUG] [SCENE2]: UG, Motion Sensor, im Raum Büro hat --------- 100 %
[09.02.2021] [12:01:18] [DEBUG] [SCENE2]: UG, Therm.Büro, im Raum Büro hat -------------- 51 %
[09.02.2021] [12:01:18] [DEBUG] [SCENE2]: HC3 läuft seit: 02-02-2021 20:38:50, (6) Tage mit FW: 5.061.36
EDIT: In den Declarations soll das Gateway Start rein