Merge pull request #112 from cyberman54/development

sync dev -> master
This commit is contained in:
Verkehrsrot 2018-07-18 19:51:01 +02:00 committed by GitHub
commit 2c0e5cb099
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 329 additions and 257 deletions

110
README.md
View File

@ -13,7 +13,7 @@ Paxcounter is a proof-of-concept device for metering passenger flows in realtime
Intention of this project is to do this without intrusion in privacy: You don't need to track people owned devices, if you just want to count them. Therefore, Paxcounter does not persistenly store MAC adresses and does no kind of fingerprinting the scanned devices.
Bonus of this project is that metered data is transferred via a LoRaWAN network, not via usual GSM/LTE or Wifi uplink.
Metered counts are transferred to a server via a LoRaWAN network, and/or a local SPI cable interface.
You can build this project battery powered and reach a full day uptime with a single 18650 Li-Ion cell.
@ -21,26 +21,28 @@ This can all be done with a single small and cheap ESP32 board for less than $20
# Hardware
Supported ESP32 based LoRa IoT boards:
**Supported ESP32 based boards**:
- **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)
*LoRa & SPI*:
- Heltec: LoRa-32
- TTGO: T3_v1, T3_v2, T3_v2.1, T-Beam
- Pycom: LoPy, LoPy4, FiPy
- WeMos: LoLin32 + [LoraNode32 shield](https://github.com/hallard/LoLin32-Lora),
LoLin32lite + [LoraNode32-Lite shield](https://github.com/hallard/LoLin32-Lite-Lora)
*SPI only*: (coming soon)
- Pyom: WiPy
- WeMos: LoLin32, LoLin32 Lite, WeMos D32
Depending on board hardware following features are supported:
- LED
- OLED Display
- RGB LED
- button
- silicon unique ID
- battery voltage monitoring
- 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).<br>
@ -49,7 +51,7 @@ Hardware dependent settings (pinout etc.) are stored in board files in /hal dire
<b>3D printable cases</b> can be found (and, if wanted so, ordered) on Thingiverse, see
<A HREF="https://www.thingiverse.com/thing:2670713">Heltec</A>, <A HREF="https://www.thingiverse.com/thing:2811127">TTGOv2</A>, <A HREF="https://www.thingiverse.com/thing:3005574">TTGOv2.1</A> for example.<br>
<b>Power consumption</b> was metered at around 1000mW, depending on board (i.e. has display or not) and user settings in paxcounter.conf. If you are limited on battery, you may want to save around 30% power by disabling bluetooth (commenting out line *#define BLECOUNTER* in paxcounter.conf).
<b>Power consumption</b> was metered at around 750 - 1000mW, depending on board and user settings in paxcounter.conf. If you are limited on battery, you may want to save around 30% power by disabling bluetooth (commenting out line *#define BLECOUNTER* in paxcounter.conf).
# Preparing
@ -123,26 +125,48 @@ If you're using [TheThingsNetwork](https://www.thethingsnetwork.org/) (TTN) you
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, which uses MSB bit numbering.
**LoRaWAN Port #1:**
Paxcounter data
**Port #1:** Paxcount data
byte 1-2: Number of unique pax, first seen on Wifi
byte 3-4: Number of unique pax, first seen on Bluetooth [0 if BT disabled]
bytes 5-18: GPS data, format see Port #4 (appended only, if GPS is present and has a fix)
GPS data (only, if GPS is present and has a fix)
**Port #2:** Device status query result
bytes 5-8: GPS latitude
bytes 9-12: GPS longitude
bytes 13-14: GPS number of satellites
bytes 15-16: GPS HDOP
bytes 17-18: GPS altitude [meter]
byte 1-2: Battery or USB Voltage [mV], 0 if unreadable
byte 3-10: Uptime [seconds]
bytes 11-14: CPU temperature [°C]
**LoRaWAN Port #2:**
**Port #3:** Device configuration query result
byte 1: Lora SF (7..12) [default 9]
byte 2: Lora TXpower (2..15) [default 15]
byte 3: Lora ADR (1=on, 0=off) [default 1]
byte 4: Screensaver status (1=on, 0=off) [default 0]
byte 5: Display status (1=on, 0=off) [default 0]
byte 6: Counter mode (0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed) [default 0]
bytes 7-8: RSSI limiter threshold value (negative) [default 0]
byte 9: Lora Payload send cycle in seconds/2 (0..255) [default 120]
byte 10: Wifi channel switch interval in seconds/100 (0..255) [default 50]
byte 11: Bluetooth channel switch interval in seconds/100 (0..255) [efault 10]
byte 12: Bluetooth scanner status (1=on, 0=0ff) [default 1]
byte 13: Wifi antenna switch (0=internal, 1=external) [default 0]
byte 14: Vendorfilter mode (0=disabled, 1=enabled) [default 0]
byte 15: RGB LED luminosity (0..100 %) [default 30]
byte 16: GPS send data mode (1=on, 0=ff) [default 1]
bytes 17-27: Software version (ASCII format, terminating with zero)
**Port #4:** GPS query result
bytes 1-4: Latitude
bytes 5-8: Longitude
byte 9: Number of satellites
bytes 10-11: HDOP
bytes 12-13: Altitude [meter]
- see remote control -
[**plain_decoder.js**](src/TTN/plain_decoder.js)
@ -279,38 +303,16 @@ 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 [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]
byte 3: Lora ADR (1=on, 0=off) [default 1]
byte 4: Screensaver status (1=on, 0=off) [default 0]
byte 5: Display status (1=on, 0=off) [default 0]
byte 6: Counter mode (0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed) [default 0]
bytes 7-8: RSSI limiter threshold value (negative) [default 0]
byte 9: Lora Payload send cycle in seconds/2 (0..255) [default 120]
byte 10: Wifi channel switch interval in seconds/100 (0..255) [default 50]
byte 11: Bluetooth channel switch interval in seconds/100 (0..255) [efault 10]
byte 12: Bluetooth scanner status (1=on, 0=0ff) [default 1]
byte 13: Wifi antenna switch (0=internal, 1=external) [default 0]
byte 14: Vendorfilter mode (0=disabled, 1=enabled) [default 0]
byte 15: RGB LED luminosity (0..100 %) [default 30]
byte 16: GPS send data mode (1=on, 0=ff) [default 1]
bytes 17-27: Software version (ASCII format, terminating with zero)
Device answers with it's current configuration on Port 3.
0x81 get device status
bytes 1-2: Battery voltage in millivolt, 0 if unreadable
bytes 3-10: Uptime in seconds
bytes 11-14: Chip temperature in degrees celsius
Device answers with it's current status on Port 2.
0x84 get device GPS status
bytes 1-4: Latitude
bytes 5-8: Longitude
byte 9: Number of satellites
byte 10-11: HDOP
bytes 12-13: altidute [meter]
Device answers with it's current status on Port 4.
# License

View File

@ -298,7 +298,7 @@ static const u8x8_display_info_t u8x8_ssd1306_128x64_noname_display_info =
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
/* spi_mode = */ 0, /* active high, rising edge */
/* ==> i2c_bus_clock_100kHz = */ 4,
/* ==> i2c_bus_clock_100kHz = */ 1,
/* data_setup_time_ns = */ 40,
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
/* tile_width = */ 16,

View File

@ -11,7 +11,9 @@
; ---> SELECT TARGET PLATFORM HERE! <---
[platformio]
env_default = heltec
;env_default = lolin32lite, heltec, generic
env_default = generic
;env_default = heltec
;env_default = ttgov1
;env_default = ttgov2
;env_default = ttgov21
@ -21,13 +23,14 @@ env_default = heltec
;env_default = fipy
;env_default = lolin32litelora
;env_default = lolin32lora
;env_default = lolin32lite
;
description = Paxcounter is a proof-of-concept ESP32 device for metering passenger flows in realtime. It counts how many mobile devices are around.
[common_env_data]
platform_espressif32 = espressif32@1.0.2
;platform_espressif32 = espressif32@1.0.2
;platform_espressif32 = espressif32@1.1.2
;platform_espressif32 = https://github.com/platformio/platform-espressif32.git#feature/stage
platform_espressif32 = https://github.com/platformio/platform-espressif32.git#feature/stage
board_build.partitions = no_ota.csv
lib_deps_all =
lib_deps_display =
@ -45,8 +48,8 @@ build_flags =
; otherwise device may crash in dense environments due to serial buffer overflow
;
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_NONE
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_INFO
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
; -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_VERBOSE
;
; override lora settings from LMiC library in lmic/config.h and use main.h instead
@ -186,3 +189,31 @@ lib_deps =
${common_env_data.lib_deps_rgbled}
build_flags =
${common_env_data.build_flags}
[env:lolin32lite]
platform = ${common_env_data.platform_espressif32}
framework = arduino
board = lolin32
board_build.partitions = ${common_env_data.board_build.partitions}
upload_speed = 921600
monitor_speed = 115200
lib_deps =
${common_env_data.lib_deps_all}
${common_env_data.lib_deps_rgbled}
build_flags =
${common_env_data.build_flags}
[env:generic]
platform = ${common_env_data.platform_espressif32}
framework = arduino
board = esp32dev
board_build.partitions = ${common_env_data.board_build.partitions}
upload_speed = 921600
monitor_speed = 115200
lib_deps =
${common_env_data.lib_deps_all}
${common_env_data.lib_deps_rgbled}
${common_env_data.lib_deps_gps}
${common_env_data.lib_deps_display}
build_flags =
${common_env_data.build_flags}

View File

@ -9,12 +9,10 @@ function Converter(decoded, port) {
converted.pax = converted.ble + converted.wifi;
}
/*
if (port === 2) {
converted.voltage /= 1000;
converted.uptime /= 60;
}
*/
return converted;
}

View File

@ -18,15 +18,19 @@ function Decoder(bytes, port) {
if (port === 2) {
// device status data
if (bytes.length === 12) {
return decode(bytes, [uint16, uptime, temperature], ['voltage', 'uptime', 'cputemp']);
}
if (port === 3) {
// device config data
if (bytes.length === 8) {
return decode(bytes, [uint8, uint16, uint8, uint8, uint8, uint8, bitmap], ['lorasf', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags']);
}
return decode(bytes, [uint8, uint8, uint16, uint8, uint8, uint8, uint8, bitmap], ['lorasf', 'txpower', 'rssilimit', 'sendcycle', 'wifichancycle', 'blescantime', 'rgblum', 'flags']);
}
if (port === 4) {
// gps data
return decode(bytes, [latLng, latLng, uint8, hdop, uint16], ['latitude', 'longitude', 'sats', 'hdop', 'altitude']);
}
}

View File

@ -1,5 +1,5 @@
#ifndef antenna_H
#define antenna_H
#ifndef _ANTENNA_H
#define _ANTENNA_H
void antenna_init(void);
void antenna_select(const uint8_t _ant);

View File

@ -1,5 +1,5 @@
#ifndef battery_H
#define battery_H
#ifndef _BATTERY_H
#define _BATTERY_H
#include <driver/adc.h>
#include <esp_adc_cal.h>

View File

@ -1,5 +1,7 @@
#ifndef BLESCAN_H
#define BLESCAN_H
#ifndef _BLESCAN_H
#define _BLESCAN_H
#include "macsniff.h"
void start_BLEscan(void);
void stop_BLEscan(void);

View File

@ -316,10 +316,5 @@ void loadConfig() {
nvs_close(my_handle);
ESP_LOGI(TAG, "Done");
// put actions to be triggered after config loaded here
#ifdef HAS_ANTENNA_SWITCH // set antenna type
antenna_select(cfg.wifiant);
#endif
}
}
} // loadConfig()

View File

@ -1,5 +1,5 @@
#ifndef CONFIGMANAGER_H
#define CONFIGMANAGER_H
#ifndef _CONFIGMANAGER_H
#define _CONFIGMANAGER_H
void eraseConfig(void);
void saveConfig(void);

View File

@ -6,6 +6,13 @@
HAS_DISPLAY u8x8(OLED_RST, OLED_SCL, OLED_SDA);
// helper string for converting LoRa spread factor values
#if defined(CFG_eu868)
const char lora_datarate[] = {"1211100908077BFSNA"};
#elif defined(CFG_us915)
const char lora_datarate[] = {"100908078CNA121110090807"};
#endif
// helper function, prints a hex key on display
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb) {
const uint8_t *p;

View File

@ -1,5 +1,5 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#ifndef _DISPLAY_H
#define _DISPLAY_H
#include <U8x8lib.h>

View File

@ -1,38 +1,77 @@
#ifndef _GLOBALS_H
#define _GLOBALS_H
// The mother of all embedded development...
#include <Arduino.h>
// needed for ESP_LOGx on arduino framework
#include <esp32-hal-log.h>
// attn: increment version after modifications to configData_t truct!
#define PROGVERSION "1.3.91" // use max 10 chars here!
#define PROGNAME "PAXCNT"
// std::set for unified array functions
#include <set>
#include <array>
#include <algorithm>
// basics
#include "main.h"
#include "led.h"
#include "macsniff.h"
#include "payload.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;
extern configData_t cfg;
extern char display_line6[], display_line7[];
extern int countermode, screensaver, adrmode, lorasf, txpower, rlim;
extern uint8_t channel, DisplayState;
extern uint16_t macs_total, macs_wifi, macs_ble; // MAC counters
extern uint64_t uptimecounter;
extern std::set<uint16_t> macs;
extern hw_timer_t *channelSwitch, *sendCycle;
extern portMUX_TYPE timerMux;
#if defined(CFG_eu868)
const char lora_datarate[] = {"1211100908077BFSNA"};
#elif defined(CFG_us915)
const char lora_datarate[] = {"100908078CNA121110090807"};
#ifdef HAS_GPS
#include "gps.h"
#endif
#ifdef HAS_GPS
extern gpsStatus_t gps_status; // struct for storing gps data
extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe
#ifdef HAS_LORA
#include "lorawan.h"
#endif
#ifdef HAS_DISPLAY
#include "display.h"
#endif
#ifdef BLECOUNTER
#include "blescan.h"
#endif
#ifdef HAS_BATTERY_PROBE
#include "battery.h"
#endif
#ifdef HAS_ANTENNA_SWITCH
#include "antenna.h"
#endif
// class for preparing payload data
#include "payload.h"
// payload encoder
#if PAYLOAD_ENCODER == 1
extern TTNplain payload;
@ -43,3 +82,11 @@ extern CayenneLPP payload;
#else
#error "No valid payload converter defined"
#endif
void reset_counters(void);
void blink_LED(uint16_t set_color, uint16_t set_blinkduration);
void led_loop(void);
uint64_t uptime();
#endif

View File

@ -1,7 +1,6 @@
#ifdef HAS_GPS
#include "globals.h"
#include <Wire.h>
// Local logging tag
static const char TAG[] = "main";

View File

@ -1,7 +1,18 @@
#ifndef gps_H
#define gps_H
#ifndef _GPS_H
#define _GPS_H
#include <TinyGPS++.h>
#include <TinyGPS++.h> // library for parsing NMEA data
typedef struct {
uint32_t latitude;
uint32_t longitude;
uint8_t satellites;
uint16_t hdop;
uint16_t altitude;
} gpsStatus_t;
extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe
extern gpsStatus_t gps_status; // Make struct for storing gps data globally available
void gps_read(void);
void gps_loop(void *pvParameters);

34
src/hal/generic.h Normal file
View File

@ -0,0 +1,34 @@
// Hardware related definitions for generic ESP32 boards
#define HAS_LORA 1 // comment out if device shall not send data via LoRa or has no LoRa
#define HAS_SPI 1 // comment out if device shall not send data via SPI
#define CFG_sx1276_radio 1 // select LoRa chip
//#define CFG_sx1272_radio 1 // select LoRa chip
#define BOARD_HAS_PSRAM // use if board has external PSRAM
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
//#define DISPLAY_FLIP 1 // use if display is rotated
#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // uses GPIO7
#define BATT_FACTOR 2 // voltage divider 100k/100k on board
#define HAS_LED GPIO_NUM_21 // on board LED
#define HAS_BUTTON GPIO_NUM_39 // on board button
#define HAS_GPS 1 // use if board has GPS
#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M or 7M with default configuration
// pin definitions for SPI interface of LoRa chip
#define PIN_SPI_SS GPIO_NUM_18 // SPI Chip Select
#define PIN_SPI_MOSI GPIO_NUM_27 // SPI Data Input
#define PIN_SPI_MISO GPIO_NUM_19 // SPI Data Output
#define PIN_SPI_SCK GPIO_NUM_5 // SPI Clock
#define RST LMIC_UNUSED_PIN // LoRa Reset (if wired)
#define DIO0 GPIO_NUM_26 // LoRa IO0
#define DIO1 GPIO_NUM_32 // LoRa IO1
#define DIO2 LMIC_UNUSED_PIN // LoRa IO2 (not needed)
// pin definitions for I2C interface of OLED Display
#define OLED_RST GPIO_NUM_16 // SSD1306 RST
#define OLED_SDA GPIO_NUM_4 // SD1306 D1+D2
#define OLED_SCL GPIO_NUM_15 // SD1306 D0

8
src/hal/lolin32lite.h Normal file
View File

@ -0,0 +1,8 @@
// Hardware related definitions for lolin32lite (without LoRa shield)
#define CFG_sx1272_radio 1 // dummy
#define HAS_LED 22 // on board LED on GPIO22
#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW
#define HAS_SPI 1 // comment out if device shall not send data via SPI

View File

@ -1,9 +1,9 @@
// Hardware related definitions for Pycom LoPy Board (not: LoPy4)
// Hardware related definitions for Pycom LoPy Board (NOT LoPy4)
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
#define HAS_SPI 1 // comment out if device shall not send data via SPI
#define CFG_sx1272_radio 1
#define HAS_LED NOT_A_PIN // LoPy4 has no on board LED, so we use RGB LED on LoPy4
#define HAS_LED NOT_A_PIN // LoPy has no on board LED, so we use RGB LED on LoPy
#define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0
// Hardware pin definitions for Pycom LoPy board

View File

@ -28,28 +28,29 @@
#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO21 -- SD1306 D1+D2
#define OLED_SCL GPIO_NUM_22 // ESP32 GPIO22 -- SD1306 D0
/* source:
https://www.thethingsnetwork.org/forum/t/big-esp32-sx127x-topic-part-2/11973
/*
ESP32 LoRa module (SPI) OLED display (I2C)
--------- ----------------- ------------------
5 SCK SCK
27 MOSI MOSI
19 MISO MISO
18 SS NSS
14 RST
26 DIO0
33 DIO1 (see note {1})
32 DIO2 (see note {2})
22 SCL SCL
21 SDA SDA
22 LED (useless, see note {3})
TTGO LoRa32 V2:
ESP32 LoRa (SPI) Display (I2C) LED
----------- ---------- ------------- ------------------
GPIO5 SCK SCK
GPIO27 MOSI MOSI
GPIO19 MISO MISO
GPIO18 SS NSS
EN RST RST
GPIO26 DIO0
GPIO33 DIO1 (see #1)
GPIO32 DIO2 (see #2)
GPIO22 SCL SCL
GPIO21 SDA SDA
GPIO22 useless (see #3)
{1} Must be manually wired!
DIO1 is wired to a separate pin but is not wired on-board to pin/GPIO33.
Explicitly wire board pin labeled DIO1 to pin 33 (see TTGO V2.0 pinout).
{2} Must be manually wired!
DIO2 is wired to a separate pin but is not wired on-board to pin/GPIO32.
Explicitly wire board pin labeled DIO2 to pin 32 (see TTGO V2.0 pinout).
{3} The on-board LED is wired to SCL (used by display) therefore totally useless!
#1 Required (used by LMIC for LoRa).
Not on-board wired to any GPIO. Must be manually wired. <<-- necessary for paxcounter
#2 Optional (used by LMIC for FSK but not for LoRa). <<-- NOT necessary for paxcounter
Not on-board wired to any GPIO. When needed: must be manually wired.
#3 GPIO22 is already used for SCL therefore LED cannot be used without conflicting with I2C and display.
*/

View File

@ -1,5 +1,5 @@
#ifndef hash_H
#define hash_H
#ifndef _HASH_H
#define _HASH_H
uint32_t rokkit(const char *data, int len);

View File

@ -1,5 +1,5 @@
//#pragma once
#ifndef _LED_H
#define _LED_H
#ifdef HAS_RGB_LED
#include <SmartLeds.h>
@ -35,3 +35,5 @@ enum led_states { LED_OFF, LED_ON };
void rgb_set_color(uint16_t hue);
void blink_LED(uint16_t set_color, uint16_t set_blinkduration);
void led_loop();
#endif

View File

@ -1,5 +1,5 @@
#ifndef LORAWAN_H
#define LORAWAN_H
#ifndef _LORAWAN_H
#define _LORAWAN_H
// LMIC-Arduino LoRaWAN Stack
#include <lmic.h>
@ -13,5 +13,6 @@ void get_hard_deveui(uint8_t *pdeveui);
void os_getDevKey(u1_t *buf);
void os_getArtEui(u1_t *buf);
void os_getDevEui(u1_t *buf);
void printKeys(void);
#endif

View File

@ -1,11 +1,14 @@
#ifndef MACSNIFF_H
#define MACSNIFF_H
#ifndef _MACSNIFF_H
#define _MACSNIFF_H
// ESP32 Functions
#include <esp_wifi.h>
// Hash function for scrambling MAC addresses
#include "hash.h"
#include "led.h"
#define MAC_SNIFF_WIFI 0
#define MAC_SNIFF_BLE 1

View File

@ -1,5 +1,6 @@
/*
ESP32-Paxcounter
//////////////////////// ESP32-Paxcounter \\\\\\\\\\\\\\\\\\\\\\\\\\
Copyright 2018 Oliver Brandmueller <ob@sysadm.in>
Copyright 2018 Klaus Wilting <verkehrsrot@arcor.de>
@ -24,15 +25,14 @@ licenses. Refer to LICENSE.txt file in repository for more details.
// Basic Config
#include "globals.h"
#include "main.h"
// Initialize global variables
configData_t cfg; // struct holds current device configuration
char display_line6[16], display_line7[16]; // display buffers
uint64_t uptimecounter = 0; // timer global for uptime counter
uint8_t DisplayState = 0; // globals for state machine
uint8_t DisplayState = 0, channel = 0; // globals for state machine
uint16_t macs_total = 0, macs_wifi = 0,
macs_ble = 0; // MAC counters globals for display
uint8_t channel = 0; // wifi channel rotation counter global for display
hw_timer_t *channelSwitch = NULL, *displaytimer = NULL,
*sendCycle = NULL; // configure hardware timer for cyclic tasks
@ -80,9 +80,6 @@ void reset_counters() {
macs_ble = 0;
}
/* begin LMIC specific parts
* ------------------------------------------------------------ */
#ifdef HAS_LORA
// LMIC enhanced Pin mapping
@ -94,10 +91,6 @@ const lmic_pinmap lmic_pins = {.mosi = PIN_SPI_MOSI,
.rst = RST,
.dio = {DIO0, DIO1, DIO2}};
#ifdef VERBOSE
void printKeys(void);
#endif // VERBOSE
// Get MCP 24AA02E64 hardware DEVEUI (override default settings if found)
#ifdef MCP_24AA02E64_I2C_ADDRESS
get_hard_deveui(buf);
@ -117,15 +110,8 @@ void lorawan_loop(void *pvParameters) {
#endif // HAS_LORA
/* end LMIC specific parts
* --------------------------------------------------------------- */
/* beginn hardware specific parts
* -------------------------------------------------------- */
// Setup IRQ handler routines for button, channel rotation, send cycle´, display
// attention, enable cache:
// https://github.com/espressif/arduino-esp32/issues/855
// Setup IRQ handler routines
// attn see https://github.com/espressif/arduino-esp32/issues/855
void IRAM_ATTR ChannelSwitchIRQ() {
portENTER_CRITICAL(&timerMux);
@ -174,9 +160,6 @@ void readButton() {
}
#endif
/* end hardware specific parts
* -------------------------------------------------------- */
// Wifi channel rotation task
void wifi_channel_loop(void *pvParameters) {
@ -353,14 +336,15 @@ void setup() {
// setup display refresh trigger IRQ using esp32 hardware timer
// https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
displaytimer = timerBegin(0, 80, true); // prescaler 80 -> divides 80 MHz CPU
// freq to 1 MHz, timer 0, count up
timerAttachInterrupt(displaytimer, &DisplayIRQ,
true); // interrupt handler DisplayIRQ, triggered by edge
timerAlarmWrite(
displaytimer, DISPLAYREFRESH_MS * 1000,
true); // reload interrupt after each trigger of display refresh cycle
timerAlarmEnable(displaytimer); // enable display interrupt
// prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 0, count up
displaytimer = timerBegin(0, 80, true);
// interrupt handler DisplayIRQ, triggered by edge
timerAttachInterrupt(displaytimer, &DisplayIRQ, true);
// reload interrupt after each trigger of display refresh cycle
timerAlarmWrite(displaytimer, DISPLAYREFRESH_MS * 1000, true);
// enable display interrupt
timerAlarmEnable(displaytimer);
#endif
// setup channel rotation trigger IRQ using esp32 hardware timer 1
@ -404,8 +388,8 @@ void setup() {
// join network
LMIC_startJoining();
// start lmic runloop in rtos task on core 1 (note: arduino main loop runs
// on core 1, too)
// start lmic runloop in rtos task on core 1
// (note: arduino main loop runs on core 1, too)
// https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/
ESP_LOGI(TAG, "Starting Lora task on core 1");
@ -454,8 +438,6 @@ void loop() {
// state machine for uptime, display, LED, button, lowmemory, senddata
uptimecounter = uptime() / 1000; // counts uptime in seconds (64bit)
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
led_loop();
#endif

View File

@ -1,78 +1,17 @@
#ifndef _MAIN_H
#define _MAIN_H
#include "led.h"
#include "macsniff.h"
#include "configmanager.h"
#include "senddata.h"
// Does nothing and avoid any compilation error with I2C
#include <Wire.h>
// ESP32 lib Functions
#include <esp32-hal-log.h> // needed for ESP_LOGx on arduino framework
#include <esp_event_loop.h> // needed for Wifi event handler
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
#ifdef HAS_LORA
#include "lorawan.h"
#endif
#ifdef HAS_DISPLAY
#include "display.h"
#endif
#ifdef HAS_GPS
#include "gps.h"
#endif
#ifdef BLECOUNTER
#include "blescan.h"
#endif
#ifdef HAS_BATTERY_PROBE
#include "battery.h"
#endif
#ifdef HAS_ANTENNA_SWITCH
#include "antenna.h"
#endif
// program version - note: increment version after modifications to configData_t
// struct!!
#define PROGVERSION "1.3.91" // 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
#include <esp_event_loop.h> // needed for Wifi event handler
void reset_counters(void);
void blink_LED(uint16_t set_color, uint16_t set_blinkduration);
void led_loop(void);
uint64_t uptime();
#endif

View File

@ -41,14 +41,15 @@
#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
// 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 PAYLOADPORT 1 // LoRaWAN Port on which device sends counts
#define RCMDPORT 2 // LoRaWAN Port on which device listenes for remote commands
#define STATUSPORT 2 // LoRaWAN Port on which device sends remote command results
#define GPSPORT 3 // LoRaWAN Port on which device sends gps query results
// Ports on which the device sends and listenes on LoRaWAN and SPI
#define PAYLOADPORT 1 // Port on which device sends counts
#define RCMDPORT 2 // Port on which device listenes for remote commands
#define STATUSPORT 2 // Port on which device sends remote command results
#define CONFIGPORT 3 // Port on which device sends gps query results
#define GPSPORT 4 // Port on which device sends gps query results
// Default RGB LED luminosity (in %)
#define RGBLUMINOSITY 30 // 30%

View File

@ -44,6 +44,7 @@ void TTNplain::addGPS(gpsStatus_t value) {
void TTNplain::addConfig(configData_t value) {
buffer[cursor++] = value.lorasf;
buffer[cursor++] = value.txpower;
buffer[cursor++] = value.adrmode;
buffer[cursor++] = value.screensaver;
buffer[cursor++] = value.screenon;
@ -112,6 +113,7 @@ void TTNpacked::addGPS(gpsStatus_t value) {
void TTNpacked::addConfig(configData_t value) {
writeUint8(value.lorasf);
writeUint8(value.txpower);
writeUint16(value.rssilimit);
writeUint8(value.sendcycle);
writeUint8(value.wifichancycle);

View File

@ -1,4 +1,3 @@
#ifndef _PAYLOAD_H_
#define _PAYLOAD_H_

View File

@ -5,6 +5,7 @@
// Basic Config
#include "globals.h"
#include "rcommand.h"
// Local logging tag
static const char TAG[] = "main";
@ -273,7 +274,7 @@ void get_config(uint8_t val) {
ESP_LOGI(TAG, "Remote command: get device configuration");
payload.reset();
payload.addConfig(cfg);
senddata(STATUSPORT);
senddata(CONFIGPORT);
};
void get_status(uint8_t val) {
@ -284,7 +285,7 @@ void get_status(uint8_t val) {
uint16_t voltage = 0;
#endif
payload.reset();
payload.addStatus(voltage, uptimecounter, temperatureRead());
payload.addStatus(voltage, uptime() / 1000, temperatureRead());
senddata(STATUSPORT);
};

View File

@ -1,5 +1,8 @@
#ifndef rcommand_H
#define rcommand_H
#ifndef _RCOMMAND_H
#define _RCOMMAND_H
#include "senddata.h"
#include "configmanager.h"
void rcommand(uint8_t cmd, uint8_t arg);
void switch_lora(uint8_t sf, uint8_t tx);

View File

@ -1,5 +1,5 @@
#ifndef SENDDATA_H
#define SENDDATA_H
#ifndef _SENDDATA_H
#define _SENDDATA_H
void senddata(uint8_t port);