Any Documentation on "physicalgraph device HubAction"?

Found a GIANT BUG in using the hubAction. It will NEVER respond if you have a 10.x.x.x ip address range.

It can’t parse the hex back to a proper IP!

So if you are trying to get any local hub actions and responses to work, right now you are going to have to use a range that starts with a 3 digit ip range, 192.x.x.x ideally.

1 Like

Shocking! I’m sure @urman is kicking himself in the head this very minute. :slight_smile:

So this is what I have been able to figure out:

10.0.0.5 should convert to “0A” “00” “00” “05”  however, in the hub this shows up as “A000005” which will not translate back to 10.0.0.5 because it is missing the leading zero for the first set.

I now know this, and will change the way I get the IP to Hex functions to add the leading zero. Had to do the same thing for port numbers…

What I don’t understand is how or why anyone would ever think average users would be able to know what their hex IP and hex port code is?

Why can’t the deviceNetworkId be stored as a string like “10.0.0.5:80” as everyone knows it, and then behind the scenes convert it to Hex (properly) and then magic, everything should work much better…

Do we know if this is a groovy function or a SmartThings function? Seems IP2Hex and Dec2Hex should be pretty standard stuff.

BTW, you might want to try dealing with this as an array or list and using a Dec2Hex function on each value (assuming there is one that works).

But now that I think about it a little more, ‘A’ is a valid result for Dec2Hex(10).

Don’t know the reason why hex is needed, but guessing that’s what the hub’s hardware needs and it is too stupid to figure it out on its own.

Anyway… hope you reported this via email.

Here’s a function I wrote to potentially solve the issue, but I can’t test it in my office since the IDE doesn’t work behind a firewall for whatever reason… (Have to dig into that later)

Can someone saavy with code test this and then set back the device NetworkId to be the debug’d string

private convertIPtoHex(ipAddress) { //expecting a string like xxx.xxx.xxx.xxx
    //debuging ip addresses
    log.debug “convert hit”
    //ipAdddress = “10.0.0.5”
   log.debug ipAddress
    //String hex = ‘0x’ + ipAddress.tokenize( ‘.’ ).collect {  String.format( ‘%02x’, it.toInteger() ) }.join()
    String hex = ipAddress.tokenize( ‘.’ ).collect {  String.format( ‘%02x’, it.toInteger() ) }.join()
    log.debug hex
    
}

otherwise I’ll test it tonight when I get home.

The issue is simple, converting decimal “10” to Hex is “A” but for IP notation, it is “0A” because decimal “192” is “C0” so in order to cover the entire range of 1-255 you need a double byte HEX.

So when the hub is trying to match up a device at “0A000005” (10.0.0.5) and the deviceNetworkId is only “A000005” it won’t work.

Simple issue, just the code examples of how to convert a string IP to hex are all wrong.

The same issue was with port numbers which can range from 1-65535

So 80 would be “50” but really needs to read “0050”

Where as 5000 would be “1388” and works or 65534 would be “FFFE”

So the existing functions someone wrote to convert IP to Hex need to be fixed, along with ports.

Wouldn’t it just be easier to do this behind the scenes and let users enter standard IP and Port notation, 10.0.0.5:80?

Why make it so difficult.

@pstuart, I don’t get it why you need to convert IP address to hex. HTTP GET works for me with dotted addresses (192.168.1.100:80). Although I’m calling it from the app, not the device handler.

@geko,

The deviceNetworkId in ST for the local hubaction GET needs a hex ip and port in the device settings.

HTTPGET which is cloud based, external does not.

If you want to port forward your cameras, then you can use HTTPGET but if you don’t want the world seeing your cameras, then you can use my code for the generic camera device. In the preferences you enter the IP and Port and I automatically convert it to Hex in the device.

I’m not talking about “external” HTTP GET. I’m talking to my WiFi thermostat locally using sendHubAction() and I don’t need to do any hex conversion.

Here’s my log reading thermostat version (GET /tstat/version):

5ce516f6-38cc-4e24-8102-793536912397 10:57:49 PM PDT: debug body: {“version”:100}
5ce516f6-38cc-4e24-8102-793536912397 10:57:49 PM PDT: debug headers: HTTP/1.1 200 OK
Server: Marvell 8688WM
Connection: close
Transfer-Encoding: chunked
Content-Type: application/json
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Pragma: no-cache
5ce516f6-38cc-4e24-8102-793536912397 10:57:49 PM PDT: debug parseLanResponse([index:01, mac:5CDAD424AC32, ip:C0A80169, port:0050, headers:SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IE1hcnZlbGwgODY4OFdNDQpDb25uZWN0aW9uOiBjbG9zZQ0KVHJhbnNmZXItRW5jb2Rpbmc6IGNodW5rZWQNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KQ2FjaGUtQ29udHJvbDogbm8tc3RvcmUsIG5vLWNhY2hlLCBtdXN0LXJldmFsaWRhdGUNCkNhY2hlLUNvbnRyb2w6IHBvc3QtY2hlY2s9MCwgcHJlLWNoZWNrPTANClByYWdtYTogbm8tY2FjaGU=, body:eyJ2ZXJzaW9uIjoxMDB9, hubId:130e9d28-2efd-4f1f-bfc3-87bf35f06bc2])
5ce516f6-38cc-4e24-8102-793536912397 10:57:49 PM PDT: debug onLocation(index:01, mac:5CDAD424AC32, ip:C0A80169, port:0050, headers:SFRUUC8xLjEgMjAwIE9LDQpTZXJ2ZXI6IE1hcnZlbGwgODY4OFdNDQpDb25uZWN0aW9uOiBjbG9zZQ0KVHJhbnNmZXItRW5jb2Rpbmc6IGNodW5rZWQNCkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvbg0KQ2FjaGUtQ29udHJvbDogbm8tc3RvcmUsIG5vLWNhY2hlLCBtdXN0LXJldmFsaWRhdGUNCkNhY2hlLUNvbnRyb2w6IHBvc3QtY2hlY2s9MCwgcHJlLWNoZWNrPTANClByYWdtYTogbm8tY2FjaGU=, body:eyJ2ZXJzaW9uIjoxMDB9)
5ce516f6-38cc-4e24-8102-793536912397 10:57:48 PM PDT: debug Executing GET /tstat/version HTTP/1.1
Accept: /
User-Agent: Linux UPnP/1.0 SmartThings
HOST: 192.168.1.105:80
on Home Hub via sendHubCommand

In your device settings, what is your device Network ID set as? I can almost guarantee it is in HEX… You can even see it in the debug ip:C0A80169, port:0050

Nope. It’s easier than you think :smile:

def sendRequest() {
    TRACE("sendRequest()")

	def httpRequest = [
      	method:		settings.httpMethod,
        path: 		settings.httpResource,
        headers:	[
        				HOST:		state.networkAddr,
						Accept: 	"*/*",
                    ]
	]

	def hubAction = new physicalgraph.device.HubAction(httpRequest)
	sendHubCommand(hubAction)
}

where ‘state.networkAdd’ is IP:PORT in dotted notation.

2 Likes

Apples and oranges… The HOST: in the request has to be in IP:PORT notation. But it all responds on the dni. if you don’t provide it in the hubaction it will default to the configured “Device Network Id”

What code are you using. Also, go into devices, click edit on the device, and what is the “Device Network Id”

I’m not passing deviceNetworkId to sendHubAction() like you do, so I don’t need to do any conversion. And like I said, this function is called from the smart app, there is no deviceNetworkId.

But there has to be a device somewhere installed either manually or via the smartApp. It has a “Device Network Id” in Hex notation.

Just go into devices, to your tstat and tell me your DNI. It will not be in 192.168.100.1:80 format.

Sorry, I didn’t make it clear perhaps. There’s no ‘device’, it’s just an app that talks to a thermostat over LAN.

So how are you viewing the Tstat data?

In a smartApp it’s not an issue, because somewhere in your code you are probably subscribing to an event like location, which will parse out responses from the hubaction.

However, devices don’t work that way.

The design map is that a SmartApp should be installed, and on set up it should “Discover” the devices and install devicetypes. During this install process, it will use the DNI from the discovery for the Device Network Id of the device it found.

Unfortunately, this concept doesn’t work for devices that can’t be “found” and there is no easy way to add a device manually in a SmartApp UI.

So that is why I wrote the Generic Camera Device to allow someone to create a camera without using a SmartApp to initiate the discovery process, like the SONOS, Dropcam, WeMo and others do.

Basically, I’m switching thermostat to Away mode when ST mode is Away. I don’t need a device for that.

WOW What a mess. This is seriously screwed up. Feels like the API is seriously flawed and incomplete. Makes one question the entire SmartThings Hub. Add to that the really slow and broken IDE and it has been a pain for the past 2 days to get to this point. Have been using standalone groovy and python for this same problem with less than 15 lines of code.

1 Like

What can I say? I get what you pay for. ST is generous enough to provide practically unrestricted access to their cloud and allows you to run your apps on their servers for free. I challenge you to show me a better deal. :smile:

1 Like

Point is: This is supposed to be an open platform and that requires a solid API. The HubAction inside a Device driver is anything but.

1 Like