Announcing the "ST_Anything" Arduino/ThingShield Project

Thanks. Ill give it a whirl.

Dan,
Do you have a groovy example of how I can accumulate the pulses?

thanks,

chin

You’ll want to use ‘state’ to create a variable inside the DTH to act as an accumulator.

state.totalGallons = state.totalGallons + value

But, you cannot accumulate forever. You’ll need to reset the value periodically (daily, weekly, monthly) to avoid overflow.

state.totalGallons = 0

Of course, you have to first scale the raw ‘value’ into the correct units (.e.g gallons) by performing some type of linear conversion.

Dan,
Am I on the right track here?

metadata {
definition (name: “Child Power Meter”, namespace: “ogiewon”, author: “Daniel Ogorchock”) {
capability “Energy Meter”
capability “Power Meter”
capability “Sensor”
command “reset”

	attribute "lastUpdated", "String"

	command "generateEvent", ["string", "string", "string"]
}

simulator {
}    
preferences {
		section("Prefs") {
		input "pulseFactor", "number", title: "pulse to Gallons factor", description: "Multipler to convert pulse to Gallons", range: "*..*", displayDuringSetup: false
	}
}

tiles(scale: 2) {
	multiAttributeTile(name: "power", type: "generic", width: 6, height: 4, canChangeIcon: true) {
		tileAttribute("device.power", key: "PRIMARY_CONTROL") {
			attributeState("default", label: '${currentValue}', unit:"Gallons/min", defaultState: true)
		}
		tileAttribute("device.lastUpdated", key: "SECONDARY_CONTROL") {
				attributeState("default", label:'    Last updated ${currentValue}',icon: "st.Health & Wellness.health9")        
        }
	}
    valueTile("state.totalGallons", "state.totalGallons", decoration: "flat") {
		state "default", label:'Consumed Gallons'
	}

}    

}

def generateEvent(String name, String name2, String value) {
log.debug(“Passed values to routine generateEvent in device named $device: Name - $name - Value - $value”)
def offsetValue = Math.round((Float.parseFloat(value))*100.0)/100.0d
offsetValue = offsetValue / pulseFactor
state.totalGallons = state.totalGallons + offsetValue

// Update device
sendEvent(name: name, value: (String)offsetValue)
sendEvent(name: name2, value: (String)state.totalGallons)

// Update lastUpdated date and time
def nowDay = new Date().format("MMM dd", location.timeZone)
def nowTime = new Date().format("h:mm a", location.timeZone)
sendEvent(name: "lastUpdated", value: nowDay + " at " + nowTime, displayed: false)

}

def installed() {
}

When copying and pasting code into the forum, please be sure to finish by highlighting all of your code, then click the Preformatted Text menu button that looks like ‘</>’. This will make your code readable and allow others to successfully copy and paste it.

As for your code, it is a decent start, but it has some issues:

There is no need to change the number of arguments being passed into ‘generateEvent()’. Doing so will actually totally break the code. That function is called by the Parent Device to pass in new data. You will be accumulating your water flow into a variable that is persisted within the Child Device only.

I do not see where you’ve added another Tile to display the accumulated ‘energy’ value. You’re going to want to use the ‘energy’ attribute to hold your accumulated value. To do that, you’d want to change your sendEvent() lines to be something like:

// Update device
sendEvent(name: name, value: offsetValue)
sendEvent(name: "energy", value: state.totalGallons)

Dan,
Thanks. I’m noob here. Learning the groovy with this project.

thanks.

Chin

Dan,
It seems to be working. I added another multiAttributeTile to show the total Gallons. I also added a reset tile to reset the totalGallons. However, I want to display when the reset happened. So instead of showing the last updated, I want to show days/hrs since it was reset. Do you know how it can be done?

	tiles {       
        multiAttributeTile(name: "power", type: "generic", width: 6, height: 4, canChangeIcon: true) {
			tileAttribute("device.power", key: "PRIMARY_CONTROL") {
				attributeState("default", label: '${currentValue}', unit:"Gallons/min", defaultState: true)
			}
 			tileAttribute("device.lastUpdated", key: "SECONDARY_CONTROL") {
    				attributeState("default", label:'    Last updated ${currentValue}',icon: "st.Health & Wellness.health9")        
            }
		}
        multiAttributeTile(name: "energy", type: "generic", width: 6, height: 4, canChangeIcon: true) {
			tileAttribute("device.energy", key: "PRIMARY_CONTROL") {
				attributeState("default", label: '${currentValue}', unit:"Gallons", defaultState: true)
			}
 			tileAttribute("device.lastUpdated", key: "SECONDARY_CONTROL") {
    				attributeState("default", label:'    Last updated ${currentValue}',icon: "st.Health & Wellness.health9")        
            }
		}

		standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat") {
			state "default", label:'reset Gallons', action:"reset"
		}
		standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat") {
			state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
		}
.
.
.
def reset() {
	return [
		state.totalGallons = 0
	]
}

Dan,
I figured out how to show the lastReset. Ignore that request.

thanks,

Chin

1 Like

Begging pardon if this has been addressed (also consider that I am quite noobish and stumbling in the dark a fair bit here on ALL things related). To be fair, I did research the thread quite a bit, but it’s quite massive and I did a fair amount of outside Googling and whatnot.

Fried my only Mega the other day. (Like I said, noobish and stumbling). Don’t ask. Complete rookie mistake. OK, fine. I set the thing down on something metal while it was powered up. In my defense, I didn’t think it was metal.

Anyway…I’ve continued fiddling with an UNO on this, more or less just to keep fiddling. The more fiddling, the more learning.

Anyway, I got to the point of attempting to test compile and send a sketch. Using the Mega/8266 wifi combo sketch.
It failed. ‘Serial’ not detected in this scope.
If I’m following all this right…
It looks like that’s because pins 18 and 19 on the Mega act as an additional high speed UART TX/RX.
I resaved the original skech with a new name (following instructions to maintain a ‘pure’ sketch) and did a simple search and replace on Serial1.begin with Serial.begin.

Failed on size. Commented out a bunch of devices and it appears compile.

Basically, other than the PITA of making sure nothing’s connected to the TX/RX pins on the Uno when uploading sketches and such, I should be able to use those 0/1 (RX/TX) respectively, right? Instead of 18 and 19? And there’s no comparable “Serial.1” on the UNO. Just “Serial” at 0/1…but they do essentially the same thing.

I have no problem with picking up another Mega. Easier for my fat fingers. Just wondering if my understanding here is correct. I’m not trying to do much with this. All I’m looking to do is be able to read a switch position and fire a relay. Just using the Arduino to do that heavy lifting and using the 8266 to do the wi-fi’ing.

Oh…and much respect and praise for what you’ve done with all this!

1 Like

Make you life super easy and just buy a NodeMCU ESP8266 board. No need for an Arduino UNO or MEGA at all. It has all of the IO you’ll need for a simple project.

https://www.amazon.com/HiLetgo-Internet-Development-Wireless-Micropython/dp/B010O1G1ES/ref=sr_1_3?ie=UTF8&qid=1523478956&sr=8-3&keywords=nodemcu+esp8266

If you’re going to use WiFi, the ESP8266 is by far the most stable WiFi platform that I have used. Just be sure to use the v2.3 ESP8266 Board support package as the new v2.4/2.4.1 version has a big memory leak in it. This is not in the ST_Anything code.

Trying to get an UNO or MEGA to work with the ESP01 is not a good noob project. The UNO only has 2KB of RAM, so it is difficult to get the code small enough. Also, you really need the MEGA’s extra HW UARTs to communicate to the ESP01 due to speed requirements. Again - DON"T DO IT! The ESP01 as a WiFi dongle has NEVER worked very well in my testing.

BTW - this thread is pretty old so you may want to keep an eye on the newer thread at

How does one get debug info? I’m assuming after flashing to my wemos d1 mini I should see some output on the com?

Yes, in the Arduino IDE Serial Monitor window, you will see debug. Make sure you set the Serial Monitor window baud-rate to 115200.

Ok let me try re-uploading my code again and seeing if I get any output this time

Hey All,

Has anyone been able to use the water sensor on a digital pin? I’ve got an esp-01 that I’m tryina use as a combo water/temp sensor. I’ll assign the water sensor D0 in the IDE, it’ll show up as a child device when setup in smart things, but when watching the serial console the esp ignores the pin if it goes high or low. This happens on the nodemcu as well (if I wanted to make two water sensors for example). I dont need the analog, its connected to a water sensing board with digital output and ajustable threshold.

The Water Sensor ST_Anything class only supports Analog inputs currently. It wouldn’t be too hard to modify a copy of the IS_Contact sensor class to do what you’re wanting.

1 Like

I have a couple of questions, but first I’d like to say THANK YOU! to Dan and Daniel for all their hard work on this project! awesome stuff!

I am playing around with ST_Anything on an ESP8266 nodeMCU board. I currently have 4 DS18B20 temperature sensors and a capacitive water sensor to keep an eye on my boat when it is stored outdoors over the winter. I basically have a few battery heat blankets (made for the purpose, NEVER use a household heating pad or bed style blanket for this! you WILL burn your boat down!) to monitor some key spots that I don’t want to freeze and to make sure water / snow melt isn’t leaking in. The water sensor gives an analog out, and I added a line of code to the water sensor .cpp file that posts the ADC value to the “recently” tab while preserving the “wet. dry” indication. I wanted to see an actual number so I could get a feel for how the water level on the sensor changes the value if I need to make any adjustments and dragging a laptop outside is a pain. I simple added another line that sends the raw m_nSensorValue as a string rather than doing the if/then on it.

Usually you would have all the DS18B20’s sharing a single pin as they all should have unique addresses from the factory. I see that you have the capability for multiple sensors on the same bus by reading the header file but I have them all on their own pins because I couldn’t figure out how to modify the code in the sketch to implement this. Not to beat on you, because I can’t claim to be the comment king of coding and you’re giving your time and energy for free, but commenting your code helps so much for the rest of us! So I guess is there some example code I missed on how this is done or could you please post some?

Also can someone point me to a post on how to run multiple ESP8266’s with ST_Anything, I’ve seen it mentioned that it is possible, but I can’t find the post explaining how to do it. I guess the fact you add a MAC address in the parent device setup tab for one device is throwing me. Do you add more device handlers or a comma in there between MACs or what? I would really like to make my own garage door controller that I can trust not to open on its own when I’m away without better layers of authentication than the commercial products already out there. I think I can leverage this project to do that since it allows for some “outside of smartthings” processing. I’ve had outdoor lights come on during the day and false sensor trips too many times to trust smarththings with something like the garage door…

And finally - Smartthings is being changed. I honestly haven’t been keeping up very closely, but I did notice somewhere that this project will only work with “classic” - Is this still the case and are there any plans to update ST_Anything to stay alive should be all be suddenly forced to move to the new app?

-Ryan

Please see this project I documented a few years ago where I have 2 temp sensors on the same pin. You have to first get the sensor serial number of each probe as documented in this post:

Specifically:

Then in your sketch you will address them:
DeviceAddress freezerProbe = { 0x28, 0xFF, 0x17, 0x99, 0x01, 0x15, 0x02, 0x13 };
DeviceAddress fridgeProbe = { 0x28, 0xFF, 0xD3, 0x6D, 0x01, 0x15, 0x02, 0x51 };

FYI, you may find much more up to date information in my newer ST_Anything thread at

Within each .cpp/.h file inside the various …Arduino\libraries\ST_Anything… folders, you will find detailed comments/documentation for the use of each of these C++ classes/objects. For example, from the top of PS_DS18B20_Temperature.cpp file, you will find the following which details the usage of this class.

//			  For Example:  st::PS_DS18B20_Temperature sensor1(F("temperature1"), 120, 0, PIN_TEMPERATURE, false); (for a single sensor)
//                          st::PS_DS18B20_Temperature sensor1(F("temperature"), 120, 0, PIN_TEMPERATURE, false, 10, 3); (for 3 sensors)
//
//			  st::PS_DS18B20_Temperature() constructor requires the following arguments
//				- String &name - REQUIRED - the name of the object - either "temperature1" for a single sensor, or "temperature" for multiple sensors
//				- 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 for the One-Wire DS18B20 sensor conenction
//				- bool In_C - OPTIONAL - true = Report Celsius, false = Report Farenheit (Farentheit is the default)
//				- byte resolution - OPTIONAL - DS18B20 sensor resolution in bits.  9, 10, 11, or 12.  Defaults to 10 for decent accuracy and performance
//				- byte num_sensors - OPTIONAL - number of OneWire DS18B20 sensors attached to OneWire bus - Defaults to 1

If you simply wanted the voltage/value from the sensor, I would recommend that you simply use the ST_Anything’s PS_Voltage voltage device. You could use this in addition to the PS_Water device. Both could read data from the same analog pin.

Running multiple copies is very simple… Just manually add another new ST_Anything Parent Device via the ST Web IDE. Then, in your phone’s app you will see the second parent, which will require you to configure the MAC address, TCP/IP address, and port like you did for the first one. Just use the unique MAC and TCP/IP address from the second ESP8266.

Samsung/SmartThings future plans are very unclear. I have no idea if any of this will work with the new app in the future. I have ported all of ST_Anything to run on Hubitat. In fact, I have moved about 99% of my devices over to Hubitat. I prefer local processing. So, at least you’ll have that platform as an option should ST decide to further alienate the DIY/Maker community.

One more tip - The Arduino MEGA ST_Anything examples demonstrate a vast number of example devices from ST_Anything. You will still start with an ESP8266 example, but can copy and paste the device definitions from the MEGA’s sketch into the ESP8266 sketch. At least it helps demonstrate the usage of these various devices.

And, as always… I’d love for someone to step up and help improve the documentation! :wink:

1 Like

Thanks so much for pointing out the things I obviously missed!!!

I have been a bit pressed for time and admittedly didn’t read as close as I should have.

Thanks again.

-Ryan

1 Like

Rick,
I just came across this thread. BTW, the link to appnote is no good.

Are you saying you can connect 10k resistor from I/O pin to ground and connect I/O pin directly to alarm system pin and the alarm system will still work while letting Mega2560 sense whether alarm pin is on or off?

Does I/O pin pull-up resistor need to be enabled in your solution as source of current?

Are you assuming alarm circuit is simple normally open or normally closed switch in parallel with 10k resistor?

And this avoids need for voltage divider and transistor?

Thanks.