Merge pull request #893 from joarSv/feature/environmental-ds18b20-sensor-support

Add support for DS18B20 temperature sensor
This commit is contained in:
Sacha Weatherstone 2021-10-27 13:54:57 +11:00 committed by GitHub
commit e6b4ee8084
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 139 additions and 99 deletions

View File

@ -111,6 +111,8 @@ lib_deps =
https://github.com/meshtastic/esp32_https_server.git https://github.com/meshtastic/esp32_https_server.git
adafruit/DHT sensor library@^1.4.1 adafruit/DHT sensor library@^1.4.1
adafruit/Adafruit Unified Sensor@^1.1.4 adafruit/Adafruit Unified Sensor@^1.1.4
paulstoffregen/OneWire@^2.3.5
robtillaart/DS18B20@^0.1.11
# Hmm - this doesn't work yet # Hmm - this doesn't work yet
# board_build.ldscript = linker/esp32.extram.bss.ld # board_build.ldscript = linker/esp32.extram.bss.ld
lib_ignore = segger_rtt lib_ignore = segger_rtt

View File

@ -80,7 +80,8 @@ typedef enum _PositionFlags {
} PositionFlags; } PositionFlags;
typedef enum _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType { typedef enum _RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType {
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11 = 0 RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11 = 0,
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20 = 1
} RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType; } RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType;
/* Struct definitions */ /* Struct definitions */

View File

@ -1,20 +1,23 @@
#include "EnvironmentalMeasurementPlugin.h" #include "EnvironmentalMeasurementPlugin.h"
#include "../mesh/generated/environmental_measurement.pb.h"
#include "MeshService.h" #include "MeshService.h"
#include "NodeDB.h" #include "NodeDB.h"
#include "RTC.h" #include "RTC.h"
#include "Router.h" #include "Router.h"
#include "configuration.h" #include "configuration.h"
#include "main.h" #include "main.h"
#include "../mesh/generated/environmental_measurement.pb.h"
#include <DHT.h> #include <DHT.h>
#include <DS18B20.h>
#include <OLEDDisplay.h> #include <OLEDDisplay.h>
#include <OLEDDisplayUi.h> #include <OLEDDisplayUi.h>
#include <OneWire.h>
#define DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000 // Some sensors (the DHT11) have a minimum required duration between read attempts #define DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
#define DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
#define DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS 1000
#define FAILED_STATE_SENSOR_READ_MULTIPLIER 10 #define FAILED_STATE_SENSOR_READ_MULTIPLIER 10
#define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true #define DISPLAY_RECEIVEID_MEASUREMENTS_ON_SCREEN true
#ifdef HAS_EINK #ifdef HAS_EINK
// The screen is bigger so use bigger fonts // The screen is bigger so use bigger fonts
#define FONT_SMALL ArialMT_Plain_16 #define FONT_SMALL ArialMT_Plain_16
@ -31,123 +34,136 @@
#define FONT_HEIGHT_SMALL fontHeight(FONT_SMALL) #define FONT_HEIGHT_SMALL fontHeight(FONT_SMALL)
#define FONT_HEIGHT_MEDIUM fontHeight(FONT_MEDIUM) #define FONT_HEIGHT_MEDIUM fontHeight(FONT_MEDIUM)
int32_t EnvironmentalMeasurementPlugin::runOnce()
int32_t EnvironmentalMeasurementPlugin::runOnce() { {
#ifndef NO_ESP32 // this only works on ESP32 devices #ifndef NO_ESP32 // this only works on ESP32 devices
/* /*
Uncomment the preferences below if you want to use the plugin Uncomment the preferences below if you want to use the plugin
without having to configure it from the PythonAPI or WebUI. without having to configure it from the PythonAPI or WebUI.
*/ */
/*radioConfig.preferences.environmental_measurement_plugin_measurement_enabled = 1; /*radioConfig.preferences.environmental_measurement_plugin_measurement_enabled = 1;
radioConfig.preferences.environmental_measurement_plugin_screen_enabled = 1; radioConfig.preferences.environmental_measurement_plugin_screen_enabled = 1;
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold = 5; radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold = 5;
radioConfig.preferences.environmental_measurement_plugin_update_interval = 30; radioConfig.preferences.environmental_measurement_plugin_update_interval = 600;
radioConfig.preferences.environmental_measurement_plugin_recovery_interval = 60; radioConfig.preferences.environmental_measurement_plugin_recovery_interval = 60;
radioConfig.preferences.environmental_measurement_plugin_display_farenheit = true; radioConfig.preferences.environmental_measurement_plugin_display_farenheit = false;
radioConfig.preferences.environmental_measurement_plugin_sensor_pin = 13; radioConfig.preferences.environmental_measurement_plugin_sensor_pin = 13;
radioConfig.preferences.environmental_measurement_plugin_sensor_type = RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType::RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11;*/ radioConfig.preferences.environmental_measurement_plugin_sensor_type =
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType::
RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20;
*/
if (! (radioConfig.preferences.environmental_measurement_plugin_measurement_enabled || radioConfig.preferences.environmental_measurement_plugin_screen_enabled)){ if (!(radioConfig.preferences.environmental_measurement_plugin_measurement_enabled ||
radioConfig.preferences.environmental_measurement_plugin_screen_enabled)) {
// If this plugin is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it // If this plugin is not enabled, and the user doesn't want the display screen don't waste any OSThread time on it
return (INT32_MAX); return (INT32_MAX);
} }
if (firstTime) { if (firstTime) {
// This is the first time the OSThread library has called this function, so do some setup // This is the first time the OSThread library has called this function, so do some setup
firstTime = 0; firstTime = 0;
if (radioConfig.preferences.environmental_measurement_plugin_measurement_enabled) if (radioConfig.preferences.environmental_measurement_plugin_measurement_enabled) {
{
DEBUG_MSG("EnvironmentalMeasurement: Initializing\n"); DEBUG_MSG("EnvironmentalMeasurement: Initializing\n");
// it's possible to have this plugin enabled, only for displaying values on the screen. // it's possible to have this plugin enabled, only for displaying values on the screen.
// therefore, we should only enable the sensor loop if measurement is also enabled // therefore, we should only enable the sensor loop if measurement is also enabled
switch(radioConfig.preferences.environmental_measurement_plugin_sensor_type) { switch (radioConfig.preferences.environmental_measurement_plugin_sensor_type) {
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11: case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11:
dht = new DHT(radioConfig.preferences.environmental_measurement_plugin_sensor_pin,DHT11); dht = new DHT(radioConfig.preferences.environmental_measurement_plugin_sensor_pin, DHT11);
this->dht->begin(); this->dht->begin();
this->dht->read(); this->dht->read();
DEBUG_MSG("EnvironmentalMeasurement: Opened DHT11 on pin: %d\n",radioConfig.preferences.environmental_measurement_plugin_sensor_pin); DEBUG_MSG("EnvironmentalMeasurement: Opened DHT11 on pin: %d\n",
radioConfig.preferences.environmental_measurement_plugin_sensor_pin);
return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20:
oneWire = new OneWire(radioConfig.preferences.environmental_measurement_plugin_sensor_pin);
ds18b20 = new DS18B20(oneWire);
this->ds18b20->begin();
this->ds18b20->setResolution(12);
this->ds18b20->requestTemperatures();
DEBUG_MSG("EnvironmentalMeasurement: Opened DS18B20 on pin: %d\n",
radioConfig.preferences.environmental_measurement_plugin_sensor_pin);
return (DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
default:
DEBUG_MSG("EnvironmentalMeasurement: Invalid sensor type selected; Disabling plugin");
return (INT32_MAX);
break; break;
default:
DEBUG_MSG("EnvironmentalMeasurement: Invalid sensor type selected; Disabling plugin");
return (INT32_MAX);
break;
} }
// begin reading measurements from the sensor
// DHT have a max read-rate of 1HZ, so we should wait at least 1 second
// after initializing the sensor before we try to read from it.
// returning the interval here means that the next time OSThread
// calls our plugin, we'll run the other branch of this if statement
// and actually do a "sendOurEnvironmentalMeasurement()"
return(DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
} }
return (INT32_MAX); return (INT32_MAX);
} } else {
else { if (!radioConfig.preferences.environmental_measurement_plugin_measurement_enabled) {
if (!radioConfig.preferences.environmental_measurement_plugin_measurement_enabled)
{
// if we somehow got to a second run of this plugin with measurement disabled, then just wait forever // if we somehow got to a second run of this plugin with measurement disabled, then just wait forever
// I can't imagine we'd ever get here though. // I can't imagine we'd ever get here though.
return (INT32_MAX); return (INT32_MAX);
} }
// this is not the first time OSThread library has called this function // this is not the first time OSThread library has called this function
// so just do what we intend to do on the interval // so just do what we intend to do on the interval
if(sensor_read_error_count > radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold) if (sensor_read_error_count > radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold) {
{ if (radioConfig.preferences.environmental_measurement_plugin_recovery_interval > 0) {
if (radioConfig.preferences.environmental_measurement_plugin_recovery_interval > 0 ) { DEBUG_MSG("EnvironmentalMeasurement: TEMPORARILY DISABLED; The "
DEBUG_MSG( "environmental_measurement_plugin_read_error_count_threshold has been exceed: %d. Will retry reads in "
"EnvironmentalMeasurement: TEMPORARILY DISABLED; The environmental_measurement_plugin_read_error_count_threshold has been exceed: %d. Will retry reads in %d seconds\n", "%d seconds\n",
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold, radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold,
radioConfig.preferences.environmental_measurement_plugin_recovery_interval); radioConfig.preferences.environmental_measurement_plugin_recovery_interval);
sensor_read_error_count = 0; sensor_read_error_count = 0;
return(radioConfig.preferences.environmental_measurement_plugin_recovery_interval*1000); return (radioConfig.preferences.environmental_measurement_plugin_recovery_interval * 1000);
} }
DEBUG_MSG( DEBUG_MSG("EnvironmentalMeasurement: DISABLED; The environmental_measurement_plugin_read_error_count_threshold has "
"EnvironmentalMeasurement: DISABLED; The environmental_measurement_plugin_read_error_count_threshold has been exceed: %d. Reads will not be retried until after device reset\n", "been exceed: %d. Reads will not be retried until after device reset\n",
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold); radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold);
return(INT32_MAX); return (INT32_MAX);
} else if (sensor_read_error_count > 0) {
DEBUG_MSG("EnvironmentalMeasurement: There have been %d sensor read failures. Will retry %d more times\n",
sensor_read_error_count, sensor_read_error_count, sensor_read_error_count,
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold -
sensor_read_error_count);
} }
else if (sensor_read_error_count > 0){ if (!sendOurEnvironmentalMeasurement()) {
DEBUG_MSG("EnvironmentalMeasurement: There have been %d sensor read failures. Will retry %d more times\n", // if we failed to read the sensor, then try again
sensor_read_error_count,
radioConfig.preferences.environmental_measurement_plugin_read_error_count_threshold-sensor_read_error_count);
}
if (!sendOurEnvironmentalMeasurement() ){
// if we failed to read the sensor, then try again
// as soon as we can according to the maximum polling frequency // as soon as we can according to the maximum polling frequency
return(DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS); // return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
switch (radioConfig.preferences.environmental_measurement_plugin_sensor_type) {
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11:
return (DHT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20:
return (DS18B20_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
default:
return (DEFAULT_SENSOR_MINIMUM_WAIT_TIME_BETWEEN_READS);
}
} }
} }
// The return of runOnce is an int32 representing the desired number of // The return of runOnce is an int32 representing the desired number of
// miliseconds until the function should be called again by the // miliseconds until the function should be called again by the
// OSThread library. Multiply the preference value by 1000 to convert seconds to miliseconds // OSThread library. Multiply the preference value by 1000 to convert seconds to miliseconds
return(radioConfig.preferences.environmental_measurement_plugin_update_interval * 1000); return (radioConfig.preferences.environmental_measurement_plugin_update_interval * 1000);
#endif #endif
} }
bool EnvironmentalMeasurementPlugin::wantUIFrame() { bool EnvironmentalMeasurementPlugin::wantUIFrame()
{
return radioConfig.preferences.environmental_measurement_plugin_screen_enabled; return radioConfig.preferences.environmental_measurement_plugin_screen_enabled;
} }
String GetSenderName(const MeshPacket &mp) { String GetSenderName(const MeshPacket &mp)
{
String sender; String sender;
auto node = nodeDB.getNode(getFrom(&mp)); auto node = nodeDB.getNode(getFrom(&mp));
if (node){ if (node) {
sender = node->user.short_name; sender = node->user.short_name;
} } else {
else {
sender = "UNK"; sender = "UNK";
} }
return sender; return sender;
} }
uint32_t GetTimeSinceMeshPacket(const MeshPacket *mp) { uint32_t GetTimeSinceMeshPacket(const MeshPacket *mp)
{
uint32_t now = getTime(); uint32_t now = getTime();
uint32_t last_seen = mp->rx_time; uint32_t last_seen = mp->rx_time;
@ -156,15 +172,13 @@ uint32_t GetTimeSinceMeshPacket(const MeshPacket *mp) {
delta = 0; delta = 0;
return delta; return delta;
} }
float EnvironmentalMeasurementPlugin::CelsiusToFarenheit(float c)
float EnvironmentalMeasurementPlugin::CelsiusToFarenheit(float c) { {
return (c*9)/5 + 32; return (c * 9) / 5 + 32;
} }
void EnvironmentalMeasurementPlugin::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y) void EnvironmentalMeasurementPlugin::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
{ {
display->setTextAlignment(TEXT_ALIGN_LEFT); display->setTextAlignment(TEXT_ALIGN_LEFT);
@ -173,21 +187,16 @@ void EnvironmentalMeasurementPlugin::drawFrame(OLEDDisplay *display, OLEDDisplay
if (lastMeasurementPacket == nullptr) { if (lastMeasurementPacket == nullptr) {
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
display->drawString(x, y += fontHeight(FONT_MEDIUM), "No measurement"); display->drawString(x, y += fontHeight(FONT_MEDIUM), "No measurement");
//DEBUG_MSG("EnvironmentalMeasurement: No previous measurement; not drawing frame\n");
return; return;
} }
EnvironmentalMeasurement lastMeasurement; EnvironmentalMeasurement lastMeasurement;
uint32_t agoSecs = GetTimeSinceMeshPacket(lastMeasurementPacket); uint32_t agoSecs = GetTimeSinceMeshPacket(lastMeasurementPacket);
String lastSender = GetSenderName(*lastMeasurementPacket); String lastSender = GetSenderName(*lastMeasurementPacket);
auto &p = lastMeasurementPacket->decoded; auto &p = lastMeasurementPacket->decoded;
if (!pb_decode_from_bytes(p.payload.bytes, if (!pb_decode_from_bytes(p.payload.bytes, p.payload.size, EnvironmentalMeasurement_fields, &lastMeasurement)) {
p.payload.size,
EnvironmentalMeasurement_fields,
&lastMeasurement)) {
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
display->drawString(x, y += fontHeight(FONT_MEDIUM), "Measurement Error"); display->drawString(x, y += fontHeight(FONT_MEDIUM), "Measurement Error");
DEBUG_MSG("EnvironmentalMeasurement: unable to decode last packet"); DEBUG_MSG("EnvironmentalMeasurement: unable to decode last packet");
@ -195,20 +204,23 @@ void EnvironmentalMeasurementPlugin::drawFrame(OLEDDisplay *display, OLEDDisplay
} }
display->setFont(FONT_SMALL); display->setFont(FONT_SMALL);
String last_temp = String(lastMeasurement.temperature,0) +"°C"; String last_temp = String(lastMeasurement.temperature, 0) + "°C";
if (radioConfig.preferences.environmental_measurement_plugin_display_farenheit){ if (radioConfig.preferences.environmental_measurement_plugin_display_farenheit) {
last_temp = String(CelsiusToFarenheit(lastMeasurement.temperature),0) +"°F";; last_temp = String(CelsiusToFarenheit(lastMeasurement.temperature), 0) + "°F";
;
} }
display->drawString(x, y += fontHeight(FONT_MEDIUM), lastSender+": "+last_temp +"/"+ String(lastMeasurement.relative_humidity,0) + "%("+String(agoSecs)+"s)"); display->drawString(x, y += fontHeight(FONT_MEDIUM),
lastSender + ": " + last_temp + "/" + String(lastMeasurement.relative_humidity, 0) + "%(" +
String(agoSecs) + "s)");
} }
bool EnvironmentalMeasurementPlugin::handleReceivedProtobuf(const MeshPacket &mp, EnvironmentalMeasurement *p) bool EnvironmentalMeasurementPlugin::handleReceivedProtobuf(const MeshPacket &mp, EnvironmentalMeasurement *p)
{ {
if (!(radioConfig.preferences.environmental_measurement_plugin_measurement_enabled || radioConfig.preferences.environmental_measurement_plugin_screen_enabled)){ if (!(radioConfig.preferences.environmental_measurement_plugin_measurement_enabled ||
// If this plugin is not enabled in any capacity, don't handle the packet, and allow other plugins to consume radioConfig.preferences.environmental_measurement_plugin_screen_enabled)) {
return false; // If this plugin is not enabled in any capacity, don't handle the packet, and allow other plugins to consume
return false;
} }
String sender = GetSenderName(mp); String sender = GetSenderName(mp);
@ -230,13 +242,32 @@ bool EnvironmentalMeasurementPlugin::sendOurEnvironmentalMeasurement(NodeNum des
DEBUG_MSG("-----------------------------------------\n"); DEBUG_MSG("-----------------------------------------\n");
DEBUG_MSG("EnvironmentalMeasurement: Read data\n"); DEBUG_MSG("EnvironmentalMeasurement: Read data\n");
if (!this->dht->read(true)){
sensor_read_error_count++; switch (radioConfig.preferences.environmental_measurement_plugin_sensor_type) {
DEBUG_MSG("EnvironmentalMeasurement: FAILED TO READ DATA\n"); case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DHT11:
if (!this->dht->read(true)) {
sensor_read_error_count++;
DEBUG_MSG("EnvironmentalMeasurement: FAILED TO READ DATA\n");
return false;
}
m.relative_humidity = this->dht->readHumidity();
m.temperature = this->dht->readTemperature();
break;
case RadioConfig_UserPreferences_EnvironmentalMeasurementSensorType_DS18B20:
if (this->ds18b20->isConversionComplete()) {
m.temperature = this->ds18b20->getTempC();
m.relative_humidity = 0; // This sensor is temperature only
this->ds18b20->requestTemperatures();
break;
} else {
sensor_read_error_count++;
DEBUG_MSG("EnvironmentalMeasurement: FAILED TO READ DATA\n");
return false;
}
default:
DEBUG_MSG("EnvironmentalMeasurement: Invalid sensor type selected; Disabling plugin");
return false; return false;
} }
m.relative_humidity = this->dht->readHumidity();
m.temperature = this->dht->readTemperature();
DEBUG_MSG("EnvironmentalMeasurement->relative_humidity: %f\n", m.relative_humidity); DEBUG_MSG("EnvironmentalMeasurement->relative_humidity: %f\n", m.relative_humidity);
DEBUG_MSG("EnvironmentalMeasurement->temperature: %f\n", m.temperature); DEBUG_MSG("EnvironmentalMeasurement->temperature: %f\n", m.temperature);
@ -250,4 +281,3 @@ bool EnvironmentalMeasurementPlugin::sendOurEnvironmentalMeasurement(NodeNum des
service.sendToMesh(p); service.sendToMesh(p);
return true; return true;
} }

View File

@ -1,15 +1,20 @@
#pragma once #pragma once
#include "ProtobufPlugin.h"
#include "../mesh/generated/environmental_measurement.pb.h" #include "../mesh/generated/environmental_measurement.pb.h"
#include "ProtobufPlugin.h"
#include <DHT.h>
#include <DS18B20.h>
#include <OLEDDisplay.h> #include <OLEDDisplay.h>
#include <OLEDDisplayUi.h> #include <OLEDDisplayUi.h>
#include <DHT.h> #include <OneWire.h>
class EnvironmentalMeasurementPlugin : private concurrency::OSThread, public ProtobufPlugin<EnvironmentalMeasurement> class EnvironmentalMeasurementPlugin : private concurrency::OSThread, public ProtobufPlugin<EnvironmentalMeasurement>
{ {
public: public:
EnvironmentalMeasurementPlugin(): concurrency::OSThread("EnvironmentalMeasurementPlugin"), ProtobufPlugin("EnvironmentalMeasurement", PortNum_ENVIRONMENTAL_MEASUREMENT_APP, &EnvironmentalMeasurement_msg) { EnvironmentalMeasurementPlugin()
lastMeasurementPacket = nullptr; : concurrency::OSThread("EnvironmentalMeasurementPlugin"),
ProtobufPlugin("EnvironmentalMeasurement", PortNum_ENVIRONMENTAL_MEASUREMENT_APP, &EnvironmentalMeasurement_msg)
{
lastMeasurementPacket = nullptr;
} }
virtual bool wantUIFrame(); virtual bool wantUIFrame();
virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y); virtual void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y);
@ -24,11 +29,13 @@ class EnvironmentalMeasurementPlugin : private concurrency::OSThread, public Pro
* Send our EnvironmentalMeasurement into the mesh * Send our EnvironmentalMeasurement into the mesh
*/ */
bool sendOurEnvironmentalMeasurement(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false); bool sendOurEnvironmentalMeasurement(NodeNum dest = NODENUM_BROADCAST, bool wantReplies = false);
private: private:
float CelsiusToFarenheit(float c); float CelsiusToFarenheit(float c);
bool firstTime = 1; bool firstTime = 1;
DHT* dht; DHT *dht;
OneWire *oneWire;
DS18B20 *ds18b20;
const MeshPacket *lastMeasurementPacket; const MeshPacket *lastMeasurementPacket;
uint32_t sensor_read_error_count = 0; uint32_t sensor_read_error_count = 0;
}; };