From fe5da9358ebbdd1c8908d5cf57efb0f43ffef49f Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Thu, 14 Jun 2018 19:49:49 +0200 Subject: [PATCH 01/38] comments in ttgo.h files updated --- platformio.ini | 4 ++-- src/hal/ttgov2.h | 4 ++-- src/hal/ttgov21.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/platformio.ini b/platformio.ini index b4c12689..6c3e5148 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,10 +11,10 @@ ; ---> SELECT TARGET PLATFORM HERE! <--- [platformio] -env_default = heltec +;env_default = heltec ;env_default = ttgov1 ;env_default = ttgov2 -;env_default = ttgov21 +env_default = ttgov21 ;env_default = ttgobeam ;env_default = lopy ;env_default = lopy4 diff --git a/src/hal/ttgov2.h b/src/hal/ttgov2.h index e4bb49b4..5d116241 100644 --- a/src/hal/ttgov2.h +++ b/src/hal/ttgov2.h @@ -23,8 +23,8 @@ // Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display #define OLED_RST U8X8_PIN_NONE // connected to CPU RST/EN -#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO4 (Pin4) -- SD1306 D1+D2 -#define OLED_SCL GPIO_NUM_22 // ESP32 GPIO15 (Pin15) -- SD1306 D0 +#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO21 -- SD1306 D1+D2 +#define OLED_SCL GPIO_NUM_22 // ESP32 GPIO22 -- SD1306 D0 /* diff --git a/src/hal/ttgov21.h b/src/hal/ttgov21.h index 1e3b38ec..96617e1f 100644 --- a/src/hal/ttgov21.h +++ b/src/hal/ttgov21.h @@ -22,5 +22,5 @@ // Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display #define OLED_RST U8X8_PIN_NONE // connected to CPU RST/EN -#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO4 (Pin4) -- SD1306 D1+D2 -#define OLED_SCL GPIO_NUM_22 // ESP32 GPIO15 (Pin15) -- SD1306 D0 \ No newline at end of file +#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO21 -- SD1306 D1+D2 +#define OLED_SCL GPIO_NUM_22 // ESP32 GPIO22 -- SD1306 D0 \ No newline at end of file From 12c6dcb0ff7d785c7aaa0be45096f759c2af2430 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sat, 16 Jun 2018 13:18:36 +0200 Subject: [PATCH 02/38] added payload.cpp and and payload.h --- platformio.ini | 4 +-- src/payload.cpp | 89 +++++++++++++++++++++++++++++++++++++++++++++++++ src/payload.h | 36 ++++++++++++++++++++ 3 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 src/payload.cpp create mode 100644 src/payload.h diff --git a/platformio.ini b/platformio.ini index 6c3e5148..9e5e47aa 100644 --- a/platformio.ini +++ b/platformio.ini @@ -14,8 +14,8 @@ ;env_default = heltec ;env_default = ttgov1 ;env_default = ttgov2 -env_default = ttgov21 -;env_default = ttgobeam +;env_default = ttgov21 +env_default = ttgobeam ;env_default = lopy ;env_default = lopy4 ;env_default = fipy diff --git a/src/payload.cpp b/src/payload.cpp new file mode 100644 index 00000000..8d992a33 --- /dev/null +++ b/src/payload.cpp @@ -0,0 +1,89 @@ + +#include "globals.h" +#include "payload.h" + +TTNplain::TTNplain(uint8_t size) : maxsize(size) { + buffer = (uint8_t *)malloc(size); + cursor = 0; +} + +TTNplain::~TTNplain(void) { free(buffer); } + +void TTNplain::reset(void) { cursor = 0; } + +uint8_t TTNplain::getSize(void) { return cursor; } + +uint8_t *TTNplain::getBuffer(void) { + // uint8_t[cursor] result; + // memcpy(result, buffer, cursor); + // return result; + return buffer; +} + +uint8_t TTNplain::copy(uint8_t *dst) { + memcpy(dst, buffer, cursor); + return cursor; +} + +void TTNplain::addCount(uint16_t value1, uint16_t value2) { + cursor = TTN_PAYLOAD_COUNTER; + buffer[cursor] = (macs_wifi & 0xff00) >> 8; + buffer[cursor++] = macs_wifi & 0xff; + buffer[cursor++] = (macs_ble & 0xff00) >> 8; + buffer[cursor++] = macs_ble & 0xff; +} + +void TTNplain::addGPS(gpsStatus_t value) { + cursor = TTN_PAYLOAD_GPS; + buffer[cursor++] = value.latitude >> 24; + buffer[cursor++] = value.latitude >> 16; + buffer[cursor++] = value.latitude >> 8; + buffer[cursor++] = value.latitude; + buffer[cursor++] = value.longitude >> 24; + buffer[cursor++] = value.longitude >> 16; + buffer[cursor++] = value.longitude >> 8; + buffer[cursor++] = value.longitude; + buffer[cursor++] = value.satellites; + buffer[cursor++] = value.hdop >> 8; + buffer[cursor++] = value.hdop; + buffer[cursor++] = value.altitude >> 8; + buffer[cursor++] = value.altitude; +} + +void TTNplain::addConfig(configData_t value) { + cursor = TTN_PAYLOAD_CONFIG; + buffer[cursor++] = value.lorasf; + buffer[cursor++] = value.adrmode; + buffer[cursor++] = value.screensaver; + buffer[cursor++] = value.screenon; + buffer[cursor++] = value.countermode; + buffer[cursor++] = value.rssilimit >> 8; + buffer[cursor++] = value.rssilimit; + buffer[cursor++] = value.sendcycle; + buffer[cursor++] = value.wifichancycle; + buffer[cursor++] = value.blescantime; + buffer[cursor++] = value.blescan; + buffer[cursor++] = value.wifiant; + buffer[cursor++] = value.vendorfilter; + buffer[cursor++] = value.rgblum; + buffer[cursor++] = value.gpsmode; + memcpy(buffer + cursor, value.version, 10); +} + +void TTNplain::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { + cursor = TTN_PAYLOAD_STATUS; + buffer[cursor++] = voltage >> 8; + buffer[cursor++] = voltage; + buffer[cursor++] = uptime >> 56; + buffer[cursor++] = uptime >> 48; + buffer[cursor++] = uptime >> 40; + buffer[cursor++] = uptime >> 32; + buffer[cursor++] = uptime >> 24; + buffer[cursor++] = uptime >> 32; + buffer[cursor++] = uptime >> 16; + buffer[cursor++] = uptime >> 8; + buffer[cursor++] = (uint32_t) cputemp >> 24; + buffer[cursor++] = (uint32_t) cputemp >> 16; + buffer[cursor++] = (uint32_t) cputemp >> 8; + buffer[cursor++] = (uint32_t) cputemp; +} \ No newline at end of file diff --git a/src/payload.h b/src/payload.h new file mode 100644 index 00000000..b4069c7b --- /dev/null +++ b/src/payload.h @@ -0,0 +1,36 @@ + +#ifndef _PAYLOAD_H_ +#define _PAYLOAD_H_ + +#include + +#define TTN_PAYLOAD_COUNTER 0 +#define TTN_PAYLOAD_GPS 4 +#define TTN_PAYLOAD_CONFIG 0 +#define TTN_PAYLOAD_STATUS 0 + +class TTNplain { +public: + TTNplain(uint8_t size); + ~TTNplain(); + + void reset(void); + uint8_t getSize(void); + uint8_t *getBuffer(void); + uint8_t copy(uint8_t *buffer); + + // application payloads + void addCount(uint16_t value1, uint16_t value2); + void addGPS(gpsStatus_t value); + + // payloads for get rcommands + void addConfig(configData_t value); + void addStatus(uint16_t voltage, uint64_t uptime, float cputemp); + +private: + uint8_t *buffer; + uint8_t maxsize; + uint8_t cursor; +}; + +#endif \ No newline at end of file From 7c03c22765413721c22457396a7bfbe4bed760e1 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sat, 16 Jun 2018 19:50:36 +0200 Subject: [PATCH 03/38] payload converter enhanced --- README.md | 34 +++++++--------- platformio.ini | 12 ++++++ src/globals.h | 53 +++++++++---------------- src/lorawan.cpp | 38 ++++++------------ src/macsniff.cpp | 2 +- src/main.cpp | 32 ++++++++++++--- src/main.h | 36 ++++++++++++++++- src/paxcounter.conf | 6 ++- src/payload.cpp | 95 ++++++++++++++++++++++++++++++++------------- src/payload.h | 32 +++++++++++---- src/rcommand.cpp | 54 +++++++++----------------- 11 files changed, 236 insertions(+), 158 deletions(-) diff --git a/README.md b/README.md index b792602c..dccacae9 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,8 @@ Legend for RGB LED (LoPy/LoPy4/FiPy/Lolin32 only): # Payload +All data is represented in big-endian-format, as long not otherwise stated. + **LoRaWAN Port #1:** Paxcounter data @@ -140,11 +142,11 @@ function Decoder(bytes, port) { decoded.wifi = (bytes[i++] << 8) | bytes[i++]; decoded.ble = (bytes[i++] << 8) | bytes[i++]; if (bytes.length > 4) { - decoded.latitude = ( (bytes[i++]) | (bytes[i++] << 8) | (bytes[i++] << 16) | bytes[i++] << 24 ); - decoded.longitude = ( (bytes[i++]) | (bytes[i++] << 8) | (bytes[i++] << 16) | bytes[i++] << 24 ); - decoded.sats = ( bytes[i++] | (bytes[i++] << 8) ); - decoded.hdop = ( bytes[i++] | (bytes[i++] << 8) ); - decoded.altitude = ( bytes[i++] | (bytes[i++] << 8) ); + decoded.latitude = ( (bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++] ); + decoded.longitude = ( (bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++] ); + decoded.sats = ( bytes[i++] ); + decoded.hdop = ( bytes[i++] << 8) | (bytes[i++] ); + decoded.altitude = ( bytes[i++] << 8) | (bytes[i++] ); } } @@ -264,7 +266,7 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts. 0x80 get device configuration -device answers with it's current configuration. The configuration is a C structure declared in file [globals.h](src/globals.h#L32-L50) with the following definition: +device answers with it's current configuration. The configuration is a C structure declared in file [main.h](src/main.h#L13-L31) with the following definition: byte 1: Lora SF (7..12) [default 9] byte 2: Lora TXpower (2..15) [default 15] @@ -283,25 +285,19 @@ device answers with it's current configuration. The configuration is a C structu byte 16: GPS send data mode (1=on, 0=ff) [default 1] bytes 17-27: Software version (ASCII format, terminating with zero) -0x81 get device uptime +0x81 get device status - bytes 1-8: Uptime in seconds (little endian format) - -0x82 get device cpu temperature - - bytes 1-4: Chip temperature in degrees celsius (little endian format) - -0x83 get device battery voltage - - bytes 1-2: Battery voltage in millivolt, 0 if unreadable (little endian format) + bytes 1-2: Battery voltage in millivolt, 0 if unreadable + bytes 3-10: Uptime in seconds + bytes 11-14: Chip temperature in degrees celsius 0x84 get device GPS status bytes 1-4: Latitude bytes 5-8: Longitude - byte 9-10: Number of satellites - byte 11-12: HDOP - bytes 13-14: altidute [meter] + byte 9: Number of satellites + byte 10-11: HDOP + bytes 12-13: altidute [meter] # License diff --git a/platformio.ini b/platformio.ini index 9e5e47aa..787cf3ae 100644 --- a/platformio.ini +++ b/platformio.ini @@ -27,6 +27,8 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng [common_env_data] platform_espressif32 = espressif32@>=1.0.2 board_build.partitions = no_ota.csv +lib_deps_all = + LoRa Serialization@>=3.0.0 lib_deps_display = U8g2@>=2.22.14 lib_deps_rgbled = @@ -55,6 +57,7 @@ board_build.partitions = ${common_env_data.board_build.partitions} monitor_speed = 115200 upload_speed = 115200 lib_deps = + ${common_env_data.lib_deps_all} ${common_env_data.lib_deps_display} build_flags = ${common_env_data.build_flags} @@ -68,6 +71,7 @@ board_build.partitions = ${common_env_data.board_build.partitions} monitor_speed = 115200 upload_speed = 115200 lib_deps = + ${common_env_data.lib_deps_all} ${common_env_data.lib_deps_display} build_flags = ${common_env_data.build_flags} @@ -81,6 +85,7 @@ board_build.partitions = ${common_env_data.board_build.partitions} monitor_speed = 115200 upload_speed = 921600 lib_deps = + ${common_env_data.lib_deps_all} ${common_env_data.lib_deps_display} build_flags = ${common_env_data.build_flags} @@ -94,6 +99,7 @@ board_build.partitions = ${common_env_data.board_build.partitions} monitor_speed = 115200 upload_speed = 921600 lib_deps = + ${common_env_data.lib_deps_all} ${common_env_data.lib_deps_display} build_flags = ${common_env_data.build_flags} @@ -107,6 +113,7 @@ board_build.partitions = ${common_env_data.board_build.partitions} monitor_speed = 115200 upload_speed = 921600 lib_deps = + ${common_env_data.lib_deps_all} ${common_env_data.lib_deps_gps} build_flags = ${common_env_data.build_flags} @@ -120,6 +127,7 @@ board_build.partitions = ${common_env_data.board_build.partitions} monitor_speed = 115200 upload_speed = 921600 lib_deps = + ${common_env_data.lib_deps_all} ${common_env_data.lib_deps_rgbled} build_flags = ${common_env_data.build_flags} @@ -133,6 +141,7 @@ board_build.partitions = ${common_env_data.board_build.partitions} monitor_speed = 115200 upload_speed = 921600 lib_deps = + ${common_env_data.lib_deps_all} ${common_env_data.lib_deps_rgbled} build_flags = ${common_env_data.build_flags} @@ -146,6 +155,7 @@ board_build.partitions = ${common_env_data.board_build.partitions} monitor_speed = 115200 upload_speed = 921600 lib_deps = + ${common_env_data.lib_deps_all} ${common_env_data.lib_deps_rgbled} build_flags = ${common_env_data.build_flags} @@ -159,6 +169,7 @@ board_build.partitions = ${common_env_data.board_build.partitions} monitor_speed = 115200 upload_speed = 256000 lib_deps = + ${common_env_data.lib_deps_all} ${common_env_data.lib_deps_rgbled} build_flags = ${common_env_data.build_flags} @@ -172,6 +183,7 @@ board_build.partitions = ${common_env_data.board_build.partitions} monitor_speed = 115200 upload_speed = 921600 lib_deps = + ${common_env_data.lib_deps_all} ${common_env_data.lib_deps_rgbled} build_flags = ${common_env_data.build_flags} diff --git a/src/globals.h b/src/globals.h index d9adb1b9..37567dfd 100644 --- a/src/globals.h +++ b/src/globals.h @@ -28,38 +28,7 @@ #include "rgb_led.h" #include "macsniff.h" #include "main.h" - -// Struct holding devices's runtime configuration -typedef struct { - uint8_t lorasf; // 7-12, lora spreadfactor - uint8_t txpower; // 2-15, lora tx power - uint8_t adrmode; // 0=disabled, 1=enabled - uint8_t screensaver; // 0=disabled, 1=enabled - uint8_t screenon; // 0=disabled, 1=enabled - uint8_t countermode; // 0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed - int16_t rssilimit; // threshold for rssilimiter, negative value! - uint8_t sendcycle; // payload send cycle [seconds/2] - uint8_t wifichancycle; // wifi channel switch cycle [seconds/100] - uint8_t blescantime; // BLE scan cycle duration [seconds] - uint8_t blescan; // 0=disabled, 1=enabled - uint8_t wifiant; // 0=internal, 1=external (for LoPy/LoPy4) - uint8_t vendorfilter; // 0=disabled, 1=enabled - uint8_t rgblum; // RGB Led luminosity (0..100%) - uint8_t gpsmode; // 0=disabled, 1=enabled - char version[10]; // Firmware version -} configData_t; - -#ifdef HAS_GPS -typedef struct { - uint32_t latitude; - uint32_t longitude; - uint8_t satellites; - uint16_t hdop; - uint16_t altitude; -} gpsStatus_t; -extern gpsStatus_t gps_status; // struct for storing gps data -extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe -#endif +#include "payload.h" extern configData_t cfg; extern uint64_t uptimecounter; @@ -69,6 +38,20 @@ extern int countermode, screensaver, adrmode, lorasf, txpower, rlim; extern uint16_t macs_total, macs_wifi, macs_ble; // MAC counters extern std::set macs; extern hw_timer_t - *channelSwitch; // hardware timer used for wifi channel switching -extern xref2u1_t rcmd_data; // buffer for rcommand results size -extern u1_t rcmd_data_size; // buffer for rcommand results size + *channelSwitch; // hardware timer used for wifi channel switching + +#ifdef HAS_GPS +extern gpsStatus_t gps_status; // struct for storing gps data +extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe +#endif + +// payload encoder +#if (PAYLOAD_ENCODER == 3) +// externe CayenneLPP payload; +#elif (PAYLOAD_ENCODER == 2) +extern TTNserialized payload; +#elif (PAYLOAD_ENCODER == 1) +extern TTNplain payload; +#else +#error "No valid payload converter defined" +#endif \ No newline at end of file diff --git a/src/lorawan.cpp b/src/lorawan.cpp index ed07f19e..fd562cb1 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -117,42 +117,28 @@ void do_send(osjob_t *j) { return; } - // prepare payload with sum of unique WIFI MACs seen - static uint8_t mydata[4]; - - mydata[0] = (macs_wifi & 0xff00) >> 8; - mydata[1] = macs_wifi & 0xff; + // Prepare payload with counter and, if applicable, gps data + payload.reset(); if (cfg.blescan) { - // append sum of unique BLE MACs seen to payload - mydata[2] = (macs_ble & 0xff00) >> 8; - mydata[3] = macs_ble & 0xff; + payload.addCount(macs_wifi, macs_ble); } else { - mydata[2] = 0; - mydata[3] = 0; + payload.addCount(macs_wifi, 0); } #ifdef HAS_GPS - static uint8_t gpsdata[18]; - if (cfg.gpsmode && gps.location.isValid()) { + if ((cfg.gpsmode) && (gps.location.isValid())) { gps_read(); - memcpy(gpsdata, mydata, 4); - memcpy(gpsdata + 4, &gps_status, sizeof(gps_status)); - ESP_LOGI(TAG, "lat=%.6f / lon=%.6f | %u Sats | HDOP=%.1f | Altitude=%u m", - gps_status.latitude / (float)1000000, - gps_status.longitude / (float)1000000, gps_status.satellites, - gps_status.hdop / (float)100, gps_status.altitude); - LMIC_setTxData2(COUNTERPORT, gpsdata, sizeof(gpsdata), - (cfg.countermode & 0x02)); - ESP_LOGI(TAG, "%d bytes queued to send", sizeof(gpsdata)); + payload.addGPS(gps_status); } else { -#endif - LMIC_setTxData2(COUNTERPORT, mydata, sizeof(mydata), - (cfg.countermode & 0x02)); - ESP_LOGI(TAG, "%d bytes queued to send", sizeof(mydata)); -#ifdef HAS_GPS + ESP_LOGI(TAG, "No valid GPS position or GPS disabled"); } #endif + + // send payload + LMIC_setTxData2(COUNTERPORT, payload.getBuffer(), payload.getSize(), + (cfg.countermode & 0x02)); + ESP_LOGI(TAG, "%d bytes queued to send", payload.getSize()); sprintf(display_lmic, "PACKET QUEUED"); // clear counter if not in cumulative counter mode diff --git a/src/macsniff.cpp b/src/macsniff.cpp index 40290731..fbe0469d 100644 --- a/src/macsniff.cpp +++ b/src/macsniff.cpp @@ -76,7 +76,7 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) { } // Log scan result - ESP_LOGI(TAG, + ESP_LOGD(TAG, "%s %s RSSI %ddBi -> MAC %s -> Hash %04X -> WiFi:%d BLTH:%d -> " "%d Bytes left", added ? "new " : "known", diff --git a/src/main.cpp b/src/main.cpp index 59251284..8dee0c0e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -56,9 +56,7 @@ uint16_t LEDColor = COLOR_NONE; // state machine variable to set RGB LED color hw_timer_t *displaytimer = NULL; // configure hardware timer used for cyclic display refresh hw_timer_t *channelSwitch = - NULL; // configure hardware timer used for wifi channel switching -xref2u1_t rcmd_data; // buffer for rcommand results size -u1_t rcmd_data_size; // buffer for rcommand results size + NULL; // configure hardware timer used for wifi channel switching #ifdef HAS_GPS gpsStatus_t gps_status; // struct for storing gps data @@ -72,6 +70,19 @@ portMUX_TYPE timerMux = std::set macs; // associative container holds total of unique MAC // adress hashes (Wifi + BLE) +// select payload encoder +#if (PAYLOAD_ENCODER == 3) +// CayenneLPP payload(PAYLOAD_BUFFER_SIZE); +#elif (PAYLOAD_ENCODER == 2) +TTNserialized payload(PAYLOAD_BUFFER_SIZE); +#elif (PAYLOAD_ENCODER == 1) +TTNplain payload(PAYLOAD_BUFFER_SIZE); +#else +#error "No valid payload converter defined" +#endif + +// TTNplain payload(PAYLOAD_BUFFER_SIZE); + // this variables will be changed in the ISR, and read in main loop static volatile int ButtonPressedIRQ = 0, DisplayTimerIRQ = 0, ChannelTimerIRQ = 0; @@ -674,11 +685,22 @@ void loop() { } #ifdef HAS_GPS - // log NMEA status every 30 seconds, useful for debugging GPS connection - if ((uptime() % 30000) == 0) + // log NMEA status every 60 seconds, useful for debugging GPS connection + if ((uptime() % 60000) == 0) { ESP_LOGI(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d", gps.passedChecksum(), gps.failedChecksum(), gps.sentencesWithFix()); + if ((cfg.gpsmode) && (gps.location.isValid())) { + gps_read(); + ESP_LOGI(TAG, + "lat=%.6f | lon=%.6f | %u Sats | HDOP=%.1f | Altitude=%um", + gps_status.latitude / (float)1000000, + gps_status.longitude / (float)1000000, gps_status.satellites, + gps_status.hdop / (float)100, gps_status.altitude); + } else { + ESP_LOGI(TAG, "No valid GPS position or GPS disabled"); + } + } #endif vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog diff --git a/src/main.h b/src/main.h index 52f7a44f..e807d7a1 100644 --- a/src/main.h +++ b/src/main.h @@ -5,11 +5,43 @@ // program version - note: increment version after modifications to configData_t // struct!! -#define PROGVERSION "1.3.81" // use max 10 chars here! +#define PROGVERSION "1.3.82" // use max 10 chars here! #define PROGNAME "PAXCNT" //--- Declarations --- +// Struct holding devices's runtime configuration +typedef struct { + uint8_t lorasf; // 7-12, lora spreadfactor + uint8_t txpower; // 2-15, lora tx power + uint8_t adrmode; // 0=disabled, 1=enabled + uint8_t screensaver; // 0=disabled, 1=enabled + uint8_t screenon; // 0=disabled, 1=enabled + uint8_t countermode; // 0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed + int16_t rssilimit; // threshold for rssilimiter, negative value! + uint8_t sendcycle; // payload send cycle [seconds/2] + uint8_t wifichancycle; // wifi channel switch cycle [seconds/100] + uint8_t blescantime; // BLE scan cycle duration [seconds] + uint8_t blescan; // 0=disabled, 1=enabled + uint8_t wifiant; // 0=internal, 1=external (for LoPy/LoPy4) + uint8_t vendorfilter; // 0=disabled, 1=enabled + uint8_t rgblum; // RGB Led luminosity (0..100%) + uint8_t gpsmode; // 0=disabled, 1=enabled + char version[10]; // Firmware version +} configData_t; + +#ifdef HAS_GPS +typedef struct { + uint32_t latitude; + uint32_t longitude; + uint8_t satellites; + uint16_t hdop; + uint16_t altitude; +} gpsStatus_t; +extern gpsStatus_t gps_status; // struct for storing gps data +extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe +#endif + enum led_states { LED_OFF, LED_ON }; #if defined(CFG_eu868) @@ -35,4 +67,4 @@ void stop_BLEscan(void); #ifdef HAS_GPS void gps_read(void); void gps_loop(void *pvParameters); -#endif +#endif \ No newline at end of file diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 47432573..0c3dad85 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -35,15 +35,17 @@ #define WIFI_CHANNEL_SWITCH_INTERVAL 50 // [seconds/100] -> 0,5 sec. // LoRa payload send cycle --> take care of duty cycle of LoRaWAN network! <-- -#define SEND_SECS 120 // [seconds/2] -> 240 sec. +//#define SEND_SECS 120 // [seconds/2] -> 240 sec. +#define SEND_SECS 30 // [seconds/2] -> 60 sec. #define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle #define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results +#define PAYLOAD_ENCODER 2 // select payload encoder: 1 = Plain [default], 2 = Lora-hserialized, 3 = Cayenne LPP +#define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit // Default LoRa Spreadfactor #define LORASFDEFAULT 9 // 7 ... 12 SF, according to LoRaWAN specs #define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy #define RCMDPORT 2 // LoRaWAN Port on which device listenes for remote commands -#define GPSPORT 3 // LoRaWAN Port on which device sends gps data #define COUNTERPORT 1 // LoRaWAN Port on which device sends counts // Default RGB LED luminosity (in %) diff --git a/src/payload.cpp b/src/payload.cpp index 8d992a33..e9d30f25 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -2,7 +2,9 @@ #include "globals.h" #include "payload.h" -TTNplain::TTNplain(uint8_t size) : maxsize(size) { +/* ---------------- plain format without special encoding ---------- */ + +TTNplain::TTNplain(uint8_t size) { buffer = (uint8_t *)malloc(size); cursor = 0; } @@ -13,28 +15,16 @@ void TTNplain::reset(void) { cursor = 0; } uint8_t TTNplain::getSize(void) { return cursor; } -uint8_t *TTNplain::getBuffer(void) { - // uint8_t[cursor] result; - // memcpy(result, buffer, cursor); - // return result; - return buffer; -} - -uint8_t TTNplain::copy(uint8_t *dst) { - memcpy(dst, buffer, cursor); - return cursor; -} +uint8_t *TTNplain::getBuffer(void) { return buffer; } void TTNplain::addCount(uint16_t value1, uint16_t value2) { - cursor = TTN_PAYLOAD_COUNTER; - buffer[cursor] = (macs_wifi & 0xff00) >> 8; - buffer[cursor++] = macs_wifi & 0xff; - buffer[cursor++] = (macs_ble & 0xff00) >> 8; - buffer[cursor++] = macs_ble & 0xff; + buffer[cursor++] = value1 >> 8; + buffer[cursor++] = value1; + buffer[cursor++] = value2 >> 8; + buffer[cursor++] = value2; } void TTNplain::addGPS(gpsStatus_t value) { - cursor = TTN_PAYLOAD_GPS; buffer[cursor++] = value.latitude >> 24; buffer[cursor++] = value.latitude >> 16; buffer[cursor++] = value.latitude >> 8; @@ -51,7 +41,6 @@ void TTNplain::addGPS(gpsStatus_t value) { } void TTNplain::addConfig(configData_t value) { - cursor = TTN_PAYLOAD_CONFIG; buffer[cursor++] = value.lorasf; buffer[cursor++] = value.adrmode; buffer[cursor++] = value.screensaver; @@ -68,10 +57,10 @@ void TTNplain::addConfig(configData_t value) { buffer[cursor++] = value.rgblum; buffer[cursor++] = value.gpsmode; memcpy(buffer + cursor, value.version, 10); + cursor += 10; } void TTNplain::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { - cursor = TTN_PAYLOAD_STATUS; buffer[cursor++] = voltage >> 8; buffer[cursor++] = voltage; buffer[cursor++] = uptime >> 56; @@ -79,11 +68,65 @@ void TTNplain::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { buffer[cursor++] = uptime >> 40; buffer[cursor++] = uptime >> 32; buffer[cursor++] = uptime >> 24; - buffer[cursor++] = uptime >> 32; buffer[cursor++] = uptime >> 16; buffer[cursor++] = uptime >> 8; - buffer[cursor++] = (uint32_t) cputemp >> 24; - buffer[cursor++] = (uint32_t) cputemp >> 16; - buffer[cursor++] = (uint32_t) cputemp >> 8; - buffer[cursor++] = (uint32_t) cputemp; -} \ No newline at end of file + buffer[cursor++] = uptime; + buffer[cursor++] = (uint32_t)cputemp >> 24; + buffer[cursor++] = (uint32_t)cputemp >> 16; + buffer[cursor++] = (uint32_t)cputemp >> 8; + buffer[cursor++] = (uint32_t)cputemp; +} + +/* ---------------- packed format with LoRa serialization Encoder ---------- */ + +TTNserialized::TTNserialized(uint8_t size) { + buffer = (uint8_t *)malloc(size); + LoraEncoder message(buffer); +} + +TTNserialized::~TTNserialized(void) { free(buffer); } + +void TTNserialized::reset(void) { } + +uint8_t TTNserialized::getSize(void) { return sizeof(buffer); } + +uint8_t *TTNserialized::getBuffer(void) { return buffer; } + +void TTNserialized::addCount(uint16_t value1, uint16_t value2) { + LoraEncoder message(buffer); + message.writeUint16(value1); + message.writeUint16(value2); +} + +void TTNserialized::addGPS(gpsStatus_t value) { + LoraEncoder message(buffer); + message.writeLatLng(value.latitude, value.longitude); + message.writeUint8(value.satellites); + message.writeUint16(value.hdop); + message.writeUint16(value.altitude); +} + +void TTNserialized::addConfig(configData_t value) { + LoraEncoder message(buffer); + message.writeUint8(value.lorasf); + message.writeUint16(value.rssilimit); + message.writeUint8(value.sendcycle); + message.writeUint8(value.wifichancycle); + message.writeUint8(value.blescantime); + message.writeUint8(value.rgblum); + message.writeBitmap( + value.adrmode ? true : false, value.screensaver ? true : false, + value.screenon ? true : false, value.countermode ? true : false, + value.blescan ? true : false, value.wifiant ? true : false, + value.vendorfilter ? true : false, value.gpsmode ? true : false); +} + +void TTNserialized::addStatus(uint16_t voltage, uint64_t uptime, + float cputemp) { + LoraEncoder message(buffer); + message.writeUint16(voltage); + message.writeUnixtime(uptime); + message.writeTemperature(cputemp); +} + +/* ---------------- Cayenne LPP format ---------- */ \ No newline at end of file diff --git a/src/payload.h b/src/payload.h index b4069c7b..f5096a9a 100644 --- a/src/payload.h +++ b/src/payload.h @@ -3,11 +3,7 @@ #define _PAYLOAD_H_ #include - -#define TTN_PAYLOAD_COUNTER 0 -#define TTN_PAYLOAD_GPS 4 -#define TTN_PAYLOAD_CONFIG 0 -#define TTN_PAYLOAD_STATUS 0 +#include "LoraEncoder.h" class TTNplain { public: @@ -17,7 +13,6 @@ public: void reset(void); uint8_t getSize(void); uint8_t *getBuffer(void); - uint8_t copy(uint8_t *buffer); // application payloads void addCount(uint16_t value1, uint16_t value2); @@ -33,4 +28,27 @@ private: uint8_t cursor; }; -#endif \ No newline at end of file +class TTNserialized { +public: + TTNserialized(uint8_t size); + ~TTNserialized(); + + void reset(void); + uint8_t getSize(void); + uint8_t *getBuffer(void); + + // application payloads + void addCount(uint16_t value1, uint16_t value2); + void addGPS(gpsStatus_t value); + + // payloads for get rcommands + void addConfig(configData_t value); + void addStatus(uint16_t voltage, uint64_t uptime, float cputemp); + +private: + uint8_t *buffer; + LoraEncoder message(byte *buffer); + //LoraEncoder(byte *buffer); +}; + +#endif diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 6b446f78..1178892a 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -27,7 +27,7 @@ void antenna_select(const uint8_t _ant); // function defined in adcread.cpp #ifdef HAS_BATTERY_PROBE -uint32_t read_voltage(void); +uint16_t read_voltage(void); #endif // function sends result of get commands to LoRaWAN network @@ -40,20 +40,13 @@ void do_transmit(osjob_t *j) { os_setTimedCallback(&rcmdjob, os_getTime() + sec2osticks(RETRANSMIT_RCMD), do_transmit); } - LMIC_setTxData2(RCMDPORT, rcmd_data, rcmd_data_size, - 0); // send data unconfirmed on RCMD Port - ESP_LOGI(TAG, "%d bytes queued to send", rcmd_data_size); + // send payload + LMIC_setTxData2(RCMDPORT, payload.getBuffer(), payload.getSize(), + (cfg.countermode & 0x02)); + ESP_LOGI(TAG, "%d bytes queued to send", payload.getSize()); sprintf(display_lmic, "PACKET QUEUED"); } -// help function to transmit result of get commands, since callback function -// do_transmit() cannot have params -void transmit(xref2u1_t mydata, u1_t mydata_size) { - rcmd_data = mydata; - rcmd_data_size = mydata_size; - do_transmit(&rcmdjob); -} - // help function to assign LoRa datarates to numeric spreadfactor values void switch_lora(uint8_t sf, uint8_t tx) { if (tx > 20) @@ -292,41 +285,33 @@ void set_lorapower(uint8_t val) { }; void get_config(uint8_t val) { - ESP_LOGI(TAG, "Remote command: get configuration"); - transmit((byte *)&cfg, sizeof(cfg)); + ESP_LOGI(TAG, "Remote command: get device configuration"); + payload.reset(); + payload.addConfig(cfg); + do_transmit(&rcmdjob); }; -void get_uptime(uint8_t val) { - ESP_LOGI(TAG, "Remote command: get uptime"); - transmit((byte *)&uptimecounter, sizeof(uptimecounter)); -}; - -void get_cputemp(uint8_t val) { - ESP_LOGI(TAG, "Remote command: get cpu temperature"); - float temp = temperatureRead(); - transmit((byte *)&temp, sizeof(temp)); -}; - -void get_voltage(uint8_t val) { - ESP_LOGI(TAG, "Remote command: get battery voltage"); +void get_status(uint8_t val) { + ESP_LOGI(TAG, "Remote command: get device status"); #ifdef HAS_BATTERY_PROBE uint16_t voltage = read_voltage(); #else uint16_t voltage = 0; #endif - transmit((byte *)&voltage, sizeof(voltage)); + payload.reset(); + payload.addStatus(voltage, uptimecounter, temperatureRead()); + do_transmit(&rcmdjob); }; void get_gps(uint8_t val) { ESP_LOGI(TAG, "Remote command: get gps status"); #ifdef HAS_GPS gps_read(); - transmit((byte *)&gps_status, sizeof(gps_status)); - ESP_LOGI(TAG, "lat=%f / lon=%f | Sats=%u | HDOP=%u | Alti=%u", - gps_status.latitude / 1000000, gps_status.longitude / 1000000, - gps_status.satellites, gps_status.hdop, gps_status.altitude); + payload.reset(); + payload.addGPS(gps_status); + do_transmit(&rcmdjob); #else - ESP_LOGE(TAG, "GPS not present"); + ESP_LOGW(TAG, "GPS function not supported"); #endif }; @@ -341,8 +326,7 @@ cmd_t table[] = {{0x01, set_rssi, true}, {0x02, set_countmode, true}, {0x0b, set_wifichancycle, true}, {0x0c, set_blescantime, true}, {0x0d, set_vendorfilter, false}, {0x0e, set_blescan, true}, {0x0f, set_wifiant, true}, {0x10, set_rgblum, true}, - {0x80, get_config, false}, {0x81, get_uptime, false}, - {0x82, get_cputemp, false}, {0x83, get_voltage, false}, + {0x80, get_config, false}, {0x81, get_status, false}, {0x84, get_gps, false}}; // check and execute remote command From 509b8b6cd338da16354d5d3b92a4be77e78f7891 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sat, 16 Jun 2018 19:54:48 +0200 Subject: [PATCH 04/38] finishing new payload converter structure --- src/globals.h | 8 ++++---- src/main.cpp | 12 +++++------- src/paxcounter.conf | 2 +- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/globals.h b/src/globals.h index 37567dfd..e9290285 100644 --- a/src/globals.h +++ b/src/globals.h @@ -46,12 +46,12 @@ extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe #endif // payload encoder -#if (PAYLOAD_ENCODER == 3) -// externe CayenneLPP payload; +#if (PAYLOAD_ENCODER == 1) +extern TTNplain payload; #elif (PAYLOAD_ENCODER == 2) extern TTNserialized payload; -#elif (PAYLOAD_ENCODER == 1) -extern TTNplain payload; +#elif (PAYLOAD_ENCODER == 3) +//extern CayenneLPP payload; #else #error "No valid payload converter defined" #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 8dee0c0e..5a3a6589 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,19 +70,17 @@ portMUX_TYPE timerMux = std::set macs; // associative container holds total of unique MAC // adress hashes (Wifi + BLE) -// select payload encoder -#if (PAYLOAD_ENCODER == 3) -// CayenneLPP payload(PAYLOAD_BUFFER_SIZE); +// initialize payload encoder +#if (PAYLOAD_ENCODER == 1) +TTNplain payload(PAYLOAD_BUFFER_SIZE); #elif (PAYLOAD_ENCODER == 2) TTNserialized payload(PAYLOAD_BUFFER_SIZE); -#elif (PAYLOAD_ENCODER == 1) -TTNplain payload(PAYLOAD_BUFFER_SIZE); +#elif (PAYLOAD_ENCODER == 3) +//CayenneLPP payload(PAYLOAD_BUFFER_SIZE); #else #error "No valid payload converter defined" #endif -// TTNplain payload(PAYLOAD_BUFFER_SIZE); - // this variables will be changed in the ISR, and read in main loop static volatile int ButtonPressedIRQ = 0, DisplayTimerIRQ = 0, ChannelTimerIRQ = 0; diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 0c3dad85..9e550d01 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -39,7 +39,7 @@ #define SEND_SECS 30 // [seconds/2] -> 60 sec. #define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle #define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results -#define PAYLOAD_ENCODER 2 // select payload encoder: 1 = Plain [default], 2 = Lora-hserialized, 3 = Cayenne LPP +#define PAYLOAD_ENCODER 1 // select payload encoder: 1 = Plain [default], 2 = Lora-hserialized, 3 = Cayenne LPP #define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit // Default LoRa Spreadfactor From ec5b1df77cfbab2e1edab5519619dc0c7a83867c Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sat, 16 Jun 2018 20:20:19 +0200 Subject: [PATCH 05/38] payload encoder testing --- src/lorawan.cpp | 2 -- src/payload.cpp | 4 ++-- src/payload.h | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index fd562cb1..69003d9c 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -130,8 +130,6 @@ void do_send(osjob_t *j) { if ((cfg.gpsmode) && (gps.location.isValid())) { gps_read(); payload.addGPS(gps_status); - } else { - ESP_LOGI(TAG, "No valid GPS position or GPS disabled"); } #endif diff --git a/src/payload.cpp b/src/payload.cpp index e9d30f25..c1c79c86 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -81,12 +81,12 @@ void TTNplain::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { TTNserialized::TTNserialized(uint8_t size) { buffer = (uint8_t *)malloc(size); - LoraEncoder message(buffer); + //LoraEncoder message(buffer); } TTNserialized::~TTNserialized(void) { free(buffer); } -void TTNserialized::reset(void) { } +void TTNserialized::reset(void) { delete buffer; } uint8_t TTNserialized::getSize(void) { return sizeof(buffer); } diff --git a/src/payload.h b/src/payload.h index f5096a9a..03311c76 100644 --- a/src/payload.h +++ b/src/payload.h @@ -48,7 +48,6 @@ public: private: uint8_t *buffer; LoraEncoder message(byte *buffer); - //LoraEncoder(byte *buffer); }; #endif From 692b90d2303b64ba7bfbac0776f108e74d56fef5 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sat, 16 Jun 2018 20:25:49 +0200 Subject: [PATCH 06/38] paxcounter.conf edit --- src/paxcounter.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 9e550d01..31423a3c 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -1,6 +1,8 @@ // ----- Paxcounter user config file ------ // // --> adapt to your needs and use case <-- +// +// Note: After editing, before "build", use "clean" button in PlatformIO! // Verbose enables serial output #define VERBOSE 1 // comment out to silence the device, for mute use build option From a6642ea8b64e4e9a9650da6587ca37bcc56faca9 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sat, 16 Jun 2018 23:14:49 +0200 Subject: [PATCH 07/38] CayenneLPP payload encoder added (experimental) --- src/globals.h | 2 +- src/main.cpp | 2 +- src/paxcounter.conf | 3 +- src/payload.cpp | 68 +++++++++++++++++++++++++++++++++++++++++++-- src/payload.h | 45 +++++++++++++++++++++++++----- 5 files changed, 108 insertions(+), 12 deletions(-) diff --git a/src/globals.h b/src/globals.h index e9290285..262fc4c8 100644 --- a/src/globals.h +++ b/src/globals.h @@ -51,7 +51,7 @@ extern TTNplain payload; #elif (PAYLOAD_ENCODER == 2) extern TTNserialized payload; #elif (PAYLOAD_ENCODER == 3) -//extern CayenneLPP payload; +extern CayenneLPP payload; #else #error "No valid payload converter defined" #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 5a3a6589..025365dd 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -76,7 +76,7 @@ TTNplain payload(PAYLOAD_BUFFER_SIZE); #elif (PAYLOAD_ENCODER == 2) TTNserialized payload(PAYLOAD_BUFFER_SIZE); #elif (PAYLOAD_ENCODER == 3) -//CayenneLPP payload(PAYLOAD_BUFFER_SIZE); +CayenneLPP payload(PAYLOAD_BUFFER_SIZE); #else #error "No valid payload converter defined" #endif diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 31423a3c..b1c31537 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -41,8 +41,9 @@ #define SEND_SECS 30 // [seconds/2] -> 60 sec. #define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle #define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results -#define PAYLOAD_ENCODER 1 // select payload encoder: 1 = Plain [default], 2 = Lora-hserialized, 3 = Cayenne LPP +#define PAYLOAD_ENCODER 3 // select payload encoder: 1 = Plain [default], 2 = Lora-serialized, 3 = CayenneLPP #define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit +#define CAYENNE_LPP 1 // uncomment this, if you need Cayenne LPP payload encoding // Default LoRa Spreadfactor #define LORASFDEFAULT 9 // 7 ... 12 SF, according to LoRaWAN specs diff --git a/src/payload.cpp b/src/payload.cpp index c1c79c86..f1a9df55 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -81,7 +81,7 @@ void TTNplain::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { TTNserialized::TTNserialized(uint8_t size) { buffer = (uint8_t *)malloc(size); - //LoraEncoder message(buffer); + // LoraEncoder message(buffer); } TTNserialized::~TTNserialized(void) { free(buffer); } @@ -129,4 +129,68 @@ void TTNserialized::addStatus(uint16_t voltage, uint64_t uptime, message.writeTemperature(cputemp); } -/* ---------------- Cayenne LPP format ---------- */ \ No newline at end of file +/* ---------------- Cayenne LPP format ---------- */ + +#ifdef CAYENNE_LPP + +CayenneLPP::CayenneLPP(uint8_t size) { + buffer = (uint8_t *)malloc(size); + cursor = 0; +} + +CayenneLPP::~CayenneLPP(void) { free(buffer); } + +void CayenneLPP::reset(void) { cursor = 0; } + +uint8_t CayenneLPP::getSize(void) { return cursor; } + +uint8_t *CayenneLPP::getBuffer(void) { return buffer; } + +void CayenneLPP::addCount(uint16_t value1, uint16_t value2) { + buffer[cursor++] = LPP_COUNT_WIFI_CHANNEL; + buffer[cursor++] = LPP_ANALOG_INPUT; + buffer[cursor++] = value1 >> 8; + buffer[cursor++] = value1; + buffer[cursor++] = LPP_COUNT_BLE_CHANNEL; + buffer[cursor++] = LPP_ANALOG_INPUT; + buffer[cursor++] = value2 >> 8; + buffer[cursor++] = value2; +} + +void CayenneLPP::addGPS(gpsStatus_t value) { + int32_t lat = value.latitude * (int32_t) 10000; + int32_t lon = value.longitude * (int32_t) 10000; + int32_t alt = value.altitude * (int32_t) 100; + + buffer[cursor++] = LPP_GPS_CHANNEL; + buffer[cursor++] = LPP_GPS; + buffer[cursor++] = lat >> 16; + buffer[cursor++] = lat >> 8; + buffer[cursor++] = lat; + buffer[cursor++] = lon >> 16; + buffer[cursor++] = lon >> 8; + buffer[cursor++] = lon; + buffer[cursor++] = alt >> 16; + buffer[cursor++] = alt >> 8; + buffer[cursor++] = alt; +} + +void CayenneLPP::addConfig(configData_t value) { + buffer[cursor++] = LPP_ADR_CHANNEL; + buffer[cursor++] = LPP_DIGITAL_INPUT; + buffer[cursor++] = value.adrmode; +} + +void CayenneLPP::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { + buffer[cursor++] = LPP_BATT_CHANNEL; + buffer[cursor++] = LPP_ANALOG_INPUT; + buffer[cursor++] = voltage >> 8; + buffer[cursor++] = voltage; + + buffer[cursor++] = LPP_TEMP_CHANNEL; + buffer[cursor++] = LPP_TEMPERATURE; + buffer[cursor++] = (uint16_t) cputemp >> 8; + buffer[cursor++] = (uint16_t) cputemp; +} + +#endif // CAYENNE_LPP \ No newline at end of file diff --git a/src/payload.h b/src/payload.h index 03311c76..ae30baf5 100644 --- a/src/payload.h +++ b/src/payload.h @@ -14,11 +14,8 @@ public: uint8_t getSize(void); uint8_t *getBuffer(void); - // application payloads void addCount(uint16_t value1, uint16_t value2); void addGPS(gpsStatus_t value); - - // payloads for get rcommands void addConfig(configData_t value); void addStatus(uint16_t voltage, uint64_t uptime, float cputemp); @@ -37,11 +34,8 @@ public: uint8_t getSize(void); uint8_t *getBuffer(void); - // application payloads void addCount(uint16_t value1, uint16_t value2); void addGPS(gpsStatus_t value); - - // payloads for get rcommands void addConfig(configData_t value); void addStatus(uint16_t voltage, uint64_t uptime, float cputemp); @@ -50,4 +44,41 @@ private: LoraEncoder message(byte *buffer); }; -#endif +#ifdef CAYENNE_LPP +// LPP channels +#define LPP_GPS_CHANNEL 20 +#define LPP_COUNT_WIFI_CHANNEL 21 +#define LPP_COUNT_BLE_CHANNEL 22 +#define LPP_BATT_CHANNEL 23 +#define LPP_ADR_CHANNEL 25 +#define LPP_TEMP_CHANNEL 26 +// LPP types +#define LPP_GPS 136 // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01m +#define LPP_TEMPERATURE 103 // 2 bytes, 0.1°C signed +#define LPP_DIGITAL_INPUT 0 // 1 byte +#define LPP_DIGITAL_OUTPUT 1 // 1 byte +#define LPP_ANALOG_INPUT 2 // 2 bytes, 0.01 signed + +class CayenneLPP { +public: + CayenneLPP(uint8_t size); + ~CayenneLPP(); + + void reset(void); + uint8_t getSize(void); + uint8_t *getBuffer(void); + + void addCount(uint16_t value1, uint16_t value2); + void addGPS(gpsStatus_t value); + void addConfig(configData_t value); + void addStatus(uint16_t voltage, uint64_t uptime, float cputemp); + +private: + uint8_t *buffer; + uint8_t maxsize; + uint8_t cursor; +}; + +#endif // CAYENNE_LPP + +#endif // _PAYLOAD_H_ From 095334a2a600cb2a690c31cb099c17b8f68d6dc4 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 00:05:26 +0200 Subject: [PATCH 08/38] new payload encoder (experimental) --- src/paxcounter.conf | 4 ++-- src/payload.cpp | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/paxcounter.conf b/src/paxcounter.conf index b1c31537..9a122198 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -41,9 +41,9 @@ #define SEND_SECS 30 // [seconds/2] -> 60 sec. #define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle #define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results -#define PAYLOAD_ENCODER 3 // select payload encoder: 1 = Plain [default], 2 = Lora-serialized, 3 = CayenneLPP +#define PAYLOAD_ENCODER 1 // select payload encoder: 1 = Plain [default], 2 = Lora-serialized, 3 = CayenneLPP #define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit -#define CAYENNE_LPP 1 // uncomment this, if you need Cayenne LPP payload encoding +//#define CAYENNE_LPP 1 // uncomment this, if you need Cayenne LPP payload encoding // Default LoRa Spreadfactor #define LORASFDEFAULT 9 // 7 ... 12 SF, according to LoRaWAN specs diff --git a/src/payload.cpp b/src/payload.cpp index f1a9df55..608bc3db 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -81,12 +81,11 @@ void TTNplain::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { TTNserialized::TTNserialized(uint8_t size) { buffer = (uint8_t *)malloc(size); - // LoraEncoder message(buffer); } TTNserialized::~TTNserialized(void) { free(buffer); } -void TTNserialized::reset(void) { delete buffer; } +void TTNserialized::reset(void) { } uint8_t TTNserialized::getSize(void) { return sizeof(buffer); } From 93de42e09b459dadf4a9b5b5093d4446459f6e36 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 00:25:40 +0200 Subject: [PATCH 09/38] payload encoder (experimental) --- src/globals.h | 6 +++++- src/main.cpp | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/globals.h b/src/globals.h index 262fc4c8..be2a175e 100644 --- a/src/globals.h +++ b/src/globals.h @@ -45,6 +45,7 @@ extern gpsStatus_t gps_status; // struct for storing gps data extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe #endif +/* // payload encoder #if (PAYLOAD_ENCODER == 1) extern TTNplain payload; @@ -54,4 +55,7 @@ extern TTNserialized payload; extern CayenneLPP payload; #else #error "No valid payload converter defined" -#endif \ No newline at end of file +#endif +*/ + +extern TTNplain payload; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 025365dd..277a40ef 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,6 +70,7 @@ portMUX_TYPE timerMux = std::set macs; // associative container holds total of unique MAC // adress hashes (Wifi + BLE) +/* // initialize payload encoder #if (PAYLOAD_ENCODER == 1) TTNplain payload(PAYLOAD_BUFFER_SIZE); @@ -80,6 +81,10 @@ CayenneLPP payload(PAYLOAD_BUFFER_SIZE); #else #error "No valid payload converter defined" #endif +*/ + +TTNplain payload(PAYLOAD_BUFFER_SIZE); + // this variables will be changed in the ISR, and read in main loop static volatile int ButtonPressedIRQ = 0, DisplayTimerIRQ = 0, From b47c58436f194d1420232a382b640dce16488cba Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 01:15:02 +0200 Subject: [PATCH 10/38] new payload encoder (experimental) --- src/globals.h | 12 ++++-------- src/main.cpp | 11 +++-------- src/paxcounter.conf | 1 - src/payload.cpp | 6 +----- src/payload.h | 31 ++++++++++++++----------------- 5 files changed, 22 insertions(+), 39 deletions(-) diff --git a/src/globals.h b/src/globals.h index be2a175e..a0473663 100644 --- a/src/globals.h +++ b/src/globals.h @@ -45,17 +45,13 @@ extern gpsStatus_t gps_status; // struct for storing gps data extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe #endif -/* // payload encoder -#if (PAYLOAD_ENCODER == 1) +#if PAYLOAD_ENCODER == 1 extern TTNplain payload; -#elif (PAYLOAD_ENCODER == 2) +#elif PAYLOAD_ENCODER == 2 extern TTNserialized payload; -#elif (PAYLOAD_ENCODER == 3) +#elif PAYLOAD_ENCODER == 3 extern CayenneLPP payload; #else #error "No valid payload converter defined" -#endif -*/ - -extern TTNplain payload; \ No newline at end of file +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 277a40ef..ac5588fa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -70,21 +70,16 @@ portMUX_TYPE timerMux = std::set macs; // associative container holds total of unique MAC // adress hashes (Wifi + BLE) -/* // initialize payload encoder -#if (PAYLOAD_ENCODER == 1) +#if PAYLOAD_ENCODER == 1 TTNplain payload(PAYLOAD_BUFFER_SIZE); -#elif (PAYLOAD_ENCODER == 2) +#elif PAYLOAD_ENCODER == 2 TTNserialized payload(PAYLOAD_BUFFER_SIZE); -#elif (PAYLOAD_ENCODER == 3) +#elif PAYLOAD_ENCODER == 3 CayenneLPP payload(PAYLOAD_BUFFER_SIZE); #else #error "No valid payload converter defined" #endif -*/ - -TTNplain payload(PAYLOAD_BUFFER_SIZE); - // this variables will be changed in the ISR, and read in main loop static volatile int ButtonPressedIRQ = 0, DisplayTimerIRQ = 0, diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 9a122198..c15f8db4 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -43,7 +43,6 @@ #define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results #define PAYLOAD_ENCODER 1 // select payload encoder: 1 = Plain [default], 2 = Lora-serialized, 3 = CayenneLPP #define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit -//#define CAYENNE_LPP 1 // uncomment this, if you need Cayenne LPP payload encoding // Default LoRa Spreadfactor #define LORASFDEFAULT 9 // 7 ... 12 SF, according to LoRaWAN specs diff --git a/src/payload.cpp b/src/payload.cpp index 608bc3db..60fb217f 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -130,8 +130,6 @@ void TTNserialized::addStatus(uint16_t voltage, uint64_t uptime, /* ---------------- Cayenne LPP format ---------- */ -#ifdef CAYENNE_LPP - CayenneLPP::CayenneLPP(uint8_t size) { buffer = (uint8_t *)malloc(size); cursor = 0; @@ -190,6 +188,4 @@ void CayenneLPP::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { buffer[cursor++] = LPP_TEMPERATURE; buffer[cursor++] = (uint16_t) cputemp >> 8; buffer[cursor++] = (uint16_t) cputemp; -} - -#endif // CAYENNE_LPP \ No newline at end of file +} \ No newline at end of file diff --git a/src/payload.h b/src/payload.h index ae30baf5..41865006 100644 --- a/src/payload.h +++ b/src/payload.h @@ -5,6 +5,20 @@ #include #include "LoraEncoder.h" +// MyDevices CayenneLPP channels +#define LPP_GPS_CHANNEL 20 +#define LPP_COUNT_WIFI_CHANNEL 21 +#define LPP_COUNT_BLE_CHANNEL 22 +#define LPP_BATT_CHANNEL 23 +#define LPP_ADR_CHANNEL 25 +#define LPP_TEMP_CHANNEL 26 +// MyDevices CayenneLPP types +#define LPP_GPS 136 // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01m +#define LPP_TEMPERATURE 103 // 2 bytes, 0.1°C signed +#define LPP_DIGITAL_INPUT 0 // 1 byte +#define LPP_DIGITAL_OUTPUT 1 // 1 byte +#define LPP_ANALOG_INPUT 2 // 2 bytes, 0.01 signed + class TTNplain { public: TTNplain(uint8_t size); @@ -44,21 +58,6 @@ private: LoraEncoder message(byte *buffer); }; -#ifdef CAYENNE_LPP -// LPP channels -#define LPP_GPS_CHANNEL 20 -#define LPP_COUNT_WIFI_CHANNEL 21 -#define LPP_COUNT_BLE_CHANNEL 22 -#define LPP_BATT_CHANNEL 23 -#define LPP_ADR_CHANNEL 25 -#define LPP_TEMP_CHANNEL 26 -// LPP types -#define LPP_GPS 136 // 3 byte lon/lat 0.0001 °, 3 bytes alt 0.01m -#define LPP_TEMPERATURE 103 // 2 bytes, 0.1°C signed -#define LPP_DIGITAL_INPUT 0 // 1 byte -#define LPP_DIGITAL_OUTPUT 1 // 1 byte -#define LPP_ANALOG_INPUT 2 // 2 bytes, 0.01 signed - class CayenneLPP { public: CayenneLPP(uint8_t size); @@ -79,6 +78,4 @@ private: uint8_t cursor; }; -#endif // CAYENNE_LPP - #endif // _PAYLOAD_H_ From 013222ed7322af06333ee8c82676bbaf6da796c9 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 11:07:29 +0200 Subject: [PATCH 11/38] Cayenne LPP payload added (experimental) --- src/lorawan.cpp | 7 +------ src/main.cpp | 4 ++-- src/paxcounter.conf | 2 +- src/payload.cpp | 22 +++++++++------------- src/payload.h | 1 + 5 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 69003d9c..0000c618 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -119,12 +119,7 @@ void do_send(osjob_t *j) { // Prepare payload with counter and, if applicable, gps data payload.reset(); - - if (cfg.blescan) { - payload.addCount(macs_wifi, macs_ble); - } else { - payload.addCount(macs_wifi, 0); - } + payload.addCount(macs_wifi, cfg.blescan ? macs_ble : 0); #ifdef HAS_GPS if ((cfg.gpsmode) && (gps.location.isValid())) { diff --git a/src/main.cpp b/src/main.cpp index ac5588fa..3ed2cc8a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -692,8 +692,8 @@ void loop() { gps_read(); ESP_LOGI(TAG, "lat=%.6f | lon=%.6f | %u Sats | HDOP=%.1f | Altitude=%um", - gps_status.latitude / (float)1000000, - gps_status.longitude / (float)1000000, gps_status.satellites, + gps_status.latitude / (float)1e6, + gps_status.longitude / (float)1e6, gps_status.satellites, gps_status.hdop / (float)100, gps_status.altitude); } else { ESP_LOGI(TAG, "No valid GPS position or GPS disabled"); diff --git a/src/paxcounter.conf b/src/paxcounter.conf index c15f8db4..990b0e81 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -41,7 +41,7 @@ #define SEND_SECS 30 // [seconds/2] -> 60 sec. #define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle #define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results -#define PAYLOAD_ENCODER 1 // select payload encoder: 1 = Plain [default], 2 = Lora-serialized, 3 = CayenneLPP +#define PAYLOAD_ENCODER 3 // select payload encoder: 1 = Plain [default], 2 = Lora-serialized, 3 = CayenneLPP #define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit // Default LoRa Spreadfactor diff --git a/src/payload.cpp b/src/payload.cpp index 60fb217f..b1031295 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -79,13 +79,11 @@ void TTNplain::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { /* ---------------- packed format with LoRa serialization Encoder ---------- */ -TTNserialized::TTNserialized(uint8_t size) { - buffer = (uint8_t *)malloc(size); -} +TTNserialized::TTNserialized(uint8_t size) { buffer = (uint8_t *)malloc(size); } TTNserialized::~TTNserialized(void) { free(buffer); } -void TTNserialized::reset(void) { } +void TTNserialized::reset(void) { } // buggy! to be done, we need to clear the buffer here, but how? uint8_t TTNserialized::getSize(void) { return sizeof(buffer); } @@ -145,20 +143,19 @@ uint8_t *CayenneLPP::getBuffer(void) { return buffer; } void CayenneLPP::addCount(uint16_t value1, uint16_t value2) { buffer[cursor++] = LPP_COUNT_WIFI_CHANNEL; - buffer[cursor++] = LPP_ANALOG_INPUT; + buffer[cursor++] = LPP_LUMINOSITY; // workaround, type meter not found? buffer[cursor++] = value1 >> 8; buffer[cursor++] = value1; buffer[cursor++] = LPP_COUNT_BLE_CHANNEL; - buffer[cursor++] = LPP_ANALOG_INPUT; + buffer[cursor++] = LPP_LUMINOSITY; // workaround, type meter not found? buffer[cursor++] = value2 >> 8; buffer[cursor++] = value2; } void CayenneLPP::addGPS(gpsStatus_t value) { - int32_t lat = value.latitude * (int32_t) 10000; - int32_t lon = value.longitude * (int32_t) 10000; - int32_t alt = value.altitude * (int32_t) 100; - + int32_t lat = value.latitude / 100; + int32_t lon = value.longitude / 100; + int32_t alt = value.altitude; buffer[cursor++] = LPP_GPS_CHANNEL; buffer[cursor++] = LPP_GPS; buffer[cursor++] = lat >> 16; @@ -183,9 +180,8 @@ void CayenneLPP::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { buffer[cursor++] = LPP_ANALOG_INPUT; buffer[cursor++] = voltage >> 8; buffer[cursor++] = voltage; - buffer[cursor++] = LPP_TEMP_CHANNEL; buffer[cursor++] = LPP_TEMPERATURE; - buffer[cursor++] = (uint16_t) cputemp >> 8; - buffer[cursor++] = (uint16_t) cputemp; + buffer[cursor++] = (uint16_t)cputemp >> 8; + buffer[cursor++] = (uint16_t)cputemp; } \ No newline at end of file diff --git a/src/payload.h b/src/payload.h index 41865006..7e372702 100644 --- a/src/payload.h +++ b/src/payload.h @@ -18,6 +18,7 @@ #define LPP_DIGITAL_INPUT 0 // 1 byte #define LPP_DIGITAL_OUTPUT 1 // 1 byte #define LPP_ANALOG_INPUT 2 // 2 bytes, 0.01 signed +#define LPP_LUMINOSITY 101 // 2 bytes, 1 lux unsigned class TTNplain { public: From ce43bfd139f8d05c107f3931d2848a41748cfa15 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 11:40:52 +0200 Subject: [PATCH 12/38] compile feature list enhanced --- src/main.cpp | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 3ed2cc8a..ac1d5684 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -468,6 +468,7 @@ void led_loop() { * ------------------------------------------------------------ */ void setup() { + char features[64] = ""; // disable brownout detection @@ -517,24 +518,24 @@ void setup() { // initialize led if needed #if (HAS_LED != NOT_A_PIN) pinMode(HAS_LED, OUTPUT); - strcat(features, " LED"); + strcat_P(features, " LED"); #endif #ifdef HAS_RGB_LED rgb_set_color(COLOR_PINK); - strcat(features, " RGB"); + strcat_P(features, " RGB"); #endif // initialize button handling if needed #ifdef HAS_BUTTON - strcat(features, " BTN_"); + strcat_P(features, " BTN_"); #ifdef BUTTON_PULLUP - strcat(features, "PU"); + strcat_P(features, "PU"); // install button interrupt (pullup mode) pinMode(HAS_BUTTON, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, RISING); #else - strcat(features, "PD"); + strcat_P(features, "PD"); // install button interrupt (pulldown mode) pinMode(HAS_BUTTON, INPUT_PULLDOWN); attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, FALLING); @@ -543,17 +544,17 @@ void setup() { // initialize wifi antenna if needed #ifdef HAS_ANTENNA_SWITCH - strcat(features, " ANT"); + strcat_P(features, " ANT"); antenna_init(); #endif // initialize gps if present #ifdef HAS_GPS - strcat(features, " GPS"); + strcat_P(features, " GPS"); #endif #ifdef HAS_DISPLAY - strcat(features, " OLED"); + strcat_P(features, " OLED"); // initialize display init_display(PROGNAME, PROGVERSION); DisplayState = cfg.screenon; @@ -589,8 +590,17 @@ void setup() { timerAlarmWrite(channelSwitch, cfg.wifichancycle * 10000, true); timerAlarmEnable(channelSwitch); +// show payload encoder +#if PAYLOAD_ENCODER == 1 + strcat_P(features, " PAYLOAD_PLAIN"); +#elif PAYLOAD_ENCODER == 2 + strcat_P(features, " PAYLOAD_SERIALIZED"); +#elif PAYLOAD_ENCODER == 3 + strcat_P(features, " PAYLOAD_CAYENNE"); +#endif + // show compiled features - ESP_LOGI(TAG, "Features %s", features); + ESP_LOGI(TAG, "Features: %s", features); // output LoRaWAN keys to console #ifdef VERBOSE @@ -630,8 +640,7 @@ void setup() { } #endif -// if device has GPS and GPS function is enabled, start GPS reader task on core -// 0 +// if device has GPS and it is enabled, start GPS reader task on core 0 #ifdef HAS_GPS if (cfg.gpsmode) { ESP_LOGI(TAG, "Starting GPS task on core 0"); @@ -639,8 +648,7 @@ void setup() { } #endif - // kickoff sendjob -> joins network and rescedules sendjob for cyclic - // transmitting payload + // joins network and rescedules sendjob for cyclic transmitting payload do_send(&sendjob); } From 87910492e08b5e8a867e6a5e3e7d71a2d4e0739d Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 13:24:20 +0200 Subject: [PATCH 13/38] payload encoder fixes (experimental) --- src/TTN/plain_converter.js | 18 ++++ src/TTN/plain_decoder.js | 23 +++++ src/TTN/serialized_converter.js | 13 +++ src/TTN/serialized_decoder.js | 162 ++++++++++++++++++++++++++++++++ src/paxcounter.conf | 6 +- src/payload.cpp | 14 ++- 6 files changed, 228 insertions(+), 8 deletions(-) create mode 100644 src/TTN/plain_converter.js create mode 100644 src/TTN/plain_decoder.js create mode 100644 src/TTN/serialized_converter.js create mode 100644 src/TTN/serialized_decoder.js diff --git a/src/TTN/plain_converter.js b/src/TTN/plain_converter.js new file mode 100644 index 00000000..1302d56c --- /dev/null +++ b/src/TTN/plain_converter.js @@ -0,0 +1,18 @@ +// Converter for device payload encoder "PLAIN" +// copy&paste to TTN Console -> Applications -> PayloadFormat -> Converter + +function Converter(decoded, port) { + + var converted = decoded; + + if (port === 1) { + converted.pax = converted.ble + converted.wifi; + if (converted.hdop) { + converted.hdop /= 100; + converted.latitude /= 1000000; + converted.longitude /= 1000000; + } + } + + return converted; +} \ No newline at end of file diff --git a/src/TTN/plain_decoder.js b/src/TTN/plain_decoder.js new file mode 100644 index 00000000..9f2768c6 --- /dev/null +++ b/src/TTN/plain_decoder.js @@ -0,0 +1,23 @@ +// Decoder for device payload encoder "PLAIN" +// copy&paste to TTN Console -> Applications -> PayloadFormat -> Decoder + +function Decoder(bytes, port) { + var decoded = {}; + + if (port === 1) { + var i = 0; + + decoded.wifi = (bytes[i++] << 8) | bytes[i++]; + decoded.ble = (bytes[i++] << 8) | bytes[i++]; + + if (bytes.length > 4) { + decoded.latitude = ((bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++]); + decoded.longitude = ((bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++]); + decoded.sats = (bytes[i++]); + decoded.hdop = (bytes[i++] << 8) | (bytes[i++]); + decoded.altitude = (bytes[i++] << 8) | (bytes[i++]); + } + } + + return decoded; +} \ No newline at end of file diff --git a/src/TTN/serialized_converter.js b/src/TTN/serialized_converter.js new file mode 100644 index 00000000..d9f3a79a --- /dev/null +++ b/src/TTN/serialized_converter.js @@ -0,0 +1,13 @@ +// Converter for device payload encoder "SERIALIZED" +// copy&paste to TTN Console -> Applications -> PayloadFormat -> Converter + +function Converter(decoded, port) { + + var converted = decoded; + + if (port === 1) { + converted.pax = converted.ble + converted.wifi; + } + + return converted; +} \ No newline at end of file diff --git a/src/TTN/serialized_decoder.js b/src/TTN/serialized_decoder.js new file mode 100644 index 00000000..d928f031 --- /dev/null +++ b/src/TTN/serialized_decoder.js @@ -0,0 +1,162 @@ +// Decoder for device payload encoder "SERIALIZED" +// copy&paste to TTN Console -> Applications -> PayloadFormat -> Decoder + +function Decoder(bytes, port) { + + var decoded = {}; + + if (port === 1) { + // only counter data, no gps + if (bytes.length == 4) { + return decode(bytes, [uint16, uint16], ['wifi', 'ble']); + } + // combined counter and gps data + if (bytes.length > 4) { + return decode(bytes, [uint16, uint16, latlng, uint8, uint16, uint16], ['wifi', 'ble', 'coords', 'sats', 'hdop', 'altitude']); + } + } + + if (port === 2) { + // device status data + if (bytes.length == 10) { + return decode(bytes, [uint16, unixtime, temperature], ['voltage', 'uptime', 'cputemp']); + } + // device config data + if (bytes.length == 8) { + return decode(bytes, [uint8, uint16, uint8, uint8, uint8, bitmap], ['lorasf', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags']); + } + } + +} + + +// ----- contents of /src/decoder.js -------------------------------------------- +// https://github.com/thesolarnomad/lora-serialization/blob/master/src/decoder.js + +var bytesToInt = function (bytes) { + var i = 0; + for (var x = 0; x < bytes.length; x++) { + i |= +(bytes[x] << (x * 8)); + } + return i; +}; + +var unixtime = function (bytes) { + if (bytes.length !== unixtime.BYTES) { + throw new Error('Unix time must have exactly 4 bytes'); + } + return bytesToInt(bytes); +}; +unixtime.BYTES = 4; + +var uint8 = function (bytes) { + if (bytes.length !== uint8.BYTES) { + throw new Error('int must have exactly 1 byte'); + } + return bytesToInt(bytes); +}; +uint8.BYTES = 1; + +var uint16 = function (bytes) { + if (bytes.length !== uint16.BYTES) { + throw new Error('int must have exactly 2 bytes'); + } + return bytesToInt(bytes); +}; +uint16.BYTES = 2; + +var latLng = function (bytes) { + if (bytes.length !== latLng.BYTES) { + throw new Error('Lat/Long must have exactly 8 bytes'); + } + + var lat = bytesToInt(bytes.slice(0, latLng.BYTES / 2)); + var lng = bytesToInt(bytes.slice(latLng.BYTES / 2, latLng.BYTES)); + + return [lat / 1e6, lng / 1e6]; +}; +latLng.BYTES = 8; + +var temperature = function (bytes) { + if (bytes.length !== temperature.BYTES) { + throw new Error('Temperature must have exactly 2 bytes'); + } + var isNegative = bytes[0] & 0x80; + var b = ('00000000' + Number(bytes[0]).toString(2)).slice(-8) + + ('00000000' + Number(bytes[1]).toString(2)).slice(-8); + if (isNegative) { + var arr = b.split('').map(function (x) { return !Number(x); }); + for (var i = arr.length - 1; i > 0; i--) { + arr[i] = !arr[i]; + if (arr[i]) { + break; + } + } + b = arr.map(Number).join(''); + } + var t = parseInt(b, 2); + if (isNegative) { + t = -t; + } + return t / 1e2; +}; +temperature.BYTES = 2; + +var humidity = function (bytes) { + if (bytes.length !== humidity.BYTES) { + throw new Error('Humidity must have exactly 2 bytes'); + } + + var h = bytesToInt(bytes); + return h / 1e2; +}; +humidity.BYTES = 2; + +var bitmap = function (byte) { + if (byte.length !== bitmap.BYTES) { + throw new Error('Bitmap must have exactly 1 byte'); + } + var i = bytesToInt(byte); + var bm = ('00000000' + Number(i).toString(2)).substr(-8).split('').map(Number).map(Boolean); + return ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] + .reduce(function (obj, pos, index) { + obj[pos] = bm[index]; + return obj; + }, {}); +}; +bitmap.BYTES = 1; + +var decode = function (bytes, mask, names) { + + var maskLength = mask.reduce(function (prev, cur) { + return prev + cur.BYTES; + }, 0); + if (bytes.length < maskLength) { + throw new Error('Mask length is ' + maskLength + ' whereas input is ' + bytes.length); + } + + names = names || []; + var offset = 0; + return mask + .map(function (decodeFn) { + var current = bytes.slice(offset, offset += decodeFn.BYTES); + return decodeFn(current); + }) + .reduce(function (prev, cur, idx) { + prev[names[idx] || idx] = cur; + return prev; + }, {}); +}; + +if (typeof module === 'object' && typeof module.exports !== 'undefined') { + module.exports = { + unixtime: unixtime, + uint8: uint8, + uint16: uint16, + temperature: temperature, + humidity: humidity, + latLng: latLng, + bitmap: bitmap, + decode: decode + }; +} \ No newline at end of file diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 990b0e81..0e83789e 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -37,11 +37,11 @@ #define WIFI_CHANNEL_SWITCH_INTERVAL 50 // [seconds/100] -> 0,5 sec. // LoRa payload send cycle --> take care of duty cycle of LoRaWAN network! <-- -//#define SEND_SECS 120 // [seconds/2] -> 240 sec. -#define SEND_SECS 30 // [seconds/2] -> 60 sec. +#define SEND_SECS 120 // [seconds/2] -> 240 sec. +//#define SEND_SECS 30 // [seconds/2] -> 60 sec. #define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle #define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results -#define PAYLOAD_ENCODER 3 // select payload encoder: 1 = Plain [default], 2 = Lora-serialized, 3 = CayenneLPP +#define PAYLOAD_ENCODER 1 // select payload encoder: 1 = Plain [default], 2 = Lora-serialized, 3 = CayenneLPP #define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit // Default LoRa Spreadfactor diff --git a/src/payload.cpp b/src/payload.cpp index b1031295..72c4005e 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -79,11 +79,15 @@ void TTNplain::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { /* ---------------- packed format with LoRa serialization Encoder ---------- */ -TTNserialized::TTNserialized(uint8_t size) { buffer = (uint8_t *)malloc(size); } +TTNserialized::TTNserialized(uint8_t size) { + buffer = (uint8_t *)malloc(size); + //LoraEncoder message(buffer); +} TTNserialized::~TTNserialized(void) { free(buffer); } -void TTNserialized::reset(void) { } // buggy! to be done, we need to clear the buffer here, but how? +void TTNserialized::reset(void) { +} // buggy! to be done, we need to clear the buffer here, but how? uint8_t TTNserialized::getSize(void) { return sizeof(buffer); } @@ -143,12 +147,12 @@ uint8_t *CayenneLPP::getBuffer(void) { return buffer; } void CayenneLPP::addCount(uint16_t value1, uint16_t value2) { buffer[cursor++] = LPP_COUNT_WIFI_CHANNEL; - buffer[cursor++] = LPP_LUMINOSITY; // workaround, type meter not found? + buffer[cursor++] = LPP_ANALOG_INPUT; // workaround, type meter not found? buffer[cursor++] = value1 >> 8; buffer[cursor++] = value1; buffer[cursor++] = LPP_COUNT_BLE_CHANNEL; - buffer[cursor++] = LPP_LUMINOSITY; // workaround, type meter not found? - buffer[cursor++] = value2 >> 8; + buffer[cursor++] = LPP_ANALOG_INPUT; // workaround, type meter not found? + buffer[cursor++] = value1 >> 8; buffer[cursor++] = value2; } From b1de323ed5c834363dc920fc514ffdf678cc1cc2 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 13:31:24 +0200 Subject: [PATCH 14/38] payload encoder fix HAS GPS --- platformio.ini | 4 ++-- src/payload.cpp | 6 ++++++ src/payload.h | 12 +++++++++--- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/platformio.ini b/platformio.ini index 787cf3ae..0caca06f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,8 +15,8 @@ ;env_default = ttgov1 ;env_default = ttgov2 ;env_default = ttgov21 -env_default = ttgobeam -;env_default = lopy +;env_default = ttgobeam +env_default = lopy ;env_default = lopy4 ;env_default = fipy ;env_default = lolin32lite diff --git a/src/payload.cpp b/src/payload.cpp index 72c4005e..54e32398 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -24,6 +24,7 @@ void TTNplain::addCount(uint16_t value1, uint16_t value2) { buffer[cursor++] = value2; } +#ifdef HAS_GPS void TTNplain::addGPS(gpsStatus_t value) { buffer[cursor++] = value.latitude >> 24; buffer[cursor++] = value.latitude >> 16; @@ -39,6 +40,7 @@ void TTNplain::addGPS(gpsStatus_t value) { buffer[cursor++] = value.altitude >> 8; buffer[cursor++] = value.altitude; } +#endif void TTNplain::addConfig(configData_t value) { buffer[cursor++] = value.lorasf; @@ -99,6 +101,7 @@ void TTNserialized::addCount(uint16_t value1, uint16_t value2) { message.writeUint16(value2); } +#ifdef HAS_GPS void TTNserialized::addGPS(gpsStatus_t value) { LoraEncoder message(buffer); message.writeLatLng(value.latitude, value.longitude); @@ -106,6 +109,7 @@ void TTNserialized::addGPS(gpsStatus_t value) { message.writeUint16(value.hdop); message.writeUint16(value.altitude); } +#endif void TTNserialized::addConfig(configData_t value) { LoraEncoder message(buffer); @@ -156,6 +160,7 @@ void CayenneLPP::addCount(uint16_t value1, uint16_t value2) { buffer[cursor++] = value2; } +#ifdef HAS_GPS void CayenneLPP::addGPS(gpsStatus_t value) { int32_t lat = value.latitude / 100; int32_t lon = value.longitude / 100; @@ -172,6 +177,7 @@ void CayenneLPP::addGPS(gpsStatus_t value) { buffer[cursor++] = alt >> 8; buffer[cursor++] = alt; } +#endif void CayenneLPP::addConfig(configData_t value) { buffer[cursor++] = LPP_ADR_CHANNEL; diff --git a/src/payload.h b/src/payload.h index 7e372702..13d3b8e1 100644 --- a/src/payload.h +++ b/src/payload.h @@ -30,9 +30,11 @@ public: uint8_t *getBuffer(void); void addCount(uint16_t value1, uint16_t value2); - void addGPS(gpsStatus_t value); void addConfig(configData_t value); void addStatus(uint16_t voltage, uint64_t uptime, float cputemp); +#ifdef HAS_GPS + void addGPS(gpsStatus_t value); +#endif private: uint8_t *buffer; @@ -50,9 +52,11 @@ public: uint8_t *getBuffer(void); void addCount(uint16_t value1, uint16_t value2); - void addGPS(gpsStatus_t value); void addConfig(configData_t value); void addStatus(uint16_t voltage, uint64_t uptime, float cputemp); +#ifdef HAS_GPS + void addGPS(gpsStatus_t value); +#endif private: uint8_t *buffer; @@ -69,9 +73,11 @@ public: uint8_t *getBuffer(void); void addCount(uint16_t value1, uint16_t value2); - void addGPS(gpsStatus_t value); void addConfig(configData_t value); void addStatus(uint16_t voltage, uint64_t uptime, float cputemp); +#ifdef HAS_GPS + void addGPS(gpsStatus_t value); +#endif private: uint8_t *buffer; From b5f735a6d3842a8e543046e99925d9ee2d90f04d Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 14:01:55 +0200 Subject: [PATCH 15/38] lopy.h + lopy4.h corrected Pytrack settings --- src/hal/lopy.h | 13 +++++++------ src/hal/lopy4.h | 9 +++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/hal/lopy.h b/src/hal/lopy.h index d54004f6..b793cd5c 100644 --- a/src/hal/lopy.h +++ b/src/hal/lopy.h @@ -5,13 +5,14 @@ #define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0 // !!EXPERIMENTAL - not tested yet!! -// uncomment this only if your LoPy lives on a Pytrack expansion board with GPS +// uncomment this only if your LoPy runs on a Pytrack expansion board with GPS // see http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf -//#define HAS_GPS 1 -//#define GPS_I2C_PINS GPIO_NUM_9, GPIO_NUM_8 // SDA, SCL -//#define GPS_I2C_ADDRESS_READ 0x21 -//#define GPS_I2C_ADDRESS_WRITE 0x20 -//#define HAS_BUTTON GPIO_NUM_4 +#define HAS_GPS 1 +#define GPS_I2C_PINS GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) +#define GPS_I2C_ADDRESS_READ 0x21 +#define GPS_I2C_ADDRESS_WRITE 0x20 +#define HAS_BUTTON GPIO_NUM_37 // (P14) +#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown // Hardware pin definitions for Pycom LoPy board #define PIN_SPI_SS GPIO_NUM_17 diff --git a/src/hal/lopy4.h b/src/hal/lopy4.h index 708a861d..52cda735 100644 --- a/src/hal/lopy4.h +++ b/src/hal/lopy4.h @@ -4,14 +4,15 @@ #define HAS_LED NOT_A_PIN // LoPy4 has no on board LED, so we use RGB LED on LoPy4 #define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0 -// !!EXPERIMENTAL - not tested yet!!f -// uncomment this only if your LoPy lives on a Pytrack expansion board with GPS +// !!EXPERIMENTAL - not tested yet!! +// uncomment this only if your LoPy runs on a Pytrack expansion board with GPS // see http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf //#define HAS_GPS 1 -//#define GPS_I2C_PINS GPIO_NUM_9, GPIO_NUM_8 // SDA, SCL +//#define GPS_I2C_PINS GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) //#define GPS_I2C_ADDRESS_READ 0x21 //#define GPS_I2C_ADDRESS_WRITE 0x20 -//#define HAS_BUTTON GPIO_NUM_4 +//#define HAS_BUTTON GPIO_NUM_37 // (P14) +//#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown // Hardware pin definitions for Pycom LoPy4 board #define PIN_SPI_SS GPIO_NUM_18 From 4d56e90ef06a38ba1497cb6bf9a7154cadd1ecd6 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 14:06:14 +0200 Subject: [PATCH 16/38] lopy.h set to default --- src/hal/lopy.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hal/lopy.h b/src/hal/lopy.h index b793cd5c..43a385bd 100644 --- a/src/hal/lopy.h +++ b/src/hal/lopy.h @@ -7,12 +7,12 @@ // !!EXPERIMENTAL - not tested yet!! // uncomment this only if your LoPy runs on a Pytrack expansion board with GPS // see http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf -#define HAS_GPS 1 -#define GPS_I2C_PINS GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) -#define GPS_I2C_ADDRESS_READ 0x21 -#define GPS_I2C_ADDRESS_WRITE 0x20 -#define HAS_BUTTON GPIO_NUM_37 // (P14) -#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown +//#define HAS_GPS 1 +//#define GPS_I2C_PINS GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) +//#define GPS_I2C_ADDRESS_READ 0x21 +//#define GPS_I2C_ADDRESS_WRITE 0x20 +//#define HAS_BUTTON GPIO_NUM_37 // (P14) +#//define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown // Hardware pin definitions for Pycom LoPy board #define PIN_SPI_SS GPIO_NUM_17 From bb37aba2c36dce77ecf170f6cf98328378e305ad Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 14:06:34 +0200 Subject: [PATCH 17/38] lopy.h corrected --- src/hal/lopy.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hal/lopy.h b/src/hal/lopy.h index 43a385bd..4932badb 100644 --- a/src/hal/lopy.h +++ b/src/hal/lopy.h @@ -12,7 +12,7 @@ //#define GPS_I2C_ADDRESS_READ 0x21 //#define GPS_I2C_ADDRESS_WRITE 0x20 //#define HAS_BUTTON GPIO_NUM_37 // (P14) -#//define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown +//define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown // Hardware pin definitions for Pycom LoPy board #define PIN_SPI_SS GPIO_NUM_17 From 85e9368c6e537ae4494b968feada543615a8a963 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 16:25:29 +0200 Subject: [PATCH 18/38] I2C gps testing --- platformio.ini | 6 ++++-- src/gpsread.cpp | 38 +++++++++++++++++++------------------- src/hal/lopy.h | 12 ++++++------ 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/platformio.ini b/platformio.ini index 0caca06f..eb728a80 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,8 +15,8 @@ ;env_default = ttgov1 ;env_default = ttgov2 ;env_default = ttgov21 -;env_default = ttgobeam -env_default = lopy +env_default = ttgobeam +;env_default = lopy ;env_default = lopy4 ;env_default = fipy ;env_default = lolin32lite @@ -143,6 +143,7 @@ upload_speed = 921600 lib_deps = ${common_env_data.lib_deps_all} ${common_env_data.lib_deps_rgbled} + ${common_env_data.lib_deps_gps} build_flags = ${common_env_data.build_flags} -include "src/hal/lopy.h" @@ -157,6 +158,7 @@ upload_speed = 921600 lib_deps = ${common_env_data.lib_deps_all} ${common_env_data.lib_deps_rgbled} + ${common_env_data.lib_deps_gps} build_flags = ${common_env_data.build_flags} -include "src/hal/lopy4.h" diff --git a/src/gpsread.cpp b/src/gpsread.cpp index ebe16999..c32d0094 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -1,6 +1,7 @@ #ifdef HAS_GPS #include "globals.h" +#include // Local logging tag static const char TAG[] = "main"; @@ -22,8 +23,8 @@ void gps_loop(void *pvParameters) { // initialize and, if needed, configure, GPS #if defined GPS_SERIAL HardwareSerial GPS_Serial(1); -#elif defined GPS_I2C - // to be done +#elif defined GPS_QUECTEL_L76 + Wire.begin(GPS_QUECTEL_L76, 400000); // I2C connect to GPS device with 400 #endif while (1) { @@ -44,30 +45,29 @@ void gps_loop(void *pvParameters) { // after GPS function was disabled, close connect to GPS device GPS_Serial.end(); -#elif defined GPS_I2C +#elif defined GPS_QUECTEL_L76 - // I2C connect to GPS device with 100 kHz - Wire.begin(GPS_I2C_PINS, 100000); Wire.beginTransmission(GPS_I2C_ADDRESS_WRITE); - Wire.write(0x00); + Wire.write(0x00); // dummy write to start read + Wire.endTransmission(); - i2c_ret == Wire.beginTransmission(GPS_I2C_ADDRESS_READ); - if (i2c_ret == 0) { // check if device seen on i2c bus - while (cfg.gpsmode) { - // feed GPS decoder with serial NMEA data from GPS device - while (Wire.available()) { - Wire.requestFrom(GPS_I2C_ADDRESS_READ, 255); - gps.encode(Wire.read()); - vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog - } + Wire.beginTransmission(GPS_I2C_ADDRESS_READ); + while (cfg.gpsmode) { + Wire.requestFrom(GPS_I2C_ADDRESS_READ, 32); + while (Wire.available()) { + gps.encode(Wire.read()); + vTaskDelay(500 / portTICK_PERIOD_MS); // polling mode: 500ms sleep } - // after GPS function was disabled, close connect to GPS device - Wire.endTransmission(); - Wire.setClock(400000); // Set back to 400KHz to speed up OLED + ESP_LOGI(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d", + gps.passedChecksum(), gps.failedChecksum(), + gps.sentencesWithFix()); } + // after GPS function was disabled, close connect to GPS device -#endif + Wire.endTransmission(); + +#endif // GPS Type } vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog diff --git a/src/hal/lopy.h b/src/hal/lopy.h index 4932badb..81e8f646 100644 --- a/src/hal/lopy.h +++ b/src/hal/lopy.h @@ -7,12 +7,12 @@ // !!EXPERIMENTAL - not tested yet!! // uncomment this only if your LoPy runs on a Pytrack expansion board with GPS // see http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf -//#define HAS_GPS 1 -//#define GPS_I2C_PINS GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) -//#define GPS_I2C_ADDRESS_READ 0x21 -//#define GPS_I2C_ADDRESS_WRITE 0x20 -//#define HAS_BUTTON GPIO_NUM_37 // (P14) -//define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown +#define HAS_GPS 1 +#define GPS_QUECTEL_L76 GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) +#define GPS_I2C_ADDRESS_READ 0x21 +#define GPS_I2C_ADDRESS_WRITE 0x20 +#define HAS_BUTTON GPIO_NUM_37 // (P14) +#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown // Hardware pin definitions for Pycom LoPy board #define PIN_SPI_SS GPIO_NUM_17 From 500d7dd6564ff1ba8d41f6797358b58027040dd4 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 16:26:36 +0200 Subject: [PATCH 19/38] I2C gps testing --- src/hal/lopy.h | 12 ++++++------ src/hal/lopy4.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/hal/lopy.h b/src/hal/lopy.h index 81e8f646..2ddf38bc 100644 --- a/src/hal/lopy.h +++ b/src/hal/lopy.h @@ -7,12 +7,12 @@ // !!EXPERIMENTAL - not tested yet!! // uncomment this only if your LoPy runs on a Pytrack expansion board with GPS // see http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf -#define HAS_GPS 1 -#define GPS_QUECTEL_L76 GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) -#define GPS_I2C_ADDRESS_READ 0x21 -#define GPS_I2C_ADDRESS_WRITE 0x20 -#define HAS_BUTTON GPIO_NUM_37 // (P14) -#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown +//#define HAS_GPS 1 +//#define GPS_QUECTEL_L76 GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) +//#define GPS_I2C_ADDRESS_READ 0x21 +//#define GPS_I2C_ADDRESS_WRITE 0x20 +//#define HAS_BUTTON GPIO_NUM_37 // (P14) +//#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown // Hardware pin definitions for Pycom LoPy board #define PIN_SPI_SS GPIO_NUM_17 diff --git a/src/hal/lopy4.h b/src/hal/lopy4.h index 52cda735..589f7f02 100644 --- a/src/hal/lopy4.h +++ b/src/hal/lopy4.h @@ -8,7 +8,7 @@ // uncomment this only if your LoPy runs on a Pytrack expansion board with GPS // see http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf //#define HAS_GPS 1 -//#define GPS_I2C_PINS GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) +//#define GPS_QUECTEL_L76 GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) //#define GPS_I2C_ADDRESS_READ 0x21 //#define GPS_I2C_ADDRESS_WRITE 0x20 //#define HAS_BUTTON GPIO_NUM_37 // (P14) From 706f90453fc3fb25929cab2bd18b3e5f430827b6 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 19:03:49 +0200 Subject: [PATCH 20/38] i2c gps read fixes --- platformio.ini | 4 ++-- src/gpsread.cpp | 10 +++++----- src/hal/lopy.h | 3 +-- src/hal/lopy4.h | 3 +-- 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/platformio.ini b/platformio.ini index eb728a80..b2181971 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,11 +11,11 @@ ; ---> SELECT TARGET PLATFORM HERE! <--- [platformio] -;env_default = heltec +env_default = heltec ;env_default = ttgov1 ;env_default = ttgov2 ;env_default = ttgov21 -env_default = ttgobeam +;env_default = ttgobeam ;env_default = lopy ;env_default = lopy4 ;env_default = fipy diff --git a/src/gpsread.cpp b/src/gpsread.cpp index c32d0094..d0cab92c 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -24,7 +24,7 @@ void gps_loop(void *pvParameters) { #if defined GPS_SERIAL HardwareSerial GPS_Serial(1); #elif defined GPS_QUECTEL_L76 - Wire.begin(GPS_QUECTEL_L76, 400000); // I2C connect to GPS device with 400 + Wire.begin(GPS_QUECTEL_L76, 400000); // I2C connect to GPS device with 400 KHz #endif while (1) { @@ -47,16 +47,16 @@ void gps_loop(void *pvParameters) { #elif defined GPS_QUECTEL_L76 - Wire.beginTransmission(GPS_I2C_ADDRESS_WRITE); + Wire.beginTransmission(GPS_ADDR); Wire.write(0x00); // dummy write to start read Wire.endTransmission(); - Wire.beginTransmission(GPS_I2C_ADDRESS_READ); + Wire.beginTransmission(GPS_ADDR); while (cfg.gpsmode) { - Wire.requestFrom(GPS_I2C_ADDRESS_READ, 32); + Wire.requestFrom(GPS_ADDR | 0x01, 32); while (Wire.available()) { gps.encode(Wire.read()); - vTaskDelay(500 / portTICK_PERIOD_MS); // polling mode: 500ms sleep + vTaskDelay(1 / portTICK_PERIOD_MS); // polling mode: 500ms sleep } ESP_LOGI(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d", diff --git a/src/hal/lopy.h b/src/hal/lopy.h index 2ddf38bc..d9d4068d 100644 --- a/src/hal/lopy.h +++ b/src/hal/lopy.h @@ -9,8 +9,7 @@ // see http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf //#define HAS_GPS 1 //#define GPS_QUECTEL_L76 GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) -//#define GPS_I2C_ADDRESS_READ 0x21 -//#define GPS_I2C_ADDRESS_WRITE 0x20 +//#define GPS_ADDR 0x10 //#define HAS_BUTTON GPIO_NUM_37 // (P14) //#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown diff --git a/src/hal/lopy4.h b/src/hal/lopy4.h index 589f7f02..e5481f12 100644 --- a/src/hal/lopy4.h +++ b/src/hal/lopy4.h @@ -9,8 +9,7 @@ // see http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf //#define HAS_GPS 1 //#define GPS_QUECTEL_L76 GPIO_NUM_25, GPIO_NUM_26 // SDA (P22), SCL (P21) -//#define GPS_I2C_ADDRESS_READ 0x21 -//#define GPS_I2C_ADDRESS_WRITE 0x20 +//#define GPS_ADDR 0x10 //#define HAS_BUTTON GPIO_NUM_37 // (P14) //#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown From a659168fc3d105448eeb183be6cb210c6b9704e7 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 22:41:32 +0200 Subject: [PATCH 21/38] new payload converter TTNpacked --- README.md | 42 +++--- platformio.ini | 7 +- ...lized_converter.js => packed_converter.js} | 2 +- ...erialized_decoder.js => packed_decoder.js} | 2 +- src/globals.h | 2 +- src/main.cpp | 4 +- src/paxcounter.conf | 8 +- src/payload.cpp | 134 +++++++++++++----- src/payload.h | 17 ++- 9 files changed, 145 insertions(+), 73 deletions(-) rename src/TTN/{serialized_converter.js => packed_converter.js} (82%) rename src/TTN/{serialized_decoder.js => packed_decoder.js} (98%) diff --git a/README.md b/README.md index dccacae9..954676c9 100644 --- a/README.md +++ b/README.md @@ -20,23 +20,25 @@ This can all be done with a single small and cheap ESP32 board for less than $20 # Hardware Supported ESP32 based LoRa IoT boards: -- **Heltec LoRa-32** a) -- **TTGOv1** a) -- **TTGOv2** a,d) -- **TTGOv2.1** a),e) -- **TTGO T-Beam** d),e),f) -- **Pycom LoPy** b),f)* -- **Pycom LoPy4** b),f)* -- **Pycom FiPy** b),f)* -- **LoLin32** with [LoraNode32 shield](https://github.com/hallard/LoLin32-Lora) b),c) -- **LoLin32 Lite** with [LoraNode32-Lite shield](https://github.com/hallard/LoLin32-Lite-Lora) b),c) +- **Heltec LoRa-32** +- **TTGOv1** +- **TTGOv2** +- **TTGOv2.1** +- **TTGO T-Beam** +- **Pycom LoPy** +- **Pycom LoPy4** +- **Pycom FiPy** +- **LoLin32** + [LoraNode32 shield](https://github.com/hallard/LoLin32-Lora) +- **LoLin32 Lite** + [LoraNode32-Lite shield](https://github.com/hallard/LoLin32-Lite-Lora) -a) on board OLED Display supported; -b) on board RGB LED supported; -c) on board Hardware unique DEVEUI supported; -d) external wiring needed, see instructions in file /hal/.h; -e) battery voltage monitoring supported; -f) on board GPS supported, *for Pycom devices with additional PyTrack board +Depending on board hardware following features are supported: +- LED +- OLED Display +- RGB LED +- button +- silicon unique ID +- battery voltage monitoring +- GPS Target platform must be selected in [platformio.ini](https://github.com/cyberman54/ESP32-Paxcounter/blob/master/platformio.ini).
Hardware dependent settings (pinout etc.) are stored in board files in /hal directory.
@@ -106,7 +108,13 @@ Legend for RGB LED (LoPy/LoPy4/FiPy/Lolin32 only): # Payload -All data is represented in big-endian-format, as long not otherwise stated. +You can select between different payload formats in [paxcounter.conf](src/paxounter.conf#L40): + +*Plain* generates human readable json fields, e.g. useful for TTN console +*Packed* generates packed json fiels, e.g. useful for own backends +*[CayenneLPP]*(https://mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload-reference-implementation) + +Hereafter described is the *Plain* format. All data is represented in big-endian-format. **LoRaWAN Port #1:** diff --git a/platformio.ini b/platformio.ini index b2181971..459696d9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,11 +11,11 @@ ; ---> SELECT TARGET PLATFORM HERE! <--- [platformio] -env_default = heltec +;env_default = heltec ;env_default = ttgov1 ;env_default = ttgov2 ;env_default = ttgov21 -;env_default = ttgobeam +env_default = ttgobeam ;env_default = lopy ;env_default = lopy4 ;env_default = fipy @@ -27,8 +27,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng [common_env_data] platform_espressif32 = espressif32@>=1.0.2 board_build.partitions = no_ota.csv -lib_deps_all = - LoRa Serialization@>=3.0.0 +;lib_deps_all = lib_deps_display = U8g2@>=2.22.14 lib_deps_rgbled = diff --git a/src/TTN/serialized_converter.js b/src/TTN/packed_converter.js similarity index 82% rename from src/TTN/serialized_converter.js rename to src/TTN/packed_converter.js index d9f3a79a..7c35ad41 100644 --- a/src/TTN/serialized_converter.js +++ b/src/TTN/packed_converter.js @@ -1,4 +1,4 @@ -// Converter for device payload encoder "SERIALIZED" +// Converter for device payload encoder "PACKED" // copy&paste to TTN Console -> Applications -> PayloadFormat -> Converter function Converter(decoded, port) { diff --git a/src/TTN/serialized_decoder.js b/src/TTN/packed_decoder.js similarity index 98% rename from src/TTN/serialized_decoder.js rename to src/TTN/packed_decoder.js index d928f031..f7e06f52 100644 --- a/src/TTN/serialized_decoder.js +++ b/src/TTN/packed_decoder.js @@ -1,4 +1,4 @@ -// Decoder for device payload encoder "SERIALIZED" +// Decoder for device payload encoder "PACKED" // copy&paste to TTN Console -> Applications -> PayloadFormat -> Decoder function Decoder(bytes, port) { diff --git a/src/globals.h b/src/globals.h index a0473663..21c7b1a8 100644 --- a/src/globals.h +++ b/src/globals.h @@ -49,7 +49,7 @@ extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe #if PAYLOAD_ENCODER == 1 extern TTNplain payload; #elif PAYLOAD_ENCODER == 2 -extern TTNserialized payload; +extern TTNpacked payload; #elif PAYLOAD_ENCODER == 3 extern CayenneLPP payload; #else diff --git a/src/main.cpp b/src/main.cpp index ac1d5684..4808e7f7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,7 +74,7 @@ std::set macs; // associative container holds total of unique MAC #if PAYLOAD_ENCODER == 1 TTNplain payload(PAYLOAD_BUFFER_SIZE); #elif PAYLOAD_ENCODER == 2 -TTNserialized payload(PAYLOAD_BUFFER_SIZE); +TTNpacked payload(PAYLOAD_BUFFER_SIZE); #elif PAYLOAD_ENCODER == 3 CayenneLPP payload(PAYLOAD_BUFFER_SIZE); #else @@ -594,7 +594,7 @@ void setup() { #if PAYLOAD_ENCODER == 1 strcat_P(features, " PAYLOAD_PLAIN"); #elif PAYLOAD_ENCODER == 2 - strcat_P(features, " PAYLOAD_SERIALIZED"); + strcat_P(features, " PAYLOAD_PACKED"); #elif PAYLOAD_ENCODER == 3 strcat_P(features, " PAYLOAD_CAYENNE"); #endif diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 0e83789e..9c762a19 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -36,12 +36,12 @@ #define WIFI_MY_COUNTRY "EU" // select locale for Wifi RF settings #define WIFI_CHANNEL_SWITCH_INTERVAL 50 // [seconds/100] -> 0,5 sec. -// LoRa payload send cycle --> take care of duty cycle of LoRaWAN network! <-- -#define SEND_SECS 120 // [seconds/2] -> 240 sec. -//#define SEND_SECS 30 // [seconds/2] -> 60 sec. +// LoRa payload parameters +#define PAYLOAD_ENCODER 2 // select payload encoder: 1=Plain [default], 2=Packed, 3=CayenneLPP +//#define SEND_SECS 120 // payload send cycle [seconds/2] -> 240 sec. +#define SEND_SECS 30 // payload send cycle [seconds/2] -> 60 sec. #define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle #define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results -#define PAYLOAD_ENCODER 1 // select payload encoder: 1 = Plain [default], 2 = Lora-serialized, 3 = CayenneLPP #define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit // Default LoRa Spreadfactor diff --git a/src/payload.cpp b/src/payload.cpp index 54e32398..97d52e66 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -80,58 +80,116 @@ void TTNplain::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { } /* ---------------- packed format with LoRa serialization Encoder ---------- */ +// derived from +// https://github.com/thesolarnomad/lora-serialization/blob/master/src/LoraEncoder.cpp -TTNserialized::TTNserialized(uint8_t size) { - buffer = (uint8_t *)malloc(size); - //LoraEncoder message(buffer); -} +TTNpacked::TTNpacked(uint8_t size) { buffer = (uint8_t *)malloc(size); } -TTNserialized::~TTNserialized(void) { free(buffer); } +TTNpacked::~TTNpacked(void) { free(buffer); } -void TTNserialized::reset(void) { -} // buggy! to be done, we need to clear the buffer here, but how? +void TTNpacked::reset(void) { buffer = 0; } -uint8_t TTNserialized::getSize(void) { return sizeof(buffer); } +uint8_t TTNpacked::getSize(void) { return sizeof(buffer); } -uint8_t *TTNserialized::getBuffer(void) { return buffer; } +uint8_t *TTNpacked::getBuffer(void) { return buffer; } -void TTNserialized::addCount(uint16_t value1, uint16_t value2) { - LoraEncoder message(buffer); - message.writeUint16(value1); - message.writeUint16(value2); +void TTNpacked::addCount(uint16_t value1, uint16_t value2) { + writeUint16(value1); + writeUint16(value2); } #ifdef HAS_GPS -void TTNserialized::addGPS(gpsStatus_t value) { - LoraEncoder message(buffer); - message.writeLatLng(value.latitude, value.longitude); - message.writeUint8(value.satellites); - message.writeUint16(value.hdop); - message.writeUint16(value.altitude); +void TTNpacked::addGPS(gpsStatus_t value) { + writeLatLng(value.latitude, value.longitude); + writeUint8(value.satellites); + writeUint16(value.hdop); + writeUint16(value.altitude); } #endif -void TTNserialized::addConfig(configData_t value) { - LoraEncoder message(buffer); - message.writeUint8(value.lorasf); - message.writeUint16(value.rssilimit); - message.writeUint8(value.sendcycle); - message.writeUint8(value.wifichancycle); - message.writeUint8(value.blescantime); - message.writeUint8(value.rgblum); - message.writeBitmap( - value.adrmode ? true : false, value.screensaver ? true : false, - value.screenon ? true : false, value.countermode ? true : false, - value.blescan ? true : false, value.wifiant ? true : false, - value.vendorfilter ? true : false, value.gpsmode ? true : false); +void TTNpacked::addConfig(configData_t value) { + writeUint8(value.lorasf); + writeUint16(value.rssilimit); + writeUint8(value.sendcycle); + writeUint8(value.wifichancycle); + writeUint8(value.blescantime); + writeUint8(value.rgblum); + writeBitmap(value.adrmode ? true : false, value.screensaver ? true : false, + value.screenon ? true : false, value.countermode ? true : false, + value.blescan ? true : false, value.wifiant ? true : false, + value.vendorfilter ? true : false, value.gpsmode ? true : false); } -void TTNserialized::addStatus(uint16_t voltage, uint64_t uptime, - float cputemp) { - LoraEncoder message(buffer); - message.writeUint16(voltage); - message.writeUnixtime(uptime); - message.writeTemperature(cputemp); +void TTNpacked::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { + writeUint16(voltage); + writeUnixtime(uptime); + writeTemperature(cputemp); +} + +void TTNpacked::_intToBytes(byte *buf, int32_t i, uint8_t byteSize) { + for (uint8_t x = 0; x < byteSize; x++) { + buf[x] = (byte)(i >> (x * 8)); + } +} + +void TTNpacked::writeUnixtime(uint32_t unixtime) { + _intToBytes(buffer, unixtime, 4); + buffer += 4; +} + +void TTNpacked::writeLatLng(double latitude, double longitude) { + int32_t lat = latitude * 1e6; + int32_t lng = longitude * 1e6; + + _intToBytes(buffer, lat, 4); + _intToBytes(buffer + 4, lng, 4); + buffer += 8; +} + +void TTNpacked::writeUint16(uint16_t i) { + _intToBytes(buffer, i, 2); + buffer += 2; +} + +void TTNpacked::writeUint8(uint8_t i) { + _intToBytes(buffer, i, 1); + buffer += 1; +} + +void TTNpacked::writeHumidity(float humidity) { + int16_t h = (int16_t)(humidity * 100); + _intToBytes(buffer, h, 2); + buffer += 2; +} + +/** + * Uses a 16bit two's complement with two decimals, so the range is + * -327.68 to +327.67 degrees + */ +void TTNpacked::writeTemperature(float temperature) { + int16_t t = (int16_t)(temperature * 100); + if (temperature < 0) { + t = ~-t; + t = t + 1; + } + buffer[0] = (byte)((t >> 8) & 0xFF); + buffer[1] = (byte)t & 0xFF; + buffer += 2; +} + +void TTNpacked::writeBitmap(bool a, bool b, bool c, bool d, bool e, bool f, + bool g, bool h) { + uint8_t bitmap = 0; + // LSB first + bitmap |= (a & 1) << 7; + bitmap |= (b & 1) << 6; + bitmap |= (c & 1) << 5; + bitmap |= (d & 1) << 4; + bitmap |= (e & 1) << 3; + bitmap |= (f & 1) << 2; + bitmap |= (g & 1) << 1; + bitmap |= (h & 1) << 0; + writeUint8(bitmap); } /* ---------------- Cayenne LPP format ---------- */ diff --git a/src/payload.h b/src/payload.h index 13d3b8e1..8899c709 100644 --- a/src/payload.h +++ b/src/payload.h @@ -3,7 +3,6 @@ #define _PAYLOAD_H_ #include -#include "LoraEncoder.h" // MyDevices CayenneLPP channels #define LPP_GPS_CHANNEL 20 @@ -42,10 +41,10 @@ private: uint8_t cursor; }; -class TTNserialized { +class TTNpacked { public: - TTNserialized(uint8_t size); - ~TTNserialized(); + TTNpacked(uint8_t size); + ~TTNpacked(); void reset(void); uint8_t getSize(void); @@ -60,7 +59,15 @@ public: private: uint8_t *buffer; - LoraEncoder message(byte *buffer); + void _intToBytes(byte *buf, int32_t i, uint8_t byteSize); + void writeUnixtime(uint32_t unixtime); + void writeLatLng(double latitude, double longitude); + void writeUint16(uint16_t i); + void writeUint8(uint8_t i); + void writeHumidity(float humidity); + void writeTemperature(float temperature); + void writeBitmap(bool a, bool b, bool c, bool d, bool e, bool f, bool g, + bool h); }; class CayenneLPP { From 7edffcc84055a4069f10a44b8e702e81b91ae21f Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 17 Jun 2018 22:45:05 +0200 Subject: [PATCH 22/38] repair platformio.ini --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 459696d9..e84d3d5f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -27,7 +27,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng [common_env_data] platform_espressif32 = espressif32@>=1.0.2 board_build.partitions = no_ota.csv -;lib_deps_all = +lib_deps_all = lib_deps_display = U8g2@>=2.22.14 lib_deps_rgbled = From 3588bb284ca95ec9d49d66356ee256820329b52d Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 18 Jun 2018 00:01:14 +0200 Subject: [PATCH 23/38] packet payload fixes --- src/payload.cpp | 38 ++++++++++++++++++-------------------- src/payload.h | 4 ++-- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/payload.cpp b/src/payload.cpp index 97d52e66..86710382 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -83,13 +83,16 @@ void TTNplain::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { // derived from // https://github.com/thesolarnomad/lora-serialization/blob/master/src/LoraEncoder.cpp -TTNpacked::TTNpacked(uint8_t size) { buffer = (uint8_t *)malloc(size); } +TTNpacked::TTNpacked(uint8_t size) { + buffer = (uint8_t *)malloc(size); + cursor = 0; +} TTNpacked::~TTNpacked(void) { free(buffer); } -void TTNpacked::reset(void) { buffer = 0; } +void TTNpacked::reset(void) { cursor = 0; } -uint8_t TTNpacked::getSize(void) { return sizeof(buffer); } +uint8_t TTNpacked::getSize(void) { return cursor; } uint8_t *TTNpacked::getBuffer(void) { return buffer; } @@ -126,40 +129,35 @@ void TTNpacked::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { writeTemperature(cputemp); } -void TTNpacked::_intToBytes(byte *buf, int32_t i, uint8_t byteSize) { +void TTNpacked::_intToBytes(uint8_t pos, int32_t i, uint8_t byteSize) { for (uint8_t x = 0; x < byteSize; x++) { - buf[x] = (byte)(i >> (x * 8)); + buffer[x + pos] = (byte)(i >> (x * 8)); } + cursor += byteSize; } void TTNpacked::writeUnixtime(uint32_t unixtime) { - _intToBytes(buffer, unixtime, 4); - buffer += 4; + _intToBytes(cursor, unixtime, 4); } void TTNpacked::writeLatLng(double latitude, double longitude) { int32_t lat = latitude * 1e6; int32_t lng = longitude * 1e6; - - _intToBytes(buffer, lat, 4); - _intToBytes(buffer + 4, lng, 4); - buffer += 8; + _intToBytes(cursor, lat, 4); + _intToBytes(cursor, lng, 4); } void TTNpacked::writeUint16(uint16_t i) { - _intToBytes(buffer, i, 2); - buffer += 2; + _intToBytes(cursor, i, 2); } void TTNpacked::writeUint8(uint8_t i) { - _intToBytes(buffer, i, 1); - buffer += 1; + _intToBytes(cursor, i, 1); } void TTNpacked::writeHumidity(float humidity) { int16_t h = (int16_t)(humidity * 100); - _intToBytes(buffer, h, 2); - buffer += 2; + _intToBytes(cursor, h, 2); } /** @@ -172,9 +170,9 @@ void TTNpacked::writeTemperature(float temperature) { t = ~-t; t = t + 1; } - buffer[0] = (byte)((t >> 8) & 0xFF); - buffer[1] = (byte)t & 0xFF; - buffer += 2; + buffer[cursor] = (byte)((t >> 8) & 0xFF); + buffer[cursor+1] = (byte)t & 0xFF; + cursor += 2; } void TTNpacked::writeBitmap(bool a, bool b, bool c, bool d, bool e, bool f, diff --git a/src/payload.h b/src/payload.h index 8899c709..a828b818 100644 --- a/src/payload.h +++ b/src/payload.h @@ -37,7 +37,6 @@ public: private: uint8_t *buffer; - uint8_t maxsize; uint8_t cursor; }; @@ -59,7 +58,8 @@ public: private: uint8_t *buffer; - void _intToBytes(byte *buf, int32_t i, uint8_t byteSize); + uint8_t cursor; + void _intToBytes(uint8_t pos, int32_t i, uint8_t byteSize); void writeUnixtime(uint32_t unixtime); void writeLatLng(double latitude, double longitude); void writeUint16(uint16_t i); From 3da1ddb804540d9753ef85971199520c8822caaa Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 18 Jun 2018 00:06:43 +0200 Subject: [PATCH 24/38] readme.md updated --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 954676c9..6a645a81 100644 --- a/README.md +++ b/README.md @@ -108,11 +108,13 @@ Legend for RGB LED (LoPy/LoPy4/FiPy/Lolin32 only): # Payload -You can select between different payload formats in [paxcounter.conf](src/paxounter.conf#L40): +You can select between different payload formats in [paxcounter.conf](src/paxcounter.conf#L40): -*Plain* generates human readable json fields, e.g. useful for TTN console -*Packed* generates packed json fiels, e.g. useful for own backends -*[CayenneLPP]*(https://mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload-reference-implementation) +- *Plain* generates human readable json fields, e.g. useful for TTN console + +- *Packed* generates packed json fiels, e.g. useful for own backends + +- *[CayenneLPP] (https://mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload-reference-implementation)* generates MyDevices Cayenne readable fields Hereafter described is the *Plain* format. All data is represented in big-endian-format. From 8a3b24a0d23ca372f291ae418cb3b4eeb4783b2f Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 18 Jun 2018 00:08:13 +0200 Subject: [PATCH 25/38] readme.md updated --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6a645a81..0e5ed12b 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ You can select between different payload formats in [paxcounter.conf](src/paxcou - *Packed* generates packed json fiels, e.g. useful for own backends -- *[CayenneLPP] (https://mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload-reference-implementation)* generates MyDevices Cayenne readable fields +- [*CayenneLPP*] (https://mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload-reference-implementation) generates MyDevices Cayenne readable fields Hereafter described is the *Plain* format. All data is represented in big-endian-format. From b69d66d7bc20dcf4c2ebfda9b2b2bc45c77d3f03 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 18 Jun 2018 00:09:21 +0200 Subject: [PATCH 26/38] readme.md updated --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0e5ed12b..5dafcf33 100644 --- a/README.md +++ b/README.md @@ -114,7 +114,7 @@ You can select between different payload formats in [paxcounter.conf](src/paxcou - *Packed* generates packed json fiels, e.g. useful for own backends -- [*CayenneLPP*] (https://mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload-reference-implementation) generates MyDevices Cayenne readable fields +- [*CayenneLPP*](https://mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload-reference-implementation) generates MyDevices Cayenne readable fields Hereafter described is the *Plain* format. All data is represented in big-endian-format. From 8ad8512eb24a9a975b96dae480fbb91f6c19323a Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 18 Jun 2018 00:35:12 +0200 Subject: [PATCH 27/38] packed_decoder.js updated --- src/TTN/packed_decoder.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TTN/packed_decoder.js b/src/TTN/packed_decoder.js index f7e06f52..af28fab4 100644 --- a/src/TTN/packed_decoder.js +++ b/src/TTN/packed_decoder.js @@ -118,7 +118,7 @@ var bitmap = function (byte) { } var i = bytesToInt(byte); var bm = ('00000000' + Number(i).toString(2)).substr(-8).split('').map(Number).map(Boolean); - return ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] + return ['adr', 'screensaver', 'display', 'countermode', 'blescan', 'antenna', 'filter', 'gpsmode'] .reduce(function (obj, pos, index) { obj[pos] = bm[index]; return obj; From f3ca06fa31557b7796ffb222cad761fd87939b24 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 18 Jun 2018 00:39:46 +0200 Subject: [PATCH 28/38] payload.cpp edited --- src/payload.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/payload.cpp b/src/payload.cpp index 86710382..b3b73e18 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -170,9 +170,8 @@ void TTNpacked::writeTemperature(float temperature) { t = ~-t; t = t + 1; } - buffer[cursor] = (byte)((t >> 8) & 0xFF); - buffer[cursor+1] = (byte)t & 0xFF; - cursor += 2; + buffer[cursor++] = (byte)((t >> 8) & 0xFF); + buffer[cursor++] = (byte)t & 0xFF; } void TTNpacked::writeBitmap(bool a, bool b, bool c, bool d, bool e, bool f, From d2739426e58eec371b90b7087ad959983a0196ed Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 18 Jun 2018 09:15:57 +0200 Subject: [PATCH 29/38] payload.cpp fixes --- src/TTN/packed_decoder.js | 16 ++++++++-------- src/gpsread.cpp | 4 ++-- src/payload.cpp | 24 +++++++++--------------- src/payload.h | 4 ++-- 4 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/TTN/packed_decoder.js b/src/TTN/packed_decoder.js index af28fab4..8c469b9b 100644 --- a/src/TTN/packed_decoder.js +++ b/src/TTN/packed_decoder.js @@ -18,12 +18,12 @@ function Decoder(bytes, port) { if (port === 2) { // device status data - if (bytes.length == 10) { - return decode(bytes, [uint16, unixtime, temperature], ['voltage', 'uptime', 'cputemp']); + if (bytes.length == 12) { + return decode(bytes, [uint16, uptime, temperature], ['voltage', 'uptime', 'cputemp']); } // device config data if (bytes.length == 8) { - return decode(bytes, [uint8, uint16, uint8, uint8, uint8, bitmap], ['lorasf', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags']); + return decode(bytes, [uint8, uint16, uint8, uint8, uint8, uint8, bitmap], ['lorasf', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags']); } } @@ -41,13 +41,13 @@ var bytesToInt = function (bytes) { return i; }; -var unixtime = function (bytes) { - if (bytes.length !== unixtime.BYTES) { - throw new Error('Unix time must have exactly 4 bytes'); +var uptime = function (bytes) { + if (bytes.length !== uptime.BYTES) { + throw new Error('uptime must have exactly 8 bytes'); } return bytesToInt(bytes); }; -unixtime.BYTES = 4; +uptime.BYTES = 4; var uint8 = function (bytes) { if (bytes.length !== uint8.BYTES) { @@ -150,7 +150,7 @@ var decode = function (bytes, mask, names) { if (typeof module === 'object' && typeof module.exports !== 'undefined') { module.exports = { - unixtime: unixtime, + uptime: uptime, uint8: uint8, uint16: uint16, temperature: temperature, diff --git a/src/gpsread.cpp b/src/gpsread.cpp index d0cab92c..11a8cf92 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -8,8 +8,8 @@ static const char TAG[] = "main"; // read GPS data and cast to global struct void gps_read() { - gps_status.latitude = (uint32_t)(gps.location.lat() * 1000000); - gps_status.longitude = (uint32_t)(gps.location.lng() * 1000000); + gps_status.latitude = (uint32_t)(gps.location.lat() * 1e6); + gps_status.longitude = (uint32_t)(gps.location.lng() * 1e6); gps_status.satellites = (uint8_t)gps.satellites.value(); gps_status.hdop = (uint16_t)gps.hdop.value(); gps_status.altitude = (uint16_t)gps.altitude.meters(); diff --git a/src/payload.cpp b/src/payload.cpp index b3b73e18..dce09224 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -125,39 +125,33 @@ void TTNpacked::addConfig(configData_t value) { void TTNpacked::addStatus(uint16_t voltage, uint64_t uptime, float cputemp) { writeUint16(voltage); - writeUnixtime(uptime); + writeUptime(uptime); writeTemperature(cputemp); } -void TTNpacked::_intToBytes(uint8_t pos, int32_t i, uint8_t byteSize) { +void TTNpacked::intToBytes(uint8_t pos, int32_t i, uint8_t byteSize) { for (uint8_t x = 0; x < byteSize; x++) { buffer[x + pos] = (byte)(i >> (x * 8)); } cursor += byteSize; } -void TTNpacked::writeUnixtime(uint32_t unixtime) { - _intToBytes(cursor, unixtime, 4); +void TTNpacked::writeUptime(uint64_t uptime) { + intToBytes(cursor, uptime, 8); } void TTNpacked::writeLatLng(double latitude, double longitude) { - int32_t lat = latitude * 1e6; - int32_t lng = longitude * 1e6; - _intToBytes(cursor, lat, 4); - _intToBytes(cursor, lng, 4); + intToBytes(cursor, latitude, 4); + intToBytes(cursor, longitude, 4); } -void TTNpacked::writeUint16(uint16_t i) { - _intToBytes(cursor, i, 2); -} +void TTNpacked::writeUint16(uint16_t i) { intToBytes(cursor, i, 2); } -void TTNpacked::writeUint8(uint8_t i) { - _intToBytes(cursor, i, 1); -} +void TTNpacked::writeUint8(uint8_t i) { intToBytes(cursor, i, 1); } void TTNpacked::writeHumidity(float humidity) { int16_t h = (int16_t)(humidity * 100); - _intToBytes(cursor, h, 2); + intToBytes(cursor, h, 2); } /** diff --git a/src/payload.h b/src/payload.h index a828b818..53cda054 100644 --- a/src/payload.h +++ b/src/payload.h @@ -59,8 +59,8 @@ public: private: uint8_t *buffer; uint8_t cursor; - void _intToBytes(uint8_t pos, int32_t i, uint8_t byteSize); - void writeUnixtime(uint32_t unixtime); + void intToBytes(uint8_t pos, int32_t i, uint8_t byteSize); + void writeUptime(uint64_t unixtime); void writeLatLng(double latitude, double longitude); void writeUint16(uint16_t i); void writeUint8(uint8_t i); From d6dc4040834bbe8f024fa60b9bc1f8a6655dfd34 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 18 Jun 2018 13:13:13 +0200 Subject: [PATCH 30/38] finalizing v1.3.82 --- README.md | 10 ++++++---- platformio.ini | 4 ++-- src/TTN/packed_decoder.js | 31 ++++++++++++++++++------------- src/paxcounter.conf | 5 ++--- 4 files changed, 28 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 5dafcf33..4815091f 100644 --- a/README.md +++ b/README.md @@ -110,13 +110,13 @@ Legend for RGB LED (LoPy/LoPy4/FiPy/Lolin32 only): You can select between different payload formats in [paxcounter.conf](src/paxcounter.conf#L40): -- *Plain* generates human readable json fields, e.g. useful for TTN console +- ***Plain*** uses big endian format and generates json fields, e.g. useful for TTN console -- *Packed* generates packed json fiels, e.g. useful for own backends +- ***Packed*** uses little endian format and generates json fields -- [*CayenneLPP*](https://mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload-reference-implementation) generates MyDevices Cayenne readable fields +- [***CayenneLPP***](https://mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload-reference-implementation) generates MyDevices Cayenne readable fields -Hereafter described is the *Plain* format. All data is represented in big-endian-format. +Hereafter described is the default *Plain* format. **LoRaWAN Port #1:** @@ -144,6 +144,8 @@ To map a GPS capable paxcounter device and at the same time contribute to TTN co **Decoder:** ```javascript + + function Decoder(bytes, port) { var decoded = {}; diff --git a/platformio.ini b/platformio.ini index e84d3d5f..75d57140 100644 --- a/platformio.ini +++ b/platformio.ini @@ -11,11 +11,11 @@ ; ---> SELECT TARGET PLATFORM HERE! <--- [platformio] -;env_default = heltec +env_default = heltec ;env_default = ttgov1 ;env_default = ttgov2 ;env_default = ttgov21 -env_default = ttgobeam +;env_default = ttgobeam ;env_default = lopy ;env_default = lopy4 ;env_default = fipy diff --git a/src/TTN/packed_decoder.js b/src/TTN/packed_decoder.js index 8c469b9b..d6f43ed0 100644 --- a/src/TTN/packed_decoder.js +++ b/src/TTN/packed_decoder.js @@ -7,22 +7,22 @@ function Decoder(bytes, port) { if (port === 1) { // only counter data, no gps - if (bytes.length == 4) { + if (bytes.length === 4) { return decode(bytes, [uint16, uint16], ['wifi', 'ble']); } // combined counter and gps data - if (bytes.length > 4) { - return decode(bytes, [uint16, uint16, latlng, uint8, uint16, uint16], ['wifi', 'ble', 'coords', 'sats', 'hdop', 'altitude']); + if (bytes.length === 17) { + return decode(bytes, [uint16, uint16, latLng, latLng, uint8, hdop, uint16], ['wifi', 'ble', 'latitude', 'longitude', 'sats', 'hdop', 'altitude']); } } if (port === 2) { // device status data - if (bytes.length == 12) { + if (bytes.length === 12) { return decode(bytes, [uint16, uptime, temperature], ['voltage', 'uptime', 'cputemp']); } // device config data - if (bytes.length == 8) { + if (bytes.length === 8) { return decode(bytes, [uint8, uint16, uint8, uint8, uint8, uint8, bitmap], ['lorasf', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags']); } } @@ -67,15 +67,19 @@ uint16.BYTES = 2; var latLng = function (bytes) { if (bytes.length !== latLng.BYTES) { - throw new Error('Lat/Long must have exactly 8 bytes'); + throw new Error('Lat/Long must have exactly 4 bytes'); } - - var lat = bytesToInt(bytes.slice(0, latLng.BYTES / 2)); - var lng = bytesToInt(bytes.slice(latLng.BYTES / 2, latLng.BYTES)); - - return [lat / 1e6, lng / 1e6]; + return bytesToInt(bytes) / 1e6; }; -latLng.BYTES = 8; +latLng.BYTES = 4; + +var hdop = function (bytes) { + if (bytes.length !== hdop.BYTES) { + throw new Error('hdop must have exactly 2 bytes'); + } + return bytesToInt(bytes) / 100; +}; +hdop.BYTES = 2; var temperature = function (bytes) { if (bytes.length !== temperature.BYTES) { @@ -118,7 +122,7 @@ var bitmap = function (byte) { } var i = bytesToInt(byte); var bm = ('00000000' + Number(i).toString(2)).substr(-8).split('').map(Number).map(Boolean); - return ['adr', 'screensaver', 'display', 'countermode', 'blescan', 'antenna', 'filter', 'gpsmode'] + return ['adr', 'screensaver', 'screen', 'countermode', 'blescan', 'antenna', 'filter', 'gpsmode'] .reduce(function (obj, pos, index) { obj[pos] = bm[index]; return obj; @@ -156,6 +160,7 @@ if (typeof module === 'object' && typeof module.exports !== 'undefined') { temperature: temperature, humidity: humidity, latLng: latLng, + hdop: hdop, bitmap: bitmap, decode: decode }; diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 9c762a19..357ed009 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -37,9 +37,8 @@ #define WIFI_CHANNEL_SWITCH_INTERVAL 50 // [seconds/100] -> 0,5 sec. // LoRa payload parameters -#define PAYLOAD_ENCODER 2 // select payload encoder: 1=Plain [default], 2=Packed, 3=CayenneLPP -//#define SEND_SECS 120 // payload send cycle [seconds/2] -> 240 sec. -#define SEND_SECS 30 // payload send cycle [seconds/2] -> 60 sec. +#define PAYLOAD_ENCODER 1 // select payload encoder: 1=Plain [default], 2=Packed, 3=CayenneLPP +#define SEND_SECS 120 // payload send cycle [seconds/2] -> 240 sec. #define MEM_LOW 2048 // [Bytes] low memory threshold triggering a send cycle #define RETRANSMIT_RCMD 5 // [seconds] wait time before retransmitting rcommand results #define PAYLOAD_BUFFER_SIZE 51 // maximum size of payload block per transmit From 57304a51c95326c40601abdc1ca00f11608b3e03 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 18 Jun 2018 13:17:10 +0200 Subject: [PATCH 31/38] Update README.md --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4815091f..ea32f823 100644 --- a/README.md +++ b/README.md @@ -141,11 +141,9 @@ If you're using [TheThingsNetwork](https://www.thethingsnetwork.org/) (TTN) you To map a GPS capable paxcounter device and at the same time contribute to TTN coverage mapping, you simply activate the [TTNmapper integration](https://www.thethingsnetwork.org/docs/applications/ttnmapper/) in TTN Console. Paxcounter generates ttnmapper compatible data fields. -**Decoder:** +**Decoder:** [TTN/plain_decoder.js](TTN/plain_decoder.js) ```javascript - - function Decoder(bytes, port) { var decoded = {}; @@ -166,7 +164,7 @@ function Decoder(bytes, port) { } ``` -**Converter:** +**Converter:** [TTN/plain_converter.js](TTN/plain_converter.js) ```javascript function Converter(decoded, port) { From acaf5cdc69229d9109cb8d2333c2fdc9cb74acb0 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 18 Jun 2018 13:21:07 +0200 Subject: [PATCH 32/38] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index ea32f823..7d1f2cf1 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ If you're using [TheThingsNetwork](https://www.thethingsnetwork.org/) (TTN) you To map a GPS capable paxcounter device and at the same time contribute to TTN coverage mapping, you simply activate the [TTNmapper integration](https://www.thethingsnetwork.org/docs/applications/ttnmapper/) in TTN Console. Paxcounter generates ttnmapper compatible data fields. -**Decoder:** [TTN/plain_decoder.js](TTN/plain_decoder.js) +[**plain_decoder.js**](src/TTN/plain_decoder.js) ```javascript function Decoder(bytes, port) { @@ -164,7 +164,7 @@ function Decoder(bytes, port) { } ``` -**Converter:** [TTN/plain_converter.js](TTN/plain_converter.js) +[**plain_converter.js**](src/TTN/plain_converter.js) ```javascript function Converter(decoded, port) { From deea6da0ab6e4de01ea6968e3a0843693a2927bc Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 18 Jun 2018 13:22:43 +0200 Subject: [PATCH 33/38] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7d1f2cf1..3cef8e58 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,10 @@ You can select between different payload formats in [paxcounter.conf](src/paxcou - [***CayenneLPP***](https://mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload-reference-implementation) generates MyDevices Cayenne readable fields +If you're using [TheThingsNetwork](https://www.thethingsnetwork.org/) (TTN) you may want to use a payload converter. Go to TTN Console - Application - Payload Formats and paste the code example below in tabs Decoder and Converter. Make sure that your application parses the fields `pax`, `ble` and `wifi`. + +To map a GPS capable paxcounter device and at the same time contribute to TTN coverage mapping, you simply activate the [TTNmapper integration](https://www.thethingsnetwork.org/docs/applications/ttnmapper/) in TTN Console. Paxcounter generates ttnmapper compatible data fields. + Hereafter described is the default *Plain* format. **LoRaWAN Port #1:** @@ -137,10 +141,6 @@ Hereafter described is the default *Plain* format. - see remote control - -If you're using [TheThingsNetwork](https://www.thethingsnetwork.org/) (TTN) you may want to use a payload converter. Go to TTN Console - Application - Payload Formats and paste the code example below in tabs Decoder and Converter. Make sure that your application parses the fields `pax`, `ble` and `wifi`. - -To map a GPS capable paxcounter device and at the same time contribute to TTN coverage mapping, you simply activate the [TTNmapper integration](https://www.thethingsnetwork.org/docs/applications/ttnmapper/) in TTN Console. Paxcounter generates ttnmapper compatible data fields. - [**plain_decoder.js**](src/TTN/plain_decoder.js) ```javascript From 370ae9820cfdb9941221a763d06dea84e0ec3866 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 18 Jun 2018 13:25:18 +0200 Subject: [PATCH 34/38] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3cef8e58..d07d06bb 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,7 @@ function Decoder(bytes, port) { if (bytes.length > 4) { decoded.latitude = ( (bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++] ); decoded.longitude = ( (bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++] ); - decoded.sats = ( bytes[i++] ); + decoded.sats = ( bytes[i++] ); decoded.hdop = ( bytes[i++] << 8) | (bytes[i++] ); decoded.altitude = ( bytes[i++] << 8) | (bytes[i++] ); } From 5d2ee32646daad25a809c534ec1a9eaca153b279 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 18 Jun 2018 22:44:57 +0200 Subject: [PATCH 35/38] platformio.ini update --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 75d57140..99415985 100644 --- a/platformio.ini +++ b/platformio.ini @@ -119,7 +119,7 @@ build_flags = -include "src/hal/ttgobeam.h" [env:fipy] -platform = espressif32@1.0.1 +platform = ${common_env_data.platform_espressif32} framework = arduino board = esp32dev board_build.partitions = ${common_env_data.board_build.partitions} From e98746176894544ec477daf8fa159ecd035f2443 Mon Sep 17 00:00:00 2001 From: Verkehrsrot Date: Mon, 18 Jun 2018 22:55:39 +0200 Subject: [PATCH 36/38] Update README.md --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index a6d43a0a..243d4ea8 100644 --- a/README.md +++ b/README.md @@ -90,16 +90,16 @@ Note: If you use this software you do this at your own risk. That means that you Paxcounter generates identifiers for sniffed MAC adresses and collects them temporary in the device's RAM for a configurable scan cycle time (default 240 seconds). After each scan cycle the collected identifiers are cleared. Identifiers are generated by salting and hashing MAC adresses. The random salt value changes after each scan cycle. Identifiers and MAC adresses are never transferred to the LoRaWAN network. No persistent storing of MAC adresses, identifiers or timestamps and no other kind of analytics than counting are implemented in this code. Wireless networks are not touched by this code, but MAC adresses from wireless devices as well within as not within wireless networks, regardless if encrypted or unencrypted, are sniffed and processed by this code. If the bluetooth option in the code is enabled, bluetooth MACs are scanned and processed by the included BLE stack, then hashed and counted by this code. -# LED +# LED blink pattern -Legend for mono color on board LED: +**Mono color LED:** - Single Flash (50ms): seen a new Wifi or BLE device - Quick blink (20ms on each 1/5 second): joining LoRaWAN network in progress or pending - Small blink (10ms on each 1/2 second): LoRaWAN data transmit in progress or pending - Long blink (200ms on each 2 seconds): LoRaWAN stack error -Legend for RGB LED (LoPy/LoPy4/FiPy/Lolin32 only): +**RGB LED:** - Green each blink: seen a new Wifi device - Magenta each blink: seen a new BLE device @@ -107,9 +107,9 @@ Legend for RGB LED (LoPy/LoPy4/FiPy/Lolin32 only): - Blue blink: LoRaWAN data transmit in progress or pending - Red long blink: LoRaWAN stack error -# Payload +# Payload format -You can select between different payload formats in [paxcounter.conf](src/paxcounter.conf#L40): +You can select different payload formats in [paxcounter.conf](src/paxcounter.conf#L40): - ***Plain*** uses big endian format and generates json fields, e.g. useful for TTN console @@ -117,11 +117,11 @@ You can select between different payload formats in [paxcounter.conf](src/paxcou - [***CayenneLPP***](https://mydevices.com/cayenne/docs/lora/#lora-cayenne-low-power-payload-reference-implementation) generates MyDevices Cayenne readable fields -If you're using [TheThingsNetwork](https://www.thethingsnetwork.org/) (TTN) you may want to use a payload converter. Go to TTN Console - Application - Payload Formats and paste the code example below in tabs Decoder and Converter. Make sure that your application parses the fields `pax`, `ble` and `wifi`. +If you're using [TheThingsNetwork](https://www.thethingsnetwork.org/) (TTN) you may want to use a payload converter. Go to TTN Console - Application - Payload Formats and paste the code example below in tabs Decoder and Converter. This way your MQTT application can parse the fields `pax`, `ble` and `wifi`. -To map a GPS capable paxcounter device and at the same time contribute to TTN coverage mapping, you simply activate the [TTNmapper integration](https://www.thethingsnetwork.org/docs/applications/ttnmapper/) in TTN Console. Paxcounter generates ttnmapper compatible data fields. +To track a paxcounter device with on board GPS and at the same time contribute to TTN coverage mapping, you simply activate the [TTNmapper integration](https://www.thethingsnetwork.org/docs/applications/ttnmapper/) in TTN Console. The formats *plain* and *packed* generate the fields `latitude`, `longitude` and `hdop` required by ttnmapper. -Hereafter described is the default *Plain* format. +Hereafter described is the default *plain* format. **LoRaWAN Port #1:** From 407bcd5df2f803c972c65bf70aab5ca09e8904a9 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Tue, 19 Jun 2018 20:38:06 +0200 Subject: [PATCH 37/38] ttgov21.h updated --- src/hal/ttgov21.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/hal/ttgov21.h b/src/hal/ttgov21.h index 96617e1f..7ec2a7d4 100644 --- a/src/hal/ttgov21.h +++ b/src/hal/ttgov21.h @@ -1,12 +1,19 @@ -// Hardware related definitions for TTGO V2.1 Board +/* Hardware related definitions for TTGO V2.1 Board +/ ATTENTION: check your board version! +/ Different versions are on the market which need different settings in this file: +/ - without label -> "old" +/ - labelled v1.5 on pcb -> "old" +/ - labelled v1.6 on pcb -> "new" +*/ + #define CFG_sx1276_radio 1 // HPD13A LoRa SoC #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C #define DISPLAY_FLIP 1 // rotated display -#define HAS_LED GPIO_NUM_23 // green on board LED_G3 (not in initial board version) -#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 -#define BATT_FACTOR 2 // voltage divider 100k/100k on board +#define HAS_LED GPIO_NUM_23 // green on board LED (new board ONLY) +#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // uses GPIO7 (new board ONLY) +#define BATT_FACTOR 2 // voltage divider 100k/100k on board (new board ONLY) // re-define pin definitions of pins_arduino.h #define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select Input @@ -15,7 +22,9 @@ #define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input // non arduino pin definitions -#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN +#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN (old board) +//#define RST GPIO_NUM_12 // connected to ESP32 RST/EN (old board v1.5) +//#define RST GPIO_NUM_19 // connected to ESP32 RST/EN (new board) #define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0 #define DIO1 GPIO_NUM_33 // ESP32 GPIO33 <-> HPDIO1 <-> HPD13A IO1 #define DIO2 GPIO_NUM_32 // ESP32 GPIO32 <-> HPDIO2 <-> HPD13A IO2 From bbed612d2cb802738f1392153810fdd60dde5ac5 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Wed, 20 Jun 2018 23:26:59 +0200 Subject: [PATCH 38/38] ttgov21.h updated --- src/hal/ttgov21.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hal/ttgov21.h b/src/hal/ttgov21.h index 7ec2a7d4..6f4d1255 100644 --- a/src/hal/ttgov21.h +++ b/src/hal/ttgov21.h @@ -22,9 +22,9 @@ #define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input // non arduino pin definitions -#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN (old board) -//#define RST GPIO_NUM_12 // connected to ESP32 RST/EN (old board v1.5) -//#define RST GPIO_NUM_19 // connected to ESP32 RST/EN (new board) +#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN (old board) +//#define RST GPIO_NUM_12 // (old board v1.5) +//#define RST GPIO_NUM_19 //(new board) #define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0 #define DIO1 GPIO_NUM_33 // ESP32 GPIO33 <-> HPDIO1 <-> HPD13A IO1 #define DIO2 GPIO_NUM_32 // ESP32 GPIO32 <-> HPDIO2 <-> HPD13A IO2