Multiple Motions/Switches from one device


(J Foshee) #1

Ok I’m using a Arduino board to create a device. The device has multiple motions and switches off it.

        tiles {
                standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "on", label: '${name}', action: "switch.off", icon: "st.presence.house.secured", backgroundColor: "#79b821"
                        state "off", label: '${name}', action: "switch.on", icon: "st.presence.house.unlocked", backgroundColor: "#ffffff"
                }
                standardTile("Front.Door", "device.contact", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "open", label: 'Front Door', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
                        state "closed", label: 'Front Door', icon: "st.contact.contact.closed", backgroundColor: "#79b821"
                }
                standardTile("Garage.Door", "device.contact", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "open", label: 'Garage Door', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
                        state "closed", label: 'Garage Door', icon: "st.contact.contact.closed", backgroundColor: "#79b821"
                }
                standardTile("Back.Door", "device.contact", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "open", label: 'Back Door', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
                        state "closed", label: 'Back Door', icon: "st.contact.contact.closed", backgroundColor: "#79b821"
                }
                standardTile("Living.Motion", "device.motion", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "active", label: 'Living Motion', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
                        state "inactive", label: 'Living Motion', icon: "st.motion.motion.inactive", backgroundColor: "#79b821"
                }
                standardTile("Kitchen.Motion", "device.motion", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "active", label: 'Kitchen Motion', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
                        state "inactive", label: 'Kitchen Motion', icon: "st.motion.motion.inactive", backgroundColor: "#79b821"
                }
                 standardTile("Hall.Motion", "device.motion", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "active", label: 'Hall Motion', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
                        state "inactive", label: 'Hall Motion', icon: "st.motion.motion.inactive", backgroundColor: "#79b821"
                }
                standardTile("Computer.Motion", "device.motion", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "active", label: 'Computer Motion', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
                        state "inactive", label: 'Computer Motion', icon: "st.motion.motion.inactive", backgroundColor: "#79b821"
                }
                standardTile("alarm", "device.alarm", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "off", label:'off', action:'alarm.both', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff"
                        state "strobe", label:'strobe!', action:'clear', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
                        state "siren", label:'siren!', action:'clear', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
                        state "both", label:'alarm!', action:'clear', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
                }
                main(["switch","Front.Door","Garage.Door","Back.Door","Living.Motion","Kitchen.Motion","Hall.Motion","Computer.Motion","alarm"])
                details(["switch","Front.Door","Garage.Door","Back.Door","Living.Motion","Kitchen.Motion","Hall.Motion","Computer.Motion","alarm"])
        }

They all show up under the device find and change state when triggered.

The problem I run into is that when I try to create a app to use one of these motions:

preferences {
	section("When there's movement...") {
		input "motion1", "capability.motionSensor", title: "Where?", multiple: true
	}

Is that the only motion sensor that shows up is the main device and not all the motions that are under the single device.

How do you deal with multiple motion/switches or any multiple items under a device and trigger off those and not the main device?


(J Foshee) #2

After thinking about it over night the only thing I could come up with is making separate devices each with a motion or switch on it. Then using the arduino device to change the state of each of those devices. My question is how would you within a device type change the state of another device.

So the question is there a way to change the state of another device inside the device type of another device?


(Todd Wackford) #3

You write an app to do that. Subscribe to events of 1 to many devices and send commands based on the events or states.


(J Foshee) #4

We are back in the same boat then. I have multiple motions under one device. How do you access the multiple motions under one device in a app? What I was talking about was change other devices under one device type.


(Todd Wackford) #5

maybe descibing the end use case would help.


(Col Hack) #6

@jfoshee, Looks like what you need is a mux/demux app, i.e. on one side of the fence you have multiple physical devices connected to your shield (switches, motion sensors, etc.), each with a unique ID. On the other side of the fence (i.e. the mobile app) you create a “virtual device” for each physical device. Then, in your app you map physical devices (by their IDs) to virtual ones (e.g. by their name), so your app could rout commands and events to appropriate devices. The SmartSheild device in this case is used only for communicating with the mux/demux app, rather than representing actual devices.


(J Foshee) #7

@kernelhack Correct that is exactly what I am looking to do but the question comes how do you reference all those motions “physical devices” as they are not devices. They are just a tile under the main device so they don’t have a global ID to call link in the “mux/demux” app.


(Col Hack) #8

That’s easy. The ThingShield just sends and receives ascii strings. You define your own message format that’s easy to parse in your demux app and when you receive these events from the Shield device you just split them into address/action parts. For example, you have 2 digital inputs: D1 and D2. Define your events as “D1.open”, D1.closed", “D2.open”, “D2.closed”. When your app receives for example “D1.closed”, it will know both “who” (D1) and “what” (closed). Now, it can map address to a virtual “Contact Sensor” device and call its parse() method with “closed” as an argument. Your virtual device than will parse “closed” or “open” and create appropriate event.


(J Foshee) #9

This is my thingshield device today. So would I tie in the virtual device in this or in a smartthings app?

/**
 *  Alarm
 *
 *  Author: Josh Foshee
 *  Date: 2014-01-17
 */

metadata {
        // Simulator metadata
        simulator {

        }

        // UI tile definitions
        tiles {
                standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "on", label: '${name}', action: "switch.off", icon: "st.presence.house.secured", backgroundColor: "#79b821"
                        state "off", label: '${name}', action: "switch.on", icon: "st.presence.house.unlocked", backgroundColor: "#ffffff"
                }
                standardTile("Front.Door", "device.contact", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "open", label: 'Front Door', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
                        state "closed", label: 'Front Door', icon: "st.contact.contact.closed", backgroundColor: "#79b821"
                }
                standardTile("Garage.Door", "device.contact", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "open", label: 'Garage Door', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
                        state "closed", label: 'Garage Door', icon: "st.contact.contact.closed", backgroundColor: "#79b821"
                }
                standardTile("Back.Door", "device.contact", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "open", label: 'Back Door', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
                        state "closed", label: 'Back Door', icon: "st.contact.contact.closed", backgroundColor: "#79b821"
                }
                standardTile("Living.Motion", "device.motion", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "active", label: 'Living Motion', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
                        state "inactive", label: 'Living Motion', icon: "st.motion.motion.inactive", backgroundColor: "#79b821"
                }
                standardTile("Kitchen.Motion", "device.motion", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "active", label: 'Kitchen Motion', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
                        state "inactive", label: 'Kitchen Motion', icon: "st.motion.motion.inactive", backgroundColor: "#79b821"
                }
                 standardTile("Hall.Motion", "device.motion", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "active", label: 'Hall Motion', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
                        state "inactive", label: 'Hall Motion', icon: "st.motion.motion.inactive", backgroundColor: "#79b821"
                }
                standardTile("Computer.Motion", "device.motion", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "active", label: 'Computer Motion', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
                        state "inactive", label: 'Computer Motion', icon: "st.motion.motion.inactive", backgroundColor: "#79b821"
                }
                standardTile("alarm", "device.alarm", width: 1, height: 1, canChangeIcon: true, canChangeBackground: true) {
                        state "off", label:'off', action:'alarm.both', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff"
                        state "strobe", label:'strobe!', action:'clear', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
                        state "siren", label:'siren!', action:'clear', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
                        state "both", label:'alarm!', action:'clear', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
                }
                main(["switch","Front.Door","Garage.Door","Back.Door","Living.Motion","Kitchen.Motion","Hall.Motion","Computer.Motion","alarm"])
                details(["switch","Front.Door","Garage.Door","Back.Door","Living.Motion","Kitchen.Motion","Hall.Motion","Computer.Motion","alarm"])
        }
}

// Parse incoming device messages to generate events
def parse(String description) {
        def msg = zigbee.parse(description)?.text
    def result
    if ( msg.length() >= 4 ) {
        // Process arm update
        if ( msg.substring(0, 2) == "AR" ) {
            result = createEvent(name: "switch", value: msg[3] == "1" ? "on":"off")
        // Process alarm update
        } else if ( msg.substring(0, 2) == "AL" ) {
            result = createEvent(name: "alarm", value: msg[3] == "1" ? "both":"off")
        // Process zone update
        } else if ( msg.substring(0, 2) == "ZN" ) {
            if ( msg.substring(3, 9) == "609001" ){
            def state = "active"
            result = createEvent(name: "Hall.Motion", value: state)
            }
            else if ( msg.substring(3, 9) == "610001" ){
            def state = "inactive"
            result = createEvent(name: "Hall.Motion", value: state)
            }
            else if ( msg.substring(3, 9) == "609002" ){
            def state = "open"
            result = createEvent(name: "Back.Door", value: state)
            }
            else if ( msg.substring(3, 9) == "610002" ){
            def state = "closed"
            result = createEvent(name: "Back.Door", value: state)
            }
            else if ( msg.substring(3, 9) == "609003" ){
            def state = "open"
            result = createEvent(name: "Garage.Door", value: state)
            }
            else if ( msg.substring(3, 9) == "610003" ){
            def state = "closed"
            result = createEvent(name: "Garage.Door", value: state)
            }
            else if ( msg.substring(3, 9) == "609004" ){
            def state = "open"
            result = createEvent(name: "Front.Door", value: state)
            }
            else if ( msg.substring(3, 9) == "610004" ){
            def state = "closed"
            result = createEvent(name: "Front.Door", value: state)
            }
            else if ( msg.substring(3, 9) == "609005" ){
            def state = "active"
            result = createEvent(name: "Kitchen.Motion", value: state)
            }
            else if ( msg.substring(3, 9) == "610005" ){
            def state = "inactive"
            result = createEvent(name: "Kitchen.Motion", value: state)
            }
            else if ( msg.substring(3, 9) == "609006" ){
            def state = "active"
            result = createEvent(name: "Living.Motion", value: state)
            }
            else if ( msg.substring(3, 9) == "610006" ){
            def state = "inactive"
            result = createEvent(name: "Living.Motion", value: state)
            }
            else if ( msg.substring(3, 9) == "609007" ){
            def state = "active"
            result = createEvent(name: "Computer.Motion", value: state)
            }
            else if ( msg.substring(3, 9) == "610007" ){
            def state = "inactive"
            result = createEvent(name: "Computer.Motion", value: state)
            }
          }
    }
        return result
}

// Commands sent to the device
def on() {
        zigbee.smartShield(text: "arm").format()
}

def off() {
        zigbee.smartShield(text: "disarm").format()
}

def strobe() {
        panic()
}

def siren() {
        panic()
} 

def both() {
        panic()
}

def panic() {
        zigbee.smartShield(text: "panic").format()
}

// TODO: Need to send off, on, off with a few secs in between to stop and clear the alarm
def clear() {
        off()
}

(Brice; SmartRulesApp.com) #10

Does this code actually work for you? I have some extremely similar code, and I can’t get the status of individual sensors to change using events like those you have under the “609*” and “610*” cases. The only way I can get them to change state is if I use “result = createEvent(name: “contact”, value: state)” which changes that state of all of the contact sensors.


(Brice; SmartRulesApp.com) #11

In response to my last comment, I found that I needed to change the device types for example from “device.motion” to “device.HallMotion”, then use “result = createEvent(name: “HallMotion”, value: state)”. Once they are all changed like this, I can control all tiles individually.

The problem I am running into now is getting the device to communicate directly with the IT-100. When I connect the RS-232 shield to my computer and pretend to be the IT-100, everything works fine; and when I connect my computer to the IT-100, everything works fine, but when I try to connect the IT-100 to the RS-232 shield, there is no communication. Any idea what could be going wrong?


(j w) #12

I’m guessing you probably figured out by now that they are both probably using the same pins, D0 and D1. The Smartshield has a switch to go between D0 and D1 or D2 and D3. However, when I tried D2 and D3, nothing was sent. It has to be an issue with my Smartshield, because I ended up manually routing the signal from D0 and D1 on my Smartshield to D2 and D3 on my duino, which worked great.


(Brice; SmartRulesApp.com) #13

Thanks for the info. You’re right, I did have this figured out. My problem was with the serial cable that I was using. I needed to buy a null modem adapter, then it worked fine.


(Stan) #14

I had the same challenge virtualizing my relays for my sprinkler system. @badgermanus posted a solution on github where he created a virtual device type and a parent app to tie them together. You can find his code at https://github.com/jwsf/device-type.arduino-8-way-relay Look for the two virtual apps at the bottom of the repository listing