[RELEASE] ST_Anything - Arduino/ESP8266/ESP32

Any news about St_Anything and new Smartthings app? I’m a new user (since December) and not very keen to do anything in old app. I have some ESP32s and temp/hum sensors on my desk but I’d like to start my project in environment that stays around for a while.

I have personally not focused on the new ST App, yet. Until ST publishes some documentation/guideline on how to integrate custom Parent/Child (Composite) Device Handlers, it will be difficult for me and others to make much progress. That being said, I did fire up the new ST App on my phone for the first time in over a year and I was pleasantly surprised to see some sign of life from an ST_Anything Parent and set of Child devices. You may want to give it a try and report back your findings.

I will say that you will still need to perform the initial configuration using the ST Web IDE and possibly the ST Classic App.

Since my home is now running happily on Hubitat, I am not personally motivated/driven to make ST_Anything work with the new ST App. I’ll happily tweak the ST Parent and Child Device Handlers once I know exactly what is needed, but I am not going to brute-force-work-it-out without any documentation.

1 Like

Ok, I’ll give it a try when I have some spare time.

I thought you were going to write some code to help me.

Please remind me… It’s been a busy couple of weeks, and I spend most of my time over in the Hubitat Community. Happy to assist if I can…

Smart keurig lol its chill thank you

I don’t think you want to depend on the SmartThings Cloud to run your coffee brewing sequence each morning. It is one thing to use it as a trigger to start the brewing cycle, but another altogether to perform each of the timing steps. It is possible, but I don’t see the value or necessity in it.

I think just having ST initiate the brewing cycle should be enough, correct?


I believe I have a working sketch that is sort of the best of both worlds. The NodeMCU ESP32 will handle all timing of the ‘button press sequences’ so no reliance on the ST cloud for that. However, you will see 4 devices created in SmartThings which will allow you to ‘monitor’ the brewing cycle if you desire. (Note, the toggling of the power button, lid switch, and brew button are only 1 second each, so visibly watching this in the ST Classic app may not be very useful.)

OK, here are a few useful tidbits of information:

  • In your ST_Anything library, you will find a file named ‘constants.h’ which you will need to edit. Please UNCOMMENT the following line as shown below and save the file. This will prevent automatic refresh updates from the ESP32 to SmartThings, which would screw up the sequencing of the various digital outputs during the brewing cycle.
#define DISABLE_REFRESH		//If uncommented, will disable periodic refresh of the sensors and executors states to the ST Cloud - improves performance, but may reduce data integrity
  • This ST_Anything_Keurig sketch creates 4 Timed Relay devices.

    • The first one (relaySwitch1) is the one that is used to start the brewing cycle. It will appear as ON in SmartThings for the entire 900,000ms (15min). Turning this off manually via the ST app is not recommended. This device should Turned ON to start the sequence as part of your Alexa Good Morning Routine.
    • The second one (relaySwitch2) is used to toggle the power button. It is used at the start of the brewing cycle to turn on the unit, and again at the end to turn off the unit. It’s output pin is held for 1000ms to accomplish this. Do NOT manually change this device from within the ST App.
    • The third one (relaySwitch3) is used to toggle the lid. It is used at the start of the brewing cycle after the unit is powered on. It’s output pin is held for 1000ms to accomplish this. Do NOT manually change this device from within the ST App.
    • The fourth one (relaySwitch4) is used to start the brewing. It is used at the start of the brewing cycle after the lid has been cycled. It’s output pin is held for 1000ms to accomplish this. Do NOT manually change this device from within the ST App.
  • The GPIO pins are defined in the sketch for the Power (GPIO19), Lid (GPIO18), and Brewing (GPIO5). These should be wired into your Keurig machine. Do NOT wire pin 23 to anything! I just needed a spare pin for the overall brewing CYCLE timer.

  • Based on your old sketch, it appears that the digital output pins were being pulled LOW to simulate the button presses. I have reproduced this behavior in the definition of the S_TimeRelay devices.

  • All of the sequencing of the brewing cycle is being handled within the callbackSend() routine. It should be fairly straightforward to understand and tweak as you see fit.

  • As always, you’ll need to edit the sketch to add your WiFi credentials

Hope this helps get you going!

//  File: ST_Anything_Keurig_ESP32WiFi.ino
//  Author: Dan G Ogorchock
//  Summary:  This Arduino Sketch, along with the ST_Anything library and the revised SmartThings 
//            library, demonstrates the ability of one ESP32 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 ESP32's WiFi.
//            ST_Anything_Keurig implements the following ST Capabilities as a demo of what is possible with a single ESP32
//              - 1 x Switch devices (used to turn on a digital output (e.g. LED, relay, etc...)
//  Change History:
//    Date        Who            What
//    ----        ---            ----
//    2020-01-26  Dan Ogorchock  Original Creation
// SmartThings Library for ESP32WiFi
#include <SmartThingsESP32WiFi.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 <EX_Switch.h>       //Implements an Executor (EX) via a digital output to a relay
#include <S_TimedRelay.h>    //Implements a Sensor to control a digital output pin with timing/cycle repeat capabilities

//Define which Arduino Pins will be used for each device
//"RESERVED" pins for ESP32 - best to avoid
#define PIN_0_RESERVED             0  //reserved ESP32 boot/program upload
#define PIN_1_RESERVED             1  //reserved ESP32 for TX0
#define PIN_3_RESERVED             3  //reserved ESP32 for RX0
#define PIN_6_RESERVED             6  //reserved ESP32 for flash
#define PIN_7_RESERVED             7  //reserved ESP32 for flash
#define PIN_8_RESERVED             8  //reserved ESP32 for flash
#define PIN_9_RESERVED             9  //reserved ESP32 for flash
#define PIN_10_RESERVED           10  //reserved ESP32 for flash
#define PIN_11_RESERVED           11  //reserved ESP32 for flash

//Digital Pins

//KEURIG Special Logic
#define PIN_CYCLE 23  //Active during complete automated brewing cycle (nothing wired to this pin!!!)
#define PIN_POWER 19  //Power Switch
#define PIN_LID   18  //Lid Switch
#define PIN_BREW   5  //Brew Switch 

bool brewingCycleActive;

//ESP832 WiFi Information
String str_ssid     = "yourSSIDhere";                           //  <---You must edit this line!
String str_password = "yourWiFiPasswordHere";                   //  <---You must edit this line!
IPAddress ip(192, 168, 1, 233);       //Device IP Address       //  <---You must edit this line!
IPAddress gateway(192, 168, 1, 1);    //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, 1);  //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, 149);    // smartthings hub ip     //  <---You must edit this line!
const unsigned int hubPort = 39500;   // smartthings hub port
//const unsigned int hubPort = 39501;   // hubitat elevation 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 callbackSend(const String &msg)
  String strTemp = msg;
//  Serial.print(F("ST_Anything CallbackSend: 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
  if (brewingCycleActive == false) {
    if (strTemp == "relaySwitch1 on") {
      Serial.println("Brewing Cycle Started");
      brewingCycleActive = true;
      Serial.println("Toggling Power Switch to turn on Keurig");
      st::receiveSmartString("relaySwitch2 on"); //Cycle Power 
  else {
    if (strTemp == "relaySwitch2 off") {
      Serial.println("Toggling Lid Switch");
      st::receiveSmartString("relaySwitch3 on"); //Toggle Lid Switch
    if (strTemp == "relaySwitch3 off") {
      Serial.println("Toggling Brew Switch");
      st::receiveSmartString("relaySwitch4 on"); //Toggle Brew Switch
    if (strTemp == "relaySwitch1 off") {         //Cycle is complete
      brewingCycleActive = false;
      Serial.println("Brewing Cycle Complete");
      Serial.println("Toggling Power Switch to turn off Keurig");
      st::receiveSmartString("relaySwitch2 on"); //Cycle Power 

//Arduino Setup() routine
void setup()

  brewingCycleActive = false;
  //Declare each Device that is attached to the Arduino
  //  Notes: 
  //         - For details on each device's constructor arguments below, please refer to the 
  //           corresponding header (.h) and program (.cpp) files.
  //         - 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

  //Interrupt Sensors 
  //Special sensors/executors (uses portions of both polling and executor classes)
  static st::S_TimedRelay           sensor1(F("relaySwitch1"), PIN_CYCLE, LOW, true, 900000, 0, 1); //Complete brewing cycle - 15 minutes
  static st::S_TimedRelay           sensor2(F("relaySwitch2"), PIN_POWER, LOW, true, 1000, 0, 1);   //Power Switch
  static st::S_TimedRelay           sensor3(F("relaySwitch3"), PIN_LID, LOW, true, 1000, 0, 1);     //Lid Switch
  static st::S_TimedRelay           sensor4(F("relaySwitch4"), PIN_BREW, LOW, true, 1000, 0, 1);    //Brew Switch
  //static st::EX_Switch              executor1(F("switch1"), PIN_SWITCH_1, LOW, true);
  //  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

  //Initialize the "Everything" Class

  //Initialize the optional local callback routine (safe to comment out if not desired)
  st::Everything::callOnMsgSend = callbackSend;
  //Create the SmartThings ESP32WiFi Communications Object
    //STATIC IP Assignment - Recommended
    st::Everything::SmartThing = new st::SmartThingsESP32WiFi(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::SmartThingsESP32WiFi(str_ssid, str_password, serverPort, hubIp, hubPort, st::receiveSmartString);

  //Run the Everything class' init() routine which establishes WiFi communications with SmartThings Hub
  //Add each sensor to the "Everything" Class
  //Add each executor to the "Everything" Class
  //Initialize each of the devices which were added to the Everything Class

//Arduino Loop() routine
void loop()
  //Execute the Everything run method which takes care of "Everything"

Thank you thank you. You are my hero. I will let you know when up and running. Need to purchase a new router first to set static ip for smartthings hub. But once i do i will run this and let you know. Thank you again a million times thank you.

1 Like

How would i go about change the MAC address on a replacement ESP32, so I don’t need to reset up my devices or pistons

I am not aware of a way to change the MAC address on an ESP32. I am not saying it cannot be done, but rather that I do not know of a way to do so.

I want to use an arduino, esp8266 wifi module directly to the smartthings of the phone without any hub.

Someone guides me, I don’t know anything…

Sorry, ST_Anything requires a SmartThings hub in order to work.

So I need to turn off a few switches when a button is pressed. I got that done no problem, but now what I really need is a cool off period before the last switch is turned off. (ie “switch1”)

I think “millis() function” is the right one to use so every thing else keeps going but not sure how to implement it.
Also if switch1 is turned back ON (val1 = 1) happens during this time, I’d like to abort the wait to off time.

Hope someone could give me a hand

//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.
int val1;     // variable for keeping local copy of the switch1 current state
int val2;     // variable for keeping local copy of the switch2 current state
int val3;     // variable for keeping local copy of the switch3 current state
int val4;     // variable for keeping local copy of the switch4 current state
int val5;     // variable for keeping local copy of the switch5 current state
int val6;     // variable for keeping local copy of the switch6 current state

void callback(const String &msg)

  Serial.print(F("ST_Anything Callback: Sniffed data = "));

  //TODO:  Add local logic here to take action when a device's value/state is changed

  //NOTE:  you may need to play with the logic below to get the behavior you desire!!!
  if (msg == "switch1 on")  { val1 = 1;}
  if (msg == "switch1 off") { val1 = 0;}
  if (msg == "switch2 on")  { val2 = 1;}
  if (msg == "switch2 off") { val2 = 0;}
  if (msg == "switch3 on")  { val3 = 1;}
  if (msg == "switch3 off") { val3 = 0;}
  if (msg == "switch4 on")  { val4 = 1;}
  if (msg == "switch4 off") { val4 = 0;}
  if (msg == "switch5 on")  { val5 = 1;}
  if (msg == "switch5 off") { val5 = 0;}
  if (msg == "switch6 on")  { val6 = 1;}
  if (msg == "switch6 off") { val6 = 0;}
//Spa Heater
  if (msg == "button1 pushed") {
    if (val5 == LOW) {st::receiveSmartString("switch1 on");
                      st::receiveSmartString("switch5 on");
                      st::receiveSmartString("switch7 on");
                      st::receiveSmartString("switch8 on");}
    else {st::receiveSmartString("switch5 off");
          st::receiveSmartString("switch7 off");
          st::receiveSmartString("switch8 off");
          //Turn off only after 5 mins
          //st::receiveSmartString("switch1 off");}

Since the callback() routine is only called when the Arduino sends data to ST, it really won’t be able to implement a millis()-based timer. However, you can accomplish your goal by utilizing loop() routine.

Within callback(), set a global variable = true, and another global = millis() (i.e. the current time). If switch1 is turned back on, set the first global variable = false (to abort the timer).

Within loop(), check to see if the first global variable = true AND if millis() is greater than the second global variable + 5mins. If both are true, issue the “st::receiveSmartString(“switch1 off”)” command. And, please be sure to set the first global variable = false, to prevent repeatedly calling the off command.

Thanks for your quick reply as always Dan!

That might be a little above my head, I think I’ll just use a webcore piston for now.

Thanks again!

Hi Rob

I’m interested in adding a reed switch to confirm the ‘open’ state of the garage doors. I wonder, did you manage to add the line of code for this? If so, is it the second line of code you used? I like the idea of Dan’s code as it is (showing opening and closing) but with the addition of ‘Open’.

Thanks in advance,



Unfortunately, no I did not get the code working. We sold our home, and our new home has a built in WiFi connection.



Is there any reports of Wemos D1 not working?
I got the code (servo) up and running.

The serial monitor says Connecting to WiFi, and show me the IP. And signal strengt - 54db

But on the next line it says disable WiFi hotspot.
That is normal?

Arduino indicate it’s online, but my Router is not showing the IP as connected.

And then also no child device.

Not so sure why, I will try another board.
I’m now using Wemos D1.

Yes, that is normal.

Try using a PING command on another computer to see if the Arduino is online.

Verify the network is behaving first. Then go back through the ResdMe instructions, line by line verifying you didn’t miss a step. Power cycling your asT hub may help as well.

Many use the Wemos D1 successfully.