-
Notifications
You must be signed in to change notification settings - Fork 0
/
RG9.h
130 lines (112 loc) · 2.92 KB
/
RG9.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
#include "esphome.h"
class RG9Component : public PollingComponent, public UARTDevice, public CustomAPIDevice {
public:
RG9Component(UARTComponent *parent) : PollingComponent(1000), UARTDevice(parent)
{
bzero(samples, sizeof(samples));
nextSample = 0;
lastFallPerMin = 600;
}
uint8_t line[64];
int lastPoll;
uint16_t pollCount;
uint16_t failCount;
Sensor *rainIntensity = new Sensor();
Sensor *rainFallPerMin = new Sensor();
uint8_t samples[60];
uint8_t nextSample;
unsigned lastFallPerMin;
bool readLine()
{
bzero(line, sizeof(line));
unsigned int i = 0;
unsigned int n = 0;
while ((n = available()) == 0) {
if (i++ > 1000) return false;
}
if (n >= sizeof(line)) n = sizeof(line)-1;
read_array(line, n);
for (unsigned int i = 0; i < n; i++) {
if (line[i] == '\0') line[i] = '\n';
}
char tmp[128];
sprintf(tmp, "%d: %s", n, line);
ESP_LOGD("RG9", (char*) tmp);
return true;
}
int parseLine()
{
int rc = -1;
uint8_t *p = line;
while (1) {
while (*p++ != 'R') {
if (*p == '\0') return rc;
}
while (isspace(*p)) p++;
int val = *p - '0';
if (0 <= val && val <= 9) rc = val;
}
return rc;
}
float get_setup_priority() const override
{
return esphome::setup_priority::LATE;
}
void setup() override
{
lastPoll = -1;
pollCount = 0;
failCount = 0;
register_service(&RG9Component::on_reset, "reset");
}
void on_reset()
{
pollCount = 50;
ESP_LOGD("RG9", "Resetting RG-9...");
}
void update() override
{
if (pollCount++ == 55) {
// Reset the device and put in continuous mode approx every day
// 65536 seconds is 18.2 hours...
write_str("K\n");
flush();
return;
}
if (pollCount == 60) {
write_str("P\n");
}
write_str("R\n");
flush();
// Response: "R [0123456789]\n"
if (readLine()) {
int state = parseLine();
if (state >= 0) {
polledState(state);
return;
}
}
// If we can't read the sensor for an hour, something is wrong
if (failCount++ > 3600) {
lastPoll = -1;
polledState(-1);
}
}
void polledState(int state)
{
failCount = 0;
samples[nextSample] = state;
if (++nextSample >= 60) nextSample = 0;
if (nextSample % 10 == 0) {
uint8_t prevMin = 0;
for (unsigned i = 0; i < 60; i++) {
prevMin += samples[i];
}
if (prevMin != lastFallPerMin) rainFallPerMin->publish_state(prevMin);
lastFallPerMin = prevMin;
}
if (lastPoll == state) return;
rainIntensity->publish_state(state);
lastPoll = state;
}
};