How to receive data from device when physical state changes

I'm working on writing my first driver for a raspberry pi based garage door controller I'm working on. I currently have a Close and Open function within the driver that makes an httpPost() call to the raspberry pi. This works to issue an open or close command, but how do I get information back about the state of the door if I open/close it manually?
I've looked at schedule(), or runEvery1Minute() to run a refresh function that could get the state of the door in the response message, but that seems inefficient. Am I missing how I would initiate something from the device side?

Welcome to hubitat!!!

You don't want to do that.....

Hubitat accepts unsolicited HTTP POST messages on port 39501. The hub will automatcially send these messages to the "parse()" method of the device who's device network ID matches the mac address of the sender. So, your RPi could send a message back to the hub that way.

Also, you could use the reply from the message that the hub is sending. That will also automatically be passed off to the device that sent it automatically.

3 Likes

I didn’t know about 39501 being a special port. Is there any documentation on this?

No...it's used by Hubduino if you want to take a look at that project here on the forum.

@Ryan780 Thanks, I'll try that out. That does seem like something that should be documented. Unless there's a more accepted method of talking with LAN devices?

Talking with or accepting data from? I don't know about "best" but it is certainly one of them. The only other method would be to have a service manager app that would accept HTTP messages with a specific URL on port 80. Those are the only two methods the hub has for accepting unsolicited HTTP calls. Now, if you only want to poll a lan device, that's a little different (but not as immediate either)

It might be documented somewhere, I can't answer that. Hubitat's documentation isn't the most complete in the world. They're working on it and it's much better than it was. But in a system this complicated and under active development there will always be holes.

So that definitely gets me closer. I now have the hubitat successfully receiving POST requests and passing to the parse function within my driver. Now the trick is interpreting the data.

#RaspberryPi Python call:
requests.post('http://10.0.0.10:39501/', json={'status':'closed', 'previous:'closing'})

#Driver parse function:
def parse(String description) {
log.debug(description)
}

Log result:
mac:B827EB39C3FB, ip:0a0000f5, port:b86e, headers:UE9TVCAvIEhUVFAvMS4xDQpBY2NlcHQ6ICovKg0KVXNlci1BZ2VudDogcHl0aG9uLXJlcXVlc3RzLzIuMjIuMA0KQ29ubmVjdGlvbjoga2VlcC1hbGl2ZQ0KSG9zdDogMTAuMC4wLjEwOjM5NTAxDQpBY2NlcHQtRW5jb2Rpbmc6IGd6aXAsIGRlZmxhdGUNCkNvbnRlbnQtTGVuZ3RoOiA0Mw0KQ29udGVudC1UeXBlOiBhcHBsaWNhdGlvbi9qc29uDQo=, body:eyJzdGF0dXMiOiAiY2xvc2VkIiwgInByZXZpb3VzIjogImNsb3NpbmcifQ==

I know the data is showing up in the body since I get an empty body if I don't pass the json argument in the python call. I have no idea how to interpret that data into anything useful though.

It's a little simpler than that.

def parse(String description) {
    def msg = parseLanMessage(description)
	def body = msg.body
    body = parseJson(body)
    def  status = body.status
    def previous = body.previous
    log.debug ("Status = $status  & Previous = $previous") 
}

Give that a try and see if spits out what you're looking for.

2 Likes

Works like a charm, thanks so much!

1 Like

Not a problem. Glad I could help.

1 Like