Skip to content

Commit

Permalink
Merge pull request letscontrolit#4820 from tonhuisman/feature/P026-ad…
Browse files Browse the repository at this point in the history
…d-internal-temperature-also-as-systemvar

[P026][Sysvars] Add Internal temperature sensor value for ESP32
  • Loading branch information
TD-er authored Sep 26, 2023
2 parents 3409e9e + 01c673e commit de55dbb
Show file tree
Hide file tree
Showing 18 changed files with 326 additions and 65 deletions.
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ on:
tags-ignore: '**'
paths-ignore:
- 'dist/Release_notes.txt'
- 'docs/**'
pull_request:
branches: [mega]

Expand Down
62 changes: 58 additions & 4 deletions docs/source/Plugin/P026.rst
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.. include:: ../Plugin/_plugin_substitutions_p02x.repl
.. include:: ../Plugin/_plugin_substitutions_p02x.repl
.. _P026_page:

|P026_typename|
Expand All @@ -21,10 +21,48 @@ Maintainer: |P026_maintainer|

Used libraries: |P026_usedlibraries|

Supported hardware
------------------
.. Supported hardware
.. ------------------
|P026_usedby|
.. .. |P026_usedby|
Introduction
------------

To monitor some internal values of an ESPEasy equiped device, the SysInfo plugin is available. This device can show up to 4 values showing user-selected system data.

Configuration
-------------

.. image:: P026_DeviceConfiguration.png

* **Name** A unique name should be entered here.

* **Enabled** The device can be disabled or enabled. When not enabled the device should not use any resources.

Output configuration
^^^^^^^^^^^^^^^^^^^^

* **Number Output Values**: Select from 1 to 4 output values, default is 4 (Quad). If more values are to be used, multiple tasks can be configured using this plugin.

.. image:: P026_NumberOutputOptions.png

* **Value 1..4**: Depending on the **Number Output Values** selection, 1 to 4 selections for output values are available. These can be chosen as desired.

.. image:: P026_ValuesOptions.png

* *Uptime*: The uptime of the unit in minutes.
* *Free RAM*: The amount of free memory in bytes.
* *Wifi RSSI*: The RSSI (Received signal strength indicator) value. This is a negative value.
* *Input VCC*: The voltage applied to the 3.3V VCC input of the ESP. This value is **only** available on ESP8266 builds with VCC enabled (included in the build name), else 0 will be shown.
* *System load*: The load as displayed on the Main and Info pages, a percentage in range 0 .. 100.
* *IP 1.Octet* .. *IP 4.Octet*: The separate parts of the active IP address of the unit, the octets are counted from left to right.
* *Web activity*: The time passed since the last web activity at the unit. Measured in seconds.
* *Free Stack*: The available stack space in bytes.
* *WiFi TX pwr*: The current setting for transmit power via WiFi. This is determined dynamically, depending on the corresponding settings in the Tools/Advanced page, RSSI and other factors.
* *Free 2nd Heap*: The available memory on the 2nd heap, **only** available in some specific ESP8266 builds, else it shows 0.
* *Internal temperature (ESP32)*: The internal temperature of the ESP. **Only** available on ESP32 units. For ESP32-S2/S3/C2/C3/C6 MCUs there is official support for the internal temperature sensor via the Espressif libraries, that has compensation applied so it shows a realistic value. For ESP32 Classic this is determined empirically, based on the deviation of the 150 kHz internal clock generator, that is rather temperature dependent, compared to the (stable) crystal frequency. This should not be seen as an absolute temperature, but *can* be used as a relative measurement f.e. when comparing heavy load vs. light load situations.
* *None*: No value.

.. Commands available
.. ^^^^^^^^^^^^^^^^^^
Expand All @@ -36,12 +74,28 @@ Supported hardware
.. .. include:: P026_events.repl
Data Acquisition
^^^^^^^^^^^^^^^^

This group of settings, **Single event with all values** and **Send to Controller** settings are standard available configuration items. Send to Controller is only visible when one or more Controllers are configured.

* **Interval** By default, Interval will be set to 60 sec. The data will be collected, and event(s) generated, using this interval.

Get Config values
~~~~~~~~~~~~~~~~~

These values are not available in *Minimal OTA* builds.

.. include:: P026_config_values.repl

Change log
----------

.. versionchanged:: 2.0
...

|added| 2023-09-25 ESP32 Internal temperature sensor option, Get Config values

|added|
Major overhaul for 2.0 release.

Expand Down
Binary file added docs/source/Plugin/P026_DeviceConfiguration.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/P026_NumberOutputOptions.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/P026_ValuesOptions.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 59 additions & 0 deletions docs/source/Plugin/P026_config_values.repl
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
.. csv-table::
:header: "Config value", "Information"
:widths: 20, 30

"
| ``[<taskname>#uptime]``
","
| Returns the uptime of the unit in minutes.
"
"
| ``[<taskname>#freeheap]``
","
| Returns the amount of free memory in bytes.
"
"
| ``[<taskname>#rssi]``
","
| Returns the RSSI (Received signal strength indicator) value. This is a negative value.
"
"
| ``[<taskname>#vcc]``
","
| Returns the voltage applied to the 3.3V VCC input of the ESP. This value is **only** available on ESP8266 builds with VCC enabled (included in the build name), else 0 will be shown.
"
"
| ``[<taskname>#load]``
","
| Returns the load as displayed on the Main and Info pages, a percentage in range 0 .. 100.
"
"
| ``[<taskname>#ip1]`` .. ``[<taskname>#ip4]``
","
| Returns the separate parts of the active IPv4 address of the unit, the parts 1..4 are counted from left to right.
"
"
| ``[<taskname>#web]``
","
| Returns the time passed since the last web activity at the unit. Measured in seconds.
"
"
| ``[<taskname>#freestack]``
","
| Returns the available stack space in bytes.
"
"
| ``[<taskname>#txpwr]``
","
| Returns the current setting for transmit power via WiFi. This is determined dynamically, depending on the corresponding settings in the Tools/Advanced page, RSSI and other factors.
"
"
| ``[<taskname>#free2ndheap]``
","
| Returns the available memory on the 2nd heap, **only** available in some specific ESP8266 builds, else it shows 0.
"
"
| ``[<taskname>#internaltemp]``
","
| Returns the internal temperature of the ESP. **Only** available on ESP32 units. For ESP32-S2/S3/C2/C3/C6 MCUs there is official support for the internal temperature sensor via the Espressif libraries, that has compensation applied so it shows a realistic value. For ESP32 Classic this is determined empirically, based on the deviation of the 150 kHz internal clock generator, that is rather temperature dependent, compared to the (stable) crystal frequency. This should not be seen as an absolute temperature, but *can* be used as a relative measurement f.e. when comparing heavy load vs. light load situations.
"
122 changes: 77 additions & 45 deletions src/_P026_Sysinfo.ino
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,46 @@
// #################################### Plugin 026: System Info ##########################################
// #######################################################################################################


# include "src/DataStructs/ESPEasy_packed_raw_data.h"
# include "src/ESPEasyCore/ESPEasyNetwork.h"
# include "src/Globals/ESPEasyWiFiEvent.h"
# include "src/Helpers/Memory.h"

# include "ESPEasy-Globals.h"
/** Changelog:
* 2023-09-24 tonhuisman: Add support for getting all values via Get Config option [<taskname>#<valuename>] where <valuename> is the default
* name as set for an output value. None is ignored. Not available in MINIMAL_OTA builds.
* Move all includes to P026_data_struct.h
* 2023-09-23 tonhuisman: Add Internal temperature option for ESP32
* Format source using Uncrustify
* Move #if check to P026_data_struct.h as Arduino compiler doesn't support that :(
* Move other defines to P026_data_struct.h
* 2023-09-23 tonhuisman: Start changelog
*/

# define PLUGIN_026
# define PLUGIN_ID_026 26
# define PLUGIN_NAME_026 "Generic - System Info"

// place sensor type selector right after the output value settings
# define P026_QUERY1_CONFIG_POS 0
# define P026_SENSOR_TYPE_INDEX (P026_QUERY1_CONFIG_POS + VARS_PER_TASK)
# define P026_NR_OUTPUT_VALUES getValueCountFromSensorType(static_cast<Sensor_VType>(PCONFIG(P026_SENSOR_TYPE_INDEX)))

# define P026_NR_OUTPUT_OPTIONS 14
# include "src/PluginStructs/P026_data_struct.h" // Arduino doesn't do #if in .ino sources :(

const __FlashStringHelper* Plugin_026_valuename(uint8_t value_nr, bool displayString) {
const __FlashStringHelper* strings[] {
F("Uptime") , F("uptime"),
F("Free RAM") , F("freeheap"),
F("Wifi RSSI") , F("rssi"),
F("Input VCC") , F("vcc"),
F("System load") , F("load"),
F("IP 1.Octet") , F("ip1"),
F("IP 2.Octet") , F("ip2"),
F("IP 3.Octet") , F("ip3"),
F("IP 4.Octet") , F("ip4"),
F("Web activity") , F("web"),
F("Free Stack") , F("freestack"),
F("None") , F(""),
F("WiFi TX pwr") , F("txpwr"),
F("Free 2nd Heap"), F("free2ndheap")
const __FlashStringHelper *strings[] {
F("Uptime"), F("uptime"),
F("Free RAM"), F("freeheap"),
F("Wifi RSSI"), F("rssi"),
F("Input VCC"), F("vcc"),
F("System load"), F("load"),
F("IP 1.Octet"), F("ip1"),
F("IP 2.Octet"), F("ip2"),
F("IP 3.Octet"), F("ip3"),
F("IP 4.Octet"), F("ip4"),
F("Web activity"), F("web"),
F("Free Stack"), F("freestack"),
F("None"), F(""),
F("WiFi TX pwr"), F("txpwr"),
F("Free 2nd Heap"), F("free2ndheap"),
# if FEATURE_INTERNAL_TEMPERATURE
F("Internal temperature (ESP32)"), F("internaltemp"),
# endif // if FEATURE_INTERNAL_TEMPERATURE
};
const size_t index = (2* value_nr) + (displayString ? 0 : 1);
const size_t index = (2 * value_nr) + (displayString ? 0 : 1);
constexpr size_t nrStrings = NR_ELEMENTS(strings);

if (index < nrStrings) {
return strings[index];
}
Expand Down Expand Up @@ -77,6 +79,7 @@ boolean Plugin_026(uint8_t function, struct EventStruct *event, String& string)
case PLUGIN_GET_DEVICEVALUENAMES:
{
const int valueCount = P026_NR_OUTPUT_VALUES;

for (uint8_t i = 0; i < VARS_PER_TASK; ++i) {
if (i < valueCount) {
const uint8_t pconfigIndex = i + P026_QUERY1_CONFIG_POS;
Expand Down Expand Up @@ -134,8 +137,9 @@ boolean Plugin_026(uint8_t function, struct EventStruct *event, String& string)
// Work around to get the "none" at the end.
options[index] = Plugin_026_valuename(11, true);
indices[index] = 11;

const int valueCount = P026_NR_OUTPUT_VALUES;

for (uint8_t i = 0; i < valueCount; ++i) {
const uint8_t pconfigIndex = i + P026_QUERY1_CONFIG_POS;
sensorTypeHelper_loadOutputSelector(event, pconfigIndex, i, P026_NR_OUTPUT_OPTIONS, options, indices);
Expand All @@ -153,6 +157,7 @@ boolean Plugin_026(uint8_t function, struct EventStruct *event, String& string)
{
// Save output selector parameters.
const int valueCount = P026_NR_OUTPUT_VALUES;

for (uint8_t i = 0; i < valueCount; ++i) {
const uint8_t pconfigIndex = i + P026_QUERY1_CONFIG_POS;
const uint8_t choice = PCONFIG(pconfigIndex);
Expand All @@ -171,10 +176,12 @@ boolean Plugin_026(uint8_t function, struct EventStruct *event, String& string)
case PLUGIN_READ:
{
const int valueCount = P026_NR_OUTPUT_VALUES;

for (int i = 0; i < valueCount; ++i) {
UserVar[event->BaseVarIndex + i] = P026_get_value(PCONFIG(i));
}
#ifndef LIMIT_BUILD_SIZE
# ifndef LIMIT_BUILD_SIZE

if (loglevelActiveFor(LOG_LEVEL_INFO)) {
String log;

Expand All @@ -191,30 +198,49 @@ boolean Plugin_026(uint8_t function, struct EventStruct *event, String& string)
addLogMove(LOG_LEVEL_INFO, log);
}
}
#endif
# endif // ifndef LIMIT_BUILD_SIZE
success = true;
break;
}
# ifndef PLUGIN_BUILD_MINIMAL_OTA
case PLUGIN_GET_CONFIG_VALUE:
{
const String cmd = parseString(string, 1);

for (uint8_t option = 0; option < P026_NR_OUTPUT_OPTIONS; ++option) {
if ((option != 11) && equals(cmd, Plugin_026_valuename(option, false))) { // Use default valuename
string = floatToString(P026_get_value(option), 2, true); // Trim trailing zeroes
success = true;
break;
}
}
break;
}
# endif // ifndef PLUGIN_BUILD_MINIMAL_OTA
# if FEATURE_PACKED_RAW_DATA
case PLUGIN_GET_PACKED_RAW_DATA:
{
// Matching JS code:
// return decode(bytes,
// [header, uint24, uint24, int8, vcc, pct_8, uint8, uint8, uint8, uint8, uint24, uint16],
// ['header', 'uptime', 'freeheap', 'rssi', 'vcc', 'load', 'ip1', 'ip2', 'ip3', 'ip4', 'web', 'freestack']);
// on ESP32 you can add 'internaltemperature' of type int16 (1e2) to the list (disabled for now, so not available)
uint8_t index = 0;
string += LoRa_addInt(P026_get_value(index++), PackedData_uint24); // uptime
string += LoRa_addInt(P026_get_value(index++), PackedData_uint24); // freeheap
string += LoRa_addFloat(P026_get_value(index++), PackedData_int8); // rssi
string += LoRa_addFloat(P026_get_value(index++), PackedData_vcc); // vcc
string += LoRa_addFloat(P026_get_value(index++), PackedData_pct_8); // load
string += LoRa_addInt(P026_get_value(index++), PackedData_uint8); // ip1
string += LoRa_addInt(P026_get_value(index++), PackedData_uint8); // ip2
string += LoRa_addInt(P026_get_value(index++), PackedData_uint8); // ip3
string += LoRa_addInt(P026_get_value(index++), PackedData_uint8); // ip4
string += LoRa_addInt(P026_get_value(index++), PackedData_uint24); // web
string += LoRa_addInt(P026_get_value(index++), PackedData_uint16); // freestack
event->Par1 = index; // valuecount
string += LoRa_addInt(P026_get_value(index++), PackedData_uint24); // uptime
string += LoRa_addInt(P026_get_value(index++), PackedData_uint24); // freeheap
string += LoRa_addFloat(P026_get_value(index++), PackedData_int8); // rssi
string += LoRa_addFloat(P026_get_value(index++), PackedData_vcc); // vcc
string += LoRa_addFloat(P026_get_value(index++), PackedData_pct_8); // load
string += LoRa_addInt(P026_get_value(index++), PackedData_uint8); // ip1
string += LoRa_addInt(P026_get_value(index++), PackedData_uint8); // ip2
string += LoRa_addInt(P026_get_value(index++), PackedData_uint8); // ip3
string += LoRa_addInt(P026_get_value(index++), PackedData_uint8); // ip4
string += LoRa_addInt(P026_get_value(index++), PackedData_uint24); // web
string += LoRa_addInt(P026_get_value(index++), PackedData_uint16); // freestack
// # if FEATURE_INTERNAL_TEMPERATURE
// string += LoRa_addInt(P026_get_value(index++) * 100.0f, PackedData_int16_1e2); // internal temperature in 0.01 degrees
// # endif // if FEATURE_INTERNAL_TEMPERATURE
event->Par1 = index; // valuecount
success = true;
break;
}
Expand All @@ -226,6 +252,7 @@ boolean Plugin_026(uint8_t function, struct EventStruct *event, String& string)
float P026_get_value(uint8_t type)
{
float res{};

switch (type)
{
case 0: res = getUptimeMinutes(); break;
Expand All @@ -243,7 +270,7 @@ float P026_get_value(uint8_t type)
case 6:
case 7:
case 8:
res = NetworkLocalIP()[type - 5]; break;
res = NetworkLocalIP()[type - 5]; break;
case 9: res = timePassedSince(lastWeb) / 1000.0f; break; // respond in seconds
case 10: res = getCurrentFreeStack(); break;
case 12: res = WiFiEventData.wifi_TX_pwr; break;
Expand All @@ -252,6 +279,11 @@ float P026_get_value(uint8_t type)
res = FreeMem2ndHeap();
# endif // ifdef USE_SECOND_HEAP
break;
case 14:
# if FEATURE_INTERNAL_TEMPERATURE
res = getInternalTemperature();
# endif // if FEATURE_INTERNAL_TEMPERATURE
break;
}
return res;
}
Expand Down
12 changes: 12 additions & 0 deletions src/src/CustomBuild/define_plugin_sets.h
Original file line number Diff line number Diff line change
Expand Up @@ -2975,6 +2975,18 @@ To create/register a plugin, you have to :
#define FEATURE_PLUGIN_PRIORITY 0 // Disable by default
#endif

#ifndef FEATURE_INTERNAL_TEMPERATURE
#if defined(ESP32) // Feature is only available on (most?) ESP32 chips
#define FEATURE_INTERNAL_TEMPERATURE 1
#else
#define FEATURE_INTERNAL_TEMPERATURE 0 // Not evailable on ESP8266
#endif
#endif
#if defined(FEATURE_INTERNAL_TEMPERATURE) && defined(ESP8266)
#undef FEATURE_INTERNAL_TEMPERATURE
#define FEATURE_INTERNAL_TEMPERATURE 0 // Not evailable on ESP8266
#endif

#ifndef FEATURE_I2C_DEVICE_CHECK
#ifdef ESP8266_1M
#define FEATURE_I2C_DEVICE_CHECK 0 // Disabled by default for 1M units
Expand Down
Loading

0 comments on commit de55dbb

Please sign in to comment.