mirror of
https://github.com/airgradienthq/arduino.git
synced 2025-12-16 18:48:26 +01:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72bf812235 | ||
|
|
2c37ab9895 | ||
|
|
565a7fa9fd | ||
|
|
9e07b67951 | ||
|
|
23f8c383fd | ||
|
|
c0ad1dbfad | ||
|
|
75be7d9fc5 | ||
|
|
309d322100 | ||
|
|
89ebe6c39f | ||
|
|
29db5469f5 |
31
.github/workflows/check.yml
vendored
31
.github/workflows/check.yml
vendored
@@ -1,5 +1,36 @@
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
trailing-whitespace:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Check for trailing whitespace
|
||||
run: |
|
||||
set -u
|
||||
|
||||
# Don't enforce checks on vendored libraries.
|
||||
readonly EXCLUDED_DIR='src/Libraries'
|
||||
|
||||
has_trailing_whitespace=false
|
||||
|
||||
while read -r line; do
|
||||
if grep \
|
||||
"\s$" \
|
||||
--line-number \
|
||||
--with-filename \
|
||||
--binary-files=without-match \
|
||||
"${line}"; then
|
||||
has_trailing_whitespace=true
|
||||
fi
|
||||
done < <(git ls-files | grep --invert-match "^${EXCLUDED_DIR}/")
|
||||
|
||||
if [ "$has_trailing_whitespace" = true ]; then
|
||||
echo "ERROR: Found trailing whitespace"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
compile:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
@@ -32,7 +32,7 @@ Each GitHub release note will also include the planned rollout date for wider av
|
||||
|
||||
## Help & Support
|
||||
|
||||
If you have any questions or problems, check out [our forum](https://forum.airgradient.com/).
|
||||
If you have any questions or problems, check out [our forum](https://forum.airgradient.com/).
|
||||
|
||||
## Development
|
||||
|
||||
|
||||
@@ -16,15 +16,15 @@ Arduino IDE version 2.x ([download](https://www.arduino.cc/en/software))
|
||||
|
||||
#### Version < 3.2.0
|
||||
|
||||
Using library manager install the latest version (Tools ➝ Manage Libraries... ➝ search for `"airgradient"`)
|
||||
Using library manager install the latest version (Tools ➝ Manage Libraries... ➝ search for `"airgradient"`)
|
||||
|
||||

|
||||
|
||||
#### Version >= 3.3.0
|
||||
|
||||
- From your terminal, go to Arduino libraries folder (windows and mac: `Documents/Arduino/libraries` or linux: `~/Arduino/Libraries`).
|
||||
- With **git** cli, execute this command `git clone --recursive https://github.com/airgradienthq/arduino.git AirGradient_Air_Quality_Sensor`
|
||||
- Restart Arduino IDE
|
||||
- With **git** cli, execute this command `git clone --recursive https://github.com/airgradienthq/arduino.git AirGradient_Air_Quality_Sensor`
|
||||
- Restart Arduino IDE
|
||||
|
||||
3. On tools tab, follow settings below
|
||||
|
||||
@@ -57,7 +57,7 @@ Upload Speed ➝ 921600
|
||||
|
||||

|
||||
|
||||
3. Install AirGradient library on library manager using the latest version (Tools ➝ Manage Libraries... ➝ search for `"airgradient"`)
|
||||
3. Install AirGradient library on library manager using the latest version (Tools ➝ Manage Libraries... ➝ search for `"airgradient"`)
|
||||
|
||||

|
||||
|
||||
@@ -65,7 +65,7 @@ Upload Speed ➝ 921600
|
||||
|
||||

|
||||
|
||||
5. Open sketch to compile (File ➝ Examples ➝ AirGradient Air Quality Sensor ➝ `<Model Option>`). Depends on the DIY model, either `BASIC`, `DiyProIndoorV3_3` and `DiyProIndoorV4_2`
|
||||
5. Open sketch to compile (File ➝ Examples ➝ AirGradient Air Quality Sensor ➝ `<Model Option>`). Depends on the DIY model, either `BASIC`, `DiyProIndoorV3_3` and `DiyProIndoorV4_2`
|
||||
6. Compile
|
||||
|
||||

|
||||
@@ -78,13 +78,13 @@ ModuleNotFoundError: No module named ‘serial’
|
||||
|
||||

|
||||
|
||||
Make sure python pyserial module installed globally in the environment by executing:
|
||||
Make sure python pyserial module installed globally in the environment by executing:
|
||||
|
||||
`$ sudo apt install -y python3-pyserial`
|
||||
|
||||
or
|
||||
or
|
||||
|
||||
`$ pip install pyserial`
|
||||
`$ pip install pyserial`
|
||||
|
||||
Choose based on how python installed on your machine. But most user, using `apt` is better.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## Local Server API
|
||||
|
||||
From [firmware version 3.0.10](firmwares) onwards, the AirGradient ONE and Open Air monitors have below API available.
|
||||
From [firmware version 3.0.10](firmwares) onwards, the AirGradient ONE and Open Air monitors have below API available.
|
||||
|
||||
### Discovery
|
||||
|
||||
@@ -20,7 +20,7 @@ http://airgradient_ecda3b1eaaaf.local/measures/current
|
||||
“ecda3b1eaaaf” being the serial number of your monitor.
|
||||
|
||||
You get the following response:
|
||||
```json
|
||||
```json
|
||||
{
|
||||
"wifi": -46,
|
||||
"serialno": "ecda3b1eaaaf",
|
||||
@@ -84,7 +84,7 @@ Compensated values apply correction algorithms to make the sensor values more ac
|
||||
|
||||
"/config" path returns the current configuration of the monitor.
|
||||
|
||||
```json
|
||||
```json
|
||||
{
|
||||
"country": "TH",
|
||||
"pmStandard": "ugm3",
|
||||
@@ -118,22 +118,22 @@ Configuration parameters can be changed with a PUT request to the monitor, e.g.
|
||||
Example to force CO2 calibration
|
||||
|
||||
```bash
|
||||
curl -X PUT -H "Content-Type: application/json" -d '{"co2CalibrationRequested":true}' http://airgradient_84fce612eff4.local/config
|
||||
curl -X PUT -H "Content-Type: application/json" -d '{"co2CalibrationRequested":true}' http://airgradient_84fce612eff4.local/config
|
||||
```
|
||||
|
||||
Example to set monitor to Celsius
|
||||
|
||||
```bash
|
||||
curl -X PUT -H "Content-Type: application/json" -d '{"temperatureUnit":"c"}' http://airgradient_84fce612eff4.local/config
|
||||
curl -X PUT -H "Content-Type: application/json" -d '{"temperatureUnit":"c"}' http://airgradient_84fce612eff4.local/config
|
||||
```
|
||||
|
||||
If you use command prompt on Windows, you need to escape the quotes:
|
||||
|
||||
|
||||
``` -d "{\"param\":\"value\"}" ```
|
||||
|
||||
### Avoiding Conflicts with Configuration on AirGradient Server
|
||||
|
||||
If the monitor is set up on the AirGradient dashboard, it will also receive the configuration parameters from there. In case you do not want this, please set `configurationControl` to `local`. In case you set it to `cloud` and want to change it to `local`, you need to make a factory reset.
|
||||
If the monitor is set up on the AirGradient dashboard, it will also receive the configuration parameters from there. In case you do not want this, please set `configurationControl` to `local`. In case you set it to `cloud` and want to change it to `local`, you need to make a factory reset.
|
||||
|
||||
### Configuration Parameters (GET/PUT)
|
||||
|
||||
@@ -204,34 +204,34 @@ Example correction configuration:
|
||||
Field Name: `pm02`
|
||||
|
||||
| Algorithm | Value | Description | SLR required |
|
||||
|------------|-------------|------|---------|
|
||||
|------------|-------------|------|---------|
|
||||
| Raw | `"none"` | No correction (default) | No |
|
||||
| EPA 2021 | `"epa_2021"` | Use EPA 2021 correction factors on top of raw value | No |
|
||||
| PMS5003_20240104 | `"slr_PMS5003_20240104"` | Correction for PMS5003 sensor batch 20240104| Yes |
|
||||
| PMS5003_20240104 | `"slr_PMS5003_20240104"` | Correction for PMS5003 sensor batch 20240104| Yes |
|
||||
| PMS5003_20231218 | `"slr_PMS5003_20231218"` | Correction for PMS5003 sensor batch 20231218| Yes |
|
||||
| PMS5003_20231030 | `"slr_PMS5003_20231030"` | Correction for PMS5003 sensor batch 20231030| Yes |
|
||||
|
||||
**NOTES**:
|
||||
**NOTES**:
|
||||
|
||||
- Set `useEpa2021` to `true` if want to apply EPA 2021 correction factors on top of SLR correction value, otherwise `false`
|
||||
- `intercept` and `scalingFactor` values can be obtained from [this article](https://www.airgradient.com/blog/low-readings-from-pms5003/)
|
||||
- If `configurationControl` is set to `local` (eg. when using Home Assistant), correction need to be set manually, see examples below
|
||||
- If `configurationControl` is set to `local` (eg. when using Home Assistant), correction need to be set manually, see examples below
|
||||
|
||||
**Examples**:
|
||||
|
||||
- PMS5003_20231030
|
||||
- PMS5003_20231030
|
||||
|
||||
```bash
|
||||
curl --location -X PUT 'http://airgradient_84fce612eff4.local/config' --header 'Content-Type: application/json' --data '{"corrections":{"pm02":{"correctionAlgorithm":"slr_PMS5003_20231030","slr":{"intercept":0,"scalingFactor":0.02838,"useEpa2021":true}}}}'
|
||||
```
|
||||
|
||||
- PMS5003_20231218
|
||||
- PMS5003_20231218
|
||||
|
||||
```bash
|
||||
curl --location -X PUT 'http://airgradient_84fce612eff4.local/config' --header 'Content-Type: application/json' --data '{"corrections":{"pm02":{"correctionAlgorithm":"slr_PMS5003_20231218","slr":{"intercept":0,"scalingFactor":0.03525,"useEpa2021":true}}}}'
|
||||
```
|
||||
|
||||
- PMS5003_20240104
|
||||
- PMS5003_20240104
|
||||
|
||||
```bash
|
||||
curl --location -X PUT 'http://airgradient_84fce612eff4.local/config' --header 'Content-Type: application/json' --data '{"corrections":{"pm02":{"correctionAlgorithm":"slr_PMS5003_20240104","slr":{"intercept":0,"scalingFactor":0.02896,"useEpa2021":true}}}}'
|
||||
@@ -244,10 +244,10 @@ Field Name:
|
||||
- Humidity: `rhum`
|
||||
|
||||
| Algorithm | Value | Description | SLR required |
|
||||
|------------|-------------|------|---------|
|
||||
|------------|-------------|------|---------|
|
||||
| Raw | `"none"` | No correction (default) | No |
|
||||
| AirGradient Standard Correction | `"ag_pms5003t_2024"` | Using standard airgradient correction (for outdoor monitor)| No |
|
||||
| Custom | `"custom"` | custom corrections constant, set `intercept` and `scalingFactor` manually | Yes |
|
||||
| Custom | `"custom"` | custom corrections constant, set `intercept` and `scalingFactor` manually | Yes |
|
||||
|
||||
*Table above apply for both Temperature and Humidity*
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
## OTA Updates
|
||||
|
||||
From [firmware version 3.1.1](https://github.com/airgradienthq/arduino/tree/3.1.1) onwards, the AirGradient ONE and Open Air monitors support over the air (OTA) updates.
|
||||
From [firmware version 3.1.1](https://github.com/airgradienthq/arduino/tree/3.1.1) onwards, the AirGradient ONE and Open Air monitors support over the air (OTA) updates.
|
||||
|
||||
#### Mechanism
|
||||
|
||||
@@ -10,7 +10,7 @@ The device attempts to update to the latest version on startup and in regular in
|
||||
|
||||
http://hw.airgradient.com/sensors/{deviceId}/generic/os/firmware.bin?current_firmware={GIT_VERSION}
|
||||
|
||||
If does pass the version it is currently running on along to the server through URL parameter 'current_firmware'.
|
||||
If does pass the version it is currently running on along to the server through URL parameter 'current_firmware'.
|
||||
This allows the server to identify if the device is already running on the latest version or should update.
|
||||
|
||||
The following scenarios are possible
|
||||
|
||||
@@ -294,7 +294,7 @@ static bool sgp41Init(void) {
|
||||
configuration.hasSensorSGP = true;
|
||||
return true;
|
||||
} else {
|
||||
Serial.println("Init SGP41 failuire");
|
||||
Serial.println("Init SGP41 failure");
|
||||
configuration.hasSensorSGP = false;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -351,7 +351,7 @@ static bool sgp41Init(void) {
|
||||
configuration.hasSensorSGP = true;
|
||||
return true;
|
||||
} else {
|
||||
Serial.println("Init SGP41 failuire");
|
||||
Serial.println("Init SGP41 failure");
|
||||
configuration.hasSensorSGP = false;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -249,7 +249,7 @@ void loop() {
|
||||
configUpdateHandle();
|
||||
|
||||
localServer._handle();
|
||||
|
||||
|
||||
if (configuration.hasSensorSGP) {
|
||||
ag.sgp41.handle();
|
||||
}
|
||||
@@ -374,7 +374,7 @@ static bool sgp41Init(void) {
|
||||
configuration.hasSensorSGP = true;
|
||||
return true;
|
||||
} else {
|
||||
Serial.println("Init SGP41 failuire");
|
||||
Serial.println("Init SGP41 failure");
|
||||
configuration.hasSensorSGP = false;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -75,8 +75,8 @@ CC BY-SA 4.0 Attribution-ShareAlike 4.0 International License
|
||||
#define SENSOR_TEMP_HUM_UPDATE_INTERVAL 6000 /** ms */
|
||||
#define DISPLAY_DELAY_SHOW_CONTENT_MS 2000 /** ms */
|
||||
#define FIRMWARE_CHECK_FOR_UPDATE_MS (60 * 60 * 1000) /** ms */
|
||||
#define TIME_TO_START_POWER_CYCLE_CELLULAR_MODULE (1 * 60) /** minutes */
|
||||
#define TIMEOUT_WAIT_FOR_CELLULAR_MODULE_READY (2 * 60) /** minutes */
|
||||
#define TIME_TO_START_POWER_CYCLE_CELLULAR_MODULE (1 * 60) /** minutes */
|
||||
#define TIMEOUT_WAIT_FOR_CELLULAR_MODULE_READY (2 * 60) /** minutes */
|
||||
|
||||
#define MEASUREMENT_TRANSMIT_CYCLE 3
|
||||
#define MAXIMUM_MEASUREMENT_CYCLE_QUEUE 80
|
||||
@@ -123,7 +123,7 @@ static uint32_t factoryBtnPressTime = 0;
|
||||
static AgFirmwareMode fwMode = FW_MODE_I_9PSL;
|
||||
static bool ledBarButtonTest = false;
|
||||
static String fwNewVersion;
|
||||
static int lastCellSignalQuality = 99; // CSQ
|
||||
static int lastCellSignalQuality = 99; // CSQ
|
||||
|
||||
// Default value is 0, indicate its not started yet
|
||||
// In minutes
|
||||
@@ -136,7 +136,7 @@ static void boardInit(void);
|
||||
static void initializeNetwork();
|
||||
static void failedHandler(String msg);
|
||||
static void configurationUpdateSchedule(void);
|
||||
static void configUpdateHandle(void);
|
||||
static void configUpdateHandle(void);
|
||||
static void updateDisplayAndLedBar(void);
|
||||
static void updateTvoc(void);
|
||||
static void updatePm(void);
|
||||
@@ -157,7 +157,7 @@ static void displayExecuteOta(AirgradientOTA::OtaResult result, String msg, int
|
||||
static int calculateMaxPeriod(int updateInterval);
|
||||
static void setMeasurementMaxPeriod();
|
||||
static void newMeasurementCycle();
|
||||
static void restartIfCeClientIssueOverTwoHours();
|
||||
static void restartIfCeClientIssueOverTwoHours();
|
||||
static void networkSignalCheck();
|
||||
static void networkingTask(void *args);
|
||||
|
||||
@@ -180,7 +180,7 @@ void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(100); /** For bester show log */
|
||||
|
||||
// Enable cullular module power board
|
||||
// Enable cullular module power board
|
||||
pinMode(GPIO_EXPANSION_CARD_POWER, OUTPUT);
|
||||
digitalWrite(GPIO_EXPANSION_CARD_POWER, HIGH);
|
||||
|
||||
@@ -284,7 +284,7 @@ void setup() {
|
||||
// Queue now only applied for cellular
|
||||
// Allocate queue memory to avoid always reallocation
|
||||
measurementCycleQueue.reserve(RESERVED_MEASUREMENT_CYCLE_CAPACITY);
|
||||
// Initialize mutex to access mesurementCycleQueue
|
||||
// Initialize mutex to access mesurementCycleQueue
|
||||
mutexMeasurementCycleQueue = xSemaphoreCreateMutex();
|
||||
}
|
||||
|
||||
@@ -312,7 +312,7 @@ void setup() {
|
||||
void loop() {
|
||||
if (networkOption == UseCellular) {
|
||||
// Check if cellular client not ready until certain time
|
||||
// Redundant check in both task to make sure its executed
|
||||
// Redundant check in both task to make sure its executed
|
||||
restartIfCeClientIssueOverTwoHours();
|
||||
}
|
||||
|
||||
@@ -559,7 +559,7 @@ static bool sgp41Init(void) {
|
||||
configuration.hasSensorSGP = true;
|
||||
return true;
|
||||
} else {
|
||||
Serial.println("Init SGP41 failuire");
|
||||
Serial.println("Init SGP41 failure");
|
||||
configuration.hasSensorSGP = false;
|
||||
}
|
||||
return false;
|
||||
@@ -725,7 +725,7 @@ static void sendDataToAg() {
|
||||
"task_led", 2048, NULL, 5, NULL);
|
||||
|
||||
delay(1500);
|
||||
|
||||
|
||||
// Build payload to check connection to airgradient server
|
||||
JSONVar root;
|
||||
root["wifi"] = wifiConnector.RSSI();
|
||||
@@ -952,6 +952,8 @@ static void boardInit(void) {
|
||||
} else {
|
||||
Serial.println("Set S8 AbcDays failure");
|
||||
}
|
||||
|
||||
ag->s8.printInformation();
|
||||
}
|
||||
|
||||
localServer.setFwMode(fwMode);
|
||||
@@ -970,7 +972,7 @@ void initializeNetwork() {
|
||||
agSerial->init(GPIO_IIC_RESET);
|
||||
if (agSerial->open()) {
|
||||
Serial.println("Cellular module found");
|
||||
// Initialize cellular module and use cellular as agClient
|
||||
// Initialize cellular module and use cellular as agClient
|
||||
cellularCard = new CellularModuleA7672XX(agSerial, GPIO_POWER_MODULE_PIN);
|
||||
agClient = new AirgradientCellularClient(cellularCard);
|
||||
networkOption = UseCellular;
|
||||
@@ -984,7 +986,7 @@ void initializeNetwork() {
|
||||
}
|
||||
|
||||
if (networkOption == UseCellular) {
|
||||
// Enable serial stream debugging to check the AT command when doing registration
|
||||
// Enable serial stream debugging to check the AT command when doing registration
|
||||
agSerial->setDebug(true);
|
||||
}
|
||||
|
||||
@@ -1005,7 +1007,7 @@ void initializeNetwork() {
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
// Provide openmetrics to have access to last transmission result
|
||||
// Provide openmetrics to have access to last transmission result
|
||||
openMetrics.setAirgradientClient(agClient);
|
||||
|
||||
if (networkOption == UseCellular) {
|
||||
@@ -1018,7 +1020,7 @@ void initializeNetwork() {
|
||||
Serial.println("Cannot initiate wifi connection");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!wifiConnector.isConnected()) {
|
||||
Serial.println("Failed connect to WiFi");
|
||||
if (wifiConnector.isConfigurePorttalTimeout()) {
|
||||
@@ -1027,17 +1029,17 @@ void initializeNetwork() {
|
||||
oledDisplay.setText("", "", "");
|
||||
ESP.restart();
|
||||
}
|
||||
|
||||
|
||||
// Directly return because the rest of the function applied if wifi is connect only
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Initiate local network configuration
|
||||
mdnsInit();
|
||||
localServer.begin();
|
||||
// Apply mqtt connection if configured
|
||||
initMqtt();
|
||||
|
||||
|
||||
// Ignore the rest if cloud connection to AirGradient is disabled
|
||||
if (configuration.isCloudConnectionDisabled()) {
|
||||
return;
|
||||
@@ -1202,7 +1204,7 @@ static void updateDisplayAndLedBar(void) {
|
||||
}
|
||||
|
||||
if (configuration.isCloudConnectionDisabled()) {
|
||||
// Ignore API related check since cloud is disabled
|
||||
// Ignore API related check since cloud is disabled
|
||||
stateMachine.displayHandle(AgStateMachineNormal);
|
||||
stateMachine.handleLeds(AgStateMachineNormal);
|
||||
return;
|
||||
@@ -1395,7 +1397,7 @@ void postUsingWifi() {
|
||||
void postUsingCellular(bool forcePost) {
|
||||
// Aquire queue mutex to get queue size
|
||||
xSemaphoreTake(mutexMeasurementCycleQueue, portMAX_DELAY);
|
||||
|
||||
|
||||
// Make sure measurement cycle available
|
||||
int queueSize = measurementCycleQueue.size();
|
||||
if (queueSize == 0) {
|
||||
@@ -1405,7 +1407,7 @@ void postUsingCellular(bool forcePost) {
|
||||
}
|
||||
|
||||
// Check queue size if its ready to transmit
|
||||
// It is ready if size is divisible by 3
|
||||
// It is ready if size is divisible by 3
|
||||
if (!forcePost && (queueSize % MEASUREMENT_TRANSMIT_CYCLE) > 0) {
|
||||
Serial.printf("Not ready to transmit, queue size are %d\n", queueSize);
|
||||
xSemaphoreGive(mutexMeasurementCycleQueue);
|
||||
@@ -1414,19 +1416,20 @@ void postUsingCellular(bool forcePost) {
|
||||
|
||||
// Build payload include all measurements from queue
|
||||
std::string payload;
|
||||
bool extendPmMeasures = configuration.isExtendedPmMeasuresEnabled();
|
||||
payload += std::to_string(CELLULAR_MEASUREMENT_INTERVAL / 1000); // Convert to seconds
|
||||
for (int i = 0; i < queueSize; i++) {
|
||||
auto mc = measurementCycleQueue.at(i);
|
||||
payload += ",";
|
||||
payload += measurements.buildMeasuresPayload(mc);
|
||||
payload += measurements.buildMeasuresPayload(mc, extendPmMeasures);
|
||||
}
|
||||
|
||||
// Release before actually post measures that might takes too long
|
||||
xSemaphoreGive(mutexMeasurementCycleQueue);
|
||||
|
||||
// Attempt to send
|
||||
if (agClient->httpPostMeasures(payload) == false) {
|
||||
// Consider network has a problem, retry in next schedule
|
||||
if (agClient->httpPostMeasures(payload, extendPmMeasures) == false) {
|
||||
// Consider network has a problem, retry in next schedule
|
||||
Serial.println("Post measures failed, retry in next schedule");
|
||||
return;
|
||||
}
|
||||
@@ -1527,7 +1530,7 @@ void setMeasurementMaxPeriod() {
|
||||
|
||||
int calculateMaxPeriod(int updateInterval) {
|
||||
// 0.8 is 80% reduced interval for max period
|
||||
// NOTE: Both network option use the same measurement interval
|
||||
// NOTE: Both network option use the same measurement interval
|
||||
return (WIFI_MEASUREMENT_INTERVAL - (WIFI_MEASUREMENT_INTERVAL * 0.8)) / updateInterval;
|
||||
}
|
||||
|
||||
@@ -1544,7 +1547,7 @@ void networkSignalCheck() {
|
||||
}
|
||||
|
||||
// Save last signal quality
|
||||
lastCellSignalQuality = result.data;
|
||||
lastCellSignalQuality = result.data;
|
||||
|
||||
if (result.data == 99) {
|
||||
// 99 indicate cellular not attached to network
|
||||
@@ -1557,7 +1560,7 @@ void networkSignalCheck() {
|
||||
}
|
||||
|
||||
/**
|
||||
* If in 2 hours cellular client still not ready, then restart system
|
||||
* If in 2 hours cellular client still not ready, then restart system
|
||||
*/
|
||||
void restartIfCeClientIssueOverTwoHours() {
|
||||
if (agCeClientProblemDetectedTime > 0 &&
|
||||
@@ -1622,10 +1625,10 @@ void networkingTask(void *args) {
|
||||
}
|
||||
|
||||
// Enable at command debug
|
||||
agSerial->setDebug(true);
|
||||
agSerial->setDebug(true);
|
||||
|
||||
// Check if cellular client not ready until certain time
|
||||
// Redundant check in both task to make sure its executed
|
||||
// Redundant check in both task to make sure its executed
|
||||
restartIfCeClientIssueOverTwoHours();
|
||||
|
||||
// Power cycling cellular module due to network issues for more than 1 hour
|
||||
@@ -1676,14 +1679,14 @@ void networkingTask(void *args) {
|
||||
|
||||
void newMeasurementCycle() {
|
||||
if (xSemaphoreTake(mutexMeasurementCycleQueue, portMAX_DELAY) == pdTRUE) {
|
||||
// Make sure queue not overflow
|
||||
// Make sure queue not overflow
|
||||
if (measurementCycleQueue.size() >= MAXIMUM_MEASUREMENT_CYCLE_QUEUE) {
|
||||
// Remove the oldest data from queue if queue reach max
|
||||
measurementCycleQueue.erase(measurementCycleQueue.begin());
|
||||
}
|
||||
|
||||
// Get current measures
|
||||
auto mc = measurements.getMeasures();
|
||||
auto mc = measurements.getMeasures();
|
||||
mc.signal = cellularCard->csqToDbm(lastCellSignalQuality); // convert to RSSI
|
||||
|
||||
measurementCycleQueue.push_back(mc);
|
||||
|
||||
@@ -6,8 +6,8 @@ OpenMetrics::OpenMetrics(Measurements &measure, Configuration &config,
|
||||
|
||||
OpenMetrics::~OpenMetrics() {}
|
||||
|
||||
void OpenMetrics::setAirGradient(AirGradient *ag) {
|
||||
this->ag = ag;
|
||||
void OpenMetrics::setAirGradient(AirGradient *ag) {
|
||||
this->ag = ag;
|
||||
}
|
||||
|
||||
void OpenMetrics::setAirgradientClient(AirgradientClient *client) {
|
||||
|
||||
@@ -15,7 +15,7 @@ framework = arduino
|
||||
build_flags = !echo '-D ARDUINO_USB_CDC_ON_BOOT=1 -D ARDUINO_USB_MODE=1 -D AG_LOG_LEVEL=AG_LOG_LEVEL_INFO -D GIT_VERSION=\\"'$(git describe --tags --always --dirty)'\\"'
|
||||
board_build.partitions = partitions.csv
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
lib_deps =
|
||||
aglib=symlink://../arduino
|
||||
EEPROM
|
||||
WebServer
|
||||
@@ -32,7 +32,7 @@ platform = espressif8266
|
||||
board = d1_mini
|
||||
framework = arduino
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
lib_deps =
|
||||
aglib=symlink://../arduino
|
||||
EEPROM
|
||||
ESP8266HTTPClient
|
||||
|
||||
@@ -47,7 +47,7 @@ bool AgApiClient::fetchServerConfiguration(void) {
|
||||
}
|
||||
#else
|
||||
HTTPClient client;
|
||||
client.setConnectTimeout(timeoutMs); // Set timeout when establishing connection to server
|
||||
client.setConnectTimeout(timeoutMs); // Set timeout when establishing connection to server
|
||||
client.setTimeout(timeoutMs); // Timeout when waiting for response from AG server
|
||||
if (apiRootChanged) {
|
||||
// If apiRoot is changed, assume not using https
|
||||
@@ -114,7 +114,7 @@ bool AgApiClient::postToServer(String data) {
|
||||
}
|
||||
#else
|
||||
HTTPClient client;
|
||||
client.setConnectTimeout(timeoutMs); // Set timeout when establishing connection to server
|
||||
client.setConnectTimeout(timeoutMs); // Set timeout when establishing connection to server
|
||||
client.setTimeout(timeoutMs); // Timeout when waiting for response from AG server
|
||||
if (apiRootChanged) {
|
||||
// If apiRoot is changed, assume not using https
|
||||
@@ -185,13 +185,13 @@ void AgApiClient::setAirGradient(AirGradient *ag) { this->ag = ag; }
|
||||
|
||||
/**
|
||||
* @brief Send the package to check the connection with cloud
|
||||
*
|
||||
*
|
||||
* @param rssi WiFi RSSI
|
||||
* @param bootCount Boot count
|
||||
* @return true Success
|
||||
* @return false Failure
|
||||
*/
|
||||
bool AgApiClient::sendPing(int rssi, int bootCount) {
|
||||
bool AgApiClient::sendPing(int rssi, int bootCount) {
|
||||
JSONVar root;
|
||||
root["wifi"] = rssi;
|
||||
root["boot"] = bootCount;
|
||||
|
||||
@@ -60,6 +60,7 @@ JSON_PROP_DEF(monitorDisplayCompensatedValues);
|
||||
JSON_PROP_DEF(corrections);
|
||||
JSON_PROP_DEF(atmp);
|
||||
JSON_PROP_DEF(rhum);
|
||||
JSON_PROP_DEF(extendedPmMeasures);
|
||||
|
||||
#define jprop_model_default ""
|
||||
#define jprop_country_default "TH"
|
||||
@@ -78,6 +79,7 @@ JSON_PROP_DEF(rhum);
|
||||
#define jprop_displayBrightness_default 100
|
||||
#define jprop_offlineMode_default false
|
||||
#define jprop_monitorDisplayCompensatedValues_default false
|
||||
#define jprop_extendedPmMeasures_default false
|
||||
|
||||
JSONVar jconfig;
|
||||
|
||||
@@ -114,7 +116,7 @@ PMCorrectionAlgorithm Configuration::matchPmAlgorithm(String algorithm) {
|
||||
|
||||
const size_t enumSize = COR_ALGO_PM_SLR_CUSTOM + 1; // Get the actual size of the enum
|
||||
PMCorrectionAlgorithm result = COR_ALGO_PM_UNKNOWN;;
|
||||
|
||||
|
||||
// Loop through enum values
|
||||
for (size_t enumVal = 0; enumVal < enumSize; enumVal++) {
|
||||
if (algorithm == PM_CORRECTION_ALGORITHM_NAMES[enumVal]) {
|
||||
@@ -122,7 +124,7 @@ PMCorrectionAlgorithm Configuration::matchPmAlgorithm(String algorithm) {
|
||||
}
|
||||
}
|
||||
|
||||
// If string not match from enum, check if correctionAlgorithm is one of the PM batch corrections
|
||||
// If string not match from enum, check if correctionAlgorithm is one of the PM batch corrections
|
||||
if (result == COR_ALGO_PM_UNKNOWN) {
|
||||
// Check the substring "slr_PMS5003_xxxxxxxx"
|
||||
if (algorithm.substring(0, 11) == "slr_PMS5003") {
|
||||
@@ -400,6 +402,7 @@ void Configuration::defaultConfig(void) {
|
||||
jconfig[jprop_model] = jprop_model_default;
|
||||
jconfig[jprop_offlineMode] = jprop_offlineMode_default;
|
||||
jconfig[jprop_monitorDisplayCompensatedValues] = jprop_monitorDisplayCompensatedValues_default;
|
||||
jconfig[jprop_extendedPmMeasures] = jprop_extendedPmMeasures_default;
|
||||
|
||||
// PM2.5 default correction
|
||||
pmCorrection.algorithm = COR_ALGO_PM_NONE;
|
||||
@@ -749,7 +752,7 @@ bool Configuration::parse(String data, bool isLocal) {
|
||||
}
|
||||
else if (JSON.typeof_(root[jprop_mqttBrokerUrl]) == "null" and !isLocal) {
|
||||
// So if its not available on the json and json comes from aigradient server
|
||||
// then set its value to default (empty)
|
||||
// then set its value to default (empty)
|
||||
jconfig[jprop_mqttBrokerUrl] = jprop_mqttBrokerUrl_default;
|
||||
}
|
||||
else {
|
||||
@@ -940,6 +943,26 @@ bool Configuration::parse(String data, bool isLocal) {
|
||||
}
|
||||
}
|
||||
|
||||
if (JSON.typeof_(root[jprop_extendedPmMeasures]) == "boolean") {
|
||||
bool value = root[jprop_extendedPmMeasures];
|
||||
bool oldValue = jconfig[jprop_extendedPmMeasures];
|
||||
if (value != oldValue) {
|
||||
changed = true;
|
||||
configLogInfo(String(jprop_extendedPmMeasures),
|
||||
String(oldValue ? "true" : "false"),
|
||||
String(value ? "true" : "false"));
|
||||
jconfig[jprop_extendedPmMeasures] = value;
|
||||
}
|
||||
} else {
|
||||
if (jsonTypeInvalid(root[jprop_extendedPmMeasures], "boolean")) {
|
||||
failedMessage = jsonTypeInvalidMessage(
|
||||
String(jprop_extendedPmMeasures), "boolean");
|
||||
jsonInvalid();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// PM2.5 Corrections
|
||||
if (updatePmCorrection(root)) {
|
||||
changed = true;
|
||||
@@ -1002,6 +1025,11 @@ bool Configuration::isTemperatureUnitInF(void) {
|
||||
return (unit == "f");
|
||||
}
|
||||
|
||||
|
||||
bool Configuration::isExtendedPmMeasuresEnabled(void) {
|
||||
return jconfig[jprop_extendedPmMeasures];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Country name, it's short name ex: TH = Thailand
|
||||
*
|
||||
@@ -1073,7 +1101,7 @@ String Configuration::getMqttBrokerUri(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get HTTP domain for post measures and get configuration
|
||||
* @brief Get HTTP domain for post measures and get configuration
|
||||
*
|
||||
* @return String http domain, might be empty string
|
||||
*/
|
||||
@@ -1368,6 +1396,18 @@ void Configuration::toConfig(const char *buf) {
|
||||
logInfo("toConfig: disableCloudConnection changed");
|
||||
}
|
||||
|
||||
/** validate extendedPmMeasures configuration */
|
||||
if (JSON.typeof_(jconfig[jprop_extendedPmMeasures]) != "boolean") {
|
||||
isConfigFieldInvalid = true;
|
||||
} else {
|
||||
isConfigFieldInvalid = false;
|
||||
}
|
||||
if (isConfigFieldInvalid) {
|
||||
jconfig[jprop_extendedPmMeasures] = jprop_extendedPmMeasures_default;
|
||||
changed = true;
|
||||
logInfo("toConfig: extendedPmMeasures changed");
|
||||
}
|
||||
|
||||
/** validate configuration control */
|
||||
if (JSON.typeof_(jprop_configurationControl) != "string") {
|
||||
isConfigFieldInvalid = true;
|
||||
@@ -1562,13 +1602,13 @@ void Configuration::setDisableCloudConnection(bool disable) {
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
bool Configuration::isLedBarModeChanged(void) {
|
||||
bool Configuration::isLedBarModeChanged(void) {
|
||||
bool changed = _ledBarModeChanged;
|
||||
_ledBarModeChanged = false;
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool Configuration::isMonitorDisplayCompensatedValues(void) {
|
||||
bool Configuration::isMonitorDisplayCompensatedValues(void) {
|
||||
return jconfig[jprop_monitorDisplayCompensatedValues];
|
||||
}
|
||||
|
||||
@@ -1591,8 +1631,8 @@ bool Configuration::isPMCorrectionChanged(void) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if PM correction is enabled
|
||||
*
|
||||
* @brief Check if PM correction is enabled
|
||||
*
|
||||
* @return true if PM correction algorithm is not None, otherwise false
|
||||
*/
|
||||
bool Configuration::isPMCorrectionEnabled(void) {
|
||||
|
||||
@@ -79,6 +79,7 @@ public:
|
||||
String toString(void);
|
||||
String toString(AgFirmwareMode fwMode);
|
||||
bool isTemperatureUnitInF(void);
|
||||
bool isExtendedPmMeasuresEnabled(void);
|
||||
String getCountry(void);
|
||||
bool isPmStandardInUSAQI(void);
|
||||
int getCO2CalibrationAbcDays(void);
|
||||
|
||||
@@ -568,7 +568,7 @@ float Measurements::getAverage(MeasurementType type, int ch) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return measurementAverage;
|
||||
return measurementAverage;
|
||||
}
|
||||
|
||||
String Measurements::pms5003FirmwareVersion(int fwCode) {
|
||||
@@ -885,7 +885,7 @@ Measurements::Measures Measurements::getMeasures() {
|
||||
return mc;
|
||||
}
|
||||
|
||||
std::string Measurements::buildMeasuresPayload(Measures &mc) {
|
||||
std::string Measurements::buildMeasuresPayload(Measures &mc, bool extendedPmMeasures) {
|
||||
std::ostringstream oss;
|
||||
|
||||
// CO2
|
||||
@@ -895,7 +895,7 @@ std::string Measurements::buildMeasuresPayload(Measures &mc) {
|
||||
|
||||
oss << ",";
|
||||
|
||||
// Temperature
|
||||
// Temperature
|
||||
if (utils::isValidTemperature(mc.temperature[0]) && utils::isValidTemperature(mc.temperature[1])) {
|
||||
float temp = (mc.temperature[0] + mc.temperature[1]) / 2.0f;
|
||||
oss << std::round(temp * 10);
|
||||
@@ -984,6 +984,76 @@ std::string Measurements::buildMeasuresPayload(Measures &mc) {
|
||||
oss << mc.signal;
|
||||
}
|
||||
|
||||
|
||||
if (extendedPmMeasures) {
|
||||
oss << ",,,,,,,,"; // Add placeholder for MAX payload (BMS & O3/NO2)
|
||||
|
||||
/// PM 0.5 particle count
|
||||
if (utils::isValidPm03Count(mc.pm_05_pc[0]) && utils::isValidPm03Count(mc.pm_05_pc[1])) {
|
||||
oss << std::round((mc.pm_05_pc[0] + mc.pm_05_pc[1]) / 2.0f);
|
||||
} else if (utils::isValidPm03Count(mc.pm_05_pc[0])) {
|
||||
oss << std::round(mc.pm_05_pc[0]);
|
||||
} else if (utils::isValidPm03Count(mc.pm_05_pc[1])) {
|
||||
oss << std::round(mc.pm_05_pc[1]);
|
||||
}
|
||||
|
||||
oss << ",";
|
||||
|
||||
/// PM 1.0 particle count
|
||||
if (utils::isValidPm03Count(mc.pm_01_pc[0]) && utils::isValidPm03Count(mc.pm_01_pc[1])) {
|
||||
oss << std::round((mc.pm_01_pc[0] + mc.pm_01_pc[1]) / 2.0f);
|
||||
} else if (utils::isValidPm03Count(mc.pm_01_pc[0])) {
|
||||
oss << std::round(mc.pm_01_pc[0]);
|
||||
} else if (utils::isValidPm03Count(mc.pm_01_pc[1])) {
|
||||
oss << std::round(mc.pm_01_pc[1]);
|
||||
}
|
||||
|
||||
oss << ",";
|
||||
|
||||
/// PM 2.5 particle count
|
||||
if (utils::isValidPm03Count(mc.pm_25_pc[0]) && utils::isValidPm03Count(mc.pm_25_pc[1])) {
|
||||
oss << std::round((mc.pm_25_pc[0] + mc.pm_25_pc[1]) / 2.0f);
|
||||
} else if (utils::isValidPm03Count(mc.pm_25_pc[0])) {
|
||||
oss << std::round(mc.pm_25_pc[0]);
|
||||
} else if (utils::isValidPm03Count(mc.pm_25_pc[1])) {
|
||||
oss << std::round(mc.pm_25_pc[1]);
|
||||
}
|
||||
|
||||
oss << ",";
|
||||
|
||||
/// PM 5.0 particle count
|
||||
if (utils::isValidPm03Count(mc.pm_5_pc[0]) && utils::isValidPm03Count(mc.pm_5_pc[1])) {
|
||||
oss << std::round((mc.pm_5_pc[0] + mc.pm_5_pc[1]) / 2.0f);
|
||||
} else if (utils::isValidPm03Count(mc.pm_5_pc[0])) {
|
||||
oss << std::round(mc.pm_5_pc[0]);
|
||||
} else if (utils::isValidPm03Count(mc.pm_5_pc[1])) {
|
||||
oss << std::round(mc.pm_5_pc[1]);
|
||||
}
|
||||
|
||||
oss << ",";
|
||||
|
||||
/// PM 10 particle count
|
||||
if (utils::isValidPm03Count(mc.pm_10_pc[0]) && utils::isValidPm03Count(mc.pm_10_pc[1])) {
|
||||
oss << std::round((mc.pm_10_pc[0] + mc.pm_10_pc[1]) / 2.0f);
|
||||
} else if (utils::isValidPm03Count(mc.pm_10_pc[0])) {
|
||||
oss << std::round(mc.pm_10_pc[0]);
|
||||
} else if (utils::isValidPm03Count(mc.pm_10_pc[1])) {
|
||||
oss << std::round(mc.pm_10_pc[1]);
|
||||
}
|
||||
|
||||
oss << ",";
|
||||
|
||||
/// PM2.5 standard particle
|
||||
if (utils::isValidPm(mc.pm_25_sp[0]) && utils::isValidPm(mc.pm_25_sp[1])) {
|
||||
float pm10 = (mc.pm_25_sp[0] + mc.pm_25_sp[1]) / 2.0f;
|
||||
oss << std::round(pm10 * 10);
|
||||
} else if (utils::isValidPm(mc.pm_25_sp[0])) {
|
||||
oss << std::round(mc.pm_25_sp[0] * 10);
|
||||
} else if (utils::isValidPm(mc.pm_25_sp[1])) {
|
||||
oss << std::round(mc.pm_25_sp[1] * 10);
|
||||
}
|
||||
}
|
||||
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
@@ -149,7 +149,7 @@ public:
|
||||
*
|
||||
* @param type measurement type that will be retrieve
|
||||
* @param ch target type value channel
|
||||
* @return moving average value of target measurements type
|
||||
* @return moving average value of target measurements type
|
||||
*/
|
||||
float getAverage(MeasurementType type, int ch = 1);
|
||||
|
||||
@@ -184,7 +184,7 @@ public:
|
||||
|
||||
Measures getMeasures();
|
||||
|
||||
std::string buildMeasuresPayload(Measures &measures);
|
||||
std::string buildMeasuresPayload(Measures &mc, bool extendedPmMeasures);
|
||||
|
||||
/**
|
||||
* Set to true if want to debug every update value
|
||||
|
||||
@@ -358,7 +358,7 @@ bool WifiConnector::isConnected(void) { return WiFi.isConnected(); }
|
||||
* this method
|
||||
*
|
||||
*/
|
||||
void WifiConnector::reset(void) {
|
||||
void WifiConnector::reset(void) {
|
||||
if(this->wifi == NULL) {
|
||||
this->wifi = new WiFiManager();
|
||||
if(this->wifi == NULL){
|
||||
@@ -366,7 +366,7 @@ void WifiConnector::reset(void) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
WIFI()->resetSettings();
|
||||
WIFI()->resetSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -406,7 +406,7 @@ bool WifiConnector::isConfigurePorttalTimeout(void) { return connectorTimeout; }
|
||||
|
||||
/**
|
||||
* @brief Set wifi connect to default WiFi
|
||||
*
|
||||
*
|
||||
*/
|
||||
void WifiConnector::setDefault(void) {
|
||||
WiFi.begin("airgradient", "cleanair");
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "AirGradient.h"
|
||||
#ifdef ESP8266
|
||||
#include <ESP8266WiFi.h>
|
||||
#else
|
||||
#else
|
||||
#include "WiFi.h"
|
||||
#endif
|
||||
|
||||
@@ -57,7 +57,7 @@ String AirGradient::getBoardName(void) {
|
||||
|
||||
/**
|
||||
* @brief Board Type is ONE_INDOOR
|
||||
*
|
||||
*
|
||||
* @return true ONE_INDOOR
|
||||
* @return false Other
|
||||
*/
|
||||
@@ -65,15 +65,15 @@ bool AirGradient::isOne(void) {
|
||||
return boardType == BoardType::ONE_INDOOR;
|
||||
}
|
||||
|
||||
bool AirGradient::isOpenAir(void) {
|
||||
return boardType == BoardType::OPEN_AIR_OUTDOOR;
|
||||
bool AirGradient::isOpenAir(void) {
|
||||
return boardType == BoardType::OPEN_AIR_OUTDOOR;
|
||||
}
|
||||
|
||||
bool AirGradient::isPro4_2(void) {
|
||||
return boardType == BoardType::DIY_PRO_INDOOR_V4_2;
|
||||
}
|
||||
|
||||
bool AirGradient::isPro3_3(void) {
|
||||
bool AirGradient::isPro3_3(void) {
|
||||
return boardType == BoardType::DIY_PRO_INDOOR_V3_3;
|
||||
}
|
||||
|
||||
|
||||
@@ -177,9 +177,9 @@ public:
|
||||
|
||||
/**
|
||||
* @brief Check that Airgradient object is OPEN_AIR
|
||||
*
|
||||
* @return true
|
||||
* @return false
|
||||
*
|
||||
* @return true
|
||||
* @return false
|
||||
*/
|
||||
bool isOpenAir(void);
|
||||
|
||||
|
||||
Submodule src/Libraries/airgradient-client updated: c23bb2ceac...0a2ff8abbb
@@ -27,7 +27,7 @@ enum BoardType {
|
||||
|
||||
/**
|
||||
* @brief Board definitions
|
||||
*
|
||||
*
|
||||
*/
|
||||
struct BoardDef {
|
||||
/** Board Support CO2 SenseS8 */
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
/**
|
||||
* @brief The class define how to handle the LED
|
||||
*
|
||||
*
|
||||
*/
|
||||
class StatusLed {
|
||||
public:
|
||||
|
||||
@@ -316,10 +316,10 @@ int PMSBase::pm25ToAQI(int pm02) {
|
||||
|
||||
|
||||
/**
|
||||
* @brief SLR correction for PM2.5
|
||||
*
|
||||
* @brief SLR correction for PM2.5
|
||||
*
|
||||
* Reference: https://www.airgradient.com/blog/low-readings-from-pms5003/
|
||||
*
|
||||
*
|
||||
* @param pm25 PM2.5 raw value
|
||||
* @param pm003Count PM0.3 count
|
||||
* @param scalingFactor Scaling factor
|
||||
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
/** For PMS5003T*/
|
||||
int16_t getTemp(void);
|
||||
uint16_t getHum(void);
|
||||
uint8_t getFirmwareVersion(void);
|
||||
uint8_t getFirmwareVersion(void);
|
||||
uint8_t getErrorCode(void);
|
||||
|
||||
int pm25ToAQI(int pm02);
|
||||
|
||||
@@ -189,21 +189,21 @@ float PMS5003::compensate(float pm25, float humidity) { return pms.compensate(pm
|
||||
|
||||
/**
|
||||
* @brief Get sensor firmware version
|
||||
*
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int PMS5003::getFirmwareVersion(void) { return _ver; }
|
||||
|
||||
/**
|
||||
* @brief Get sensor error code
|
||||
*
|
||||
* @return uint8_t
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t PMS5003::getErrorCode(void) { return pms.getErrorCode(); }
|
||||
|
||||
/**
|
||||
* @brief Is sensor connect with device
|
||||
*
|
||||
*
|
||||
* @return true Connected
|
||||
* @return false Removed
|
||||
*/
|
||||
@@ -255,14 +255,14 @@ void PMS5003::resetFailCount(void) {
|
||||
|
||||
/**
|
||||
* @brief Get number of fail count
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int PMS5003::getFailCount(void) { return pms.getFailCount(); }
|
||||
|
||||
/**
|
||||
* @brief Get number of fail count max
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int PMS5003::getFailCountMax(void) { return pms.getFailCountMax(); }
|
||||
|
||||
@@ -218,21 +218,21 @@ float PMS5003T::compensate(float pm25, float humidity) { return pms.compensate(p
|
||||
|
||||
/**
|
||||
* @brief Get module(s) firmware version
|
||||
*
|
||||
*
|
||||
* @return int Version code
|
||||
*/
|
||||
int PMS5003T::getFirmwareVersion(void) { return _ver; }
|
||||
|
||||
/**
|
||||
* @brief Get sensor error code
|
||||
*
|
||||
* @return uint8_t
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t PMS5003T::getErrorCode(void) { return pms.getErrorCode(); }
|
||||
|
||||
/**
|
||||
* @brief Is sensor connect to device
|
||||
*
|
||||
*
|
||||
* @return true Connected
|
||||
* @return false Removed
|
||||
*/
|
||||
@@ -281,14 +281,14 @@ void PMS5003T::resetFailCount(void) {
|
||||
|
||||
/**
|
||||
* @brief Get fail count
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int PMS5003T::getFailCount(void) { return pms.getFailCount(); }
|
||||
|
||||
/**
|
||||
* @brief Get fail count max
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int PMS5003T::getFailCountMax(void) { return pms.getFailCountMax(); }
|
||||
|
||||
@@ -6,11 +6,11 @@ PMS5003TBase::~PMS5003TBase() {}
|
||||
|
||||
/**
|
||||
* @brief Compensate the temperature
|
||||
*
|
||||
*
|
||||
* Reference formula: https://www.airgradient.com/documentation/correction-algorithms/
|
||||
*
|
||||
* @param temp
|
||||
* @return * float
|
||||
*
|
||||
* @param temp
|
||||
* @return * float
|
||||
*/
|
||||
float PMS5003TBase::compensateTemp(float temp) {
|
||||
if (temp < 10.0f) {
|
||||
@@ -21,11 +21,11 @@ float PMS5003TBase::compensateTemp(float temp) {
|
||||
|
||||
/**
|
||||
* @brief Compensate the humidity
|
||||
*
|
||||
*
|
||||
* Reference formula: https://www.airgradient.com/documentation/correction-algorithms/
|
||||
*
|
||||
* @param temp
|
||||
* @return * float
|
||||
*
|
||||
* @param temp
|
||||
* @return * float
|
||||
*/
|
||||
float PMS5003TBase::compensateHum(float hum) {
|
||||
hum = hum * 1.259f + 7.34f;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
class PMS5003TBase
|
||||
{
|
||||
private:
|
||||
|
||||
|
||||
public:
|
||||
PMS5003TBase();
|
||||
~PMS5003TBase();
|
||||
|
||||
@@ -835,3 +835,13 @@ bool S8::setAbcPeriod(int hours) {
|
||||
* @return int Hour
|
||||
*/
|
||||
int S8::getAbcPeriod(void) { return getCalibPeriodABC(); }
|
||||
|
||||
|
||||
void S8::printInformation(void) {
|
||||
Serial.print("S8 type ID: 0x");
|
||||
Serial.println(getSensorTypeId(), HEX);
|
||||
Serial.print("S8 serial number: 0x");
|
||||
Serial.println(getSensorId(), HEX);
|
||||
Serial.print("S8 memory map version: 0x");
|
||||
Serial.println(getMemoryMapVersion(), HEX);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ public:
|
||||
bool isBaseLineCalibrationDone(void);
|
||||
bool setAbcPeriod(int hours);
|
||||
int getAbcPeriod(void);
|
||||
void printInformation(void);
|
||||
|
||||
private:
|
||||
/** Variables */
|
||||
|
||||
@@ -140,7 +140,7 @@ void Sgp41::pause() {
|
||||
tvoc = utils::getInvalidVOC();
|
||||
noxRaw = utils::getInvalidNOx();
|
||||
nox = utils::getInvalidNOx();
|
||||
}
|
||||
}
|
||||
|
||||
void Sgp41::resume() {
|
||||
onPause = false;
|
||||
|
||||
Reference in New Issue
Block a user