SmartThings Labs and LAN Devices

I have looked at that page, and it seems that the LAN device has to use the internet address (https://graph.api.smartthings.com) and cannot communicate over the LAN directly. Is that correct?

From what I’ve seen, yes, you need to use the address you listed rather than a local ip address for callbacks to a SmartApp. I haven’t seen any examples or documentation using a local hub IP address in callback mappings.

Ok, thats unfortunate, but not a deal breaker I guess. Thanks for your input.

LAN callbacks are possible, according to the docs. You have to register your callback as described here:

http://docs.smartthings.com/en/latest/cloud-and-lan-connected-device-types-developers-guide/building-lan-connected-device-types/building-the-device-type.html

I tried following that, but had no luck. Have you gotten this working?

I looked at that LAN callback section and tried it a number of ways with no luck. If it is allowed, there seems to be a missing piece in the docs as to how to do it.

I don’t have a working example yet, but there’s some progress.

So what about proper LAN callback handling, any news?
In current it works for me only if I keep subscribtion to location in Service Manager.
And in locationHandler I have to call correponding Device Type’s parse function.
But this approach looks weird for me.

I am having issues with UPnP Eventing NOTIFYs not being delivered to my Device Type, which I interpret to be the same as your LAN callback. When an external event is sent to ST, I can see via Wireshark that the NOTIFY is sent to ST Hub with the correct SubscriptionID, but my Device Type is never delivered the message. [JFYI - on Android I am using the Cling UPnP toolkit (4thline.org/projects/cling).]

I am interested in the solution (workaround?) that you have identified. I interpret that keeping the subscription to location in service manager means never doing an unsubscribe(), but do not understand what you mean by “in locationHandler I have to call correponding Device Type’s parse function”?

Right, I do not call unsubscribe() anymore.
And in Service Manager’s locationHandler() method I parse the message (in our case it’s JSON format) to know originator’s ID. That ID was provided to device in subscribe command and in my case it’s just DNI (can be UDN for you?). So I can find child and call its method:

else if(type?.contains(“json”)) {
def body = new groovy.json.JsonSlurper().parseText(bodyString)
def child = getChildDevice( body?.id )
if(child) {
log.trace "Message forwarded to $child"
child.parse_json( body )
}

1 Like

@SDmitry Thanks!

While my issue did not turn out to be this, your suggestion to not call unsubscribe() helped to confirm a suspicion about the ST UPnP implementation. It turns out that there must be a case sensitivity in the implementation of Header Fields, as once Cling was modified to use all caps, NOTIFY messages now get delivered to the Device Type.

I am hoping that someone can help with something that is related to the http call and creating a Smart app. What I would like to be able to is trigger a Blue Iris Camera (original thread post, here) to record for several minutes when a door sensor is tripped. I tried to take a look at @emc56 code to see if I could easily modify it to my needs but I can seem to do so because at this point I lack the coding skills. Eric’s code seems to use a motion sensor as a trigger and I would like to use a door sensor as the trigger. And then there is of course the modification to use the correct http. Thanks in advance.

You can forget using blue iris in a device type. It requires being able to chain a few local http calls in a synchronous fashion. The only current local http call implementation is that BS async crap that sends everything to parse() with no idea which response goes with which request.

I’ve been struggling with this for days and here is what I got so far : A code that react to the presence but a systematic error message after httpget or sendhttp() comands are sent. Last error message was a timeout while the url works fine from any browser of course.

here is the code I’ve been working with so far :


/**
 *  
 */
definition(
    name: "Presence videosurveillance status",
    namespace: "smartthings",
    author: "elfege",
    description: "Presence Changes video surveillance status",
    category: "Safety & Security",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Meta/text_presence.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Meta/text_presence@2x.png"
)

preferences {
	section("When a presence sensor arrives or departs this location..") {
		input "presence", "capability.presenceSensor", title: "Which sensor?"
	}
}

def installed() {
	subscribe(presence, "presence", presenceHandler)
}

def updated() {
	unsubscribe()
	subscribe(presence, "presence", presenceHandler)
}
    


def presenceHandler(evt) {


def params1 = [            
    uri: "http://192.168.10.110:8000/alloff",
             
]

def params2 = [            
    uri: "http://192.168.10.110:8000/allon",
        
]

if (evt.value == "present") {
		log.debug "${presence.label ?: presence.name} has arrived at the ${location}"
    	sendPush("${presence.label ?: presence.name} has arrived at the ${location}")
            
    try { 
    sendhttp(params1) { resp ->
        resp.headers.each {
           log.debug "${it.name} : ${it.value}"
        }
        log.debug "response contentType: ${resp.contentType}"
        log.debug "response data: ${resp.data}"
    }
   }

catch (e) {
    log.error "something went wrong: $e"
   }

  }
else if (evt.value == "not present") {
		log.debug "${presence.label ?: presence.name} has left the ${location}"
    	sendPush("${presence.label ?: presence.name} has left the ${location}")
    try {  
       httpGet(params2) { resp ->
        resp.headers.each {
           log.debug "${it.name} : ${it.value}"
        }
        log.debug "response contentType: ${resp.contentType}"
        log.debug "response data: ${resp.data}"
    }
} catch (e) {
    log.error "something went wrong: $e"
}

}
}

httpGet can only be called to public ip’s you need to use local hubaction to do what you want to do. The Hue connect or Sonos connect are ok examples of how this can work.

Thank you for answering so fast ! Well, public ip address, even though I do have a static IP, I can’t do it because ispy doesn’t seem to allow its use. What do you mean by local hubaction (I’m not a developper, only an amateur who’s very stubborn and dedicated ! Hope it’s ok. ) I get that local hubaction means that I have to program a request throuhg the hub directly, but I have no idea where to start to achieve that… :smirk:

Docs are very helpful. Just search for hubaction.

http://docs.smartthings.com/en/latest/cloud-and-lan-connected-device-types-developers-guide/building-lan-connected-device-types/building-the-device-type.html?highlight=hubaction

[quote=“pstuart, post:53, topic:1100, full:true”]
Docs are very helpful. Just search for hubaction.[/quote]
The docs for HubAction are anything but helpful. Very incomplete and somewhat inaccurate. Need I point you at your own posts from this past summer? :sunglasses:

Not sure what you want here? The docs explain how to do it. The real issue is the local hubaction isn’t very robust or reliable. However, if you search there are many discussions on how to do it in many different actions.

And trust me, the docs are extremely helpful and ever expanding. Far better then a year ago. Combine the docs and a github search and there are tons of examples even outside of this community as well.

Not sure if you’ve found anything, but here is a simple example:

hubAction = new physicalgraph.device.HubAction([ method: "POST", path: SOME_ENDPOINT_ON_YOUR_SERVER (eg. "/hubaction"), headers: [ HOST: settings.ip + ":" + settings.port, "Content-Type": "application/json" ], body: SOME_JSON_STRING ])

settings.ip and settings.port reference your web server. I don’t have the mDNS stuff working to auto-detect it, so it’s a manual entry for now :wink: