How To Send an Event to a Zwave Device Type?


(Paul) #1

I am using sendEvent(device, map) to send an event to a device.

The parse() method is called with an argument of type Map. This causes a Groovy runtime error.

I defined another parse() method which takes a map as an argument.

Is this the right approach?


(Paul) #2

A bonus question. If multiple devices subscribe to the same event / event handler, how do I know which device (type Device) caused the event handler to be called?


(Andrew Mager) #3

@psfunatyo Paul, can you send us the code you’re using?

@wackware @pstuart @tgauchat @rappleg Any ideas?


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #5

So at the risk of just exposing my confusion, what Paul is saying doesn’t make sense to me.

http://docs.smartthings.com/en/latest/device-type-developers-guide/parse.html

  • parse() takes a String as argument, NOT a Map.
  • parse() is not an arbitrary method name … it is a standard and required (?) method for Device Handlers, except for Cloud-Connected Device Types. It doesn’t make sense to overload “parse(String)” with an additional signature, such as “parse(Map)

or is Paul referring to a Cloud-Connected Device (which uses a different method parseEventData(Map) in the documented example):

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

Next…:

  • Devices don’t subscribe to Events, only SmartApps, according to my interpretation of the Documentation for SmartDevice Type and Device. Neither of these mentions a subscribe() method.

https://graph.api.smartthings.com/ide/doc/deviceType
https://graph.api.smartthings.com/ide/doc/device

So…

  • This question doesn’t make sense to me, because devices do not “subscribe to events”; instead, SmartApps do. And the subscription for device events is either to a specific device’s events, or the event data is returned by the subscription as an Object of type Event, which contains the ID of the Device Instance or other generator of that Event (very specifically, because Event includes the Hub and Location ID too).

https://graph.api.smartthings.com/ide/doc/event

The use of Event as the parameter to the Handler Method of subscribe() is discussed here:
http://docs.smartthings.com/en/latest/smartapp-developers-guide/simple-event-handler-smartapps.html


So if we see Paul’s code, that would clarify if he’s talking about stuff directly within or between Devices, or SmartApps … ?

Or am I missing a piece of the puzzle that you can explain to me? :confused:

Thanks!


(Paul) #6

Here is the caveat: I haven’t looked at this since November of last year and I believe a lot of the documentation has been improved since.

In SmartThings, a motion sensor generates two event types: “active” and “inactive”. However, the Philio (Zipato) motion sensor only generates a single event “motion detected”. In Z-Wave terms, it generates a “command: 3003, payload: FF 0C”, but never a “command: 3003, payload: 00 0C”.

I have a helper app which subscribes to the events of motion sersor device handler.

    // Smart App    
    def initialize() {
            subscribe(motion1, "motion.active", motionActiveHandler)
    }
        
    def motionActiveHandler(evt) {
            def dev = settings.motion1.find() { it.id == evt.deviceId }
            if (dev) {
        		sendEvent(dev, [name: "motion", value: "inactive"])
        	}
    }

The helper app sends an inactive event to the device handler. The device handler has an overloaded parse(map) defined.

    // Device Handler
   def parse(Map evt) {
        def result = [];
        if (evt)
        	result << evt;
        return result
    }

Do I like it? Not really. But I wasn’t able to figure out how to get it working in any other way.


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #7

Thanks for the followup, Paul – It looks like you found a creative workaround to a sticky situation. Such things are something inelegant but if it works … it works, right?

There’s always a possibility that fresh eyes might come up with an alternative way to handle this.
and/or
Your solution may be helpful in similar situations!!!

If you would like to share the entire code (SmartApp and Device Handler) with paste or a Github link … then see what feedback arises. I’m not sure how much I can do without the actual device to test with … though I suppose the Simulator can be configured to send a representation of the single Motion Detected Event as if from the physical device…

BTW: That seems like unusually sloppy behavior for a motion sensor, right? Did you come up with any explanation? I suppose that typical motion sensors send “inactive” after a certain timeout period, and that triggers the “inactive” event message; whereas Philio must still have this concept of timeout – since it needs to decide whether or not to send the next “active” event message; it’s just too lazy to send the “inactive” in between. Is my understanding correct?

So I’m wildly speculating whether or not this concept of timeout could be included in the Device Handler without a helper SmartApp. If you can’t call the parse() method directly, wouldn’t it be sufficient to call sendEvent() from within the Device Handler after some “pause” amount? Yet the Device Handler exits after the platform calls parse() for the “active” message… we’d have to inhibit that or spawn another process… Can a DeviceHandler call “runIn()”? Is there an execution time limit like for SmartApps?


(Paul) #8

I really dislike the idea of having to run a helper app to solve this problem. It is not efficient and you have to manage an additional SmartApp.

I tried to create both the “active” and “inactive” events in the device handler, but at times those events would be handled out of order and I couldn’t figure out how to create a delay.

I am not sure whether to call it “sloppy”; maybe a different philosophy. The manual explicitly specifies this behavior and considering that the motion sensor can be configured for different modes with different behaviors there must have put quite some thought in the design.


(ActionTiles.com co-founder Terry @ActionTiles; GitHub: @cosmicpuppy) #9

I’m not sure I’m as concerned about the use of the helper SmartApp in the solution. It is almost intuitive: Most Motion Sensors report a “inactive” sometime after reporting “active”. In the case of the Zipato, there is no “inactive” message, so you need something to send this message. Devices can’t directly interact with other Devices (unless they are Child Devices of the same Parent (?) – and that would involve a Service-Manager SmartApp; i.e., a helper SmartApp; anyway… so essentially the same solution components, just even more complicated.

At first I thought this must be like a Capability “Momentary”; since a Momentary doesn’t have any Attributes; it just fires a State change (?!). That would be like firing the “active” Motion detected event. The Virtual sample code for Momentary, though, makes it a Switch as well, and just does an immediate reset with no time delay; the Z-Wave sample, though, expects an “on” and “off” message from the Device like a Switch (i.e., while it is not “pushed = on, unpushed = off”; but rather “pushed = on and then immediately off” … there are two distinct messages from the device).


So if avoiding the use of a helper SmartApp is desired, the challenge is figuring out what sort of synchronous sequencing and any delays are necessary and possible within a single Device Handler. The “out of order” stuff you encountered is not unexpected and unless someone has already solved it, it would take some creative experimentation and/or expert help to solve.

This is a good one for @Mager to think about and increase his expertise! :wink:


(Patrick Stuart [@pstuart]) #10

Why not just set a timer on the devicetype to reset the motion back to inactive? Why the need for a “helper” app at all?