Update new external scripts

master
shaun feakes 2018-08-11 14:28:18 -05:00
parent 06b298d4e5
commit 796c1be923
16 changed files with 370 additions and 70 deletions

View File

@ -4,7 +4,7 @@
More details & pics to come
linux daemon to control sprinklers.<br>
* <b>This is designed to be small, efficient and fail safe.</b>
* <b>This daemon is designed to be small, efficient and fail safe.</b>
The sprinkler zone control is done through GPIO pins, so simply connect a relay board to the GPIO pins, and the realys to your sprinkler valves & power supply. Provides web UI, MQTT client & HTTP API endpoints. So you can control your pool equiptment from any phone/tablet or computer, and should work with just about Home control systems, including Apple HomeKit, Samsung, Alexa, Google, etc home hubs.
It is not designed to be a feature rich solution with elaborate UI, but rather a solution that can be completley controlled from smart hubs. It can run completley self contained without any automation hub as it does have a web UI and calendar for scheduling zone runtimes, rain day delay etc. But advanced features like integrated rain censors and web forecast delays should be done through your smart hub, or the supplied scripts.
@ -96,6 +96,10 @@ Specifically, make sure you configure your MQTT, Pool Equiptment Labels & Domoti
[sprinklerDarkskys.sh](https://github.com/sfeakes/sprinklerd/blob/master/extras/sprinklerDarkskys.sh)
Script to check the chance of rain from darkskys forecast API, if it's greater than a configured percentage then enable the 24h rainDelay on SprinklerD.
Simply edit the scrips with your values, and use cron to run it 30mins before your sprinkelrs are due to turn on each day. If the chance of rain is over your configured % it will enable SprinklerD's 24h rain delay, which will stop the sprinklers running that day, and the 24h delay will timeout before the sprinklers are due to run the next day. (or be enabeled again if the chance of rain is high)
You can also use this script to simply sent the 'chance or rain today' to SprinklerD, and allow SprinklerD to make the decision if to enable rain delay, depending on options configured in the UI.
[sprinklerMeteohub.sh](https://github.com/sfeakes/sprinklerd/blob/master/extras/sprinklerMeteohub.sh)
Script to pull daily rain total from Hereohub and send it to SprinklerD. SprinklerD will then turn on rain dalys (14h or 48h) depending on rain threshold.
[sprinklerRainDelay.sh](https://github.com/sfeakes/sprinklerd/blob/master/extras/sprinklerRainDelay.sh)
Script to enable extended rain delays. i.e. I have my weatherstation triger this script when it detects rain. The script will cancel any running zones and enable a rain delay. You can use a number on command line parameter to enable long delays, (number represents number of days). So if my rainsensor logs over 5mm rain in any 24h period it will call this script with a 2 day delay, or 3 day delay if over 15mm of rain.
@ -164,7 +168,17 @@ http://sprinklerd.ip.address:port?type=option&option=24hdelay&state=off
<host>?type=option&option=allz&state=on // Run all zones default times (ignore 24h delay & calendar settings)
<host>?type=zone&zone=2&state=on&runtime=3 // Run zone 2 for 3 mins (ignore 24h delay & calendar settings)
<host>?type=zrtcfg&zone=2&time=10 // change zone 2 default runtime to 10
<host>?type=cron&zone=1&runtime=12' // Run zone 1 for 12 mins (calendar & 24hdelay settings overide this request)
<host>?type=cron&zone=1&runtime=12&state=on' // Run zone 1 for 12 mins (calendar & 24hdelay settings overide this request)
* // Sensor config options
<host>?type=config&option=raindelaychance&value=50 // Enable 24h rain delay is % change or rain today is higher than this value
<host>?type=config&option=raindelaytotal1&value=0.5 // Enable 24h rain delay is total rain was greater than this value
<host>?type=config&option=raindelaytotal2&value=1.5 // Enable 48h rain delay is total rain was greater than this value
* // Sensor options (remote sensors posting to SprinklerD)
* // These are used to determin if to enable rain delay and cancel running zones.
<host>?type=sensor&sensor=chanceofrain&value=27 // Set % chance of rain for today to 87%
<host>?type=sensor&sensor=raintotal&value=0.34 // Set rain total for todaye to 0.34"
```
The JSON that's returned is completley flat, this is so it can be passed with really small lightweight passers, even grep and awk. If you want a full JSON with arrays that's easier to use with full json parsers you can use the below
```

View File

@ -58,6 +58,10 @@ void write_cache() {
fprintf(fp, "%d\n", _sdconfig_.calendar);
fprintf(fp, "%d\n", _sdconfig_.delay24h);
fprintf(fp, "%li\n", _sdconfig_.delay24h_time);
fprintf(fp, "%d\n", _sdconfig_.precipChanceDelay);
fprintf(fp, "%.1f\n", _sdconfig_.precipInchDelay1day);
fprintf(fp, "%.1f\n", _sdconfig_.precipInchDelay2day);
fprintf(fp, "-1\n");
for (zone=1; zone <= _sdconfig_.zones; zone ++) {
fprintf(fp, "%d\n", _sdconfig_.zonecfg[zone].default_runtime);
}
@ -71,42 +75,55 @@ void write_cache() {
void read_cache() {
FILE *fp;
int i;
float f;
int c = 0;
bool z = false;
int zs = 0;
fp = fopen(_sdconfig_.cache_file, "r");
if (fp == NULL) {
logMessage(LOG_ERR, "Open file failed '%s'\n", _sdconfig_.cache_file);
return;
}
while (EOF != fscanf (fp, "%d", &i)) {
if (c == 0){
//while (EOF != fscanf (fp, "%d", &i)) {
while (EOF != fscanf (fp, "%f", &f)) {
if (f == -1) {
z = true;
zs = c;
c++;
continue;
}
i = (int)f;
if (z == true) {
_sdconfig_.zonecfg[ (c - zs) ].default_runtime = i;
logMessage(LOG_DEBUG, "Read default_runtime '%d' for zone %d\n", i, (c - zs) );
} else if (c == 0){
_sdconfig_.calendar = i;
logMessage(LOG_DEBUG, "Read calendar '%s' from cache\n", _sdconfig_.calendar?"ON":"OFF");
logMessage(LOG_DEBUG, "Read Calendar '%s' from cache\n", _sdconfig_.calendar?"ON":"OFF");
} else if (c == 1){
_sdconfig_.delay24h = i;
logMessage(LOG_DEBUG, "Read delay24h '%s' from cache\n", _sdconfig_.delay24h?"ON":"OFF");
} else if (c == 2){
_sdconfig_.delay24h_time = i;
logMessage(LOG_DEBUG, "Read delay24h endtime '%li' from cache\n",_sdconfig_.delay24h_time);
} else if ( c-2 <= _sdconfig_.zones) {
_sdconfig_.zonecfg[c-2].default_runtime = i;
} else if (c == 3){
_sdconfig_.precipChanceDelay = i;
logMessage(LOG_DEBUG, "Read Chance of Rain delay '%d' from cache\n",_sdconfig_.precipChanceDelay);
} else if (c == 4){
_sdconfig_.precipInchDelay1day = f;
logMessage(LOG_DEBUG, "Read Rain 1d delay '%f'in from cache\n",_sdconfig_.precipInchDelay1day);
} else if (c == 5){
_sdconfig_.precipInchDelay2day = f;
logMessage(LOG_DEBUG, "Read Rain 2d delay '%f'in from cache\n",_sdconfig_.precipInchDelay2day);
}/* else if ( c-1 <= _sdconfig_.zones) {
_sdconfig_.gpiocfg[c-1].default_runtime = i;
logMessage(LOG_DEBUG, "Read default_runtime '%d' for zone %d\n", i, c-1);
}
}*/
c++;
}
/*
fscanf (fp, "%d", &i);
if (i > -1 && i< 2) {
_sdconfig_.system = i;
logMessage(LOG_DEBUG, "Read System '%s' from cache\n", _sdconfig_.system?"ON":"OFF");
}
fscanf (fp, "%d", &i);
if (i > -1 && i< 5000) {
_sdconfig_.delay24h = i;
logMessage(LOG_DEBUG, "Read delay24h '%s' from cache\n", _sdconfig_.delay24h?"ON":"OFF");
}
*/
fclose (fp);
}

View File

@ -78,6 +78,9 @@ struct sprinklerdcfg {
bool delay24h;
long delay24h_time;
bool master_valve;
int precipChanceDelay;
float precipInchDelay1day;
float precipInchDelay2day;
struct DZcache *dz_cache;
struct GPIOcfg *zonecfg;
//struct GPIOcfg *gpiocfg;
@ -88,6 +91,8 @@ struct sprinklerdcfg {
struct szRunning currentZone;
char cache_file[512];
bool eventToUpdateHappened;
int todayRainChance;
float todayRainTotal;
};

View File

@ -7,12 +7,14 @@
#
darkskyAPI='0123456789abcdef9876543210fedcba'
location='42.3601,-71.0589'
probabilityOver=0.5
probabilityOver=1.0 # Don't set delay from this script, use the SprinklerD config to decide if to set delay
sprinklerdEnableDelay="http://localhost/?type=option&option=24hdelay&state=reset"
sprinklerdProbability="http://localhost/?type=sensor&sensor=chanceofrain&value="
echoerr() { printf "%s\n" "$*" >&2; }
echomsg() { if [ -t 1 ]; then echo "$@" 1>&2; fi; }
command -v curl >/dev/null 2>&1 || { echoerr "curl is not installed. Aborting!"; exit 1; }
command -v jq >/dev/null 2>&1 || { echoerr "jq is not installed. Aborting!"; exit 1; }
command -v bc >/dev/null 2>&1 || { echoerr "bc not installed. Aborting!"; exit 1; }
@ -26,6 +28,8 @@ fi
echomsg -n "Probability of rain today is "`echo "$probability * 100" | bc`"%"
curl -s "$sprinklerdProbability`echo \"$probability * 100\" | bc`" > /dev/null
if (( $(echo "$probability > $probabilityOver" | bc -l) )); then
echomsg -n ", enabeling rain delay"
curl -s "$sprinklerdEnableDelay" > /dev/null

30
extras/sprinklerMeteohub.sh Executable file
View File

@ -0,0 +1,30 @@
#
# Change the URL's below to point to Meteohub server and SprinklerD server
#
meteohubRainTotal="http://hurricane/meteograph.cgi?text=day1_rain0_total_in"
#meteohubRainTotal="http://192.168.144.101/meteograph.cgi?text=last24h_rain0_total_in"
#meteohubRainTotal="http://192.168.144.101/meteograph.cgi?text=alltime_rain0_total_in"
sprinklerdSetRainTotal="http://localhost/?type=sensor&sensor=raintotal&value="
echoerr() { printf "%s\n" "$*" >&2; }
echomsg() { if [ -t 1 ]; then echo "$@" 1>&2; fi; }
command -v curl >/dev/null 2>&1 || { echoerr "curl is not installed. Aborting!"; exit 1; }
rainTotal=$(curl -s "$meteohubRainTotal")
if [ $? -ne 0 ]; then
echoerr "Error reading Metrohub URL, please check!"
echoerr "Assuming rain sensor is not responding, not sending rain total to SprinklerD"
exit 1;
fi
echomsg -n "Rain total is $rainTotal\" at `date`"
curl -s "$sprinklerdSetRainTotal$rainTotal" > /dev/null
echomsg ""

View File

@ -59,21 +59,28 @@ int build_sprinkler_JSON(char* buffer, int size)
int i;
memset(&buffer[0], 0, size);
int length = 0;
char status[30];
char status[50];
if(_sdconfig_.currentZone.type!=zcNONE)
sprintf(status,"Zone %d : time left %02d:%02d",_sdconfig_.currentZone.zone, _sdconfig_.currentZone.timeleft / 60, _sdconfig_.currentZone.timeleft % 60 );
sprintf(status,"Active: Zone %d : time left %02d:%02d",_sdconfig_.currentZone.zone, _sdconfig_.currentZone.timeleft / 60, _sdconfig_.currentZone.timeleft % 60 );
else if (_sdconfig_.todayRainChance > 0 || _sdconfig_.todayRainTotal > 0)
sprintf(status, "Today:- Chance of rain: %d%%, Rain total: %.2f\\\"", _sdconfig_.todayRainChance, _sdconfig_.todayRainTotal);
else
status[0] = '\0';
length += sprintf(buffer+length, "{ \"title\" : \"%s\",\"calendar\" : \"%s\", \"24hdelay\" : \"%s\", \"allz\" : \"%s\", \"zones\" : \"%d\", \"24hdelay-offtime\" : %li, \"status\" : \"%s\"",
length += sprintf(buffer+length, "{ \"title\" : \"%s\",\"calendar\" : \"%s\", \"24hdelay\" : \"%s\", \"allz\" : \"%s\", \"zones\" : \"%d\", \"24hdelay-offtime\" : %li, \"status\" : \"%s\", \"raindelaychance\" : \"%d\", \"raindelaytotal1\" : \"%.1f\", \"raindelaytotal2\" : \"%.1f\", \"todaychanceofrain\" : \"%d\", \"todayraintotal\" : \"%.2f\"",
_sdconfig_.name,
_sdconfig_.calendar?"on":"off",
_sdconfig_.delay24h?"on":"off",
_sdconfig_.currentZone.type==zcALL?"on":"off",
_sdconfig_.zones,
_sdconfig_.delay24h_time,
status);
status,
_sdconfig_.precipChanceDelay,
_sdconfig_.precipInchDelay1day,
_sdconfig_.precipInchDelay2day,
_sdconfig_.todayRainChance,
_sdconfig_.todayRainTotal);
for (i=1; i <= _sdconfig_.zones ; i++)
{
@ -98,13 +105,27 @@ int build_advanced_sprinkler_JSON(char* buffer, int size)
int i, day;
memset(&buffer[0], 0, size);
int length = 0;
/*
length += sprintf(buffer+length, "{ \"title\" : \"%s\",\"calendar\" : \"%s\", \"24hdelay\" : \"%s\", \"allz\" : \"%s\", \"#zones\" : %d, \"24hdelay-offtime\" : %li",
_sdconfig_.name, _sdconfig_.calendar?"on":"off",
_sdconfig_.name,
_sdconfig_.calendar?"on":"off",
_sdconfig_.delay24h?"on":"off",
_sdconfig_.currentZone.type==zcALL?"on":"off",
_sdconfig_.zones,
_sdconfig_.delay24h_time);
*/
length += sprintf(buffer+length, "{ \"title\" : \"%s\",\"calendar\" : \"%s\", \"24hdelay\" : \"%s\", \"allz\" : \"%s\", \"zones\" : \"%d\", \"24hdelay-offtime\" : %li, \"raindelaychance\" : \"%d\", \"raindelaytotal1\" : \"%.1f\", \"raindelaytotal2\" : \"%.1f\", \"todaychanceofrain\" : \"%d\", \"todayraintotal\" : \"%.2f\"",
_sdconfig_.name,
_sdconfig_.calendar?"on":"off",
_sdconfig_.delay24h?"on":"off",
_sdconfig_.currentZone.type==zcALL?"on":"off",
_sdconfig_.zones,
_sdconfig_.delay24h_time,
_sdconfig_.precipChanceDelay,
_sdconfig_.precipInchDelay1day,
_sdconfig_.precipInchDelay2day,
_sdconfig_.todayRainChance,
_sdconfig_.todayRainTotal);
length += sprintf(buffer+length, ", \"zones\": {");
for (i=1; i <= _sdconfig_.zones ; i++)

View File

@ -442,7 +442,7 @@ int serve_web_request(struct mg_connection *nc, struct http_message *http_msg, c
reset_delay24h_time(atoi(buf));
}
length = build_sprinkler_JSON(buffer, size);
} else if (strncasecmp(buf, "allz", 8) == 0 ) {
} else if (strncasecmp(buf, "allz", 4) == 0 ) {
mg_get_http_var(&http_msg->query_string, "state", buf, buflen);
zc_zone(zcALL, 0, (is_value_ON(buf)?zcON:zcOFF), 0);
length = build_sprinkler_JSON(buffer, size);
@ -452,21 +452,50 @@ int serve_web_request(struct mg_connection *nc, struct http_message *http_msg, c
}
*changedOption = true;
//broadcast_sprinklerdstate(nc);
} else if ( strcmp(buf, "zone") == 0 || strcmp(buf, "cron") == 0 ) {
//logMessage(LOG_DEBUG, "WEB REQUEST zone %s\n",buf);
zcRunType type = zcSINGLE;
if (strcmp(buf, "cron") == 0)
type = zcCRON;
mg_get_http_var(&http_msg->query_string, "zone", buf, buflen);
zone = atoi(buf);
mg_get_http_var(&http_msg->query_string, "runtime", buf, buflen);
runtime = atoi(buf);
mg_get_http_var(&http_msg->query_string, "state", buf, buflen);
//if ( (strncasecmp(buf, "off", 3) == 0 || strncmp(buf, "0", 1) == 0) && zone <= _sdconfig_.zones) {
if ( is_value_ON(buf) == true && zone <= _sdconfig_.zones) {
zc_zone(type, zone, zcON, runtime);
length = build_sprinkler_JSON(buffer, size);
} else if (strncasecmp(buf, "config", 6) == 0) {
mg_get_http_var(&http_msg->query_string, "option", buf, buflen);
if (strncasecmp(buf, "raindelaychance", 15) == 0)
{
mg_get_http_var(&http_msg->query_string, "value", buf, buflen);
_sdconfig_.precipChanceDelay = atoi(buf);
}
else if (strncasecmp(buf, "raindelaytotal1", 15) == 0)
{
mg_get_http_var(&http_msg->query_string, "value", buf, buflen);
_sdconfig_.precipInchDelay1day = atof(buf);
}
else if (strncasecmp(buf, "raindelaytotal2", 15) == 0)
{
mg_get_http_var(&http_msg->query_string, "value", buf, buflen);
_sdconfig_.precipInchDelay2day = atof(buf);
}
length = build_sprinkler_JSON(buffer, size);
} else if (strncasecmp(buf, "sensor", 6) == 0) {
mg_get_http_var(&http_msg->query_string, "sensor", buf, buflen);
if (strncasecmp(buf, "chanceofrain", 13) == 0) {
mg_get_http_var(&http_msg->query_string, "value", buf, buflen);
setTodayChanceOfRain(atoi(buf));
} else if (strncasecmp(buf, "raintotal", 9) == 0) {
mg_get_http_var(&http_msg->query_string, "value", buf, buflen);
setTodayRainTotal(atof(buf));
}
length = build_sprinkler_JSON(buffer, size);
} else if (strcmp(buf, "zone") == 0 || strcmp(buf, "cron") == 0) {
//logMessage(LOG_DEBUG, "WEB REQUEST zone %s\n",buf);
zcRunType type = zcSINGLE;
if (strcmp(buf, "cron") == 0)
type = zcCRON;
mg_get_http_var(&http_msg->query_string, "zone", buf, buflen);
zone = atoi(buf);
mg_get_http_var(&http_msg->query_string, "runtime", buf, buflen);
runtime = atoi(buf);
mg_get_http_var(&http_msg->query_string, "state", buf, buflen);
//if ( (strncasecmp(buf, "off", 3) == 0 || strncmp(buf, "0", 1) == 0) && zone <= _sdconfig_.zones) {
if (is_value_ON(buf) == true && zone <= _sdconfig_.zones)
{
zc_zone(type, zone, zcON, runtime);
length = build_sprinkler_JSON(buffer, size);
//} else if ( (strncasecmp(buf, "on", 2) == 0 || strncmp(buf, "1", 1) == 0) && zone <= _sdconfig_.zones) {
} else if ( is_value_ON(buf) == false && zone <= _sdconfig_.zones) {
zc_zone(type, zone, zcOFF, runtime);

Binary file not shown.

View File

@ -118,25 +118,4 @@ GPIO_PULL_UPDN=1
GPIO_ON_STATE=0
DOMOTICZ_IDX=207
#
# This is for future support of sensors, not implimented yet
#
#PIN
#NAME name
#PIN_MODE Setup as input or output
#PULL_UPDN setup pull up pull down resistor NONE|PUD_OFF|PUD_DOWN|PUD_UP
#TRIGGER_EVENT_ON trigger_event on NONE|INT_EDGE_SETUP|INT_EDGE_FALLING|INT_EDGE_RISING|INT_EDGE_BOTH
#TRIGGER_EVENT_STATE trigger_event_received_state LOW|HIGH|BOTH
#COMMAND triggered_event_runcmd = external command to run
#DOMOTICZ_IDX Domoticz IDX
[GPIO]
[GPIO:1]
NAME=Rain Sensor
GPIO_PIN=4
WPI_PIN=7
PIN_MODE=0
#PULL_UPDN=0
TRIGGER_EVENT_ON=3
COMMAND_HIGH=/usr/bin/curl -s -o /dev/null 'http://localhost?type=option&option=24hdelay&state=on'
COMMAND_LOW=/usr/bin/curl -s -o /dev/null 'http://localhost?type=option&option=24hdelay&state=off'

View File

@ -0,0 +1,142 @@
[SPRINKLERD]
PORT=80
NAME=My Sprinklers
DOCUMENTROOT = /nas/data/Development/Raspberry/SprinklerD/web/
CACHE = /var/cache/sprinklerd.cache
# The log level. [DEBUG, INFO, NOTICE, WARNING, ERROR]
#LOG_LEVEL = DEBUG
LOG_LEVEL = NOTICE
# mqtt stuff
#MQTT_ADDRESS = trident:1883
#MQTT_USER = someusername
#MQTT_PASSWD = somepassword
#MQT_TOPIC = sprinklerd
#MQTT_DZ_PUB_TOPIC = domoticz/in
#MQTT_DZ_SUB_TOPIC = domoticz/out
#DZIDX_CALENDAR = 197
#DZIDX_24HDELAY = 198
#DZIDX_ALL_ZONES = 199
# Options for the below ZONE and GPIO configuration
#
# LOW 0
# HIGH 1
#
# PUD_OFF 0
# PUD_DOWN 1
# PUD_UP 2
#NAME = name of zone
#GPIO_PIN = GPIO Pin # This is WiringPi Pin#, not Raspberry Pi board pin#.
#WPI_PIN = use instead of GPIO_PIN if compiled with USE_WIRINGPI flag
#GPIO_PULL_UPDN = setup pull up pull down resistor PUD_OFF|PUD_DOWN|PUD_UP
#GPIO_ON_STATE = State GPIO reads when relay for zone is on. HIGH or LOW 1 or 0
#DOMOTICZ_IDX = Domoticz IDX 0 or remove entry if you don;t use Domoticz (only if you use domoticz)
#MASTER_VALVE = YES=1 NO=0 // turn on with any zone
# Don't use ZONE:0 for anything other than master valve, if you don't have a master valve simply delete it and start from ZONE:1
[ZONE]
[ZONE:0]
NAME=Master Valve
MASTER_VALVE=1
GPIO_PIN=17
WPI_PIN=0
GPIO_PULL_UPDN=1
GPIO_ON_STATE=0
[ZONE:1]
NAME=Island
DEFAULT_RUNTIME=10
GPIO_PIN=18
WPI_PIN=1
GPIO_PULL_UPDN=1
GPIO_ON_STATE=0
DOMOTICZ_IDX=200
[ZONE:2]
NAME=Driveway
DEFAULT_RUNTIME=10
GPIO_PIN=27
WPI_PIN=2
GPIO_PULL_UPDN=1
GPIO_ON_STATE=0
DOMOTICZ_IDX=201
[ZONE:3]
NAME=Diningroom Flowerbeds
DEFAULT_RUNTIME=10
GPIO_PIN=22
WPI_PIN=3
GPIO_PULL_UPDN=1
GPIO_ON_STATE=0
DOMOTICZ_IDX=202
[ZONE:4]
NAME=Front Flowerbeds
DEFAULT_RUNTIME=10
GPIO_PIN=23
WPI_PIN=4
GPIO_PULL_UPDN=1
GPIO_ON_STATE=0
DOMOTICZ_IDX=203
[ZONE:5]
NAME=Backgarden Left
DEFAULT_RUNTIME=10
GPIO_PIN=24
WPI_PIN=5
GPIO_PULL_UPDN=1
GPIO_ON_STATE=0
DOMOTICZ_IDX=204
[ZONE:6]
NAME=Backgarden Right
DEFAULT_RUNTIME=10
GPIO_PIN=25
WPI_PIN=6
GPIO_PULL_UPDN=1
GPIO_ON_STATE=0
DOMOTICZ_IDX=205
[ZONE:7]
NAME=Garage Flowerbeds
DEFAULT_RUNTIME=10
GPIO_PIN=5
WPI_PIN=21
GPIO_PULL_UPDN=1
GPIO_ON_STATE=0
DOMOTICZ_IDX=206
[ZONE:8]
NAME=Golfcart path
DEFAULT_RUNTIME=10
GPIO_PIN=6
WPI_PIN=22
GPIO_PULL_UPDN=1
GPIO_ON_STATE=0
DOMOTICZ_IDX=207
#
# This is for future support of sensors, not implimented yet
#
#PIN
#NAME name
#PIN_MODE Setup as input or output
#PULL_UPDN setup pull up pull down resistor NONE|PUD_OFF|PUD_DOWN|PUD_UP
#TRIGGER_EVENT_ON trigger_event on NONE|INT_EDGE_SETUP|INT_EDGE_FALLING|INT_EDGE_RISING|INT_EDGE_BOTH
#TRIGGER_EVENT_STATE trigger_event_received_state LOW|HIGH|BOTH
#COMMAND triggered_event_runcmd = external command to run
#DOMOTICZ_IDX Domoticz IDX
[GPIO]
[GPIO:1]
NAME=Rain Sensor
GPIO_PIN=4
WPI_PIN=7
PIN_MODE=0
#PULL_UPDN=0
TRIGGER_EVENT_ON=3
COMMAND_HIGH=/usr/bin/curl -s -o /dev/null 'http://localhost?type=option&option=24hdelay&state=on'
COMMAND_LOW=/usr/bin/curl -s -o /dev/null 'http://localhost?type=option&option=24hdelay&state=off'

View File

@ -9,6 +9,37 @@
#define DELAY24H_SEC 86400
bool setTodayChanceOfRain(int percent)
{
logMessage(LOG_DEBUG, "Set today's chance of rain = %d\n",percent);
if (percent <= 100 && percent >= 0) {
_sdconfig_.todayRainChance = percent;
if (_sdconfig_.precipChanceDelay > 0 && _sdconfig_.todayRainChance >= _sdconfig_.precipChanceDelay)
enable_delay24h(true);
return true;
}
return false;
}
bool setTodayRainTotal(float rain)
{
_sdconfig_.todayRainTotal = rain;
logMessage(LOG_DEBUG, "Today's rain total = %f\n",_sdconfig_.todayRainTotal);
if (_sdconfig_.precipInchDelay2day > 0 && _sdconfig_.todayRainTotal >= _sdconfig_.precipInchDelay2day) {
time_t now;
time(&now);
reset_delay24h_time(now + (DELAY24H_SEC * 2) ); // today + 2 days in seconds
} else if (_sdconfig_.precipInchDelay1day > 0 && _sdconfig_.todayRainTotal >= _sdconfig_.precipInchDelay1day) {
enable_delay24h(true);
}
return true;
}
bool check_delay24h()
{
if (_sdconfig_.delay24h_time > 0) {
@ -43,6 +74,7 @@ void enable_delay24h(bool state)
time(&_sdconfig_.delay24h_time);
_sdconfig_.delay24h_time = _sdconfig_.delay24h_time + DELAY24H_SEC;
logMessage(LOG_NOTICE, "Turning on rain Delay\n");
zc_rain_delay_enabeled();
} else {
_sdconfig_.delay24h_time = 0;
logMessage(LOG_NOTICE, "Turning off rain Delay\n");
@ -66,11 +98,13 @@ void reset_delay24h_time(unsigned long dtime)
_sdconfig_.delay24h = true;
_sdconfig_.delay24h_time = dtime;
logMessage(LOG_NOTICE, "Reset rain Delay custom time\n");
zc_rain_delay_enabeled();
} else {
_sdconfig_.delay24h = true;
time(&_sdconfig_.delay24h_time);
_sdconfig_.delay24h_time = _sdconfig_.delay24h_time + DELAY24H_SEC;
logMessage(LOG_NOTICE, "Reset rain Delay\n");
zc_rain_delay_enabeled();
}
write_cache();
}
@ -128,6 +162,8 @@ void write_cron() {
}
}
}
fprintf(fp, "0 0 * * * root /usr/bin/curl -s -o /dev/null 'localhost?type=sensor&sensor=chanceofrain&value=0'\n");
fprintf(fp, "0 0 * * * root /usr/bin/curl -s -o /dev/null 'localhost?type=sensor&sensor=raintotal&value=0'\n");
fprintf(fp, "#***** AUTO GENERATED DO NOT EDIT *****\n");
fclose(fp);

View File

@ -14,5 +14,7 @@ void enable_delay24h(bool state);
bool check_delay24h();
void reset_delay24h_time();
void enable_calendar(bool state);
bool setTodayChanceOfRain(int percent);
bool setTodayRainTotal(float rain);
#endif // SD_CRON_H_

View File

@ -1,6 +1,6 @@
#ifndef SD_VERSION_H
#define SD_VERSION_H
#define SD_VERSION "1.0a"
#define SD_VERSION "1.0b"
#endif

View File

@ -165,7 +165,8 @@
}
input.btn-toggle-round:checked+label:before {
background-color: rgb(76, 217, 100);
/*background-color: rgb(76, 217, 100);*/
background-color: #2196F3;
}
input.btn-toggle-round:checked+label:after {
@ -272,6 +273,10 @@
html = html+calendarhtmlrow("Fri", 5, zones);
html = html+calendarhtmlrow("Sat", 6, zones);
html = html+calendarhtmlrow("Sun", 0, zones);
html = html + '<tr><td colspan="2">Delay if chance of rain is above</td><td colspan="'+zones+'" align="left"><input type="number" id="raindelaychance" class="input-ios" onchange="update(this);" pattern="[0-9]*" maxlength="2" inputmode="numeric" min="0" max="100" step="1">percent</td></tr> \
<tr><td colspan="2">Delay 24 hours if rain total </td><td colspan="'+zones+'" align="left"><input type="number" id="raindelaytotal1" class="input-ios" onchange="update(this);" pattern="[0-9]*" maxlength="2" inputmode="numeric" min="0" max="10" step="0.1">inches</td></tr> \
<tr><td colspan="2">Delay 48 hours if rain total </td><td colspan="'+zones+'" align="left"><input type="number" id="raindelaytotal2" class="input-ios" onchange="update(this);" pattern="[0-9]*" maxlength="2" inputmode="numeric" min="0" max="10" step="0.1">inches</td></tr>' ;
rnz = document.getElementById('options');
rnz.innerHTML = rnz.innerHTML.replace("<!-- AUTO HTML -->", html);
}
@ -321,7 +326,7 @@
document.getElementById('title').innerHTML = data[obj];
} if (obj == 'status') {
if (data[obj].length > 0)
document.getElementById('status').innerHTML = "Active:&nbsp;"+data[obj];
document.getElementById('status').innerHTML = data[obj].replace('/ /g', '&nbsp;');
else
document.getElementById('status').innerHTML = "Run now options";
} else if (obj == '24hdelay-offtime') {
@ -335,8 +340,10 @@
} else if ( (field = document.getElementById(obj)) != null){
if (obj.substr(-5,5) == '-name')
field.innerHTML = resize(data[obj]);
else
field.value = data[obj];
else {
if (field.id != document.activeElement.id) // Only update if not being edited
field.value = data[obj];
}
} else {
if ( (btn = document.getElementById('btn-toggle-' + obj)) != null){
if (data[obj] == 'on')
@ -376,6 +383,9 @@
http.send(null);
cleanupCalendar();
}
} else if (type.id.substr(0,9) == 'raindelay'){ // rainChance, rainTotal1d, rainTotal2d
http.open('GET', location.href + '?type=config&option='+type.id+'&value='+type.value);
http.send(null);
} else if (type.id.substr(0,11) == 'btn-toggle-'){
// If there is a 'xx-runtime' id then it's a zone to start, else it's a cfg button
if ( (rto = document.getElementById(type.name + '-runtime')) != null){

View File

@ -66,6 +66,16 @@ bool zc_check() {
return false;
}
void zc_rain_delay_enabeled() {
// Turn off any running zone that was enabeled by cron, leave on any zones that were manually turned on.
if(_sdconfig_.currentZone.type==zcCRON && _sdconfig_.currentZone.zone > 0) {
logMessage (LOG_INFO, "Turning off zone %d '%s' due to rain delay\n",_sdconfig_.currentZone.zone, _sdconfig_.zonecfg[_sdconfig_.currentZone.zone].name);
zc_zone(zcSINGLE, _sdconfig_.currentZone.zone, zcOFF, 0);
}
}
void zc_master(zcState state) {
if (!_sdconfig_.master_valve)

View File

@ -21,5 +21,6 @@ struct szRunning {
bool zc_check();
bool zc_zone(zcRunType type, int zone, zcState state, int length);
void zc_rain_delay_enabeled();
#endif