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.

#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.

Here's the Node Red flow which can be imported into your Node Red Pi:

[{"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 me an email if communications is lost between the Pi and the Arduino.

And finally the dashboard:

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