sendEvent() and subscribe() problem with string case

Having trouble with a sendEvent() in a device driver that has a name of "StatusBits" and app code to subscribe() to the same name.

In order to get it working i had to change the name from "StatusBits" to "statusBits" (lower case the first letter).

Q: Is there some rule I am missing for how this is done inside the HE?

The primary reason I am asking is because in another device driver i have the same thing going on using the name "Particulates" and this works just fine.

I assume you mean an attribute name (and not the driver name, which wouldn't really make sense here, but I thought it was good to make sure)? There's definitely a convention for these to be camelCased, and I'd recommend that unless you have a good reason not to. Still, I'm not sure that there's an actual rule (though there might be given that there are things like the device.currentXYZ() methods that return the current value of attribute XYZ with a capitalized first letter being required in the method name, e.g., currentSwitch for attribute switch). Staff would have to speak to that for sure, and I'm not sure this would explain why it's working for you in once place but not another...

(I've moved this to the Developers section/cateogry on the forum, since it's not really about the use of an app, in hopes more appropriate eyes will see it. Hope that's OK!)

1 Like

Which ST DTH/SmartApp are you trying to Port to Hubitat? Since it is a StatusBits DTH/SmartApp, that would have been written by @gecko a long time ago.

There is no port going on here, but an App written for a specific purpose to support hardware that we have designed. "StatusBits" is one of the attributes in a zigbee driver that is being used to send events to subscribed Apps in the HE.

I am just wondering if there are some "case rules" that i am not aware of in getting this to work.

1 Like

Thank you for moving that. Wherever is most appropriate is just fine.

Interesting... Sorry for the confusion. There was a fairly prolific SmartThings community member named @gecko/StatusBits. That's what I thought you were working on. Carry on...nothing to see here...:wink:

1 Like

Assuming you changed the name in how the attribute is declared and how the event is sent?

Actually, the attribute is still "StatusBits", but the sendEvent() and the subscribe() have to use "statusBits".

And have you unsubscribed and resubscribed just in case and you see the actual events in the event log of the device? If so, we should tag Chuck, Mike or Bruce. Is there a requirement that it be capitalized? As bertabcd1234 mentioned the convention is definitely that they are not capitalized and attributes follow camel case.

https://docs.hubitat.com/index.php?title=Driver_Capability_List

I'm guessing that's enforced for whatever reason but we would need to tag one of them for a definite answer.

You guys are a lot better than me, debugging code without seeing it! :wink: Perhaps if the OP posted their code, that would tell us what the problem is.

I got nervous you guys found a bug so here is a test I worked up:

driver:

metadata {
    definition (name: "Test Attributes", namespace: "exampe", author: "Example") {
        capability "Sensor"
        attribute "StatusBits", "String"
        command "sendTestEvent"
    }
}

preferences {}

def installed() {
    sendEvent(name: "StatusBits", value:"123")
}

def parse(String description) {
    log.debug(description)
}

def sendTestEvent() {
    if(device.currentValue("StatusBits") == "123")
        sendEvent(name: "StatusBits", value:"456")
    else 
        sendEvent(name: "StatusBits", value:"123")
}

App:

definition(
    name: "SubscribeStatusBits",
    namespace: "example",
    author: "Example",
    description: "Subscribe to StatusBits",
    category: "My Apps",
    iconUrl: "",
    iconX2Url: "",
    iconX3Url: "")


preferences {
	section {
    	input "mySensor", "capability.sensor", title: "sensor", multiple: false, required: false
	}
}

def installed() {
    updated()
}

def updated() {
    unsubscribe()
    subscribe(mySensor, "StatusBits", "handleEvent")
}

def handleEvent(evt) {
    log.debug "Got event for ${evt.name}, value: ${evt.value}"
    log.debug "Device current value: ${mySensor.currentValue("StatusBits")}"
}

Seems fine to me:

app:4756 2020-05-12 12:49:57.425 pm debug Device current value: 123
app:4756 2020-05-12 12:49:57.422 pm debug Got event for StatusBits, value: 123
app:4756 2020-05-12 12:49:56.869 pm debug Device current value: 456
app:4756 2020-05-12 12:49:56.867 pm debug Got event for StatusBits, value: 456
2 Likes

I never mocked it up. I typically exercise blind faith until a user has proven I shouldn't trust them. :slight_smile:

i'll post what i have as soon as i get a break to justify what i was seeing and/or to have someone point out what is incorrect.

zigbee device driver with this in the metadata:

	attribute "StatusBits", "NUMBER" 		// AAA0
	attribute "PowerLevel", "NUMBER" 		// AAA1, DutyCyclePercent

in the driver Parse(), i have this:

	case 0: // StatusBits
	  name = "statusBits"
      descriptionText = "StatusBits is 0x${map.value}"
	  break

and this to send events:

        sendEvent(name:name,value:value,descriptionText:descriptionText, unit:unit)

in the App Code, i have the subscribe as:

        subscribe(GeneratorDevice, "statusBits", handleGeneratorEvent)

If I change to "StatusBits" in the case body as well as the subscribe, I never get the handler called. If I lower case the first letter, it always works.

based on the other example above, I must be doing something incorrect and am all ears as to what it might be.

	case 0: // StatusBits
	  name = "statusBits"
      descriptionText = "StatusBits is 0x${map.value}"
	  break

Yeah, this is the offending part. You are setting the name of the event in the driver to "statusBits" and creating an event with that name. So you aren't even using the attribute it turns out. You can send any event you want to be honest with or without an attribute. If you want to you can:

sendEvent(name: "NONONONONONONON": value: "BUWUAHAHAHAHA")

And the driver won't complain. It will even show up on the edit page in the states section. If you navigate away it won't save in that section though. That's what making it an attribute gets you (and other persistent things).

So, you are sending the wrong event. Change the name you send to "StatusBits" in your case 0.

Sometimes just for fun I send a bunch of events that aren't "attributed" so the end user can see config once but doesn't have to live with it. It's a handy thing to be able to send any event. In this case, I bet you were not expecting that would be the case and only events that matched attributes would be sent.

1 Like

Sorry, that made no sense as to why it is not working. The "statusBits" does work, and the "StatusBits" does not. I am not trying to send the attribute, but just the name of the attribute and the value off to the App. The App subscribes properly to the cased or non-cased name, but one comes through and the other does not.

Yes, it does make sense. Did you even make the change I told you to make?

Before:

case 0: // StatusBits
  name = "statusBits"
  descriptionText = "StatusBits is 0x${map.value}"
  break

After:

case 0: // StatusBits
  name = "StatusBits"
  descriptionText = "StatusBits is 0x${map.value}"
  break

You are sending the event with a lowercase "statusBits". What is there not to get?

Do i detect attitude?

If you read my posts, that is exactly what does not work, so please re-read as that is originally what i did.

Are you looking for help or are you looking for a fight? Saying that it made no sense without trying it is already attitude. I can't possibly understand what you are hoping to get out of this topic now that you've already had the the literal platform developer tell you it's working as intended and an extremely involved community developer telling you exactly what was wrong to send the correct event.

Congrats. I don't trust you. I think you've earned it. :+1:

I think this was the poster making fun of themself, saying that they could understand why the snippet they posted doesn't make sense (it was apparently a variation with case they tried for testing, not one with all initial caps as originally stated), not a dig saying that what you posted as help didn't make sense. :slight_smile:

That being said, this would probably be easier to troubleshoot if you (OP) posted a fully (non?)functioning minimal test case app/driver instead of just snippets--too much else could be going on with what needs to be "filled in" to make those work. Since it worked fine for Chuck, I suspect the issue may be coming from elsewhere, and trying it strip it down to exactly what causes the problem might expose what that is for you--or if it's still problematic then, then you'll have something they can use to reproduce the behavior.

Good luck!

Maybe.

And for every other developer that sends and subscribes to events.

I played around with Chuck's POC and confirmed that the attribute has absolutely no bearing on the outcome. You can change the case or remove it and the event is still sent exactly as it is in the sendEvent method call.