diff --git a/BresserWeatherSensorLW.ino b/BresserWeatherSensorLW.ino index 4b1b21c..b75cb52 100644 --- a/BresserWeatherSensorLW.ino +++ b/BresserWeatherSensorLW.ino @@ -88,6 +88,7 @@ // 20242529 Fixed payload size calculation // 20240530 Updated to RadioLib v6.6.0 // 20240603 Added AppLayer status uplink +// 20240606 Changed appStatusUplinkInterval from const to variable // // ToDo: // - Fix restoring nonces/session buffers after examples in @@ -272,7 +273,13 @@ void print_wakeup_reason() */ void loadSecrets(uint64_t &joinEUI, uint64_t &devEUI, uint8_t *nwkKey, uint8_t *appKey) { - if (!LittleFS.begin()) + + if (!LittleFS.begin( + #if defined(ESP32) + // Format the LittleFS partition on error; parameter only available for ESP32 + true + #endif + )) { log_d("Could not initialize LittleFS."); } @@ -893,6 +900,8 @@ void setup() } // Set appStatusUplink flag if required + uint8_t appStatusUplinkInterval = appLayer.getAppStatusUplinkInterval(); + log_i("App status uplink interval: %u", appStatusUplinkInterval); if (appStatusUplinkInterval && (fCntUp % appStatusUplinkInterval == 0)) { appStatusUplinkPending = true; @@ -1031,7 +1040,7 @@ void setup() uint8_t *persist = node.getBufferSession(); memcpy(LWsession, persist, RADIOLIB_LORAWAN_SESSION_BUF_SIZE); - // wait until next uplink - observing legal & TTN FUP constraints + // wait until next uplink - observing legal & TTN Fair Use Policy constraints gotoSleep(sleepDuration()); } diff --git a/BresserWeatherSensorLWCfg.h b/BresserWeatherSensorLWCfg.h index 65b7660..227d80a 100644 --- a/BresserWeatherSensorLWCfg.h +++ b/BresserWeatherSensorLWCfg.h @@ -53,6 +53,9 @@ // 20240528 Added encoding of invalid values, modified default payload, fixes // 20240603 Added definitions for sensor status flags // Added appStatusUplinkInterval +// 20240607 Added ARDUINO_DFROBOT_FIREBEETLE_ESP32 variant selection +// Updated HELTEC_WIFI_LORA_32_V3 definition +// Modified STATUS_INTERVAL // // Note: // Depending on board package file date, either @@ -78,17 +81,12 @@ // #define NVS_LOG //--- Select Board --- -#if !defined(ARDUINO_TTGO_LoRa32_V1) && !defined(ARDUINO_TTGO_LoRa32_V2) && \ - !defined(ARDUINO_TTGO_LoRa32_v21new) && !defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2) && \ - !defined(ARDUINO_FEATHER_ESP32) && !defined(ARDUINO_ADAFRUIT_FEATHER_RP2040) && \ - !defined(ARDUINO_heltec_wifi_32_lora_V3) && !defined(ARDUINO_heltec_wifi_lora_32_V3) && \ - !defined(ARDUINO_M5STACK_Core2) && !defined(ARDUINO_M5STACK_CORE2) && \ - !defined(ARDUINO_ESP32S3_POWERFEATHER) +#if defined(ARDUINO_DFROBOT_FIREBEETLE_ESP32) // Use pinning for LoRaWAN Node -#define LORAWAN_NODE +//#define LORAWAN_NODE // Use pinning for Firebeetle Cover LoRa -//#define FIREBEETLE_ESP32_COVER_LORA +#define FIREBEETLE_ESP32_COVER_LORA #endif #if defined(ARDUINO_FEATHER_ESP32) @@ -125,8 +123,8 @@ const uint8_t PAYLOAD_SIZE = 51; // RTC to network time sync interval (in minutes) #define CLOCK_SYNC_INTERVAL 24 * 60 -// TODO: Modify to set this value via downlink -const uint8_t appStatusUplinkInterval = 120; +// Status message uplink interval (in frames) +#define STATUS_INTERVAL 120 // Timeout for weather sensor data reception (seconds) #define WEATHERSENSOR_TIMEOUT 180 @@ -197,7 +195,7 @@ const uint8_t appStatusUplinkInterval = 120; #pragma message("No power-saving & deep-discharge protection implemented yet.") // On-board VB #define PIN_ADC_IN A0 -#elif defined(ARDUINO_heltec_wifi_32_lora_V3) || defined(ARDUINO_heltec_wifi_lora_32_V3) +#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V3) || defined(ARDUINO_heltec_wifi_lora_32_V3) // On-board VB #define PIN_ADC_IN A0 #elif defined(ARDUINO_ESP32S3_POWERFEATHER) @@ -286,7 +284,7 @@ const uint8_t ADC3_SAMPLES = 10; // Voltage divider R1 / (R1 + R2) -> V_meas = V(R1 + R2); V_adc = V(R1) #if defined(ARDUINO_THINGPULSE_EPULSE_FEATHER) const float UBATT_DIV = 0.6812; -#elif defined(ARDUINO_heltec_wifi_32_lora_V3) || defined(ARDUINO_heltec_wifi_lora_32_V3) +#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V3) || defined(ARDUINO_heltec_wifi_lora_32_V3) #define ADC_CTRL 37 // R17=100k, R14=390k => 100k / (100k + 390 k) const float UBATT_DIV = 0.2041; diff --git a/BresserWeatherSensorLWCmd.h b/BresserWeatherSensorLWCmd.h index 752b5d7..668d8f9 100644 --- a/BresserWeatherSensorLWCmd.h +++ b/BresserWeatherSensorLWCmd.h @@ -38,6 +38,7 @@ // 20240507 Added CMD_GET_SENSORS_CFG/CMD_SET_SENSORS_CFG // 20240508 Updated description of CMD_GET_SENSORS_CFG/CMD_SET_SENSORS_CFG // 20240603 Added CMD_GET_SENSORS_STAT +// 20240606 Added CMD_GET_STATUS_INTERVAL/CMD_SET_STATUS_INTERVAL // // ToDo: // - @@ -166,6 +167,29 @@ // Port: CMD_GET_SENSORS_STAT #define CMD_GET_SENSORS_STAT 0xD0 +// CMD_GET_STATUS_INTERVAL +// ------------------------ +// Note: Get status interval in frame counts +// Port: CMD_GET_STATUS_INTERVAL +#define CMD_GET_STATUS_INTERVAL 0xD2 + +// Downlink (command): +// byte0: 0x00 + +// Uplink (response): +// byte0: status_interval[7:0] + +// CMD_SET_STATUS_INTERVAL +// ------------------------ +// Note: Set status interval in frame counts +// Port: CMD_SET_STATUS_INTERVAL +#define CMD_SET_STATUS_INTERVAL 0xD3 + +// Downlink (command): +// byte0: status_interval[7:0] + +// Uplink: n.a. + // CMD_GET_SENSORS_INC // -------------------- // Note: Get sensors include list (0...12 IDs) diff --git a/README.md b/README.md index fb355bc..f47e461 100644 --- a/README.md +++ b/README.md @@ -410,6 +410,7 @@ Many software parameters can be defined at compile time, i.e. in [BresserWeather | \ | Bitmap for enabling analog input channels; each bit position corresponds to a channel | | \ | Bitmap for enabling digital input channels in a broader sense — GPIO, SPI, I2C, UART, ... | | | Bitmap for Bresser sensor type \ battery status; each bit position corresponds to a channel | +| | Sensor status message uplink interval in no. of uplink frames; 0...255; 0: disabled | | | Bitmap for 1-Wire sensor status; each bit position corresponds to an index | | | Bitmap for analog input status; each bit position corresponds to a channel | | | Bitmap for digital input channel status | @@ -445,6 +446,8 @@ Many software parameters can be defined at compile time, i.e. in [BresserWeather | CMD_GET_WS_TIMEOUT | 0xC0 (192) | 0x00 | ws_timeout[7:0] | | CMD_SET_WS_TIMEOUT | 0xC1 (193) | ws_timeout[7:0] | n.a. | | CMD_RESET_RAINGAUGE | 0xC3 (195) | flags[7:0] | n.a. | +| CMD_GET_STATUS_INTERVAL | 0xD2 (210) | 0x00 | status_interval[7:0] | +| CMD_SET_STATUS_INTERVAL | 0xD3 (211) | status_interval[7:0] | n.a. | | CMD_GET_SENSORS_STAT | 0xD0 (208) | 0x00 | type00_st[7:0]
type01_st[7:0]
...
type15_st[7:0]
onewire_st[15:8]
onewire_st[7:0]
analog_st[15:8]
analog_st[7:0]
digital_st[31:24]
digital_st[23:16]
digital_st[15:8]
digital_st[7:0]
ble_st[15:8]
ble_st[7:0] | | CMD_GET_SENSORS_INC | 0xC4 (196) | 0x00 | sensors_inc0[31:24]
sensors_inc0[23:15]
sensors_inc0[16:8]
sensors_inc0[7:0]
... | | CMD_SET_SENSORS_INC | 0xC5 (197) | sensors_inc0[31:24]
sensors_inc0[23:15]
sensors_inc0[16:8]
sensors_inc0[7:0]
... | n.a. | @@ -489,6 +492,8 @@ Many software parameters can be defined at compile time, i.e. in [BresserWeather | CMD_GET_WS_TIMEOUT | {"cmd": "CMD_GET_WS_TIMEOUT"} | {"ws_timeout": } | | CMD_SET_WS_TIMEOUT | {"ws_timeout": } | n.a. | | CMD_RESET_RAINGAUGE | {"reset_flags": } | n.a. | +| CMD_GET_STATUS_INTERVAL | {"cmd": "CMD_GET_STATUS_INTERVAL"} | {"status_interval": } | +| CMD_SET_STATUS_INTERVAL | {"status_interval": } | n.a. | | CMD_GET_SENSORS_STAT | {"cmd": "CMD_GET_SENSORS_STAT"} | "sensor_status": {"ble": , "bresser": [, ..., ]} | | CMD_GET_SENSORS_INC | {"cmd": "CMD_GET_SENSORS_INC"} | {"sensors_inc": [, ..., ]} | | CMD_SET_SENSORS_INC | {"sensors_inc": [, ..., ]} | n.a. | diff --git a/extras/customization/AppLayerMinimal.h b/extras/customization/AppLayerMinimal.h index 716b096..343d353 100644 --- a/extras/customization/AppLayerMinimal.h +++ b/extras/customization/AppLayerMinimal.h @@ -32,6 +32,7 @@ // History: // // 20240513 Created +// 20240607 Added getAppStatusUplinkInterval() for compatibility // // ToDo: // - @@ -84,6 +85,16 @@ class AppLayer { }; + /*! + * \brief Get sensor status message uplink interval + * + * \returns status uplink interval in frame counts (o: disabled) + */ + uint8_t getAppStatusUplinkInterval(void) + { + return 0; + }; + /*! * \brief Decode app layer specific downlink messages * diff --git a/scripts/downlink_formatter.js b/scripts/downlink_formatter.js index 132bbc8..4e5e04a 100644 --- a/scripts/downlink_formatter.js +++ b/scripts/downlink_formatter.js @@ -21,6 +21,8 @@ // port = CMD_GET_LW_CONFIG, {"cmd": "CMD_GET_LW_CONFIG"} / payload = 0x00 // port = CMD_GET_WS_TIMEOUT, {"cmd": "CMD_GET_WS_TIMEOUT" / payload = 0x00 // port = CMD_SET_WS_TIMEOUT, {"ws_timeout": } +// port = CMD_GET_STATUS_INTERVAL, {"cmd": "CMD_GET_STATUS_INTERVAL"} / payload = 0x00 +// port = CMD_SET_STATUS_INTERVAL, {"status_interval": } // port = CMD_GET_SENSORS_STAT, {"cmd": "CMD_GET_SENSORS_STAT"} / payload = 0x00 // port = CMD_GET_SENSORS_INC, {"cmd": "CMD_GET_SENSORS_INC"} / payload = 0x00 // port = CMD_SET_SENSORS_INC, {"sensors_inc": [, ..., ]} @@ -43,6 +45,8 @@ // // CMD_GET_WS_TIMEOUT {"ws_timeout": } // +// CMD_GET_STATUS_INTERVAL {"status_interval": } +// // CMD_GET_SENSORS_STAT {"sensor_status": {bresser: [, ..., ], "ble_stat": }} // // CMD_GET_SENSORS_INC {"sensors_inc": [, ...]} @@ -63,6 +67,7 @@ // : unix epoch time, see https://www.epochconverter.com/ ( / "0x....") // : 0...15 (1: hourly / 2: daily / 4: weekly / 8: monthly) / "0x0"..."0xF" // : 0x00: GPS / 0x01: RTC / 0x02: LORA / 0x03: unsynched / 0x04: set (source unknown) +// : Sensor status message uplink interval in no. of frames (0...255, 0: disabled) // : e.g. "0xDEADBEEF" // : e.g. "0xDEADBEEF" // : max. number of Bresser sensors per receive cycle; 1...8 @@ -119,6 +124,7 @@ // 20240519 Added CMD_GET_APP_PAYLOAD_CFG/CMD_SET_APP_PAYLOAD_CFG // 20240530 Added decoding of CMD_GET_APP_PAYLOAD_CFG/CMD_SET_APP_PAYLOAD_CFG // 20240603 Added CMD_GET_SENSORS_STAT +// 20240607 Added CMD_GET_STATUS_INTERVAL/CMD_SET_STATUS_INTERVAL // // ToDo: // - @@ -134,6 +140,8 @@ const CMD_GET_LW_CONFIG = 0xB1; const CMD_GET_WS_TIMEOUT = 0xC0; const CMD_SET_WS_TIMEOUT = 0xC1; const CMD_RESET_RAINGAUGE = 0xC3; +const CMD_GET_STATUS_INTERVAL = 0xD2; +const CMD_SET_STATUS_INTERVAL = 0xD3; const CMD_GET_SENSORS_STAT = 0xD0; const CMD_GET_SENSORS_INC = 0xC4; const CMD_SET_SENSORS_INC = 0xC5; @@ -270,6 +278,14 @@ function encodeDownlink(input) { errors: [] }; } + else if (input.data.cmd == "CMD_GET_STATUS_INTERVAL") { + return { + bytes: [0], + fPort: CMD_GET_STATUS_INTERVAL, + warnings: [], + errors: [] + }; + } else if (input.data.cmd == "CMD_GET_SENSORS_STAT") { return { bytes: [0], @@ -401,6 +417,13 @@ function encodeDownlink(input) { warnings: [], errors: [] }; + } else if (input.data.hasOwnProperty('status_interval')) { + return { + bytes: [input.data.status_interval], + fPort: CMD_SET_STATUS_INTERVAL, + warnings: [], + errors: [] + }; } else if (input.data.hasOwnProperty('sensors_inc')) { k = 0; for (i = 0; i < input.data.sensors_inc.length; i++) { @@ -537,6 +560,7 @@ function decodeDownlink(input) { case CMD_GET_DATETIME: case CMD_GET_LW_CONFIG: case CMD_GET_WS_TIMEOUT: + case CMD_GET_STATUS_INTERVAL: case CMD_GET_SENSORS_STAT: case CMD_GET_SENSORS_INC: case CMD_GET_SENSORS_EXC: @@ -579,6 +603,12 @@ function decodeDownlink(input) { reset_flags: "0x" + uint8(input.bytes).toString(16) } }; + case CMD_SET_STATUS_INTERVAL: + return { + data: { + status_interval: uint8(input.bytes) + } + }; case CMD_SET_SENSORS_INC: return { data: { diff --git a/scripts/generate_decoder.py b/scripts/generate_decoder.py deleted file mode 100644 index a84dad9..0000000 --- a/scripts/generate_decoder.py +++ /dev/null @@ -1,143 +0,0 @@ -#!/usr/bin/env python3 - -######################################################################################### -# Generate LoRaWAN Javascript payload decoder function from Arduino C++ header file -# -# Usage: -# g++ -dM -E BresserWeatherSensorTTNCfg.h | ~/generate_decoder.py -# or -# g++ -dM -D -E BresserWeatherSensorTTNCfg.h | ~/generate_decoder.py -# -# The C++ preprocessor is used to evaluate the defines in the header file. -# Its output is then passed to this script, which creates the decoder function call -# to be copied into the Javascript decoder in the LoRaWAN Network provider's -# web interface. -# -# created: 02/2023 -# -# MIT License -# Copyright (C) 02/2023 Matthias Prinke (https://github.com/matthias-bs) -# -# History: -# -# 20230221 Created -# 20230716 Added lightning sensor data, split status bitmap in status_node and status -# -# To Do: -# - -# -######################################################################################### -import sys -import re - -# List of known features -features = [ - 'SENSORID_EN', - 'ONEWIRE_EN', - 'SLEEP_EN', - 'THEENGSDECODER_EN', - 'RAINDATA_EN', - 'SOILSENSOR_EN', - 'MITHERMOMETER_EN', - 'DISTANCESENSOR_EN', - 'LIGHTNINGSENSOR_EN', - 'ADC_EN', - 'PIN_ADC_IN', - 'PIN_ADC0_IN', - 'PIN_ADC1_IN', - 'PIN_ADC2_IN', - 'PIN_ADC3_IN', -] - -# Javascript decoder generator -# -# The position in the dictionary below must match the order of assignments to the -# encoder object in doUplink() (BresserWeatherSensorTTN.ino). -# -# The position in the dictionary then defines the order in the output! -# -# Format: -# : {'cond': , 'type': } -# -# : JSON output key name -# : feature which must be present in input or '' if unconditional -# : decoder datatype (or rather name of decoding function) -generator = { - 'id' : {'cond': 'SENSORID_EN', 'type': 'uint32'}, - 'status_node' : {'cond': '', 'type': 'bitmap'}, - 'status' : {'cond': '', 'type': 'bitmap'}, - 'air_temp_c': {'cond': '', 'type': 'temperature'}, - 'humidity': {'cond': '', 'type': 'uint8'}, - 'wind_gust_meter_sec': {'cond': '', 'type': 'uint16fp1'}, - 'wind_avg_meter_sec': {'cond': '', 'type': 'uint16fp1'}, - 'wind_direction_deg': {'cond': '', 'type': 'uint16fp1'}, - 'rain_mm': {'cond': '', 'type': 'rawfloat'}, - 'supply_v': {'cond': 'ADC_EN', 'type': 'uint16'}, - 'battery_v': {'cond': 'PIN_ADC3_IN', 'type': 'uint16'}, - 'water_temp_c': {'cond': 'ONEWIRE_EN', 'type': 'temperature'}, - 'indoor_temp_c': {'cond': 'THEENGSDECODER_EN', 'type': 'temperature'}, - 'indoor_humidity': {'cond': 'THEENGSDECODER_EN', 'type': 'uint8'}, - 'indoor_temp_c': {'cond': 'MITHERMOMETER_EN', 'type': 'temperature'}, - 'indoor_humidity': {'cond': 'MITHERMOMETER_EN', 'type': 'uint8'}, - 'soil_temp_c': {'cond': 'SOILSENSOR_EN', 'type': 'temperature'}, - 'soil_moisture': {'cond': 'SOILSENSOR_EN', 'type': 'uint8'}, - 'rain_hr': {'cond': 'RAINDATA_EN', 'type': 'rawfloat'}, - 'rain_day': {'cond': 'RAINDATA_EN', 'type': 'rawfloat'}, - 'rain_week': {'cond': 'RAINDATA_EN', 'type': 'rawfloat'}, - 'rain_mon': {'cond': 'RAINDATA_EN', 'type': 'rawfloat'}, - 'adc0_v': {'cond': 'PIN_ADC0_IN', 'type': 'uint16'}, - 'adc1_v': {'cond': 'PIN_ADC1_IN', 'type': 'uint16'}, - 'adc2_v': {'cond': 'PIN_ADC2_IN', 'type': 'uint16'}, - 'distance_mm': {'cond': 'DISTANCESENSOR_EN', 'type': 'uint16'}, - 'lightning_time': {'cond': 'LIGHTNINGSENSOR_EN', 'type': 'unixtime'}, - 'lightning_count': {'cond': 'LIGHTNINGSENSOR_EN', 'type': 'uint16'}, - 'lightning_distance_km': {'cond': 'LIGHTNINGSENSOR_EN', 'type': 'uint8'}, -} - -header = ''' - return decode( - bytes, -'''[1:-1] - -types = ' ' * 8 + '[\n' - -keys = ' ' * 8 + '[\n' - -footer = ''' - ); -'''[1:-1] - -# Process input from C-preprocessor -list=[] -for line in sys.stdin: - line = line.removeprefix('#define') - - # remove leading whitespaces - line = line.lstrip() - - # remove trailing whitespaces - line = line.strip() - - # remove whitespaces followed by non-whitespaces at end of line - # e.g. "PIN_ADC0_IN A3" -> PIN_ADC0_IN - line = re.sub(r'\s+\S+$', '', line) - - # Add all known features from input to the list - if line in features: - list.append(line) - -# Print the list for debugging -#print(list) - -# Generate the output -for k,v in generator.items(): - if v['cond'] == '' or v['cond'] in list: - types += ' ' * 12 + v['type'] + ',\n' - keys += ' ' * 12 + k + ',\n' - -# Print the result -print(header) -print(types) -print(' ' * 8 + '],') -print(keys) -print(footer) diff --git a/scripts/uplink_formatter.js b/scripts/uplink_formatter.js index 9025a65..0ab3ddc 100644 --- a/scripts/uplink_formatter.js +++ b/scripts/uplink_formatter.js @@ -21,6 +21,8 @@ // port = CMD_GET_LW_CONFIG, {"cmd": "CMD_GET_LW_CONFIG"} / payload = 0x00 // port = CMD_GET_WS_TIMEOUT, {"cmd": "CMD_GET_WS_TIMEOUT" / payload = 0x00 // port = CMD_SET_WS_TIMEOUT, {"ws_timeout": } +// port = CMD_GET_STATUS_INTERVAL, {"cmd": "CMD_GET_STATUS_INTERVAL"} / payload = 0x00 +// port = CMD_SET_STATUS_INTERVAL, {"status_interval": } // port = CMD_GET_SENSORS_STAT, {"cmd": "CMD_GET_SENSORS_STAT"} / payload = 0x00 // port = CMD_GET_SENSORS_INC, {"cmd": "CMD_GET_SENSORS_INC"} / payload = 0x00 // port = CMD_SET_SENSORS_INC, {"sensors_inc": [, ..., ]} @@ -42,6 +44,8 @@ // // CMD_GET_WS_TIMEOUT {"ws_timeout": } // +// CMD_GET_STATUS_INTERVAL {"status_interval": } +// // CMD_GET_SENSORS_STAT {"sensor_status": {bresser: [, ..., ], "ble_stat": }} // // CMD_GET_SENSORS_INC {"sensors_inc": [, ...]} @@ -62,6 +66,7 @@ // : unix epoch time, see https://www.epochconverter.com/ ( / "0x....") // : 0...15 (1: hourly / 2: daily / 4: weekly / 8: monthly) / "0x0"..."0xF" // : 0x00: GPS / 0x01: RTC / 0x02: LORA / 0x03: unsynched / 0x04: set (source unknown) +// : Sensor status message uplink interval in no. of frames (0...255, 0: disabled) // : e.g. "0xDEADBEEF" // : e.g. "0xDEADBEEF" // : max. number of Bresser sensors per receive cycle; 1...8 @@ -128,6 +133,7 @@ // 20240604 Added suppression of invalid value in unixtime decoder // 20240605 Fixed decoding of NaN values, fixed flags for compatibility mode // 20240606 Changed naming of post-processed lightning data +// 20240607 Added CMD_GET_STATUS_INTERVAL // // ToDo: // - @@ -153,6 +159,7 @@ function decoder(bytes, port) { const CMD_GET_BLE_CONFIG = 0xCA; const CMD_GET_APP_PAYLOAD_CFG = 0xCE; const CMD_GET_SENSORS_STAT = 0xD0; + const CMD_GET_STATUS_INTERVAL = 0xD2; const rtc_source_code = { 0x00: "GPS", @@ -194,7 +201,7 @@ function decoder(bytes, port) { dateObj = new Date(bytesToInt(bytes) * 1000); let time = dateObj.toISOString(); let timestamp = bytesToInt(bytes); - if (SKIP_INVALID_SIGNALS && timestamp == -1) { + if (SKIP_INVALID_SIGNALS && (timestamp == -1) || (timestamp == 0)) { return NaN; } return { time: time, timestamp: timestamp }; @@ -661,6 +668,15 @@ function decoder(bytes, port) { ], ['bresser', 'onewire', 'analog', 'digital'] ); + } else if (port === CMD_GET_STATUS_INTERVAL) { + return decode( + port, + bytes, + [uint8 + ], + ['status_interval' + ] + ); } else if (port === CMD_GET_SENSORS_STAT) { return decode( port, diff --git a/src/AppLayer.cpp b/src/AppLayer.cpp index 7277915..f56268a 100644 --- a/src/AppLayer.cpp +++ b/src/AppLayer.cpp @@ -59,6 +59,7 @@ // 20240531 Moved BLE specific code to PayloadBLE.cpp // 20240603 Added encoding of sensor battery status flags // Added CMD_GET_SENSORS_STAT +// 20240606 Added CMD_GET_STATUS_INTERVAL/CMD_SET_STATUS_INTERVAL // // ToDo: // - @@ -166,6 +167,21 @@ AppLayer::decodeDownlink(uint8_t port, uint8_t *payload, size_t size) return 0; } + if ((port == CMD_GET_STATUS_INTERVAL) && (payload[0] == 0x00) && (size == 1)) + { + log_d("Get status_interval"); + return CMD_GET_STATUS_INTERVAL; + } + + if ((port == CMD_SET_STATUS_INTERVAL) && (size == 1)) + { + log_d("Set status_interval: %u frames", payload[0]); + appPrefs.begin("BWS-LW-APP", false); + appPrefs.putUChar("stat_interval", payload[0]); + appPrefs.end(); + return 0; + } + if ((port == CMD_GET_SENSORS_STAT) && (payload[0] == 0x00) && (size == 1)) { log_d("Get sensors' status"); @@ -317,6 +333,19 @@ void AppLayer::getConfigPayload(uint8_t cmd, uint8_t &port, LoraEncoder &encoder port = CMD_GET_BLE_CONFIG; } #endif + else if (cmd == CMD_GET_STATUS_INTERVAL) + { + encoder.writeUint8(getAppStatusUplinkInterval()); + port = CMD_GET_STATUS_INTERVAL; + } + else if (cmd == CMD_GET_SENSORS_STAT) + { + for (size_t i = 0; i < APP_STATUS_SIZE; i++) + { + encoder.writeUint8(appStatus[i]); + } + port = CMD_GET_SENSORS_STAT; + } else if (cmd == CMD_GET_SENSORS_STAT) { for (size_t i = 0; i < APP_STATUS_SIZE; i++) @@ -325,7 +354,6 @@ void AppLayer::getConfigPayload(uint8_t cmd, uint8_t &port, LoraEncoder &encoder } port = CMD_GET_SENSORS_STAT; } - else if (cmd == CMD_GET_SENSORS_INC) { uint8_t payload[48]; diff --git a/src/AppLayer.h b/src/AppLayer.h index 3f000f8..3178e0a 100644 --- a/src/AppLayer.h +++ b/src/AppLayer.h @@ -45,6 +45,7 @@ // 20240530 Removed BleSensors as base class & from initializers // 20240531 Moved BLE specific code to PayloadBLE.h // 20240603 Added appStatus[] +// 20240607 Added getAppStatusUplinkInterval() // // ToDo: // - @@ -215,7 +216,7 @@ class AppLayer : public PayloadBresser, PayloadAnalog, PayloadDigital void getPayloadStage2(uint8_t port, LoraEncoder &encoder); /*! - * Get configuration data for uplink + * \brief Get configuration data for uplink * * Get the configuration data requested in a downlink command and * prepare it as payload in a uplink response. @@ -226,6 +227,19 @@ class AppLayer : public PayloadBresser, PayloadAnalog, PayloadDigital */ void getConfigPayload(uint8_t cmd, uint8_t &port, LoraEncoder &encoder); + /*! + * \brief Get sensor status message uplink interval + * + * \returns status uplink interval in frame counts (0: disabled) + */ + uint8_t getAppStatusUplinkInterval(void) + { + appPrefs.begin("BWS-LW-APP", false); + uint8_t status_interval = appPrefs.getUChar("stat_interval", STATUS_INTERVAL); + appPrefs.end(); + return status_interval; + }; + /*! * Set AppLayer payload config in Preferences * diff --git a/src/adc/adc.cpp b/src/adc/adc.cpp index dae0376..b880baf 100644 --- a/src/adc/adc.cpp +++ b/src/adc/adc.cpp @@ -39,6 +39,7 @@ // for ARDUINO_heltec_wifi_lora_32_V3 // 20240430 Modified getBatteryVoltage() // 20240504 Heltec WiFi 32 LoRa V3: Changed ADC input attenuation to get higher accuracy +// 20240607 Changed ARDUINO_HELTEC_WIFI_LORA_32_V3 to uppercase // // ToDo: // - @@ -85,7 +86,7 @@ uint16_t getBatteryVoltage(void) // Here come the good guys... return getVoltage(); -#elif defined(ARDUINO_heltec_wifi_32_lora_V3) || defined(ARDUINO_heltec_wifi_lora_32_V3) +#elif defined(ARDUINO_HELTEC_WIFI_LORA_32_V3) || defined(ARDUINO_heltec_wifi_lora_32_V3) // Enable ADC input switch, measure voltage and disable ADC input switch uint16_t voltage; pinMode(ADC_CTRL, OUTPUT);