Need Help formatting a wattr command to send a string to a Zigbee device

I'm trying to send a string to a Zigbee CC2530 based device. The information on the device states it communicates with "ZCL_CLUSTER_ID_GEN_MULTISTATE_VALUE_BASIC" and "ATTRID_IOV_BASIC_STATE_TEXT" (see below).

I've put together the he wattr command, guessing how to built the different parameters. I skipped the CMD parameter but don't know if it being missing screws up the command structure.

Any guidance or an example will be greatly appreciated.
Thanks
John

Error LOG:

My Reference Material:

Zigbee clusters

Zigbee cluster: ZCL_CLUSTER_ID_GEN_MULTISTATE_VALUE_BASIC
Zigbee attributes: ATTRID_IOV_BASIC_STATE_TEXT - UART data
You should use the "ZCL_DATATYPE_OCTET_STR" (0x41) or "ZCL_DATATYPE_CHAR_STR" (0x42) data types for this attribute.

Additional Info:

try:

he wattr 0x${device.deviceNetworkId} 1 0x0014 0x08 0x000E 0x42 {testString}

dev:40912024-10-26 21:58:31.759infofingerprint profileId:"0104", endpointId:"01", inClusters:"0000,0014", outClusters:"0000", model:"ptvo.switch", manufacturer:"ptvo.info", controllerType: "ZGB"

Device info:

dev:40912024-10-26 21:58:31.660traceZCL version:01
dev:40912024-10-26 21:58:31.657traceSoftware Build Id:2024-07-23
dev:40912024-10-26 21:58:31.654traceModel:ptvo.switch
dev:40912024-10-26 21:58:31.651traceManufacturer:ptvo.info

Error LOG:

My Latest Code:

// Hubitat driver for  PTVO CC2530 Zigbee Board

import hubitat.device.HubAction
import hubitat.device.HubMultiAction
import hubitat.device.Protocol

metadata
{
    definition(name: "Zigbee Raw Message", namespace: "johnrob", author: "johnr")
    {
        capability "Actuator"
        //capability "Switch"

        //capability "Initialize"

        attribute "mystr", "String"
        
        command "Str01"
        command "sendCommand", ["string"] //allows arbitrary comm
        

    }
    preferences{
       // input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true
       // input name: "logInfo", type: "bool", title: "Enable Info logging", defaultValue: false
       
    } //  --- metadata ---
}

def parse(String description){

    log.info  "Raw Description#$description"

    Map map = [:]
    def event = zigbee.getEvent(description)

    //if (event) sendEvent(event)

    if (description?.startsWith('read attr -')){

        def descMap = zigbee.parseDescriptionAsMap(description)

        if (descMap.cluster == "000C" && descMap.attrId == "0055"){     // zigbee spec 0x000C= read analog cluster  0x0055 = present value
            ZigbeeHexMap = descMap.value
            log.info "Zigbee Msg#$ZigbeeHexMap"
            float SensorValue = ConvertHexToFloat(ZigbeeHexMap)
            def otherAttrs = descMap?.additionalAttrs
            otherAttrs.each{
                unitaddress = it.value
            }
            log.info ("$unitaddress")
            def (units, address) = unitaddress.tokenize( ',' )   //   <--- units and I2C address



        } // --- if cluster ---
    } // --- if "read attr" ---
} // --- parse ---

def Str01() {
    string  mystr = "wxyz"
    def packed = hubitat.helper.HexUtils.byteArrayToHexString(mystr.getBytes())
    "he wattr 0x${device.deviceNetworkId} 1 0x0014 0x08 0x000E 0x42 {4"+packed+"}"
}

I believe that the error in the logs says that you should change string to String.

1 Like

The log error is gone, however I'm not sure my message format is correct, mostly due to the not needed CMD parameter.
And the receiving end is not receiving the message.

Any reason to not use either of the built in commands for this?

to write an attribute use
Zigbee.writeAttribute(Integer cluster, Integer attributeId, Integer dataType, Integer value, Map additionalParams = [:], int delay = 2000)
where additional attributes mfgCode can be used if it's a manufacturer specific cluster
and destEndpoint can be used if the endpoint of interest is not the device default endpoint.

To send a command use:
Zigbee.command(Integer cluster, Integer command, Map additionalParams, int delay = 2000, String... payload)
where additional attributes mfgCode can be used if it's a manufacturer specific cluster
and destEndpoint can be used if the endpoint of interest is not the device default endpoint.

2 Likes

Lack of understanding.

The device documentation states the device supports:

And I didn't know the alternate you suggested would meet this criteria. And when I the parameters of your suggestion I was unsure how to deal with the seemingly single data value. My goal is to send a multiple char string message.

However, I'll give your suggestion a try.

Thanks

John

I have no idea if this will be of any help or not... Years ago I wrote a driver for the old SmartThings Thingshield, which sends and receives a text string via Zigbee. I doubt that old ThingShield was following any traditional Zigbee standards, but I was able to get things working on Hubitat with the help of Chuck Schwer.

Here is the code from my driver for sending a string over Zigbee to the ThingShield. Maybe it'll help?

def sendData(String message) {
    if (logEnable) log.debug "sendData(${message}) called"
    sendThingShield(message)
}

def sendThingShield(String message) {
    def encodedString = DataType.pack(message, DataType.STRING_CHAR).substring(2)
	return "he raw 0x${device.deviceNetworkId} 1 0x${device.endpointId} 0x0 {00000a0a" + encodedString + "}"
}

This still works to this day. I recently tested a ThingShield for a ST user who was finally moving over to Hubitat.

1 Like

@ogiewon Thank you (again) for your help. (now and in the past).

I'll give it a try.

John

1 Like

I believe writing value "abcd" to attribute 0x000E of cluster 0x0014 can be done with:

he raw 0xE860 0x01 0x01 0x0014 {104302 0E00 42 0461626364}
       ^      ^    ^    ^           ^  ^    ^  ^ ^
       |      |    |    |           |  |    |  |  ` 0x61 = 'a', 0x62 = 'b', 0x63 = 'c', 0x64 = 'd'
       |      |    |    |           |  |    |   ` 0x04 = string size (4 ascii characters, 1 byte per char)
       |      |    |    |           |  |     ` 0x42 = string data type
       |      |    |    |           |   ` 0x000E = attribute id (reversed / little endian)
       |      |    |    |            ` 0x02 = Write Attribute command id
       |      |    |     ` 0x0014 = cluster id
       |      |     ` 0x01 = device (destination) endpoint id
       |       ` 0x01 = hub (source) endpoint id
        ` replace with ${device.deviceNetworkId}

Writing an array of strings (which the spec says attribute 0x000E expects) is way above my pay grade :slight_smile:

2 Likes

It's well above my pay grade as well. However I never let that stop me before.

Any idea what the 1043 is before the 02 = write attribute command ID?
{104302 0E00 42 0461626364}

With this and what @ogiewon posted perhaps I can get this going.

Thanks
John

2 Likes

10 = Frame control field, check the spec for what each bit (not byte) means:

43 = Transaction sequence number, I believe can be whatever you want

When I'm dealing with data to and from a device that i'm not sure about, i send read attribute requests to the cluster and attribute of interest, that way I can get an idea of what the device is expecting from a write standpoint.

Also, I hate to say it, but developing zigbee drivers without having a sniffer to actually see how the commands are being formatted both to and from the device can be very difficult.

3 Likes

Thanks for the hint.

I have a sniffer (in a box), working on getting it going. I've used Wireshark before but working on getting the "sniffing" part working.