Looking for some ideas. I have the below in place and can see each individual motion sensor triggering when activated. The issue is that I can’t view the motion sensors outside of the Arduino/ST_Anything. I’m thinking this is done with multiplexing and virtual sensors but I’m not certain where to start. I have looked but don’t quite understand how it’s done.
//******************************************************************************************
// File: ST_Anything_WiFiEsp.ino
// Authors: Dan G Ogorchock & Daniel J Ogorchock (Father and Son)
//
// Summary: This Arduino Sketch, along with the ST_Anything library and the revised SmartThings
// library, demonstrates the ability of one Arduino + ESP-01 board to
// implement a multi input/output custom device for integration into SmartThings.
// The ST_Anything library takes care of all of the work to schedule device updates
// as well as all communications with the ESP-01 board.
//
// This example requires the use of an Arduino MEGA2560 since the ESP-01 WiFi board
// needs a high-speed UART for communications. This example assumes the ESP-01 is
// connected to the MEGA’s “Serial1” UART on pins 18 & 19.
//
//
// Change History:
//
// Date Who What
// ---- — ----
// 2015-01-03 Dan & Daniel Original Creation
// 2017-02-12 Dan Ogorchock Revised to use the new SMartThings v2.0 library
// 2017-02-20 Dan Ogorchock Revised to use the ESP-01 board
//
//******************************************************************************************
//******************************************************************************************
// SmartThings Library for Arduino + ESP-01 board combination.
//******************************************************************************************
#include <SmartThingsWiFiEsp.h> //Library to provide API to the SmartThings ESP-01 WiFi board
//******************************************************************************************
// ST_Anything Library
//******************************************************************************************
#include <Constants.h> //Constants.h is designed to be modified by the end user to adjust behavior of the ST_Anything library
#include <Device.h> //Generic Device Class, inherited by Sensor and Executor classes
#include <Sensor.h> //Generic Sensor Class, typically provides data to ST Cloud (e.g. Temperature, Motion, etc…)
#include <Executor.h> //Generic Executor Class, typically receives data from ST Cloud (e.g. Switch)
#include <InterruptSensor.h> //Generic Interrupt “Sensor” Class, waits for change of state on digital input
#include <PollingSensor.h> //Generic Polling “Sensor” Class, polls Arduino pins periodically
#include <Everything.h> //Master Brain of ST_Anything library that ties everything together and performs ST Shield communications
#include <PS_Illuminance.h> //Implements a Polling Sensor (PS) to measure light levels via a photo resistor
#include <PS_TemperatureHumidity.h> //Implements a Polling Sensor (PS) to measure Temperature and Humidity via DHT library
#include <PS_Water.h> //Implements a Polling Sensor (PS) to measure presence of water (i.e. leak detector)
#include <IS_Motion.h> //Implements an Interrupt Sensor (IS) to detect motion via a PIR sensor
#include <IS_Contact.h> //Implements an Interrupt Sensor (IS) to monitor the status of a digital input pin
#include <IS_Button.h> //Implements an Interrupt Sensor (IS) to monitor the status of a digital input pin for button presses
#include <EX_Switch.h> //Implements an Executor (EX) via a digital output to a relay
#include <EX_Alarm.h> //Implements Executor (EX)as an Alarm Siren capability via a digital output to a relay
//**********************************************************************************************************
//Define which Arduino Pins will be used for each device
// Notes: Arduino communicates with the ESP-01 using the “Serial1” Hardware Serial UART.
// This is on digital pins 18 & 19 on the Mega.
//**********************************************************************************************************
//“RESERVED” pins for ESP-01 - best to avoid
#define PIN_18_RESERVED 18 //reserved ESP-01 on MEGA
#define PIN_19_RESERVED 19 //reserved ESP-01 on MEGA
#define PIN_WATER A4
#define PIN_ILLUMINANCE A5
#define PIN_TEMPERATUREHUMIDITY 5
#define PIN_MOTION0 6
#define PIN_MOTION1 2
#define PIN_MOTION2 3
#define PIN_MOTION3 4
#define PIN_CONTACT 7
#define PIN_SWITCH 8
#define PIN_ALARM 9
#define PIN_BUTTON1 10
#define PIN_BUTTON2 11
//******************************************************************************************
//WiFiEsp Information
//******************************************************************************************
String str_ssid = // <—You must edit this line!
String str_password = "; // <—You must edit this line!
IPAddress ip(; // Device IP Address // <—You must edit this line!
const unsigned int serverPort = 8090; // port to run the http server on
// Smartthings hub information
IPAddress hubIp( // smartthings hub ip // <—You must edit this line!
const unsigned int hubPort = 39500; // smartthings hub port
//******************************************************************************************
//st::Everything::callOnMsgSend() optional callback routine. This is a sniffer to monitor
// data being sent to ST. This allows a user to act on data changes locally within the
// Arduino sktech.
//******************************************************************************************
void callback(const String &msg)
{
Serial.print(F("ST_Anything Callback: Sniffed data = "));
Serial.println(msg);
//TODO: Add local logic here to take action when a device’s value/state is changed
//Masquerade as the ThingShield to send data to the Arduino, as if from the ST Cloud (uncomment and edit following line)
//st::receiveSmartString(“Put your command here!”); //use same strings that the Device Handler would send
}
//******************************************************************************************
//Arduino Setup() routine
//******************************************************************************************
void setup()
{
//******************************************************************************************
//Declare each Device that is attached to the Arduino
// Notes: - For each device, there is typically a corresponding “tile” defined in your
// SmartThings DeviceType Groovy code
// - For details on each device’s constructor arguments below, please refer to the
// corresponding header (.h) and program (.cpp) files.
// - The name assigned to each device (1st argument below) must match the Groovy
// DeviceType Tile name. (Note: “temphumid” below is the exception to this rule
// as the DHT sensors produce both “temperature” and “humidity”. Data from that
// particular sensor is sent to the ST Hub in two separate updates, one for
// “temperature” and one for “humidity”)
//******************************************************************************************
//Polling Sensors
static st::PS_Illuminance sensor1(F(“illuminance”), 120, 0, PIN_ILLUMINANCE, 0, 1024, 0, 1000);
static st::PS_TemperatureHumidity sensor2(F(“temphumid”), 120, 10, PIN_TEMPERATUREHUMIDITY, st::PS_TemperatureHumidity::DHT22);
static st::PS_Water sensor3(F(“water”), 60, 20, PIN_WATER, 200);
//Interrupt Sensors
static st::IS_Motion sensor4(F(“motion0”), PIN_MOTION0, HIGH, false);
static st::IS_Motion sensor8(F(“motion1”), PIN_MOTION1, HIGH, false);
static st::IS_Motion sensor9(F(“motion2”), PIN_MOTION2, HIGH, false);
static st::IS_Motion sensor10(F(“motion3”), PIN_MOTION3, HIGH, false);
static st::IS_Contact sensor5(F(“contact”), PIN_CONTACT, LOW, true);
static st::IS_Button sensor6(F(“button:1”), PIN_BUTTON1);
static st::IS_Button sensor7(F(“button:2”), PIN_BUTTON2);
//Executors
static st::EX_Switch executor1(F(“switch”), PIN_SWITCH, LOW, true);
static st::EX_Alarm executor2(F(“alarm”), PIN_ALARM, LOW, true);
//*****************************************************************************
// Configure debug print output from each main class
//*****************************************************************************
st::Everything::debug=true;
st::Executor::debug=true;
st::Device::debug=true;
st::PollingSensor::debug=true;
st::InterruptSensor::debug=true;
//*****************************************************************************
//Initialize the “Everything” Class
//*****************************************************************************
//Initialize the optional local callback routine (safe to comment out if not desired)
st::Everything::callOnMsgSend = callback;
//Create the SmartThings WiFiEsp (ESP-01) Communications Object
st::Everything::SmartThing = new st::SmartThingsWiFiEsp(&Serial1, str_ssid, str_password, ip, serverPort, hubIp, hubPort, st::receiveSmartString);
//Initialize the Serial1 baudrate to match your ESP-01’s baud rate (e.g. 9600, 57600, 115200)
Serial1.begin(115200);
//Run the Everything class’ init() routine which establishes Ethernet communications with the SmartThings Hub
st::Everything::init();
//*****************************************************************************
//Add each sensor to the “Everything” Class
//*****************************************************************************
st::Everything::addSensor(&sensor1);
st::Everything::addSensor(&sensor2);
st::Everything::addSensor(&sensor3);
st::Everything::addSensor(&sensor4);
st::Everything::addSensor(&sensor5);
st::Everything::addSensor(&sensor6);
st::Everything::addSensor(&sensor7);
st::Everything::addSensor(&sensor8);
st::Everything::addSensor(&sensor9);
st::Everything::addSensor(&sensor10);
//*****************************************************************************
//Add each executor to the “Everything” Class
//*****************************************************************************
st::Everything::addExecutor(&executor1);
st::Everything::addExecutor(&executor2);
//*****************************************************************************
//Initialize each of the devices which were added to the Everything Class
//*****************************************************************************
st::Everything::initDevices();
}
//******************************************************************************************
//Arduino Loop() routine
//******************************************************************************************
void loop()
{
//*****************************************************************************
//Execute the Everything run method which takes care of “Everything”
//*****************************************************************************
st::Everything::run();
}
Device Handler
/**
*/
metadata {
definition (name: “ST_Anything_Ethernet”, namespace: “ogiewon”, author: “Dan Ogorchock”) {
capability "Configuration"
capability "Illuminance Measurement"
capability "Temperature Measurement"
capability "Relative Humidity Measurement"
capability "Water Sensor"
capability "Motion Sensor"
capability "Switch"
capability "Sensor"
capability "Alarm"
capability "Contact Sensor"
capability "Polling"
capability "Button"
capability “Holdable Button”
command "test"
command "alarmoff"
}
simulator {
}
// Preferences
preferences {
input "ip", "text", title: "Arduino IP Address", description: "ip", required: true, displayDuringSetup: true
input "port", "text", title: "Arduino Port", description: "port", required: true, displayDuringSetup: true
input "mac", "text", title: "Arduino MAC Addr", description: "mac", required: true, displayDuringSetup: true
input "illuminanceSampleRate", "number", title: "Light Sensor Inputs", description: "Sampling Interval (seconds)", defaultValue: 30, required: true, displayDuringSetup: true
input "temphumidSampleRate", "number", title: "Temperature/Humidity Sensor Inputs", description: "Sampling Interval (seconds)", defaultValue: 30, required: true, displayDuringSetup: true
input "waterSampleRate", "number", title: "Water Sensor Inputs", description: "Sampling Interval (seconds)", defaultValue: 30, required: true, displayDuringSetup: true
input "numButtons", "number", title: "Number of Buttons", description: "Number of Buttons to be implemented", defaultValue: 0, required: true, displayDuringSetup: true
}
// Tile Definitions
tiles {
valueTile("illuminance", "device.illuminance", width: 1, height: 1) {
state("illuminance", label:'${currentValue} ${unit}', unit:"lux",
backgroundColors:[
[value: 9, color: "#767676"],
[value: 315, color: "#ffa81e"],
[value: 1000, color: "#fbd41b"]
]
)
}
valueTile("temperature", "device.temperature", width: 1, height: 1) {
state("temperature", label:'${currentValue}�',
backgroundColors:[
[value: 31, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 95, color: "#d04e00"],
[value: 96, color: "#bc2323"]
]
)
}
valueTile("humidity", "device.humidity", inactiveLabel: false) {
state "humidity", label:'${currentValue}% humidity', unit:""
}
standardTile("water", "device.water", width: 1, height: 1) {
state "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
state "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0"
}
standardTile("motion0", "device.motion0", width: 1, height: 1) {
state("active", label:'Kitchen', icon:"st.motion.motion.active", backgroundColor:"#53a7c0")
state("inactive", label:'Kitchen', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff")
}
standardTile("motion1", "device.motion1", width: 1, height: 1) {
state("active", label:'Droom', icon:"st.motion.motion.active", backgroundColor:"#53a7c0")
state("inactive", label:'Droom', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff")
}
standardTile("motion2", "device.motion2", width: 1, height: 1) {
state("active", label:'DStairs', icon:"st.motion.motion.active", backgroundColor:"#53a7c0")
state("inactive", label:'DStairs', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff")
}
standardTile("motion3", "device.motion3", width: 1, height: 1) {
state("active", label:'BroomUp', icon:"st.motion.motion.active", backgroundColor:"#53a7c0")
state("inactive", label:'BroomUp', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff")
}
standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) {
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
}
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat") {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
standardTile("contact", "device.contact", width: 1, height: 1) {
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
}
standardTile("alarm", "device.alarm", width: 1, height: 1) {
state "off", label:'off', action:'alarm.siren', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff"
state "strobe", label:'', action:'alarmoff', icon:"st.secondary.strobe", backgroundColor:"#cccccc"
state "siren", label:'siren!', action:'alarmoff', icon:"st.alarm.beep.beep", backgroundColor:"#e86d13"
state "both", label:'alarm!', action:'alarmoff', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
}
standardTile("test", "device.alarm", inactiveLabel: false, decoration: "flat") {
state "default", label:'', action:"test", icon:"st.secondary.test"
}
standardTile("off", "device.alarm", , width: 1, height: 1) {
state "default", label:'Alarm', action:"alarmoff", icon:"st.secondary.off"
}
//standardTile("off", "device.alarm", inactiveLabel: false, decoration: "flat") {
// state "default", label:'', action:"alarmoff", icon:"st.secondary.off"
//}
main(["motion1","temperature","humidity","illuminance","switch","contact","alarm","water","motion0","motion2","motion3"])
details(["motion1","temperature","humidity","illuminance","switch","contact","alarm","test","off","water","configure","motion0","motion1","motion2","motion3"])
}
}
// parse events into attributes
def parse(String description) {
//log.debug "Parsing ‘${description}’"
def msg = parseLanMessage(description)
def headerString = msg.header
if (!headerString) {
//log.debug "headerstring was null for some reason :("
}
def bodyString = msg.body
if (bodyString) {
log.debug "BodyString: $bodyString"
def parts = bodyString.split(" ")
def name = parts.length>0?parts[0].trim():null
def value = parts.length>1?parts[1].trim():null
def results = []
if (name.startsWith("button")) {
def pieces = name.split(":")
def btnName = pieces.length>0?pieces[0].trim():null
def btnNum = pieces.length>1?pieces[1].trim():null
//log.debug "In parse: name = ${name}, value = ${value}, btnName = ${btnName}, btnNum = ${btnNum}"
results = createEvent([name: btnName, value: value, data: [buttonNumber: btnNum], descriptionText: "${btnName} ${btnNum} was ${value} ", isStateChange: true, displayed: true])
}
else {
results = createEvent(name: name, value: value)
}
log.debug results
return results
}
}
private getHostAddress() {
def ip = settings.ip
def port = settings.port
log.debug "Using ip: ${ip} and port: ${port} for device: ${device.id}"
return ip + ":" + port
}
def sendEthernet(message) {
log.debug "Executing ‘sendEthernet’ ${message}"
new physicalgraph.device.HubAction(
method: “POST”,
path: “/${message}?”,
headers: [ HOST: “${getHostAddress()}” ]
)
}
// handle commands
def on() {
log.debug "Executing ‘switch on’"
sendEthernet(“switch on”)
}
def off() {
log.debug "Executing ‘switch off’"
sendEthernet(“switch off”)
}
def alarmoff() {
log.debug "Executing ‘alarm off’"
sendEthernet(“alarm off”)
}
def strobe() {
log.debug "Executing ‘alarm strobe’"
sendEthernet(“alarm strobe”)
}
def siren() {
log.debug "Executing ‘alarm siren’"
sendEthernet(“alarm siren”)
}
def both() {
log.debug "Executing ‘alarm both’"
sendEthernet(“alarm both”)
}
def test() {
log.debug “Executing ‘alarm test’”
[
sendEthernet(“alarm both”),
“delay 3000”,
sendEthernet(“alarm off”)
]
}
def poll() {
//temporarily implement poll() to issue a configure() command to send the polling interval settings to the arduino
configure()
}
def configure() {
log.debug "Executing ‘configure’"
updateDeviceNetworkID()
sendEvent(name: “numberOfButtons”, value: numButtons)
//log.debug "illuminance " + illuminanceSampleRate + "|temphumid " + temphumidSampleRate + "|water " + waterSampleRate
log.debug "water " + waterSampleRate
log.debug "illuminance " + illuminanceSampleRate
log.debug "temphumid " + temphumidSampleRate
[
sendEthernet("water " + waterSampleRate),
“delay 1000”,
sendEthernet("illuminance " + illuminanceSampleRate),
“delay 1000”,
sendEthernet("temphumid " + temphumidSampleRate)
]
}
def updateDeviceNetworkID() {
log.debug "Executing ‘updateDeviceNetworkID’"
if(device.deviceNetworkId!=mac) {
log.debug “setting deviceNetworkID = ${mac}“
device.setDeviceNetworkId(”${mac}”)
}
}
def updated() {
if (!state.updatedLastRanAt || now() >= state.updatedLastRanAt + 5000) {
state.updatedLastRanAt = now()
log.debug "Executing ‘updated’"
runIn(3, updateDeviceNetworkID)
sendEvent(name: “numberOfButtons”, value: numButtons)
}
else {
log.trace “updated(): Ran within last 5 seconds so aborting.”
}
}
def initialize() {
sendEvent(name: “numberOfButtons”, value: numButtons)
}