Walter,
Thanks for your reply.
Below a dzvent script I used in 2022.1 for tracking "last_seen" using "HTTPJsON" from de Domoticz object in memory to find the updated time. This is than used to update the "updated" time in the dbase for that smoke sensor. I use another script to track all by battery devices to warn me if the battery runs out.
The reason is quite simple the "smoke" detectors don't update the "Lastupdate" item in the database. Other sensors I have installed (wifi and RFXCOM433 sensors) do update this item on regular heartbeat times.
As reported with the new 2022.2 no reporting to the domoticz object anymore and I could not find a way to fix it.
The mqtt broker send out messages(see above) but don't now if they are correct for the new 2022.2 release.
In the mean time I have bridged two MQTT brokers and the messages are received in the second MQTT broker. In HA I have put an automatization that republish the messages to "homeassistant/#" so HA can read(discover) it. This works only partly, some are "auto discovered" but also "last_seen" is not updated at the moment. But since there is 7000km between the two brokers there might be some lag. To be investigated.
I have a look comming week if I can make some sens form the cpp code...
Thanks,
Rini
Dzvent code.....>
local devicesToCheck = {
{ ['name'] = 'ZB_smoke_hal_last_seen' , ['DeviceIdx'] = 81 , ['UpdDevIdx'] = 69 }, -- add you device list here. First line is an example from my Domoticz.
{ ['name'] = 'ZB_smoke_woonkamer_last_seen', ['DeviceIdx'] = 82 , ['UpdDevIdx'] = 71 }, -- find you devices IDx in Domoticz/Setup/Devices
{ ['name'] = 'ZB_smoke_frank_last_seen' , ['DeviceIdx'] = 83 , ['UpdDevIdx'] = 67 }, -- (-1 in UpdDevIdx => means no other device need to be updated.
{ ['name'] = 'ZB_cox_frank_last_seen' , ['DeviceIdx'] = 85 , ['UpdDevIdx'] = 73 }
}
local last_seen = 'smoke_update'
local chkdev_name = nil
local chkdev_idx = -1
local upddev_name = nil
local upddev_idx = -1
local battery_warn = 25 -- 25% battery level warning
local dead_warn = 241 -- xx minuytes no heartbeat ....
local env_mail = nil -- your mail if notification by mail needed, nil if not
local env_port = '8080' -- your mail if notification by mail needed, nil if not
local env_https = false -- true if only https supported
local env_username = nil -- base 64 if local auth is needed (see Local Networks (no username/password) option, add 127.0.0.*)
local env_password = nil -- base 64 if local auth is needed (see Local Networks (no username/password) option, add 127.0.0.*)
local env_ReturnNotif = true --Notification on normal condition return
local message = ''
local message_light = 'Device(s): '
return {
on = {
timer = { 'every 1 hours' }, -- call to url will be done at this set time
httpResponses = { last_seen } -- must match with the callback passed to the openURL command
-- devices = {
-- '*ZB_smoke*last_seen'
-- }
},
logging = {
level = domoticz.LOG_INFO, ---only info needed
marker = last_seen,
},
data = {
chkdev_name = { initial = 'none'},
chkdev_idx = { initial =-1 },
upddev_name = { initial ='none'},
upddev_idx = { initial =-1},
state = { initial = ""},
messageSent = { "Nothing" } -- for persistent data notification
},
execute = function(dz, item)
local Time = require ('Time')
local conditionDeviceState = "Off" -- keep track of warinng states
local SubSystem = nil
--[[ Notifications available :
-- NSS_GOOGLE_CLOUD_MESSAGING NSS_HTTP NSS_KODI NSS_LOGITECH_MEDIASERVER NSS_NMA NSS_PROWL NSS_PUSHALOT NSS_PUSHBULLET NSS_PUSHOVER NSS_PUSHSAFER NSS_TELEGRAM
-- If severals needed, use {}.
-- Example :{dz.NSS_TELEGRAM, dz.NSS_HTTP}
-- must be declared in function block (
https://www.dz.com/forum/viewtopic.php?f=71&t=33539)
--]]
local function logWrite(str,level)
dz.log(tostring(str),level or dz.LOG_DEBUG)
end
local function get_device_info(devIdx,topic)
ans = nil
if type(devIdx) == 'string' then
devIdx_n = tonumber(devIdx);
else
devIdx_n = devIdx;
end
for i, dev2chk in pairs(devicesToCheck) do
if devIdx_n == dev2chk['DeviceIdx'] then
if topic == 'chkdev_name' then
ans = dev2chk['name'];
elseif topic == 'chkdev_idx' then
ans = dev2chk['DeviceIdx'];
elseif topic == 'upddev_idx' then
ans = dev2chk['UpdDevIdx'];
elseif topic == 'upddev_name' then
ans = dz.devices(dev2chk['UpdDevIdx']).name;
else
ans="unkown topic";
end
end
end
return ans
end
local function notification(subject, message)
dz.log("State before notify : " .. dz.data.state,dz.LOG_DEBUG)
dz.log("State after notify : " .. conditionDeviceState,dz.LOG_DEBUG)
if conditionDeviceState ~= dz.data.state then
dz.log("Notification sending",dz.LOG_INFO)
if SubSystem == nil then
dz.notify(subject, message, dz.PRIORITY_NORMAL)
else
dz.notify(subject, message, dz.PRIORITY_NORMAL, '', '', SubSystem)
end
if env_mail ~= nil then
dz.email('Dead devices', message, env_mail)
end
dz.data.state = "On"
dz.data.messageSent = message_light
else
dz.log("Nothing to send, message not updated",dz.LOG_INFO)
end
end
local function triggerJSON()
local URLString = "http"
if env_https then
URLString = URLString .. 's'
end
if (env_password == nil or env_username == nil) then
--url = '
http://127.0.0.1:8080/json.htm?type=devices&rid='.. chkdev_idx ..'',
URLString = URLString .. "://127.0.0.1:"..env_port.."/json.htm?type=devices&used=false"
else
URLString = URLString .. "://127.0.0.1:"..env_port.."/json.htm?type=devices&used=false&username="..env_username.."&password="..env_password
end
dz.openURL({ url = URLString,
method = "GET",
callback = last_seen })
end
local function updateJSON(upddev_idx,chk_signalLevel,chk_batterylevel)
-- dz.settings['Domoticz url']='http://127.0.0.1:'..env_port
-- logWrite("URL=" .. dz.settings['Domoticz url'])
-- url construction
-- local js_prefix=dz.settings['Domoticz url'] .. '/json.htm?type=command¶m=udevice&nvalue=0&svalue=
-- update device
dz.log("DeviceID '"..upddev_idx.."' will be updated from last-seen (ZB)device",dz.LOG_DEBUG)
-- url construction
local js_prefix='
http://127.0.0.1:'.. env_port .. '/json.htm?type=command¶m=udevice&nvalue=0&svalue='
dz.openURL(js_prefix ..
'&idx='.. upddev_idx ..
'&rssi=' .. chk_signalLevel ..
'&battery='.. chk_batterylevel ..
'&linkqualit=120')
end
if (item.isTimer) then
triggerJSON() -- call the url
end
if (item.isHTTPResponse) then
if (item.ok) then
if (item.isJSON) then
-- local Time = require('Time')
local now = Time()
-- local rt = dz.utils.fromJSON(trigger.data) -- convert json data to Lua table
-- local sensor2update=string.gsub(dz.data.trigger_device,'last_seen','smoke',1) --get ther real name of the sensors
local results = item.json.result -- just an example
for i, deviceToCheck in pairs(devicesToCheck) do
local chkdev_idx = deviceToCheck['DeviceIdx']
local chkdev_found = false
-- loop through the devices (one by one)
for j, node in pairs(results) do
-- if string.match(results
.Name,'smoke.*last_seen') ~= nil then -- mache anything between smoke and last_seen
-- if string.match(results.Name,string.gsub(trigger_device,'last_seen','',1)) ~= nil then -- get the sensor info
-- update some device in Domoticz
num_idx = tonumber(node.idx) -- need number(int)
if chkdev_idx == num_idx then
logWrite("Device " .. node.Name .. " device " .. node.idx .. " has battery: ".. node.BatteryLevel)
chkdev_found = true
-- Find device to update
-- upddev_name = string.gsub(node.Name,'last_seen','smoke',1) --replace lasst_seen by smoke
local upddev_name = get_device_info(node.idx,'upddev_name')
local upddev_idx = get_device_info(node.idx,'upddev_idx')
local chk_lastup = Time(node.LastUpdate)
logWrite('Device:'.. upddev_name)
logWrite('Minutes ago: ' .. chk_lastup.minutesAgo)
local chk_batterylevel=node.BatteryLevel
local chk_signalLevel=node.SignalLevel
-- Current_batterylevel=90
logWrite("batteryLevel=" .. chk_batterylevel)
-- update device if needed.... (60 minutes?)
if chk_lastup.minutesAgo < 61 and upddev_idx > 0 then
dz.log("Device '"..upddev_name.."(" ..upddev_idx .. ")' will be updated from last-seen (ZB)device",dz.LOG_INFO)
--update relate Device
updateJSON(upddev_idx,chk_signalLevel,chk_batterylevel)
end
-- check batterylevels and warn if necc (zit nu in battery_checking)
if chk_batterylevel < battery_warn then
logWrite ('Device: ' .. upddev_name .. ' has low batterylevel ('..chk_batterylevel..'%). Need to be replaced')
-- warnnnnnnn
dz.log("Device "..upddev_name.." has low batterylevel ("..chk_batterylevel.."%)",dz.LOG_INFO) -- change notification logline to suit your needs
-- dz.notify(upddev_name,"Batterij van "..device.name.." moet vervangen worden ("..device.batteryLevel.."%)",dz.PRIORITY_NORMAL) -- change notification message to suit your needs
end
if chk_lastup.minutesAgo > dead_warn then --- check for dead devices
--
message = message .. 'Device ' ..
upddev_name .. ' seems to be dead. No heartbeat for at least ' ..
chk_lastup.minutesAgo .. ' minutes at ' .. now.raw .. '. \n\r'
message_light = message_light .. upddev_name .. ', '
-- notification('Warning',message)
end
break
end
end
if not chkdev_found then
-- looped through all devices but device not found
dz.log("Device: "..chkdev_idx.." not available in 'unused' device-list (see devicesToCheck array)",dz.LOG_ERROR)
end
end
if (message ~= "") then
message_light = message_light .. 'seem(s) to be dead'
dz.log(message_light, dz.LOG_DEBUG)
dz.log(dz.data.messageSent, dz.LOG_DEBUG)
if (message_light ~= dz.data.messageSent) then
dz.data.state = "Off" -- force sending if new device added
end
conditionDeviceState = "On"
notification('Warning',message_light)
dz.log('Dead devices found: ' .. message, dz.LOG_ERROR)
end
if dz.data.state ~= conditionDeviceState then --Normal state return
dz.data.state = conditionDeviceState
if env_ReturnNotif == true then
if SubSystem == nil then
dz.notify('Information','Return to normal state, all devices are operational')
else
dz.notify('Information','Return to normal state, all devices are operational', '', '', '', SubSystem)
end
end
else
dz.log("State Reset not needed",dz.LOG_DEBUG)
end
dz.log("Live state: " .. dz.data.state,dz.LOG_DEBUG)
dz.log("Live condition: " .. conditionDeviceState,dz.LOG_DEBUG)
else
dz.log('There was a problem handling event request (Trig OK json NOK)', dz.LOG_ERROR)
dz.log(item, dz.LOG_ERROR)
end
else
dz.log('There was a problem handling trigger event request', dz.LOG_ERROR)
dz.log(item, dz.LOG_ERROR)
end
end
end
}