10
10
#include < OLEDDisplay.h>
11
11
#include < OLEDDisplayUi.h>
12
12
13
- EnvironmentalMeasurementPlugin *environmentalMeasurementPlugin;
14
- EnvironmentalMeasurementPluginRadio *environmentalMeasurementPluginRadio;
15
-
16
- EnvironmentalMeasurementPlugin::EnvironmentalMeasurementPlugin () : concurrency::OSThread(" EnvironmentalMeasurementPlugin" ) {}
17
-
18
- uint32_t sensor_read_error_count = 0 ;
19
-
20
- #define DHT_11_GPIO_PIN 13
21
13
#define DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000 // Some sensors (the DHT11) have a minimum required duration between read attempts
22
14
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
23
15
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
24
16
25
- DHT dht (DHT_11_GPIO_PIN,DHT11);
26
-
27
17
28
18
#ifdef HAS_EINK
29
19
// The screen is bigger so use bigger fonts
@@ -49,11 +39,15 @@ int32_t EnvironmentalMeasurementPlugin::runOnce() {
49
39
Uncomment the preferences below if you want to use the plugin
50
40
without having to configure it from the PythonAPI or WebUI.
51
41
*/
42
+
52
43
/* radioConfig.preferences.environmental_measurement_plugin_measurement_enabled = 1;
53
44
radioConfig.preferences.environmental_measurement_plugin_screen_enabled = 1;
54
45
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold = 5;
55
46
radioConfig.preferences.environmental_measurement_plugin_update_interval = 30;
56
- radioConfig.preferences.environmental_measurement_plugin_recovery_interval = 600;*/
47
+ radioConfig.preferences.environmental_measurement_plugin_recovery_interval = 60;
48
+ radioConfig.preferences.environmental_measurement_plugin_display_farenheit = true;
49
+ radioConfig.preferences.environmental_measurement_plugin_sensor_pin = 13;
50
+ radioConfig.preferences.environmental_measurement_plugin_sensor_type = RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType::RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11;*/
57
51
58
52
if (! (radioConfig.preferences .environmental_measurement_plugin_measurement_enabled || radioConfig.preferences .environmental_measurement_plugin_screen_enabled )){
59
53
// If this plugin is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it
@@ -62,20 +56,32 @@ int32_t EnvironmentalMeasurementPlugin::runOnce() {
62
56
63
57
if (firstTime) {
64
58
// This is the first time the OSThread library has called this function, so do some setup
65
- DEBUG_MSG (" EnvironmentalMeasurement: Initializing\n " );
66
- environmentalMeasurementPluginRadio = new EnvironmentalMeasurementPluginRadio ();
59
+
67
60
firstTime = 0 ;
68
- // begin reading measurements from the sensor
69
- // DHT have a max read-rate of 1HZ, so we should wait at least 1 second
70
- // after initializing the sensor before we try to read from it.
71
- // returning the interval here means that the next time OSThread
72
- // calls our plugin, we'll run the other branch of this if statement
73
- // and actually do a "sendOurEnvironmentalMeasurement()"
61
+
74
62
if (radioConfig.preferences .environmental_measurement_plugin_measurement_enabled )
75
63
{
64
+ DEBUG_MSG (" EnvironmentalMeasurement: Initializing\n " );
76
65
// it's possible to have this plugin enabled, only for displaying values on the screen.
77
66
// therefore, we should only enable the sensor loop if measurement is also enabled
78
- dht.begin ();
67
+ switch (radioConfig.preferences .environmental_measurement_plugin_sensor_type ) {
68
+ case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11:
69
+ dht = new DHT (radioConfig.preferences .environmental_measurement_plugin_sensor_pin ,DHT11);
70
+ this ->dht ->begin ();
71
+ this ->dht ->read ();
72
+ DEBUG_MSG (" EnvironmentalMeasurement: Opened DHT11 on pin: %d\n " ,radioConfig.preferences .environmental_measurement_plugin_sensor_pin );
73
+ break ;
74
+ default :
75
+ DEBUG_MSG (" EnvironmentalMeasurement: Invalid sensor type selected; Disabling plugin" );
76
+ return (INT32_MAX);
77
+ break ;
78
+ }
79
+ // begin reading measurements from the sensor
80
+ // DHT have a max read-rate of 1HZ, so we should wait at least 1 second
81
+ // after initializing the sensor before we try to read from it.
82
+ // returning the interval here means that the next time OSThread
83
+ // calls our plugin, we'll run the other branch of this if statement
84
+ // and actually do a "sendOurEnvironmentalMeasurement()"
79
85
return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
80
86
}
81
87
return (INT32_MAX);
@@ -96,6 +102,7 @@ int32_t EnvironmentalMeasurementPlugin::runOnce() {
96
102
" EnvironmentalMeasurement: TEMPORARILY DISABLED; The environmental_measurement_plugin_read_error_count_threshold has been exceed: %d. Will retry reads in %d seconds\n " ,
97
103
radioConfig.preferences .environmental_measurement_plugin_read_error_count_threshold ,
98
104
radioConfig.preferences .environmental_measurement_plugin_recovery_interval );
105
+ sensor_read_error_count = 0 ;
99
106
return (radioConfig.preferences .environmental_measurement_plugin_recovery_interval *1000 );
100
107
}
101
108
DEBUG_MSG (
@@ -110,7 +117,7 @@ int32_t EnvironmentalMeasurementPlugin::runOnce() {
110
117
sensor_read_error_count,
111
118
radioConfig.preferences .environmental_measurement_plugin_read_error_count_threshold -sensor_read_error_count);
112
119
}
113
- if (! environmentalMeasurementPluginRadio-> sendOurEnvironmentalMeasurement () ){
120
+ if (!sendOurEnvironmentalMeasurement () ){
114
121
// if we failed to read the sensor, then try again
115
122
// as soon as we can according to the maximum polling frequency
116
123
return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
@@ -123,20 +130,10 @@ int32_t EnvironmentalMeasurementPlugin::runOnce() {
123
130
#endif
124
131
}
125
132
126
- bool EnvironmentalMeasurementPluginRadio ::wantUIFrame () {
133
+ bool EnvironmentalMeasurementPlugin ::wantUIFrame () {
127
134
return radioConfig.preferences .environmental_measurement_plugin_screen_enabled ;
128
135
}
129
136
130
- void EnvironmentalMeasurementPluginRadio::drawFrame (OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
131
- {
132
- display->setTextAlignment (TEXT_ALIGN_LEFT);
133
- display->setFont (FONT_MEDIUM);
134
- display->drawString (x, y, " Environment" );
135
- display->setFont (FONT_SMALL);
136
- display->drawString (x, y += fontHeight (FONT_MEDIUM), lastSender+" : T:" + String (lastMeasurement.temperature ,2 ) + " H:" + String (lastMeasurement.relative_humidity ,2 ));
137
-
138
- }
139
-
140
137
String GetSenderName (const MeshPacket &mp) {
141
138
String sender;
142
139
@@ -149,55 +146,99 @@ String GetSenderName(const MeshPacket &mp) {
149
146
return sender;
150
147
}
151
148
152
- bool EnvironmentalMeasurementPluginRadio::handleReceivedProtobuf (const MeshPacket &mp, const EnvironmentalMeasurement *pptr)
149
+ uint32_t GetTimeSinceMeshPacket (const MeshPacket *mp) {
150
+ uint32_t now = getTime ();
151
+
152
+ uint32_t last_seen = mp->rx_time ;
153
+ int delta = (int )(now - last_seen);
154
+ if (delta < 0 ) // our clock must be slightly off still - not set from GPS yet
155
+ delta = 0 ;
156
+
157
+ return delta;
158
+
159
+ }
160
+
161
+
162
+ float EnvironmentalMeasurementPlugin::CelsiusToFarenheit (float c) {
163
+ return (c*9 )/5 + 32 ;
164
+ }
165
+
166
+
167
+ void EnvironmentalMeasurementPlugin::drawFrame (OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
153
168
{
154
- const EnvironmentalMeasurement &p = *pptr;
169
+ display->setTextAlignment (TEXT_ALIGN_LEFT);
170
+ display->setFont (FONT_MEDIUM);
171
+ display->drawString (x, y, " Environment" );
172
+ if (lastMeasurementPacket == nullptr ) {
173
+ display->setFont (FONT_SMALL);
174
+ display->drawString (x, y += fontHeight (FONT_MEDIUM), " No measurement" );
175
+ // DEBUG_MSG("EnvironmentalMeasurement: No previous measurement; not drawing frame\n");
176
+ return ;
177
+ }
178
+
179
+ EnvironmentalMeasurement lastMeasurement;
155
180
181
+
182
+ uint32_t agoSecs = GetTimeSinceMeshPacket (lastMeasurementPacket);
183
+ String lastSender = GetSenderName (*lastMeasurementPacket);
184
+
185
+ auto &p = lastMeasurementPacket->decoded ;
186
+ if (!pb_decode_from_bytes (p.payload .bytes ,
187
+ p.payload .size ,
188
+ EnvironmentalMeasurement_fields,
189
+ &lastMeasurement)) {
190
+ display->setFont (FONT_SMALL);
191
+ display->drawString (x, y += fontHeight (FONT_MEDIUM), " Measurement Error" );
192
+ DEBUG_MSG (" EnvironmentalMeasurement: unable to decode last packet" );
193
+ return ;
194
+ }
195
+
196
+ display->setFont (FONT_SMALL);
197
+ String last_temp = String (lastMeasurement.temperature ,0 ) +" °C" ;
198
+ if (radioConfig.preferences .environmental_measurement_plugin_display_farenheit ){
199
+ last_temp = String (CelsiusToFarenheit (lastMeasurement.temperature ),0 ) +" °F" ;;
200
+ }
201
+
202
+ display->drawString (x, y += fontHeight (FONT_MEDIUM), lastSender+" : " +last_temp +" /" + String (lastMeasurement.relative_humidity ,0 ) + " %(" +String (agoSecs)+" s)" );
203
+
204
+ }
205
+
206
+ bool EnvironmentalMeasurementPlugin::handleReceivedProtobuf (const MeshPacket &mp, const EnvironmentalMeasurement *p)
207
+ {
156
208
if (!(radioConfig.preferences .environmental_measurement_plugin_measurement_enabled || radioConfig.preferences .environmental_measurement_plugin_screen_enabled )){
157
209
// If this plugin is not enabled in any capacity, don't handle the packet, and allow other plugins to consume
158
210
return false ;
159
211
}
160
- bool wasBroadcast = mp.to == NODENUM_BROADCAST;
161
212
162
213
String sender = GetSenderName (mp);
163
-
164
- // Show new nodes on LCD screen
165
- if (DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN && wasBroadcast) {
166
- String lcd = String (" Env Measured: " ) +sender + " \n " +
167
- " T: " + p.temperature + " \n " +
168
- " H: " + p.relative_humidity + " \n " ;
169
- screen->print (lcd.c_str ());
170
- }
171
- DEBUG_MSG (" -----------------------------------------\n " );
172
214
173
215
DEBUG_MSG (" EnvironmentalMeasurement: Received data from %s\n " , sender);
174
- DEBUG_MSG (" EnvironmentalMeasurement->relative_humidity: %f\n " , p.relative_humidity );
175
- DEBUG_MSG (" EnvironmentalMeasurement->temperature: %f\n " , p.temperature );
216
+ DEBUG_MSG (" EnvironmentalMeasurement->relative_humidity: %f\n " , p->relative_humidity );
217
+ DEBUG_MSG (" EnvironmentalMeasurement->temperature: %f\n " , p->temperature );
218
+
219
+ lastMeasurementPacket = packetPool.allocCopy (mp);
176
220
177
- lastMeasurement = p;
178
- lastSender = sender;
179
221
return false ; // Let others look at this message also if they want
180
222
}
181
223
182
- bool EnvironmentalMeasurementPluginRadio ::sendOurEnvironmentalMeasurement (NodeNum dest, bool wantReplies)
224
+ bool EnvironmentalMeasurementPlugin ::sendOurEnvironmentalMeasurement (NodeNum dest, bool wantReplies)
183
225
{
184
226
EnvironmentalMeasurement m;
185
227
186
228
m.barometric_pressure = 0 ; // TODO: Add support for barometric sensors
187
- m.relative_humidity = dht.readHumidity ();
188
- m.temperature = dht.readTemperature ();;
189
-
190
229
DEBUG_MSG (" -----------------------------------------\n " );
191
230
192
231
DEBUG_MSG (" EnvironmentalMeasurement: Read data\n " );
193
- DEBUG_MSG (" EnvironmentalMeasurement->relative_humidity: %f\n " , m.relative_humidity );
194
- DEBUG_MSG (" EnvironmentalMeasurement->temperature: %f\n " , m.temperature );
195
-
196
- if (isnan (m.relative_humidity ) || isnan (m.temperature ) ){
232
+ if (!this ->dht ->read (true )){
197
233
sensor_read_error_count++;
198
234
DEBUG_MSG (" EnvironmentalMeasurement: FAILED TO READ DATA\n " );
199
235
return false ;
200
236
}
237
+ m.relative_humidity = this ->dht ->readHumidity ();
238
+ m.temperature = this ->dht ->readTemperature ();
239
+
240
+ DEBUG_MSG (" EnvironmentalMeasurement->relative_humidity: %f\n " , m.relative_humidity );
241
+ DEBUG_MSG (" EnvironmentalMeasurement->temperature: %f\n " , m.temperature );
201
242
202
243
sensor_read_error_count = 0 ;
203
244
0 commit comments