Initial upload
This commit is contained in:
1 parent
c2db6ee4b6
commit
f238dc3f0f
45 files changed
+10444
-201
No files matched your search
@@ -0,0 +1,37 @@
|
||||
#ifdef LOPY
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// Local logging tag
|
||||
static const char *TAG = "antenna";
|
||||
|
||||
static antenna_type_t antenna_type_selected = ANTENNA_TYPE_INTERNAL;
|
||||
|
||||
void antenna_init(void) {
|
||||
gpio_config_t gpioconf = {.pin_bit_mask = 1ull << PIN_ANTENNA_SWITCH,
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE};
|
||||
gpio_config(&gpioconf);
|
||||
}
|
||||
|
||||
void antenna_select (antenna_type_t _antenna) {
|
||||
if (PIN_ANTENNA_SWITCH < 32) {
|
||||
// set the pin value
|
||||
if (_antenna == ANTENNA_TYPE_EXTERNAL) {
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << PIN_ANTENNA_SWITCH);
|
||||
} else {
|
||||
GPIO_REG_WRITE(GPIO_OUT_W1TC_REG, 1 << PIN_ANTENNA_SWITCH);
|
||||
}
|
||||
} else {
|
||||
if (_antenna == ANTENNA_TYPE_EXTERNAL) {
|
||||
GPIO_REG_WRITE(GPIO_OUT1_W1TS_REG, 1 << (PIN_ANTENNA_SWITCH & 31));
|
||||
} else {
|
||||
GPIO_REG_WRITE(GPIO_OUT1_W1TC_REG, 1 << (PIN_ANTENNA_SWITCH & 31));
|
||||
}
|
||||
}
|
||||
antenna_type_selected = _antenna;
|
||||
}
|
||||
|
||||
#endif //
|
||||
@@ -0,0 +1,38 @@
|
||||
// Log Level magic
|
||||
#include "main.h"
|
||||
|
||||
// not using this seems to break U8X8LIB
|
||||
#include <Arduino.h>
|
||||
|
||||
// Local logging tag
|
||||
static const char *TAG = "blecount";
|
||||
|
||||
// Basic Config
|
||||
#include "globals.h"
|
||||
#include "loraconf.h"
|
||||
|
||||
#ifdef BLECOUNTER
|
||||
#include <BLEDevice.h>
|
||||
#include <BLEUtils.h>
|
||||
#include <BLEScan.h>
|
||||
#include <BLEAdvertisedDevice.h>
|
||||
|
||||
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
|
||||
void onResult(BLEAdvertisedDevice advertisedDevice) {
|
||||
}
|
||||
};
|
||||
|
||||
void BLECount() {
|
||||
u8x8.clearLine(3);
|
||||
u8x8.drawString(0,3,"BLE Scan...");
|
||||
BLEDevice::init("PaxCnt");
|
||||
BLEScan* pBLEScan = BLEDevice::getScan(); //create new scan
|
||||
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
|
||||
pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster
|
||||
BLEScanResults foundDevices = pBLEScan->start(cfg.blescancycle);
|
||||
u8x8.clearLine(3);
|
||||
u8x8.setCursor(0,3);
|
||||
blenum=foundDevices.getCount();
|
||||
u8x8.printf("BLE#: %4i",blenum);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,248 @@
|
||||
/* configmanager persists runtime configuration using NVRAM of ESP32*/
|
||||
|
||||
#include "globals.h"
|
||||
#include <nvs.h>
|
||||
#include <nvs_flash.h>
|
||||
|
||||
// Local logging tag
|
||||
static const char *TAG = "configmanager";
|
||||
|
||||
nvs_handle my_handle;
|
||||
|
||||
esp_err_t err;
|
||||
|
||||
// populate cfg vars with factory settings
|
||||
void defaultConfig() {
|
||||
cfg.lorasf = LORASFDEFAULT; // 7-12, initial lora spreadfactor defined in main.h
|
||||
cfg.txpower = 15; // 2-15, lora tx power
|
||||
cfg.adrmode = 1; // 0=disabled, 1=enabled
|
||||
cfg.screensaver = 0; // 0=disabled, 1=enabled
|
||||
cfg.screenon = 1; // 0=disbaled, 1=enabled
|
||||
cfg.countermode = 0; // 0=cyclic, 1=cumulative, 2=cyclic confirmed
|
||||
cfg.rssilimit = 0; // threshold for rssilimiter, negative value!
|
||||
cfg.wifiscancycle = SEND_SECS; // wifi scan cycle [seconds/2]
|
||||
cfg.wifichancycle = WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100]
|
||||
cfg.blescancycle = BLESCANTIME; // BLE scan cycle [seconds]
|
||||
cfg.blescan = 0; // 0=disabled, 1=enabled
|
||||
strncpy( cfg.version, PROGVERSION, sizeof(cfg.version)-1 );
|
||||
}
|
||||
|
||||
void open_storage() {
|
||||
err = nvs_flash_init();
|
||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
|
||||
// NVS partition was truncated and needs to be erased
|
||||
// Retry nvs_flash_init
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
err = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK( err );
|
||||
|
||||
// Open
|
||||
ESP_LOGI(TAG, "Opening NVS");
|
||||
err = nvs_open("config", NVS_READWRITE, &my_handle);
|
||||
if (err != ESP_OK)
|
||||
ESP_LOGI(TAG, "Error (%d) opening NVS handle", err);
|
||||
else
|
||||
ESP_LOGI(TAG, "Done");
|
||||
}
|
||||
|
||||
// erase all keys and values in NVRAM
|
||||
void eraseConfig() {
|
||||
ESP_LOGI(TAG, "Clearing settings in NVS");
|
||||
open_storage();
|
||||
if (err == ESP_OK) {
|
||||
nvs_erase_all(my_handle);
|
||||
nvs_commit(my_handle);
|
||||
nvs_close(my_handle);
|
||||
ESP_LOGI(TAG, "Done");}
|
||||
else {
|
||||
ESP_LOGW(TAG, "NVS erase failed"); }
|
||||
}
|
||||
|
||||
// save current configuration from RAM to NVRAM
|
||||
void saveConfig() {
|
||||
ESP_LOGI(TAG, "Storing settings in NVS");
|
||||
open_storage();
|
||||
if (err == ESP_OK) {
|
||||
int8_t flash8 = 0;
|
||||
int16_t flash16 = 0;
|
||||
size_t required_size;
|
||||
char storedversion[10];
|
||||
|
||||
if( nvs_get_str(my_handle, "version", storedversion, &required_size) != ESP_OK || strcmp(storedversion, cfg.version) != 0 )
|
||||
nvs_set_str(my_handle, "version", cfg.version);
|
||||
|
||||
if( nvs_get_i8(my_handle, "lorasf", &flash8) != ESP_OK || flash8 != cfg.lorasf )
|
||||
nvs_set_i8(my_handle, "lorasf", cfg.lorasf);
|
||||
|
||||
if( nvs_get_i8(my_handle, "txpower", &flash8) != ESP_OK || flash8 != cfg.txpower )
|
||||
nvs_set_i8(my_handle, "txpower", cfg.txpower);
|
||||
|
||||
if( nvs_get_i8(my_handle, "adrmode", &flash8) != ESP_OK || flash8 != cfg.adrmode )
|
||||
nvs_set_i8(my_handle, "adrmode", cfg.adrmode);
|
||||
|
||||
if( nvs_get_i8(my_handle, "screensaver", &flash8) != ESP_OK || flash8 != cfg.screensaver )
|
||||
nvs_set_i8(my_handle, "screensaver", cfg.screensaver);
|
||||
|
||||
if( nvs_get_i8(my_handle, "screenon", &flash8) != ESP_OK || flash8 != cfg.screenon )
|
||||
nvs_set_i8(my_handle, "screenon", cfg.screenon);
|
||||
|
||||
if( nvs_get_i8(my_handle, "countermode", &flash8) != ESP_OK || flash8 != cfg.countermode )
|
||||
nvs_set_i8(my_handle, "countermode", cfg.countermode);
|
||||
|
||||
if( nvs_get_i8(my_handle, "wifiscancycle", &flash8) != ESP_OK || flash8 != cfg.wifiscancycle )
|
||||
nvs_set_i8(my_handle, "wifiscancycle", cfg.wifiscancycle);
|
||||
|
||||
if( nvs_get_i8(my_handle, "wifichancycle", &flash8) != ESP_OK || flash8 != cfg.wifichancycle )
|
||||
nvs_set_i8(my_handle, "wifichancycle", cfg.wifichancycle);
|
||||
|
||||
if( nvs_get_i8(my_handle, "blescancycle", &flash8) != ESP_OK || flash8 != cfg.blescancycle )
|
||||
nvs_set_i8(my_handle, "blescancycle", cfg.blescancycle);
|
||||
|
||||
if( nvs_get_i8(my_handle, "blescanmode", &flash8) != ESP_OK || flash8 != cfg.blescan )
|
||||
nvs_set_i8(my_handle, "blescanmode", cfg.blescan);
|
||||
|
||||
if( nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK || flash16 != cfg.rssilimit )
|
||||
nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit);
|
||||
|
||||
err = nvs_commit(my_handle);
|
||||
nvs_close(my_handle);
|
||||
if ( err == ESP_OK ) {
|
||||
ESP_LOGI(TAG, "Done");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "NVS config write failed");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Error (%d) opening NVS handle", err);
|
||||
}
|
||||
}
|
||||
|
||||
// set and save cfg.version
|
||||
void migrateVersion() {
|
||||
sprintf(cfg.version, "%s", PROGVERSION);
|
||||
ESP_LOGI(TAG, "version set to %s", cfg.version);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
// load configuration from NVRAM into RAM and make it current
|
||||
void loadConfig() {
|
||||
defaultConfig(); // start with factory settings
|
||||
ESP_LOGI(TAG, "Reading settings from NVS");
|
||||
open_storage();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGW(TAG,"Error (%d) opening NVS handle, storing defaults", err);
|
||||
saveConfig(); } // saves factory settings to NVRAM
|
||||
else {
|
||||
int8_t flash8 = 0;
|
||||
int16_t flash16 = 0;
|
||||
size_t required_size;
|
||||
|
||||
// check if configuration stored in NVRAM matches PROGVERSION
|
||||
if( nvs_get_str(my_handle, "version", NULL, &required_size) == ESP_OK ) {
|
||||
nvs_get_str(my_handle, "version", cfg.version, &required_size);
|
||||
ESP_LOGI(TAG, "NVRAM settings version = %s", cfg.version);
|
||||
if (strcmp(cfg.version, PROGVERSION)) {
|
||||
ESP_LOGI(TAG, "migrating NVRAM settings to new version %s", PROGVERSION);
|
||||
nvs_close(my_handle);
|
||||
migrateVersion();
|
||||
}
|
||||
} else {
|
||||
ESP_LOGI(TAG, "new version %s, deleting NVRAM settings", PROGVERSION);
|
||||
nvs_close(my_handle);
|
||||
eraseConfig();
|
||||
migrateVersion();
|
||||
}
|
||||
|
||||
// overwrite defaults with valid values from NVRAM
|
||||
if( nvs_get_i8(my_handle, "lorasf", &flash8) == ESP_OK ) {
|
||||
cfg.lorasf = flash8;
|
||||
ESP_LOGI(TAG, "lorasf = %i", flash8);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "lorasf set to default %i", cfg.lorasf);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
if( nvs_get_i8(my_handle, "txpower", &flash8) == ESP_OK ) {
|
||||
cfg.txpower = flash8;
|
||||
ESP_LOGI(TAG, "txpower = %i", flash8);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "txpower set to default %i", cfg.txpower);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
if( nvs_get_i8(my_handle, "adrmode", &flash8) == ESP_OK ) {
|
||||
cfg.adrmode = flash8;
|
||||
ESP_LOGI(TAG, "adrmode = %i", flash8);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "adrmode set to default %i", cfg.adrmode);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
if( nvs_get_i8(my_handle, "screensaver", &flash8) == ESP_OK ) {
|
||||
cfg.screensaver = flash8;
|
||||
ESP_LOGI(TAG, "screensaver = %i", flash8);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "screensaver set to default %i", cfg.screensaver);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
if( nvs_get_i8(my_handle, "screenon", &flash8) == ESP_OK ) {
|
||||
cfg.screenon = flash8;
|
||||
ESP_LOGI(TAG, "screenon = %i", flash8);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "screenon set to default %i", cfg.screenon);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
if( nvs_get_i8(my_handle, "countermode", &flash8) == ESP_OK ) {
|
||||
cfg.countermode = flash8;
|
||||
ESP_LOGI(TAG, "countermode = %i", flash8);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "countermode set to default %i", cfg.countermode);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
if( nvs_get_i8(my_handle, "wifiscancycle", &flash8) == ESP_OK ) {
|
||||
cfg.wifiscancycle = flash8;
|
||||
ESP_LOGI(TAG, "wifiscancycle = %i", flash8);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "WIFI scan cycle set to default %i", cfg.wifiscancycle);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
if( nvs_get_i8(my_handle, "wifichancycle", &flash8) == ESP_OK ) {
|
||||
cfg.wifichancycle = flash8;
|
||||
ESP_LOGI(TAG, "wifichancycle = %i", flash8);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "WIFI channel cycle set to default %i", cfg.wifichancycle);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
if( nvs_get_i8(my_handle, "blescancycle", &flash8) == ESP_OK ) {
|
||||
cfg.blescancycle = flash8;
|
||||
ESP_LOGI(TAG, "blescancycle = %i", flash8);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "BLEscan cycle set to default %i", cfg.blescancycle);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
if( nvs_get_i8(my_handle, "blescanmode", &flash8) == ESP_OK ) {
|
||||
cfg.blescan = flash8;
|
||||
ESP_LOGI(TAG, "BLEscanmode = %i", flash8);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "BLEscanmode set to default %i", cfg.blescan);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
if( nvs_get_i16(my_handle, "rssilimit", &flash16) == ESP_OK ) {
|
||||
cfg.rssilimit = flash16;
|
||||
ESP_LOGI(TAG, "rssilimit = %i", flash16);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "rssilimit set to default %i", cfg.rssilimit);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
nvs_close(my_handle);
|
||||
ESP_LOGI(TAG, "Done");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
/* struct holding devices's runtime configuration */
|
||||
|
||||
typedef struct {
|
||||
int8_t lorasf; // 7-12, lora spreadfactor
|
||||
int8_t txpower; // 2-15, lora tx power
|
||||
int8_t adrmode; // 0=disabled, 1=enabled
|
||||
int8_t screensaver; // 0=disabled, 1=enabled
|
||||
int8_t screenon; // 0=disabled, 1=enabled
|
||||
int8_t countermode; // 0=cyclic unconfirmed, 1=cumulative, 2=cyclic confirmed
|
||||
int16_t rssilimit; // threshold for rssilimiter, negative value!
|
||||
int8_t wifiscancycle; // wifi scan cycle [seconds/2]
|
||||
int8_t wifichancycle; // wifi channel switch cycle [seconds/100]
|
||||
int8_t blescancycle; // BLE scan cycle [seconds]
|
||||
int8_t blescan; // 0=disabled, 1=enabled
|
||||
char version[10]; // Firmware version
|
||||
} configData_t;
|
||||
@@ -0,0 +1,40 @@
|
||||
// First things first
|
||||
#include "main.h"
|
||||
|
||||
// The mother of all embedded development...
|
||||
#include <Arduino.h>
|
||||
|
||||
// we neededthis to ESP_LOGx on arduino framework
|
||||
#include "esp32-hal-log.h"
|
||||
|
||||
#include <String.h>
|
||||
|
||||
// std::set for unified array functions
|
||||
#include <set>
|
||||
|
||||
// OLED Display
|
||||
#include <U8x8lib.h>
|
||||
|
||||
// LMIC-Arduino LoRaWAN Stack
|
||||
#include <lmic.h>
|
||||
#include <hal/hal.h>
|
||||
|
||||
// configData_t
|
||||
#include "configmanager.h"
|
||||
|
||||
extern uint8_t mydata[];
|
||||
extern uint64_t uptimecounter;
|
||||
extern int macnum, blenum, countermode, screensaver, adrmode, lorasf, txpower, rlim;
|
||||
extern bool joinstate;
|
||||
|
||||
extern osjob_t sendjob;
|
||||
|
||||
extern std::set<uint64_t, std::greater <uint64_t> > macs;
|
||||
|
||||
extern U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8;
|
||||
|
||||
extern configData_t cfg;
|
||||
|
||||
#ifdef BLECOUNTER
|
||||
extern int scanTime;
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Pycom Limited.
|
||||
*
|
||||
* This software is licensed under the GNU GPL version 3 or any
|
||||
* later version, with permitted additional terms. For more information
|
||||
* see the Pycom Licence v1.0 document supplied with this file, or
|
||||
* available at https://www.pycom.io/opensource/licensing
|
||||
*/
|
||||
|
||||
#ifndef _ANTENNA_H_
|
||||
#define _ANTENNA_H_
|
||||
|
||||
typedef enum {
|
||||
ANTENNA_TYPE_INTERNAL = 0,
|
||||
ANTENNA_TYPE_EXTERNAL
|
||||
} antenna_type_t;
|
||||
|
||||
extern void antenna_init (void);
|
||||
extern void antenna_select (antenna_type_t antenna_type);
|
||||
|
||||
#endif /* _ANTENNA_H_ */
|
||||
@@ -0,0 +1,24 @@
|
||||
// Hardware related definitions for Heltec LoRa-32 Board
|
||||
|
||||
#define HELTEC
|
||||
#define HAS_DISPLAY // has OLED-Display
|
||||
#define HAS_LED // has on usable board LED
|
||||
#define HAS_BUTTON // has onboard button
|
||||
#define CFG_sx1276_radio 1
|
||||
|
||||
// re-define pin definitions of pins_arduino.h
|
||||
#define PIN_SPI_SS 18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select Input
|
||||
#define PIN_SPI_MOSI 27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input
|
||||
#define PIN_SPI_MISO 19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output
|
||||
#define PIN_SPI_SCK 5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input
|
||||
|
||||
// non arduino pin definitions
|
||||
#define RST 14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger Input
|
||||
#define DIO0 26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done
|
||||
#define DIO1 33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout
|
||||
#define DIO2 32 // ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only)
|
||||
|
||||
// Hardware pin definitions for Heltec LoRa-32 Board with OLED SSD1306 I2C Display
|
||||
#define OLED_RST 16 // ESP32 GPIO16 (Pin16) -- SD1306 Reset
|
||||
#define OLED_SDA 4 // ESP32 GPIO4 (Pin4) -- SD1306 Data
|
||||
#define OLED_SCL 15 // ESP32 GPIO15 (Pin15) -- SD1306 Clock
|
||||
@@ -0,0 +1,18 @@
|
||||
// Hardware related definitions for Pycom LoPy Board (not: LoPy4)
|
||||
|
||||
#define LOPY
|
||||
#define CFG_sx1272_radio 1
|
||||
|
||||
// Hardware pin definitions for Pycom LoPy board
|
||||
#define PIN_SPI_SS 17
|
||||
#define PIN_SPI_MOSI 27
|
||||
#define PIN_SPI_MISO 19
|
||||
#define PIN_SPI_SCK 5
|
||||
#define RST 18
|
||||
#define DIO0 23 // LoRa IRQ
|
||||
#define DIO1 23 // workaround
|
||||
#define DIO2 23 // workaround
|
||||
|
||||
// select WIFI antenna (internal = onboard / external = u.fl socket)
|
||||
#define PIN_ANTENNA_SWITCH 16
|
||||
#define WIFI_LOPY_ANTENNA ANTENNA_TYPE_INTERNAL
|
||||
@@ -0,0 +1,18 @@
|
||||
// Hardware related definitions for Pycom LoPy Board (not: LoPy4)
|
||||
|
||||
#define LOPY
|
||||
#define CFG_sx1276_radio 1
|
||||
|
||||
// Hardware pin definitions for Pycom LoPy4 board
|
||||
#define PIN_SPI_SS 18
|
||||
#define PIN_SPI_MOSI 27
|
||||
#define PIN_SPI_MISO 19
|
||||
#define PIN_SPI_SCK 5
|
||||
#define RST LMIC_UNUSED_PIN
|
||||
#define DIO0 23 // LoRa IRQ
|
||||
#define DIO1 23 // workaround
|
||||
#define DIO2 23 // workaround
|
||||
|
||||
// select WIFI antenna (internal = onboard / external = u.fl socket)
|
||||
#define PIN_ANTENNA_SWITCH 21
|
||||
#define WIFI_LOPY_ANTENNA ANTENNA_TYPE_INTERNAL
|
||||
@@ -0,0 +1,48 @@
|
||||
// Hardware related definitions for TTGO V2 Board
|
||||
|
||||
#define TTGO
|
||||
#define HAS_DISPLAY // has OLED-Display
|
||||
#define CFG_sx1276_radio 1
|
||||
|
||||
// re-define pin definitions of pins_arduino.h
|
||||
#define PIN_SPI_SS 18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select Input
|
||||
#define PIN_SPI_MOSI 27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input
|
||||
#define PIN_SPI_MISO 19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output
|
||||
#define PIN_SPI_SCK 5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input
|
||||
|
||||
// non arduino pin definitions
|
||||
#define RST LMIC_UNUSED_PIN // not sure
|
||||
#define DIO0 26 // wired on PCB
|
||||
#define DIO1 33 // needs to be wired external
|
||||
#define DIO2 32 // needs to be wired external (but not necessary for LoRa)
|
||||
|
||||
// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display
|
||||
#define OLED_RST U8X8_PIN_NONE // to be checked if really not connected
|
||||
#define OLED_SDA 21 // ESP32 GPIO4 (Pin4) -- SD1306 Data
|
||||
#define OLED_SCL 22 // ESP32 GPIO15 (Pin15) -- SD1306 Clock
|
||||
|
||||
|
||||
/*
|
||||
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})
|
||||
|
||||
{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!
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/************************************************************
|
||||
* LMIC LoRaWAN configuration
|
||||
*
|
||||
* Read the values from TTN console (or whatever applies)
|
||||
*
|
||||
************************************************************/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
/*
|
||||
|
||||
// Only define DEVEUI here if you don't want it to be derived from device's MAC address
|
||||
// Use little endian format (lsb)
|
||||
|
||||
//static const u1_t DEVEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
// This EUI must be in little-endian format, so least-significant-byte
|
||||
// first. When copying an EUI from ttnctl output, this means to reverse
|
||||
// the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,
|
||||
// 0x70.
|
||||
static const u1_t APPEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5, 0xB3, 0x70 };
|
||||
|
||||
// This key should be in big endian format (or, since it is not really a
|
||||
// number but a block of memory, endianness does not really apply). In
|
||||
// practice, a key taken from ttnctl can be copied as-is.
|
||||
// The key shown here is the semtech default key.
|
||||
static const u1_t APPKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
*/
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
|
||||
// Basic Config
|
||||
#include "main.h"
|
||||
// #include <Arduino.h>
|
||||
|
||||
#include "globals.h"
|
||||
#include "loraconf.h"
|
||||
|
||||
// LMIC-Arduino LoRaWAN Stack
|
||||
#include <lmic.h>
|
||||
#include <hal/hal.h>
|
||||
|
||||
// needs to be defined here
|
||||
uint8_t mydata[] = "0000";
|
||||
|
||||
// Local logging Tag
|
||||
static const char *TAG = "lorawan";
|
||||
|
||||
// function defined in main.cpp
|
||||
void set_onboard_led(int state);
|
||||
|
||||
// functions defined in rcommand.cpp
|
||||
void rcommand(int cmd, int arg);
|
||||
void switch_lora(int sf, int tx);
|
||||
|
||||
// DevEUI generator using devices's MAC address
|
||||
void gen_lora_deveui(uint8_t *pdeveui) {
|
||||
uint8_t *p = pdeveui, dmac[6];
|
||||
int i = 0;
|
||||
esp_efuse_mac_get_default(dmac);
|
||||
// deveui is LSB, we reverse it so TTN DEVEUI display
|
||||
// will remain the same as MAC address
|
||||
// MAC is 6 bytes, devEUI 8, set first 2 ones
|
||||
// with an arbitrary value
|
||||
*p++ = 0xFF;
|
||||
*p++ = 0xFE;
|
||||
// Then next 6 bytes are mac address reversed
|
||||
for ( i=0; i<6 ; i++) {
|
||||
*p++ = dmac[5-i];
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef VERBOSE
|
||||
|
||||
// Display a key
|
||||
void printKey(const char * name, const uint8_t * key, uint8_t len, bool lsb) {
|
||||
uint8_t start=lsb?len:0;
|
||||
uint8_t end = lsb?0:len;
|
||||
const uint8_t * p ;
|
||||
char keystring[len+1] = "", keybyte[3];
|
||||
for (uint8_t i=0; i<len ; i++) {
|
||||
p = lsb ? key+len-i-1 : key+i;
|
||||
sprintf(keybyte, "%02X", * p);
|
||||
strncat(keystring, keybyte, 2);
|
||||
}
|
||||
ESP_LOGI(TAG, "%s: %s", name, keystring);
|
||||
}
|
||||
|
||||
// Display OTAA keys
|
||||
void printKeys(void) {
|
||||
// LMIC may not have used callback to fill
|
||||
// all EUI buffer so we do it here to a temp
|
||||
// buffer to be able to display them
|
||||
uint8_t buf[32];
|
||||
os_getDevEui((u1_t*) buf);
|
||||
printKey("DevEUI", buf, 8, true);
|
||||
os_getArtEui((u1_t*) buf);
|
||||
printKey("AppEUI", buf, 8, true);
|
||||
os_getDevKey((u1_t*) buf);
|
||||
printKey("AppKey", buf, 16, false);
|
||||
}
|
||||
|
||||
#endif // VERBOSE
|
||||
|
||||
void do_send(osjob_t* j){
|
||||
mydata[0] = (macnum & 0x0000ff00) >> 8;
|
||||
mydata[1] = macnum & 0x000000ff;
|
||||
mydata[2] = (blenum & 0x0000ff00) >> 8;
|
||||
mydata[3] = blenum & 0x000000ff;
|
||||
|
||||
// Check if there is not a current TX/RX job running
|
||||
if (LMIC.opmode & OP_TXRXPEND) {
|
||||
ESP_LOGI(TAG, "OP_TXRXPEND, not sending");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "LORA BUSY");
|
||||
} else {
|
||||
// Prepare upstream data transmission at the next possible time.
|
||||
LMIC_setTxData2(1, mydata, sizeof(mydata)-1, (cfg.countermode & 0x02));
|
||||
ESP_LOGI(TAG, "Packet queued");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "PACKET QUEUED");
|
||||
set_onboard_led(1);
|
||||
}
|
||||
// Next TX is scheduled after TX_COMPLETE event.
|
||||
}
|
||||
|
||||
void onEvent (ev_t ev) {
|
||||
switch(ev) {
|
||||
case EV_SCAN_TIMEOUT:
|
||||
ESP_LOGI(TAG, "EV_SCAN_TIMEOUT");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "SCAN TIMEOUT");
|
||||
break;
|
||||
case EV_BEACON_FOUND:
|
||||
ESP_LOGI(TAG, "EV_BEACON_FOUND");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "BEACON FOUND");
|
||||
break;
|
||||
case EV_BEACON_MISSED:
|
||||
ESP_LOGI(TAG, "EV_BEACON_MISSED");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "BEACON MISSED");
|
||||
break;
|
||||
case EV_BEACON_TRACKED:
|
||||
ESP_LOGI(TAG, "EV_BEACON_TRACKED");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "BEACON TRACKED");
|
||||
break;
|
||||
case EV_JOINING:
|
||||
ESP_LOGI(TAG, "EV_JOINING");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "JOINING");
|
||||
break;
|
||||
case EV_JOINED:
|
||||
ESP_LOGI(TAG, "EV_JOINED");
|
||||
u8x8.clearLine(6); // erase "Join Wait" message from display, see main.cpp
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "JOINED");
|
||||
// Disable link check validation (automatically enabled
|
||||
// during join, but not supported by TTN at this time).
|
||||
LMIC_setLinkCheckMode(0);
|
||||
// set data rate adaptation
|
||||
LMIC_setAdrMode(cfg.adrmode);
|
||||
// Set data rate and transmit power (note: txpower seems to be ignored by the library)
|
||||
switch_lora(cfg.lorasf,cfg.txpower);
|
||||
joinstate=true;
|
||||
// show effective LoRa parameters after join
|
||||
ESP_LOGI(TAG, "ADR=%i, SF=%i, TXPOWER=%i", cfg.adrmode, cfg.lorasf, cfg.txpower);
|
||||
break;
|
||||
case EV_RFU1:
|
||||
ESP_LOGI(TAG, "EV_RFU1");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "RFUI");
|
||||
break;
|
||||
case EV_JOIN_FAILED:
|
||||
ESP_LOGI(TAG, "EV_JOIN_FAILED");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "JOIN FAILED");
|
||||
break;
|
||||
case EV_REJOIN_FAILED:
|
||||
ESP_LOGI(TAG, "EV_REJOIN_FAILED");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "REJOIN FAILED");
|
||||
break;
|
||||
case EV_TXCOMPLETE:
|
||||
ESP_LOGI(TAG, "EV_TXCOMPLETE (includes waiting for RX windows)");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "TX COMPLETE");
|
||||
set_onboard_led(0);
|
||||
if (LMIC.txrxFlags & TXRX_ACK) {
|
||||
ESP_LOGI(TAG, "Received ack");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "RECEIVED ACK");
|
||||
}
|
||||
if (LMIC.dataLen) {
|
||||
ESP_LOGI(TAG, "Received %i bytes of payload", LMIC.dataLen);
|
||||
u8x8.clearLine(6);
|
||||
u8x8.setCursor(0, 6);
|
||||
u8x8.printf("Rcvd %i bytes", LMIC.dataLen);
|
||||
u8x8.clearLine(7);
|
||||
u8x8.setCursor(0, 7);
|
||||
// LMIC.snr = SNR twos compliment [dB] * 4
|
||||
// LMIC.rssi = RSSI [dBm] (-196...+63)
|
||||
u8x8.printf("RSSI %d SNR %d", LMIC.rssi, (signed char)LMIC.snr / 4);
|
||||
// check if payload received on command port, then call remote command interpreter
|
||||
if ( (LMIC.txrxFlags & TXRX_PORT) && (LMIC.frame[LMIC.dataBeg-1] == RCMDPORT ) ) {
|
||||
// caution: buffering LMIC values here because rcommand() can modify LMIC.frame
|
||||
unsigned char* buffer = new unsigned char[MAX_LEN_FRAME];
|
||||
memcpy(buffer, LMIC.frame, MAX_LEN_FRAME); //Copy data from cfg to char*
|
||||
int i, k = LMIC.dataBeg, l = LMIC.dataBeg+LMIC.dataLen-2;
|
||||
for (i=k; i<=l; i+=2)
|
||||
rcommand(buffer[i], buffer[i+1]);
|
||||
delete[] buffer; //free memory
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EV_LOST_TSYNC:
|
||||
ESP_LOGI(TAG, "EV_LOST_TSYNC");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "LOST TSYNC");
|
||||
break;
|
||||
case EV_RESET:
|
||||
ESP_LOGI(TAG, "EV_RESET");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "RESET");
|
||||
break;
|
||||
case EV_RXCOMPLETE:
|
||||
// data received in ping slot
|
||||
ESP_LOGI(TAG, "EV_RXCOMPLETE");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "RX COMPLETE");
|
||||
break;
|
||||
case EV_LINK_DEAD:
|
||||
ESP_LOGI(TAG, "EV_LINK_DEAD");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "LINK DEAD");
|
||||
break;
|
||||
case EV_LINK_ALIVE:
|
||||
ESP_LOGI(TAG, "EV_LINK_ALIVE");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.drawString(0, 7, "LINK ALIVE");
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "Unknown event");
|
||||
u8x8.clearLine(7);
|
||||
u8x8.setCursor(0, 7);
|
||||
u8x8.printf("UNKNOWN EVENT %d", ev);
|
||||
break;
|
||||
}
|
||||
}
|
||||
+424
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
*
|
||||
* Oliver Brandmueller <ob@sysadm.in> 2017/2018
|
||||
* Klaus Wilting <verkehrsrot@arcor.de> 2018
|
||||
*
|
||||
* some lines of code taken from:
|
||||
*
|
||||
* Copyright (c) 2017, Łukasz Marcin Podkalicki <lpodkalicki@gmail.com>
|
||||
* ESP32/016 WiFi Sniffer.
|
||||
* https://github.com/lpodkalicki/blog/tree/master/esp32/016_wifi_sniffer
|
||||
*
|
||||
* Arduino-LMIC Library
|
||||
* TTN OTAA Example
|
||||
* https://github.com/matthijskooijman/arduino-lmic/blob/master/examples/ttn-otaa/
|
||||
*
|
||||
* nkolban esp32 snippets
|
||||
* BLE Scan
|
||||
* https://github.com/nkolban/esp32-snippets/tree/master/cpp_utils/tests/BLETests/Arduino/BLE_scan
|
||||
*
|
||||
* parts of code in lorawan.cpp has been grabbed from RadioHead Library
|
||||
*/
|
||||
|
||||
// First things first
|
||||
#include "main.h"
|
||||
|
||||
// std::set for unified array functions
|
||||
#include <set>
|
||||
|
||||
// OLED driver
|
||||
#include <U8x8lib.h>
|
||||
|
||||
#ifdef HAS_DISPLAY
|
||||
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(OLED_RST, OLED_SCL, OLED_SDA);
|
||||
#else
|
||||
U8X8_NULL u8x8;
|
||||
#endif
|
||||
|
||||
// LMIC-Arduino LoRaWAN Stack
|
||||
#include <lmic.h>
|
||||
#include <hal/hal.h>
|
||||
|
||||
// Basic Config
|
||||
#include "loraconf.h"
|
||||
#include "configmanager.h"
|
||||
|
||||
// WiFi Functions
|
||||
#include <esp_wifi.h>
|
||||
#include <esp_wifi_types.h>
|
||||
#include <esp_system.h>
|
||||
#include <esp_event.h>
|
||||
#include <esp_event_loop.h>
|
||||
#include <esp_spi_flash.h>
|
||||
|
||||
configData_t cfg; // struct holds current device configuration
|
||||
osjob_t sendjob, initjob; // LMIC
|
||||
|
||||
// Initialize global variables
|
||||
int macnum = 0, blenum = 0;
|
||||
uint32_t uptimecounter = 0;
|
||||
bool joinstate = false;
|
||||
extern uint8_t mydata[];
|
||||
|
||||
std::set<uint64_t, std::greater <uint64_t> > macs; // storage holds MAC frames
|
||||
|
||||
// this variable will be changed in the ISR, and read in main loop
|
||||
static volatile bool ButtonTriggered = false;
|
||||
|
||||
// local Tag for logging
|
||||
static const char *TAG = "paxcnt";
|
||||
// Note: Log level control seems working during runtime, so we need to switch loglevel
|
||||
// by compiler build option in platformio.ini
|
||||
#ifndef VERBOSE
|
||||
int redirect_log(const char * fmt, va_list args) {
|
||||
//do nothing
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// defined in configmanager.cpp
|
||||
void eraseConfig(void);
|
||||
void saveConfig(void);
|
||||
void loadConfig(void);
|
||||
|
||||
|
||||
/* begin LMIC specific parts ------------------------------------------------------------ */
|
||||
|
||||
// defined in lorawan.cpp
|
||||
void gen_lora_deveui(uint8_t * pdeveui);
|
||||
#ifdef VERBOSE
|
||||
void printKeys(void);
|
||||
#endif // VERBOSE
|
||||
|
||||
// LMIC callback functions
|
||||
void os_getArtEui (u1_t *buf) { memcpy(buf, APPEUI, 8);}
|
||||
void os_getDevKey (u1_t *buf) { memcpy(buf, APPKEY, 16);}
|
||||
#ifdef DEVEUI // if DEVEUI defined in loraconf.h use that and hardwire it in code ...
|
||||
void os_getDevEui (u1_t *buf) { memcpy(buf, DEVEUI, 8);}
|
||||
#else // ... otherwise generate DEVEUI at runtime from devices's MAC
|
||||
void os_getDevEui (u1_t *buf) { gen_lora_deveui(buf);}
|
||||
#endif
|
||||
|
||||
// LMIC enhanced Pin mapping
|
||||
const lmic_pinmap lmic_pins = {
|
||||
.mosi = PIN_SPI_MOSI,
|
||||
.miso = PIN_SPI_MISO,
|
||||
.sck = PIN_SPI_SCK,
|
||||
.nss = PIN_SPI_SS,
|
||||
.rxtx = LMIC_UNUSED_PIN,
|
||||
.rst = RST,
|
||||
.dio = {DIO0, DIO1, DIO2}
|
||||
};
|
||||
|
||||
// LMIC functions
|
||||
void onEvent(ev_t ev);
|
||||
void do_send(osjob_t* j);
|
||||
|
||||
// LoRaWAN Initjob
|
||||
static void lora_init (osjob_t* j) {
|
||||
// reset MAC state
|
||||
LMIC_reset();
|
||||
// This tells LMIC to make the receive windows bigger, in case your clock is 1% faster or slower.
|
||||
LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
|
||||
// start joining
|
||||
LMIC_startJoining();
|
||||
}
|
||||
|
||||
// LMIC Task
|
||||
void lorawan_loop(void * pvParameters) {
|
||||
configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check
|
||||
while(1) {
|
||||
os_runloop_once();
|
||||
vTaskDelay(10/portTICK_PERIOD_MS);
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
/* end LMIC specific parts --------------------------------------------------------------- */
|
||||
|
||||
|
||||
|
||||
/* beginn hardware specific parts -------------------------------------------------------- */
|
||||
|
||||
#ifdef LOPY
|
||||
// defined in antenna.cpp
|
||||
void antenna_init (void);
|
||||
void antenna_select (antenna_type_t antenna_type);
|
||||
#endif
|
||||
|
||||
#if defined BLECOUNTER
|
||||
void BLECount(void);
|
||||
#else
|
||||
btStop();
|
||||
#endif
|
||||
|
||||
void set_onboard_led(int st){
|
||||
#ifdef HAS_LED
|
||||
switch (st) {
|
||||
case 1: digitalWrite(LED_BUILTIN, HIGH); break;
|
||||
case 0: digitalWrite(LED_BUILTIN, LOW); break;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef HAS_BUTTON
|
||||
// Button Handling, board dependent -> perhaps to be moved to new hal.cpp
|
||||
// IRAM_ATTR necessary here, see https://github.com/espressif/arduino-esp32/issues/855
|
||||
void IRAM_ATTR isr_button_pressed(void) {
|
||||
ButtonTriggered++; }
|
||||
#endif
|
||||
|
||||
/* end hardware specific parts -------------------------------------------------------- */
|
||||
|
||||
|
||||
/* begin wifi specific parts ---------------------------------------------------------- */
|
||||
|
||||
// defined in wifisniffer.cpp
|
||||
void wifi_sniffer_init(void);
|
||||
void wifi_sniffer_set_channel(uint8_t channel);
|
||||
void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
|
||||
|
||||
//WiFi Sniffer Task
|
||||
void wifi_sniffer_loop(void * pvParameters) {
|
||||
|
||||
configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check
|
||||
uint8_t channel = 1;
|
||||
int nloop=0, lorawait=0;
|
||||
|
||||
while (true) {
|
||||
nloop++;
|
||||
vTaskDelay(cfg.wifichancycle*10 / portTICK_PERIOD_MS);
|
||||
yield();
|
||||
wifi_sniffer_set_channel(channel);
|
||||
channel = (channel % WIFI_CHANNEL_MAX) + 1;
|
||||
|
||||
// duration of one wifi scan loop reached? then send data and begin new scan cycle
|
||||
if( nloop >= ((100 / cfg.wifichancycle) * (cfg.wifiscancycle * 2)) ) {
|
||||
u8x8.setPowerSave(!cfg.screenon); // set display on if enabled
|
||||
nloop = 0; // reset wlan sniffing loop counter
|
||||
|
||||
// execute BLE count if BLE function is enabled
|
||||
#ifdef BLECOUNTER
|
||||
if ( cfg.blescan )
|
||||
BLECount();
|
||||
#endif
|
||||
|
||||
// Prepare and execute LoRaWAN data upload
|
||||
u8x8.setCursor(0,4);
|
||||
u8x8.printf("MAC#: %4i", macnum);
|
||||
do_send(&sendjob); // send payload
|
||||
vTaskDelay(500/portTICK_PERIOD_MS);
|
||||
yield();
|
||||
|
||||
// clear counter if not in cumulative counter mode
|
||||
if ( cfg.countermode != 1 ) {
|
||||
macs.erase(macs.begin(), macs.end()); // clear RAM
|
||||
macnum = 0;
|
||||
u8x8.clearLine(0); u8x8.clearLine(1); // clear Display counter
|
||||
}
|
||||
|
||||
// wait until payload is sent, while wifi scanning and mac counting task continues
|
||||
lorawait = 0;
|
||||
while(LMIC.opmode & OP_TXRXPEND) {
|
||||
if(!lorawait) u8x8.drawString(0,6,"LoRa wait ");
|
||||
lorawait++;
|
||||
// in case sending really fails: reset and rejoin network
|
||||
if( (lorawait % MAXLORARETRY ) == 0) {
|
||||
ESP_LOGI(TAG, "Payload not sent, trying reset and rejoin");
|
||||
esp_restart();
|
||||
};
|
||||
vTaskDelay(1000/portTICK_PERIOD_MS);
|
||||
yield();
|
||||
}
|
||||
|
||||
u8x8.clearLine(6);
|
||||
|
||||
if (cfg.screenon && cfg.screensaver) vTaskDelay(2000/portTICK_PERIOD_MS); // pause for displaying results
|
||||
yield();
|
||||
u8x8.setPowerSave(1 && cfg.screensaver); // set display off if screensaver is enabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* end wifi specific parts ------------------------------------------------------------ */
|
||||
|
||||
// uptime counter 64bit to prevent millis() rollover after 49 days
|
||||
uint64_t uptime() {
|
||||
static uint32_t low32, high32;
|
||||
uint32_t new_low32 = millis();
|
||||
if (new_low32 < low32) high32++;
|
||||
low32 = new_low32;
|
||||
return (uint64_t) high32 << 32 | low32;
|
||||
}
|
||||
|
||||
// Print a key on display
|
||||
void DisplayKey(const uint8_t * key, uint8_t len, bool lsb) {
|
||||
uint8_t start=lsb?len:0;
|
||||
uint8_t end = lsb?0:len;
|
||||
const uint8_t * p ;
|
||||
for (uint8_t i=0; i<len ; i++) {
|
||||
p = lsb ? key+len-i-1 : key+i;
|
||||
u8x8.printf("%02X", *p);
|
||||
}
|
||||
u8x8.printf("\n");
|
||||
}
|
||||
|
||||
void init_display(const char *Productname, const char *Version) {
|
||||
u8x8.begin();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
#ifdef HAS_DISPLAY
|
||||
uint8_t buf[32];
|
||||
u8x8.clear();
|
||||
u8x8.setFlipMode(0);
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.draw2x2String(0, 0, Productname);
|
||||
u8x8.setInverseFont(0);
|
||||
u8x8.draw2x2String(2, 2, Productname);
|
||||
delay(1500);
|
||||
u8x8.clear();
|
||||
u8x8.setFlipMode(1);
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.draw2x2String(0, 0, Productname);
|
||||
u8x8.setInverseFont(0);
|
||||
u8x8.draw2x2String(2, 2, Productname);
|
||||
delay(1500);
|
||||
|
||||
u8x8.setFlipMode(0);
|
||||
u8x8.clear();
|
||||
|
||||
// Display chip information
|
||||
#ifdef VERBOSE
|
||||
esp_chip_info_t chip_info;
|
||||
esp_chip_info(&chip_info);
|
||||
u8x8.printf("ESP32 %d cores\nWiFi%s%s\n",
|
||||
chip_info.cores,
|
||||
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
|
||||
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
|
||||
u8x8.printf("ESP Rev.%d\n", chip_info.revision);
|
||||
u8x8.printf("%dMB %s Flash\n", spi_flash_get_chip_size() / (1024 * 1024),
|
||||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int." : "ext.");
|
||||
#endif // VERBOSE
|
||||
|
||||
u8x8.print(Productname);
|
||||
u8x8.print(" v");
|
||||
u8x8.println(PROGVERSION);
|
||||
u8x8.println("DEVEUI:");
|
||||
os_getDevEui((u1_t*) buf);
|
||||
DisplayKey(buf, 8, true);
|
||||
delay(5000);
|
||||
u8x8.clear();
|
||||
#endif // HAS_DISPLAY
|
||||
}
|
||||
|
||||
/* begin Aruino SETUP ------------------------------------------------------------ */
|
||||
|
||||
void setup() {
|
||||
|
||||
// setup debug output or silence device
|
||||
#ifdef VERBOSE
|
||||
Serial.begin(115200);
|
||||
esp_log_level_set("*", ESP_LOG_VERBOSE);
|
||||
#else
|
||||
// mute logs completely by redirecting them to silence function
|
||||
esp_log_level_set("*", ESP_LOG_NONE);
|
||||
esp_log_set_vprintf(redirect_log);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Starting %s %s", PROGNAME, PROGVERSION);
|
||||
|
||||
// ESP Event Loop
|
||||
esp_event_loop_init(NULL, NULL);
|
||||
|
||||
// Print chip information on startup
|
||||
#ifdef VERBOSE
|
||||
esp_chip_info_t chip_info;
|
||||
esp_chip_info(&chip_info);
|
||||
ESP_LOGI(TAG, "This is ESP32 chip with %d CPU cores, WiFi%s%s, silicon revision %d, %dMB %s Flash",
|
||||
chip_info.cores,
|
||||
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
|
||||
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "",
|
||||
chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024),
|
||||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");
|
||||
#endif // VERBOSE
|
||||
|
||||
// Read settings from NVRAM
|
||||
loadConfig(); // includes initialize if necessary
|
||||
|
||||
// initialize hardware -> perhaps to be moved to new hal.cpp
|
||||
#ifdef HAS_LED
|
||||
// initialize LED
|
||||
pinMode(LED_BUILTIN, OUTPUT); // white LED on Heltec board
|
||||
digitalWrite(LED_BUILTIN, LOW);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_BUTTON
|
||||
// install button interrupt
|
||||
pinMode(GPIO_NUM_0, INPUT_PULLDOWN); // button "PROG" on Heltec board
|
||||
attachInterrupt(digitalPinToInterrupt(GPIO_NUM_0), isr_button_pressed, FALLING);
|
||||
#endif
|
||||
|
||||
// initialize wifi antenna
|
||||
#ifdef LOPY
|
||||
antenna_init();
|
||||
antenna_select(WIFI_LOPY_ANTENNA);
|
||||
#endif
|
||||
|
||||
// initialize display
|
||||
init_display(PROGNAME, PROGVERSION);
|
||||
u8x8.setPowerSave(!cfg.screenon); // set display off if disabled
|
||||
u8x8.setCursor(0,5);
|
||||
u8x8.printf(!cfg.rssilimit ? "RLIM: off" : "RLIM: %4i", cfg.rssilimit);
|
||||
u8x8.drawString(0,6,"Join Wait ");
|
||||
|
||||
// output LoRaWAN keys to console
|
||||
#ifdef VERBOSE
|
||||
printKeys();
|
||||
#endif // VERBOSE
|
||||
|
||||
os_init(); // setup LMIC
|
||||
os_setCallback(&initjob, lora_init); // setup initial job & join network
|
||||
wifi_sniffer_init(); // setup wifi in monitor mode and start MAC counting
|
||||
|
||||
// Start FreeRTOS tasks
|
||||
#if CONFIG_FREERTOS_UNICORE // run all tasks on core 0 and switch off core 1
|
||||
ESP_LOGI(TAG, "Starting Lora task on core 0");
|
||||
xTaskCreatePinnedToCore(lorawan_loop, "loratask", 2048, ( void * ) 1, ( 5 | portPRIVILEGE_BIT ), NULL, 0);
|
||||
ESP_LOGI(TAG, "Starting Wifi task on core 0");
|
||||
xTaskCreatePinnedToCore(wifi_sniffer_loop, "wifisniffer", 4096, ( void * ) 1, 1, NULL, 0);
|
||||
// to come here: code for switching off core 1
|
||||
#else // run wifi task on core 0 and lora task on core 1
|
||||
ESP_LOGI(TAG, "Starting Lora task on core 1");
|
||||
xTaskCreatePinnedToCore(lorawan_loop, "loratask", 2048, ( void * ) 1, ( 5 | portPRIVILEGE_BIT ), NULL, 1);
|
||||
ESP_LOGI(TAG, "Starting Wifi task on core 0");
|
||||
xTaskCreatePinnedToCore(wifi_sniffer_loop, "wifisniffer", 4096, ( void * ) 1, 1, NULL, 0);
|
||||
#endif
|
||||
|
||||
// Kickoff first sendjob, use payload "0000"
|
||||
uint8_t mydata[] = "0000";
|
||||
do_send(&sendjob);
|
||||
}
|
||||
|
||||
/* end Aruino SETUP ------------------------------------------------------------ */
|
||||
|
||||
|
||||
/* begin Aruino LOOP ------------------------------------------------------------ */
|
||||
|
||||
// Arduino main moop, runs on core 1
|
||||
// https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/
|
||||
void loop() {
|
||||
while(1) {
|
||||
|
||||
if (ButtonTriggered) {
|
||||
ButtonTriggered = false;
|
||||
ESP_LOGI(TAG, "Button pressed, resetting device to factory defaults");
|
||||
eraseConfig();
|
||||
esp_restart();
|
||||
}
|
||||
else {
|
||||
vTaskDelay(1000/portTICK_PERIOD_MS);
|
||||
uptimecounter = uptime() / 1000; // count uptime seconds
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* end Aruino LOOP ------------------------------------------------------------ */
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
// program version
|
||||
#define PROGVERSION "1.2.0" // use max 10 chars here!
|
||||
#define PROGNAME "PAXCNT"
|
||||
|
||||
// Verbose enables serial output
|
||||
#define VERBOSE 1 // comment out to silence the device, for mute use build option
|
||||
|
||||
// set this to include BLE counting and vendor filter functions
|
||||
#define VENDORFILTER 1 // comment out if you want to count things, not people
|
||||
#define BLECOUNTER 1 // comment out if you don't want BLE count
|
||||
|
||||
// BLE scan time
|
||||
#define BLESCANTIME 30 // [seconds]
|
||||
|
||||
// WiFi Sniffer cycle interval
|
||||
#define SEND_SECS 120 // [seconds/2] -> 240 sec.
|
||||
|
||||
// WiFi sniffer config
|
||||
#define WIFI_CHANNEL_MAX 13
|
||||
#define WIFI_CHANNEL_SWITCH_INTERVAL 50 // [seconds/100] -> 0,5 sec.
|
||||
|
||||
// Default LoRa Spreadfactor
|
||||
#define LORASFDEFAULT 9 // 7 ... 12
|
||||
#define MAXLORARETRY 500 // maximum count of TX retries if LoRa busy
|
||||
#define RCMDPORT 2 // LoRaWAN Port on which device listenes for remote commands
|
||||
|
||||
// LMIC settings
|
||||
// define hardware independent LMIC settings here, settings of standard library in /lmic/config.h will be ignored
|
||||
// define hardware specifics settings in platformio.ini as build_flag for hardware environment
|
||||
|
||||
#define CFG_eu868 1
|
||||
//#define CFG_us915 1
|
||||
// This is the SX1272/SX1273 radio, which is also used on the HopeRF
|
||||
// RFM92 boards.
|
||||
//#define CFG_sx1272_radio 1
|
||||
// This is the SX1276/SX1277/SX1278/SX1279 radio, which is also used on
|
||||
// the HopeRF RFM95 boards.
|
||||
//#define CFG_sx1276_radio 1
|
||||
|
||||
// 16 μs per tick
|
||||
// LMIC requires ticks to be 15.5μs - 100 μs long
|
||||
#define US_PER_OSTICK_EXPONENT 4
|
||||
#define US_PER_OSTICK (1 << US_PER_OSTICK_EXPONENT)
|
||||
#define OSTICKS_PER_SEC (1000000 / US_PER_OSTICK)
|
||||
|
||||
// Set this to 1 to enable some basic debug output (using printf) about
|
||||
// RF settings used during transmission and reception. Set to 2 to
|
||||
// enable more verbose output. Make sure that printf is actually
|
||||
// configured (e.g. on AVR it is not by default), otherwise using it can
|
||||
// cause crashing.
|
||||
//#define LMIC_DEBUG_LEVEL 1
|
||||
|
||||
// Enable this to allow using printf() to print to the given serial port
|
||||
// (or any other Print object). This can be easy for debugging. The
|
||||
// current implementation only works on AVR, though.
|
||||
//#define LMIC_PRINTF_TO Serial
|
||||
|
||||
// Any runtime assertion failures are printed to this serial port (or
|
||||
// any other Print object). If this is unset, any failures just silently
|
||||
// halt execution.
|
||||
#define LMIC_FAILURE_TO Serial
|
||||
|
||||
// Uncomment this to disable all code related to joining
|
||||
//#define DISABLE_JOIN
|
||||
// Uncomment this to disable all code related to ping
|
||||
#define DISABLE_PING
|
||||
// Uncomment this to disable all code related to beacon tracking.
|
||||
// Requires ping to be disabled too
|
||||
#define DISABLE_BEACONS
|
||||
|
||||
// Uncomment these to disable the corresponding MAC commands.
|
||||
// Class A
|
||||
//#define DISABLE_MCMD_DCAP_REQ // duty cycle cap
|
||||
//#define DISABLE_MCMD_DN2P_SET // 2nd DN window param
|
||||
//#define DISABLE_MCMD_SNCH_REQ // set new channel
|
||||
// Class B
|
||||
//#define DISABLE_MCMD_PING_SET // set ping freq, automatically disabled by DISABLE_PING
|
||||
//#define DISABLE_MCMD_BCNI_ANS // next beacon start, automatical disabled by DISABLE_BEACON
|
||||
|
||||
// In LoRaWAN, a gateway applies I/Q inversion on TX, and nodes do the
|
||||
// same on RX. This ensures that gateways can talk to nodes and vice
|
||||
// versa, but gateways will not hear other gateways and nodes will not
|
||||
// hear other nodes. By uncommenting this macro, this inversion is
|
||||
// disabled and this node can hear other nodes. If two nodes both have
|
||||
// this macro set, they can talk to each other (but they can no longer
|
||||
// hear gateways). This should probably only be used when debugging
|
||||
// and/or when talking to the radio directly (e.g. like in the "raw"
|
||||
// example).
|
||||
//#define DISABLE_INVERT_IQ_ON_RX
|
||||
|
||||
// This allows choosing between multiple included AES implementations.
|
||||
// Make sure exactly one of these is uncommented.
|
||||
//
|
||||
// This selects the original AES implementation included LMIC. This
|
||||
// implementation is optimized for speed on 32-bit processors using
|
||||
// fairly big lookup tables, but it takes up big amounts of flash on the
|
||||
// AVR architecture.
|
||||
// #define USE_ORIGINAL_AES
|
||||
//
|
||||
// This selects the AES implementation written by Ideetroon for their
|
||||
// own LoRaWAN library. It also uses lookup tables, but smaller
|
||||
// byte-oriented ones, making it use a lot less flash space (but it is
|
||||
// also about twice as slow as the original).
|
||||
#define USE_IDEETRON_AES
|
||||
@@ -0,0 +1,214 @@
|
||||
// remote command interpreter
|
||||
// parses multiple number of command / value pairs from LoRaWAN remote command port (RCMDPORT)
|
||||
// checks commands and executes each command with 1 argument per command
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
// Local logging tag
|
||||
static const char *TAG = "rcommand";
|
||||
|
||||
// functions defined in configmanager.cpp
|
||||
void eraseConfig(void);
|
||||
void saveConfig(void);
|
||||
|
||||
// table of remote commands and assigned functions
|
||||
typedef struct {
|
||||
const int nam;
|
||||
void (*func)(int);
|
||||
const bool store;
|
||||
} cmd_t;
|
||||
|
||||
// help function to assign LoRa datarates to spreadfactor values
|
||||
void switch_lora (int sf, int tx) {
|
||||
if ( tx > 20 ) return;
|
||||
cfg.txpower = tx;
|
||||
switch (sf) {
|
||||
case 7: LMIC_setDrTxpow(DR_SF7,tx); cfg.lorasf=sf; break;
|
||||
case 8: LMIC_setDrTxpow(DR_SF8,tx); cfg.lorasf=sf; break;
|
||||
case 9: LMIC_setDrTxpow(DR_SF9,tx); cfg.lorasf=sf; break;
|
||||
case 10: LMIC_setDrTxpow(DR_SF10,tx); cfg.lorasf=sf; break;
|
||||
case 11: LMIC_setDrTxpow(DR_SF11,tx); cfg.lorasf=sf; break;
|
||||
case 12: LMIC_setDrTxpow(DR_SF12,tx); cfg.lorasf=sf; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
// set of functions that can be triggered by remote commands
|
||||
void set_reset(int val) {
|
||||
switch (val) {
|
||||
case 0: // restart device
|
||||
ESP_LOGI(TAG, "Remote command: restart device");
|
||||
u8x8.clearLine(5);
|
||||
u8x8.setCursor(0, 5);
|
||||
u8x8.printf("Reset pending ");
|
||||
vTaskDelay(10000/portTICK_PERIOD_MS); // wait for LMIC to confirm LoRa downlink to server
|
||||
esp_restart();
|
||||
break;
|
||||
case 1: // reset MAC counter
|
||||
ESP_LOGI(TAG, "Remote command: reset MAC counter");
|
||||
macs.erase(macs.begin(), macs.end()); // clear RAM
|
||||
macnum = 0;
|
||||
u8x8.clearLine(0); u8x8.clearLine(1); // clear Display counter
|
||||
u8x8.clearLine(5);
|
||||
u8x8.setCursor(0, 5);
|
||||
u8x8.printf("Reset counter ");
|
||||
break;
|
||||
case 2: // reset device to factory settings
|
||||
ESP_LOGI(TAG, "Remote command: reset device to factory settings");
|
||||
u8x8.clearLine(5);
|
||||
u8x8.setCursor(0, 5);
|
||||
u8x8.printf("Factory reset ");
|
||||
eraseConfig();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
void set_rssi(int val) {
|
||||
cfg.rssilimit = val * -1;
|
||||
ESP_LOGI(TAG, "Remote command: set RSSI limit to %i", cfg.rssilimit);
|
||||
u8x8.clearLine(5);
|
||||
u8x8.setCursor(0, 5);
|
||||
u8x8.printf(!cfg.rssilimit ? "RLIM: off" : "RLIM: -%4i", cfg.rssilimit);
|
||||
};
|
||||
|
||||
void set_wifiscancycle(int val) {
|
||||
cfg.wifiscancycle = val;
|
||||
ESP_LOGI(TAG, "Remote command: set Wifi scan cycle duration to %i seconds", cfg.wifiscancycle*2);
|
||||
};
|
||||
|
||||
void set_wifichancycle(int val) {
|
||||
cfg.wifichancycle = val;
|
||||
ESP_LOGI(TAG, "Remote command: set Wifi channel switch interval to %i seconds", cfg.wifichancycle/100);
|
||||
};
|
||||
|
||||
void set_blescancycle(int val) {
|
||||
cfg.blescancycle = val;
|
||||
ESP_LOGI(TAG, "Remote command: set Wifi channel cycle duration to %i seconds", cfg.blescancycle);
|
||||
};
|
||||
|
||||
void set_countmode(int val) {
|
||||
switch (val) {
|
||||
case 0: // cyclic unconfirmed
|
||||
cfg.countermode = 0;
|
||||
ESP_LOGI(TAG, "Remote command: set counter mode to cyclic unconfirmed");
|
||||
break;
|
||||
case 1: // cumulative
|
||||
cfg.countermode = 1;
|
||||
ESP_LOGI(TAG, "Remote command: set counter mode to cumulative");
|
||||
break;
|
||||
default: // cyclic confirmed
|
||||
cfg.countermode = 2;
|
||||
ESP_LOGI(TAG, "Remote command: set counter mode to cyclic confirmed");
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
void set_screensaver(int val) {
|
||||
ESP_LOGI(TAG, "Remote command: set screen saver to %s ", val ? "on" : "off");
|
||||
switch (val) {
|
||||
case 1: cfg.screensaver = val; break;
|
||||
default: cfg.screensaver = 0; break;
|
||||
}
|
||||
u8x8.setPowerSave(cfg.screensaver); // set display 0=on / 1=off
|
||||
};
|
||||
|
||||
void set_display(int val) {
|
||||
ESP_LOGI(TAG, "Remote command: set screen to %s", val ? "on" : "off");
|
||||
switch (val) {
|
||||
case 1: cfg.screenon = val; break;
|
||||
default: cfg.screenon = 0; break;
|
||||
}
|
||||
u8x8.setPowerSave(!cfg.screenon); // set display 0=on / 1=off
|
||||
};
|
||||
|
||||
void set_lorasf(int val) {
|
||||
ESP_LOGI(TAG, "Remote command: set LoRa SF to %i", val);
|
||||
switch_lora(val, cfg.txpower);
|
||||
};
|
||||
|
||||
void set_loraadr(int val) {
|
||||
ESP_LOGI(TAG, "Remote command: set LoRa ADR mode to %s", val ? "on" : "off");
|
||||
switch (val) {
|
||||
case 1: cfg.adrmode = val; break;
|
||||
default: cfg.adrmode = 0; break;
|
||||
}
|
||||
LMIC_setAdrMode(cfg.adrmode);
|
||||
};
|
||||
|
||||
void set_blescan(int val) {
|
||||
ESP_LOGI(TAG, "Remote command: set BLE scan mode to %s", val ? "on" : "off");
|
||||
switch (val) {
|
||||
case 1: cfg.blescan = val; break;
|
||||
default:
|
||||
cfg.blescan = 0;
|
||||
btStop();
|
||||
u8x8.clearLine(3); // clear BLE results from display
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
void set_lorapower(int val) {
|
||||
ESP_LOGI(TAG, "Remote command: set LoRa TXPOWER to %i", val);
|
||||
switch_lora(cfg.lorasf, val);
|
||||
};
|
||||
|
||||
void set_noop (int val) {
|
||||
ESP_LOGI(TAG, "Remote command: noop - doing nothing");
|
||||
};
|
||||
|
||||
void get_config (int val) {
|
||||
ESP_LOGI(TAG, "Remote command: get configuration");
|
||||
int size = sizeof(configData_t);
|
||||
// declare send buffer (char byte array)
|
||||
unsigned char *sendData = new unsigned char[size];
|
||||
// copy current configuration (struct) to send buffer
|
||||
memcpy(sendData, &cfg, size);
|
||||
LMIC_setTxData2(RCMDPORT, sendData, size-1, 0); // send data unconfirmed on RCMD Port
|
||||
delete sendData; // free memory
|
||||
ESP_LOGI(TAG, "Configuration data queued in send queue");
|
||||
};
|
||||
|
||||
void get_uptime (int val) {
|
||||
ESP_LOGI(TAG, "Remote command: get uptime");
|
||||
int size = sizeof(uptimecounter);
|
||||
unsigned char *sendData = new unsigned char[size];
|
||||
memcpy(sendData, (unsigned char*)&uptimecounter, size);
|
||||
LMIC_setTxData2(RCMDPORT, sendData, size-1, 0); // send data unconfirmed on RCMD Port
|
||||
delete sendData; // free memory
|
||||
ESP_LOGI(TAG, "Uptime queued in send queue");
|
||||
};
|
||||
|
||||
// assign previously defined functions to set of numeric remote commands
|
||||
// format: opcode, function, flag (1 = do make settings persistent / 0 = don't)
|
||||
//
|
||||
cmd_t table[] = {
|
||||
{0x01, set_rssi, true},
|
||||
{0x02, set_countmode, true},
|
||||
{0x03, set_screensaver, true},
|
||||
{0x04, set_display, true},
|
||||
{0x05, set_lorasf, true},
|
||||
{0x06, set_lorapower, true},
|
||||
{0x07, set_loraadr, true},
|
||||
{0x08, set_noop, false},
|
||||
{0x09, set_reset, false},
|
||||
{0x0a, set_wifiscancycle, true},
|
||||
{0x0b, set_wifichancycle, true},
|
||||
{0x0c, set_blescancycle, true},
|
||||
{0x0d, set_blescan, true},
|
||||
{0x80, get_config, false},
|
||||
{0x81, get_uptime, false},
|
||||
};
|
||||
|
||||
// check and execute remote command
|
||||
void rcommand(int cmd, int arg) {
|
||||
int i = sizeof(table) / sizeof(table[0]); // number of commands in command table
|
||||
bool store_flag = false;
|
||||
while(i--) {
|
||||
if(cmd == table[i].nam) { // check if valid command
|
||||
table[i].func(arg); // then execute assigned function
|
||||
if ( table[i].store ) store_flag = true; // set save flag if function needs to store configuration
|
||||
break; // exit check loop, since command was found
|
||||
}
|
||||
}
|
||||
if (store_flag) saveConfig(); // if save flag is set: store new configuration in NVS to make it persistent
|
||||
}
|
||||
+1435
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,100 @@
|
||||
#include "main.h"
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// Basic Config
|
||||
#include "globals.h"
|
||||
#include "loraconf.h"
|
||||
|
||||
// WiFi Functions
|
||||
#include <esp_wifi.h>
|
||||
#include <esp_wifi_types.h>
|
||||
#include <esp_system.h>
|
||||
#include <esp_event.h>
|
||||
#include <esp_event_loop.h>
|
||||
|
||||
// Local logging tag
|
||||
static const char *TAG = "wifisniffer";
|
||||
|
||||
static wifi_country_t wifi_country = {.cc="EU", .schan=1, .nchan=13, .policy=WIFI_COUNTRY_POLICY_AUTO};
|
||||
|
||||
#ifdef VENDORFILTER
|
||||
#include <array>
|
||||
#include <algorithm>
|
||||
#include "vendor_array.h"
|
||||
#endif
|
||||
|
||||
extern void wifi_sniffer_init(void);
|
||||
extern void wifi_sniffer_set_channel(uint8_t channel);
|
||||
extern void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
|
||||
|
||||
typedef struct {
|
||||
unsigned frame_ctrl:16;
|
||||
unsigned duration_id:16;
|
||||
uint8_t addr1[6]; /* receiver address */
|
||||
uint8_t addr2[6]; /* sender address */
|
||||
uint8_t addr3[6]; /* filtering address */
|
||||
unsigned sequence_ctrl:16;
|
||||
uint8_t addr4[6]; /* optional */
|
||||
} wifi_ieee80211_mac_hdr_t;
|
||||
|
||||
typedef struct {
|
||||
wifi_ieee80211_mac_hdr_t hdr;
|
||||
uint8_t payload[0]; /* network data ended with 4 bytes csum (CRC32) */
|
||||
} wifi_ieee80211_packet_t;
|
||||
|
||||
void wifi_sniffer_init(void) {
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
|
||||
ESP_ERROR_CHECK( esp_wifi_set_country(&wifi_country) );
|
||||
ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
|
||||
ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_NULL) );
|
||||
ESP_ERROR_CHECK( esp_wifi_start() );
|
||||
ESP_ERROR_CHECK( esp_wifi_set_max_tx_power(-128) ); // we don't need to TX, so we use lowest power level to save energy
|
||||
wifi_promiscuous_filter_t filter = {.filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // we need only MGMT frames
|
||||
ESP_ERROR_CHECK(esp_wifi_set_promiscuous_filter(&filter)); // set MAC frame filter
|
||||
ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(&wifi_sniffer_packet_handler));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true));
|
||||
}
|
||||
|
||||
void wifi_sniffer_set_channel(uint8_t channel) {
|
||||
esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
|
||||
}
|
||||
|
||||
void wifi_sniffer_packet_handler(void* buff, wifi_promiscuous_pkt_type_t type) {
|
||||
const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff;
|
||||
const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload;
|
||||
const wifi_ieee80211_mac_hdr_t *hdr = &ipkt->hdr;
|
||||
char counter [10];
|
||||
|
||||
if (( cfg.rssilimit == 0 ) || (ppkt->rx_ctrl.rssi > cfg.rssilimit )) { // rssi is negative value
|
||||
uint64_t addr2int = ( (uint64_t)hdr->addr2[0] ) | ( (uint64_t)hdr->addr2[1] << 8 ) | ( (uint64_t)hdr->addr2[2] << 16 ) | \
|
||||
( (uint64_t)hdr->addr2[3] << 24 ) | ( (uint64_t)hdr->addr2[4] << 32 ) | ( (uint64_t)hdr->addr2[5] << 40 );
|
||||
|
||||
#ifdef VENDORFILTER
|
||||
uint32_t vendor2int = ( (uint32_t)hdr->addr2[2] ) | ( (uint32_t)hdr->addr2[1] << 8 ) | ( (uint32_t)hdr->addr2[0] << 16 );
|
||||
|
||||
if ( std::find(vendors.begin(), vendors.end(), vendor2int) != vendors.end() ) {
|
||||
#endif
|
||||
macs.insert(addr2int);
|
||||
|
||||
// INFO: RSSI when adding MAC
|
||||
ESP_LOGI(TAG, "WiFi RSSI: %02d", ppkt->rx_ctrl.rssi);
|
||||
|
||||
// if new unique MAC logged increment counter on display
|
||||
if ( macs.size() > macnum ) {
|
||||
macnum = macs.size();
|
||||
itoa(macnum, counter, 10);
|
||||
u8x8.draw2x2String(0, 0, counter);
|
||||
ESP_LOGI(TAG, "MAC counter: %4i", macnum);
|
||||
}
|
||||
|
||||
|
||||
#ifdef VENDORFILTER
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Ignoring RSSI %02d (limit: %i)", ppkt->rx_ctrl.rssi, cfg.rssilimit );
|
||||
}
|
||||
yield();
|
||||
}
|
||||
Reference in new issue
Block a user