Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Device Network ID collision with another DTH #199

Open
jezzaaa opened this issue Mar 4, 2019 · 5 comments
Open

Device Network ID collision with another DTH #199

jezzaaa opened this issue Mar 4, 2019 · 5 comments

Comments

@jezzaaa
Copy link

jezzaaa commented Mar 4, 2019

I struggled for days to find out why nothing was coming out of my SmartThings hub into the Bridge. Finally I noticed an error in the live logging that referred to a Device Network ID (DNID), hinting that it wasn't unique.

Turns out both cast-web-api and smartthings-mqtt-bridge both use the MAC address of where they run, as the DNID. As I had installed cast-web-api first, I suppose it got all the messages destined for smartthings-mqtt-bridge.

I hacked the DTH to prefix the MAC with "MQTT", to make it more likely to be unique. Immediately, I started getting MQTT messages through.

Now I just have to work out why I can't get any traffic going the other way...

@jmbinette
Copy link

jmbinette commented Jul 31, 2019

@jezzaaa Di you find a way to solve this ?

I have exactly the same problem and running both in Docker

@jezzaaa
Copy link
Author

jezzaaa commented Jul 31, 2019

Yes, I hacked the DTH code to prefix the MAC with "MQTT", to make it more likely to be unique.

But I gave up on trying to use MQTT.

@jmbinette
Copy link

jmbinette commented Jul 31, 2019

MQTT working for me, let me know if I can help

Could you point me the exact places you had to modify DTH?

I thought it was the way ST hub was communicating, not related to code :
"Yes, the SmartThings local incoming calls work by whitelisting by MAC address. And outgoing calls work by IP"

@jezzaaa
Copy link
Author

jezzaaa commented Aug 1, 2019

I can do most of what I want without MQTT, so there isn't an urgent need. But it'd be nice - when I get a bit of time.

My diff looks like the below:

<     // Setting Network Device Id
<     def hex = "$settings.mac".toUpperCase().replaceAll(':', '')
<     if (device.deviceNetworkId != "$hex") {
<         device.deviceNetworkId = "$hex"
<         log.debug "Device Network Id set to ${device.deviceNetworkId}"
---
>     def hex = ""
>     if (device.deviceNetworkId == NULL || device.deviceNetworkId == "") {
>         // Setting Network Device Id
>         //hex = "MQTT"+$settings.mac.toUpperCase().replaceAll(':', '')
>         hex = ipToHex(settings.ip+":"+settings.port)
>         log.debug "debug:"+hex
>         if (device.deviceNetworkId != "$hex") {
>             device.deviceNetworkId = "$hex"
>             log.debug "Device Network Id set to $hex -> ${device.deviceNetworkId}"
>         }

I originally just prefixed the right-hand-side of the assignment to hex with the string "MQTT". This is now commented out and replaced - not because it didn't work but because it didn't make sense to me to use the MAC address at all.

The MAC address is unique to the device, but not to the services running on the device. Instead, it makes sense to use something that's unique to the service (and doesn't have to be unique to the site because it will always operate in the local network).

So the new code gets the IP address and port number of the listening socket, converts them to hex and joints them together with a colon. In this way, a different service listening on a different port will have a different device ID even when it's running on the same device (thus same MAC).

The call to ipToHex() refers to a function I added, but didn't include in the above diff, for clarity. It looks like this:

// accepts a IP:PORT string and converts it to a hex identifier
// for setting the SmartThings deviceNetworkId
// NOTE: does not handle octet less than 0x10 = 16!
private String ipToHex(String ip) {
  def parts   = ip.tokenize(':')
  def address = parts[0]
  def port            = parts[1]
  def octets  = address.tokenize('.')
  def hex             = ""

  log.debug "converting ipToHex"
  octets.each {
    hex = hex + Integer.toHexString(it as Integer).toUpperCase()
  }
  hex = hex + ":" + Integer.toHexString(port as Integer).toUpperCase().padLeft(4,'0')
  return hex
}

@jmbinette
Copy link

Great ! Thank you I will def try that !

@stjohnjohnson could we integrate this kind of mod ? I think it would help many people

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants