forked from OpenSprinkler/OpenSprinkler-Firmware
-
Notifications
You must be signed in to change notification settings - Fork 0
/
OpenSprinkler.h
379 lines (339 loc) · 14 KB
/
OpenSprinkler.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
/* OpenSprinkler Unified (AVR/RPI/BBB/LINUX/ESP8266) Firmware
* Copyright (C) 2015 by Ray Wang ([email protected])
*
* OpenSprinkler library header file
* Feb 2015 @ OpenSprinkler.com
*
* This file is part of the OpenSprinkler library
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef _OPENSPRINKLER_H
#define _OPENSPRINKLER_H
#include "defines.h"
#include "utils.h"
#include "gpio.h"
#include "images.h"
#include "mqtt.h"
#if defined(ARDUINO) // headers for Arduino
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include "I2CRTC.h"
#if defined(ESP8266) // for ESP8266
#include <FS.h>
#include <LittleFS.h>
#include <ENC28J60lwIP.h>
#include <RCSwitch.h>
#include <OpenThingsFramework.h>
#include <DNSServer.h>
#include <Ticker.h>
#include "SSD1306Display.h"
#include "espconnect.h"
#else // for AVR
#include <SdFat.h>
#include <Ethernet.h>
#include "LiquidCrystal.h"
#endif
#else // headers for RPI/BBB/LINUX
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/stat.h>
#include "etherport.h"
#endif // end of headers
#if defined(ARDUINO)
#if defined(ESP8266)
extern ESP8266WebServer *update_server;
extern OTF::OpenThingsFramework *otf;
extern ENC28J60lwIP eth;
#else
extern EthernetServer *m_server;
#endif
extern bool useEth;
#else
extern EthernetServer *m_server;
#endif
/** Non-volatile data structure */
struct NVConData {
uint16_t sunrise_time; // sunrise time (in minutes)
uint16_t sunset_time; // sunset time (in minutes)
uint32_t rd_stop_time; // rain delay stop time
uint32_t external_ip; // external ip
uint8_t reboot_cause; // reboot cause
};
struct StationAttrib { // station attributes
byte mas:1;
byte igs:1; // ignore sensor 1
byte mas2:1;
byte dis:1;
byte seq:1; // this bit is retired and replaced by sequential group id
byte igs2:1; // ignore sensor 2
byte igrd:1; // ignore rain delay
byte igpu:1; // todo: ignore pause
byte gid; // sequential group id
byte reserved[2]; // reserved bytes for the future
}; // total is 4 bytes so far
/** Station data structure */
struct StationData {
char name[STATION_NAME_SIZE];
StationAttrib attrib;
byte type; // station type
byte sped[STATION_SPECIAL_DATA_SIZE]; // special station data
};
/** RF station data structures - Must fit in STATION_SPECIAL_DATA_SIZE */
struct RFStationData {
byte on[6];
byte off[6];
byte timing[4];
};
/** Remote station data structures - Must fit in STATION_SPECIAL_DATA_SIZE */
struct RemoteStationData {
byte ip[8];
byte port[4];
byte sid[2];
};
/** GPIO station data structures - Must fit in STATION_SPECIAL_DATA_SIZE */
struct GPIOStationData {
byte pin[2];
byte active;
};
/** HTTP station data structures - Must fit in STATION_SPECIAL_DATA_SIZE */
struct HTTPStationData {
byte data[STATION_SPECIAL_DATA_SIZE];
};
/** Volatile controller status bits */
struct ConStatus {
byte enabled:1; // operation enable (when set, controller operation is enabled)
byte rain_delayed:1; // rain delay bit (when set, rain delay is applied)
byte sensor1:1; // sensor1 status bit (when set, sensor1 on is detected)
byte program_busy:1; // HIGH means a program is being executed currently
byte has_curr_sense:1; // HIGH means the controller has a current sensing pin
byte safe_reboot:1; // HIGH means a safe reboot has been marked
byte req_ntpsync:1; // request ntpsync
byte req_network:1; // request check network
byte display_board:5; // the board that is being displayed onto the lcd
byte network_fails:3; // number of network fails
byte mas:8; // master station index
byte mas2:8; // master2 station index
byte sensor2:1; // sensor2 status bit (when set, sensor2 on is detected)
byte sensor1_active:1; // sensor1 active bit (when set, sensor1 is activated)
byte sensor2_active:1; // sensor2 active bit (when set, sensor2 is activated)
byte req_mqtt_restart:1;// request mqtt restart
byte pause_state:1; // pause station runs
};
/** OTF configuration */
struct OTCConfig {
byte en;
String token;
String server;
uint32_t port;
};
extern const char iopt_json_names[];
extern const uint8_t iopt_max[];
class OpenSprinkler {
public:
// data members
#if defined(ESP8266)
static SSD1306Display lcd; // 128x64 OLED display
#elif defined(ARDUINO)
static LiquidCrystal lcd; // 16x2 character LCD
#else
// todo: LCD define for RPI/BBB
#endif
#if defined(OSPI)
static byte pin_sr_data; // RPi shift register data pin to handle RPi rev. 1
#endif
static OSMqtt mqtt;
static NVConData nvdata;
static ConStatus status;
static ConStatus old_status;
static byte nboards, nstations;
static byte hw_type; // hardware type
static byte hw_rev; // hardware minor
static byte iopts[]; // integer options
static const char*sopts[]; // string options
static byte station_bits[]; // station activation bits. each byte corresponds to a board (8 stations)
// first byte-> master controller, second byte-> ext. board 1, and so on
// todo future: the following attribute bytes are for backward compatibility
static byte attrib_mas[];
static byte attrib_igs[];
static byte attrib_mas2[];
static byte attrib_igs2[];
static byte attrib_igrd[];
static byte attrib_dis[];
static byte attrib_spe[];
static byte attrib_grp[];
static byte masters[NUM_MASTER_ZONES][NUM_MASTER_OPTS];
// variables for time keeping
static time_t sensor1_on_timer; // time when sensor1 is detected on last time
static time_t sensor1_off_timer; // time when sensor1 is detected off last time
static time_t sensor1_active_lasttime; // most recent time sensor1 is activated
static time_t sensor2_on_timer; // time when sensor2 is detected on last time
static time_t sensor2_off_timer; // time when sensor2 is detected off last time
static time_t sensor2_active_lasttime; // most recent time sensor1 is activated
static time_t raindelay_on_lasttime; // time when the most recent rain delay started
static ulong pause_timer; // count down timer in paused state
static ulong flowcount_rt; // flow count (for computing real-time flow rate)
static ulong flowcount_log_start; // starting flow count (for logging)
static byte button_timeout; // button timeout
static time_t checkwt_lasttime; // time when weather was checked
static time_t checkwt_success_lasttime; // time when weather check was successful
static time_t powerup_lasttime; // time when controller is powered up most recently
static uint8_t last_reboot_cause; // last reboot cause
static byte weather_update_flag;
// member functions
// -- setup
static void update_dev(); // update software for Linux instances
static void reboot_dev(uint8_t); // reboot the microcontroller
static void begin(); // initialization, must call this function before calling other functions
static byte start_network(); // initialize network with the given mac and port
static byte start_ether(); // initialize ethernet with the given mac and port
static bool network_connected(); // check if the network is up
static bool load_hardware_mac(byte* buffer, bool wired=false); // read hardware mac address
static time_t now_tz();
// -- station names and attributes
static void get_station_data(byte sid, StationData* data); // get station data
static void set_station_data(byte sid, StationData* data); // set station data
static void get_station_name(byte sid, char buf[]); // get station name
static void set_station_name(byte sid, char buf[]); // set station name
static byte get_station_type(byte sid); // get station type
static byte is_sequential_station(byte sid);
static byte is_master_station(byte sid);
static byte bound_to_master(byte sid, byte mas);
static byte get_master_id(byte mas);
static int16_t get_on_adj(byte mas);
static int16_t get_off_adj(byte mas);
static byte is_running(byte sid);
static byte get_station_gid(byte sid);
static void set_station_gid(byte sid, byte gid);
//static StationAttrib get_station_attrib(byte sid); // get station attribute
static void attribs_save(); // repackage attrib bits and save (backward compatibility)
static void attribs_load(); // load and repackage attrib bits (backward compatibility)
static uint16_t parse_rfstation_code(RFStationData *data, ulong *on, ulong *off); // parse rf code into on/off/time sections
static void switch_rfstation(RFStationData *data, bool turnon); // switch rf station
static void switch_remotestation(RemoteStationData *data, bool turnon, uint16_t dur=0); // switch remote station
static void switch_gpiostation(GPIOStationData *data, bool turnon); // switch gpio station
static void switch_httpstation(HTTPStationData *data, bool turnon); // switch http station
// -- options and data storeage
static void nvdata_load();
static void nvdata_save();
static void options_setup();
static void pre_factory_reset();
static void factory_reset();
static void iopts_load();
static void iopts_save();
static bool sopt_save(byte oid, const char *buf);
static void sopt_load(byte oid, char *buf);
static String sopt_load(byte oid);
static void populate_master();
static byte password_verify(const char *pw); // verify password
// -- controller operation
static void enable(); // enable controller operation
static void disable(); // disable controller operation, all stations will be closed immediately
static void raindelay_start(); // start raindelay
static void raindelay_stop(); // stop rain delay
static void detect_binarysensor_status(time_t curr_time);// update binary (rain, soil) sensor status
static byte detect_programswitch_status(time_t curr_time); // get program switch status
static void sensor_resetall();
static uint16_t read_current(); // read current sensing value
static uint16_t baseline_current; // resting state current
static int detect_exp(); // detect the number of expansion boards
static byte weekday_today(); // returns index of today's weekday (Monday is 0)
static byte set_station_bit(byte sid, byte value, uint16_t dur=0); // set station bit of one station (sid->station index, value->0/1)
static void switch_special_station(byte sid, byte value, uint16_t dur=0); // swtich special station
static void clear_all_station_bits(); // clear all station bits
static void apply_all_station_bits(); // apply all station bits (activate/deactive values)
static int8_t send_http_request(uint32_t ip4, uint16_t port, char* p, void(*callback)(char*)=NULL, uint16_t timeout=5000);
static int8_t send_http_request(const char* server, uint16_t port, char* p, void(*callback)(char*)=NULL, uint16_t timeout=5000);
static int8_t send_http_request(char* server_with_port, char* p, void(*callback)(char*)=NULL, uint16_t timeout=5000);
// -- LCD functions
#if defined(ARDUINO) // LCD functions for Arduino
#if defined(ESP8266)
static void lcd_print_pgm(PGM_P str); // ESP8266 does not allow PGM_P followed by PROGMEM
static void lcd_print_line_clear_pgm(PGM_P str, byte line);
#else
static void lcd_print_pgm(PGM_P PROGMEM str); // print a program memory string
static void lcd_print_line_clear_pgm(PGM_P PROGMEM str, byte line);
#endif
static void lcd_print_time(time_t t); // print current time
static void lcd_print_ip(const byte *ip, byte endian); // print ip
static void lcd_print_mac(const byte *mac); // print mac
static void lcd_print_screen(char c); // print station bits of the board selected by display_board
static void lcd_print_version(byte v); // print version number
static String time2str(uint32_t t) {
uint16_t h = hour(t);
uint16_t m = minute(t);
uint16_t s = second(t);
String str = "";
str+=h/10;
str+=h%10;
str+=":";
str+=m/10;
str+=m%10;
str+=":";
str+=s/10;
str+=s%10;
return str;
}
// -- UI and buttons
static byte button_read(byte waitmode); // Read button value. options for 'waitmodes' are:
// BUTTON_WAIT_NONE, BUTTON_WAIT_RELEASE, BUTTON_WAIT_HOLD
// return values are 'OR'ed with flags
// check defines.h for details
// -- UI functions --
static void ui_set_options(int oid); // ui for setting options (oid-> starting option index)
static void lcd_set_brightness(byte value=1);
static void lcd_set_contrast();
#if defined(ESP8266)
static OTCConfig otc;
static IOEXP *mainio, *drio;
static IOEXP *expanders[];
static RCSwitch rfswitch;
static void detect_expanders();
static void flash_screen();
static void toggle_screen_led();
static void set_screen_led(byte status);
static byte get_wifi_mode() { if (useEth) return WIFI_MODE_STA; else return wifi_testmode ? WIFI_MODE_STA : iopts[IOPT_WIFI_MODE];}
static byte wifi_testmode;
static String wifi_ssid, wifi_pass;
static byte wifi_bssid[6], wifi_channel;
static void config_ip();
static void save_wifi_ip();
static void reset_to_ap();
static byte state;
#endif
private:
static void lcd_print_option(int i); // print an option to the lcd
static void lcd_print_2digit(int v); // print a integer in 2 digits
static void lcd_start();
static byte button_read_busy(byte pin_butt, byte waitmode, byte butt, byte is_holding);
#if defined(ESP8266)
static void parse_otc_config();
static void latch_boost();
static void latch_open(byte sid);
static void latch_close(byte sid);
static void latch_setzonepin(byte sid, byte value);
static void latch_setallzonepins(byte value);
static void latch_disable_alloutputs_v2();
static void latch_setzoneoutput_v2(byte sid, byte A, byte K);
static void latch_apply_all_station_bits();
static byte prev_station_bits[];
#endif
#endif // LCD functions
static byte engage_booster;
};
#endif // _OPENSPRINKLER_H