Garden Sprinkler Version 2

After running a Raspberry Pi based sprinkler from my workshop, I got a little worried about all the dirt, grime and sawdust covering my Pi and clogging the cooling fan. I decided to split the functions between an Arduino Uno and a Raspberry Pi running Node Red and MQTT. The Arduino is running in the hostile environment of the workshop and the Pi runs in my air conditioned Ham Shack on a UPS.

I consider the Arduino a stupid device that only listens for commands from the Pi and responds by turning water valves on and off. When a command is received, an acknowledgement is sent back to the Pi. When a command is received to turn on a valve, a timeout timer starts that will cause the valves to be turned off if a turn off command is not received in a reasonable time period. I run my sprinkler a maximum of 15 minutes at a time and the timeout will reset the sprinkler after 21 minutes. I do this in case communications is lost between a turn on and turn off command. Other than the timeout timer, the Arduino makes no decisions on its own.

The Arduino has an Ethernet shield and an interface to a relay module. Here is the code running on the Arduino. Change the code to match yout network requirements and desired I/O pins connected to the relay board.

Click here to see the Arduino sketch: ↓ ↓ ↓ ↓ ↓

#include <Ethernet.h>

#include <MQTT.h>

#include <Wire.h>

//#include "Adafruit_MCP9808.h"

int masterPin = 8;

int zone1Pin = 7;

int zone2Pin = 4;

byte mac[] = {0x00, 0x50, 0x56, 0xFE, 0x09, 0x97};

byte ip[] = {192, 168, 254, 97}; // <- change to match your network

//Adafruit_MCP9808 tempsensor = Adafruit_MCP9808();

//String temp_str;

//char temp[50];

EthernetClient net;

MQTTClient client;

unsigned long startMillis;

unsigned long currentMillis;

const unsigned long timeout = 1260000; // 21 minutes

char timerstarted = '0';

void connect() {

//Serial.print("connecting...");

while (!client.connect("arduino", "try", "try")) {

//Serial.print(".");

delay(1000);

}

//Serial.println("\nconnected!");

client.subscribe("garden/#");

// client.unsubscribe("/hello");

}

void messageReceived(String &topic, String &payload) {

// Serial.println("incoming: " + topic + " - " + payload);

if (topic == "garden/valve/master") {

Serial.println("incoming: " + topic + " - " + payload);

if (payload == "1") {

timerstarted = '1';

startMillis = millis(); // start timeout counter

digitalWrite(masterPin, LOW);

client.publish("gardenuino/masterack", "1");

} else {

timerstarted = '0';

digitalWrite(masterPin, HIGH);

client.publish("gardenuino/masterack", "0");

}

}

if (topic == "garden/valve/zone1") {

Serial.println("incoming: " + topic + " - " + payload);

if (payload == "1") {

digitalWrite(zone1Pin, LOW);

client.publish("gardenuino/zone1ack", "1");

} else { digitalWrite(zone1Pin, HIGH);

client.publish("gardenuino/zone1ack", "0");

}

}

if (topic == "garden/valve/zone2") {

Serial.println("incoming: " + topic + " - " + payload);

if (payload == "1") {

digitalWrite(zone2Pin, LOW);

client.publish("gardenuino/zone2ack", "1");

} else { digitalWrite(zone2Pin, HIGH);

client.publish("gardenuino/zone2ack", "0");

}

}

if (topic == "garden/alive") {

client.publish("gardenuino/alive", "1");

// tempsensor.wake(); // wake up, ready to read!

// float f = tempsensor.readTempF();

// temp_str = String(f);

// temp_str.toCharArray(temp, temp_str.length() - 1);

// delay(2000);

// tempsensor.shutdown_wake(1);

// client.publish("garden/temperature", temp);

}

}

void setup() {

pinMode(masterPin, OUTPUT);

pinMode(zone1Pin, OUTPUT);

pinMode(zone2Pin, OUTPUT);

digitalWrite(masterPin, HIGH);

digitalWrite(zone1Pin, HIGH);

digitalWrite(zone2Pin, HIGH);

Serial.begin(115200);

Ethernet.begin(mac, ip);

client.begin("192.168.254.101", net);

client.onMessage(messageReceived);

connect();

Serial.println("I am here");

//if (!tempsensor.begin(0x18)) {

// Serial.println("Couldn't find MCP9808! Check your connections and verify the address is correct.");

// while (1);

// }

// Serial.println("Found MCP9808!");

// tempsensor.setResolution(3); // sets the resolution mode of reading, the modes are defined in the table bellow:

}

void loop() {

if (timerstarted == '1')

{

currentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)

if (currentMillis - startMillis >= timeout) //test whether the period has elapsed

{

// turn off all the valves

digitalWrite(masterPin, HIGH);

digitalWrite(zone1Pin, HIGH);

digitalWrite(zone2Pin, HIGH);

Serial.println("\ntimed out!");

timerstarted = '0';

client.publish("gardenuino/valvetimeout", "1");

}

}

client.loop();

if (!client.connected()) {

connect();

}

}

// Forgive me for not cleaning up the indentation in the code. It works for me, that's all I'll say.


Click here to see the Node Red flow : ↓ ↓ ↓ ↓ ↓

(Can be imported into Node Red)

[{"id":"c88275b9.e16f08","type":"timerswitch","z":"5a966310.e46a0c","name":"Zone1 Timer","ontopic":"","offtopic":"","onpayload":"1","offpayload":"0","disabled":false,"schedules":[{"on_h":"08","on_m":"00","on_s":"00","off_h":"08","off_m":"15","off_s":"00","valid":true}],"x":110,"y":320,"wires":[["ece957a9.1bc8e8"]]},{"id":"fe49c899.486cf8","type":"mqtt out","z":"5a966310.e46a0c","name":"garden/disable","topic":"garden/disable","qos":"2","retain":"true","broker":"e0ba888b.b9d328","x":600,"y":60,"wires":[]},{"id":"10855c88.1a9fe3","type":"function","z":"5a966310.e46a0c","name":"flow.set enabled","func":"flow.set(\"disabled\",msg.payload);\nreturn msg;","outputs":1,"noerr":0,"x":600,"y":120,"wires":[[]]},{"id":"ff2d1e23.c4cd9","type":"mqtt in","z":"5a966310.e46a0c","name":"","topic":"garden/disable","qos":"2","broker":"e0ba888b.b9d328","x":120,"y":160,"wires":[["84395796.014f58"]]},{"id":"b1d6aabd.4b6938","type":"comment","z":"5a966310.e46a0c","name":"System Disable","info":"","x":100,"y":20,"wires":[]},{"id":"84395796.014f58","type":"function","z":"5a966310.e46a0c","name":"String to Num","func":"if (msg.payload == \"1\") { \n msg1 = { payload:1 };\n } else {\n msg1 = { payload:0 };\n }\nreturn [msg1];","outputs":1,"noerr":0,"x":320,"y":160,"wires":[["d6f7b0a9.35984","10855c88.1a9fe3"]]},{"id":"cd7c326a.901c","type":"function","z":"5a966310.e46a0c","name":"Toggle \"Disable\"","func":"var msg1 = flow.get(\"disabled\")|| \"\";\nif (msg1 == 1){\n flow.set(\"disabled\",0);\n msg1 = { payload:0};\n}else{\n flow.set(\"disabled\",1);\n msg1 = { payload:1};\n}\nreturn [msg1];","outputs":1,"noerr":0,"x":320,"y":60,"wires":[["fe49c899.486cf8"]]},{"id":"4f0d8416.bbcfec","type":"ui_button","z":"5a966310.e46a0c","name":"","group":"863689d4.9f3c88","order":2,"width":"2","height":"2","passthru":false,"label":"","tooltip":"","color":"red","bgcolor":"#333333","icon":"power_settings_new","payload":"1","payloadType":"num","topic":"","x":90,"y":60,"wires":[["cd7c326a.901c"]]},{"id":"d6f7b0a9.35984","type":"ui_gauge","z":"5a966310.e46a0c","name":"Disabled","group":"863689d4.9f3c88","order":1,"width":"2","height":"2","gtype":"donut","title":"Disabled","label":"","format":"{{value}}","min":0,"max":"1","colors":["#00b500","#e6e600","#ff0000"],"seg1":"","seg2":"","x":580,"y":160,"wires":[]},{"id":"437ffb3b.f97fb4","type":"comment","z":"5a966310.e46a0c","name":"Timers","info":"","x":70,"y":260,"wires":[]},{"id":"6690d2b0.10768c","type":"function","z":"5a966310.e46a0c","name":"Rainy Day?","func":"var wet = msg.payload[\"weather\"];\nwet = wet.toLowerCase();\n\nif (wet == \"rain\"){\n msg.payload = 1;\n flow.set(\"raining\",msg.payload);\n return msg;\n}","outputs":1,"noerr":0,"x":610,"y":720,"wires":[["3dd7e19b.5e7ebe"]]},{"id":"3dd7e19b.5e7ebe","type":"mqtt out","z":"5a966310.e46a0c","name":"garden/rain","topic":"garden/rain","qos":"2","retain":"true","broker":"e0ba888b.b9d328","x":830,"y":720,"wires":[]},{"id":"5cd82c0f.e18cf4","type":"inject","z":"5a966310.e46a0c","name":"Query Every 10 Minutes","topic":"","payload":"1","payloadType":"num","repeat":"600","crontab":"","once":true,"onceDelay":"1","x":190,"y":720,"wires":[["33e4c091.a93d4"]]},{"id":"6f53601d.49e6d","type":"function","z":"5a966310.e46a0c","name":"Rainy Day Reset","func":"flow.set(\"raining\",0);\nreturn msg;","outputs":1,"noerr":0,"x":850,"y":760,"wires":[[]]},{"id":"f50de06c.6bfc1","type":"comment","z":"5a966310.e46a0c","name":"Rain Override","info":"","x":70,"y":700,"wires":[]},{"id":"53e05615.b41f38","type":"inject","z":"5a966310.e46a0c","name":"Reset Rain at 8:00PM","topic":"","payload":"0","payloadType":"num","repeat":"","crontab":"00 20 * * *","once":false,"onceDelay":0.1,"x":570,"y":800,"wires":[["3dd7e19b.5e7ebe","6f53601d.49e6d"]]},{"id":"bfc61232.98284","type":"ui_button","z":"5a966310.e46a0c","name":"Rain Reset","group":"928b09a9.067248","order":8,"width":"2","height":"2","passthru":false,"label":"Rain RST","tooltip":"","color":"","bgcolor":"#333333","icon":"cloud_off","payload":"0","payloadType":"num","topic":"","x":610,"y":760,"wires":[["6f53601d.49e6d","3dd7e19b.5e7ebe","4af678b1.144b98"]]},{"id":"c44c7e51.104c1","type":"ui_text","z":"5a966310.e46a0c","group":"6297bca7.d83e54","order":1,"width":"4","height":"2","name":"Garden Weather Text","label":"","format":"{{payload.weather}}<br/>Temp {{(payload.tempc * 9/5 + 32).toFixed(1)}}&deg;F<br/>Humidity {{payload.humidity}}%<br/>Clouds {{payload.clouds}}%","layout":"col-center","x":640,"y":680,"wires":[]},{"id":"33e4c091.a93d4","type":"openweathermap","z":"5a966310.e46a0c","name":"Local Weather","wtype":"current","lon":"-83.44","lat":"34.11","city":"","country":"","language":"en","x":400,"y":720,"wires":[["6690d2b0.10768c","c44c7e51.104c1"]]},{"id":"ece957a9.1bc8e8","type":"function","z":"5a966310.e46a0c","name":"Overide","func":"var rain = flow.get(\"raining\")|| \"\";\nvar disable = flow.get(\"disabled\")|| \"\";\nif (rain === 1 || disable === 1){\n msg.payload = 0;\n}\nreturn msg;","outputs":1,"noerr":0,"x":300,"y":320,"wires":[["ecec1734.898728","3993d411.66003c"]]},{"id":"1c1955b4.2cc83a","type":"mqtt out","z":"5a966310.e46a0c","name":"","topic":"garden/valve/zone1","qos":"2","retain":"false","broker":"e0ba888b.b9d328","x":690,"y":280,"wires":[]},{"id":"3993d411.66003c","type":"mqtt out","z":"5a966310.e46a0c","name":"","topic":"garden/valve/master","qos":"","retain":"false","broker":"e0ba888b.b9d328","x":700,"y":360,"wires":[]},{"id":"ecec1734.898728","type":"delay","z":"5a966310.e46a0c","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":480,"y":280,"wires":[["1c1955b4.2cc83a"]]},{"id":"25e25155.db97ae","type":"function","z":"5a966310.e46a0c","name":"flow.set masteron","func":"flow.set(\"masteron\",msg.payload);\nflow.set(\"timeron\",0);\nmsg.payload=flow.get(\"timeron\")|| 0;\nreturn msg;","outputs":1,"noerr":0,"x":410,"y":1460,"wires":[[]]},{"id":"f1417b6f.3b1008","type":"mqtt in","z":"5a966310.e46a0c","name":"Master On","topic":"garden/valve/master","qos":"2","datatype":"auto","broker":"e0ba888b.b9d328","x":120,"y":560,"wires":[[]]},{"id":"c2c1677e.4290e8","type":"inject","z":"5a966310.e46a0c","name":"1 Second Trigger","topic":"","payload":"","payloadType":"date","repeat":"1","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":880,"wires":[["8f694a9e.42fc78"]]},{"id":"8f694a9e.42fc78","type":"function","z":"5a966310.e46a0c","name":"Format Watering Time","func":"var elapsed = flow.get(\"timeron\")|| 0;\nvar total_elapsed = flow.get(\"daily_total\")|| 0;\nvar running = flow.get(\"masteron\")|| \"\";\nvar minutes = 0;\nvar seconds = 0;\nvar total_minutes = 0;\nvar total_seconds = 0;\nif (running === \"1\"){\n elapsed = elapsed + 1;\n total_elapsed = total_elapsed + 1;\n flow.set(\"timeron\",elapsed);\n flow.set(\"daily_total\",total_elapsed);\n} else {\n flow.set(\"timeron\",0);\n}\nminutes = Math.floor( elapsed / 60);\ntotal_minutes= Math.floor( total_elapsed / 60);\nseconds = elapsed - (minutes * 60);\ntotal_seconds = total_elapsed - (total_minutes * 60);\nseconds = (\"0\" + seconds).slice(-2);\ntotal_seconds = (\"0\" + total_seconds).slice(-2);\nmsg.payload= \"Watering Time \" + minutes + \":\" + seconds+\"<br/> Total Today \"+total_minutes+\":\"+total_seconds;\nreturn msg;","outputs":1,"noerr":0,"x":400,"y":880,"wires":[["e5eaccc4.5a078"]]},{"id":"89c3c8b.5fd2f38","type":"comment","z":"5a966310.e46a0c","name":"Watering Time Text","info":"","x":110,"y":840,"wires":[]},{"id":"e5eaccc4.5a078","type":"ui_text","z":"5a966310.e46a0c","group":"9403836f.e9086","order":3,"width":"4","height":"2","name":"Timer Text","label":"","format":"{{msg.payload}}","layout":"col-center","x":630,"y":880,"wires":[]},{"id":"34c15d2c.7b0bf2","type":"ui_gauge","z":"5a966310.e46a0c","name":"Rain","group":"928b09a9.067248","order":7,"width":"2","height":"2","gtype":"donut","title":"Rain","label":"","format":"{{value}}","min":0,"max":"1","colors":["#00b500","#e6e600","#ff0000"],"seg1":"","seg2":"","x":270,"y":780,"wires":[]},{"id":"c2b9bb3.53b5d48","type":"comment","z":"5a966310.e46a0c","name":"Is Garden Arduino Alive?","info":"","x":130,"y":1100,"wires":[]},{"id":"18a336d5.869789","type":"inject","z":"5a966310.e46a0c","name":"1Minute Trigger","topic":"","payload":"1","payloadType":"str","repeat":"60","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":1160,"wires":[["a94f5dae.621d4"]]},{"id":"a94f5dae.621d4","type":"mqtt out","z":"5a966310.e46a0c","name":"","topic":"garden/alive","qos":"2","retain":"false","broker":"e0ba888b.b9d328","x":370,"y":1160,"wires":[]},{"id":"70ad55e2.38d53c","type":"mqtt in","z":"5a966310.e46a0c","name":"","topic":"gardenuino/alive","qos":"2","datatype":"auto","broker":"e0ba888b.b9d328","x":140,"y":1220,"wires":[["a5000345.72cf9"]]},{"id":"a5000345.72cf9","type":"dead-man-switch","z":"5a966310.e46a0c","name":"","delay":"5","delayUnit":"minutes","x":360,"y":1220,"wires":[["51952e75.d8d2b","5450d60b.97a8d8"]]},{"id":"51952e75.d8d2b","type":"function","z":"5a966310.e46a0c","name":"","func":"//var msg1 = 0;\nif (msg.payload == \"timeout\") { \n msg1 = { payload:1 };\n } else {\n msg1 = { payload:0 };\n }\nreturn [msg1];","outputs":1,"noerr":0,"x":550,"y":1220,"wires":[["ad8dcb7a.9eff98","3ca7e2e7.e8b5de"]]},{"id":"ad8dcb7a.9eff98","type":"ui_gauge","z":"5a966310.e46a0c","name":"Ping Timeout","group":"928b09a9.067248","order":10,"width":"2","height":"2","gtype":"donut","title":"Ping Timeout","label":"","format":"{{value}}","min":0,"max":"1","colors":["#00b500","#e6e600","#ff0000"],"seg1":"","seg2":"","x":730,"y":1220,"wires":[]},{"id":"11e7d95e.5792e7","type":"ui_button","z":"5a966310.e46a0c","name":"Timeout Reset","group":"928b09a9.067248","order":12,"width":"2","height":"2","passthru":false,"label":"Reset","tooltip":"","color":"","bgcolor":"#333333","icon":"fa-check","payload":"0","payloadType":"num","topic":"","x":360,"y":1280,"wires":[["51952e75.d8d2b","a5000345.72cf9"]]},{"id":"3ca7e2e7.e8b5de","type":"debug","z":"5a966310.e46a0c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":730,"y":1260,"wires":[]},{"id":"49072a58.704564","type":"function","z":"5a966310.e46a0c","name":"Overide","func":"var rain = flow.get(\"raining\")|| \"\";\nvar disable = flow.get(\"disabled\")|| \"\";\nif (rain === 1 || disable === 1){\n msg.payload = 0;\n}\nreturn msg;","outputs":1,"noerr":0,"x":300,"y":500,"wires":[["ff1c8b1.074ad78","ba45e43e.3fc418"]]},{"id":"edbf990c.cd7f38","type":"mqtt out","z":"5a966310.e46a0c","name":"","topic":"garden/valve/zone2","qos":"2","retain":"false","broker":"e0ba888b.b9d328","x":690,"y":460,"wires":[]},{"id":"ba45e43e.3fc418","type":"mqtt out","z":"5a966310.e46a0c","name":"","topic":"garden/valve/master","qos":"","retain":"false","broker":"e0ba888b.b9d328","x":700,"y":500,"wires":[]},{"id":"ff1c8b1.074ad78","type":"delay","z":"5a966310.e46a0c","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":480,"y":460,"wires":[["edbf990c.cd7f38"]]},{"id":"5b472ba1.aa45c4","type":"timerswitch","z":"5a966310.e46a0c","name":"Zone2 Timer","ontopic":"","offtopic":"","onpayload":"1","offpayload":"0","disabled":false,"schedules":[],"x":130,"y":500,"wires":[["49072a58.704564"]]},{"id":"eb10d3a3.d644a","type":"ui_gauge","z":"5a966310.e46a0c","name":"Master Ack","group":"928b09a9.067248","order":4,"width":"2","height":"2","gtype":"donut","title":"Master Ack","label":"","format":"{{value}}","min":0,"max":"1","colors":["#00b500","#e6e600","#0000ff"],"seg1":"","seg2":"","x":610,"y":1340,"wires":[]},{"id":"f2616d4f.785e1","type":"ui_gauge","z":"5a966310.e46a0c","name":"Zone 1 Ack","group":"928b09a9.067248","order":5,"width":"2","height":"2","gtype":"donut","title":"Zone1 Ack","label":"","format":"{{value}}","min":0,"max":"1","colors":["#00b500","#e6e600","#0000ff"],"seg1":"","seg2":"","x":610,"y":1380,"wires":[]},{"id":"f79a4f76.88052","type":"ui_gauge","z":"5a966310.e46a0c","name":"Zone 2 Ack","group":"928b09a9.067248","order":6,"width":"2","height":"2","gtype":"donut","title":"Zone2 Ack","label":"","format":"{{value}}","min":0,"max":"1","colors":["#00b500","#e6e600","#0000ff"],"seg1":"","seg2":"","x":610,"y":1420,"wires":[]},{"id":"8826544c.5723e8","type":"mqtt in","z":"5a966310.e46a0c","name":"","topic":"gardenuino/masterack","qos":"2","datatype":"auto","broker":"e0ba888b.b9d328","x":160,"y":1340,"wires":[["3a558765.44eb88","25e25155.db97ae"]]},{"id":"4d038d1f.20b014","type":"mqtt in","z":"5a966310.e46a0c","name":"","topic":"gardenuino/zone1ack","qos":"2","datatype":"auto","broker":"e0ba888b.b9d328","x":160,"y":1380,"wires":[["ea47f7bc.d7a468"]]},{"id":"5e00253a.e8e48c","type":"mqtt in","z":"5a966310.e46a0c","name":"","topic":"gardenuino/zone2ack","qos":"2","datatype":"auto","broker":"e0ba888b.b9d328","x":160,"y":1420,"wires":[["e7210a6e.7f03f8"]]},{"id":"3a558765.44eb88","type":"function","z":"5a966310.e46a0c","name":"String to Num","func":"if (msg.payload == \"1\") { \n msg1 = { payload:1 };\n } else {\n msg1 = { payload:0 };\n }\nreturn [msg1];","outputs":1,"noerr":0,"x":400,"y":1340,"wires":[["eb10d3a3.d644a","2235b312.92fedc"]]},{"id":"ea47f7bc.d7a468","type":"function","z":"5a966310.e46a0c","name":"String to Num","func":"if (msg.payload == \"1\") { \n msg1 = { payload:1 };\n } else {\n msg1 = { payload:0 };\n }\nreturn [msg1];","outputs":1,"noerr":0,"x":400,"y":1380,"wires":[["f2616d4f.785e1"]]},{"id":"e7210a6e.7f03f8","type":"function","z":"5a966310.e46a0c","name":"String to Num","func":"if (msg.payload == \"1\") { \n msg1 = { payload:1 };\n } else {\n msg1 = { payload:0 };\n }\nreturn [msg1];","outputs":1,"noerr":0,"x":400,"y":1420,"wires":[["f79a4f76.88052"]]},{"id":"2235b312.92fedc","type":"debug","z":"5a966310.e46a0c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":610,"y":1300,"wires":[]},{"id":"4af678b1.144b98","type":"debug","z":"5a966310.e46a0c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":890,"y":640,"wires":[]},{"id":"6e567ce2.f90a34","type":"mqtt in","z":"5a966310.e46a0c","name":"Rain","topic":"garden/rain","qos":"2","datatype":"auto","broker":"e0ba888b.b9d328","x":110,"y":780,"wires":[["34c15d2c.7b0bf2"]]},{"id":"2348d101.ab929e","type":"ui_button","z":"5a966310.e46a0c","name":"Zone 1 PB","group":"26a8ca98.e502c6","order":1,"width":"2","height":"2","passthru":true,"label":"Zone1","tooltip":"","color":"","bgcolor":"#333333","icon":"forward_10","payload":"1","payloadType":"num","topic":"","x":130,"y":1600,"wires":[["33ee55e0.f7413a"]]},{"id":"33ee55e0.f7413a","type":"trigger","z":"5a966310.e46a0c","op1":"1","op2":"0","op1type":"str","op2type":"str","duration":"10","extend":false,"units":"min","reset":"0","bytopic":"all","name":"","x":330,"y":1600,"wires":[["9265d905.231bf8","6d4cd61d.212b08"]]},{"id":"9265d905.231bf8","type":"delay","z":"5a966310.e46a0c","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":520,"y":1640,"wires":[["346117c9.dedc28"]]},{"id":"7ec536b6.d29a48","type":"ui_button","z":"5a966310.e46a0c","name":"Zone 2 PB","group":"26a8ca98.e502c6","order":1,"width":"2","height":"2","passthru":true,"label":"Zone2","tooltip":"","color":"","bgcolor":"#333333","icon":"forward_10","payload":"1","payloadType":"num","topic":"","x":130,"y":1700,"wires":[["2c4c140a.4eb4cc"]]},{"id":"2c4c140a.4eb4cc","type":"trigger","z":"5a966310.e46a0c","op1":"1","op2":"0","op1type":"str","op2type":"str","duration":"10","extend":false,"units":"min","reset":"0","bytopic":"all","name":"","x":330,"y":1700,"wires":[["2d269cf5.2279a4","6d4cd61d.212b08"]]},{"id":"2d269cf5.2279a4","type":"delay","z":"5a966310.e46a0c","name":"","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":520,"y":1700,"wires":[["34363fe4.d49de"]]},{"id":"346117c9.dedc28","type":"mqtt out","z":"5a966310.e46a0c","name":"","topic":"garden/valve/zone1","qos":"2","retain":"false","broker":"e0ba888b.b9d328","x":730,"y":1640,"wires":[]},{"id":"6d4cd61d.212b08","type":"mqtt out","z":"5a966310.e46a0c","name":"","topic":"garden/valve/master","qos":"","retain":"false","broker":"e0ba888b.b9d328","x":560,"y":1600,"wires":[]},{"id":"34363fe4.d49de","type":"mqtt out","z":"5a966310.e46a0c","name":"","topic":"garden/valve/zone2","qos":"2","retain":"false","broker":"e0ba888b.b9d328","x":730,"y":1700,"wires":[]},{"id":"9d6f688c.2219b8","type":"mqtt in","z":"5a966310.e46a0c","name":"","topic":"garden/valve/master","qos":"2","datatype":"auto","broker":"e0ba888b.b9d328","x":130,"y":1840,"wires":[["677b4372.eea0fc"]]},{"id":"74750658.f6dc48","type":"mqtt in","z":"5a966310.e46a0c","name":"","topic":"garden/valve/zone1","qos":"2","datatype":"auto","broker":"e0ba888b.b9d328","x":130,"y":1880,"wires":[["5a03791e.4af108"]]},{"id":"8d41396a.597288","type":"mqtt in","z":"5a966310.e46a0c","name":"","topic":"garden/valve/zone2","qos":"2","datatype":"auto","broker":"e0ba888b.b9d328","x":130,"y":1920,"wires":[["19514a49.398bb6"]]},{"id":"5a03791e.4af108","type":"ui_gauge","z":"5a966310.e46a0c","name":"Zone 1","group":"928b09a9.067248","order":2,"width":"2","height":"2","gtype":"donut","title":"Zone 1","label":"","format":"{{value}}","min":0,"max":"1","colors":["#00b500","#e6e600","#0000ff"],"seg1":"","seg2":"","x":340,"y":1880,"wires":[]},{"id":"677b4372.eea0fc","type":"ui_gauge","z":"5a966310.e46a0c","name":"Master","group":"928b09a9.067248","order":1,"width":"2","height":"2","gtype":"donut","title":"Master","label":"","format":"{{value}}","min":0,"max":"1","colors":["#00b500","#e6e600","#0000ff"],"seg1":"","seg2":"","x":330,"y":1840,"wires":[]},{"id":"19514a49.398bb6","type":"ui_gauge","z":"5a966310.e46a0c","name":"Zone 2","group":"928b09a9.067248","order":3,"width":"2","height":"2","gtype":"donut","title":"Zone 2","label":"","format":"{{value}}","min":0,"max":"1","colors":["#00b500","#e6e600","#0000ff"],"seg1":"","seg2":"","x":340,"y":1920,"wires":[]},{"id":"de6c4439.9f61e8","type":"ui_button","z":"5a966310.e46a0c","name":"Reset","group":"26a8ca98.e502c6","order":1,"width":"2","height":"2","passthru":false,"label":"Reset","tooltip":"","color":"","bgcolor":"#333333","icon":"block","payload":"0","payloadType":"num","topic":"","x":110,"y":1760,"wires":[["33ee55e0.f7413a","6d4cd61d.212b08","9265d905.231bf8","2d269cf5.2279a4","2c4c140a.4eb4cc"]]},{"id":"34814649.6447ca","type":"inject","z":"5a966310.e46a0c","name":"Reset Daily Total","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"59 23 * * *","once":false,"onceDelay":0.1,"x":150,"y":940,"wires":[["100619b2.a4c806"]]},{"id":"100619b2.a4c806","type":"function","z":"5a966310.e46a0c","name":"","func":"flow.set(\"daily_total\",0);\nreturn msg;","outputs":1,"noerr":0,"x":350,"y":940,"wires":[[]]},{"id":"5450d60b.97a8d8","type":"function","z":"5a966310.e46a0c","name":"Garden Arduino Message","func":"if (msg.payload == \"timeout\") { \n var msg1 = { payload:\"(from Garden) Garden Arduino timeout \" + new Date() };\n }\nreturn [msg1];","outputs":1,"noerr":0,"x":610,"y":1160,"wires":[["f16948e8.e6eaa8"]]},{"id":"f16948e8.e6eaa8","type":"e-mail","z":"5a966310.e46a0c","server":"smtp-mail.outlook.com","port":"587","secure":false,"tls":false,"name":"destination@youremail.com","dname":"","x":840,"y":1160,"wires":[]},{"id":"a309209f.f53af","type":"mqtt in","z":"5a966310.e46a0c","name":"gardenuino/valvetimeout","topic":"gardenuino/valvetimeout","qos":"2","datatype":"auto","broker":"e0ba888b.b9d328","x":150,"y":1980,"wires":[["db39e962.6fd928","ab63d7a6.fae108"]]},{"id":"db39e962.6fd928","type":"ui_gauge","z":"5a966310.e46a0c","name":"Valve Timeout","group":"928b09a9.067248","order":11,"width":"2","height":"2","gtype":"donut","title":"Valve Timeout","label":"","format":"{{value}}","min":0,"max":"1","colors":["#00b500","#e6e600","#ff0000"],"seg1":"","seg2":"","x":400,"y":1980,"wires":[]},{"id":"ab63d7a6.fae108","type":"debug","z":"5a966310.e46a0c","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":380,"y":2040,"wires":[]},{"id":"e0ba888b.b9d328","type":"mqtt-broker","z":"","name":"Local","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"863689d4.9f3c88","type":"ui_group","z":"","name":"Disabled","tab":"a460c32f.87fcd","order":2,"disp":true,"width":"4","collapse":false},{"id":"928b09a9.067248","type":"ui_group","z":"","name":"Status","tab":"a460c32f.87fcd","order":1,"disp":true,"width":"6","collapse":false},{"id":"6297bca7.d83e54","type":"ui_group","z":"","name":"Weather","tab":"a460c32f.87fcd","order":4,"disp":true,"width":"4","collapse":false},{"id":"9403836f.e9086","type":"ui_group","z":"","name":"Timer","tab":"a460c32f.87fcd","order":3,"disp":true,"width":"4","collapse":false},{"id":"26a8ca98.e502c6","type":"ui_group","z":"","name":"Override","tab":"a460c32f.87fcd","disp":true,"width":"6","collapse":false},{"id":"a460c32f.87fcd","type":"ui_tab","z":"","name":"Garden","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

You'll have to get your own API key from OpenWeatherMap.org (https://openweathermap.org/api) for the local weather node and provide your own credentials for the email node. I use outlook.com to send emails to my gmail account. You can use your ISP or whoever you like. I use the email node to send an email if communications is lost between the Pi and the Arduino.

https://sites.google.com/a/wt4y.com/radio/home-automation/garden-sprinkler-version-2/GardenDashboardV2.png