Python plugin: Battery Level for Z-Wave Devices

Python and python framework

Moderator: leecollings

assenzuid
Posts: 135
Joined: Friday 13 November 2015 9:11
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: The Netherlands, Emmen Area
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by assenzuid »

Beta version 4.10270, plugin not working since end november.

Code: Select all

Error: (Battery Level ZWave) Enable to find a zwave controller configuration file ! 
alanlsmith
Posts: 132
Joined: Monday 07 August 2017 17:17
Target OS: Linux
Domoticz version: Latest β
Location: Near London (Saaarf!)
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by alanlsmith »

assenzuid wrote: Thursday 13 December 2018 12:49 Beta version 4.10270, plugin not working since end november.

Code: Select all

Error: (Battery Level ZWave) Enable to find a zwave controller configuration file ! 
As far as I know beta 10268 was only released yesterday (12 Dec) so I don't think we have reached 10270 yet. Unless I'm missing something, which is quite possible.
Domoticz Latest β, RPi 4B with 110Gb SSD for Domoticz, RPi 4B with 110Gb SSD for Node-Red & a RPi 2B for logging / IP addressing. RFXCOM, PiZiGate, Z-Wave, Harmony, Hue lamps and a bit of Broadlink.
nmaster
Posts: 54
Joined: Saturday 16 August 2014 17:17
Target OS: Linux
Domoticz version: 3.6304
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by nmaster »

Hi.

I just tried this plugin on my domoticz system, Beta version V4.10311 and I get same error.
Logread
Posts: 228
Joined: Sunday 28 August 2016 7:48
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: France
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by Logread »

nmaster wrote: Saturday 26 January 2019 17:09 Hi.

I just tried this plugin on my domoticz system, Beta version V4.10311 and I get same error.
You did not say which platform you are running domoticz on, but if it is Linux based can you please check if there is a file named ./Config/zwcfg_0x????????.xml in your domoticz install (where ???????? is an hex number corresponding to the zwave home ID of your setup) ?

if not, may be try to locate it with the linux "which" command ?

I checked one of my production systems with domoticz version 4.10362 (more recent than yours) on a Raspberry with Raspbian Stretch and it works fine.
nmaster
Posts: 54
Joined: Saturday 16 August 2014 17:17
Target OS: Linux
Domoticz version: 3.6304
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by nmaster »

Hi Logread.

You're right, sorry.

My platform is:

Code: Select all

Linux minishuttle 4.18.0-13-generic #14-Ubuntu SMP Wed Dec 5 09:04:24 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
I have a custom config folder /config/, and in it I have a wcfg_0x????????.xml.

I start my domoticz with these options:

Code: Select all

domoticz -sslwww 1443 -sslcert /config/keys/server_cert.pem -userdata /config/ -dbase /config/domoticz.db
In /config/ I also have a plugins folder.
Logread
Posts: 228
Joined: Sunday 28 August 2016 7:48
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: France
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by Logread »

nmaster wrote: Sunday 27 January 2019 16:23 Hi Logread.

You're right, sorry.

My platform is:

Code: Select all

Linux minishuttle 4.18.0-13-generic #14-Ubuntu SMP Wed Dec 5 09:04:24 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
I have a custom config folder /config/, and in it I have a wcfg_0x????????.xml.

I start my domoticz with these options:

Code: Select all

domoticz -sslwww 1443 -sslcert /config/keys/server_cert.pem -userdata /config/ -dbase /config/domoticz.db
Got it. So, given that your setup is non standard, I recommend that you edit the plugin code to account for the custom config folder.
hkemal
Posts: 13
Joined: Wednesday 16 January 2019 14:04
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by hkemal »

Hello,

I am running the latest version of plugin on the latest domoticz stable.

The values do not get updated after 60 min. The values only update if I stop the plugin and start it again.

My sensor was reporting battery values in OZW from 20% to 8% over a course of couple of days, but the value of the plugin was not updating. After I stopped and started the plugin again, I got the correct value of 8%.
Then I changed the battery and the OZW and Plugin shown 8%. Couple of hours ago the OZW updated the value several times and is currently 46%. THe value of the plugin still shows 8% and the last update time is the time I restarted the plug in.

Any ideas?

Regards
hkemal
hkemal
Posts: 13
Joined: Wednesday 16 January 2019 14:04
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by hkemal »

I turned on debuging in the plugin and restarted it at 13:01 with 30min update interval.

13:01:45 The plugin reads the battery values.
13:01 - ... The plugin reports this every 10s" Pushing 'onHeartbeatCallback' on to queue, Processing 'onHeartbeatCallback' message"
13:31:45 (or after that) The plugin does not read the battery values at all.

So according to the Heartbeat the plugin is running, but still it does not trigger reading out according to the update interval.
Logread
Posts: 228
Joined: Sunday 28 August 2016 7:48
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: France
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by Logread »

hkemal wrote: Tuesday 29 January 2019 13:39 I turned on debuging in the plugin and restarted it at 13:01 with 30min update interval.

13:01:45 The plugin reads the battery values.
13:01 - ... The plugin reports this every 10s" Pushing 'onHeartbeatCallback' on to queue, Processing 'onHeartbeatCallback' message"
13:31:45 (or after that) The plugin does not read the battery values at all.

So according to the Heartbeat the plugin is running, but still it does not trigger reading out according to the update interval.
The battery levels are updated by openzwave. If openzwave does not update the levels then the plugin does not.
haikassy
Posts: 1
Joined: Monday 29 April 2019 8:46
Target OS: Linux
Domoticz version:
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by haikassy »

Hello there,

Code: Select all

"""
Domoticz Python plugin for Monitoring and logging of battery level for z-wave nodes
Author: Logread
Versions:
    0.2.0: made code more object oriented with cleaner scoping of variables
    0.3.0: refactor of code to use asyncronous callbacks for http calls
    0.3.1: skip zwave devices with "non standard" ID attribution (thanks @bdormael)
    0.3.2: rewrote the hashing of device ID into zwave node id in line with /hardware/ZWaveBase.cpp
    0.4.0: Major change: Use openzwave as data source instead of the Domoticz API... 
            simpler, faster and possibly more "real-time" information
    0.4.1: Code made compliant with Python plugin framework breaking changes
            https://www.domoticz.com/forum/viewtopic.php?f=65&t=17554
    0.4.2: Code cleanup
    0.4.3: Added support for Synology Jadahl install (different location of zwave config file)
    0.4.4: Fixed typo in battery level low icon callup, causing device update errors for that level
    0.4.5: Fixed bug in the polling of zwave nodes (thanks to domoticz forum user @PBdA !)
    0.4.6: Fixed issue when on system reboot the zwave conf file is empty as openzwave rebuilts it
    0.4.7: Added battery levels as parameters (jrcasal)
    0.4.8: zwave controller validity check at each poll rather than only at startup
"""
"""
<plugin key="BatteryLevel" name="Battery monitoring for Z-Wave nodes" author="logread" version="0.4.8" wikilink="http://www.domoticz.com/wiki/plugins/BatteryLevel.html" externallink="https://github.com/999LV/BatteryLevel">
    <params>
        <param field="Mode1" label="Polling interval (minutes, between 30 and 1440 min)" width="40px" required="true" default="60"/>
        <param field="Mode2" label="Battery Level is Full (percent, between 75 and 99)"  width="40px" required="true" default="75" />
        <param field="Mode3" label="Battery Level is OK (percent, between 40 and 75)"    width="40px" required="true" default="50" />
        <param field="Mode4" label="Battery Level is empty (percent, between 10 and 25)" width="40px" required="true" default="25" />
        <param field="Mode6" label="Debug" width="75px">
            <options>
                <option label="True"  value="Debug"/>
                <option label="False" value="Normal"  default="true" />
            </options>
        </param>
    </params>
</plugin>
"""
import Domoticz
import xml.etree.ElementTree as xml
import os
import glob
from datetime import datetime
from datetime import timedelta

icons = {"batterylevelfull": "batterylevelfull icons.zip",
         "batterylevelok": "batterylevelok icons.zip",
         "batterylevellow": "batterylevellow icons.zip",
         "batterylevelempty": "batterylevelempty icons.zip"}


class zwnode:

    def __init__(self, nodeid, name, level):
        self.nodeid = nodeid
        self.name = name
        self.level = level


# noinspection SyntaxError
class BasePlugin:

    def __init__(self):
        self.debug = False
        self.BatteryNodes = []  # work list that contains 'zwnode' objects
        self.nextupdate = datetime.now()
        self.pollinterval = 60  # default polling interval in minutes
        self.batterylevelfull = 75 # Default values for Battery Levels
        self.batterylevelok   = 50
        self.batterylevellow  = 25
        self.zwaveinfofilepath = None
        return

    def onStart(self):
        global icons
        Domoticz.Debug("onStart called")
        if Parameters["Mode6"] == 'Debug':
            self.debug = True
            Domoticz.Debugging(1)
            DumpConfigToLog()
        else:
            Domoticz.Debugging(0)
            
        # Load custom battery levels
        # Battery  Full
        try:
            temp = int(Parameters["Mode2"])
        except:
            Domoticz.Error("Invalid Battery Full parameter")
        else:
            if temp < 75:
                temp = 75
                Domoticz.Error("Specified Battery Full value too low: changed to 75%")
            elif temp > 99:
                temp = 99
                Domoticz.Error("Specified Battery Full value too high: changed to 99%")
            self.batterylevelfull = temp
        Domoticz.Log("Setting battery level to full if greater or equal than {} percent".format(str(self.batterylevelfull)))
            
        # Battery OK
        try:
            temp = int(Parameters["Mode3"])
        except:
            Domoticz.Error("Invalid Battery OK parameter")
        else:
            if temp < 40:
                temp = 40
                Domoticz.Error("Specified Battery OK value too low: changed to 40%")
            elif temp > 75:
                temp = 75
                Domoticz.Error("Specified Battery OK value too high: changed to 75%")   
            self.batterylevelok = temp
        Domoticz.Log("Setting battery level to normal if greater or equal than {} percent".format(str(self.batterylevelok)))
            
        # Battery LOW
        try:
            temp = int(Parameters["Mode4"])
        except:
            Domoticz.Error("Invalid Battery LOW parameter")
        else:
            if temp < 10:
                temp = 10
                Domoticz.Error("Specified Battery LOW value too low: changed to 10%")
            elif temp > 25:
                temp = 25
                Domoticz.Error("Specified Battery LOW value too high: changed to 25%")
            self.batterylevellow = temp
        Domoticz.Log("Setting battery level to empty if less or equal than {} percent".format(str(self.batterylevellow)))
        
        # load custom battery images
        for key, value in icons.items():
            if key not in Images:
                Domoticz.Image(value).Create()
                Domoticz.Debug("Added icon: " + key + " from file " + value)
        Domoticz.Debug("Number of icons loaded = " + str(len(Images)))
        for image in Images:
            Domoticz.Debug("Icon " + str(Images[image].ID) + " " + Images[image].Name)

        # check polling interval parameter
        try:
            temp = int(Parameters["Mode1"])
        except:
            Domoticz.Error("Invalid polling interval parameter")
        else:
            if temp < 30:
                temp = 30  # minimum polling interval
                Domoticz.Error("Specified polling interval too short: changed to 30 minutes")
            elif temp > 1440:
                temp = 1440  # maximum polling interval is 1 day
                Domoticz.Error("Specified polling interval too long: changed to 1440 minutes (24 hours)")
            self.pollinterval = temp
        Domoticz.Log("Using polling interval of {} minutes".format(str(self.pollinterval)))


    def onStop(self):
        Domoticz.Debug("onStop called")
        Domoticz.Debugging(0)


    def onHeartbeat(self):
        now = datetime.now()
        if now >= self.nextupdate:
            self.nextupdate = now + timedelta(minutes=self.pollinterval)
            self.pollnodes()

    # BatteryLevel specific methods

    def pollnodes(self):
        self.BatteryNodes = []

        if not self.zwaveinfofilepath:
            # find zwave controller(s)... only one active allowed !
            controllers = glob.glob("./Config/zwcfg_0x????????.xml")
            if not controllers:
                # test if we are running on a synology (different file locations)
                controllers = glob.glob("/volume1/@appstore/domoticz/var/zwcfg_0x????????.xml")
            for controller in controllers:
                lastmod = datetime.fromtimestamp(os.stat(controller).st_mtime)
                if lastmod < datetime.now() - timedelta(hours=2):
                    Domoticz.Error(
                        "Ignoring controller {} since presumed dead (not updated for more than 2 hours)".format(
                            controller))
                    self.zwaveinfofilepath = None
                else:
                    self.zwaveinfofilepath = controller
                    break

            if not self.zwaveinfofilepath:
                Domoticz.Error("Enable to find a zwave controller configuration file !")
            else:
                # poll the openzwave file
                try:
                    zwavexml = xml.parse(self.zwaveinfofilepath)
                    zwave = zwavexml.getroot()
                except:
                    Domoticz.Error("Error reading openzwave file {}".format(self.zwaveinfofilepath))
                else:
                    for node in zwave:
                        for commandclass in node[1]:  # node[1] is the list of CommandClasses
                            if commandclass.attrib["id"] == "128":  # CommandClass id=128 is BATTERY_LEVEL
                                self.BatteryNodes.append(zwnode(int(node.attrib["id"]), node.attrib["name"],
                                                                int(commandclass[1].attrib["value"])))
                                break

        for node in self.BatteryNodes:
            Domoticz.Debug("Node {} {} has battery level of {}%".format(node.nodeid, node.name, node.level))
            # if device does not yet exist, then create it
            if not (node.nodeid in Devices):
                Domoticz.Device(Name=node.name, Unit=node.nodeid, TypeName="Custom",
                                Options={"Custom": "1;%"}).Create()
            self.UpdateDevice(node.nodeid, str(node.level))


    def UpdateDevice(self, Unit, Percent):
        # Make sure that the Domoticz device still exists (they can be deleted) before updating it
        if Unit in Devices:
            levelBatt = int(Percent)
            if levelBatt >= self.batterylevelfull:
                icon = "batterylevelfull"
            elif levelBatt >= self.batterylevelok:
                icon = "batterylevelok"
            elif levelBatt >= self.batterylevellow:
                icon = "batterylevellow"
            else:
                icon = "batterylevelempty"
            try:
                Devices[Unit].Update(nValue=0, sValue=Percent, Image=Images[icon].ID)
            except:
                Domoticz.Error("Failed to update device unit " + str(Unit))
        return


global _plugin
_plugin = BasePlugin()

def onStart():
    global _plugin
    _plugin.onStart()

def onStop():
    global _plugin
    _plugin.onStop()

def onHeartbeat():
    global _plugin
    _plugin.onHeartbeat()

# Generic helper functions
def DumpConfigToLog():
    for x in Parameters:
        if Parameters[x] != "":
            Domoticz.Debug( "'" + x + "':'" + str(Parameters[x]) + "'")
    Domoticz.Debug("Device count: " + str(len(Devices)))
    for x in Devices:
        Domoticz.Debug("Device:           " + str(x) + " - " + str(Devices[x]))
        Domoticz.Debug("Device ID:       '" + str(Devices[x].ID) + "'")
        Domoticz.Debug("Device Name:     '" + Devices[x].Name + "'")
        Domoticz.Debug("Device nValue:    " + str(Devices[x].nValue))
        Domoticz.Debug("Device sValue:   '" + Devices[x].sValue + "'")
        Domoticz.Debug("Device LastLevel: " + str(Devices[x].LastLevel))
    return
I've search a code for python plugin you can check this after that any problem you visit python tutorial & get the solution.
jvlerick
Posts: 6
Joined: Sunday 03 December 2017 15:18
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by jvlerick »

I'm running Beta v. 4.10798 (19/5/2019/) and Battery monitoring has stopped working. Not sure exactly when it stopped but I noticed that battery level was not updated after replacing a battery from a smoke sensor.

The log shows these 2 errors:
Error: (Battery Monitoring) Ignoring controller ./Config/zwcfg_0x????????.xml since presumed dead (not updated for more than 2 hours)
Error: (Battery Monitoring) Enable to find a zwave controller configuration file !

In domoticz/config there is indeed a zwcfg_0x????????.xml that looks like it is not being updated. There is also a ozwcache_0x????????.xml that does get updated regularly.

How can I get working again?
Logread
Posts: 228
Joined: Sunday 28 August 2016 7:48
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: France
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by Logread »

jvlerick wrote: Monday 20 May 2019 20:03 I'm running Beta v. 4.10798 (19/5/2019/) and Battery monitoring has stopped working. Not sure exactly when it stopped but I noticed that battery level was not updated after replacing a battery from a smoke sensor.

The log shows these 2 errors:
Error: (Battery Monitoring) Ignoring controller ./Config/zwcfg_0x????????.xml since presumed dead (not updated for more than 2 hours)
Error: (Battery Monitoring) Enable to find a zwave controller configuration file !

In domoticz/config there is indeed a zwcfg_0x????????.xml that looks like it is not being updated. There is also a ozwcache_0x????????.xml that does get updated regularly.

How can I get working again?
I was anticipating this question when I saw that domoticz was recently upgraded to openzwave 1.6 that uses a different cache file than 1.4
I need to update the plugin accordingly but not yet found the time.
In the meantime, you can edit the code of plugin.py to replace zwcfg_0x????????.xml by ozwcache_0x????????.xml and that should get you going... please report back if this works.
jvlerick
Posts: 6
Joined: Sunday 03 December 2017 15:18
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by jvlerick »

Thanks for your swift reply. I opened plugin.py in a tekst editor and replaced the 2 instances I found.
After reboot it is still not working and I now have these errors in the log:

2019-05-20 20:33:52.632 Error: (Battery Monitoring) 'onHeartbeat' failed 'KeyError'.
2019-05-20 20:33:52.632 Error: (Battery Monitoring) ----> Line 246 in '/home/pi/domoticz/plugins/BatteryLevel/plugin.py', function onHeartbeat
2019-05-20 20:33:52.632 Error: (Battery Monitoring) ----> Line 164 in '/home/pi/domoticz/plugins/BatteryLevel/plugin.py', function onHeartbeat
2019-05-20 20:33:52.632 Error: (Battery Monitoring) ----> Line 202 in '/home/pi/domoticz/plugins/BatteryLevel/plugin.py', function pollnodes
Logread
Posts: 228
Joined: Sunday 28 August 2016 7:48
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: France
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by Logread »

Ok. I need to investigate, but I have not yet upgraded to recent betas. Can you please send by pm your ozwcache file so that I can check if its structure changed ?
jvlerick
Posts: 6
Joined: Sunday 03 December 2017 15:18
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by jvlerick »

As soon as I can get a copy off my Raspberry, I'll send it, as I have not found a way to quickly copy it from my Pi to my PC
pics
Posts: 1
Joined: Tuesday 12 September 2017 16:34
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by pics »

int(commandclass[1].attrib["value"])

must be change by

int(commandclass[3].attrib["value"])


on line 202 (plugin.py)
Logread
Posts: 228
Joined: Sunday 28 August 2016 7:48
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: France
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by Logread »

pics wrote: Monday 10 June 2019 18:46 int(commandclass[1].attrib["value"])

must be change by

int(commandclass[3].attrib["value"])


on line 202 (plugin.py)
Thanks, I’ll check into this (another user sent me a sample cache file). I’ll work on this and release another version in the coming days.
jvlerick
Posts: 6
Joined: Sunday 03 December 2017 15:18
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by jvlerick »

That seems to do the trick indeed. Thanks!
Logread
Posts: 228
Joined: Sunday 28 August 2016 7:48
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: France
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by Logread »

Version 0.5.0 of the plugin is now available from GitHub for upgrading.

It should be compatible with recent beta versions of domoticz using openzwave 1.6, but I could not test (I have not yet upgraded to OZW 1.6), so please report back.

It retains backward compatibility with previous OZW versions (that is tested !)

Thanks to @pics and @dobber !
Logread
Posts: 228
Joined: Sunday 28 August 2016 7:48
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: France
Contact:

Re: Python plugin: Battery Level for Z-Wave Devices

Post by Logread »

Plugin version 0.6.0 is now available for download

Follow instruction from the wiki: https://www.domoticz.com/wiki/Plugins/BatteryLevel.html

Please note this version uses a new Domoticz API call designed by @Gizmocuz for openzwave 1.6 and will only work with Domoticz version 4.11253 or higher !
When updating, please check out the new parameters introduced in that version in the hardware tab. Otherwide the plugin will fail to work.
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest