App and driver porting to Hubitat

From ST documentation:

zigbee.convertToHexString()

Convert the given value to a hex string of given width

Signature:

zigbee.convertToHexString(Integer value, Integer width)

COPY

Parameters:

  • value : Integer value to be converted
  • width : the minimum width of the hex string. Default value is 2

Looks like you need a second "width" parameter

Maybe
${zigbee.convertToHexString(status,2)}${zigbee.convertToHexString(seconds,2)}

:man_shrugging:

OR
you may need to convert "status" and "seconds" to integers beforehand

${zigbee.convertToHexString(status.toInteger())}${zigbee.convertToHexString(seconds.toInteger())}

This one is my guess. But I haven't used that function in HE, that I can remember.

I believe there is a second parameter to that function

zigbee.convertToHexString()

Convert the given value to a hex string of given width

Signature:

zigbee.convertToHexString(Integer value, Integer width)

COPY

Parameters:

  • value : Integer value to be converted
  • width : the minimum width of the hex string. Default value is 2

:+1: Thank you, that fixed it! I swear I tried that before asking for help and it failed. However, this time it worked. I guess the default value, 2, did not make it into HE.

@mlciskey @JasonJoelOld Thank you for responding.

2 Likes

driver sendEvent difference
In a driver after issuing a sendEvent for an attribute,

sendEvent(name: "armMode", value: armMode)

then subsequently in the same event issuing a

device.currentState("armMode")

the value of the attribute at the beginning of the event is returned, not the current actual value as done in ST

The solution

2 Likes

Again, I want to caution that using this method can add more load on your hub that is not needed. It does not make sense to set a value and then immediately look up that same value in most cases.

1 Like

I agree with you. If the purpose is to validate that a command took, a runIn() call is the more efficient way to handle it. In my opinion. And that's exactly how I implemented the test procedures in my Z-Wave Repeater driver.

I understand. However, sometimes a low level of overhead is easier when porting a ST DTH to a HE driver

In my situation I have an easy workaround and when I tried the true option it did not work.

Edit: As Chuck mentioned the sendEvent command is queued by the system, so even using the "true" option may not get the value in the sendEvent command because it has not executed. If you bump into this fix the logic or code a workaround.

Couple I've found.

isNumber() and toInteger() are both string functions (for converting numeric strings to integers). Also toDecimal(), etc. According to Groovy spec, that is.

On ST, if you pass these an integer, they fail silently/gracefully. In HE, they error out. I'd argue ST is wrong to have them fail silently, but it's a difference that will have you pulling hair out as you go and change all your variable "checks")

findAllChildAppsByName('app name') fails
groovy.lang.MissingMethodException: No signature of method:

Is findAllChildAppsByName('app name') supported?

If not, does getChildApps() work?

The following are supported for an app

List<InstalledApp> getAllChildApps()
List<InstalledApp> getChildApps()
InstalledAppWrapper getChildAppById(Long childAppId)
InstalledAppWrapper getChildAppByLabel(String childAppLabel)

I'm not sure what the difference is between getChildApps() and getAllChildApps() though.

1 Like

there is no difference in Hubitat between these, one is just an alias for the other.

1 Like

Thank you for the fast reply. I uncommented my older getChildApp() code and it worked. I have a bit of recoding to do.

In SmartThings:
getChildApps() Gets child apps that are in "COMPLETED" status
getAllChildApps() Sets all child apps inluding those that have not be "Completed"

Is there a link for the information you posted?

It's in the currently incomplete Documentation section - App Object - Hubitat Documentation

In SmartThings, zigbee.parse(String description) can be used for a SmartShield generated map of ZigBee catchall messages. Some examples:

  1. catchall: 0000 0013 00 00 0040 00 0030 00 00 0000 00 00 413000D64ED801008D150080
    is parsed as
    SmartShield(text: null, manufacturerId: 0x0000, direction: 0x00, data: [0x41, 0x30, 0x00, 0xd6, 0x4e, 0xd8, 0x01, 0x00, 0x8d, 0x15, 0x00, 0x80], number: null, isManufacturerSpecific: false, messageType: 0x00, senderShortId: 0x0030, isClusterSpecific: false, sourceEndpoint: 0x00, profileId: 0x0000, command: 0x00, clusterId: 0x0013, destinationEndpoint: 0x00, options: 0x0040)

  2. catchall: 0104 0000 01 01 0040 00 0030 00 00 0000 0A 01 050042166C756D692E73656E736F725F6D61676E65742E61713201002003
    is parsed as
    SmartShield(text: null, manufacturerId: 0x0000, direction: 0x01, data: [0x05, 0x00, 0x42, 0x16, 0x6c, 0x75, 0x6d, 0x69, 0x2e, 0x73, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x5f, 0x6d, 0x61, 0x67, 0x6e, 0x65, 0x74, 0x2e, 0x61, 0x71, 0x32, 0x01, 0x00, 0x20, 0x03], number: null, isManufacturerSpecific: false, messageType: 0x00, senderShortId: 0x0030, isClusterSpecific: false, sourceEndpoint: 0x01, profileId: 0x0104, command: 0x0a, clusterId: 0x0000, destinationEndpoint: 0x01, options: 0x0040)

Maybe I'm dreaming, but it seems the Hubitat hub used to do the same, but currently (as of hub v2.0.8.113) the output from zigbee.parse(String description) of a catchall message is not a map and completely different. Here's what the Hubitat hub does with the same two example catchall messages:

  1. catchall: 0000 0013 00 00 0040 00 0030 00 00 0000 00 00 413000D64ED801008D150080
    is parsed as
    com.hubitat.zigbee.SmartShield(19, 0, [65, 48, 0, 214, 78, 216, 1, 0, 141, 21, 0, 128], 0, 0, false, false, 0, 0, null, 64, 0, 48, 0, null)

  2. catchall: 0104 0000 01 01 0040 00 0030 00 00 0000 0A 01 050042166C756D692E73656E736F725F6D61676E65742E61713201002003
    is parsed as
    com.hubitat.zigbee.SmartShield(0, 10, [5, 0, 66, 22, 108, 117, 109, 105, 46, 115, 101, 110, 115, 111, 114, 95, 109, 97, 103, 110, 101, 116, 46, 97, 113, 50, 1, 0, 32, 3], 1, 1, false, false, 0, 0, null, 64, 260, 48, 1, null)

The Hubitat output appears to be a list, but although I can match the data: portion inside the brackets, I am not sure of what everything else is supposed to represent.

So, what - if anything - can I use to parse catchall messages into a map on Hubitat?

Tagging @mike.maxwell since he's probably the only person who can answer this.

Is it alright if I give it a shot?

Nope, thats an object

Yep

Nope

You are looking at the string output of an object (SmartShield). Our toString() method is clearly different than ST's implementation. I have plans to fix up that object and populate the text field properly. I will change the toString while I'm in there. The properties are all there already: text, manufacturerId, direction, data, number, isManufacturerSpecific, messageType, senderShortId, isClusterSpecific, sourceEndpoint, profileId, command, clusterId, destinationEndpoint, options. You can use them if you want, but I get the impression that is only supposed to be for the ThingShield parsing.

use: zigbee.parseDescriptionAsMap(String)

https://docs.hubitat.com/index.php?title=Zigbee_Object#parseDescriptionAsMap

It will give you a map with the following keys: raw, clusterId, sourceEndpoint, destinationEndpoint, options, messageType, dni, isClusterSpecific, isManufacturerSpecific, manufacturerId, command, direction, data

def descMap = zigbee.parseDescriptionAsMap(description)

As an fyi, you guys crack me up, complaining about the lack of example drivers, and yet no one even looks at (much less studies) what we do have posted...
Line 65: HubitatPublic/GenericZigbeeRGBWBulb.groovy at master ยท hubitat/HubitatPublic ยท GitHub

1 Like

How does that difference work in ST? What is the difference from the user perspective with an app that is completed vs one that is not?

Nope. Not true in my case. And I haven't been complaining about a lack of example drivers.

I did look at that driver, and the previous line 64 does a return on any catchall: messages, so why would I expect zigbee.parseDescriptionAsMap(description) to do the trick?

Also, I did look at the Hubitat Documentation page on the ZigBee Methods, and I could swear the entry for parseDescriptionAsMap was not there when I looked a couple hours ago. Perhaps I missed it.

Honestly, I find it offensive that it's implied I am wasting your time asking dumb questions when I do spend the time to research as best I can, rarely ask any questions in general, and have never contacted support after my second instance.

The work I do on device drivers is unpaid, not my as my form of employment, and the time I have to dedicate to it is limited. I am not a programmer by trade, and can't be expected to know as much as you well seasoned professionals do. I just don't see how it warrants taking pot-shots when I do occasionally ask for help.

Nevertheless, as much as I am less and less inclined to ask for it with these kinds of responses, thanks for the reply.

4 Likes