NodeManager.h 39.2 KB
Newer Older
DV's avatar
DV committed
1
2
3
4
5
6
7
8
/*
 * NodeManager
 */
#ifndef NodeManager_h
#define NodeManager_h

#include <Arduino.h>

user2684's avatar
user2684 committed
9
// define NodeManager version
user2684's avatar
user2684 committed
10
#define VERSION "1.6-dev"
DV's avatar
DV committed
11
12
13
14
15
16
17
18
19

/***********************************
   Constants
*/

// define sleep mode
#define IDLE 0
#define SLEEP 1
#define WAIT 2
20
#define ALWAYS_ON 3
DV's avatar
DV committed
21
22
23
24
25
26

// define time unit
#define SECONDS 0
#define MINUTES 1
#define HOURS 2
#define DAYS 3
27
#define CYCLES 4
DV's avatar
DV committed
28
29
30
31
32
33
34
35
36
37

// define value type
#define TYPE_INTEGER 0
#define TYPE_FLOAT 1
#define TYPE_STRING 2

// define interrupt pins
#define INTERRUPT_PIN_1 3
#define INTERRUPT_PIN_2 2

38
39
40
41
42
// define configuration settings that can be saved and loaded from the EEPROM
#define SAVE_SLEEP_MODE 0
#define SAVE_SLEEP_TIME 1
#define SAVE_SLEEP_UNIT 2

DV's avatar
DV committed
43
44
45
46
47
48
// define eeprom addresses
#define EEPROM_SLEEP_SAVED 0
#define EEPROM_SLEEP_MODE 1
#define EEPROM_SLEEP_TIME_MAJOR 2
#define EEPROM_SLEEP_TIME_MINOR 3
#define EEPROM_SLEEP_UNIT 4
49
50
51
#define EEPROM_USER_START 100

// define requests
DV's avatar
DV committed
52

DV's avatar
DV committed
53
54
55
56
57
/************************************
 * Include user defined configuration settings
 */
 
#include "config.h"
DV's avatar
DV committed
58
59

/***********************************
DV's avatar
DV committed
60
   Default configuration settings
DV's avatar
DV committed
61
*/
62
63
64
65
// if enabled, enable debug messages on serial port
#ifndef DEBUG
  #define DEBUG 1
#endif
DV's avatar
DV committed
66
67

// if enabled, enable the capability to power on sensors with the arduino's pins to save battery while sleeping
DV's avatar
DV committed
68
69
70
#ifndef POWER_MANAGER
  #define POWER_MANAGER 1
#endif
DV's avatar
DV committed
71
// if enabled, will load the battery manager library to allow the battery level to be reported automatically or on demand
DV's avatar
DV committed
72
73
74
#ifndef BATTERY_MANAGER
  #define BATTERY_MANAGER 1
#endif
DV's avatar
DV committed
75
// if enabled, allow modifying the configuration remotely by interacting with the configuration child id
DV's avatar
DV committed
76
77
78
#ifndef REMOTE_CONFIGURATION
  #define REMOTE_CONFIGURATION 1
#endif
DV's avatar
DV committed
79
// if enabled, persist the configuration settings on EEPROM
DV's avatar
DV committed
80
81
82
#ifndef PERSIST
  #define PERSIST 0
#endif
DV's avatar
DV committed
83
84

// if enabled, send a SLEEPING and AWAKE service messages just before entering and just after leaving a sleep cycle
DV's avatar
DV committed
85
#ifndef SERVICE_MESSAGES
86
  #define SERVICE_MESSAGES 0
DV's avatar
DV committed
87
#endif
DV's avatar
DV committed
88
// if enabled, a battery sensor will be created at BATTERY_CHILD_ID and will report vcc voltage together with the battery level percentage
DV's avatar
DV committed
89
90
91
#ifndef BATTERY_SENSOR
  #define BATTERY_SENSOR 1
#endif
DV's avatar
DV committed
92

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// the child id used to allow remote configuration
#ifndef CONFIGURATION_CHILD_ID
  #define CONFIGURATION_CHILD_ID 200
#endif
// the child id used to report the battery voltage to the controller
#ifndef BATTERY_CHILD_ID
  #define BATTERY_CHILD_ID 201
#endif
// define the maximum number of sensors that can be managed
#ifndef MAX_SENSORS
  #define MAX_SENSORS 10
#endif

/***********************************
   Default module settings
*/

110
// Enable this module to use one of the following sensors: SENSOR_ANALOG_INPUT, SENSOR_LDR, SENSOR_THERMISTOR, SENSOR_ACS712
DV's avatar
DV committed
111
112
113
#ifndef MODULE_ANALOG_INPUT
  #define MODULE_ANALOG_INPUT 0
#endif
DV's avatar
DV committed
114
// Enable this module to use one of the following sensors: SENSOR_DIGITAL_INPUT
DV's avatar
DV committed
115
116
117
#ifndef MODULE_DIGITAL_INPUT
  #define MODULE_DIGITAL_INPUT 0
#endif
DV's avatar
DV committed
118
// Enable this module to use one of the following sensors: SENSOR_DIGITAL_OUTPUT, SENSOR_RELAY, SENSOR_LATCHING_RELAY
DV's avatar
DV committed
119
120
121
#ifndef MODULE_DIGITAL_OUTPUT
  #define MODULE_DIGITAL_OUTPUT 0
#endif
DV's avatar
DV committed
122
// Enable this module to use one of the following sensors: SENSOR_SHT21, SENSOR_HTU21D
DV's avatar
DV committed
123
124
125
#ifndef MODULE_SHT21
  #define MODULE_SHT21 0
#endif
DV's avatar
DV committed
126
// Enable this module to use one of the following sensors: SENSOR_DHT11, SENSOR_DHT22
DV's avatar
DV committed
127
128
129
#ifndef MODULE_DHT
  #define MODULE_DHT 0
#endif
DV's avatar
DV committed
130
// Enable this module to use one of the following sensors: SENSOR_SWITCH, SENSOR_DOOR, SENSOR_MOTION
DV's avatar
DV committed
131
132
133
#ifndef MODULE_SWITCH
  #define MODULE_SWITCH 0
#endif
DV's avatar
DV committed
134
// Enable this module to use one of the following sensors: SENSOR_DS18B20
DV's avatar
DV committed
135
136
137
#ifndef MODULE_DS18B20
  #define MODULE_DS18B20 0
#endif
DV's avatar
DV committed
138
139
140
141
142
143
144
145
// Enable this module to use one of the following sensors: SENSOR_BH1750
#ifndef MODULE_BH1750
  #define MODULE_BH1750 0
#endif
// Enable this module to use one of the following sensors: SENSOR_MLX90614
#ifndef MODULE_MLX90614
  #define MODULE_MLX90614 0
#endif
146
147
148
149
// Enable this module to use one of the following sensors: SENSOR_BME280
#ifndef MODULE_BME280
  #define MODULE_BME280 0
#endif
150
151
152
153
154
155
156
157
158
159
160
161
// Enable this module to use one of the following sensors: SENSOR_SONOFF
#ifndef MODULE_SONOFF
  #define MODULE_SONOFF 0
#endif
// Enable this module to use one of the following sensors: SENSOR_BMP085
#ifndef MODULE_BMP085
  #define MODULE_BMP085 0
#endif
// Enable this module to use one of the following sensors: SENSOR_HCSR04
#ifndef MODULE_HCSR04
  #define MODULE_HCSR04 0
#endif
162
163
164
165
// Enable this module to use one of the following sensors: SENSOR_MCP9808
#ifndef MODULE_MCP9808
  #define MODULE_MCP9808 0
#endif
166
167
168
169
// Enable this module to use one of the following sensors: SENSOR_MQ
#ifndef MODULE_MQ
  #define MODULE_MQ 0
#endif
170

DV's avatar
DV committed
171
/***********************************
172
   Supported Sensors
DV's avatar
DV committed
173
*/
174
175
176
177
178
179
180
181
182
183
184
185
186
187
enum supported_sensors {
  #if MODULE_ANALOG_INPUT == 1
    // Generic analog sensor, return a pin's analog value or its percentage
    SENSOR_ANALOG_INPUT,
    // LDR sensor, return the light level of an attached light resistor in percentage
    SENSOR_LDR,
    // Thermistor sensor, return the temperature based on the attached thermistor
    SENSOR_THERMISTOR,
    // ML8511 UV sensor
    SENSOR_ML8511,
    // Current sensor
    SENSOR_ACS712,
    // rain gauge sensor
    SENSOR_RAIN_GAUGE,
188
189
190
191
    // Rain sensor, return the percentage of rain from an attached analog sensor
    SENSOR_RAIN,
    // Soil moisture sensor, return the percentage of moisture from an attached analog sensor
    SENSOR_SOIL_MOISTURE,
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
  #endif
  #if MODULE_DIGITAL_INPUT == 1
    // Generic digital sensor, return a pin's digital value
    SENSOR_DIGITAL_INPUT,
  #endif
  #if MODULE_DIGITAL_OUTPUT == 1
    // Generic digital output sensor, allows setting the digital output of a pin to the requested value
    SENSOR_DIGITAL_OUTPUT,
    // Relay sensor, allows activating the relay
    SENSOR_RELAY,
    // Latching Relay sensor, allows activating the relay with a pulse
    SENSOR_LATCHING_RELAY,
  #endif
  #if MODULE_DHT == 1
    // DHT11/DHT22 sensors, return temperature/humidity based on the attached DHT sensor
    SENSOR_DHT11,
    SENSOR_DHT22,
  #endif
  #if MODULE_SHT21 == 1
    // SHT21 sensor, return temperature/humidity based on the attached SHT21 sensor
    SENSOR_SHT21,
    SENSOR_HTU21D,
  #endif
  #if MODULE_SWITCH == 1
    // Generic switch, wake up the board when a pin changes status
    SENSOR_SWITCH,
    // Door sensor, wake up the board and report when an attached magnetic sensor has been opened/closed
    SENSOR_DOOR,
    // Motion sensor, wake up the board and report when an attached PIR has triggered
    SENSOR_MOTION,
  #endif
  #if MODULE_DS18B20 == 1
    // DS18B20 sensor, return the temperature based on the attached sensor
    SENSOR_DS18B20,
  #endif
  #if MODULE_BH1750 == 1
    // BH1750 sensor, return light in lux
    SENSOR_BH1750,
  #endif
  #if MODULE_MLX90614 == 1
    // MLX90614 sensor, contactless temperature sensor
    SENSOR_MLX90614,
  #endif
  #if MODULE_BME280 == 1
    // MLX90614 sensor, contactless temperature sensor
    SENSOR_BME280,
  #endif
  #if MODULE_SONOFF == 1
    // Sonoff wireless smart switch
    SENSOR_SONOFF,
  #endif
  #if MODULE_BMP085 == 1
    // BMP085/BMP180 sensor, return temperature and pressure
    SENSOR_BMP085,
  #endif
  #if MODULE_HCSR04 == 1
    // HC-SR04 sensor, return the distance between the sensor and an object
    SENSOR_HCSR04,
  #endif
  #if MODULE_MCP9808 == 1
    // MCP9808 sensor, precision temperature sensor
    SENSOR_MCP9808,
  #endif
255
256
257
258
  #if MODULE_MQ == 1
    // MQ2 air quality sensor
    SENSOR_MQ,
  #endif
259
};
DV's avatar
DV committed
260
261
262
263
/***********************************
  Libraries
*/

264
265
266
267
268
269
270
271
// include supporting libraries
#ifdef MY_USE_UDP
    #include <WiFiUdp.h>
#endif
#ifdef MY_GATEWAY_ESP8266
  #include <ESP8266WiFi.h>
#endif

DV's avatar
DV committed
272
273
// include MySensors libraries
#include <core/MySensorsCore.h>
274
#include <core/MyCapabilities.h>
DV's avatar
DV committed
275
276
277
278
279
280
281
282
283
284
285
286
287

// include third party libraries
#if MODULE_DHT == 1
  #include <DHT.h>
#endif
#if MODULE_SHT21 == 1
  #include <Wire.h>
  #include <Sodaq_SHT2x.h>
#endif
#if MODULE_DS18B20 == 1
  #include <OneWire.h>
  #include <DallasTemperature.h>
#endif
DV's avatar
DV committed
288
289
290
291
292
293
294
295
#if MODULE_BH1750 == 1
  #include <BH1750.h>
  #include <Wire.h>
#endif
#if MODULE_MLX90614 == 1
  #include <Wire.h>
  #include <Adafruit_MLX90614.h>
#endif
296
297
298
299
300
301
#if MODULE_BME280 == 1
  #include <Wire.h>
  #include <SPI.h>
  #include <Adafruit_Sensor.h>
  #include <Adafruit_BME280.h>
#endif
302
303
304
305
306
307
308
309
310
311
#if MODULE_SONOFF == 1
  #include <Bounce2.h>
#endif
#if MODULE_BMP085 == 1
  #include <Wire.h>
  #include <Adafruit_BMP085.h>
#endif
#if MODULE_HCSR04 == 1
  #include <NewPing.h>
#endif
312
313
314
315
#if MODULE_MCP9808 == 1
  #include <Wire.h>
  #include "Adafruit_MCP9808.h"
#endif
DV's avatar
DV committed
316

317
/*******************************************************************
DV's avatar
DV committed
318
319
   Classes
*/
320
class NodeManager;
DV's avatar
DV committed
321
322
323
324
325
326
327
328
329

/*
   PowerManager
*/

class PowerManager {
  public:
    PowerManager() {};
    // to save battery the sensor can be optionally connected to two pins which will act as vcc and ground and activated on demand
user2684's avatar
user2684 committed
330
    void setPowerPins(int ground_pin, int vcc_pin, int wait_time = 50);
331
    // turns the power pins on
DV's avatar
DV committed
332
    void powerOn();
333
    // turns the power pins on
DV's avatar
DV committed
334
    void powerOff();
335
    // returns the Vcc voltge
336
    float getVcc();
337
    // turns true if power pins are configured
user2684's avatar
user2684 committed
338
    bool isConfigured();
DV's avatar
DV committed
339
340
341
342
343
344
  private:
    int _vcc_pin = -1;
    int _ground_pin = -1;
    long _wait = 0;
};

345
346
347
/*
   Timer
*/
DV's avatar
DV committed
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
380
381
382
383
384
385
class Timer {
  public:
    Timer(NodeManager* node_manager);
    // start the timer which will be over when interval passes by. Unit can be either CYCLES or MINUTES
    void start(long target, int unit);
    void start();
    // stop the timer
    void stop();
    // set the timer configuration but do not start it
    void set(long target, int unit);
    // update the timer. To be called at every cycle
    void update();
    // returns true if the time is over
    bool isOver();
    // return true if the timer is running
    bool isRunning();
    // returns true if the timer has been configured
    bool isConfigured();
    // reset the timer and start over
    void restart();
    // return the current elapsed time
    float getElapsed();
    // return the configured unit
    int getUnit();
    // return the configured target
    int getTarget();
   private:
    NodeManager* _node_manager;
    long _target = 0;
    int _unit = 0;
    float _elapsed = 0;
    bool _use_millis = false;
    long _last_millis = 0;
    float _sleep_time = 0;
    bool _is_running = false;
    bool _is_configured = false;
};
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407

/*
   Request
*/

class Request {
  public:
    Request(const char* string);
    // return the parsed function
    int getFunction();
    // return the value as an int
    int getValueInt();
    // return the value as a float
    float getValueFloat();
    // return the value as a string
    char* getValueString();
   private:
    NodeManager* _node_manager;
    int _function;
    char* _value;
};

DV's avatar
DV committed
408
409
410
411
412
/***************************************
   Sensor: generic sensor class
*/
class Sensor {
  public:
413
    Sensor(NodeManager* node_manager, int child_id, int pin);
414
    // [1] where the sensor is attached to (default: not set)
DV's avatar
DV committed
415
416
    void setPin(int value);
    int getPin();
417
    // [2] child_id of this sensor (default: not set)
DV's avatar
DV committed
418
419
420
421
422
    void setChildId(int value);
    int getChildId();
    // presentation of this sensor (default: S_CUSTOM)
    void setPresentation(int value);
    int getPresentation();
423
    // [3] type of this sensor (default: V_CUSTOM)
DV's avatar
DV committed
424
425
    void setType(int value);
    int getType();
426
    // [4] description of the sensor (default: '')
user2684's avatar
user2684 committed
427
    void setDescription(char *value);
428
    // [5] For some sensors, the measurement can be queried multiple times and an average is returned (default: 1)
DV's avatar
DV committed
429
    void setSamples(int value);
430
    // [6] If more then one sample has to be taken, set the interval in milliseconds between measurements (default: 0)
DV's avatar
DV committed
431
    void setSamplesInterval(int value);
432
    // [7] if true will report the measure only if different than the previous one (default: false)
433
    void setTrackLastValue(bool value);
434
    // [8] if track last value is enabled, force to send an update after the configured number of cycles (default: -1)
DV's avatar
DV committed
435
    void setForceUpdate(int value);
436
    void setForceUpdateCycles(int value);
437
    // [9] if track last value is enabled, force to send an update after the configured number of minutes (default: -1)
438
    void setForceUpdateMinutes(int value);
439
    // [10] the value type of this sensor (default: TYPE_INTEGER)
DV's avatar
DV committed
440
    void setValueType(int value);
441
    int getValueType();
442
443
    // [11] for float values, set the float precision (default: 2)
    void  setFloatPrecision(int value);
DV's avatar
DV committed
444
445
    #if POWER_MANAGER == 1
      // to save battery the sensor can be optionally connected to two pins which will act as vcc and ground and activated on demand
user2684's avatar
user2684 committed
446
      void setPowerPins(int ground_pin, int vcc_pin, int wait_time = 50);
447
      // [12] if enabled the pins will be automatically powered on while awake and off during sleeping (default: true)
DV's avatar
DV committed
448
      void setAutoPowerPins(bool value);
449
      // [13] manually turn the power on
DV's avatar
DV committed
450
      void powerOn();
451
      // [14] manually turn the power off
DV's avatar
DV committed
452
453
      void powerOff();
    #endif
454
455
456
457
    // get the latest recorded value from the sensor
    int getValueInt();
    float getValueFloat();
    char* getValueString();
458
    // [15] After how many cycles the sensor will report back its measure (default: 1 cycle)
459
    void setReportIntervalCycles(int value);
460
    // [16] After how many minutes the sensor will report back its measure (default: 1 cycle)
461
    void setReportIntervalMinutes(int value);
462
463
    // process a remote request
    void process(Request & request);
464
465
    // return the pin the interrupt is attached to
    int getInterruptPin();
DV's avatar
DV committed
466
467
468
    // define what to do at each stage of the sketch
    virtual void before();
    virtual void presentation();
user2684's avatar
user2684 committed
469
    virtual void setup();
DV's avatar
DV committed
470
471
472
473
    virtual void loop(const MyMessage & message);
    virtual void receive(const MyMessage & message);
    // abstract functions, subclasses need to implement
    virtual void onBefore() = 0;
user2684's avatar
user2684 committed
474
    virtual void onSetup() = 0;
DV's avatar
DV committed
475
476
    virtual void onLoop() = 0;
    virtual void onReceive(const MyMessage & message) = 0;
477
    virtual void onProcess(Request & request) = 0;
DV's avatar
DV committed
478
479
  protected:
    MyMessage _msg;
480
    MyMessage _msg_service;
481
    NodeManager* _node_manager;
DV's avatar
DV committed
482
483
484
485
    int _pin = -1;
    int _child_id;
    int _presentation = S_CUSTOM;
    int _type = V_CUSTOM;
user2684's avatar
user2684 committed
486
    char* _description = "";
DV's avatar
DV committed
487
488
489
490
491
492
493
494
495
496
497
    int _samples = 1;
    int _samples_interval = 0;
    bool _track_last_value = false;
    int _value_type = TYPE_INTEGER;
    int _float_precision = 2;
    int _value_int = -1;
    float _value_float = -1;
    char * _value_string = "";
    int _last_value_int = -1;
    float _last_value_float = -1;
    char * _last_value_string = "";
498
499
500
501
502
    int _interrupt_pin = -1;
    #if POWER_MANAGER  == 1
      PowerManager _powerManager;
      bool _auto_power_pins = true;
    #endif
503
504
    Timer* _report_timer;
    Timer* _force_update_timer;
505
    void _send(MyMessage & msg);
506
507
    bool _isReceive(const MyMessage & message);
    bool _isWorthSending(bool comparison);
DV's avatar
DV committed
508
509
};

510
#if MODULE_ANALOG_INPUT == 1
DV's avatar
DV committed
511
512
513
514
515
/*
   SensorAnalogInput: read the analog input of a configured pin
*/
class SensorAnalogInput: public Sensor {
  public:
516
    SensorAnalogInput(NodeManager* node_manager, int child_id, int pin);
517
    // [101] the analog reference to use (default: not set, can be either INTERNAL or DEFAULT)
DV's avatar
DV committed
518
    void setReference(int value);
519
    // [102] reverse the value or the percentage (e.g. 70% -> 30%) (default: false)
DV's avatar
DV committed
520
    void setReverse(bool value);
521
    // [103] when true returns the value as a percentage (default: true)
DV's avatar
DV committed
522
    void setOutputPercentage(bool value);
523
    // [104] minimum value for calculating the percentage (default: 0)
DV's avatar
DV committed
524
    void setRangeMin(int value);
525
    // [105] maximum value for calculating the percentage (default: 1024)
DV's avatar
DV committed
526
527
528
    void setRangeMax(int value);
    // define what to do at each stage of the sketch
    void onBefore();
user2684's avatar
user2684 committed
529
    void onSetup();
DV's avatar
DV committed
530
531
    void onLoop();
    void onReceive(const MyMessage & message);
532
    void onProcess(Request & request);
DV's avatar
DV committed
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
  protected:
    int _reference = -1;
    bool _reverse = false;
    bool _output_percentage = true;
    int _range_min = 0;
    int _range_max = 1024;
    int _getPercentage(int value);
    int _getAnalogRead();
};

/*
   SensorLDR: return the percentage of light from a Light dependent resistor
*/
class SensorLDR: public SensorAnalogInput {
  public:
548
    SensorLDR(NodeManager* node_manager, int child_id, int pin);
DV's avatar
DV committed
549
550
551
552
553
554
555
};

/*
   SensorThermistor: read the temperature from a thermistor
*/
class SensorThermistor: public Sensor {
  public:
556
    SensorThermistor(NodeManager* node_manager, int child_id, int pin);
557
    // [101] resistance at 25 degrees C (default: 10000)
558
    void setNominalResistor(long value);
559
    // [102] temperature for nominal resistance (default: 25)
DV's avatar
DV committed
560
    void setNominalTemperature(int value);
561
    // [103] The beta coefficient of the thermistor (default: 3950)
DV's avatar
DV committed
562
    void setBCoefficient(int value);
563
    // [104] the value of the resistor in series with the thermistor (default: 10000)
564
    void setSeriesResistor(long value);
565
    // [105] set a temperature offset
DV's avatar
DV committed
566
567
568
    void setOffset(float value);
    // define what to do at each stage of the sketch
    void onBefore();
user2684's avatar
user2684 committed
569
    void onSetup();
DV's avatar
DV committed
570
571
    void onLoop();
    void onReceive(const MyMessage & message);
572
    void onProcess(Request & request);
DV's avatar
DV committed
573
  protected:
574
    long _nominal_resistor = 10000;
DV's avatar
DV committed
575
576
    int _nominal_temperature = 25;
    int _b_coefficient = 3950;
577
    long _series_resistor = 10000;
DV's avatar
DV committed
578
579
580
    float _offset = 0;
};

581
582
/*
    SensorML8511
583
*/
584
585
586

class SensorML8511: public Sensor {
  public:
587
    SensorML8511(NodeManager* node_manager, int child_id, int pin);
588
589
590
591
592
    // define what to do at each stage of the sketch
    void onBefore();
    void onSetup();
    void onLoop();
    void onReceive(const MyMessage & message);
593
    void onProcess(Request & request);
594
595
596
  protected:
    float _mapfloat(float x, float in_min, float in_max, float out_min, float out_max);
};
597
598
599
600
601
602
603

/*
    SensorACS712
*/

class SensorACS712: public Sensor {
  public:
604
    SensorACS712(NodeManager* node_manager, int child_id, int pin);
605
    // [101] set how many mV are equivalent to 1 Amp. The value depends on the module (100 for 20A Module, 66 for 30A Module) (default: 185);
606
    void setmVPerAmp(int value);
607
    // [102] set ACS offset (default: 2500);
608
609
610
611
612
613
    void setOffset(int value);
    // define what to do at each stage of the sketch
    void onBefore();
    void onSetup();
    void onLoop();
    void onReceive(const MyMessage & message);
614
    void onProcess(Request & request);
615
616
617
618
  protected:
    int _ACS_offset = 2500;
    int _mv_per_amp = 185;
};
619
620
621
622
623
624
625

/*
    SensorRainGauge
*/

class SensorRainGauge: public Sensor {
  public:
626
    SensorRainGauge(NodeManager* node_manager, int child_id, int pin);
627
    // [101] set how frequently to report back to the controller in minutes. After reporting the measure is resetted (default: 60)
628
    void setReportInterval(int value);
629
    // [102] set how many mm of rain to count for each tip (default: 0.11)
630
631
632
633
634
635
    void setSingleTip(float value);
    // define what to do at each stage of the sketch
    void onBefore();
    void onSetup();
    void onLoop();
    void onReceive(const MyMessage & message);
636
    void onProcess(Request & request);
637
638
639
640
641
  public:
    static void _onTipped();
    static long _last_tip;
    static long _count;
  protected:
642
    int _report_interval = 60;
643
    float _single_tip = 0.11;
644
    Timer* _timer;
645
};
646

647
648
649
650
651
/*
   SensorRain
*/
class SensorRain: public SensorAnalogInput {
  public:
652
    SensorRain(NodeManager* node_manager, int child_id, int pin);
653
654
655
656
657
658
659
};

/*
   SensorSoilMoisture
*/
class SensorSoilMoisture: public SensorAnalogInput {
  public:
660
    SensorSoilMoisture(NodeManager* node_manager, int child_id, int pin);
661
};
662
#endif
663

664
665

#if MODULE_DIGITAL_INPUT == 1
DV's avatar
DV committed
666
667
668
669
670
/*
   SensorDigitalInput: read the digital input of the configured pin
*/
class SensorDigitalInput: public Sensor {
  public:
671
    SensorDigitalInput(NodeManager* node_manager, int child_id, int pin);
DV's avatar
DV committed
672
673
    // define what to do at each stage of the sketch
    void onBefore();
user2684's avatar
user2684 committed
674
    void onSetup();
DV's avatar
DV committed
675
676
    void onLoop();
    void onReceive(const MyMessage & message);
677
    void onProcess(Request & request);
DV's avatar
DV committed
678
};
679
#endif
DV's avatar
DV committed
680

681
#if MODULE_DIGITAL_OUTPUT == 1
DV's avatar
DV committed
682
683
684
685
686
/*
   SensorDigitalOutput: control a digital output of the configured pin
*/
class SensorDigitalOutput: public Sensor {
  public:
687
    SensorDigitalOutput(NodeManager* node_manager, int child_id, int pin);
688
    // [101] set how to initialize the output (default: LOW)
DV's avatar
DV committed
689
    void setInitialValue(int value);
690
    // [102] if greater than 0, send a pulse of the given duration in ms and then restore the output back to the original value (default: 0)
DV's avatar
DV committed
691
    void setPulseWidth(int value);
692
    // [103] define which value to set to the output when set to on (default: HIGH)
693
    void setOnValue(int value);
694
    // [104] when legacy mode is enabled expect a REQ message to trigger, otherwise the default SET (default: false)
695
    void setLegacyMode(bool value);
696
    // [105] automatically turn the output off after the given number of minutes
697
    void setSafeguard(int value);
698
    // [106] if true the input value becomes a duration in minutes after which the output will be automatically turned off (default: false)
699
700
701
702
703
    void setInputIsElapsed(bool value);
    // manually switch the output to the provided value
    void set(int value);
    // get the current state
    int getState();
DV's avatar
DV committed
704
705
    // define what to do at each stage of the sketch
    void onBefore();
user2684's avatar
user2684 committed
706
    void onSetup();
DV's avatar
DV committed
707
708
    void onLoop();
    void onReceive(const MyMessage & message);
709
    void onProcess(Request & request);
DV's avatar
DV committed
710
711
  protected:
    int _initial_value = LOW;
712
    int _on_value = HIGH;
713
    int _state = 0;
DV's avatar
DV committed
714
    int _pulse_width = 0;
715
    bool _legacy_mode = false;
716
717
    bool _input_is_elapsed = false;
    Timer* _safeguard_timer;
DV's avatar
DV committed
718
719
720
721
722
723
724
725
};


/*
   SensorRelay
*/
class SensorRelay: public SensorDigitalOutput {
  public:
726
    SensorRelay(NodeManager* node_manager, int child_id, int pin);
DV's avatar
DV committed
727
728
729
730
731
732
733
};

/*
   SensorLatchingRelay
*/
class SensorLatchingRelay: public SensorRelay {
  public:
734
    SensorLatchingRelay(NodeManager* node_manager, int child_id, int pin);
DV's avatar
DV committed
735
};
736
#endif
DV's avatar
DV committed
737
738
739
740
741
742
743

/*
   SensorDHT
*/
#if MODULE_DHT == 1
class SensorDHT: public Sensor {
  public:
744
    SensorDHT(NodeManager* node_manager, int child_id, int pin, DHT* dht, int sensor_type, int dht_type);
DV's avatar
DV committed
745
746
    // define what to do at each stage of the sketch
    void onBefore();
user2684's avatar
user2684 committed
747
    void onSetup();
DV's avatar
DV committed
748
749
    void onLoop();
    void onReceive(const MyMessage & message);
750
    void onProcess(Request & request);
751
752
753
    // constants
    const static int TEMPERATURE = 0;
    const static int HUMIDITY = 1;
DV's avatar
DV committed
754
755
756
757
758
759
760
761
762
  protected:
    DHT* _dht;
    int _dht_type = DHT11;
    float _offset = 0;
    int _sensor_type = 0;
};
#endif

/*
DV's avatar
DV committed
763
   SensorSHT21: temperature and humidity sensor
DV's avatar
DV committed
764
765
766
767
*/
#if MODULE_SHT21 == 1
class SensorSHT21: public Sensor {
  public:
768
    SensorSHT21(NodeManager* node_manager, int child_id, int sensor_type);
DV's avatar
DV committed
769
770
    // define what to do at each stage of the sketch
    void onBefore();
user2684's avatar
user2684 committed
771
    void onSetup();
DV's avatar
DV committed
772
773
    void onLoop();
    void onReceive(const MyMessage & message);
774
    void onProcess(Request & request);
775
776
777
    // constants
    const static int TEMPERATURE = 0;
    const static int HUMIDITY = 1;
DV's avatar
DV committed
778
779
780
781
  protected:
    float _offset = 0;
    int _sensor_type = 0;
};
DV's avatar
DV committed
782
783
784
785
786
787
788

/*
   SensorHTU21D: temperature and humidity sensor
*/

class SensorHTU21D: public SensorSHT21 {
  public:
789
    SensorHTU21D(NodeManager* node_manager, int child_id, int pin);
DV's avatar
DV committed
790
};
DV's avatar
DV committed
791
792
793
794
795
#endif

/*
 * SensorSwitch
 */
796
#if MODULE_SWITCH == 1
DV's avatar
DV committed
797
798
class SensorSwitch: public Sensor {
  public:
799
    SensorSwitch(NodeManager* node_manager, int child_id, int pin);
800
    // [101] set the interrupt mode. Can be CHANGE, RISING, FALLING (default: CHANGE)
DV's avatar
DV committed
801
    void setMode(int value);
802
    // [102] milliseconds to wait before reading the input (default: 0)
DV's avatar
DV committed
803
    void setDebounce(int value);
804
    // [103] time to wait in milliseconds after a change is detected to allow the signal to be restored to its normal value (default: 0)
DV's avatar
DV committed
805
    void setTriggerTime(int value);
806
    // [104] Set initial value on the interrupt pin (default: HIGH)
807
    void setInitial(int value);
DV's avatar
DV committed
808
809
    // define what to do at each stage of the sketch
    void onBefore();
user2684's avatar
user2684 committed
810
    void onSetup();
DV's avatar
DV committed
811
812
    void onLoop();
    void onReceive(const MyMessage & message);
813
    void onProcess(Request & request);
DV's avatar
DV committed
814
815
816
817
  protected:
    int _debounce = 0;
    int _trigger_time = 0;
    int _mode = CHANGE;
818
    int _initial = HIGH;
DV's avatar
DV committed
819
820
821
822
823
824
825
};

/*
 * SensorDoor
 */
class SensorDoor: public SensorSwitch {
  public:
826
    SensorDoor(NodeManager* node_manager, int child_id, int pin);
DV's avatar
DV committed
827
828
829
830
831
832
833
};

/*
 * SensorMotion
 */
class SensorMotion: public SensorSwitch {
  public:
834
    SensorMotion(NodeManager* node_manager, int child_id, int pin);
DV's avatar
DV committed
835
};
836
#endif
DV's avatar
DV committed
837
838
839
840
841
842
/*
   SensorDs18b20
*/
#if MODULE_DS18B20 == 1
class SensorDs18b20: public Sensor {
  public:
843
    SensorDs18b20(NodeManager* node_manager, int child_id, int pin, DallasTemperature* sensors, int index);
user2684's avatar
user2684 committed
844
845
    // returns the sensor's resolution in bits
    int getResolution();
846
    // [101] set the sensor's resolution in bits
user2684's avatar
user2684 committed
847
    void setResolution(int value);
848
    // [102] sleep while DS18B20 calculates temperature (default: false)
849
    void setSleepDuringConversion(bool value);
850
851
    // return the sensors' device address
    DeviceAddress* getDeviceAddress();
852
853
854
855
856
    // define what to do at each stage of the sketch
    void onBefore();
    void onSetup();
    void onLoop();
    void onReceive(const MyMessage & message);
857
    void onProcess(Request & request);
DV's avatar
DV committed
858
859
860
  protected:
    float _offset = 0;
    int _index;
861
    bool _sleep_during_conversion = false;
DV's avatar
DV committed
862
    DallasTemperature* _sensors;
user2684's avatar
user2684 committed
863
    DeviceAddress _device_address;
DV's avatar
DV committed
864
865
866
};
#endif

DV's avatar
DV committed
867
868
869
870
871
872
/*
   SensorBH1750
*/
#if MODULE_BH1750 == 1
class SensorBH1750: public Sensor {
  public:
873
    SensorBH1750(NodeManager* node_manager, int child_id);
DV's avatar
DV committed
874
875
    // define what to do at each stage of the sketch
    void onBefore();
user2684's avatar
user2684 committed
876
    void onSetup();
DV's avatar
DV committed
877
878
    void onLoop();
    void onReceive(const MyMessage & message);
879
    void onProcess(Request & request);
DV's avatar
DV committed
880
881
882
883
884
885
886
887
888
889
890
  protected:
    BH1750* _lightSensor;
};
#endif

/*
   SensorMLX90614
*/
#if MODULE_MLX90614 == 1
class SensorMLX90614: public Sensor {
  public:
891
    SensorMLX90614(NodeManager* node_manager, int child_id, Adafruit_MLX90614* mlx, int sensor_type);
DV's avatar
DV committed
892
893
    // define what to do at each stage of the sketch
    void onBefore();
user2684's avatar
user2684 committed
894
    void onSetup();
DV's avatar
DV committed
895
896
    void onLoop();
    void onReceive(const MyMessage & message);
897
    void onProcess(Request & request);
898
899
900
    // constants
    const static int TEMPERATURE_AMBIENT = 0;
    const static int TEMPERATURE_OBJECT = 1;
DV's avatar
DV committed
901
902
903
904
905
  protected:
    Adafruit_MLX90614* _mlx;
    int _sensor_type;
};
#endif
DV's avatar
DV committed
906

907

908
/*
909
 * SensorBosch
910
*/
911
912
913

#if MODULE_BME280 == 1 || MODULE_BMP085 == 1
class SensorBosch: public Sensor {
914
  public:
915
    SensorBosch(NodeManager* node_manager, int child_id, int sensor_type);
916
    // [101] define how many pressure samples to keep track of for calculating the forecast (default: 5)
user2684's avatar
user2684 committed
917
    void setForecastSamplesCount(int value);
918
919
    // define what to do at each stage of the sketch
    void onBefore();
user2684's avatar
user2684 committed
920
    void onSetup();
921
922
    void onLoop();
    void onReceive(const MyMessage & message);
923
    void onProcess(Request & request);
924
925
926
927
928
929
    // constants
    const static int TEMPERATURE = 0;
    const static int HUMIDITY = 1;
    const static int PRESSURE = 2;
    const static int FORECAST = 3;
    static uint8_t GetI2CAddress(uint8_t chip_id);
930
931
  protected:
    int _sensor_type;
user2684's avatar
user2684 committed
932
933
934
935
936
937
938
939
940
    char* _weather[6] = { "stable", "sunny", "cloudy", "unstable", "thunderstorm", "unknown" };
    int _forecast_samples_count = 5;
    float* _forecast_samples;
    int _minute_count = 0;
    float _pressure_avg;
    float _pressure_avg2;
    float _dP_dt;
    bool _first_round = true;
    float _getLastPressureSamplesAverage();
941
942
943
944
945
946
947
948
949
950
    void _forecast(float pressure);
};
#endif

/*
   SensorBME280
*/
#if MODULE_BME280 == 1
class SensorBME280: public SensorBosch {
  public:
951
    SensorBME280(NodeManager* node_manager, int child_id, Adafruit_BME280* bme, int sensor_type);
952
953
954
955
956
957
958
959
960
961
962
963
    void onLoop();
  protected:
    Adafruit_BME280* _bme;
};
#endif

/*
   SensorBMP085
*/
#if MODULE_BMP085 == 1
class SensorBMP085: public SensorBosch {
  public:
964
    SensorBMP085(NodeManager* node_manager, int child_id, Adafruit_BMP085* bmp, int sensor_type);
965
966
967
    void onLoop();
  protected:
    Adafruit_BMP085* _bmp;
968
969
970
};
#endif

971
972
973
974
975
976
/*
   SensorHCSR04
*/
#if MODULE_HCSR04 == 1
class SensorHCSR04: public Sensor {
  public:
977
    SensorHCSR04(NodeManager* node_manager, int child_id, int pin);
978
    // [101] Arduino pin tied to trigger pin on the ultrasonic sensor (default: the pin set while registering the sensor)
979
    void setTriggerPin(int value);
980
    // [102] Arduino pin tied to echo pin on the ultrasonic sensor (default: the pin set while registering the sensor)
981
    void setEchoPin(int value);
982
    // [103] Maximum distance we want to ping for (in centimeters) (default: 300)
983
984
985
986
987
988
    void setMaxDistance(int value);
    // define what to do at each stage of the sketch
    void onBefore();
    void onSetup();
    void onLoop();
    void onReceive(const MyMessage & message);
989
    void onProcess(Request & request);
990
991
992
993
994
995
996
  protected:
    int _trigger_pin;
    int _echo_pin;
    int _max_distance = 300;
    NewPing* _sonar;
};
#endif
997

998
999
1000
1001
1002
1003
/*
   SensorSonoff
*/
#if MODULE_SONOFF == 1
class SensorSonoff: public Sensor {
  public:
1004
    SensorSonoff(NodeManager* node_manager, int child_id);
1005
    // [101] set the button's pin (default: 0)
1006
    void setButtonPin(int value);
1007
    // [102] set the relay's pin (default: 12)
1008
    void setRelayPin(int value);
1009
    // [103] set the led's pin (default: 13)
1010
1011
1012
1013
1014
1015
    void setLedPin(int value);
    // define what to do at each stage of the sketch
    void onBefore();
    void onSetup();
    void onLoop();
    void onReceive(const MyMessage & message);
1016
    void onProcess(Request & request);
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
  protected:
    Bounce _debouncer = Bounce();
    int _button_pin = 0;
    int _relay_pin = 12;
    int _led_pin = 13;
    int _old_value = 0;
    bool _state = false;
    int _relay_on = 1;
    int _relay_off = 0;
    int _led_on = 0;
    int _led_off = 1;
    void _blink();
    void _toggle();
};
#endif

1033
1034
1035
1036
1037
1038
/*
   SensorMCP9808
*/
#if MODULE_MCP9808 == 1
class SensorMCP9808: public Sensor {
  public:
1039
    SensorMCP9808(NodeManager* node_manager, int child_id, Adafruit_MCP9808* mcp);
1040
1041
1042
1043
1044
    // define what to do at each stage of the sketch
    void onBefore();
    void onSetup();
    void onLoop();
    void onReceive(const MyMessage & message);
1045
    void onProcess(Request & request);
1046
1047
1048
1049
1050
  protected:
    Adafruit_MCP9808* _mcp;
};
#endif

1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
/*
    SensorMQ
 */
 #if MODULE_MQ == 1
class SensorMQ: public Sensor {
  public:
    SensorMQ(NodeManager* node_manager, int child_id, int pin);
    // [101] define the target gas whose ppm has to be returned. 0: LPG, 1: CO, 2: Smoke (default: 1);
    void setTargetGas(int value);
    // [102] define the load resistance on the board, in kilo ohms (default: 1);
    void setRlValue(float value);
    // [103] define the Ro resistance on the board (default: 10000);
    void setRoValue(float value);
    // [104] Sensor resistance in clean air (default: 9.83);
    void setCleanAirFactor(float value);
    // [105] define how many samples you are going to take in the calibration phase (default: 50);
    void setCalibrationSampleTimes(int value);
    // [106] define the time interal(in milisecond) between each samples in the cablibration phase (default: 500);
    void setCalibrationSampleInterval(int value);
    // [107] define how many samples you are going to take in normal operation (default: 50);
    void setReadSampleTimes(int value);
    // [108] define the time interal(in milisecond) between each samples in the normal operations (default: 5);
    void setReadSampleInterval(int value);
    // set the LPGCurve array (default: {2.3,0.21,-0.47})
    void setLPGCurve(float *value);
    // set the COCurve array (default: {2.3,0.72,-0.34})
    void setCOCurve(float *value);
    // set the SmokeCurve array (default: {2.3,0.53,-0.44})
    void setSmokeCurve(float *value);
    // define what to do at each stage of the sketch
    void onBefore();
    void onSetup();
    void onLoop();
    void onReceive(const MyMessage & message);
    void onProcess(Request & request);
  protected:
    float _rl_value = 1.0;
    float _ro_clean_air_factor = 9.83;
    int _calibration_sample_times = 50;
    int _calibration_sample_interval = 500;
    int _read_sample_interval = 50;
    int _read_sample_times = 5;
    float _ro = 10000.0;
    float _LPGCurve[3] = {2.3,0.21,-0.47};
    float _COCurve[3] = {2.3,0.72,-0.34};
    float _SmokeCurve[3] = {2.3,0.53,-0.44};
    float _MQResistanceCalculation(int raw_adc);
    float _MQCalibration();
    float _MQRead();
    int _MQGetGasPercentage(float rs_ro_ratio, int gas_id);
    int  _MQGetPercentage(float rs_ro_ratio, float *pcurve);
    int _gas_lpg = 0;
    int _gas_co = 1;
    int _gas_smoke = 2;
    int _target_gas = _gas_co;
};
#endif
user2684's avatar
user2684 committed
1108

DV's avatar
DV committed
1109
1110
1111
1112
1113
1114
/***************************************
   NodeManager: manages all the aspects of the node
*/
class NodeManager {
  public:
    NodeManager();
1115
    // [10] send the same service message multiple times (default: 1)
DV's avatar
DV committed
1116
    void setRetries(int value);
1117
    int getRetries();
DV's avatar
DV committed
1118
    #if BATTERY_MANAGER == 1
1119
      // [11] the expected vcc when the batter is fully discharged, used to calculate the percentage (default: 2.7)
DV's avatar
DV committed
1120
      void setBatteryMin(float value);
1121
      // [12] the expected vcc when the batter is fully charged, used to calculate the percentage (default: 3.3)
DV's avatar
DV committed
1122
      void setBatteryMax(float value);
1123
      // [13] after how many sleeping cycles report the battery level to the controller. When reset the battery is always reported (default: -)
DV's avatar
DV committed
1124
      void setBatteryReportCycles(int value);
1125
      // [14] after how many minutes report the battery level to the controller. When reset the battery is always reported (default: 60)
1126
      void setBatteryReportMinutes(int value);
1127
      // [15] if true, the battery level will be evaluated by measuring the internal vcc without the need to connect any pin, if false the voltage divider methon will be used (default: true)
1128
      void setBatteryInternalVcc(bool value);
1129
      // [16] if setBatteryInternalVcc() is set to false, the analog pin to which the battery's vcc is attached (https://www.mysensors.org/build/battery) (default: -1)
1130
      void setBatteryPin(int value);
1131
      // [17] if setBatteryInternalVcc() is set to false, the volts per bit ratio used to calculate the battery voltage (default: 0.003363075)
1132
      void setBatteryVoltsPerBit(float value);
1133
      // [18] If true, wake up by an interrupt counts as a valid cycle for battery reports otherwise only uninterrupted sleep cycles would contribute (default: true)
1134
      void setBatteryReportWithInterrupt(bool value);
1135
1136
      // [2] Send a battery level report to the controller
      void batteryReport();
DV's avatar
DV committed
1137
    #endif
1138
    // [3] define the way the node should behave. It can be (0) IDLE (stay awake withtout executing each sensors' loop), (1) SLEEP (go to sleep for the configured interval), (2) WAIT (wait for the configured interval), (3) ALWAYS_ON (stay awake and execute each sensors' loop)
1139
1140
    void setSleepMode(int value);
    void setMode(int value);
1141
    int getMode();
1142
    // [4] define for how long the board will sleep (default: 0)
1143
    void setSleepTime(int value);
1144
    int getSleepTime();
1145
    // [5] define the unit of SLEEP_TIME. It can be SECONDS, MINUTES, HOURS or DAYS (default: MINUTES)
1146
    void setSleepUnit(int value);
1147
    int getSleepUnit();
1148
1149
    // configure the node's behavior, parameters are mode, time and unit
    void setSleep(int value1, int value2, int value3);
1150
    // [19] if enabled, when waking up from the interrupt, the board stops sleeping. Disable it when attaching e.g. a motion sensor (default: true)
1151
    void setSleepInterruptPin(int value);
DV's avatar
DV committed
1152
1153
    // configure the interrupt pin and mode. Mode can be CHANGE, RISING, FALLING (default: MODE_NOT_DEFINED)
    void setInterrupt(int pin, int mode, int pull = -1);
1154
    // [20] optionally sleep interval in milliseconds before sending each message to the radio network (default: 0)
DV's avatar
DV committed
1155
    void setSleepBetweenSend(int value);
1156
    int getSleepBetweenSend();
DV's avatar
DV committed
1157
1158
1159
1160
    // register a built-in sensor
    int registerSensor(int sensor_type, int pin = -1, int child_id = -1);
    // register a custom sensor
    int registerSensor(Sensor* sensor);
1161
    // [26] un-register a sensor
1162
    void unRegisterSensor(int sensor_index);
DV's avatar
DV committed
1163
1164
    // return a sensor by its index
    Sensor* get(int sensor_index);
user2684's avatar
user2684 committed
1165
1166
1167
    Sensor* getSensor(int sensor_index);
    // assign a different child id to a sensor
    bool renameSensor(int old_child_id, int new_child_id);
DV's avatar
DV committed
1168
1169
    #if POWER_MANAGER == 1
      // to save battery the sensor can be optionally connected to two pins which will act as vcc and ground and activated on demand
user2684's avatar
user2684 committed
1170
      void setPowerPins(int ground_pin, int vcc_pin, int wait_time = 50);
1171
      // [23] if enabled the pins will be automatically powered on while awake and off during sleeping (default: true)
DV's avatar
DV committed
1172
      void setAutoPowerPins(bool value);
1173
      // [24] manually turn the power on
DV's avatar
DV committed
1174
      void powerOn();
1175
      // [25] manually turn the power off
DV's avatar
DV committed
1176
1177
      void powerOff();
    #endif
1178
    // [21] set this to true if you want destination node to send ack back to this node (default: false)
user2684's avatar
user2684 committed
1179
    void setAck(bool value);
1180