Use addChildDevice with manual IP entry


(Brice; SmartRulesApp.com) #1

I’m trying to create a SmartApp to act as a “Service Manager” for a LAN device. The device does not support SSDP, so I want to just allow the user to manually enter the IP:port for the device, then add the device using addChildDevice. Unfortunately, this doesn’t seem to work, but I could just be passing bad arguments to addChildDevice. I can’t find documentation on it anywhere. Below is a snippet of my code which will currently get this error:

groovy.lang.MissingMethodException: No signature of method: physicalgraph.device.HubService.get() is applicable for argument types: (physicalgraph.app.HubWrapper) values: [physicalgraph.app.HubWrapper@17d2a4b6]
Possible solutions: get(java.lang.String), grep(), getAt(java.lang.String), grep(java.lang.Object), wait(), any() @ line 57

Please let me know if you see anything wrong. Thanks!

definition(
    name: "MacThing Setup",
    namespace: "com.obycode",
    author: "ObyCode",
    description: "Use this app to connect your device to SmartThings",
    category: "Fun & Social",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")


preferences {
	section("Setup my device with this IP:port (click the icon in the status bar to find this):") {
		input "theAddr", "string", multiple: false, required: true
	}
    section("on this hub...") {
    	input "theHub", "hub", multiple: false, required: true
	}
	section("and give it this name...") {
		input "theName", "string", multiple: false, required: true
	}
}

def installed() {
	log.debug "Installed with settings: ${settings}"

	initialize()
}

def updated() {
	log.debug "Updated with settings: ${settings}"

	unsubscribe()
	initialize()
}

def initialize() {
	log.debug "name is $theName, addr is $theAddr, hub is $theHub"
    def parts = theAddr.split(":")
	def iphex = convertIPtoHex(parts[0])
	def porthex = convertPortToHex(parts[1])
    def dni = "$iphex:$porthex"
	d = addChildDevice("com.obycode", "myDevice", dni, theHub, [label:"$theName", name:"$theName", completedSetup: true])
	log.trace "created ${d.displayName} with id $dni"
}

private String convertIPtoHex(ipAddress) { 
    String hex = ipAddress.tokenize( '.' ).collect {  String.format( '%02x', it.toInteger() ) }.join()
    log.debug "IP address entered is $ipAddress and the converted hex code is $hex"
    return hex

}

private String convertPortToHex(port) {
	String hexport = port.toString().format( '%04x', port.toInteger() )
    log.debug hexport
    return hexport
}

(Brice; SmartRulesApp.com) #2

I’ve been looking this over and its clear that all I really need is to know how to get the correct “hub” argument from “theHub” to pass into addChildDevice. If I replace that argument with “null”, then I can successfully add the device, but it cannot communicate since the hub is null. “theHub” is of type “physicalgraph.app.HubWrapper” Can anyone please help me discover how to get this other hub type from this type that I have? Thanks!


(Geko) #3

All examples I’ve seen seem to have the hub argument set to null.


(Patrick Stuart [@pstuart]) #4

Look at the sonos connect smartapp…

Looks like you can get existing child devices and get the .value.hub of that child device, but I can’t seem to find a way documented to get the hubId although that is a variable in it…

When I get home I’ll do some digging to see what I can find… But you solved the issue of why my discovery app wasn’t working :slight_smile: no hub to respond to :smile:


(Brice; SmartRulesApp.com) #5

If I set the hub to null, then when I try to send a message over the LAN, it can;t communicate because it needs the hub to do that :frowning:.


(Brice; SmartRulesApp.com) #6

Yes, I saw that, but in that case, the device was discovered using SSDP, which my device doesn’t support. I want to just manually enter the IP:port and select the hub. Glad I helped solve your issue!


I give up - why don't I get a response back from my LAN connected device?
(Geko) #7

Here’s how to get a List of hubs:

def myHubs = location.hubs

(Patrick Stuart [@pstuart]) #8

Here’s how you can get a list of the hub names, no idea if it will actually work instead of null but give it a shot…

def hubNames = location.hubs*.name.findAll { it }


(fxstein) #9

Following along as I have the very same issue with the ISY. I have its address and it has a very simple API, just can’t get the very basics of the device manger to work.


(fxstein) #10

Here is what I get if I use addChildDevice:

def initialize() {
log.debug "name is $isyName, addr is $isyAddr, hub is $theHub"
    def dni = convertAddrToHex(isyAddr)

def isy = getChildDevice(dni)
if(!isy) {
	isy = addChildDevice("fxstein", "Switch", dni, theHub, [name:"$isyName", label:name, completedSetup: true])
	isy.take()
	log.debug "created ${isy.displayName} with id $dni"
} else {
	log.debug "Device already created"
}

log.trace "Device in use ${isy.displayName} with id $dni"
}

I keep getting the error that the DeviceType is unknown inside of my namespace. Does that mean I first have to create a custom device type for it?

9:21:25 AM PDT: error physicalgraph.app.exception.UnknownDeviceTypeException: Device type 'Switch' in namespace 'fxstein' not found. @ line 47
9:21:25 AM PDT: debug Device address entered is 10.0.1.199:80 and the converted hexAddr code is 0a0001c7:0050

(Brice; SmartRulesApp.com) #11

Yes, you need to have a device type created with the namespace and name matching what you use here.


(Brice; SmartRulesApp.com) #12

Thanks for the input. This works, but it gives me the same “physicalgraph.app.HubWrapper” type as I have with “theHub”. I’m not sure what field of this type needs to be passed to “addChildType”. If I just pass one of those, then I get the error mentioned in my original post.


(Patrick Stuart [@pstuart]) #13

This will give you the hub names…

Or just create an input to choose a hub with these:

input "hub", "hub", title: "Select Hub"


(Brice; SmartRulesApp.com) #14

Thanks Patrick. I understand that, that is what I’m doing. But I just don’t know what to do with that once I have it. If I pass that in to “addChildDevice”, I get the error. I’m wondering if there is some field of that type that I need to pass, but there is no documentation about it.


(Patrick Stuart [@pstuart]) #15

Try converting it to a string. Or post code so I can see what is different from what I have


(Brice; SmartRulesApp.com) #16

The code is at the top of this page. If I try to pass “theHub.name” instead, then I get a “You are not authorized to perform the operation” error. Is the name the correct argument, and I’m just missing some permissions to add a device? Error from log is shown below:

org.springframework.security.access.AccessDeniedException: Access is denied @ line 58


(Patrick Stuart [@pstuart]) #17

So have you tried the code

def hubNames = location.hubs*.name.findAll { it }

and return hubNames[0] for the first in the list?


(fxstein) #18

Ok - makes sense. Thank you. Need to study the NEST and Sonos Connectors a bit more.

I basically need to create a device for the ISY994 to talk to and then child devices for switches, dimmers and scenes. - Still very early days for me around here.


(Brice; SmartRulesApp.com) #19

Using “hubNames[0]” (or hubNames[1]) still gets me the permissions error. Is this working for you?


(Patrick Stuart [@pstuart]) #20

What you have here is a bug…

The GUID for the hub is what this command is looking for. The GUID isn’t available in the IDE, if you force it to the GUID of the Hub, it works.

I’d open a support ticket with ST and see if they can get this fixed. There should be a method to get the GUID of the Hub, but I can’t find one.

You can certainly get it after the fact, but this goes to exactly the problem with the whole SmartApp spawning custom device types… Really an afterthought…

DeviceTypes should be allowed without discovery through a SmartApp.