mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 04:07:47 +00:00
Merge branch 'letscontrolit:mega' into mega
This commit is contained in:
+204
-3
@@ -23,15 +23,216 @@ Maintainer: |P082_maintainer|
|
||||
|
||||
Used libraries: |P082_usedlibraries|
|
||||
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Almost all GPS modules on the market have a serial (UART) interface and without any configuration they output standard NMEA sentences at 9600 baud.
|
||||
|
||||
Some may differ in the quality of the GPS antenna and/or the generation of the used GPS receiver.
|
||||
|
||||
This often results in improved sensitivity and thus less time needed to get a fix, or maintaining a fix.
|
||||
|
||||
Controlling GPS Receiver
|
||||
------------------------
|
||||
|
||||
A lot of GPS modules sold are based on u-blox modules, or at least they claim to use u-blox modules as there are lots of couterfeit modules on the market.
|
||||
|
||||
Some (perfectly fine) modules are sold under a different name, but still use (real) u-blox modules.
|
||||
For example the BN-220 GPS modules are known to use u-blox modules and firmware from u-blox.
|
||||
These modules can thus be sent u-blox specific commands.
|
||||
|
||||
Currently the only u-blox specific commands supported by this plugin are to put the module in "backup mode".
|
||||
This is essentially turning off the entire module, except for the memory content with the satellite information.
|
||||
|
||||
See the commands section to manually control the GPS sleep mode.
|
||||
|
||||
|
||||
Time from GPS
|
||||
-------------
|
||||
|
||||
A GPS receiver is an excellent time source.
|
||||
The main advantage is that the time reported by a GPS receiver does not experience time drift.
|
||||
|
||||
Some GPS receivers have a pin labelled "PPS" which can be used to increase the accuracy even more.
|
||||
The accuracy can be at microseconds level when using the PPS pin.
|
||||
|
||||
The internal time of ESPEasy will be set by the GPS task when the GPS receiver has a fix.
|
||||
|
||||
|
||||
|
||||
|
||||
Tips for best performance
|
||||
-------------------------
|
||||
|
||||
Types of antennas
|
||||
^^^^^^^^^^^^^^^^^
|
||||
|
||||
Most GPS modules are sold including a GPS antenna.
|
||||
Pay attention to the ones sold with an external and detachable GPS antenna as quite a few are sold with really bad antennas
|
||||
|
||||
The size of the antenna is an important factor for the sensitivity.
|
||||
A rule of thumb is that bigger is better (up-to roughly 25x25 mm).
|
||||
But a lot of sellers on sites like Ali Express and others sell 25x25 ceramic antennas which perform really badly.
|
||||
Compared to these bad antennas, the often included small (12x6 mm) ceramic antenna does perform better.
|
||||
|
||||
Modules fixed mounted to the ceramic antenna, like the BN220, do have a relatively small ceramic antenna of 18x18 mm, but these do perform quite good.
|
||||
|
||||
Antenna Orientation
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The best orientation is to point the antenna to the open sky.
|
||||
Thus with the plane of the (ceramic) antenna parallel to the ground.
|
||||
|
||||
But for some use cases, a line of sight to the sky is more important than the orientation to the ground.
|
||||
|
||||
Do not cover the antenna with metal.
|
||||
|
||||
Starting from a "cold boot", it may take a while for the GPS receiver to get the first fix.
|
||||
If this takes longer than a few minutes, try taking the receiver outside, with as much non obstructed view to the sky as possible.
|
||||
|
||||
|
||||
Most GPS receivers do have a very small rechargable battery to keep the satellite trajectory information between runs.
|
||||
This may speed up the time to get a fix.
|
||||
However, those rechargable batteries take a long time to get charged (order of 50 hours) and they may sometimes be able to keep the data in the memory for about the same time.
|
||||
Thus when using the GPS for a short time and then disconnecting the power these batteries are quite useless.
|
||||
|
||||
When used in low-power setups, it is best to turn the GPS into "backup mode" to keep the memory powered.
|
||||
Another option is to remove these batteries and connect an external power source to power the RAM of the GPS module.
|
||||
When desoldering these batteries, try to remove them as quickly as possible, as they often are not designed to handle heat very well.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
Sensor
|
||||
^^^^^^
|
||||
|
||||
Serial Port
|
||||
"""""""""""
|
||||
|
||||
The configuration of the serial port is the same as with any other sensor using a serial port.
|
||||
Only the TX pin on the ESP, connected to the RX pin on the GPS is optional.
|
||||
It only needs to be connected if commands have to be sent to the GPS.
|
||||
|
||||
The baud rate is not selectable for this plugin, as every plugin on the market does have a default setting of 9600 baud.
|
||||
|
||||
PPS pin
|
||||
"""""""
|
||||
|
||||
|
||||
Current Sensor Data
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
|
||||
Reference Point
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
Output Configuration
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Value N
|
||||
"""""""
|
||||
|
||||
Each of the 4 task values can be set to a specific measurement value.
|
||||
|
||||
* Longitude
|
||||
* Latitude
|
||||
* Altitude
|
||||
* Speed (m/s)
|
||||
* Satellites Visible
|
||||
* Satellites Tracked
|
||||
* HDOP - Horizontal Dilution Of Precision
|
||||
* Fix Quality
|
||||
* Max SNR in dBHz - Mainly used for diagnostics
|
||||
* Checksum Fail - Mainly used for diagnostics
|
||||
* Distance (ODO) - Trip distance in meters
|
||||
* Distance from Reference Point - See the Reference Point setting.
|
||||
|
||||
Most units of measure are clear, but some may need a bit more explanation.
|
||||
|
||||
**HDOP**
|
||||
|
||||
The HDOP value is a standard indicator for the accuracy of the position.
|
||||
It is the standard deviation for the position (in the horizontal plane, there is also a VDOP, which we don't use)
|
||||
|
||||
The deviation is multiplied with a factor to get the standard deviation in meters.
|
||||
This factor is usually around 5 - 10 meters, depending on the used GPS module.
|
||||
Just to simplify it, you can take roughly 7.5 meters.
|
||||
|
||||
The HDOP is computed by the GPS module depending on the angle between tracked GPS satellites.
|
||||
Just to get an idea of the concept, try to pinpoint the crossing point of 2 circles you draw on a piece of paper.
|
||||
If the centers of those circles are relatively close to each other, in relation to the radius, then there is a large part of the 2 circles where they cross each other.
|
||||
If the angle between the 2 radii and the point where they cross is roughly 90 degree, it is very easy to see where they cross.
|
||||
|
||||
The used computation is a bit more elaborate as the GPS may track upto 16 satellites and you may see some reflected signals, etc.
|
||||
But in principle it is just about how large the expected error is, related to the angle between the tracked satellites.
|
||||
|
||||
**Satellites Visible/Tracked**
|
||||
|
||||
A satellite must be "visible" to the GPS receiver, before it can be used to compute the location.
|
||||
If a satellite is actually used to determine the position, it is considered to be tracked.
|
||||
|
||||
Whether a satellite is usable to track, depends on a number of factors, which may differ among brands and models of GPS receivers.
|
||||
|
||||
For a 2D position fix, at least 3 satellites must be tracked.
|
||||
For a 3D position fix, at least 4 satellites must be tracked.
|
||||
|
||||
If just the bare minimum of satellites is being tracked, the GPS receiver may loose its fix quite often.
|
||||
|
||||
|
||||
|
||||
Distance Update Interval
|
||||
""""""""""""""""""""""""
|
||||
|
||||
Normally a task may send new values every set "Interval", or when ``TaskRun`` is called from the rules.
|
||||
On mobile units, it may be useful to also trigger sending a new value every N travelled meters.
|
||||
This way, samples can be taken at a fixed distance, regardless the speed.
|
||||
|
||||
If the unit is stationary, new values will still be sent every "Interval" number of seconds.
|
||||
|
||||
Typical use case is when the unit is mounted in a car, it isn't that useful to get new samples at a very high rate.
|
||||
A useful setting of the "Interval" can be every 900 seconds (15 minutes) and 100 m travelled.
|
||||
New samples will be sent by whichever of these two comes first.
|
||||
|
||||
This can also be useful to trigger a new reading of other sensors, to collect sensor data at a specific grid interval on the map.
|
||||
|
||||
Some controllers, like the LoRaWAN (TTN) controller allow to couple a counter to a set of samples.
|
||||
This is called the "Sample Set Initiator".
|
||||
On every new sample sent to this controller from a specific task, a counter is incremented.
|
||||
This was designed specifically for this use case where a new sample from a task, like the GPS, may trigger a number of new samples from other tasks.
|
||||
These other samples will then be accompanied by the same sample set counter.
|
||||
|
||||
Some packets of a controller like the LoRaWAN (TTN) controller, may get lost during transmission.
|
||||
This way the received samples can still be grouped together and if the travelled path is predictable these samples can even be tracked back to the most likely position where they may have been taken.
|
||||
|
||||
|
||||
Data Acquisition
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
||||
The GPS receiver yields more measurement values than the max. 4 that can be used in a task.
|
||||
When the GPS receiver is linked to the LoRaWAN (TTN) controller, all relevant received data will be transmitted.
|
||||
This allows for more information to be processed on the receiving end, compared to other controllers.
|
||||
|
||||
|
||||
|
||||
Supported hardware
|
||||
------------------
|
||||
|
||||
|P082_usedby|
|
||||
|
||||
.. Commands available
|
||||
.. ^^^^^^^^^^^^^^^^^^
|
||||
Commands available
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. .. include:: P082_commands.repl
|
||||
.. include:: P082_commands.repl
|
||||
|
||||
Events
|
||||
~~~~~~
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
.. csv-table::
|
||||
:header: "Command", "Extra information"
|
||||
:widths: 20, 30
|
||||
|
||||
"
|
||||
``gps,sleep``
|
||||
|
||||
","
|
||||
Send u-blox specific command to put the GPS in backup mode.
|
||||
This turns off all parts of the GPS, except for the last known satellite trajectories.
|
||||
|
||||
Use this to get a faster fix, compared to turning off the power to the GPS.
|
||||
|
||||
In order to send a command to the GPS, the GPS RX pin must be connected.
|
||||
|
||||
"
|
||||
"
|
||||
``gps,wake``
|
||||
|
||||
","
|
||||
Send just any character to the GPS to wake it from backup mode (see ``gps,sleep``)
|
||||
|
||||
This is u-blox specific.
|
||||
|
||||
In order to send a command to the GPS, the GPS RX pin must be connected.
|
||||
|
||||
"
|
||||
@@ -554,10 +554,10 @@ P065 :ref:`P065_page`
|
||||
.. .. include:: ../Plugin/P072_commands.repl
|
||||
|
||||
|
||||
.. P073 :ref:`P073_page`
|
||||
.. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
P073 :ref:`P073_page`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. .. include:: ../Plugin/P073_commands.repl
|
||||
.. include:: ../Plugin/P073_commands.repl
|
||||
|
||||
|
||||
.. P074 :ref:`P074_page`
|
||||
@@ -608,10 +608,10 @@ P079 :ref:`P079_page`
|
||||
.. .. include:: ../Plugin/P081_commands.repl
|
||||
|
||||
|
||||
.. P082 :ref:`P082_page`
|
||||
.. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
P082 :ref:`P082_page`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. .. include:: ../Plugin/P082_commands.repl
|
||||
.. include:: ../Plugin/P082_commands.repl
|
||||
|
||||
P088 :ref:`P088_page`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -652,6 +652,12 @@ P101 :ref:`P101_page`
|
||||
.. include:: ../Plugin/P101_commands.repl
|
||||
|
||||
|
||||
P104 :ref:`P104_page`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. include:: ../Plugin/P104_commands.repl
|
||||
|
||||
|
||||
|
||||
P115 :ref:`P115_page`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -314,6 +314,26 @@ int ESPeasySerial::baudRate(void) {
|
||||
return getHW()->baudRate();
|
||||
}
|
||||
|
||||
bool ESPeasySerial::isTxEnabled(void) {
|
||||
if (!isValid()) {
|
||||
return false;
|
||||
}
|
||||
if (isI2Cserial()) {
|
||||
return true;
|
||||
}
|
||||
return _transmitPin != -1;
|
||||
}
|
||||
|
||||
bool ESPeasySerial::isRxEnabled(void) {
|
||||
if (!isValid()) {
|
||||
return false;
|
||||
}
|
||||
if (isI2Cserial()) {
|
||||
return true;
|
||||
}
|
||||
return _receivePin != -1;
|
||||
}
|
||||
|
||||
// Not supported in ESP32, since only HW serial is used.
|
||||
// Function included since it is used in some libraries.
|
||||
bool ESPeasySerial::listen() {
|
||||
|
||||
@@ -302,8 +302,12 @@ public:
|
||||
size_t size) override;
|
||||
|
||||
void setDebugOutput(bool);
|
||||
#endif
|
||||
|
||||
bool isTxEnabled(void);
|
||||
bool isRxEnabled(void);
|
||||
|
||||
#if defined(ESP8266)
|
||||
bool hasRxError(void);
|
||||
|
||||
void startDetectBaudrate();
|
||||
|
||||
@@ -375,16 +375,28 @@ void ESPeasySerial::setDebugOutput(bool enable) {
|
||||
}
|
||||
|
||||
bool ESPeasySerial::isTxEnabled(void) {
|
||||
if (!isValid() || isSWserial() || isI2Cserial()) {
|
||||
if (!isValid()) {
|
||||
return false;
|
||||
}
|
||||
if (isI2Cserial()) {
|
||||
return true;
|
||||
}
|
||||
if (isSWserial()) {
|
||||
return _transmitPin != -1;
|
||||
}
|
||||
return getHW()->isTxEnabled();
|
||||
}
|
||||
|
||||
bool ESPeasySerial::isRxEnabled(void) {
|
||||
if (!isValid() || isSWserial() || isI2Cserial()) {
|
||||
if (!isValid()) {
|
||||
return false;
|
||||
}
|
||||
if (isI2Cserial()) {
|
||||
return true;
|
||||
}
|
||||
if (isSWserial()) {
|
||||
return _receivePin != -1;
|
||||
}
|
||||
return getHW()->isRxEnabled();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ESPeasySerial",
|
||||
"version": "2.0.7",
|
||||
"version": "2.0.8",
|
||||
"keywords": [
|
||||
"serial", "io", "softwareserial", "hardwareserial"
|
||||
],
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name=ESPeasySerial
|
||||
version=2.0.7
|
||||
version=2.0.8
|
||||
author=Gijs Noorlander
|
||||
maintainer=Gijs Noorlander <gijs.noorlander@gmail.com>
|
||||
sentence=Wrapper for SoftwareSerial, SC16IS752 I2C to UART bridge and HardwareSerial for ESP8266 and ESP32/ESP32S2.
|
||||
|
||||
@@ -71,6 +71,8 @@ bool TinyGPSPlus::encode(char c)
|
||||
{
|
||||
term[curTermOffset] = 0;
|
||||
isValidSentence = endOfTermHandler();
|
||||
} else if (curSentenceType == GPS_SENTENCE_GPTXT) {
|
||||
isValidSentence = endOfTermHandler();
|
||||
}
|
||||
++curTermNumber;
|
||||
curTermOffset = 0;
|
||||
@@ -203,6 +205,21 @@ bool TinyGPSPlus::endOfTermHandler()
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GPS_SENTENCE_GPGLL:
|
||||
date.commit();
|
||||
time.commit();
|
||||
if (sentenceHasFix && date.valid && time.valid)
|
||||
{
|
||||
location.commit();
|
||||
if (!(location.valid)) {
|
||||
// one of them is invalid, so consider the entire sentence invalid
|
||||
date.valid = false;
|
||||
time.valid = false;
|
||||
location.valid = false;
|
||||
++invalidDataCount;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GPS_SENTENCE_GPGGA:
|
||||
time.commit();
|
||||
satellites.commit();
|
||||
@@ -232,6 +249,8 @@ bool TinyGPSPlus::endOfTermHandler()
|
||||
}
|
||||
hdop.commit();
|
||||
break;
|
||||
case GPS_SENTENCE_GPTXT:
|
||||
break;
|
||||
}
|
||||
|
||||
// Commit all custom listeners of this sentence type
|
||||
@@ -266,25 +285,31 @@ bool TinyGPSPlus::endOfTermHandler()
|
||||
{
|
||||
case COMBINE(GPS_SENTENCE_GPRMC, 1): // Time in both sentences
|
||||
case COMBINE(GPS_SENTENCE_GPGGA, 1):
|
||||
case COMBINE(GPS_SENTENCE_GPGLL, 5):
|
||||
time.setTime(term);
|
||||
break;
|
||||
case COMBINE(GPS_SENTENCE_GPRMC, 2): // GPRMC validity
|
||||
case COMBINE(GPS_SENTENCE_GPGLL, 6):
|
||||
sentenceHasFix = term[0] == 'A';
|
||||
break;
|
||||
case COMBINE(GPS_SENTENCE_GPRMC, 3): // Latitude
|
||||
case COMBINE(GPS_SENTENCE_GPGGA, 2):
|
||||
case COMBINE(GPS_SENTENCE_GPGLL, 1):
|
||||
location.setLatitude(term);
|
||||
break;
|
||||
case COMBINE(GPS_SENTENCE_GPRMC, 4): // N/S
|
||||
case COMBINE(GPS_SENTENCE_GPGGA, 3):
|
||||
case COMBINE(GPS_SENTENCE_GPGLL, 2):
|
||||
location.rawNewLatData.negative = term[0] == 'S';
|
||||
break;
|
||||
case COMBINE(GPS_SENTENCE_GPRMC, 5): // Longitude
|
||||
case COMBINE(GPS_SENTENCE_GPGGA, 4):
|
||||
case COMBINE(GPS_SENTENCE_GPGLL, 3):
|
||||
location.setLongitude(term);
|
||||
break;
|
||||
case COMBINE(GPS_SENTENCE_GPRMC, 6): // E/W
|
||||
case COMBINE(GPS_SENTENCE_GPGGA, 5):
|
||||
case COMBINE(GPS_SENTENCE_GPGLL, 4):
|
||||
location.rawNewLngData.negative = term[0] == 'W';
|
||||
break;
|
||||
case COMBINE(GPS_SENTENCE_GPRMC, 7): // Speed (GPRMC)
|
||||
@@ -698,6 +723,15 @@ void TinyGPSPlus::parseSentenceType(const char *term)
|
||||
{
|
||||
curSentenceType = GPS_SENTENCE_GPGSV;
|
||||
}
|
||||
else if (strcmp(&term[2], "TXT") == 0)
|
||||
{
|
||||
curSentenceType = GPS_SENTENCE_GPTXT;
|
||||
}
|
||||
else if (strcmp(&term[2], "GLL") == 0)
|
||||
{
|
||||
curSentenceType = GPS_SENTENCE_GPGLL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -316,6 +316,10 @@ private:
|
||||
GPS_SENTENCE_GPGSA, // GSA - GPS DOP and active satellites
|
||||
GPS_SENTENCE_GPGSV, // GSV - Satellites in view
|
||||
|
||||
GPS_SENTENCE_GPGLL, // GLL - Latitude and longitude, with time of position fix and status
|
||||
|
||||
GPS_SENTENCE_GPTXT, // Free format TXT field
|
||||
|
||||
GPS_SENTENCE_OTHER};
|
||||
|
||||
enum {
|
||||
|
||||
@@ -10,7 +10,7 @@ lib_ignore = ESP8266WiFi, ESP8266Ping, ESP8266WebServer, ESP8266H
|
||||
|
||||
[esp32_common]
|
||||
extends = common, core_esp32_3_3_0
|
||||
lib_deps = td-er/ESPeasySerial @ 2.0.7, adafruit/Adafruit ILI9341 @ ^1.5.6, Adafruit GFX Library, LOLIN_EPD, Adafruit BusIO, VL53L0X @ 1.3.0, SparkFun VL53L1X 4m Laser Distance Sensor @ 1.2.9, td-er/SparkFun MAX1704x Fuel Gauge Arduino Library @ ^1.0.1, ArduinoOTA, ESP32HTTPUpdateServer
|
||||
lib_deps = td-er/ESPeasySerial @ 2.0.8, adafruit/Adafruit ILI9341 @ ^1.5.6, Adafruit GFX Library, LOLIN_EPD, Adafruit BusIO, VL53L0X @ 1.3.0, SparkFun VL53L1X 4m Laser Distance Sensor @ 1.2.9, td-er/SparkFun MAX1704x Fuel Gauge Arduino Library @ ^1.0.1, ArduinoOTA, ESP32HTTPUpdateServer
|
||||
lib_ignore = ${esp32_always.lib_ignore}, ESP32_ping, IRremoteESP8266, HeatpumpIR
|
||||
board_build.f_flash = 80000000L
|
||||
board_build.flash_mode = dout
|
||||
|
||||
@@ -52,7 +52,7 @@ extends = common
|
||||
board_build.f_cpu = 80000000L
|
||||
build_flags = ${debug_flags.build_flags} ${mqtt_flags.build_flags} -DHTTPCLIENT_1_1_COMPATIBLE=0
|
||||
build_unflags = -DDEBUG_ESP_PORT
|
||||
lib_deps = td-er/ESPeasySerial @ 2.0.7, adafruit/Adafruit ILI9341 @ ^1.5.6, Adafruit GFX Library, LOLIN_EPD, Adafruit BusIO, bblanchon/ArduinoJson @ ^6.17.2, VL53L0X @ 1.3.0, SparkFun VL53L1X 4m Laser Distance Sensor @ 1.2.9, td-er/RABurton ESP8266 Mutex @ ^1.0.2, td-er/SparkFun MAX1704x Fuel Gauge Arduino Library @ ^1.0.1, ESP8266HTTPUpdateServer
|
||||
lib_deps = td-er/ESPeasySerial @ 2.0.8, adafruit/Adafruit ILI9341 @ ^1.5.6, Adafruit GFX Library, LOLIN_EPD, Adafruit BusIO, bblanchon/ArduinoJson @ ^6.17.2, VL53L0X @ 1.3.0, SparkFun VL53L1X 4m Laser Distance Sensor @ 1.2.9, td-er/RABurton ESP8266 Mutex @ ^1.0.2, td-er/SparkFun MAX1704x Fuel Gauge Arduino Library @ ^1.0.1, ESP8266HTTPUpdateServer
|
||||
lib_ignore = ${esp82xx_defaults.lib_ignore}, IRremoteESP8266, HeatpumpIR, LittleFS(esp8266), ServoESP32, TinyWireM
|
||||
board = esp12e
|
||||
monitor_filters = esp8266_exception_decoder
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ MarkupSafe==2.0.1
|
||||
marshmallow==3.14.0
|
||||
packaging==21.0
|
||||
pathtools==0.1.2
|
||||
platformio>=5.2.2
|
||||
platformio>=5.2.3
|
||||
port-for==0.6.1
|
||||
pycparser==2.20
|
||||
pyelftools==0.27
|
||||
|
||||
+3
-1
@@ -82,7 +82,9 @@ bool CPlugin_002(CPlugin::Function function, struct EventStruct *event, String&
|
||||
if (deserializeDomoticzJson(event->String2, idx, nvalue, nvaluealt, svalue1, switchtype)) {
|
||||
for (taskIndex_t x = 0; x < TASKS_MAX; x++) {
|
||||
// We need the index of the controller we are: 0...CONTROLLER_MAX
|
||||
if (Settings.TaskDeviceEnabled[x] && (Settings.TaskDeviceID[ControllerID][x] == idx)) // get idx for our controller index
|
||||
if (Settings.TaskDeviceEnabled[x] &&
|
||||
Settings.TaskDeviceSendData[ControllerID][x] &&
|
||||
(Settings.TaskDeviceID[ControllerID][x] == idx)) // get idx for our controller index
|
||||
{
|
||||
String action;
|
||||
bool mustSendEvent = false;
|
||||
|
||||
+4
-4
@@ -81,7 +81,7 @@ bool CPlugin_005(CPlugin::Function function, struct EventStruct *event, String&
|
||||
const int lastindex = event->String1.lastIndexOf('/');
|
||||
const String lastPartTopic = event->String1.substring(lastindex + 1);
|
||||
|
||||
if (lastPartTopic == F("cmd")) {
|
||||
if (lastPartTopic.equals(F("cmd"))) {
|
||||
// Example:
|
||||
// topic: ESP_Easy/Bathroom_pir_env/cmd
|
||||
// data: gpio,14,0
|
||||
@@ -116,14 +116,14 @@ bool CPlugin_005(CPlugin::Function function, struct EventStruct *event, String&
|
||||
|
||||
if (validTopic) {
|
||||
// in case of event, store to buffer and return...
|
||||
String command = parseString(cmd, 1);
|
||||
const String command = parseString(cmd, 1);
|
||||
|
||||
if ((command == F("event")) || (command == F("asyncevent"))) {
|
||||
if ((command.equals(F("event"))) || (command.equals(F("asyncevent")))) {
|
||||
if (Settings.UseRules) {
|
||||
eventQueue.addMove(parseStringToEnd(cmd, 2));
|
||||
}
|
||||
} else {
|
||||
ExecuteCommand(event->TaskIndex, EventValueSource::Enum::VALUE_SOURCE_MQTT, cmd.c_str(), true, true, true);
|
||||
ExecuteCommand_all(EventValueSource::Enum::VALUE_SOURCE_MQTT, cmd.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -92,9 +92,10 @@ bool CPlugin_006(CPlugin::Function function, struct EventStruct *event, String&
|
||||
cmd += topicSplit[6].toInt(); // Par1
|
||||
cmd += ',';
|
||||
|
||||
if ((event->String2 == F("false")) || (event->String2 == F("true")))
|
||||
if ((event->String2.equalsIgnoreCase(F("false"))) ||
|
||||
(event->String2.equalsIgnoreCase(F("true"))))
|
||||
{
|
||||
cmd += (event->String2 == F("true")) ? '1' : '0'; // Par2
|
||||
cmd += (event->String2.equalsIgnoreCase(F("true"))) ? '1' : '0'; // Par2
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+6
-14
@@ -42,13 +42,13 @@ boolean Plugin_053(uint8_t function, struct EventStruct *event, String& string)
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 4;
|
||||
# else // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# else // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
Device[deviceCount].FormulaOption = false;
|
||||
Device[deviceCount].ValueCount = 3;
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
@@ -166,27 +166,19 @@ boolean Plugin_053(uint8_t function, struct EventStruct *event, String& string)
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
{
|
||||
addFormSubHeader(F("Device"));
|
||||
# ifdef PLUGIN_053_ENABLE_S_AND_T
|
||||
int unitModelCount = 5;
|
||||
# else // ifdef PLUGIN_053_ENABLE_S_AND_T
|
||||
int unitModelCount = 3;
|
||||
# endif // ifdef PLUGIN_053_ENABLE_S_AND_T
|
||||
int unitModelCount = 5;
|
||||
const __FlashStringHelper *unitModels[] = {
|
||||
toString(PMSx003_type::PMS1003_5003_7003),
|
||||
toString(PMSx003_type::PMS2003_3003),
|
||||
# ifdef PLUGIN_053_ENABLE_S_AND_T
|
||||
toString(PMSx003_type::PMS5003_S),
|
||||
toString(PMSx003_type::PMS5003_T),
|
||||
# endif // ifdef PLUGIN_053_ENABLE_S_AND_T
|
||||
toString(PMSx003_type::PMS5003_ST)
|
||||
};
|
||||
const int unitModelOptions[] = {
|
||||
static_cast<int>(PMSx003_type::PMS1003_5003_7003),
|
||||
static_cast<int>(PMSx003_type::PMS2003_3003),
|
||||
# ifdef PLUGIN_053_ENABLE_S_AND_T
|
||||
static_cast<int>(PMSx003_type::PMS5003_S),
|
||||
static_cast<int>(PMSx003_type::PMS5003_T),
|
||||
# endif // ifdef PLUGIN_053_ENABLE_S_AND_T
|
||||
static_cast<int>(PMSx003_type::PMS5003_ST)
|
||||
};
|
||||
addFormSelector(F("Sensor model"), F("p053_model"), unitModelCount, unitModels, unitModelOptions, PLUGIN_053_SENSOR_MODEL_SELECTOR);
|
||||
@@ -314,9 +306,9 @@ boolean Plugin_053(uint8_t function, struct EventStruct *event, String& string)
|
||||
|
||||
PMSx003_type Plugin_053_sensortype = PMSx003_type::PMS1003_5003_7003;
|
||||
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
Plugin_053_sensortype = GET_PLUGIN_053_SENSOR_MODEL_SELECTOR;
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
|
||||
initPluginTaskData(
|
||||
event->TaskIndex,
|
||||
|
||||
+96
-2
@@ -30,6 +30,9 @@
|
||||
# define PLUGIN_VALUENAME4_082 "Speed"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# define P082_TIMEOUT PCONFIG(0)
|
||||
# define P082_TIMEOUT_LABEL PCONFIG_LABEL(0)
|
||||
# define P082_BAUDRATE PCONFIG(1)
|
||||
@@ -42,6 +45,10 @@
|
||||
# define P082_QUERY4 PCONFIG(6)
|
||||
# define P082_LONG_REF PCONFIG_FLOAT(0)
|
||||
# define P082_LAT_REF PCONFIG_FLOAT(1)
|
||||
#ifdef P082_USE_U_BLOX_SPECIFIC
|
||||
# define P082_POWER_MODE PCONFIG(7)
|
||||
# define P082_DYNAMIC_MODEL PCONFIG_LONG(0)
|
||||
#endif // P082_USE_U_BLOX_SPECIFIC
|
||||
|
||||
# define P082_NR_OUTPUT_VALUES VARS_PER_TASK
|
||||
# define P082_QUERY1_CONFIG_POS 3
|
||||
@@ -53,7 +60,6 @@
|
||||
# define P082_QUERY3_DFLT P082_query::P082_QUERY_ALT
|
||||
# define P082_QUERY4_DFLT P082_query::P082_QUERY_SPD
|
||||
|
||||
|
||||
// Must use volatile declared variable (which will end up in iRAM)
|
||||
volatile unsigned long P082_pps_time = 0;
|
||||
void Plugin_082_interrupt() ICACHE_RAM_ATTR;
|
||||
@@ -164,6 +170,53 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string)
|
||||
addFormNumericBox(F("Fix Timeout"), P082_TIMEOUT_LABEL, P082_TIMEOUT, 100, 10000);
|
||||
addUnit(F("ms"));
|
||||
|
||||
#ifdef P082_USE_U_BLOX_SPECIFIC
|
||||
|
||||
addFormSubHeader(F("U-Blox specific"));
|
||||
|
||||
{
|
||||
const __FlashStringHelper * options[3] = {
|
||||
toString(P082_PowerMode::Max_Performance),
|
||||
toString(P082_PowerMode::Power_Save),
|
||||
toString(P082_PowerMode::Eco)
|
||||
};
|
||||
const int indices[3] = {
|
||||
static_cast<int>(P082_PowerMode::Max_Performance),
|
||||
static_cast<int>(P082_PowerMode::Power_Save),
|
||||
static_cast<int>(P082_PowerMode::Eco)
|
||||
};
|
||||
addFormSelector(F("Power Mode"), F("pwrmode"), 3, options, indices, P082_POWER_MODE);
|
||||
}
|
||||
|
||||
{
|
||||
const __FlashStringHelper * options[10] = {
|
||||
toString(P082_DynamicModel::Portable),
|
||||
toString(P082_DynamicModel::Stationary),
|
||||
toString(P082_DynamicModel::Pedestrian),
|
||||
toString(P082_DynamicModel::Automotive),
|
||||
toString(P082_DynamicModel::Sea),
|
||||
toString(P082_DynamicModel::Airborne_1g),
|
||||
toString(P082_DynamicModel::Airborne_2g),
|
||||
toString(P082_DynamicModel::Airborne_4g),
|
||||
toString(P082_DynamicModel::Wrist),
|
||||
toString(P082_DynamicModel::Bike)
|
||||
};
|
||||
const int indices[10] = {
|
||||
static_cast<int>(P082_DynamicModel::Portable),
|
||||
static_cast<int>(P082_DynamicModel::Stationary),
|
||||
static_cast<int>(P082_DynamicModel::Pedestrian),
|
||||
static_cast<int>(P082_DynamicModel::Automotive),
|
||||
static_cast<int>(P082_DynamicModel::Sea),
|
||||
static_cast<int>(P082_DynamicModel::Airborne_1g),
|
||||
static_cast<int>(P082_DynamicModel::Airborne_2g),
|
||||
static_cast<int>(P082_DynamicModel::Airborne_4g),
|
||||
static_cast<int>(P082_DynamicModel::Wrist),
|
||||
static_cast<int>(P082_DynamicModel::Bike)
|
||||
};
|
||||
addFormSelector(F("Dynamic Platform Model"), F("dynmodel"), 10, options, indices, P082_DYNAMIC_MODEL);
|
||||
}
|
||||
#endif // P082_USE_U_BLOX_SPECIFIC
|
||||
|
||||
addFormSubHeader(F("Current Sensor Data"));
|
||||
|
||||
P082_html_show_stats(event);
|
||||
@@ -214,6 +267,10 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string)
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE: {
|
||||
#ifdef P082_USE_U_BLOX_SPECIFIC
|
||||
P082_POWER_MODE = getFormItemInt(F("pwrmode"));
|
||||
P082_DYNAMIC_MODEL = getFormItemInt(F("dynmodel"));
|
||||
#endif // P082_USE_U_BLOX_SPECIFIC
|
||||
P082_TIMEOUT = getFormItemInt(P082_TIMEOUT_LABEL);
|
||||
P082_DISTANCE = getFormItemInt(P082_DISTANCE_LABEL);
|
||||
|
||||
@@ -255,6 +312,10 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string)
|
||||
// pinMode(pps_pin, INPUT_PULLUP);
|
||||
attachInterrupt(pps_pin, Plugin_082_interrupt, RISING);
|
||||
}
|
||||
#ifdef P082_USE_U_BLOX_SPECIFIC
|
||||
P082_data->setPowerMode(static_cast<P082_PowerMode>(P082_POWER_MODE));
|
||||
P082_data->setDynamicModel(static_cast<P082_DynamicModel>(P082_DYNAMIC_MODEL));
|
||||
#endif // P082_USE_U_BLOX_SPECIFIC
|
||||
} else {
|
||||
clearPluginTaskData(event->TaskIndex);
|
||||
}
|
||||
@@ -277,7 +338,11 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string)
|
||||
|
||||
if ((nullptr != P082_data) && P082_data->loop()) {
|
||||
# ifdef P082_SEND_GPS_TO_LOG
|
||||
addLog(LOG_LEVEL_DEBUG, P082_data->_lastSentence);
|
||||
if (P082_data->_lastSentence.substring(0,10).indexOf(F("TXT")) != -1) {
|
||||
addLog(LOG_LEVEL_INFO, P082_data->_lastSentence);
|
||||
} else {
|
||||
addLog(LOG_LEVEL_DEBUG, P082_data->_lastSentence);
|
||||
}
|
||||
# endif // ifdef P082_SEND_GPS_TO_LOG
|
||||
Scheduler.schedule_task_device_timer(event->TaskIndex, millis());
|
||||
delay(0); // Processing a full sentence may take a while, run some
|
||||
@@ -394,6 +459,35 @@ boolean Plugin_082(uint8_t function, struct EventStruct *event, String& string)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PLUGIN_WRITE:
|
||||
{
|
||||
P082_data_struct *P082_data =
|
||||
static_cast<P082_data_struct *>(getPluginTaskData(event->TaskIndex));
|
||||
|
||||
if ((nullptr != P082_data) && P082_data->isInitialized()) {
|
||||
const String command = parseString(string, 1);
|
||||
const String subcommand = parseString(string, 2);
|
||||
|
||||
if (command.equals(F("gps"))) {
|
||||
if (subcommand.equals(F("wake"))) {
|
||||
success = P082_data->wakeUp();
|
||||
} else if (subcommand.equals(F("sleep"))) {
|
||||
success = P082_data->powerDown();
|
||||
}
|
||||
#ifdef P082_USE_U_BLOX_SPECIFIC
|
||||
else if (subcommand.equals(F("maxperf"))) {
|
||||
success = P082_data->setPowerMode(P082_PowerMode::Max_Performance);
|
||||
} else if (subcommand.equals(F("powersave"))) {
|
||||
success = P082_data->setPowerMode(P082_PowerMode::Power_Save);
|
||||
} else if (subcommand.equals(F("eco"))) {
|
||||
success = P082_data->setPowerMode(P082_PowerMode::Eco);
|
||||
}
|
||||
#endif // P082_USE_U_BLOX_SPECIFIC
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
# ifdef USES_PACKED_RAW_DATA
|
||||
case PLUGIN_GET_PACKED_RAW_DATA:
|
||||
{
|
||||
|
||||
@@ -46,17 +46,17 @@ P053_data_struct::P053_data_struct(
|
||||
int8_t pwrPin,
|
||||
PMSx003_type sensortype,
|
||||
uint32_t delay_read_after_wakeup_ms
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
, bool oversample
|
||||
, bool splitCntBins
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
)
|
||||
: _taskIndex(TaskIndex),
|
||||
_sensortype(sensortype),
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
_oversample(oversample),
|
||||
_splitCntBins(splitCntBins),
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
_delay_read_after_wakeup_ms(delay_read_after_wakeup_ms),
|
||||
_resetPin(resetPin), _pwrPin(pwrPin)
|
||||
{
|
||||
@@ -129,7 +129,7 @@ void P053_data_struct::SerialRead16(uint16_t& value, uint16_t *checksum)
|
||||
*checksum += data_low;
|
||||
}
|
||||
|
||||
# ifdef P053_LOW_LEVEL_DEBUG
|
||||
# ifdef P053_LOW_LEVEL_DEBUG
|
||||
|
||||
// Low-level logging to see data from sensor
|
||||
String log = F("PMSx003 : uint8_t high=0x");
|
||||
@@ -139,7 +139,7 @@ void P053_data_struct::SerialRead16(uint16_t& value, uint16_t *checksum)
|
||||
log += F(" result=0x");
|
||||
log += String(value, HEX);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
# endif // ifdef P053_LOW_LEVEL_DEBUG
|
||||
# endif // ifdef P053_LOW_LEVEL_DEBUG
|
||||
}
|
||||
|
||||
void P053_data_struct::SerialFlush() {
|
||||
@@ -260,8 +260,16 @@ bool P053_data_struct::processData(struct EventStruct *event) {
|
||||
SerialRead16(data[i], &checksum);
|
||||
}
|
||||
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
# ifdef P053_LOW_LEVEL_DEBUG
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
|
||||
if (GET_PLUGIN_053_SENSOR_MODEL_SELECTOR == PMSx003_type::PMS5003_T) {
|
||||
data[PMS_Temp_C] = data[PMS_T_Temp_C]; // Move data to the 'usual' location for Temp/Hum
|
||||
data[PMS_Hum_pct] = data[PMS_T_Hum_pct];
|
||||
}
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
|
||||
# ifndef BUILD_NO_DEBUG
|
||||
# ifdef P053_LOW_LEVEL_DEBUG
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) { // Available on all supported sensor models
|
||||
String log;
|
||||
@@ -281,7 +289,7 @@ bool P053_data_struct::processData(struct EventStruct *event) {
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)
|
||||
&& (GET_PLUGIN_053_SENSOR_MODEL_SELECTOR != PMSx003_type::PMS2003_3003)) { // 'Count' values not available on
|
||||
@@ -304,24 +312,26 @@ bool P053_data_struct::processData(struct EventStruct *event) {
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
|
||||
# ifdef PLUGIN_053_ENABLE_S_AND_T
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_DEBUG)
|
||||
&& (GET_PLUGIN_053_SENSOR_MODEL_SELECTOR == PMSx003_type::PMS5003_ST)) { // Values only available on PMS5003ST
|
||||
&& ((GET_PLUGIN_053_SENSOR_MODEL_SELECTOR == PMSx003_type::PMS5003_ST)
|
||||
|| (GET_PLUGIN_053_SENSOR_MODEL_SELECTOR == PMSx003_type::PMS5003_T))) { // Values only available on PMS5003ST & PMS5003T
|
||||
String log;
|
||||
log.reserve(45);
|
||||
log = F("PMSx003 : temp=");
|
||||
log += static_cast<float>(data[PMS_Temp_C]) / 10.0f;
|
||||
log += F(", humi=");
|
||||
log += static_cast<float>(data[PMS_Hum_pct]) / 10.0f;
|
||||
log += F(", hcho=");
|
||||
log += static_cast<float>(data[PMS_Formaldehyde_mg_m3]) / 1000.0f;
|
||||
|
||||
if (GET_PLUGIN_053_SENSOR_MODEL_SELECTOR == PMSx003_type::PMS5003_ST) {
|
||||
log += F(", hcho=");
|
||||
log += static_cast<float>(data[PMS_Formaldehyde_mg_m3]) / 1000.0f;
|
||||
}
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
# endif // ifdef PLUGIN_053_ENABLE_S_AND_T
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# endif // ifdef P053_LOW_LEVEL_DEBUG
|
||||
# endif // ifndef BUILD_NO_DEBUG
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# endif // ifdef P053_LOW_LEVEL_DEBUG
|
||||
# endif // ifndef BUILD_NO_DEBUG
|
||||
|
||||
// Compare checksums
|
||||
SerialRead16(checksum2, nullptr);
|
||||
@@ -350,14 +360,14 @@ bool P053_data_struct::processData(struct EventStruct *event) {
|
||||
# endif // ifndef BUILD_NO_DEBUG
|
||||
return false;
|
||||
}
|
||||
# ifndef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# ifndef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
|
||||
// Data is checked and good, fill in output
|
||||
UserVar[event->BaseVarIndex] = data[PMS_PM1_0_ug_m3_normal];
|
||||
UserVar[event->BaseVarIndex + 1] = data[PMS_PM2_5_ug_m3_normal];
|
||||
UserVar[event->BaseVarIndex + 2] = data[PMS_PM10_0_ug_m3_normal];
|
||||
_values_received = 1;
|
||||
# else // ifndef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# else // ifndef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
|
||||
// Store in the averaging buffer to process later
|
||||
if (!_oversample) {
|
||||
@@ -368,7 +378,7 @@ bool P053_data_struct::processData(struct EventStruct *event) {
|
||||
_data[i] += data[i];
|
||||
}
|
||||
++_values_received;
|
||||
# endif // ifndef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# endif // ifndef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
|
||||
|
||||
// Store new checksum, to help detect duplicates.
|
||||
@@ -606,11 +616,14 @@ bool P053_data_struct::getValue(uint8_t index, float& value) {
|
||||
if (!hasFormaldehyde()) { return false; }
|
||||
value = _data[index] / 1000.0f;
|
||||
break;
|
||||
case PMS_cnt5_0_100ml:
|
||||
case PMS_cnt10_0_100ml: // this option was missing :-|
|
||||
|
||||
if (_sensortype == PMSx003_type::PMS5003_T) { return false; } // else: fall through
|
||||
case PMS_cnt0_3_100ml:
|
||||
case PMS_cnt0_5_100ml:
|
||||
case PMS_cnt1_0_100ml:
|
||||
case PMS_cnt2_5_100ml:
|
||||
case PMS_cnt5_0_100ml:
|
||||
value = _data[index];
|
||||
|
||||
if (_splitCntBins) {
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
// Difference in build size is roughly 4k
|
||||
# define PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
|
||||
// #define PLUGIN_053_ENABLE_S_AND_T // Enable setting to support S and T types, in addition to bas PMSx003 and PMSx003ST
|
||||
|
||||
# if !defined(PLUGIN_BUILD_CUSTOM) && defined(SIZE_1M) && defined(PLUGIN_053_ENABLE_EXTRA_SENSORS) // Turn off for 1M OTA builds
|
||||
# undef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# endif // if defined(SIZE_1M) && defined(PLUGIN_BUILD_MINIMAL_OTA) && defined(PLUGIN_053_ENABLE_EXTRA_SENSORS)
|
||||
@@ -108,7 +106,9 @@ const __FlashStringHelper* toString(PMSx003_event_datatype selection);
|
||||
|
||||
# define PMS_Formaldehyde_mg_m3 12
|
||||
# define PMS_Temp_C 13
|
||||
# define PMS_T_Temp_C 10
|
||||
# define PMS_Hum_pct 14
|
||||
# define PMS_T_Hum_pct 11
|
||||
# define PMS_Reserved 15
|
||||
# define PMS_FW_rev_error 16
|
||||
# define PMS_RECEIVE_BUFFER_SIZE ((PMS5003_ST_SIZE / 2) - 3)
|
||||
@@ -125,13 +125,13 @@ public:
|
||||
int8_t resetPin,
|
||||
int8_t pwrPin,
|
||||
PMSx003_type sensortype,
|
||||
uint32_t delay_read_after_wakeup_ms
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
uint32_t delay_read_after_wakeup_ms
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
,
|
||||
bool oversample
|
||||
,
|
||||
bool splitCntBins
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
);
|
||||
|
||||
P053_data_struct() = delete;
|
||||
@@ -155,13 +155,13 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
void sendEvent(const String& baseEvent,
|
||||
uint8_t index);
|
||||
|
||||
bool hasFormaldehyde() const;
|
||||
bool hasTempHum() const;
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
|
||||
public:
|
||||
|
||||
@@ -183,14 +183,14 @@ private:
|
||||
|
||||
void requestData();
|
||||
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
|
||||
float getValue(uint8_t index);
|
||||
|
||||
bool getValue(uint8_t index,
|
||||
float & value);
|
||||
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
# endif // ifdef PLUGIN_053_ENABLE_EXTRA_SENSORS
|
||||
void clearReceivedData();
|
||||
|
||||
public:
|
||||
|
||||
@@ -27,10 +27,35 @@ const __FlashStringHelper * Plugin_082_valuename(P082_query value_nr, bool displ
|
||||
return F("");
|
||||
}
|
||||
|
||||
const __FlashStringHelper* toString(P082_PowerMode mode) {
|
||||
switch (mode) {
|
||||
case P082_PowerMode::Max_Performance: return F("Max Performance");
|
||||
case P082_PowerMode::Power_Save: return F("Power Save");
|
||||
case P082_PowerMode::Eco: return F("ECO");
|
||||
}
|
||||
return F("");
|
||||
}
|
||||
|
||||
const __FlashStringHelper* toString(P082_DynamicModel model) {
|
||||
switch (model) {
|
||||
case P082_DynamicModel::Portable: return F("Portable");
|
||||
case P082_DynamicModel::Stationary: return F("Stationary");
|
||||
case P082_DynamicModel::Pedestrian: return F("Pedestrian");
|
||||
case P082_DynamicModel::Automotive: return F("Automotive");
|
||||
case P082_DynamicModel::Sea: return F("Sea");
|
||||
case P082_DynamicModel::Airborne_1g: return F("Airborne_1g");
|
||||
case P082_DynamicModel::Airborne_2g: return F("Airborne_2g");
|
||||
case P082_DynamicModel::Airborne_4g: return F("Airborne_4g");
|
||||
case P082_DynamicModel::Wrist: return F("Wrist");
|
||||
case P082_DynamicModel::Bike: return F("Bike");
|
||||
}
|
||||
return F("");
|
||||
}
|
||||
|
||||
P082_data_struct::P082_data_struct() : gps(nullptr), easySerial(nullptr) {}
|
||||
|
||||
P082_data_struct::~P082_data_struct() {
|
||||
powerDown();
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -56,6 +81,7 @@ bool P082_data_struct::init(ESPEasySerialPort port, const int16_t serial_rx, con
|
||||
|
||||
if (easySerial != nullptr) {
|
||||
easySerial->begin(9600);
|
||||
wakeUp();
|
||||
}
|
||||
return isInitialized();
|
||||
}
|
||||
@@ -76,24 +102,78 @@ bool P082_data_struct::loop() {
|
||||
|
||||
while (available > 0 && timePassedSince(startLoop) < 10) {
|
||||
--available;
|
||||
char c = easySerial->read();
|
||||
int c = easySerial->read();
|
||||
if (c >= 0) {
|
||||
# ifdef P082_SEND_GPS_TO_LOG
|
||||
if (_currentSentence.length() <= 80) {
|
||||
// No need to capture more than 80 bytes as a NMEA message is never that long.
|
||||
_currentSentence += c;
|
||||
}
|
||||
if (_currentSentence.length() <= 80) {
|
||||
// No need to capture more than 80 bytes as a NMEA message is never that long.
|
||||
if (c != 0) {
|
||||
_currentSentence += static_cast<char>(c);
|
||||
}
|
||||
}
|
||||
# endif // ifdef P082_SEND_GPS_TO_LOG
|
||||
|
||||
if (gps->encode(c)) {
|
||||
// Full sentence received
|
||||
if (c == 0x85) {
|
||||
// Found possible start of u-blox message
|
||||
unsigned long timeout = millis() + 200;
|
||||
unsigned int bytesRead = 0;
|
||||
bool done = false;
|
||||
bool ack_nak_read = false;
|
||||
while (!timeOutReached(timeout) && !done)
|
||||
{
|
||||
if (available == 0) {
|
||||
available = easySerial->available();
|
||||
} else {
|
||||
const int c = easySerial->read();
|
||||
if (c >= 0) {
|
||||
switch (bytesRead) {
|
||||
case 0:
|
||||
if (c != 0x62) {
|
||||
done = true;
|
||||
}
|
||||
++bytesRead;
|
||||
break;
|
||||
case 1:
|
||||
if (c != 0x05) {
|
||||
done = true;
|
||||
}
|
||||
++bytesRead;
|
||||
break;
|
||||
case 2:
|
||||
if (c == 0x01) {
|
||||
ack_nak_read = true;
|
||||
addLog(LOG_LEVEL_INFO, F("GPS : ACK-ACK"));
|
||||
} else if (c == 0x00) {
|
||||
ack_nak_read = true;
|
||||
addLog(LOG_LEVEL_ERROR, F("GPS : ACK-NAK"));
|
||||
}
|
||||
done = true;
|
||||
break;
|
||||
default:
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!done) {
|
||||
addLog(LOG_LEVEL_ERROR, F("GPS : Ack/Nack timeout"));
|
||||
} else if (!ack_nak_read) {
|
||||
addLog(LOG_LEVEL_ERROR, F("GPS : Unexpected reply"));
|
||||
}
|
||||
}
|
||||
|
||||
if (gps->encode(c)) {
|
||||
// Full sentence received
|
||||
# ifdef P082_SEND_GPS_TO_LOG
|
||||
_lastSentence = _currentSentence;
|
||||
_currentSentence = "";
|
||||
_lastSentence = _currentSentence;
|
||||
_currentSentence.clear();
|
||||
# endif // ifdef P082_SEND_GPS_TO_LOG
|
||||
completeSentence = true;
|
||||
} else {
|
||||
if (available == 0) {
|
||||
available = easySerial->available();
|
||||
completeSentence = true;
|
||||
} else {
|
||||
if (available == 0) {
|
||||
available = easySerial->available();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,4 +259,102 @@ bool P082_data_struct::getDateTime(struct tm& dateTime, uint32_t& age, bool& pps
|
||||
return true;
|
||||
}
|
||||
|
||||
bool P082_data_struct::powerDown() {
|
||||
const uint8_t UBLOX_GPSStandby[] = {0xB5, 0x62, 0x02, 0x41, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x4D, 0x3B};
|
||||
return writeToGPS(UBLOX_GPSStandby, sizeof(UBLOX_GPSStandby));
|
||||
}
|
||||
|
||||
bool P082_data_struct::wakeUp() {
|
||||
if (isInitialized()) {
|
||||
if (easySerial->isTxEnabled()) {
|
||||
easySerial->println(); // Send some character to wake it up.
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef P082_USE_U_BLOX_SPECIFIC
|
||||
bool P082_data_struct::setPowerMode(P082_PowerMode mode) {
|
||||
switch (mode) {
|
||||
case P082_PowerMode::Max_Performance:
|
||||
{
|
||||
const uint8_t UBLOX_command[] = {0xB5, 0x62, 0x06, 0x11, 0x02, 0x00, 0x08, 0x00, 0x21, 0x91};
|
||||
return writeToGPS(UBLOX_command, sizeof(UBLOX_command));
|
||||
}
|
||||
case P082_PowerMode::Power_Save:
|
||||
{
|
||||
const uint8_t UBLOX_command[] = {0xB5, 0x62, 0x06, 0x11, 0x02, 0x00, 0x08, 0x01, 0x22, 0x92};
|
||||
return writeToGPS(UBLOX_command, sizeof(UBLOX_command));
|
||||
}
|
||||
case P082_PowerMode::Eco:
|
||||
{
|
||||
const uint8_t UBLOX_command[] = {0xB5, 0x62, 0x06, 0x11, 0x02, 0x00, 0x08, 0x04, 0x25, 0x95};
|
||||
return writeToGPS(UBLOX_command, sizeof(UBLOX_command));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool P082_data_struct::setDynamicModel(P082_DynamicModel model) {
|
||||
|
||||
const uint8_t dynModel = static_cast<uint8_t>(model);
|
||||
if (dynModel == 1 || dynModel > 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t UBLOX_command[] = {
|
||||
0xB5, 0x62, // header
|
||||
0x06, // class
|
||||
0x24, // ID, UBX-CFG-NAV5
|
||||
0x24, 0x00, // length
|
||||
0x01, 0x00, // mask
|
||||
dynModel, // dynModel
|
||||
0x03, // fixMode auto 2D/3D
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
setUbloxChecksum(UBLOX_command, sizeof(UBLOX_command));
|
||||
return writeToGPS(UBLOX_command, sizeof(UBLOX_command));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef P082_USE_U_BLOX_SPECIFIC
|
||||
void P082_data_struct::computeUbloxChecksum(const uint8_t* data, size_t size, uint8_t & CK_A, uint8_t & CK_B) {
|
||||
CK_A = 0;
|
||||
CK_B = 0;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
CK_A = CK_A + data[i];
|
||||
CK_B = CK_B + CK_A;
|
||||
}
|
||||
}
|
||||
|
||||
void P082_data_struct::setUbloxChecksum(uint8_t* data, size_t size) {
|
||||
uint8_t CK_A;
|
||||
uint8_t CK_B;
|
||||
computeUbloxChecksum(data + 2, size - 4, CK_A, CK_B);
|
||||
data[size - 2] = CK_A;
|
||||
data[size - 1] = CK_B;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool P082_data_struct::writeToGPS(const uint8_t* data, size_t size) {
|
||||
if (isInitialized()) {
|
||||
if (easySerial->isTxEnabled()) {
|
||||
if (size != easySerial->write(data, size)) {
|
||||
addLog(LOG_LEVEL_ERROR, F("GPS : Written less bytes than expected"));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
addLog(LOG_LEVEL_ERROR, F("GPS : Cannot send to GPS"));
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // ifdef USES_P082
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#ifndef LIMIT_BUILD_SIZE
|
||||
# define P082_SEND_GPS_TO_LOG
|
||||
//# define P082_USE_U_BLOX_SPECIFIC // TD-er: Disabled for now, as it is not working reliable/predictable
|
||||
#endif
|
||||
|
||||
# define P082_TIMESTAMP_AGE 1500
|
||||
@@ -34,8 +35,35 @@ enum class P082_query : uint8_t {
|
||||
const __FlashStringHelper * Plugin_082_valuename(P082_query value_nr, bool displayString);
|
||||
|
||||
|
||||
enum class P082_PowerMode : uint8_t {
|
||||
Max_Performance = 0,
|
||||
Power_Save = 1,
|
||||
Eco = 2
|
||||
};
|
||||
|
||||
const __FlashStringHelper* toString(P082_PowerMode mode);
|
||||
|
||||
|
||||
enum class P082_DynamicModel : uint8_t {
|
||||
Portable = 0,
|
||||
Stationary = 2,
|
||||
Pedestrian = 3,
|
||||
Automotive = 4,
|
||||
Sea = 5,
|
||||
Airborne_1g = 6, // airborne with <1g acceleration
|
||||
Airborne_2g = 7, // airborne with <2g acceleration
|
||||
Airborne_4g = 8, // airborne with <4g acceleration
|
||||
Wrist = 9, // Only recommended for wrist-worn applications. Receiver will filter out armmotion (just available for protocol version > 17).
|
||||
Bike = 10 // Used for applications with equivalent dynamics to those of a motor bike. Lowvertical acceleration assumed. (supported in protocol versions 19.2)
|
||||
};
|
||||
|
||||
const __FlashStringHelper* toString(P082_DynamicModel model);
|
||||
|
||||
struct P082_data_struct : public PluginTaskData_base {
|
||||
|
||||
// Enum is being stored, so don't change int values
|
||||
|
||||
|
||||
P082_data_struct();
|
||||
|
||||
~P082_data_struct();
|
||||
@@ -65,6 +93,34 @@ struct P082_data_struct : public PluginTaskData_base {
|
||||
uint32_t & age,
|
||||
bool & pps_sync);
|
||||
|
||||
// Send command to GPS to put it in PMREQ backup mode (UBLOX only)
|
||||
// @retval true when successful in sending command
|
||||
bool powerDown();
|
||||
|
||||
// Send some characters to GPS to wake up
|
||||
bool wakeUp();
|
||||
#ifdef P082_USE_U_BLOX_SPECIFIC
|
||||
bool setPowerMode(P082_PowerMode mode);
|
||||
|
||||
bool setDynamicModel(P082_DynamicModel model);
|
||||
#endif
|
||||
|
||||
private:
|
||||
#ifdef P082_USE_U_BLOX_SPECIFIC
|
||||
// Compute checksum
|
||||
// Caller should offset the data pointer to the correct start where the CRC should start.
|
||||
// @param size The length over which the CRC should be computed
|
||||
// @param CK_A, CK_B The 2 checksum bytes.
|
||||
static void computeUbloxChecksum(const uint8_t* data, size_t size, uint8_t & CK_A, uint8_t & CK_B);
|
||||
|
||||
// Set checksum.
|
||||
// First 2 bytes of the array are skipped
|
||||
static void setUbloxChecksum(uint8_t* data, size_t size);
|
||||
#endif
|
||||
|
||||
bool writeToGPS(const uint8_t* data, size_t size);
|
||||
public:
|
||||
|
||||
TinyGPSPlus *gps = nullptr;
|
||||
ESPeasySerial *easySerial = nullptr;
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ else:
|
||||
"-DUSES_P026", # System info
|
||||
"-DUSES_P027", # INA219
|
||||
"-DUSES_P028", # BME280
|
||||
"-DUSES_P033", # Dummy
|
||||
"-DUSES_P036", # FrameOLED
|
||||
"-DUSES_P038", # Neopixel
|
||||
"-DUSES_P045", # MPU6050
|
||||
"-DUSES_P049", # MHZ19
|
||||
"-DUSES_P052", # SenseAir
|
||||
|
||||
Reference in New Issue
Block a user