@ogiewon Hello Dan! I have just started to begin trying to use your fantastic code to control an ESP-8266. I have uploaded the sketch ST_Anything_Multiples_ESP01WiFi.ino to the board and have set up the device in the SmartThings app, but I keep getting an error saying, “Child device creation failed. Please make sure that the ‘null’ is installed and published.” Any help would be appreciated. Thanks!
V There’s is a bug introduced by ST in the last month or so causing the error you’re seeing. Just delete the parent device and recreate it, remembering to configure its settings via your phone app. Afterwards, the child devices should be created.
If you manually delete a child device, the problem will return. It actually clears itself up after about 24 hours…
OR
It could be that you tried renaming the devices in the Arduino sketch. Are you starting with an unaltered version of my example sketch? Of course, you you have to edit the network section to work with your router.
Awesome Awesome Awesome, so many thanks for this project! Can’t tell you how many hours I invested into trying to get ESP8266 sensors integrated into ST!
I’m having a slight issue with adding contact sensors. When I first install this, usually neither show up. If I then add the first contact sensor, recompile and flash, then add the second, recompile and flash, I can get them added one by one. Any thoughts?
My code is below:
//******************************************************************************************
// File: ST_Anything_Multiples_ESP8266WiFi.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 NodeMCU ESP8266 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 NodeMCU ESP8266's WiFi.
//
// ST_Anything_Multiples implements the following ST Capabilities as a demo of what is possible with a single NodeMCU ESP8266
// - 1 x Alarm device (using a simple digital output)
// - 1 x Contact Sensor devices (used to monitor magnetic door sensors)
// - 1 x Switch devices (used to turn on a digital output (e.g. LED, relay, etc...)
// - 1 x Motion devices (used to detect motion)
// - 1 x Smoke Detector devices (using simple digital input)
// - 1 x Temperature Measurement devices (Temperature from Dallas Semi 1-Wire DS18B20 device)
// - 1 x Relay Switch devices (used to turn on a digital output for a set number of cycles And On/Off times (e.g.relay, etc...))
// - 2 x Button devices (sends "pushed" if held for less than 1 second, else sends "held"
// - 1 x Water Sensor devices (using the 1 analog input pin to measure voltage from a water detector board)
//
// 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-04-17 Dan Ogorchock New example showing use of Multiple device of same ST Capability
// used with new Parent/Child Device Handlers (i.e. Composite DH)
// 2017-05-25 Dan Ogorchock Revised example sketch, taking into account limitations of NodeMCU GPIO pins
//
//******************************************************************************************
//******************************************************************************************
// SmartThings Library for ESP8266WiFi
//******************************************************************************************
#include <SmartThingsESP8266WiFi.h>
//******************************************************************************************
// 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_DS18B20_Temperature.h> //Implements a Polling Sesnor (PS) to measure Temperature via DS18B20 libraries
#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_Smoke.h> //Implements an Interrupt Sensor (IS) to monitor the status of a digital input pin
#include <IS_DoorControl.h> //Implements an Interrupt Sensor (IS) and Executor to monitor the status of a digital input pin and control a digital output 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
#include <S_TimedRelay.h> //Implements a Sensor to control a digital output pin with timing capabilities
//*************************************************************************************************
//NodeMCU v1.0 ESP8266-12e Pin Definitions (makes it much easier as these match the board markings)
//*************************************************************************************************
//#define LED_BUILTIN 16
//#define BUILTIN_LED 16
//
//#define D0 16 //no internal pullup resistor
//#define D1 5
//#define D2 4
//#define D3 0 //must not be pulled low during power on/reset, toggles value during boot
//#define D4 2 //must not be pulled low during power on/reset, toggles value during boot
//#define D5 14
//#define D6 12
//#define D7 13
//#define D8 15 //must not be pulled high during power on/reset
//******************************************************************************************
//Define which Arduino Pins will be used for each device
//******************************************************************************************
#define PIN_CONTACT_1 D1 //SmartThings Capabilty "Contact Sensor"
#define PIN_CONTACT_2 D2 //SmartThings Capabilty "Contact Sensor"
#define PIN_TEMPERATURE_1 D6 //SmartThings Capabilty "Temperature Measurement" (Dallas Semiconductor DS18B20)
#define PIN_TEMPERATUREHUMIDITY1 D7 //SmartThings Capabilty "Temperature Measurement" (DHT Temp and Humidity Sensor)
//******************************************************************************************
//ESP8266 WiFi Information
//******************************************************************************************
String str_ssid = "xxxx"; // <---You must edit this line!
String str_password = "xxxx"; // <---You must edit this line!
IPAddress ip(192, 168, 1, 105); //Device IP Address // <---You must edit this line!
IPAddress gateway(192, 168, 1, 2); //Router gateway // <---You must edit this line!
IPAddress subnet(255, 255, 255, 0); //LAN subnet mask // <---You must edit this line!
IPAddress dnsserver(192, 168, 1, 2); //DNS server // <---You must edit this line!
const unsigned int serverPort = 8090; // port to run the http server on
// Smartthings Hub Information
IPAddress hubIp(192, 168, 1, 56); // 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 Device Hanlder Groovy code, except when using new COMPOSITE Device Handler
// - 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
// Device Handler names. (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")
// - The new Composite Device Handler is comprised of a Parent DH and various Child
// DH's. The names used below MUST not be changed for the Automatic Creation of
// child devices to work properly. Simply increment the number by +1 for each duplicate
// device (e.g. contact1, contact2, contact3, etc...) You can rename the Child Devices
// to match your specific use case in the ST Phone Application.
//******************************************************************************************
//Polling Sensors
static st::PS_DS18B20_Temperature sensor1(F("temperature0"), 15, 0, PIN_TEMPERATURE_1, false, 10, 1);
//Interrupt Sensors
static st::IS_Contact sensor3(F("contact1"), PIN_CONTACT_1, LOW, true);
static st::IS_Contact sensor4(F("contact2"), PIN_CONTACT_2, LOW, true);
//DHT Sensors
static st::PS_TemperatureHumidity sensor2(F("temphumid1"), 15, 0, PIN_TEMPERATUREHUMIDITY1, st::PS_TemperatureHumidity::DHT11,"temperature1","humidity1");
//*****************************************************************************
// Configure debug print output from each main class
// -Note: Set these to "false" if using Hardware Serial on pins 0 & 1
// to prevent communication conflicts with the ST Shield communications
//*****************************************************************************
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 ESP8266WiFi Communications Object
//STATIC IP Assignment - Recommended
st::Everything::SmartThing = new st::SmartThingsESP8266WiFi(str_ssid, str_password, ip, gateway, subnet, dnsserver, serverPort, hubIp, hubPort, st::receiveSmartString);
//DHCP IP Assigment - Must set your router's DHCP server to provice a static IP address for this device's MAC address
//st::Everything::SmartThing = new st::SmartThingsESP8266WiFi(str_ssid, str_password, serverPort, hubIp, hubPort, st::receiveSmartString);
//Run the Everything class' init() routine which establishes WiFi communications with 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);
//*****************************************************************************
//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();
}
You really shouldn’t have to add them one at a time. Maybe some sort of race condition on the ST Cloud Servers? You can always just press the REFRESH tile on the parent device. This causes all of the devices to send a status update to ST. Any missing children will be created. Also, sometimes you need to refresh the ST app to pick up the new children. On iOS, I just drag down on the device page until I see the spinning wheel icon appear, then let go. This causes the app to refresh its data.
Thanks Dan!
Another question. I noticed after I unplug my ESP8266 that my temperature data remains at the last value. I’m planning to use this device as a fridge/freezer monitor, so if my board stops working I’d rather the values go stale, rather than remain at their last value.
Any thoughts on this? Maybe some time of keep alive?
Matt,
That is how all ST devices work, unfortunately. You can very easily install a community developed SmartApp called “Device Monitor” which will notify you if any of your devices stop updating values for an extended period of time versus normal.
Check it out here. I use it and it works very well!
Thanks Dan, two more questions regarding DHT22 setup:
-
Can you clarify what the “120, 10” are used for in the line of code below for the DHT22?
static st::PS_TemperatureHumidity sensor2(F(“temphumid”), 120, 10, PIN_TEMPERATUREHUMIDITY, st::PS_TemperatureHumidity::DHT22) -
Is it possible to setup multiple DHT22 sensors? It appears that PS_TemperatureHumidity.h automatically names the children temperture1 and humidity1. Would I have to create an additional PS_TemperatureHumidity.h for each DHT22?
On question 2 I have 5 DHT21’s in my home/outside.
You just have to define additional PINs etc… like this:
#define PIN_TEMPERATUREHUMIDITY_1 23
#define PIN_TEMPERATUREHUMIDITY_2 25
#define PIN_TEMPERATUREHUMIDITY_3 27
#define PIN_TEMPERATUREHUMIDITY_4 29
#define PIN_TEMPERATUREHUMIDITY_5 33
and then the sensors of course you are using DHT22:
static st::PS_TemperatureHumidity sensor1(F(“temphumid1”), 60, 40, PIN_TEMPERATUREHUMIDITY_1, st::PS_TemperatureHumidity::DHT21,“temperature1”,“humidity1”);
static st::PS_TemperatureHumidity sensor2(F(“temphumid2”), 60, 50, PIN_TEMPERATUREHUMIDITY_2, st::PS_TemperatureHumidity::DHT21,“temperature2”,“humidity2”);
static st::PS_TemperatureHumidity sensor3(F(“temphumid3”), 60, 50, PIN_TEMPERATUREHUMIDITY_3, st::PS_TemperatureHumidity::DHT21,“temperature3”,“humidity3”);
static st::PS_TemperatureHumidity sensor4(F(“temphumid4”), 60, 50, PIN_TEMPERATUREHUMIDITY_4, st::PS_TemperatureHumidity::DHT21,“temperature4”,“humidity4”);
static st::PS_TemperatureHumidity sensor5(F(“temphumid5”), 60, 50, PIN_TEMPERATUREHUMIDITY_5, st::PS_TemperatureHumidity::DHT21,“temperature5”,“humidity5”);
Finally don’t forget the addSensor section:
st::Everything::addSensor(&sensor1);
st::Everything::addSensor(&sensor2);
st::Everything::addSensor(&sensor3);
st::Everything::addSensor(&sensor4);
st::Everything::addSensor(&sensor5);
The child objects are created in the main sensor list and you can rename them to whatever you want them called with settings for each child object.
Thanks David. Do you know what the “60, 50” nomenclature is for?
At the top of each device’s class .h and .cpp file you will find a detailed explanation of what each of the arguments is used for. The comments/documentation for the DHT Temperature & Humidity sensors is below.
So, the “60, 50” nomenclature means that the device will be scanned every 60 seconds, with a “50” second offset from the top of a 60 second window of time.
For multiple sensors, I would probably go with 120 seconds for the poling interval. For the offset, I would set the first one to be 5 seconds, the second one to be 10 seconds, and so on (i.e. 5, 10, 15, 20, 25, 30, etc…). This prevents trying to collect and transfer all the data at once. It also provides a more balanced workload for the ST cloud to handle. No reason to slam it all at once.
// Create an instance of this class in your sketch's global variable section
// For Example: st::PS_TemperatureHumidity sensor2("temphumid1", 120, 7, PIN_TEMPERATUREHUMIDITY, st::PS_TemperatureHumidity::DHT22, "temperature1", "humidity1", false);
//
// st::PS_TemperatureHumidity() constructor requires the following arguments
// - String &name - REQUIRED - the name of the object - must match the Groovy ST_Anything DeviceType tile name
// - long interval - REQUIRED - the polling interval in seconds
// - long offset - REQUIRED - the polling interval offset in seconds - used to prevent all polling sensors from executing at the same time
// - byte pin - REQUIRED - the Arduino Pin to be used as a digital output
// - DHT_SENSOR DHTSensorType - REQUIRED - the type of DHT sensor (DHT11, DHT21, DHT22, DHT33, or DHT44)
// - String strTemp - OPTIONAL - name of temperature sensor to send to ST Cloud (defaults to "temperature")
// - String strHumid - OPTIONAL - name of humidity sensor to send to ST Cloud (defaults to "humidity")
// - bool In_C - OPTIONAL - true = Report Celsius, false = Report Farenheit (Farentheit is the default)
hi, thank you for this code. My project is to control my garage by wiring my garage remote to a relay (my garage opener has a fancy control panel that I can’t simply wire the relay into). I previously tried using a raspberry pi with webiopi, but that was very flaky. Your code, along with the ESP8266-12e works very well.
I have a problem, though. The relay seems to engage for approximately 10 or more seconds no matter what I set the onTime and offTime to when calling the relaySwitch constructor. I even changed the value in the relayswitch.h header file with no effect.
Please note that my relay board is a normally on type so I set the reverse logic variable to true when calling the constructor. Also, I only have two relays connected at this time, nothing else.
#define PIN_TIMEDRELAY_1 D5 //SmartThings Capability "Relay Switch"
#define PIN_TIMEDRELAY_2 D6 //SmartThings Capability "Relay Switch"
static st::S_TimedRelay sensor1(F("relaySwitch1"), PIN_TIMEDRELAY_1, LOW, true, 1, 1, 1);
static st::S_TimedRelay sensor2(F("relaySwitch2"), PIN_TIMEDRELAY_2, LOW, true, 1, 1, 1);
Happy to try to help troubleshooting. Can you please post your entire sketch either here, or in a private message? That will help me to debug your actual code.
I have never seen the TimedRelay device not work as designed. The only thing that I can think which would mess up the timing is if there was a lot of extra code added to you loop() function in the sketch. Any delays or looping code inside of loop() will screw up all of the timing.
@ogiewon, great work and thanks for your efforts here, fantastic.
I’ve been experimenting with the ESP8266 NODEMCU (great little device), I’m now controlling my TV trough ask alexa and the ESP (http://thingsthataresmart.wiki/index.php?title=How_to_Control_your_TV_through_Alexa_and_Smartthings if anyone is interested ), and have just got your project up and running with a motion and illuminance sensor.
I really like the idea of having just the single parent device, and have updated the code so the child devices are not created as you have shown.
A question, is it possible to move the refresh buttons to the bottom of the list (think it is by adjusting the order in the code) and having one of the sensors (such as light level) as a full tile and the other shown below, much in the same way of a multi sensor, the Aeon Multisensor as an example below
Sure, you can most definitely create your own custom Device Handler and lay out everything exactly the way you want. As long as you have only one of each ST Capabiliy (i.e. one contact sensor, one temperature sensor, one motion sensor, etc…), you do NOT need to even create child devices. You can simply create all of the tiles you need in the Device Handler.
If you look through some of the deprecated device handlers from earlier ST_Anything releases, you will see examples of having all local tiles in one DH. Take a look at the following example… Just make sure the names of each tile matches exactly the names for each device in your sketch (case sensitive!)
Fantastic, thanks. Will have a look and see where I get!
Where did you find information on creating the parent without children? My use case has just a single switch (executor) and I would like to have just a single line in my phone app. Right now the parent and child get a slot on the mobile UI.
I posted the information literally a few posts above this one… This was my old way of using a traditional device handler. You just need to remove any of the tiles that you do not want to use, and change the names of the ones you want to use to match the names assigned in your sketch’s setup() routine. Also, remove any of the “capabilities” aside from those you wish to keep.
You can also avoid having two devices show up by simply editing one line of the parent device handler:
On line 379 in the parent-st-anything-ethernet.groovy DH, change the isComponent from false to true. Afterwards, you need to save and publish it. Then remove the existing parent device and manually recreate again. This will result in a single device in the ST App’s “Things View” but there are still technically two devices (the parent and the child).
addChildDevice(deviceHandlerName, "${device.deviceNetworkId}-${deviceName}${deviceNumber}", null,
[completedSetup: true, label: "${device.displayName} (${deviceName}${deviceNumber})",
isComponent: true, componentName: "${deviceName}${deviceNumber}", componentLabel: "${deviceName} ${deviceNumber}"])
So I tried the changing of line 379. It’s interesting that if I pick a name during device creation that I’d previously used, it gives me options for “replace” or “remove”. This was after I deleted the previous device in ST browser interface. If I hit replace, it spins and spins attempting the check the device’s health. Never came back so I aborted.
I created a new device with a different name and things worked normally. I see the parent in the phone’s UI and I have to select it in order to get to the screen with the child to turn on the switch. Is it possible to have the phone’s UI show only the child so that the switch may be activated from the top level device screen?
Yes, you should be able to do that simply by rearranging the tiles in the DH. I haven’t tried this though, so give it a try and let us know.
tiles (scale: 2){
childDeviceTiles("all")
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'Refresh', action: "refresh.refresh", icon: "st.secondary.refresh-icon"
}
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "configure", label:'Configure', action:"configuration.configure", icon:"st.secondary.tools"
}
valueTile("numberOfButtons", "device.numberOfButtons", inactiveLabel: false, width: 2, height: 2) {
state "numberOfButtons", label:'${currentValue} buttons', unit:""
}
}
Using the non-parent/child device handler above really is probably what you want to do. It’ll take a little more tweaking on your part, but you’ll get exactly what you want and will learn about customizing a Device Handler in the process. There is decent ST Documentation regarding writing device handlers which will probably help. Just remember to change the tile name from “switch” to “switch1” to match the strings being sent to and from the arduino.
Alright, I have removed and then added the device, but the hub still does not populate the child devices… I have also double checked the IP settings for conflicts, verified the SmartThings Hub IP and MAC address of ESP-01, and checked the WiFi settings. Also, under the serial monitor when setting up the device, it seems like the chip initializes correctly.
Can you please tell me if I’m doing this correctly ? I have an ESP-01 with the corresponding Multiples sketch, with nothing attached to either GPIO pins.
“https://importhack.files.wordpress.com/2014/11/esp8266-reflash-firmware.png”
Like this, but without the TX and RX pins attached i.e. only power, ground and pull HIGH on CHPD
I have only changed the lines that you have typed, “You must edit this line!”. I have no other ESP8266 devices registered in the hub, just this one. Also, I am using an Android phone for the setup. Is this setup okay?
The SmartThings IDE displays these log events-
Oh, and the reason why there is a change in numberOfButtons is because the app didn’t allow me to save the device with 0 buttons, which is strange. I had to save saying it had 2 then re-save with 0. Excuse me for bothering you so much .