Skip to content

Commit

Permalink
Merge pull request #4748 from tonhuisman/feature/P028-add-detection-m…
Browse files Browse the repository at this point in the history
…ode-setting

[P028] Add detection-mode setting
  • Loading branch information
TD-er authored Sep 17, 2023
2 parents 934641c + 86d6019 commit 77925a8
Show file tree
Hide file tree
Showing 12 changed files with 140 additions and 30 deletions.
27 changes: 27 additions & 0 deletions docs/source/Plugin/P028.rst
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,38 @@ Single event with all values, Send to Controller and Interval settings are stand

* **Interval** By default, Interval will be set to 60 sec. The minimum value allowed is 1 sec.


Data Source
^^^^^^^^^^^

.. note:: The **Data Source** section is only available when the task is configured to receive data from a remote node!

When using :ref:`c013_page` and having multiple ESP nodes using the same ``ESPEasy p2p UDP port`` (see the Tools/Advanced page, default: 8266, IANA registered), you can receive values from a remote node with the same plugin active. How to configure this is documented in the P2P Controller page.

In a regular configuration, having the sensor connected locally, the plugin auto-detects what type of sensor is used, either BME280 or BMP280, and auto-adjusts the values supported. When receiving data from the P2P network, this 'setting' is verified and must match on the receiving end of the P2P connection. This information is not included in the P2P protocol data, so a configuration option is available, only shown if the task is configured to receive remote data.

.. image:: P028_DataSource.png

* **Remote Unit**: Shows the unit number and name the data is received from.

* **Output values mode**: Allows selection of the sensor that is installed on the sending unit (node).

.. image:: P028_OutputValuesMode.png

Available options:

* *BME280*: Sending node has a BME280 sensor, will provide the Temperature, Humidity and Pressure values.

* *BMP280*: Sending node has a BMP280 sensor, will provide the Temperature and Pressure values.


Values
^^^^^^

The measured values are available in ``Temperature``, ``Humidity`` and ``Pressure``. A formula can be set to recalculate. The number of decimals is by default set to 2, and can be set to 0 for ``Humidity`` and ``Pressure``, as no decimals are provided from the measurement.

.. note:: When a BMP280 sensor, that provides only ``Temperature`` and ``Pressure`` data, is connected, the ``Humidity`` value will still be visible, but show 0.

.. Commands available
.. ^^^^^^^^^^^^^^^^^^
Expand Down
Binary file added docs/source/Plugin/P028_DataSource.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/source/Plugin/P028_OutputValuesMode.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 11 additions & 2 deletions src/_C013.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ bool CPlugin_013(CPlugin::Function function, struct EventStruct *event, String&
Protocol[protocolCount].usesTemplate = false;
Protocol[protocolCount].usesAccount = false;
Protocol[protocolCount].usesPassword = false;
Protocol[protocolCount].usesHost = false;
Protocol[protocolCount].defaultPort = 8266;
Protocol[protocolCount].usesID = false;
Protocol[protocolCount].Custom = true;
Expand Down Expand Up @@ -79,6 +80,12 @@ bool CPlugin_013(CPlugin::Function function, struct EventStruct *event, String&
break;
}

case CPlugin::Function::CPLUGIN_WEBFORM_SHOW_HOST_CONFIG:
{
string = F("-");
break;
}

/*
case CPlugin::Function::CPLUGIN_FLUSH:
{
Expand Down Expand Up @@ -154,7 +161,8 @@ void C013_SendUDPTaskData(struct EventStruct *event, uint8_t destUnit, uint8_t d
// For example sending different sensor type data from one dummy to another is probably not going to work well
dataReply.sensorType = event->getSensorType();

const TaskValues_Data_t* taskValues = UserVar.getTaskValues_Data(event->TaskIndex);
const TaskValues_Data_t *taskValues = UserVar.getTaskValues_Data(event->TaskIndex);

if (taskValues != nullptr) {
for (taskVarIndex_t x = 0; x < VARS_PER_TASK; ++x)
{
Expand Down Expand Up @@ -313,7 +321,8 @@ void C013_Receive(struct EventStruct *event) {
const Sensor_VType sensorType = TempEvent.getSensorType();

if (dataReply.matchesSensorType(sensorType)) {
TaskValues_Data_t * taskValues = UserVar.getTaskValues_Data(dataReply.destTaskIndex);
TaskValues_Data_t *taskValues = UserVar.getTaskValues_Data(dataReply.destTaskIndex);

if (taskValues != nullptr) {
for (taskVarIndex_t x = 0; x < VARS_PER_TASK; ++x)
{
Expand Down
6 changes: 6 additions & 0 deletions src/_C016.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ bool CPlugin_016(CPlugin::Function function, struct EventStruct *event, String&
break;
}

case CPlugin::Function::CPLUGIN_WEBFORM_SHOW_HOST_CONFIG:
{
string = F("-");
break;
}

default:
break;
}
Expand Down
61 changes: 54 additions & 7 deletions src/_P028_BME280.ino
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@
// #################### Plugin 028 BME280 I2C Temp/Hum/Barometric Pressure Sensor #######################
// #######################################################################################################

/** Changelog:
* 2023-07-27 tonhuisman: Revert most below changes and implement PLUGIN_GET_DEVICEVTYPE so the P2P controller validates against the correct
* setting. Setting is only available if a remote data-feed is active, and offers BME280 and BMP280 options only.
* 2023-07-26 tonhuisman: Ignore all humidity data (and log messages) if BMP280 Sensor model is selected
* 2023-07-25 tonhuisman: Add setting to enable forcing the plugin into either BME280 or BMP280 mode, default is Auto-detect
* Add changelog
*/

# include "src/PluginStructs/P028_data_struct.h"

// #include <math.h>
Expand Down Expand Up @@ -94,6 +102,21 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string)
break;
}

case PLUGIN_GET_DEVICEVTYPE:
{
const P028_data_struct::BMx_DetectMode detectMode = static_cast<P028_data_struct::BMx_DetectMode>(P028_DETECTION_MODE);

// We want to configure this only when a remote data-feed is used
if ((Settings.TaskDeviceDataFeed[event->TaskIndex] != 0) && (P028_data_struct::BMx_DetectMode::BMP280 == detectMode)) {
// Patch the sensor type to output only the measured values, and/or match with a P2P remote sensor
event->sensorType = Sensor_VType::SENSOR_TYPE_TEMP_EMPTY_BARO;
event->idx = getValueCountFromSensorType(Sensor_VType::SENSOR_TYPE_TEMP_EMPTY_BARO);
}

success = true;
break;
}

case PLUGIN_INIT:
{
const float tempOffset = P028_TEMPERATURE_OFFSET / 10.0f;
Expand Down Expand Up @@ -138,7 +161,7 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string)
if (nullptr != P028_data) {
if (P028_data->sensorID != P028_data_struct::Unknown_DEVICE) {
String detectedString = F("Detected: ");
detectedString += P028_data->getDeviceName();
detectedString += P028_data_struct::getDeviceName(P028_data->sensorID);
addUnit(detectedString);
}
}
Expand All @@ -151,7 +174,8 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string)
String offsetNote = F("Offset in units of 0.1 degree Celsius");

if (nullptr != P028_data) {
if (P028_data->hasHumidity()) {
if ((P028_data_struct::BMx_DetectMode::BMP280 != static_cast<P028_data_struct::BMx_DetectMode>(P028_DETECTION_MODE)) &&
P028_data->hasHumidity()) {
offsetNote += F(" (also correct humidity)");
}
}
Expand All @@ -161,6 +185,24 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string)
break;
}

case PLUGIN_WEBFORM_LOAD_ALWAYS:
{
if (Settings.TaskDeviceDataFeed[event->TaskIndex] != 0) { // We want to configure this *only* when a remote data-feed is used
const __FlashStringHelper *detectOptionList[] = {
P028_data_struct::getDeviceName(P028_data_struct::BMx_ChipId::BME280_DEVICE),
P028_data_struct::getDeviceName(P028_data_struct::BMx_ChipId::BMP280_DEVICE),
};
const int detectOptions[] = {
static_cast<int>(P028_data_struct::BMx_DetectMode::BME280),
static_cast<int>(P028_data_struct::BMx_DetectMode::BMP280),
};
addFormSelector(F("Output values mode"), F("det"), 2, detectOptionList, detectOptions, P028_DETECTION_MODE);

success = true;
}
break;
}

case PLUGIN_WEBFORM_SHOW_ERRORSTATE_OPT:
{
# ifndef BUILD_NO_DEBUG
Expand Down Expand Up @@ -221,7 +263,11 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string)
P028_ALTITUDE = getFormItemInt(F("elev"));
P028_TEMPERATURE_OFFSET = getFormItemInt(F("tempoffset"));
P028_ERROR_STATE_OUTPUT = getFormItemInt(F("err"));
success = true;

if (Settings.TaskDeviceDataFeed[event->TaskIndex] != 0) { // We want to configure this only when a remote data-feed is used
P028_DETECTION_MODE = getFormItemInt(F("det"));
}
success = true;
break;
}
case PLUGIN_ONCE_A_SECOND:
Expand Down Expand Up @@ -264,6 +310,7 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string)
if (!P028_data->hasHumidity()) {
// Patch the sensor type to output only the measured values.
event->sensorType = Sensor_VType::SENSOR_TYPE_TEMP_EMPTY_BARO;
event->idx = getValueCountFromSensorType(Sensor_VType::SENSOR_TYPE_TEMP_EMPTY_BARO);
}
UserVar[event->BaseVarIndex] = ExtraTaskSettings.checkAllowedRange(0, P028_data->last_temp_val);
UserVar[event->BaseVarIndex + 1] = P028_data->last_hum_val;
Expand All @@ -281,24 +328,24 @@ boolean Plugin_028(uint8_t function, struct EventStruct *event, String& string)
String log;

if (log.reserve(40)) { // Prevent re-allocation
log = P028_data->getDeviceName();
log = P028_data_struct::getDeviceName(P028_data->sensorID);
log += F(": Address: ");
log += formatToHex(P028_I2C_ADDRESS, 2);
addLogMove(LOG_LEVEL_INFO, log);

// addLogMove does also clear the string.
log = P028_data->getDeviceName();
log = P028_data_struct::getDeviceName(P028_data->sensorID);
log += F(": Temperature: ");
log += formatUserVarNoCheck(event->TaskIndex, 0);
addLogMove(LOG_LEVEL_INFO, log);

if (P028_data->hasHumidity()) {
log = P028_data->getDeviceName();
log = P028_data_struct::getDeviceName(P028_data->sensorID);
log += F(": Humidity: ");
log += formatUserVarNoCheck(event->TaskIndex, 1);
addLogMove(LOG_LEVEL_INFO, log);
}
log = P028_data->getDeviceName();
log = P028_data_struct::getDeviceName(P028_data->sensorID);
log += F(": Barometric Pressure: ");
log += formatUserVarNoCheck(event->TaskIndex, 2);
addLogMove(LOG_LEVEL_INFO, log);
Expand Down
1 change: 1 addition & 0 deletions src/src/DataTypes/ESPEasy_plugin_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#define PLUGIN_PROCESS_CONTROLLER_DATA 48 // Can be called from the controller to signal the plugin to generate (or handle) sending the data.
#define PLUGIN_PRIORITY_INIT_ALL 49 // Pre-initialize all plugins that are set to PowerManager priority (not implemented in plugins)
#define PLUGIN_PRIORITY_INIT 50 // Pre-initialize a singe plugins that is set to PowerManager priority
#define PLUGIN_WEBFORM_LOAD_ALWAYS 51 // Loaded *after* PLUGIN_WEBFORM_LOAD, also shown for remote data-feed devices



Expand Down
4 changes: 3 additions & 1 deletion src/src/Globals/Plugins.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@ bool PluginCall(uint8_t Function, struct EventStruct *event, String& str)
case PLUGIN_INIT:
case PLUGIN_EXIT:
case PLUGIN_WEBFORM_LOAD:
case PLUGIN_WEBFORM_LOAD_ALWAYS:
case PLUGIN_WEBFORM_LOAD_OUTPUT_SELECTOR:
case PLUGIN_READ:
case PLUGIN_GET_PACKED_RAW_DATA:
Expand All @@ -682,7 +683,7 @@ bool PluginCall(uint8_t Function, struct EventStruct *event, String& str)
// Only exception is when ErrorStateValues is needed.
// Therefore only need to call LoadTaskSettings for those tasks with ErrorStateValues
LoadTaskSettings(event->TaskIndex);
} else if (Function == PLUGIN_INIT || Function == PLUGIN_WEBFORM_LOAD) {
} else if (Function == PLUGIN_INIT || Function == PLUGIN_WEBFORM_LOAD || Function == PLUGIN_WEBFORM_LOAD_ALWAYS) {
// LoadTaskSettings may call PLUGIN_GET_DEVICEVALUENAMES.
LoadTaskSettings(event->TaskIndex);
}
Expand Down Expand Up @@ -842,6 +843,7 @@ bool PluginCall(uint8_t Function, struct EventStruct *event, String& str)
if (Function == PLUGIN_GET_DEVICEVALUENAMES ||
Function == PLUGIN_WEBFORM_SAVE ||
Function == PLUGIN_WEBFORM_LOAD ||
Function == PLUGIN_WEBFORM_LOAD_ALWAYS ||
Function == PLUGIN_SET_DEFAULTS ||
Function == PLUGIN_INIT_VALUE_RANGES ||
Function == PLUGIN_WEBFORM_SHOW_SERIAL_PARAMS
Expand Down
8 changes: 4 additions & 4 deletions src/src/PluginStructs/P028_data_struct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ uint8_t P028_data_struct::get_control_settings() const {
return sensorID == Unknown_DEVICE ? 0u : 0x93; // Oversampling: 8x P, 8x T, normal mode
}

const __FlashStringHelper * P028_data_struct::getDeviceName() const {
const __FlashStringHelper * P028_data_struct::getDeviceName(BMx_ChipId sensorID) {
switch (sensorID) {
case BMP280_DEVICE_SAMPLE1:
case BMP280_DEVICE_SAMPLE2: return F("BMP280 sample");
case BMP280_DEVICE_SAMPLE2: return F("sample BMP280");
case BMP280_DEVICE: return F("BMP280");
case BME280_DEVICE: return F("BME280");
default: return F("Unknown");
Expand Down Expand Up @@ -102,7 +102,7 @@ bool P028_data_struct::updateMeasurements(taskIndex_t task_index) {

if (loglevelActiveFor(LOG_LEVEL_INFO)) {
log.reserve(120); // Prevent re-allocation
log = getDeviceName();
log = getDeviceName(sensorID);
log += ':';
}
bool logAdded = false;
Expand Down Expand Up @@ -210,7 +210,7 @@ bool P028_data_struct::check() {

if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log = F("BMx280: Detected ");
log += getDeviceName();
log += getDeviceName(sensorID);
addLogMove(LOG_LEVEL_INFO, log);
}
}
Expand Down
15 changes: 11 additions & 4 deletions src/src/PluginStructs/P028_data_struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
# define P028_ALTITUDE PCONFIG(1)
# define P028_TEMPERATURE_OFFSET PCONFIG(2)
# define P028_ERROR_STATE_OUTPUT PCONFIG(3)
# define P028_DETECTION_MODE PCONFIG(4)

struct P028_data_struct : public PluginTaskData_base {
struct bme280_calib_data
Expand Down Expand Up @@ -107,6 +108,12 @@ struct P028_data_struct : public PluginTaskData_base {
BME280_DEVICE = 0x60
};

enum BMx_DetectMode : uint8_t {
Auto = 0u,
BME280 = BMx_ChipId::BME280_DEVICE,
BMP280 = BMx_ChipId::BMP280_DEVICE,
};

enum BMx_state {
BMx_Uninitialized = 0,
BMx_Initialized,
Expand All @@ -119,7 +126,7 @@ struct P028_data_struct : public PluginTaskData_base {

P028_data_struct(uint8_t addr,
float tempOffset);
P028_data_struct() = delete;
P028_data_struct() = delete;
virtual ~P028_data_struct() = default;

private:
Expand All @@ -130,11 +137,11 @@ struct P028_data_struct : public PluginTaskData_base {

public:

const __FlashStringHelper* getDeviceName() const;
static const __FlashStringHelper* getDeviceName(BMx_ChipId sensorID);

bool hasHumidity() const;
bool hasHumidity() const;

bool initialized() const;
bool initialized() const;

private:

Expand Down
Loading

0 comments on commit 77925a8

Please sign in to comment.