Odd commands being generated

Can someone help me out here and make sure I am not going mad! I have a Qubino Smart Meter (ZMNHTD1) which is being detected and set up as a Aeon Home Energy Monitor. In the DH code it does actually say it handles the Qubino (and it has some specific settings for the model number etc.) so I think that’s fine. I have also tried a community DH which supports more values (voltages etc.) and now I have started my own DH but all have the same odd behavior…

It works fine for a while, maybe up to an hour or so, where it is reporting the power usage all OK but then it stops working and I start getting this logged:

Exception ‘java.lang.NullPointerException: Cannot invoke method parse() on null object’ encountered parsing 'cmd: 2104, payload: ’

In that example the command is 2104 but if I power cycle it, it will work for a bit but then I will get a different one like:

Exception ‘java.lang.NullPointerException: Cannot invoke method parse() on null object’ encountered parsing 'cmd: 4621, payload: ’

I understand the first two digits of the command are the code from here: https://graph.api.smartthings.com/ide/doc/zwave-utils.html but I have had some, like “B0” which are not even listed as valid commands?! It’s as if my Qubino starts spewing out rubbish on to my network; could that be the case (i.e. a malfunctioning device) or am I missing something?

Thanks for any help you can give…

I will tag for you @johnconstantelo, he might can help with this issue.

1 Like

I am trying to use the same qubino meter too, sometimes I am getting a null value returned from the parse but I grabbed the section from the original device handler (Aeon Home Energy Monitor) to just test first if it was not null first. I assume that this will still give you an error though as you are trying to parse it first to see what it is.

def parse(String description) {
	def result = null
    def cmd = zwave.parse(description)
    log.debug(cmd)
    if (cmd) {
    	log.debug("Created event")
		result = createEvent(zwaveEvent(cmd))
        log.debug(result)
	}
	log.debug "Parse returned ${result?.descriptionText}"
	return result
}

What version of the z-wave meter command class are you using with it? The device handler for the Aeon Home Energy Monitor used version 2 but from the information I can find on the device it uses version 4. The documentation that smart things reference for z-wave commands only supports V1, V2 and V3. I did change the device handler to use version 3 and the results where a bit more reliable so maybe could give that a try?

Can I ask also did you mange to set the configuration parameter 42 to send updates at a set timed interval, cant seem to get it working.

OK, so just for fun I am now pre-parsing the “description” and ignoring it is the payload is null; so now there are no errors:

def parse(String description) { 
    def payload=null
    def start = description.indexOf("payload:")
    if (start>-1) payload=description.substring(start+9)
    if (payload=="") {
    	log.debug "Returning..."	
    	return
    }
    log.debug "Parsing..."
	def result = null
	def cmd = zwave.parse(description, [0x31: 1, 0x32: 1, 0x60: 3])
	if (cmd) {
		result = createEvent(zwaveEvent(cmd))
	}
	log.debug "Parse returned ${result?.descriptionText}"
	return result
}

But that doesn’t really solve the problem, because it is now silently ignoring the spurious commands and still not updating.

I am not sure which version of the command class I am using; how would I know (sorry, I have written a fair bit of code in my time, but I am not all that familiar with ST)?

Yes, I seem to have set the parameters because as I am getting frequent events (although they all fail with the above issue). I am using this:

def configure() {
	log.debug "configure()..."
	if (zwaveInfo.model.equals("0052")) {
		log.debug "Setting Qubino to 5% change or every 1 minute"
        delayBetween([
				encap(zwave.configurationV1.configurationSet(parameterNumber: 40, size: 1, scaledConfigurationValue: 5)), // Device will report on 5% power change
				encap(zwave.configurationV1.configurationSet(parameterNumber: 42, size: 2, scaledConfigurationValue: 60)), // report every 1 minute
		], 500)
        }
	else
		log.debug "Unknown model: $zwaveInfo.model"
}

And you just need to hit the configure button on the classic app to apply these.

I’m not too sure on your problem but I’ll give you a way of maybe testing it a bit further to see if you are getting a meter event. The command classes are just functions that the z-wave devices support, reference material on them can be found here. In smart things you basically parse the event coming in using the parse method and then use the create event method to create an event for the given command. The function zwaveEvent is normally an overloaded function which means depending upon the particular z-wave command passed to it a different implementation will be called.

In the original device handler you should have a refresh function that is called when you click the refresh button in the GUI. Add the lines for voltage, watts, kwh and amps below. Here I use version 3 of the meter command class and I am using the command zwave.meterV3.meterGet to poll these values.

def refresh() {
	log.debug "refresh()..."
	delayBetween([
    		// Change back to encap
			crcEncap(zwave.associationV2.associationRemove(groupingIdentifier: 1, nodeId:[])), // Refresh Node ID in Group 1
   			crcEncap(zwave.associationV2.associationSet(groupingIdentifier: 1, nodeId:zwaveHubNodeId)), //Assign Node ID of SmartThings to Group 1
			crcEncap(zwave.meterV3.meterGet(scale: 0)), //kwh
			crcEncap(zwave.meterV3.meterGet(scale: 2)), //Watts 
            crcEncap(zwave.meterV3.meterGet(scale: 4)), //Voltage 
            crcEncap(zwave.meterV3.meterGet(scale: 5))  //Amps
	])
}

I see you have the function encap which if you are using the default device handler should look something like this.

private encap(physicalgraph.zwave.Command cmd) {
	if (zwaveInfo.zw.contains("s")) {
		secEncap(cmd)
	} else if (zwaveInfo?.cc?.contains("56")){
        crcEncap(cmd)
	} else {
		cmd.format()
	}
}

private crcEncap(physicalgraph.zwave.Command cmd) {
	zwave.crc16EncapV1.crc16Encap().encapsulate(cmd).format()
}

I noticed that it always reverted to using the secEncap with this meter as zwaveInfo.zw returns Ls but the device commands show that this meter uses CRC16 Encapsulation so thats why I call crcEncap in the first snippet to format the command.

When the meter is polled it will return with a meterV3.MeterReport command to the parse method. You need to define a function to handle this command, the one I am using is shown below.

def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd) {
	def meterTypes = ["Unknown", "Electric", "Gas", "Water"]
    def electricNames = ["energy", "energy", "power", "count",  "voltage", "current", "powerFactor",  "unknown"]
    def electricUnits = ["kWh",    "kVAh",   "W",     "pulses", "V",       "A",       "Power Factor", ""]
    def map = [ name: electricNames[cmd.scale], unit: electricUnits[cmd.scale], displayed: state.display]
    
    //NOTE ScaledPreviousMeterValue does not always contain a value
    // Either will be first value if true or other value 
    def previousValue = cmd.scaledPreviousMeterValue ?: 0
    
    // Switch is like a case statment in bash 
    // Testing the scale for each of the sensors 
   	switch(cmd.scale) {
        case 0: //kWh
	    previousValue = device.currentValue("energy") ?: cmd.scaledPreviousMeterValue ?: 0
            map.value = cmd.scaledMeterValue
            break;
        case 1: //kVAh
            map.value = cmd.scaledMeterValue
            break;
        case 2: //Watts
            previousValue = device.currentValue("power") ?: cmd.scaledPreviousMeterValue ?: 0
            map.value = Math.round(cmd.scaledMeterValue)
            break;
        case 3: //pulses
            map.value = Math.round(cmd.scaledMeterValue)
            break;
        case 4: //Volts
            previousValue = device.currentValue("voltage") ?: cmd.scaledPreviousMeterValue ?: 0
            map.value = cmd.scaledMeterValue
            break;
        case 5: //Amps
            previousValue = device.currentValue("current") ?: cmd.scaledPreviousMeterValue ?: 0
            map.value = cmd.scaledMeterValue
            break;
        case 6: //Power Factor
        case 7: //Unknown
            map.value = cmd.scaledMeterValue
            break;
        default:
            break;
    }
    createEvent(map) // Will handle updating the values for the meter 
}

Now anytime you click the refresh button it should poll the meter for the current value of voltage, energy, power and current. Might be a bit of an easier way of debugging.

Regarding the configuration parameters I have got the timer working however it only updates every 10 minutes. According to the official user manual the meter can report on a minimum interval of 60 seconds. However according to the z-wave alliance the meter can only report at an minimum interval of 10 minutes.

Is your device reporting at a regular interval of 60 seconds or is your values of Watts changing quite frequently so it is inducing a report?

Hello,

I have included some of your code and the only odd thing that I don’t understand is that, as you say, the device is returning Ls for zwaveInfo.zw which I understood means it is secure (whatever that means?) and yet you are forcing it to use:
zwave.crc16EncapV1.crc16Encap().encapsulate(cmd).format()
rather than:
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
and I am not sure why I would do that, especially as the secure encapsulation is actually working on mine?

But that is an aside really, because my issue is about the random commands with null payloads still.

So, after I made the changes last night, all was well and from 19:25 and it started making regular reports. At least every minute, even when the difference in wattage was less than 5% (there are some reports that are as little as 0.2 W different from the previous one) and they are logging more or less the same number of seconds past each minute, so the 60 second reports do seem to work…

…until midnight! Maybe that is a coincidence but it seems odd. Other times this has happened it has happened at random times, so I won’t focus on the timing for now (I will turn the power off later and see what happens tonight). But as of midnight, we started receiving “zw device: 44, command: 4A21, payload:” (i.e. an invalid command and null payload). And that has repeated a couple of times a minute ever since!

As far as I am aware 0x4A isn’t even a valid command from one of these and I have had several other commands (i.e. 0x21 and 0x46) at random (although until I reboot it, it keeps resending the same one).

Hi @HeMan,

I have solved my problem on the timing somewhat if you want to have a read here .

I was just sharing what I had done and tried as some of it may solve your problem. The reason I suggested using CRC15 was that on the z-wave allaince website here it mentions that CRC16 Encapsulation command class is compatible, I wasn’t sure if the the securityV1 was. Looking at the user manual however now though page 48 both methods are supported and work fine.

I am going to develop the device handler a bit more first and then I dont mind sharing with you if it actually works and the issues I run into, it seems to be a bit of a learning curve getting used to it.

Glad you are making progress Warren, happy to share my stuff too…

But my current problem is my dodgy module. So at 18:51 I power cycled it and it started reporting every minute all OK again.21:19 it started reporting this:
zw device: 44, command: 6A21, payload:

Another random command with a null payload?!

Do I take it no one else is seeing this behaviour? If not, could this just be a dead module I need to return?

Checked the log messages for my meter there and beginning to run into a similar problem but a different command. This was after just 10 minutes of being operational so you got longer than me.

ce3b2848-133f-469b-acc3-acd34f1b4519 10:13:23: debug Parse returned null
ce3b2848-133f-469b-acc3-acd34f1b4519 10:13:23: debug null
ce3b2848-133f-469b-acc3-acd34f1b4519 10:13:23: warn Exception 'java.lang.NullPointerException: Cannot invoke method parse() on null object' encountered parsing 'cmd: 2104, payload: '

The way the commands are broken is the first byte is the command class and the second byte is the command. So far you say you have had 2104 ,4A21, 4621. Using this file as a reference to find out what these are:

0x21 - COMMAND_CLASS_CONTROLLER_REPLICATION

COMMAND VALUE
CTRL_REPLICATION_TRANSFER_GROUP 0x31
CTRL_REPLICATION_TRANSFER_GROUP_NAME 0x32
CTRL_REPLICATION_TRANSFER_SCENE 0x33
CTRL_REPLICATION_TRANSFER_SCENE_NAME 0x34

0x4A - COMMAND_CLASS_TARIFF_CONFIG

COMMAND VALUE
TARIFF_TBL_SUPPLIER_SET 0x01
TARIFF_TBL_SET 0x02
TARIFF_TBL_REMOVE 0x03

0x46 - COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE (NOTE THIS IS DEPRECIATED ACCORDING TO FILE ABOVE)

COMMAND VALUE
SCHEDULE_SET 0x01
SCHEDULE_GET 0x02
SCHEDULE_REPORT 0x03
SCHEDULE_CHANGED_GET 0x04
SCHEDULE_CHANGED_REPORT 0x05
SCHEDULE_OVERRIDE_SET 0x06
SCHEDULE_OVERRIDE_GET 0x07
SCHEDULE_OVERRIDE_REPORT 0x08

So none of the commands associated with these classes that the meter is sending are valid commands. In the manual for the device I cannot see that the meter supports COMMAND_CLASS_CONTROLLER_REPLICATION, COMMAND_CLASS_TARIFF_CONFIG or COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE.

The device begins to work after I reset it but shortly after returns to giving the above log message for the 2104 command.

Well, and I hope you don’t take this the wrong way, but I am a little relieved yours is failing too! At least it isn’t something I am doing and this suggests we (probably) don’t both have faulty modules.

I have spoken to Quibino today and they are suggesting a firmware upgrade. I am just confirming the details with them, but if you like I can go first and let you know if it solves the issue…

If it does, you will need a USB z-wave dongle for the upgrade of the firmware, so if you haven’t got one to hand you might like to get one ordered (they are only a few pounds on eBay etc.).

Nope I’d rather everyone’s fail than an odd one here and there, you are fine. Yeah that would be great please let me know how you get on with it and if it fixes the issue as I need this device to work. A bit annoying now that might have to buy extra hardware to use this device, the point of the hub was that no external z-wave usb sticks where needed. How did you manage to get in contact with Qubino? I have submitted a ticket but no response so far.

I bought one of these: https://www.everspring.com/portfolio-item/sa413-z-wave-usb-stick/
It only cost £7.50 from eBay including postage and as ST doesn’t do firmware upgrades it is the only way of upgrading firmware in any z-wave device, so it might be worth getting one (although at a quick glance I can’t see any on eBay currently; maybe it’s been replaced with a newer model?).

I just contacted them through their web site and a chap called Igor got back to me this morning.

I am going to have to turn the power off again, so will do this later and let you know…

1 Like

Thanks let me know how it goes!

Well, the firmware updating seems to work but doesn’t actually change anything (not even the reported firmware version of 7.11)! The other odd thing is that even though I have done a few factory resets the kWh figure has never reset, which seems odd?! I will let you know what Igor says on all this shortly…

The other odd thing, which is more of a SmartThings question, is that I have noticed when it is working, the app updates the current Watt value even though the Parse function isn’t being run! Is that possible? I have added a log.debug to the first line of the Parse function and yet it isn’t being run when the 1-minute updates come in. Does that sound right to you?