ST_Anything - Changing the switch state for high level relay and issue with additional buttons in the app

First off thanks in advance for anyone who can help me out with these small issues!

I am using high level relays to control two light circuits with an ESP01 and everything works great but the lights states are inverted. ie when they are on they show off and vise versa. Is see it commented in the code it is for a low level relay so how can I change this? I tried changing the below from LOW to HIGH which did not work and also tried LOW, false and this also didn’t work. Do I need to adjust anything in the ST_Anything library or can I do it right in my sketch?

static st::EX_Switch executor1(F(“switch1”), PIN_Daylight, LOW, true);
static st::EX_Switch executor2(F(“switch2”), PIN_Nightlight, LOW, true);

Also when I added the device to ST it added an extra button so I now have two “switch 1” and one “switch 2”. Can I just delete the duplicate child or will this mess everything up? And lastly, is there anyway I can prevent both switches from going on? I want one or the other on or both off. I would like to do this in the arduino sketch so it is not possible for both circuits to be on at the same time. MY voltage regulator cant handle both circuits on at once.

//******************************************************************************************
//  File: ST_Anything_Multiples_ESP01WiFi.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 ESP8266-01 (ESP-01) 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's WiFi.
//    
//            ST_Anything_Multiples implements the following ST Capabilities in multiples of 1 as a demo of what is possible with a single ESP-01
//              - 1 x Contact Sensor device (used to monitor magnetic door sensors)
//              - 1 x Motion devices (used to detect motion)
//
//  Note:  The tiny ESP-01 only has 2 GPIO pins, so this example is somewhat limited.  Use the ST_ANything_Multiples_ESP8266WiFi.ino example to see 
//         what else is possible.  As long as you only try using 2 pins, you can use them for whatever you'd like.
//
//  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-21  Dan Ogorchock  New example specifically for running everythin on a ESP-01 (no Arduino required!)
//    2017-04-24  Dan Ogorchock  Updated for use with new v2.5 Parent/Child Device handlers
//    2018-02-09  Dan Ogorchock  Added support for Hubitat Elevation Hub
//
//******************************************************************************************
//******************************************************************************************
// 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_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 <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
//******************************************************************************************

#define PIN_Daylight              0
#define PIN_Nightlight            2

//******************************************************************************************
//ESP8266 WiFi Information
//******************************************************************************************
String str_ssid     = "Internet";                           //  <---You must edit this line!
String str_password = "password";                   //  <---You must edit this line!
IPAddress ip(x, x, x, x);       //Device IP Address       //  <---You must edit this line!
IPAddress gateway(x, x, x, x);    //Router gateway          //  <---You must edit this line!
IPAddress subnet(x, x, x, x);   //LAN subnet mask         //  <---You must edit this line!
IPAddress dnsserver(x, x, x, x);  //DNS server              //  <---You must edit this line!
const unsigned int serverPort = 8090; // port to run the http server on

// Smartthings / Hubitat Hub TCP/IP Address
IPAddress hubIp(x, x, x, x);    // smartthings/hubitat hub ip //  <---You must edit this line!

// SmartThings / Hubitat Hub TCP/IP Address: UNCOMMENT line that corresponds to your hub, COMMENT the other
const unsigned int hubPort = 39500;   // smartthings hub port
//const unsigned int hubPort = 39501;   // hubitat 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 ESP-01
  //  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
 
  //Interrupt Sensors 

  //Executors
  static st::EX_Switch executor1(F("switch1"), PIN_Daylight, LOW, true);
  static st::EX_Switch executor2(F("switch2"), PIN_Nightlight, 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 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
  //*****************************************************************************

  //*****************************************************************************
  //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();
}

When you have a question like this, you’ll always get the fastest and most accurate answers if you ask in the author thread for that particular code. The author will be automatically notified when a new post is added to the thread, and other people using the same code may also be able to help.

If you think your topic is going to be too long to add to the author thread, just start a detail thread like the one you have here but ask your individual question in the author thread with a link to the detail thread for follow up. :sunglasses:

In this case, ask your question in the following thread:

Also, speaking of not being able to handle everything… :nauseated_face:

A number of community members, including me, rely on text to speech software. Please put code in code blocks, otherwise we have to listen to the entire unintelligible thing read out to make sure we don’t miss some other comment in your post. Thanks!

1 Like

At the top of every ST_Anything devices class module (.h and .cpp files) you will find the documentation, which explains how to invert the logic of the EX_Switch class.

//  Summary:  EX_Switch is a class which implements the SmartThings "Switch" device capability.
//			  It inherits from the st::Executor class.
//
//			  Create an instance of this class in your sketch's global variable section
//			  For Example:  st::EX_Switch executor1(F("switch1"), PIN_SWITCH, LOW, true);
//
//			  st::EX_Switch() constructor requires the following arguments
//				- String &name - REQUIRED - the name of the object - must match the Groovy ST_Anything DeviceType tile name
//				- byte pin - REQUIRED - the Arduino Pin to be used as a digital output
//				- bool startingState - OPTIONAL - the value desired for the initial state of the switch.  LOW = "off", HIGH = "on"
//				- bool invertLogic - OPTIONAL - determines whether the Arduino Digital Output should use inverted logic

I can assure you that changing the last parameter does work to change from an Active High to an Active Low relay.

This duplicate is an unfortunate consequence of the delays in the ST Cloud. You can delete the one that does not actually work. If doing so screws things up, just delete the Parent Device (not the groovy DTH code) and manually recreate it again.

Are you an Arduino Programmer? If so, you should be able to add some simple logic to the sketch’s “callback()” function. In this callback() routine, you can get notified immediately when either of the two switches are turned on, and then turn off the other one. If you look through the main ST_Anything thread, you will see some examples of how to do this.

Hopefully this will help get you started. As @JDRoberts mentioned, posting in the main ST_Anything thread will get you more assistance from other ST_Anything users. I am actually more focused on Hubitat these days, but I still check into this community fairly often. If JD Roberts had not tagged me though, it is doubtful that I would have ever noticed your thread.

1 Like

@JDRoberts Thanks for the explanation and sorry for posting in the wrong place!

@Ogiewon Thank you so much for the help with this and for creating ST_Anything!!! Sorry, I should have looked in the .CPP and .H files first but didn’t want to accidentally mess anything up! I am a fairly new to coding in Arduino and pretty much just piece together what I can. I do have SOME programming background so I can follow the code at least. Ill look through the ST_Anything thread to learn how to ensure only one switch is on at a time. I will have to look into Hubitat I’m not even sure what that is.

1 Like

Hubitat is a different home automation hub which doesn’t have a cloud, it runs everything locally except for connections to third-party services like IFTTT or Alexa. . It supports SmartThings groovy code, so some people who have smartthings Use both in order to take advantage of the local operation characteristics of Hubitat. And some people who leave smartthings because they are frustrated with cloud processing go to Hubitat as an alternative.

2 Likes

Interesting, I never heard of it but it looks like a nice hub. Ill have to do a little more research, thanks a lot!

https://community.smartthings.com/t/hubitat-elevation-hub-home-automation-that-is-local/117107

1 Like

@ogiewon

I looked through the thread you mentioned and below is what I took from it. It works but does not respond as fast as I would like. There is a delay where both lights can be on at the same time for a split second before the msg is received and the other lights pin is brought to LOW. Is there a better way to do this than what I have below?

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
  if (msg == "switch1 on") digitalWrite(PIN_Nightlight, LOW);
  if (msg == "switch2 on") digitalWrite(PIN_Daylight, LOW);
  
  //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
}

I would love a more stable hub and one that runs everything locally but I don’t have too many issues with ST. I have the Habitat hub on my Amazon wish list now and may pick it up when it goes on sale to check it out. What is everyone’s thoughts on the Vera hub? My buddy has it and swears by it but it is no where near as easy to work with as ST.

Right now, all low-cost hubs have pluses and minuses, they all have a rating around 3.5 stars on Amazon, and there is migration in all directions. Just depends on finding the one that best meets your own specific needs. :sunglasses:

There are several threads already in the forum comparing various alternatives.

That’s the problem, sometimes I don’t even know what I need or if there is a better native solution out there! I normally just stick with what ever is the most popular with hopes that there will be a lot more information and it will have the most device integrations. That’s more or less why I went with ST originally, it seems to work with the most devices and the community is extremely helpful! I just wish I was an expert with circuits and coding so I could complete projects a lot faster hahaha.

1 Like

Yes, there is a better way. You can actually register another callback function to catch the commands coming from ST, instead of those being sent to ST.

I describe this capability here:

So, using this design, you would add the second callbackRcvd() function as follows

Create the following new callbackRcvd() function immediately above or below the existing callback() function in your sketch. Note that we should never manipulate the GPIO pins directly. We want ST_Anything to take care of those for us to make sure SmartThings is being kept up to date. So I modified your logic below.

void callbackRcvd(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
  if (msg == "switch1 on") st::receiveSmartString("switch2 off");
  if (msg == "switch2 on") st::receiveSmartString("switch1 off");
  
  //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
}

Snippet from your sketch’s setup() routine - note the second callbackRcvd function where you have to register the new callbackRcvd function.

  //*****************************************************************************
  //Initialize the "Everything" Class
  //*****************************************************************************

  //Initialize the optional local callback routine (safe to comment out if not desired)
  st::Everything::callOnMsgSend = callback;
  st::Everything::callOnMsgRcvd = callbackRcvd;

And finally, since you want to make sure the two outputs are never both on at the same time, you’re going to need to modify the Everything.cpp file as follows. Note, I had to move the call to the callOnMsgRcvd function to earlier in the sequence to make sure we turn off the other switch device before turning on the new one.

	void receiveSmartString(String message)
	{
		message.trim();
		if(Everything::debug && message.length()>1)
		{
			Serial.print(F("Everything: Received: "));
			Serial.println(message);
		}

		if(Everything::callOnMsgRcvd!=0)
		{
			Everything::callOnMsgRcvd(message);
		}
		
		if (message == "refresh")
		{
			Everything::refreshDevices();
		}
		else if (message.length() > 1)		//ignore empty string messages from the ST Hub
		{
			Device *p = Everything::getDeviceByName(message.substring(0, message.indexOf(' ')));
			if (p != 0)
			{
				p->beSmart(message);	//pass the incoming SmartThings Shield message to the correct Device's beSmart() routine
			}
		}
		
//		if(Everything::callOnMsgRcvd!=0)
//		{
//			Everything::callOnMsgRcvd(message);
//		}

	}

3 Likes

The Hubitat Elevation hub is on sale right now for $85 directly from Hubitat.com. This sale is only for this holiday weekend. This is the lowest price I have ever seen it. I actually already have two Hubitat Elevation hubs - one for Production, and one as a test and development platform as I like to write code. My family appreciates that I don’t screw up the production hub with my development!

1 Like

@ogiewon

You are amazing, thank you so much for the help and putting up with my lack of knowledge! Ill try this after I clear some snow from a storm…I think I will pick one up then. From what I saw in the thread @JDRoberts posted it seems like a lot of people are happy with it and it seems very stable. Thanks again and hopefully I can return the favor in the future! If you ever need someone to test code or whatever let me know!

1 Like