Merge pull request #79 from GreyRook/clang-format

WIP Clang format
This commit is contained in:
Verkehrsrot 2018-06-10 21:34:15 +02:00 committed by GitHub
commit 28f0396185
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 2271 additions and 3079 deletions

108
.clang-format Normal file
View File

@ -0,0 +1,108 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
- Regex: '.*'
Priority: 1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never
...

View File

@ -5,39 +5,43 @@
#include <driver/adc.h> #include <driver/adc.h>
#include <esp_adc_cal.h> #include <esp_adc_cal.h>
#define DEFAULT_VREF 1100 // to be done: use adc2_vref_to_gpio() to obtain a better estimate #define DEFAULT_VREF \
1100 // to be done: use adc2_vref_to_gpio() to obtain a better estimate
#define NO_OF_SAMPLES 64 // we do multisampling #define NO_OF_SAMPLES 64 // we do multisampling
// Local logging tag // Local logging tag
static const char TAG[] = "main"; static const char TAG[] = "main";
static void print_char_val_type(esp_adc_cal_value_t val_type) static void print_char_val_type(esp_adc_cal_value_t val_type) {
{
if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) { if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
ESP_LOGI(TAG,"ADC characterization based on Two Point values stored in eFuse"); ESP_LOGI(TAG,
"ADC characterization based on Two Point values stored in eFuse");
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) { } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
ESP_LOGI(TAG,"ADC characterization based on reference voltage stored in eFuse"); ESP_LOGI(TAG,
"ADC characterization based on reference voltage stored in eFuse");
} else { } else {
ESP_LOGI(TAG,"ADC characterization based on default reference voltage"); ESP_LOGI(TAG, "ADC characterization based on default reference voltage");
} }
} }
uint16_t read_voltage(void) uint16_t read_voltage(void) {
{
static const adc1_channel_t channel = HAS_BATTERY_PROBE; static const adc1_channel_t channel = HAS_BATTERY_PROBE;
static const adc_atten_t atten = ADC_ATTEN_DB_11; static const adc_atten_t atten = ADC_ATTEN_DB_11;
static const adc_unit_t unit = ADC_UNIT_1; static const adc_unit_t unit = ADC_UNIT_1;
//configure ADC1 // configure ADC1
ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_12)); ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_12));
ESP_ERROR_CHECK(adc1_config_channel_atten(channel, atten)); ESP_ERROR_CHECK(adc1_config_channel_atten(channel, atten));
//calibrate ADC1 // calibrate ADC1
esp_adc_cal_characteristics_t *adc_chars = (esp_adc_cal_characteristics_t *) calloc(1, sizeof(esp_adc_cal_characteristics_t)); esp_adc_cal_characteristics_t *adc_chars =
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars); (esp_adc_cal_characteristics_t *)calloc(
1, sizeof(esp_adc_cal_characteristics_t));
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(
unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars);
print_char_val_type(val_type); print_char_val_type(val_type);
//multisample ADC1 // multisample ADC1
uint32_t adc_reading = 0; uint32_t adc_reading = 0;
for (int i = 0; i < NO_OF_SAMPLES; i++) { for (int i = 0; i < NO_OF_SAMPLES; i++) {
adc_reading += adc1_get_raw(channel); adc_reading += adc1_get_raw(channel);
@ -45,12 +49,13 @@ uint16_t read_voltage(void)
adc_reading /= NO_OF_SAMPLES; adc_reading /= NO_OF_SAMPLES;
//Convert adc_reading to voltage in mV // Convert adc_reading to voltage in mV
uint16_t voltage = (uint16_t) esp_adc_cal_raw_to_voltage(adc_reading, adc_chars); uint16_t voltage =
#ifdef BATT_FACTOR (uint16_t)esp_adc_cal_raw_to_voltage(adc_reading, adc_chars);
#ifdef BATT_FACTOR
voltage *= BATT_FACTOR; voltage *= BATT_FACTOR;
#endif #endif
ESP_LOGI(TAG,"Raw: %d / Voltage: %dmV", adc_reading, voltage); ESP_LOGI(TAG, "Raw: %d / Voltage: %dmV", adc_reading, voltage);
return voltage; return voltage;
} }
#endif // HAS_BATTERY_PROBE #endif // HAS_BATTERY_PROBE

View File

@ -1,4 +1,5 @@
/* switches wifi antenna, if board has switch to select internal and external antenna */ /* switches wifi antenna, if board has switch to select internal and external
* antenna */
#ifdef HAS_ANTENNA_SWITCH #ifdef HAS_ANTENNA_SWITCH
@ -7,10 +8,7 @@
// Local logging tag // Local logging tag
static const char TAG[] = "wifi"; static const char TAG[] = "wifi";
typedef enum { typedef enum { ANTENNA_INT = 0, ANTENNA_EXT } antenna_type_t;
ANTENNA_INT = 0,
ANTENNA_EXT
} antenna_type_t;
void antenna_init(void) { void antenna_init(void) {
gpio_config_t gpioconf = {.pin_bit_mask = 1ull << HAS_ANTENNA_SWITCH, gpio_config_t gpioconf = {.pin_bit_mask = 1ull << HAS_ANTENNA_SWITCH,
@ -21,7 +19,7 @@ void antenna_init(void) {
gpio_config(&gpioconf); gpio_config(&gpioconf);
} }
void antenna_select (const uint8_t _ant) { void antenna_select(const uint8_t _ant) {
if (HAS_ANTENNA_SWITCH < 32) { if (HAS_ANTENNA_SWITCH < 32) {
if (_ant == ANTENNA_EXT) { if (_ant == ANTENNA_EXT) {
GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << HAS_ANTENNA_SWITCH); GPIO_REG_WRITE(GPIO_OUT_W1TS_REG, 1 << HAS_ANTENNA_SWITCH);

View File

@ -8,13 +8,14 @@ https://github.com/nkolban/esp32-snippets/tree/master/BLE/scanner
#include "globals.h" #include "globals.h"
// Bluetooth specific includes // Bluetooth specific includes
#include <bt_types.h>
#include <esp_blufi_api.h> // needed for BLE_ADDR types, do not remove
#include <esp_bt.h> #include <esp_bt.h>
#include <esp_bt_main.h> #include <esp_bt_main.h>
#include <esp_gap_ble_api.h> #include <esp_gap_ble_api.h>
#include <esp_blufi_api.h> // needed for BLE_ADDR types, do not remove
#include <bt_types.h>
#define BT_BD_ADDR_HEX(addr) addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] #define BT_BD_ADDR_HEX(addr) \
addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]
// local Tag for logging // local Tag for logging
static const char TAG[] = "bluetooth"; static const char TAG[] = "bluetooth";
@ -23,7 +24,7 @@ static const char TAG[] = "bluetooth";
bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type); bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type);
const char *bt_addr_t_to_string(esp_ble_addr_type_t type) { const char *bt_addr_t_to_string(esp_ble_addr_type_t type) {
switch(type) { switch (type) {
case BLE_ADDR_TYPE_PUBLIC: case BLE_ADDR_TYPE_PUBLIC:
return "BLE_ADDR_TYPE_PUBLIC"; return "BLE_ADDR_TYPE_PUBLIC";
case BLE_ADDR_TYPE_RANDOM: case BLE_ADDR_TYPE_RANDOM:
@ -38,45 +39,81 @@ const char *bt_addr_t_to_string(esp_ble_addr_type_t type) {
} // bt_addr_t_to_string } // bt_addr_t_to_string
const char *btsig_gap_type(uint32_t gap_type) { const char *btsig_gap_type(uint32_t gap_type) {
switch (gap_type) switch (gap_type) {
{ case 0x01:
case 0x01: return "Flags"; return "Flags";
case 0x02: return "Incomplete List of 16-bit Service Class UUIDs"; case 0x02:
case 0x03: return "Complete List of 16-bit Service Class UUIDs"; return "Incomplete List of 16-bit Service Class UUIDs";
case 0x04: return "Incomplete List of 32-bit Service Class UUIDs"; case 0x03:
case 0x05: return "Complete List of 32-bit Service Class UUIDs"; return "Complete List of 16-bit Service Class UUIDs";
case 0x06: return "Incomplete List of 128-bit Service Class UUIDs"; case 0x04:
case 0x07: return "Complete List of 128-bit Service Class UUIDs"; return "Incomplete List of 32-bit Service Class UUIDs";
case 0x08: return "Shortened Local Name"; case 0x05:
case 0x09: return "Complete Local Name"; return "Complete List of 32-bit Service Class UUIDs";
case 0x0A: return "Tx Power Level"; case 0x06:
case 0x0D: return "Class of Device"; return "Incomplete List of 128-bit Service Class UUIDs";
case 0x0E: return "Simple Pairing Hash C/C-192"; case 0x07:
case 0x0F: return "Simple Pairing Randomizer R/R-192"; return "Complete List of 128-bit Service Class UUIDs";
case 0x10: return "Device ID/Security Manager TK Value"; case 0x08:
case 0x11: return "Security Manager Out of Band Flags"; return "Shortened Local Name";
case 0x12: return "Slave Connection Interval Range"; case 0x09:
case 0x14: return "List of 16-bit Service Solicitation UUIDs"; return "Complete Local Name";
case 0x1F: return "List of 32-bit Service Solicitation UUIDs"; case 0x0A:
case 0x15: return "List of 128-bit Service Solicitation UUIDs"; return "Tx Power Level";
case 0x16: return "Service Data - 16-bit UUID"; case 0x0D:
case 0x20: return "Service Data - 32-bit UUID"; return "Class of Device";
case 0x21: return "Service Data - 128-bit UUID"; case 0x0E:
case 0x22: return "LE Secure Connections Confirmation Value"; return "Simple Pairing Hash C/C-192";
case 0x23: return "LE Secure Connections Random Value"; case 0x0F:
case 0x24: return "URI"; return "Simple Pairing Randomizer R/R-192";
case 0x25: return "Indoor Positioning"; case 0x10:
case 0x26: return "Transport Discovery Data"; return "Device ID/Security Manager TK Value";
case 0x17: return "Public Target Address"; case 0x11:
case 0x18: return "Random Target Address"; return "Security Manager Out of Band Flags";
case 0x19: return "Appearance"; case 0x12:
case 0x1A: return "Advertising Interval"; return "Slave Connection Interval Range";
case 0x1B: return "LE Bluetooth Device Address"; case 0x14:
case 0x1C: return "LE Role"; return "List of 16-bit Service Solicitation UUIDs";
case 0x1D: return "Simple Pairing Hash C-256"; case 0x1F:
case 0x1E: return "Simple Pairing Randomizer R-256"; return "List of 32-bit Service Solicitation UUIDs";
case 0x3D: return "3D Information Data"; case 0x15:
case 0xFF: return "Manufacturer Specific Data"; return "List of 128-bit Service Solicitation UUIDs";
case 0x16:
return "Service Data - 16-bit UUID";
case 0x20:
return "Service Data - 32-bit UUID";
case 0x21:
return "Service Data - 128-bit UUID";
case 0x22:
return "LE Secure Connections Confirmation Value";
case 0x23:
return "LE Secure Connections Random Value";
case 0x24:
return "URI";
case 0x25:
return "Indoor Positioning";
case 0x26:
return "Transport Discovery Data";
case 0x17:
return "Public Target Address";
case 0x18:
return "Random Target Address";
case 0x19:
return "Appearance";
case 0x1A:
return "Advertising Interval";
case 0x1B:
return "LE Bluetooth Device Address";
case 0x1C:
return "LE Role";
case 0x1D:
return "Simple Pairing Hash C-256";
case 0x1E:
return "Simple Pairing Randomizer R-256";
case 0x3D:
return "3D Information Data";
case 0xFF:
return "Manufacturer Specific Data";
default: default:
return "Unknown type"; return "Unknown type";
@ -84,14 +121,14 @@ const char *btsig_gap_type(uint32_t gap_type) {
} // btsig_gap_type } // btsig_gap_type
// using IRAM_:ATTR here to speed up callback function // using IRAM_:ATTR here to speed up callback function
IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event,
{ esp_ble_gap_cb_param_t *param) {
esp_ble_gap_cb_param_t *p = (esp_ble_gap_cb_param_t *)param; esp_ble_gap_cb_param_t *p = (esp_ble_gap_cb_param_t *)param;
ESP_LOGD(TAG, "BT payload rcvd -> type: 0x%.2x -> %s", *p->scan_rst.ble_adv, btsig_gap_type(*p->scan_rst.ble_adv)); ESP_LOGD(TAG, "BT payload rcvd -> type: 0x%.2x -> %s", *p->scan_rst.ble_adv,
btsig_gap_type(*p->scan_rst.ble_adv));
switch (event) switch (event) {
{
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT:
// restart scan // restart scan
ESP_ERROR_CHECK(esp_ble_gap_start_scanning(BLESCANTIME)); ESP_ERROR_CHECK(esp_ble_gap_start_scanning(BLESCANTIME));
@ -99,49 +136,58 @@ IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb
case ESP_GAP_BLE_SCAN_RESULT_EVT: case ESP_GAP_BLE_SCAN_RESULT_EVT:
// evaluate scan results // evaluate scan results
if ( p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_CMPL_EVT) // Inquiry complete, scan is done if (p->scan_rst.search_evt ==
ESP_GAP_SEARCH_INQ_CMPL_EVT) // Inquiry complete, scan is done
{ // restart scan { // restart scan
ESP_ERROR_CHECK(esp_ble_gap_start_scanning(BLESCANTIME)); ESP_ERROR_CHECK(esp_ble_gap_start_scanning(BLESCANTIME));
return; return;
} }
if (p->scan_rst.search_evt == ESP_GAP_SEARCH_INQ_RES_EVT) // Inquiry result for a peer device if (p->scan_rst.search_evt ==
ESP_GAP_SEARCH_INQ_RES_EVT) // Inquiry result for a peer device
{ // evaluate sniffed packet { // evaluate sniffed packet
ESP_LOGD(TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x", BT_BD_ADDR_HEX(p->scan_rst.bda)); ESP_LOGD(TAG, "Device address (bda): %02x:%02x:%02x:%02x:%02x:%02x",
ESP_LOGD(TAG, "Addr_type : %s", bt_addr_t_to_string(p->scan_rst.ble_addr_type)); BT_BD_ADDR_HEX(p->scan_rst.bda));
ESP_LOGD(TAG, "Addr_type : %s",
bt_addr_t_to_string(p->scan_rst.ble_addr_type));
ESP_LOGD(TAG, "RSSI : %d", p->scan_rst.rssi); ESP_LOGD(TAG, "RSSI : %d", p->scan_rst.rssi);
if ((cfg.rssilimit) && (p->scan_rst.rssi < cfg.rssilimit )) { // rssi is negative value if ((cfg.rssilimit) &&
ESP_LOGI(TAG, "BLTH RSSI %d -> ignoring (limit: %d)", p->scan_rst.rssi, cfg.rssilimit); (p->scan_rst.rssi < cfg.rssilimit)) { // rssi is negative value
ESP_LOGI(TAG, "BLTH RSSI %d -> ignoring (limit: %d)", p->scan_rst.rssi,
cfg.rssilimit);
break; break;
} }
#ifdef VENDORFILTER #ifdef VENDORFILTER
if ((p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RANDOM) || (p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RPA_RANDOM)) { if ((p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RANDOM) ||
(p->scan_rst.ble_addr_type == BLE_ADDR_TYPE_RPA_RANDOM)) {
ESP_LOGD(TAG, "BT device filtered"); ESP_LOGD(TAG, "BT device filtered");
break; break;
} }
#endif #endif
// add this device and show new count total if it was not previously added // add this device and show new count total if it was not previously added
mac_add((uint8_t *) p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE); mac_add((uint8_t *)p->scan_rst.bda, p->scan_rst.rssi, MAC_SNIFF_BLE);
/* to be improved in vendorfilter if: /* to be improved in vendorfilter if:
// you can search for elements in the payload using the // you can search for elements in the payload using the
// function esp_ble_resolve_adv_data() // function esp_ble_resolve_adv_data()
// //
// Like this, that scans for the "Complete name" (looking inside the payload buffer) // Like this, that scans for the "Complete name" (looking inside the
payload buffer)
// uint8_t len; // uint8_t len;
// uint8_t *data = esp_ble_resolve_adv_data(p->scan_rst.ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &len); // uint8_t *data = esp_ble_resolve_adv_data(p->scan_rst.ble_adv,
ESP_BLE_AD_TYPE_NAME_CMPL, &len);
filter BLE devices using their advertisements to get filter alternative to vendor OUI filter BLE devices using their advertisements to get filter alternative to
if vendorfiltering is on, we ... vendor OUI if vendorfiltering is on, we ...
- want to count: mobile phones and tablets - want to count: mobile phones and tablets
- don't want to count: beacons, peripherals (earphones, headsets, printers), cars and machines - don't want to count: beacons, peripherals (earphones, headsets,
see printers), cars and machines see
https://github.com/nkolban/ESP32_BLE_Arduino/blob/master/src/BLEAdvertisedDevice.cpp https://github.com/nkolban/ESP32_BLE_Arduino/blob/master/src/BLEAdvertisedDevice.cpp
http://www.libelium.com/products/meshlium/smartphone-detection/ http://www.libelium.com/products/meshlium/smartphone-detection/
@ -150,9 +196,10 @@ IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb
https://www.bluetooth.com/specifications/assigned-numbers/baseband https://www.bluetooth.com/specifications/assigned-numbers/baseband
"The Class of Device (CoD) in case of Bluetooth which allows us to differentiate the type of "The Class of Device (CoD) in case of Bluetooth which allows us to
device (smartphone, handsfree, computer, LAN/network AP). With this parameter we can differentiate the type of device (smartphone, handsfree, computer,
differentiate among pedestrians and vehicles." LAN/network AP). With this parameter we can differentiate among
pedestrians and vehicles."
*/ */
@ -164,29 +211,29 @@ IRAM_ATTR void gap_callback_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb
} }
} // gap_callback_handler } // gap_callback_handler
esp_err_t register_ble_callback(void) { esp_err_t register_ble_callback(void) {
ESP_LOGI(TAG, "Register GAP callback"); ESP_LOGI(TAG, "Register GAP callback");
// This function is called to occur gap event, such as scan result. // This function is called to occur gap event, such as scan result.
//register the scan callback function to the gap module // register the scan callback function to the gap module
ESP_ERROR_CHECK(esp_ble_gap_register_callback(&gap_callback_handler)); ESP_ERROR_CHECK(esp_ble_gap_register_callback(&gap_callback_handler));
static esp_ble_scan_params_t ble_scan_params = static esp_ble_scan_params_t ble_scan_params = {
{
.scan_type = BLE_SCAN_TYPE_PASSIVE, .scan_type = BLE_SCAN_TYPE_PASSIVE,
.own_addr_type = BLE_ADDR_TYPE_RANDOM, .own_addr_type = BLE_ADDR_TYPE_RANDOM,
#ifdef VENDORFILTER #ifdef VENDORFILTER
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_WLIST_PRA_DIR, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_WLIST_PRA_DIR,
// ADV_IND, ADV_NONCONN_IND, ADV_SCAN_IND packets are used for broadcasting // ADV_IND, ADV_NONCONN_IND, ADV_SCAN_IND packets are used for broadcasting
// data in broadcast applications (e.g., Beacons), so we don't want them in vendorfilter mode // data in broadcast applications (e.g., Beacons), so we don't want them in
#else // vendorfilter mode
#else
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL, .scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
#endif #endif
.scan_interval = (uint16_t) (cfg.blescantime * 10 / 0.625), // Time = N * 0.625 msec .scan_interval =
.scan_window = (uint16_t) (BLESCANWINDOW / 0.625) // Time = N * 0.625 msec (uint16_t)(cfg.blescantime * 10 / 0.625), // Time = N * 0.625 msec
.scan_window = (uint16_t)(BLESCANWINDOW / 0.625) // Time = N * 0.625 msec
}; };
ESP_LOGI(TAG, "Set GAP scan parameters"); ESP_LOGI(TAG, "Set GAP scan parameters");
@ -198,16 +245,18 @@ esp_err_t register_ble_callback(void) {
} // register_ble_callback } // register_ble_callback
void start_BLEscan(void){ void start_BLEscan(void) {
ESP_LOGI(TAG, "Initializing bluetooth scanner ..."); ESP_LOGI(TAG, "Initializing bluetooth scanner ...");
// Initialize BT controller to allocate task and other resource. // Initialize BT controller to allocate task and other resource.
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT(); esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
bt_cfg.controller_task_stack_size = BLESTACKSIZE; // set BT stack size to value configured in paxcounter.conf bt_cfg.controller_task_stack_size =
BLESTACKSIZE; // set BT stack size to value configured in paxcounter.conf
ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg)); ESP_ERROR_CHECK(esp_bt_controller_init(&bt_cfg));
ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BTDM)); ESP_ERROR_CHECK(esp_bt_controller_enable(ESP_BT_MODE_BTDM));
// Init and alloc the resource for bluetooth stack, must be done prior to every bluetooth stuff // Init and alloc the resource for bluetooth stack, must be done prior to
// every bluetooth stuff
ESP_ERROR_CHECK(esp_bluedroid_init()); ESP_ERROR_CHECK(esp_bluedroid_init());
ESP_ERROR_CHECK(esp_bluedroid_enable()); ESP_ERROR_CHECK(esp_bluedroid_enable());
@ -217,7 +266,7 @@ void start_BLEscan(void){
ESP_LOGI(TAG, "Bluetooth scanner started"); ESP_LOGI(TAG, "Bluetooth scanner started");
} // start_BLEscan } // start_BLEscan
void stop_BLEscan(void){ void stop_BLEscan(void) {
ESP_LOGI(TAG, "Shutting down bluetooth scanner ..."); ESP_LOGI(TAG, "Shutting down bluetooth scanner ...");
ESP_ERROR_CHECK(esp_ble_gap_register_callback(NULL)); ESP_ERROR_CHECK(esp_ble_gap_register_callback(NULL));
ESP_ERROR_CHECK(esp_bluedroid_disable()); ESP_ERROR_CHECK(esp_bluedroid_disable());

View File

@ -13,12 +13,13 @@ esp_err_t err;
// defined in antenna.cpp // defined in antenna.cpp
#ifdef HAS_ANTENNA_SWITCH #ifdef HAS_ANTENNA_SWITCH
void antenna_select(const uint8_t _ant); void antenna_select(const uint8_t _ant);
#endif #endif
// populate cfg vars with factory settings // populate cfg vars with factory settings
void defaultConfig() { void defaultConfig() {
cfg.lorasf = LORASFDEFAULT; // 7-12, initial lora spreadfactor defined in paxcounter.conf cfg.lorasf = LORASFDEFAULT; // 7-12, initial lora spreadfactor defined in
// paxcounter.conf
cfg.txpower = 15; // 2-15, lora tx power cfg.txpower = 15; // 2-15, lora tx power
cfg.adrmode = 1; // 0=disabled, 1=enabled cfg.adrmode = 1; // 0=disabled, 1=enabled
cfg.screensaver = 0; // 0=disabled, 1=enabled cfg.screensaver = 0; // 0=disabled, 1=enabled
@ -26,15 +27,18 @@ void defaultConfig() {
cfg.countermode = 0; // 0=cyclic, 1=cumulative, 2=cyclic confirmed cfg.countermode = 0; // 0=cyclic, 1=cumulative, 2=cyclic confirmed
cfg.rssilimit = 0; // threshold for rssilimiter, negative value! cfg.rssilimit = 0; // threshold for rssilimiter, negative value!
cfg.sendcycle = SEND_SECS; // payload send cycle [seconds/2] cfg.sendcycle = SEND_SECS; // payload send cycle [seconds/2]
cfg.wifichancycle = WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100] cfg.wifichancycle =
cfg.blescantime = BLESCANINTERVAL / 10; // BT channel scan cycle duration [seconds/100], default 1 (= 10ms) WIFI_CHANNEL_SWITCH_INTERVAL; // wifi channel switch cycle [seconds/100]
cfg.blescantime =
BLESCANINTERVAL /
10; // BT channel scan cycle duration [seconds/100], default 1 (= 10ms)
cfg.blescan = 1; // 0=disabled, 1=enabled cfg.blescan = 1; // 0=disabled, 1=enabled
cfg.wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4) cfg.wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4)
cfg.vendorfilter = 1; // 0=disabled, 1=enabled cfg.vendorfilter = 1; // 0=disabled, 1=enabled
cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%)
cfg.gpsmode = 1; // 0=disabled, 1=enabled cfg.gpsmode = 1; // 0=disabled, 1=enabled
strncpy( cfg.version, PROGVERSION, sizeof(cfg.version)-1 ); strncpy(cfg.version, PROGVERSION, sizeof(cfg.version) - 1);
} }
void open_storage() { void open_storage() {
@ -45,7 +49,7 @@ void open_storage() {
ESP_ERROR_CHECK(nvs_flash_erase()); ESP_ERROR_CHECK(nvs_flash_erase());
err = nvs_flash_init(); err = nvs_flash_init();
} }
ESP_ERROR_CHECK( err ); ESP_ERROR_CHECK(err);
// Open // Open
ESP_LOGI(TAG, "Opening NVS"); ESP_LOGI(TAG, "Opening NVS");
@ -64,9 +68,10 @@ void eraseConfig() {
nvs_erase_all(my_handle); nvs_erase_all(my_handle);
nvs_commit(my_handle); nvs_commit(my_handle);
nvs_close(my_handle); nvs_close(my_handle);
ESP_LOGI(TAG, "Done");} ESP_LOGI(TAG, "Done");
else { } else {
ESP_LOGW(TAG, "NVS erase failed"); } ESP_LOGW(TAG, "NVS erase failed");
}
} }
// save current configuration from RAM to NVRAM // save current configuration from RAM to NVRAM
@ -79,57 +84,74 @@ void saveConfig() {
size_t required_size; size_t required_size;
char storedversion[10]; char storedversion[10];
if( nvs_get_str(my_handle, "version", storedversion, &required_size) != ESP_OK || strcmp(storedversion, cfg.version) != 0 ) 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); nvs_set_str(my_handle, "version", cfg.version);
if( nvs_get_i8(my_handle, "lorasf", &flash8) != ESP_OK || flash8 != cfg.lorasf ) if (nvs_get_i8(my_handle, "lorasf", &flash8) != ESP_OK ||
flash8 != cfg.lorasf)
nvs_set_i8(my_handle, "lorasf", cfg.lorasf); nvs_set_i8(my_handle, "lorasf", cfg.lorasf);
if( nvs_get_i8(my_handle, "txpower", &flash8) != ESP_OK || flash8 != cfg.txpower ) if (nvs_get_i8(my_handle, "txpower", &flash8) != ESP_OK ||
flash8 != cfg.txpower)
nvs_set_i8(my_handle, "txpower", cfg.txpower); nvs_set_i8(my_handle, "txpower", cfg.txpower);
if( nvs_get_i8(my_handle, "adrmode", &flash8) != ESP_OK || flash8 != cfg.adrmode ) if (nvs_get_i8(my_handle, "adrmode", &flash8) != ESP_OK ||
flash8 != cfg.adrmode)
nvs_set_i8(my_handle, "adrmode", cfg.adrmode); nvs_set_i8(my_handle, "adrmode", cfg.adrmode);
if( nvs_get_i8(my_handle, "screensaver", &flash8) != ESP_OK || flash8 != cfg.screensaver ) if (nvs_get_i8(my_handle, "screensaver", &flash8) != ESP_OK ||
flash8 != cfg.screensaver)
nvs_set_i8(my_handle, "screensaver", cfg.screensaver); nvs_set_i8(my_handle, "screensaver", cfg.screensaver);
if( nvs_get_i8(my_handle, "screenon", &flash8) != ESP_OK || flash8 != cfg.screenon ) if (nvs_get_i8(my_handle, "screenon", &flash8) != ESP_OK ||
flash8 != cfg.screenon)
nvs_set_i8(my_handle, "screenon", cfg.screenon); nvs_set_i8(my_handle, "screenon", cfg.screenon);
if( nvs_get_i8(my_handle, "countermode", &flash8) != ESP_OK || flash8 != cfg.countermode ) if (nvs_get_i8(my_handle, "countermode", &flash8) != ESP_OK ||
flash8 != cfg.countermode)
nvs_set_i8(my_handle, "countermode", cfg.countermode); nvs_set_i8(my_handle, "countermode", cfg.countermode);
if( nvs_get_i8(my_handle, "sendcycle", &flash8) != ESP_OK || flash8 != cfg.sendcycle ) if (nvs_get_i8(my_handle, "sendcycle", &flash8) != ESP_OK ||
flash8 != cfg.sendcycle)
nvs_set_i8(my_handle, "sendcycle", cfg.sendcycle); nvs_set_i8(my_handle, "sendcycle", cfg.sendcycle);
if( nvs_get_i8(my_handle, "wifichancycle", &flash8) != ESP_OK || flash8 != cfg.wifichancycle ) if (nvs_get_i8(my_handle, "wifichancycle", &flash8) != ESP_OK ||
flash8 != cfg.wifichancycle)
nvs_set_i8(my_handle, "wifichancycle", cfg.wifichancycle); nvs_set_i8(my_handle, "wifichancycle", cfg.wifichancycle);
if( nvs_get_i8(my_handle, "blescantime", &flash8) != ESP_OK || flash8 != cfg.blescantime ) if (nvs_get_i8(my_handle, "blescantime", &flash8) != ESP_OK ||
flash8 != cfg.blescantime)
nvs_set_i8(my_handle, "blescantime", cfg.blescantime); nvs_set_i8(my_handle, "blescantime", cfg.blescantime);
if( nvs_get_i8(my_handle, "blescanmode", &flash8) != ESP_OK || flash8 != cfg.blescan ) if (nvs_get_i8(my_handle, "blescanmode", &flash8) != ESP_OK ||
flash8 != cfg.blescan)
nvs_set_i8(my_handle, "blescanmode", cfg.blescan); nvs_set_i8(my_handle, "blescanmode", cfg.blescan);
if( nvs_get_i8(my_handle, "wifiant", &flash8) != ESP_OK || flash8 != cfg.wifiant ) if (nvs_get_i8(my_handle, "wifiant", &flash8) != ESP_OK ||
flash8 != cfg.wifiant)
nvs_set_i8(my_handle, "wifiant", cfg.wifiant); nvs_set_i8(my_handle, "wifiant", cfg.wifiant);
if( nvs_get_i8(my_handle, "vendorfilter", &flash8) != ESP_OK || flash8 != cfg.vendorfilter ) if (nvs_get_i8(my_handle, "vendorfilter", &flash8) != ESP_OK ||
flash8 != cfg.vendorfilter)
nvs_set_i8(my_handle, "vendorfilter", cfg.vendorfilter); nvs_set_i8(my_handle, "vendorfilter", cfg.vendorfilter);
if( nvs_get_i8(my_handle, "rgblum", &flash8) != ESP_OK || flash8 != cfg.rgblum ) if (nvs_get_i8(my_handle, "rgblum", &flash8) != ESP_OK ||
flash8 != cfg.rgblum)
nvs_set_i8(my_handle, "rgblum", cfg.rgblum); nvs_set_i8(my_handle, "rgblum", cfg.rgblum);
if( nvs_get_i8(my_handle, "gpsmode", &flash8) != ESP_OK || flash8 != cfg.gpsmode ) if (nvs_get_i8(my_handle, "gpsmode", &flash8) != ESP_OK ||
flash8 != cfg.gpsmode)
nvs_set_i8(my_handle, "gpsmode", cfg.gpsmode); nvs_set_i8(my_handle, "gpsmode", cfg.gpsmode);
if( nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK || flash16 != cfg.rssilimit ) if (nvs_get_i16(my_handle, "rssilimit", &flash16) != ESP_OK ||
flash16 != cfg.rssilimit)
nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit); nvs_set_i16(my_handle, "rssilimit", cfg.rssilimit);
err = nvs_commit(my_handle); err = nvs_commit(my_handle);
nvs_close(my_handle); nvs_close(my_handle);
if ( err == ESP_OK ) { if (err == ESP_OK) {
ESP_LOGI(TAG, "Done"); ESP_LOGI(TAG, "Done");
} else { } else {
ESP_LOGW(TAG, "NVS config write failed"); ESP_LOGW(TAG, "NVS config write failed");
@ -152,19 +174,21 @@ void loadConfig() {
ESP_LOGI(TAG, "Reading settings from NVS"); ESP_LOGI(TAG, "Reading settings from NVS");
open_storage(); open_storage();
if (err != ESP_OK) { if (err != ESP_OK) {
ESP_LOGW(TAG,"Error (%d) opening NVS handle, storing defaults", err); ESP_LOGW(TAG, "Error (%d) opening NVS handle, storing defaults", err);
saveConfig(); } // saves factory settings to NVRAM saveConfig();
} // saves factory settings to NVRAM
else { else {
int8_t flash8 = 0; int8_t flash8 = 0;
int16_t flash16 = 0; int16_t flash16 = 0;
size_t required_size; size_t required_size;
// check if configuration stored in NVRAM matches PROGVERSION // check if configuration stored in NVRAM matches PROGVERSION
if( nvs_get_str(my_handle, "version", NULL, &required_size) == ESP_OK ) { if (nvs_get_str(my_handle, "version", NULL, &required_size) == ESP_OK) {
nvs_get_str(my_handle, "version", cfg.version, &required_size); nvs_get_str(my_handle, "version", cfg.version, &required_size);
ESP_LOGI(TAG, "NVRAM settings version = %s", cfg.version); ESP_LOGI(TAG, "NVRAM settings version = %s", cfg.version);
if (strcmp(cfg.version, PROGVERSION)) { if (strcmp(cfg.version, PROGVERSION)) {
ESP_LOGI(TAG, "migrating NVRAM settings to new version %s", PROGVERSION); ESP_LOGI(TAG, "migrating NVRAM settings to new version %s",
PROGVERSION);
nvs_close(my_handle); nvs_close(my_handle);
migrateVersion(); migrateVersion();
} }
@ -176,7 +200,7 @@ void loadConfig() {
} }
// overwrite defaults with valid values from NVRAM // overwrite defaults with valid values from NVRAM
if( nvs_get_i8(my_handle, "lorasf", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "lorasf", &flash8) == ESP_OK) {
cfg.lorasf = flash8; cfg.lorasf = flash8;
ESP_LOGI(TAG, "lorasf = %d", flash8); ESP_LOGI(TAG, "lorasf = %d", flash8);
} else { } else {
@ -184,7 +208,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "txpower", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "txpower", &flash8) == ESP_OK) {
cfg.txpower = flash8; cfg.txpower = flash8;
ESP_LOGI(TAG, "txpower = %d", flash8); ESP_LOGI(TAG, "txpower = %d", flash8);
} else { } else {
@ -192,7 +216,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "adrmode", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "adrmode", &flash8) == ESP_OK) {
cfg.adrmode = flash8; cfg.adrmode = flash8;
ESP_LOGI(TAG, "adrmode = %d", flash8); ESP_LOGI(TAG, "adrmode = %d", flash8);
} else { } else {
@ -200,7 +224,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "screensaver", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "screensaver", &flash8) == ESP_OK) {
cfg.screensaver = flash8; cfg.screensaver = flash8;
ESP_LOGI(TAG, "screensaver = %d", flash8); ESP_LOGI(TAG, "screensaver = %d", flash8);
} else { } else {
@ -208,7 +232,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "screenon", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "screenon", &flash8) == ESP_OK) {
cfg.screenon = flash8; cfg.screenon = flash8;
ESP_LOGI(TAG, "screenon = %d", flash8); ESP_LOGI(TAG, "screenon = %d", flash8);
} else { } else {
@ -216,7 +240,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "countermode", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "countermode", &flash8) == ESP_OK) {
cfg.countermode = flash8; cfg.countermode = flash8;
ESP_LOGI(TAG, "countermode = %d", flash8); ESP_LOGI(TAG, "countermode = %d", flash8);
} else { } else {
@ -224,7 +248,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "sendcycle", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "sendcycle", &flash8) == ESP_OK) {
cfg.sendcycle = flash8; cfg.sendcycle = flash8;
ESP_LOGI(TAG, "sendcycle = %d", flash8); ESP_LOGI(TAG, "sendcycle = %d", flash8);
} else { } else {
@ -232,7 +256,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "wifichancycle", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "wifichancycle", &flash8) == ESP_OK) {
cfg.wifichancycle = flash8; cfg.wifichancycle = flash8;
ESP_LOGI(TAG, "wifichancycle = %d", flash8); ESP_LOGI(TAG, "wifichancycle = %d", flash8);
} else { } else {
@ -240,7 +264,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "wifiant", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "wifiant", &flash8) == ESP_OK) {
cfg.wifiant = flash8; cfg.wifiant = flash8;
ESP_LOGI(TAG, "wifiantenna = %d", flash8); ESP_LOGI(TAG, "wifiantenna = %d", flash8);
} else { } else {
@ -248,7 +272,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "vendorfilter", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "vendorfilter", &flash8) == ESP_OK) {
cfg.vendorfilter = flash8; cfg.vendorfilter = flash8;
ESP_LOGI(TAG, "vendorfilter = %d", flash8); ESP_LOGI(TAG, "vendorfilter = %d", flash8);
} else { } else {
@ -256,7 +280,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "rgblum", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "rgblum", &flash8) == ESP_OK) {
cfg.rgblum = flash8; cfg.rgblum = flash8;
ESP_LOGI(TAG, "rgbluminosity = %d", flash8); ESP_LOGI(TAG, "rgbluminosity = %d", flash8);
} else { } else {
@ -264,7 +288,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "blescantime", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "blescantime", &flash8) == ESP_OK) {
cfg.blescantime = flash8; cfg.blescantime = flash8;
ESP_LOGI(TAG, "blescantime = %d", flash8); ESP_LOGI(TAG, "blescantime = %d", flash8);
} else { } else {
@ -272,7 +296,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "blescanmode", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "blescanmode", &flash8) == ESP_OK) {
cfg.blescan = flash8; cfg.blescan = flash8;
ESP_LOGI(TAG, "BLEscanmode = %d", flash8); ESP_LOGI(TAG, "BLEscanmode = %d", flash8);
} else { } else {
@ -280,7 +304,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i16(my_handle, "rssilimit", &flash16) == ESP_OK ) { if (nvs_get_i16(my_handle, "rssilimit", &flash16) == ESP_OK) {
cfg.rssilimit = flash16; cfg.rssilimit = flash16;
ESP_LOGI(TAG, "rssilimit = %d", flash16); ESP_LOGI(TAG, "rssilimit = %d", flash16);
} else { } else {
@ -288,7 +312,7 @@ void loadConfig() {
saveConfig(); saveConfig();
} }
if( nvs_get_i8(my_handle, "gpsmode", &flash8) == ESP_OK ) { if (nvs_get_i8(my_handle, "gpsmode", &flash8) == ESP_OK) {
cfg.gpsmode = flash8; cfg.gpsmode = flash8;
ESP_LOGI(TAG, "GPSmode = %d", flash8); ESP_LOGI(TAG, "GPSmode = %d", flash8);
} else { } else {
@ -301,8 +325,8 @@ void loadConfig() {
// put actions to be triggered after config loaded here // put actions to be triggered after config loaded here
#ifdef HAS_ANTENNA_SWITCH // set antenna type, if device has one #ifdef HAS_ANTENNA_SWITCH // set antenna type, if device has one
antenna_select(cfg.wifiant); antenna_select(cfg.wifiant);
#endif #endif
} }
} }

View File

@ -2,32 +2,32 @@
#include <Arduino.h> #include <Arduino.h>
// std::set for unified array functions // std::set for unified array functions
#include <set>
#include <array>
#include <algorithm> #include <algorithm>
#include <array>
#include <set>
// OLED Display // OLED Display
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
#include <U8x8lib.h> #include <U8x8lib.h>
#endif #endif
//GPS // GPS
#ifdef HAS_GPS #ifdef HAS_GPS
#include <TinyGPS++.h> #include <TinyGPS++.h>
#endif #endif
// LMIC-Arduino LoRaWAN Stack // LMIC-Arduino LoRaWAN Stack
#include <lmic.h>
#include <hal/hal.h> #include <hal/hal.h>
#include <lmic.h>
// LED controls // LED controls
#ifdef HAS_RGB_LED #ifdef HAS_RGB_LED
#include <SmartLeds.h> #include <SmartLeds.h>
#endif #endif
#include "rgb_led.h"
#include "macsniff.h" #include "macsniff.h"
#include "main.h" #include "main.h"
#include "rgb_led.h"
// Struct holding devices's runtime configuration // Struct holding devices's runtime configuration
typedef struct { typedef struct {
@ -47,18 +47,18 @@ typedef struct {
uint8_t rgblum; // RGB Led luminosity (0..100%) uint8_t rgblum; // RGB Led luminosity (0..100%)
uint8_t gpsmode; // 0=disabled, 1=enabled uint8_t gpsmode; // 0=disabled, 1=enabled
char version[10]; // Firmware version char version[10]; // Firmware version
} configData_t; } configData_t;
#ifdef HAS_GPS #ifdef HAS_GPS
typedef struct { typedef struct {
uint32_t latitude; uint32_t latitude;
uint32_t longitude; uint32_t longitude;
uint8_t satellites; uint8_t satellites;
uint16_t hdop; uint16_t hdop;
uint16_t altitude; uint16_t altitude;
} gpsStatus_t; } gpsStatus_t;
extern gpsStatus_t gps_status; // struct for storing gps data extern gpsStatus_t gps_status; // struct for storing gps data
extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe extern TinyGPSPlus gps; // Make TinyGPS++ instance globally availabe
#endif #endif
extern configData_t cfg; extern configData_t cfg;
@ -68,6 +68,7 @@ extern char display_lora[], display_lmic[];
extern int countermode, screensaver, adrmode, lorasf, txpower, rlim; extern int countermode, screensaver, adrmode, lorasf, txpower, rlim;
extern uint16_t macs_total, macs_wifi, macs_ble; // MAC counters extern uint16_t macs_total, macs_wifi, macs_ble; // MAC counters
extern std::set<uint16_t> macs; extern std::set<uint16_t> macs;
extern hw_timer_t * channelSwitch; // hardware timer used for wifi channel switching extern hw_timer_t
*channelSwitch; // hardware timer used for wifi channel switching
extern xref2u1_t rcmd_data; // buffer for rcommand results size extern xref2u1_t rcmd_data; // buffer for rcommand results size
extern u1_t rcmd_data_size; // buffer for rcommand results size extern u1_t rcmd_data_size; // buffer for rcommand results size

View File

@ -7,45 +7,44 @@ static const char TAG[] = "main";
// read GPS data and cast to global struct // read GPS data and cast to global struct
void gps_read() { void gps_read() {
gps_status.latitude = (uint32_t) (gps.location.lat() * 1000000); gps_status.latitude = (uint32_t)(gps.location.lat() * 1000000);
gps_status.longitude = (uint32_t) (gps.location.lng() * 1000000); gps_status.longitude = (uint32_t)(gps.location.lng() * 1000000);
gps_status.satellites = (uint8_t) gps.satellites.value(); gps_status.satellites = (uint8_t)gps.satellites.value();
gps_status.hdop = (uint16_t) gps.hdop.value(); gps_status.hdop = (uint16_t)gps.hdop.value();
gps_status.altitude = (uint16_t) gps.altitude.meters(); gps_status.altitude = (uint16_t)gps.altitude.meters();
} }
// GPS serial feed FreeRTos Task // GPS serial feed FreeRTos Task
void gps_loop(void * pvParameters) { void gps_loop(void *pvParameters) {
configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
// initialize and, if needed, configure, GPS // initialize and, if needed, configure, GPS
#if defined GPS_SERIAL #if defined GPS_SERIAL
HardwareSerial GPS_Serial(1); HardwareSerial GPS_Serial(1);
#elif defined GPS_I2C #elif defined GPS_I2C
// to be done // to be done
#endif #endif
while(1) { while (1) {
if (cfg.gpsmode) if (cfg.gpsmode) {
{ #if defined GPS_SERIAL
#if defined GPS_SERIAL
// serial connect to GPS device // serial connect to GPS device
GPS_Serial.begin(GPS_SERIAL); GPS_Serial.begin(GPS_SERIAL);
while(cfg.gpsmode) { while (cfg.gpsmode) {
// feed GPS decoder with serial NMEA data from GPS device // feed GPS decoder with serial NMEA data from GPS device
while (GPS_Serial.available()) { while (GPS_Serial.available()) {
gps.encode(GPS_Serial.read()); gps.encode(GPS_Serial.read());
} }
vTaskDelay(1/portTICK_PERIOD_MS); // reset watchdog vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog
} }
// after GPS function was disabled, close connect to GPS device // after GPS function was disabled, close connect to GPS device
GPS_Serial.end(); GPS_Serial.end();
#elif defined GPS_I2C #elif defined GPS_I2C
// I2C connect to GPS device with 100 kHz // I2C connect to GPS device with 100 kHz
Wire.begin(GPS_I2C_PINS, 100000); Wire.begin(GPS_I2C_PINS, 100000);
@ -54,12 +53,12 @@ void gps_loop(void * pvParameters) {
i2c_ret == Wire.beginTransmission(GPS_I2C_ADDRESS_READ); i2c_ret == Wire.beginTransmission(GPS_I2C_ADDRESS_READ);
if (i2c_ret == 0) { // check if device seen on i2c bus if (i2c_ret == 0) { // check if device seen on i2c bus
while(cfg.gpsmode) { while (cfg.gpsmode) {
// feed GPS decoder with serial NMEA data from GPS device // feed GPS decoder with serial NMEA data from GPS device
while (Wire.available()) { while (Wire.available()) {
Wire.requestFrom(GPS_I2C_ADDRESS_READ, 255); Wire.requestFrom(GPS_I2C_ADDRESS_READ, 255);
gps.encode(Wire.read()); gps.encode(Wire.read());
vTaskDelay(1/portTICK_PERIOD_MS); // reset watchdog vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog
} }
} }
// after GPS function was disabled, close connect to GPS device // after GPS function was disabled, close connect to GPS device
@ -68,10 +67,10 @@ void gps_loop(void * pvParameters) {
Wire.setClock(400000); // Set back to 400KHz to speed up OLED Wire.setClock(400000); // Set back to 400KHz to speed up OLED
} }
#endif #endif
} }
vTaskDelay(1/portTICK_PERIOD_MS); // reset watchdog vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog
} // end of infinite loop } // end of infinite loop

View File

@ -8,18 +8,32 @@
#define HAS_BUTTON GPIO_NUM_0 // button "PROG" on board #define HAS_BUTTON GPIO_NUM_0 // button "PROG" on board
// re-define pin definitions of pins_arduino.h // re-define pin definitions of pins_arduino.h
#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select Input #define PIN_SPI_SS \
#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select
#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output // Input
#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input #define PIN_SPI_MOSI \
GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input
#define PIN_SPI_MISO \
GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output
#define PIN_SPI_SCK \
GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input
// non arduino pin definitions // non arduino pin definitions
#define RST GPIO_NUM_14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger Input #define RST \
#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done GPIO_NUM_14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger
#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout // Input
#define DIO2 LMIC_UNUSED_PIN // 32 ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) #define DIO0 \
GPIO_NUM_26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for
// detecting LoRa RX_Done & TX_Done
#define DIO1 \
GPIO_NUM_33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for
// detecting LoRa RX_Timeout
#define DIO2 \
LMIC_UNUSED_PIN // 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 // Hardware pin definitions for Heltec LoRa-32 Board with OLED SSD1306 I2C
// Display
#define OLED_RST GPIO_NUM_16 // ESP32 GPIO16 (Pin16) -- SD1306 RST #define OLED_RST GPIO_NUM_16 // ESP32 GPIO16 (Pin16) -- SD1306 RST
#define OLED_SDA GPIO_NUM_4 // ESP32 GPIO4 (Pin4) -- SD1306 D1+D2 #define OLED_SDA GPIO_NUM_4 // ESP32 GPIO4 (Pin4) -- SD1306 D1+D2
#define OLED_SCL GPIO_NUM_15 // ESP32 GPIO15 (Pin15) -- SD1306 D0 #define OLED_SCL GPIO_NUM_15 // ESP32 GPIO15 (Pin15) -- SD1306 D0

View File

@ -6,9 +6,13 @@
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board
//#define DISPLAY_FLIP 1 // uncomment this for rotated display //#define DISPLAY_FLIP 1 // uncomment this for rotated display
#define HAS_LED NOT_A_PIN // Led os on same pin as Lora SS pin, to avoid problems, we don't use it #define HAS_LED \
#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW NOT_A_PIN // Led os on same pin as Lora SS pin, to avoid problems, we don't
// Anyway shield is on over the LoLin32 board, so we won't be able to see this LED // use it
#define LED_ACTIVE_LOW \
1 // Onboard LED is active when pin is LOW
// Anyway shield is on over the LoLin32 board, so we won't be able to see
// this LED
#define HAS_RGB_LED 13 // ESP32 GPIO13 (pin13) On Board Shield WS2812B RGB LED #define HAS_RGB_LED 13 // ESP32 GPIO13 (pin13) On Board Shield WS2812B RGB LED
#define HAS_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield #define HAS_BUTTON 15 // ESP32 GPIO15 (pin15) Button is on the LoraNode32 shield
#define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown #define BUTTON_PULLUP 1 // Button need pullup instead of default pulldown
@ -16,17 +20,30 @@
#define CFG_sx1276_radio 1 // RFM95 module #define CFG_sx1276_radio 1 // RFM95 module
// re-define pin definitions of pins_arduino.h // re-define pin definitions of pins_arduino.h
#define PIN_SPI_SS 5 // ESP32 GPIO5 (Pin5) -- SX1276 NSS (Pin19) SPI Chip Select Input #define PIN_SPI_SS \
#define PIN_SPI_MOSI 23 // ESP32 GPIO23 (Pin23) -- SX1276 MOSI (Pin18) SPI Data Input 5 // ESP32 GPIO5 (Pin5) -- SX1276 NSS (Pin19) SPI Chip Select Input
#define PIN_SPI_MISO 19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output #define PIN_SPI_MOSI \
#define PIN_SPI_SCK 18 // ESP32 GPIO18 (Pin18 -- SX1276 SCK (Pin16) SPI Clock Input 23 // ESP32 GPIO23 (Pin23) -- SX1276 MOSI (Pin18) SPI Data Input
#define PIN_SPI_MISO \
19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output
#define PIN_SPI_SCK \
18 // ESP32 GPIO18 (Pin18 -- SX1276 SCK (Pin16) SPI Clock Input
// non arduino pin definitions // non arduino pin definitions
#define RST 25 // ESP32 GPIO25 (Pin25) -- SX1276 NRESET (Pin7) Reset Trigger Input #define RST \
#define DIO0 27 // ESP32 GPIO27 (Pin27) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done 25 // ESP32 GPIO25 (Pin25) -- SX1276 NRESET (Pin7) Reset Trigger Input
#define DIO1 26 // ESP32 GPIO26 (Pin26) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout #define DIO0 \
#define DIO2 LMIC_UNUSED_PIN // 4 ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) 27 // ESP32 GPIO27 (Pin27) -- SX1276 DIO0 (Pin8) used by LMIC for detecting
#define DIO5 LMIC_UNUSED_PIN // 35 ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC for LoRa (Timeout for FSK only) // LoRa RX_Done & TX_Done
#define DIO1 \
26 // ESP32 GPIO26 (Pin26) -- SX1276 DIO1 (Pin9) used by LMIC for detecting
// LoRa RX_Timeout
#define DIO2 \
LMIC_UNUSED_PIN // 4 ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by
// LMIC for LoRa (Timeout for FSK only)
#define DIO5 \
LMIC_UNUSED_PIN // 35 ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC
// for LoRa (Timeout for FSK only)
// Hardware pin definitions for LoRaNode32 Board with OLED I2C Display // Hardware pin definitions for LoRaNode32 Board with OLED I2C Display
#define OLED_RST U8X8_PIN_NONE // Not reset pin #define OLED_RST U8X8_PIN_NONE // Not reset pin

View File

@ -15,17 +15,30 @@
#define CFG_sx1276_radio 1 // RFM95 module #define CFG_sx1276_radio 1 // RFM95 module
// re-define pin definitions of pins_arduino.h // re-define pin definitions of pins_arduino.h
#define PIN_SPI_SS 5 // ESP32 GPIO5 (Pin5) -- SX1276 NSS (Pin19) SPI Chip Select Input #define PIN_SPI_SS \
#define PIN_SPI_MOSI 23 // ESP32 GPIO23 (Pin23) -- SX1276 MOSI (Pin18) SPI Data Input 5 // ESP32 GPIO5 (Pin5) -- SX1276 NSS (Pin19) SPI Chip Select Input
#define PIN_SPI_MISO 19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output #define PIN_SPI_MOSI \
#define PIN_SPI_SCK 18 // ESP32 GPIO18 (Pin18 -- SX1276 SCK (Pin16) SPI Clock Input 23 // ESP32 GPIO23 (Pin23) -- SX1276 MOSI (Pin18) SPI Data Input
#define PIN_SPI_MISO \
19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output
#define PIN_SPI_SCK \
18 // ESP32 GPIO18 (Pin18 -- SX1276 SCK (Pin16) SPI Clock Input
// non arduino pin definitions // non arduino pin definitions
#define RST 25 // ESP32 GPIO25 (Pin25) -- SX1276 NRESET (Pin7) Reset Trigger Input #define RST \
#define DIO0 27 // ESP32 GPIO27 (Pin27) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done 25 // ESP32 GPIO25 (Pin25) -- SX1276 NRESET (Pin7) Reset Trigger Input
#define DIO1 26 // ESP32 GPIO26 (Pin26) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout #define DIO0 \
#define DIO2 LMIC_UNUSED_PIN // 4 ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) 27 // ESP32 GPIO27 (Pin27) -- SX1276 DIO0 (Pin8) used by LMIC for detecting
#define DIO5 LMIC_UNUSED_PIN // 35 ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC for LoRa (Timeout for FSK only) // LoRa RX_Done & TX_Done
#define DIO1 \
26 // ESP32 GPIO26 (Pin26) -- SX1276 DIO1 (Pin9) used by LMIC for detecting
// LoRa RX_Timeout
#define DIO2 \
LMIC_UNUSED_PIN // 4 ESP32 GPIO4 (Pin4) -- SX1276 DIO2 (Pin10) not used by
// LMIC for LoRa (Timeout for FSK only)
#define DIO5 \
LMIC_UNUSED_PIN // 35 ESP32 GPIO35 (Pin35) -- SX1276 DIO5 not used by LMIC
// for LoRa (Timeout for FSK only)
// Hardware pin definitions for LoRaNode32 Board with OLED I2C Display // Hardware pin definitions for LoRaNode32 Board with OLED I2C Display
#define OLED_RST U8X8_PIN_NONE // Not reset pin #define OLED_RST U8X8_PIN_NONE // Not reset pin

View File

@ -1,12 +1,14 @@
// Hardware related definitions for Pycom LoPy Board (not: LoPy4) // Hardware related definitions for Pycom LoPy Board (not: LoPy4)
#define CFG_sx1272_radio 1 #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 // 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 #define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0
// !!EXPERIMENTAL - not tested yet!! // !!EXPERIMENTAL - not tested yet!!
// uncomment this only if your LoPy lives on a Pytrack expansion board with GPS // uncomment this only if your LoPy lives on a Pytrack expansion board with GPS
// see http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf // see
// http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf
//#define HAS_GPS 1 //#define HAS_GPS 1
//#define GPS_I2C_PINS GPIO_NUM_9, GPIO_NUM_8 // SDA, SCL //#define GPS_I2C_PINS GPIO_NUM_9, GPIO_NUM_8 // SDA, SCL
//#define GPS_I2C_ADDRESS_READ 0x21 //#define GPS_I2C_ADDRESS_READ 0x21

View File

@ -1,12 +1,14 @@
// Hardware related definitions for Pycom LoPy Board (not: LoPy4) // Hardware related definitions for Pycom LoPy Board (not: LoPy4)
#define CFG_sx1276_radio 1 #define CFG_sx1276_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 // 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 #define HAS_RGB_LED GPIO_NUM_0 // WS2812B RGB LED on GPIO0
// !!EXPERIMENTAL - not tested yet!!f // !!EXPERIMENTAL - not tested yet!!f
// uncomment this only if your LoPy lives on a Pytrack expansion board with GPS // uncomment this only if your LoPy lives on a Pytrack expansion board with GPS
// see http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf // see
// http://www.quectel.com/UploadImage/Downlad/Quectel_L76-L_I2C_Application_Note_V1.0.pdf
//#define HAS_GPS 1 //#define HAS_GPS 1
//#define GPS_I2C_PINS GPIO_NUM_9, GPIO_NUM_8 // SDA, SCL //#define GPS_I2C_PINS GPIO_NUM_9, GPIO_NUM_8 // SDA, SCL
//#define GPS_I2C_ADDRESS_READ 0x21 //#define GPS_I2C_ADDRESS_READ 0x21

View File

@ -3,20 +3,31 @@
#define CFG_sx1276_radio 1 // HPD13A LoRa SoC #define CFG_sx1276_radio 1 // HPD13A LoRa SoC
#define HAS_LED GPIO_NUM_21 // on board green LED_G1 #define HAS_LED GPIO_NUM_21 // on board green LED_G1
//#define HAS_BUTTON GPIO_NUM_39 // on board button "BOOT" (next to reset button) !! seems not to work!! //#define HAS_BUTTON GPIO_NUM_39 // on board button "BOOT" (next to reset
#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 // button) !! seems not to work!!
#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 BATT_FACTOR 2 // voltage divider 100k/100k on board
#define HAS_GPS 1 // use on board GPS #define HAS_GPS 1 // use on board GPS
#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M or 7M with default configuration #define GPS_SERIAL \
9600, SERIAL_8N1, GPIO_NUM_12, \
GPIO_NUM_15 // UBlox NEO 6M or 7M with default configuration
// re-define pin definitions of pins_arduino.h // 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 #define PIN_SPI_SS \
#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select
#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output // Input
#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input #define PIN_SPI_MOSI \
GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input
#define PIN_SPI_MISO \
GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output
#define PIN_SPI_SCK \
GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input
// non arduino pin definitions // non arduino pin definitions
#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN #define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN
#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0 #define DIO0 GPIO_NUM_26 // ESP32 GPIO26 <-> HPD13A IO0
#define DIO1 GPIO_NUM_33 // Lora1 <-> HPD13A IO1 // !! NEEDS EXTERNAL WIRING !! #define DIO1 GPIO_NUM_33 // Lora1 <-> HPD13A IO1 // !! NEEDS EXTERNAL WIRING !!
#define DIO2 LMIC_UNUSED_PIN // Lora2 <-> HPD13A IO2 // needs external wiring, but not necessary for LoRa, only FSK #define DIO2 \
LMIC_UNUSED_PIN // Lora2 <-> HPD13A IO2 // needs external wiring, but not
// necessary for LoRa, only FSK

View File

@ -9,16 +9,29 @@
#define HAS_BUTTON GPIO_NUM_0 // button "PRG" on board #define HAS_BUTTON GPIO_NUM_0 // button "PRG" on board
// re-define pin definitions of pins_arduino.h // re-define pin definitions of pins_arduino.h
#define PIN_SPI_SS GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select Input #define PIN_SPI_SS \
#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- SX1276 NSS (Pin19) SPI Chip Select
#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output // Input
#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input #define PIN_SPI_MOSI \
GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- SX1276 MOSI (Pin18) SPI Data Input
#define PIN_SPI_MISO \
GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- SX1276 MISO (Pin17) SPI Data Output
#define PIN_SPI_SCK \
GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- SX1276 SCK (Pin16) SPI Clock Input
// non arduino pin definitions // non arduino pin definitions
#define RST GPIO_NUM_14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger Input #define RST \
#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for detecting LoRa RX_Done & TX_Done GPIO_NUM_14 // ESP32 GPIO14 (Pin14) -- SX1276 NRESET (Pin7) Reset Trigger
#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for detecting LoRa RX_Timeout // Input
#define DIO2 LMIC_UNUSED_PIN // 32 ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by LMIC for LoRa (Timeout for FSK only) #define DIO0 \
GPIO_NUM_26 // ESP32 GPIO26 (Pin15) -- SX1276 DIO0 (Pin8) used by LMIC for
// detecting LoRa RX_Done & TX_Done
#define DIO1 \
GPIO_NUM_33 // ESP32 GPIO33 (Pin13) -- SX1276 DIO1 (Pin9) used by LMIC for
// detecting LoRa RX_Timeout
#define DIO2 \
LMIC_UNUSED_PIN // 32 ESP32 GPIO32 (Pin12) -- SX1276 DIO2 (Pin10) not used by
// LMIC for LoRa (Timeout for FSK only)
// Hardware pin definitions for TTGOv1 Board with OLED SSD1306 I2C Display // Hardware pin definitions for TTGOv1 Board with OLED SSD1306 I2C Display
#define OLED_RST GPIO_NUM_16 // ESP32 GPIO16 (Pin16) -- SD1306 Reset #define OLED_RST GPIO_NUM_16 // ESP32 GPIO16 (Pin16) -- SD1306 Reset

View File

@ -4,29 +4,38 @@
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
//#define DISPLAY_FLIP 1 // uncomment this for rotated display //#define DISPLAY_FLIP 1 // uncomment this for rotated display
#define HAS_LED NOT_A_PIN // on-board LED is wired to SCL (used by display) therefore totally useless #define HAS_LED \
NOT_A_PIN // on-board LED is wired to SCL (used by display) therefore totally
// useless
// disable brownout detection (needed on TTGOv2 for battery powered operation) // disable brownout detection (needed on TTGOv2 for battery powered operation)
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature #define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
// re-define pin definitions of pins_arduino.h // 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 #define PIN_SPI_SS \
#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select
#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output // Input
#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input #define PIN_SPI_MOSI \
GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input
#define PIN_SPI_MISO \
GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output
#define PIN_SPI_SCK \
GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input
// non arduino pin definitions // non arduino pin definitions
#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN #define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN
#define DIO0 GPIO_NUM_26 // ESP32 GPIO26 wired on PCB to HPD13A #define DIO0 GPIO_NUM_26 // ESP32 GPIO26 wired on PCB to HPD13A
#define DIO1 GPIO_NUM_33 // HPDIO1 on pcb, needs to be wired external to GPIO33 #define DIO1 GPIO_NUM_33 // HPDIO1 on pcb, needs to be wired external to GPIO33
#define DIO2 LMIC_UNUSED_PIN // 32 HPDIO2 on pcb, needs to be wired external to GPIO32 (not necessary for LoRa, only FSK) #define DIO2 \
LMIC_UNUSED_PIN // 32 HPDIO2 on pcb, needs to be wired external to GPIO32 (not
// necessary for LoRa, only FSK)
// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display // 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_RST U8X8_PIN_NONE // connected to CPU RST/EN
#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO4 (Pin4) -- SD1306 D1+D2 #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_SCL GPIO_NUM_22 // ESP32 GPIO15 (Pin15) -- SD1306 D0
/* /*
ESP32 LoRa module (SPI) OLED display (I2C) ESP32 LoRa module (SPI) OLED display (I2C)
--------- ----------------- ------------------ --------- ----------------- ------------------
@ -48,6 +57,6 @@
{2} Must be manually wired! {2} Must be manually wired!
DIO2 is wired to a separate pin but is not wired on-board to pin/GPIO32. 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). 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! {3} The on-board LED is wired to SCL (used by display) therefore totally
useless!
*/ */

View File

@ -4,15 +4,22 @@
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C #define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
#define DISPLAY_FLIP 1 // rotated display #define DISPLAY_FLIP 1 // rotated display
#define HAS_LED GPIO_NUM_23 // green on board LED_G3 (not in initial board version) #define HAS_LED \
#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 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 BATT_FACTOR 2 // voltage divider 100k/100k on board
// re-define pin definitions of pins_arduino.h // 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 #define PIN_SPI_SS \
#define PIN_SPI_MOSI GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input GPIO_NUM_18 // ESP32 GPIO18 (Pin18) -- HPD13A NSS/SEL (Pin4) SPI Chip Select
#define PIN_SPI_MISO GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output // Input
#define PIN_SPI_SCK GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input #define PIN_SPI_MOSI \
GPIO_NUM_27 // ESP32 GPIO27 (Pin27) -- HPD13A MOSI/DSI (Pin6) SPI Data Input
#define PIN_SPI_MISO \
GPIO_NUM_19 // ESP32 GPIO19 (Pin19) -- HPD13A MISO/DSO (Pin7) SPI Data Output
#define PIN_SPI_SCK \
GPIO_NUM_5 // ESP32 GPIO5 (Pin5) -- HPD13A SCK (Pin5) SPI Clock Input
// non arduino pin definitions // non arduino pin definitions
#define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN #define RST LMIC_UNUSED_PIN // connected to ESP32 RST/EN
@ -20,7 +27,8 @@
#define DIO1 GPIO_NUM_33 // ESP32 GPIO33 <-> HPDIO1 <-> HPD13A IO1 #define DIO1 GPIO_NUM_33 // ESP32 GPIO33 <-> HPDIO1 <-> HPD13A IO1
#define DIO2 GPIO_NUM_32 // ESP32 GPIO32 <-> HPDIO2 <-> HPD13A IO2 #define DIO2 GPIO_NUM_32 // ESP32 GPIO32 <-> HPDIO2 <-> HPD13A IO2
// Hardware pin definitions for TTGO V2 Board with OLED SSD1306 0,96" I2C Display // 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_RST U8X8_PIN_NONE // connected to CPU RST/EN
#define OLED_SDA GPIO_NUM_21 // ESP32 GPIO4 (Pin4) -- SD1306 D1+D2 #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_SCL GPIO_NUM_22 // ESP32 GPIO15 (Pin15) -- SD1306 D0

View File

@ -5,13 +5,15 @@
* and rename this file to src/loraconf.h * and rename this file to src/loraconf.h
* *
* Note that DEVEUI, APPEUI and APPKEY should all be specified in MSB format. * Note that DEVEUI, APPEUI and APPKEY should all be specified in MSB format.
* (This is different from standard LMIC-Arduino which expects DEVEUI and APPEUI in LSB format.) * (This is different from standard LMIC-Arduino which expects DEVEUI and APPEUI
in LSB format.)
* Set your DEVEUI here, if you have one. You can leave this untouched, * Set your DEVEUI here, if you have one. You can leave this untouched,
* then the DEVEUI will be generated during runtime from device's MAC adress * then the DEVEUI will be generated during runtime from device's MAC adress
* and will be displayed on device's screen as well as on serial console. * and will be displayed on device's screen as well as on serial console.
* *
* NOTE: Use MSB format (as displayed in TTN console, so you can cut & paste from there) * NOTE: Use MSB format (as displayed in TTN console, so you can cut & paste
from there)
* For TTN, APPEUI in MSB format always starts with 0x70, 0xB3, 0xD5 * For TTN, APPEUI in MSB format always starts with 0x70, 0xB3, 0xD5
* *
* Note: If using a board with Microchip 24AA02E64 Uinique ID for deveui, * Note: If using a board with Microchip 24AA02E64 Uinique ID for deveui,
@ -21,8 +23,9 @@
#include <Arduino.h> #include <Arduino.h>
static const u1_t DEVEUI[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const u1_t DEVEUI[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
static const u1_t APPEUI[8]={ 0x70, 0xB3, 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const u1_t APPEUI[8] = {0x70, 0xB3, 0xD5, 0x00, 0x00, 0x00, 0x00, 0x00};
static const u1_t APPKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const u1_t APPKEY[16] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

View File

@ -3,11 +3,11 @@
// LMIC-Arduino LoRaWAN Stack // LMIC-Arduino LoRaWAN Stack
#include "loraconf.h" #include "loraconf.h"
#include <lmic.h>
#include <hal/hal.h> #include <hal/hal.h>
#include <lmic.h>
#ifdef MCP_24AA02E64_I2C_ADDRESS #ifdef MCP_24AA02E64_I2C_ADDRESS
#include <Wire.h> // Needed for 24AA02E64, does not hurt anything if included and not used #include <Wire.h> // Needed for 24AA02E64, does not hurt anything if included and not used
#endif #endif
// Local logging Tag // Local logging Tag
@ -29,23 +29,23 @@ void gen_lora_deveui(uint8_t *pdeveui) {
*p++ = 0xFF; *p++ = 0xFF;
*p++ = 0xFE; *p++ = 0xFE;
// Then next 6 bytes are mac address reversed // Then next 6 bytes are mac address reversed
for ( i=0; i<6 ; i++) { for (i = 0; i < 6; i++) {
*p++ = dmac[5-i]; *p++ = dmac[5 - i];
} }
} }
// Function to do a byte swap in a byte array // Function to do a byte swap in a byte array
void RevBytes(unsigned char* b, size_t c) void RevBytes(unsigned char *b, size_t c) {
{
u1_t i; u1_t i;
for (i = 0; i < c / 2; i++) for (i = 0; i < c / 2; i++) {
{ unsigned char t = b[i]; unsigned char t = b[i];
b[i] = b[c - 1 - i]; b[i] = b[c - 1 - i];
b[c - 1 - i] = t; } b[c - 1 - i] = t;
}
} }
void get_hard_deveui(uint8_t *pdeveui) { void get_hard_deveui(uint8_t *pdeveui) {
// read DEVEUI from Microchip 24AA02E64 2Kb serial eeprom if present // read DEVEUI from Microchip 24AA02E64 2Kb serial eeprom if present
#ifdef MCP_24AA02E64_I2C_ADDRESS #ifdef MCP_24AA02E64_I2C_ADDRESS
uint8_t i2c_ret; uint8_t i2c_ret;
// Init this just in case, no more to 100KHz // Init this just in case, no more to 100KHz
@ -55,14 +55,14 @@ void get_hard_deveui(uint8_t *pdeveui) {
i2c_ret = Wire.endTransmission(); i2c_ret = Wire.endTransmission();
// check if device seen on i2c bus // check if device seen on i2c bus
if (i2c_ret == 0) { if (i2c_ret == 0) {
char deveui[32]=""; char deveui[32] = "";
uint8_t data; uint8_t data;
Wire.beginTransmission(MCP_24AA02E64_I2C_ADDRESS); Wire.beginTransmission(MCP_24AA02E64_I2C_ADDRESS);
Wire.write(MCP_24AA02E64_MAC_ADDRESS); Wire.write(MCP_24AA02E64_MAC_ADDRESS);
Wire.requestFrom(MCP_24AA02E64_I2C_ADDRESS, 8); Wire.requestFrom(MCP_24AA02E64_I2C_ADDRESS, 8);
while (Wire.available()) { while (Wire.available()) {
data = Wire.read(); data = Wire.read();
sprintf(deveui+strlen(deveui), "%02X ", data); sprintf(deveui + strlen(deveui), "%02X ", data);
*pdeveui++ = data; *pdeveui++ = data;
} }
i2c_ret = Wire.endTransmission(); i2c_ret = Wire.endTransmission();
@ -78,12 +78,12 @@ void get_hard_deveui(uint8_t *pdeveui) {
#ifdef VERBOSE #ifdef VERBOSE
// Display a key // Display a key
void printKey(const char * name, const uint8_t * key, uint8_t len, bool lsb) { void printKey(const char *name, const uint8_t *key, uint8_t len, bool lsb) {
const uint8_t * p ; const uint8_t *p;
char keystring[len+1] = "", keybyte[3]; char keystring[len + 1] = "", keybyte[3];
for (uint8_t i=0; i<len ; i++) { for (uint8_t i = 0; i < len; i++) {
p = lsb ? key+len-i-1 : key+i; p = lsb ? key + len - i - 1 : key + i;
sprintf(keybyte, "%02X", * p); sprintf(keybyte, "%02X", *p);
strncat(keystring, keybyte, 2); strncat(keystring, keybyte, 2);
} }
ESP_LOGI(TAG, "%s: %s", name, keystring); ESP_LOGI(TAG, "%s: %s", name, keystring);
@ -95,17 +95,17 @@ void printKeys(void) {
// all EUI buffer so we do it here to a temp // all EUI buffer so we do it here to a temp
// buffer to be able to display them // buffer to be able to display them
uint8_t buf[32]; uint8_t buf[32];
os_getDevEui((u1_t*) buf); os_getDevEui((u1_t *)buf);
printKey("DevEUI", buf, 8, true); printKey("DevEUI", buf, 8, true);
os_getArtEui((u1_t*) buf); os_getArtEui((u1_t *)buf);
printKey("AppEUI", buf, 8, true); printKey("AppEUI", buf, 8, true);
os_getDevKey((u1_t*) buf); os_getDevKey((u1_t *)buf);
printKey("AppKey", buf, 16, false); printKey("AppKey", buf, 16, false);
} }
#endif // VERBOSE #endif // VERBOSE
void do_send(osjob_t* j){ void do_send(osjob_t *j) {
// Check if there is a pending TX/RX job running // Check if there is a pending TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) { if (LMIC.opmode & OP_TXRXPEND) {
@ -129,30 +129,29 @@ void do_send(osjob_t* j){
mydata[3] = 0; mydata[3] = 0;
} }
#ifdef HAS_GPS #ifdef HAS_GPS
static uint8_t gpsdata[18]; static uint8_t gpsdata[18];
if (cfg.gpsmode && gps.location.isValid()) { if (cfg.gpsmode && gps.location.isValid()) {
gps_read(); gps_read();
memcpy (gpsdata, mydata, 4); memcpy(gpsdata, mydata, 4);
memcpy (gpsdata+4, &gps_status, sizeof(gps_status)); memcpy(gpsdata + 4, &gps_status, sizeof(gps_status));
ESP_LOGI(TAG, "lat=%.6f / lon=%.6f | %u Sats | HDOP=%.1f | Altitude=%u m", \ ESP_LOGI(TAG, "lat=%.6f / lon=%.6f | %u Sats | HDOP=%.1f | Altitude=%u m",
gps_status.latitude / (float) 1000000, \ gps_status.latitude / (float)1000000,
gps_status.longitude / (float) 1000000, \ gps_status.longitude / (float)1000000, gps_status.satellites,
gps_status.satellites, \ gps_status.hdop / (float)100, gps_status.altitude);
gps_status.hdop / (float) 100, \ LMIC_setTxData2(COUNTERPORT, gpsdata, sizeof(gpsdata),
gps_status.altitude); (cfg.countermode & 0x02));
LMIC_setTxData2(COUNTERPORT, gpsdata, sizeof(gpsdata), (cfg.countermode & 0x02));
ESP_LOGI(TAG, "%d bytes queued to send", sizeof(gpsdata)); ESP_LOGI(TAG, "%d bytes queued to send", sizeof(gpsdata));
} } else {
else { #endif
#endif LMIC_setTxData2(COUNTERPORT, mydata, sizeof(mydata),
LMIC_setTxData2(COUNTERPORT, mydata, sizeof(mydata), (cfg.countermode & 0x02)); (cfg.countermode & 0x02));
ESP_LOGI(TAG, "%d bytes queued to send", sizeof(mydata)); ESP_LOGI(TAG, "%d bytes queued to send", sizeof(mydata));
sprintf(display_lmic, "PACKET QUEUED"); sprintf(display_lmic, "PACKET QUEUED");
#ifdef HAS_GPS #ifdef HAS_GPS
} }
#endif #endif
// clear counter if not in cumulative counter mode // clear counter if not in cumulative counter mode
if (cfg.countermode != 1) { if (cfg.countermode != 1) {
@ -161,70 +160,110 @@ void do_send(osjob_t* j){
ESP_LOGI(TAG, "Counter cleared (countermode = %d)", cfg.countermode); ESP_LOGI(TAG, "Counter cleared (countermode = %d)", cfg.countermode);
} }
// Schedule next transmission // Schedule next transmission
end: end:
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(cfg.sendcycle * 2), do_send); os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(cfg.sendcycle * 2),
do_send);
} // do_send() } // do_send()
void onEvent (ev_t ev) { void onEvent(ev_t ev) {
char buff[24]=""; char buff[24] = "";
switch(ev) { switch (ev) {
case EV_SCAN_TIMEOUT: strcpy_P(buff, PSTR("SCAN TIMEOUT")); break; case EV_SCAN_TIMEOUT:
case EV_BEACON_FOUND: strcpy_P(buff, PSTR("BEACON FOUND")); break; strcpy_P(buff, PSTR("SCAN TIMEOUT"));
case EV_BEACON_MISSED: strcpy_P(buff, PSTR("BEACON MISSED")); break; break;
case EV_BEACON_TRACKED: strcpy_P(buff, PSTR("BEACON TRACKED")); break; case EV_BEACON_FOUND:
case EV_JOINING: strcpy_P(buff, PSTR("JOINING")); break; strcpy_P(buff, PSTR("BEACON FOUND"));
case EV_LOST_TSYNC: strcpy_P(buff, PSTR("LOST TSYNC")); break; break;
case EV_RESET: strcpy_P(buff, PSTR("RESET")); break; case EV_BEACON_MISSED:
case EV_RXCOMPLETE: strcpy_P(buff, PSTR("RX COMPLETE")); break; strcpy_P(buff, PSTR("BEACON MISSED"));
case EV_LINK_DEAD: strcpy_P(buff, PSTR("LINK DEAD")); break; break;
case EV_LINK_ALIVE: strcpy_P(buff, PSTR("LINK ALIVE")); break; case EV_BEACON_TRACKED:
case EV_RFU1: strcpy_P(buff, PSTR("RFUI")); break; strcpy_P(buff, PSTR("BEACON TRACKED"));
case EV_JOIN_FAILED: strcpy_P(buff, PSTR("JOIN FAILED")); break; break;
case EV_REJOIN_FAILED: strcpy_P(buff, PSTR("REJOIN FAILED")); break; case EV_JOINING:
strcpy_P(buff, PSTR("JOINING"));
break;
case EV_LOST_TSYNC:
strcpy_P(buff, PSTR("LOST TSYNC"));
break;
case EV_RESET:
strcpy_P(buff, PSTR("RESET"));
break;
case EV_RXCOMPLETE:
strcpy_P(buff, PSTR("RX COMPLETE"));
break;
case EV_LINK_DEAD:
strcpy_P(buff, PSTR("LINK DEAD"));
break;
case EV_LINK_ALIVE:
strcpy_P(buff, PSTR("LINK ALIVE"));
break;
case EV_RFU1:
strcpy_P(buff, PSTR("RFUI"));
break;
case EV_JOIN_FAILED:
strcpy_P(buff, PSTR("JOIN FAILED"));
break;
case EV_REJOIN_FAILED:
strcpy_P(buff, PSTR("REJOIN FAILED"));
break;
case EV_JOINED: case EV_JOINED:
strcpy_P(buff, PSTR("JOINED")); strcpy_P(buff, PSTR("JOINED"));
sprintf(display_lora, " "); // clear previous lmic status message from display sprintf(display_lora,
" "); // clear previous lmic status message from display
// set data rate adaptation // set data rate adaptation
LMIC_setAdrMode(cfg.adrmode); LMIC_setAdrMode(cfg.adrmode);
// Set data rate and transmit power (note: txpower seems to be ignored by the library) // Set data rate and transmit power (note: txpower seems to be ignored by
switch_lora(cfg.lorasf,cfg.txpower); // the library)
switch_lora(cfg.lorasf, cfg.txpower);
// show effective LoRa parameters after join // show effective LoRa parameters after join
ESP_LOGI(TAG, "ADR=%d, SF=%d, TXPOWER=%d", cfg.adrmode, cfg.lorasf, cfg.txpower); ESP_LOGI(TAG, "ADR=%d, SF=%d, TXPOWER=%d", cfg.adrmode, cfg.lorasf,
cfg.txpower);
break; break;
case EV_TXCOMPLETE: case EV_TXCOMPLETE:
strcpy_P(buff, (LMIC.txrxFlags & TXRX_ACK) ? PSTR("RECEIVED ACK") : PSTR("TX COMPLETE")); strcpy_P(buff, (LMIC.txrxFlags & TXRX_ACK) ? PSTR("RECEIVED ACK")
sprintf(display_lora, " "); // clear previous lmic status message from display : PSTR("TX COMPLETE"));
sprintf(display_lora,
" "); // clear previous lmic status message from display
if (LMIC.dataLen) { if (LMIC.dataLen) {
ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d", LMIC.dataLen, LMIC.rssi, (signed char)LMIC.snr / 4); ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d",
LMIC.dataLen, LMIC.rssi, (signed char)LMIC.snr / 4);
// LMIC.snr = SNR twos compliment [dB] * 4 // LMIC.snr = SNR twos compliment [dB] * 4
// LMIC.rssi = RSSI [dBm] (-196...+63) // LMIC.rssi = RSSI [dBm] (-196...+63)
sprintf(display_lora, "RSSI %d SNR %d", LMIC.rssi, (signed char)LMIC.snr / 4 ); sprintf(display_lora, "RSSI %d SNR %d", LMIC.rssi,
(signed char)LMIC.snr / 4);
// check if payload received on command port, then call remote command interpreter // check if payload received on command port, then call remote command
if ( (LMIC.txrxFlags & TXRX_PORT) && (LMIC.frame[LMIC.dataBeg-1] == RCMDPORT ) ) { // interpreter
// caution: buffering LMIC values here because rcommand() can modify LMIC.frame if ((LMIC.txrxFlags & TXRX_PORT) &&
unsigned char* buffer = new unsigned char[MAX_LEN_FRAME]; (LMIC.frame[LMIC.dataBeg - 1] == RCMDPORT)) {
memcpy(buffer, LMIC.frame, MAX_LEN_FRAME); //Copy data from cfg to char* // caution: buffering LMIC values here because rcommand() can modify
int i, k = LMIC.dataBeg, l = LMIC.dataBeg+LMIC.dataLen-2; // LMIC.frame
for (i=k; i<=l; i+=2) { unsigned char *buffer = new unsigned char[MAX_LEN_FRAME];
rcommand(buffer[i], buffer[i+1]); 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 delete[] buffer; // free memory
} }
} }
break; break;
default: sprintf_P(buff, PSTR("UNKNOWN EVENT %d"), ev); break; default:
sprintf_P(buff, PSTR("UNKNOWN EVENT %d"), ev);
break;
} }
// Log & Display if asked // Log & Display if asked
@ -234,4 +273,3 @@ void onEvent (ev_t ev) {
} }
} // onEvent() } // onEvent()

View File

@ -2,9 +2,9 @@
#define LORAWAN_H #define LORAWAN_H
void onEvent(ev_t ev); void onEvent(ev_t ev);
void do_send(osjob_t* j); void do_send(osjob_t *j);
void gen_lora_deveui(uint8_t * pdeveui); void gen_lora_deveui(uint8_t *pdeveui);
void RevBytes(unsigned char* b, size_t c); void RevBytes(unsigned char *b, size_t c);
void get_hard_deveui(uint8_t *pdeveui); void get_hard_deveui(uint8_t *pdeveui);
#endif #endif

View File

@ -3,19 +3,23 @@
#include "globals.h" #include "globals.h"
#ifdef VENDORFILTER #ifdef VENDORFILTER
#include "vendor_array.h" #include "vendor_array.h"
#endif #endif
// Local logging tag // Local logging tag
static const char TAG[] = "wifi"; static const char TAG[] = "wifi";
static wifi_country_t wifi_country = {.cc=WIFI_MY_COUNTRY, .schan=WIFI_CHANNEL_MIN, .nchan=WIFI_CHANNEL_MAX, .policy=WIFI_COUNTRY_POLICY_MANUAL}; static wifi_country_t wifi_country = {.cc = WIFI_MY_COUNTRY,
.schan = WIFI_CHANNEL_MIN,
.nchan = WIFI_CHANNEL_MAX,
.policy = WIFI_COUNTRY_POLICY_MANUAL};
// globals // globals
uint16_t salt; uint16_t salt;
uint16_t reset_salt(void) { uint16_t reset_salt(void) {
salt = random(65536); // get new 16bit random for salting hashes and set global salt var salt = random(
65536); // get new 16bit random for salting hashes and set global salt var
return salt; return salt;
} }
@ -28,70 +32,85 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) {
// only last 3 MAC Address bytes are used for MAC address anonymization // only last 3 MAC Address bytes are used for MAC address anonymization
// but since it's uint32 we take 4 bytes to avoid 1st value to be 0 // but since it's uint32 we take 4 bytes to avoid 1st value to be 0
addr2int = ( (uint32_t)paddr[2] ) | ( (uint32_t)paddr[3] << 8 ) | ( (uint32_t)paddr[4] << 16 ) | ( (uint32_t)paddr[5] << 24 ); addr2int = ((uint32_t)paddr[2]) | ((uint32_t)paddr[3] << 8) |
((uint32_t)paddr[4] << 16) | ((uint32_t)paddr[5] << 24);
#ifdef VENDORFILTER #ifdef VENDORFILTER
vendor2int = ( (uint32_t)paddr[2] ) | ( (uint32_t)paddr[1] << 8 ) | ( (uint32_t)paddr[0] << 16 ); vendor2int = ((uint32_t)paddr[2]) | ((uint32_t)paddr[1] << 8) |
((uint32_t)paddr[0] << 16);
// use OUI vendor filter list only on Wifi, not on BLE // use OUI vendor filter list only on Wifi, not on BLE
if ( (sniff_type==MAC_SNIFF_BLE) || std::find(vendors.begin(), vendors.end(), vendor2int) != vendors.end() ) if ((sniff_type == MAC_SNIFF_BLE) ||
{ std::find(vendors.begin(), vendors.end(), vendor2int) != vendors.end()) {
#endif #endif
// salt and hash MAC, and if new unique one, store identifier in container and increment counter on display // salt and hash MAC, and if new unique one, store identifier in container
// and increment counter on display
// https://en.wikipedia.org/wiki/MAC_Address_Anonymization // https://en.wikipedia.org/wiki/MAC_Address_Anonymization
addr2int += (uint32_t)salt; // add 16-bit salt to pseudo MAC addr2int += (uint32_t)salt; // add 16-bit salt to pseudo MAC
snprintf(buff, sizeof(buff), "%08X", addr2int); // convert unsigned 32-bit salted MAC to 8 digit hex string snprintf(
hashedmac = rokkit(&buff[3], 5); // hash MAC last string value, use 5 chars to fit hash in uint16_t container buff, sizeof(buff), "%08X",
auto newmac = macs.insert(hashedmac); // add hashed MAC to total container if new unique addr2int); // convert unsigned 32-bit salted MAC to 8 digit hex string
added = newmac.second ? true:false; // true if hashed MAC is unique in container hashedmac = rokkit(&buff[3], 5); // hash MAC last string value, use 5 chars
// to fit hash in uint16_t container
auto newmac = macs.insert(
hashedmac); // add hashed MAC to total container if new unique
added = newmac.second ? true
: false; // true if hashed MAC is unique in container
// Count only if MAC was not yet seen // Count only if MAC was not yet seen
if (added) { if (added) {
// increment counter and one blink led // increment counter and one blink led
if (sniff_type == MAC_SNIFF_WIFI ) { if (sniff_type == MAC_SNIFF_WIFI) {
macs_wifi++; // increment Wifi MACs counter macs_wifi++; // increment Wifi MACs counter
#if (HAS_LED != NOT_A_PIN) || defined (HAS_RGB_LED) #if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
blink_LED(COLOR_GREEN, 50); blink_LED(COLOR_GREEN, 50);
#endif #endif
} }
#ifdef BLECOUNTER #ifdef BLECOUNTER
else if (sniff_type == MAC_SNIFF_BLE ) { else if (sniff_type == MAC_SNIFF_BLE) {
macs_ble++; // increment BLE Macs counter macs_ble++; // increment BLE Macs counter
#if (HAS_LED != NOT_A_PIN) || defined (HAS_RGB_LED) #if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
blink_LED(COLOR_MAGENTA, 50); blink_LED(COLOR_MAGENTA, 50);
#endif #endif
} }
#endif #endif
} }
// Log scan result // Log scan result
ESP_LOGI(TAG, "%s %s RSSI %ddBi -> MAC %s -> Hash %04X -> WiFi:%d BLTH:%d -> %d Bytes left", ESP_LOGI(TAG,
"%s %s RSSI %ddBi -> MAC %s -> Hash %04X -> WiFi:%d BLTH:%d -> "
"%d Bytes left",
added ? "new " : "known", added ? "new " : "known",
sniff_type==MAC_SNIFF_WIFI ? "WiFi":"BLTH", sniff_type == MAC_SNIFF_WIFI ? "WiFi" : "BLTH", rssi, buff,
rssi, buff, hashedmac, macs_wifi, macs_ble, hashedmac, macs_wifi, macs_ble, ESP.getFreeHeap());
ESP.getFreeHeap());
#ifdef VENDORFILTER #ifdef VENDORFILTER
} else { } else {
// Very noisy // Very noisy
// ESP_LOGD(TAG, "Filtered MAC %02X:%02X:%02X:%02X:%02X:%02X", paddr[0],paddr[1],paddr[2],paddr[3],paddr[5],paddr[5]); // ESP_LOGD(TAG, "Filtered MAC %02X:%02X:%02X:%02X:%02X:%02X",
// paddr[0],paddr[1],paddr[2],paddr[3],paddr[5],paddr[5]);
} }
#endif #endif
// True if MAC WiFi/BLE was new // True if MAC WiFi/BLE was new
return added; // function returns bool if a new and unique Wifi or BLE mac was counted (true) or not (false) return added; // function returns bool if a new and unique Wifi or BLE mac was
// counted (true) or not (false)
} }
void wifi_sniffer_init(void) { void wifi_sniffer_init(void) {
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM
wifi_promiscuous_filter_t filter = {.filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // we need only MGMT frames wifi_promiscuous_filter_t filter = {
.filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // we need only MGMT frames
ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg
ESP_ERROR_CHECK(esp_wifi_set_country(&wifi_country)); // set locales for RF and channels ESP_ERROR_CHECK(
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM)); // we don't need NVRAM esp_wifi_set_country(&wifi_country)); // set locales for RF and channels
//ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL)); ESP_ERROR_CHECK(
ESP_ERROR_CHECK(esp_wifi_set_promiscuous_filter(&filter)); // set MAC frame filter esp_wifi_set_storage(WIFI_STORAGE_RAM)); // we don't need NVRAM
// ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
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_rx_cb(&wifi_sniffer_packet_handler));
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true)); // now switch on monitor mode ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true)); // now switch on monitor mode
} }
@ -101,16 +120,19 @@ void wifi_sniffer_set_channel(uint8_t channel) {
} }
// using IRAM_:ATTR here to speed up callback function // using IRAM_:ATTR here to speed up callback function
IRAM_ATTR void wifi_sniffer_packet_handler(void* buff, wifi_promiscuous_pkt_type_t type) { IRAM_ATTR 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_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff;
const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload; const wifi_ieee80211_packet_t *ipkt =
(wifi_ieee80211_packet_t *)ppkt->payload;
const wifi_ieee80211_mac_hdr_t *hdr = &ipkt->hdr; const wifi_ieee80211_mac_hdr_t *hdr = &ipkt->hdr;
if ((cfg.rssilimit) && (ppkt->rx_ctrl.rssi < cfg.rssilimit )) { // rssi is negative value if ((cfg.rssilimit) &&
ESP_LOGI(TAG, "WiFi RSSI %d -> ignoring (limit: %d)", ppkt->rx_ctrl.rssi, cfg.rssilimit); (ppkt->rx_ctrl.rssi < cfg.rssilimit)) { // rssi is negative value
ESP_LOGI(TAG, "WiFi RSSI %d -> ignoring (limit: %d)", ppkt->rx_ctrl.rssi,
cfg.rssilimit);
} else { } else {
uint8_t *p = (uint8_t *) hdr->addr2; uint8_t *p = (uint8_t *)hdr->addr2;
mac_add(p, ppkt->rx_ctrl.rssi, MAC_SNIFF_WIFI) ; mac_add(p, ppkt->rx_ctrl.rssi, MAC_SNIFF_WIFI);
} }
} }

View File

@ -8,12 +8,12 @@
#define MAC_SNIFF_BLE 1 #define MAC_SNIFF_BLE 1
typedef struct { typedef struct {
unsigned frame_ctrl:16; unsigned frame_ctrl : 16;
unsigned duration_id:16; unsigned duration_id : 16;
uint8_t addr1[6]; /* receiver address */ uint8_t addr1[6]; /* receiver address */
uint8_t addr2[6]; /* sender address */ uint8_t addr2[6]; /* sender address */
uint8_t addr3[6]; /* filtering address */ uint8_t addr3[6]; /* filtering address */
unsigned sequence_ctrl:16; unsigned sequence_ctrl : 16;
uint8_t addr4[6]; /* optional */ uint8_t addr4[6]; /* optional */
} wifi_ieee80211_mac_hdr_t; } wifi_ieee80211_mac_hdr_t;
@ -28,6 +28,6 @@ void wifi_sniffer_set_channel(uint8_t channel);
void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type); void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
// function defined in rokkithash.cpp // function defined in rokkithash.cpp
uint32_t rokkit(const char * , int ); uint32_t rokkit(const char *, int);
#endif #endif

View File

@ -16,8 +16,8 @@ Copyright 2018 Klaus Wilting <verkehrsrot@arcor.de>
limitations under the License. limitations under the License.
NOTICE: NOTICE:
Parts of the source files in this repository are made available under different licenses. Parts of the source files in this repository are made available under different
Refer to LICENSE.txt file in repository for more details. licenses. Refer to LICENSE.txt file in repository for more details.
*/ */
@ -29,50 +29,58 @@ Refer to LICENSE.txt file in repository for more details.
// LMIC-Arduino LoRaWAN Stack // LMIC-Arduino LoRaWAN Stack
#include "loraconf.h" #include "loraconf.h"
#include <lmic.h>
#include <hal/hal.h> #include <hal/hal.h>
#include <lmic.h>
// ESP32 lib Functions // 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_event_loop.h> // needed for Wifi event handler
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes #include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
#include <esp32-hal-log.h> // needed for ESP_LOGx on arduino framework
// Initialize global variables // Initialize global variables
configData_t cfg; // struct holds current device configuration configData_t cfg; // struct holds current device configuration
osjob_t sendjob, rcmdjob; // LMIC job handler osjob_t sendjob, rcmdjob; // LMIC job handler
uint64_t uptimecounter = 0; // timer global for uptime counter uint64_t uptimecounter = 0; // timer global for uptime counter
uint8_t DisplayState = 0; // globals for state machine uint8_t DisplayState = 0; // globals for state machine
uint16_t macs_total = 0, macs_wifi = 0, macs_ble = 0; // MAC counters globals for display 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 uint8_t channel = 0; // wifi channel rotation counter global for display
char display_lora[16], display_lmic[16]; // display buffers char display_lora[16], display_lmic[16]; // display buffers
led_states LEDState = LED_OFF; // LED state global for state machine led_states LEDState = LED_OFF; // LED state global for state machine
led_states previousLEDState = LED_ON; // This will force LED to be off at boot since State is OFF led_states previousLEDState =
LED_ON; // This will force LED to be off at boot since State is OFF
unsigned long LEDBlinkStarted = 0; // When (in millis() led blink started) unsigned long LEDBlinkStarted = 0; // When (in millis() led blink started)
uint16_t LEDBlinkDuration = 0; // How long the blink need to be uint16_t LEDBlinkDuration = 0; // How long the blink need to be
uint16_t LEDColor = COLOR_NONE; // state machine variable to set RGB LED color 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 *displaytimer =
hw_timer_t * channelSwitch = NULL; // configure hardware timer used for wifi channel switching 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 xref2u1_t rcmd_data; // buffer for rcommand results size
u1_t rcmd_data_size; // buffer for rcommand results size u1_t rcmd_data_size; // buffer for rcommand results size
#ifdef HAS_GPS #ifdef HAS_GPS
gpsStatus_t gps_status; // struct for storing gps data gpsStatus_t gps_status; // struct for storing gps data
TinyGPSPlus gps; // create TinyGPS++ instance TinyGPSPlus gps; // create TinyGPS++ instance
#endif #endif
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED; // sync main loop and ISR when modifying IRQ handler shared variables portMUX_TYPE timerMux =
portMUX_INITIALIZER_UNLOCKED; // sync main loop and ISR when modifying IRQ
// handler shared variables
std::set<uint16_t> macs; // associative container holds total of unique MAC adress hashes (Wifi + BLE) std::set<uint16_t> macs; // associative container holds total of unique MAC
// adress hashes (Wifi + BLE)
// this variables will be changed in the ISR, and read in main loop // this variables will be changed in the ISR, and read in main loop
static volatile int ButtonPressedIRQ = 0, DisplayTimerIRQ = 0, ChannelTimerIRQ = 0; static volatile int ButtonPressedIRQ = 0, DisplayTimerIRQ = 0,
ChannelTimerIRQ = 0;
// local Tag for logging // local Tag for logging
static const char TAG[] = "main"; static const char TAG[] = "main";
#ifndef VERBOSE #ifndef VERBOSE
int redirect_log(const char * fmt, va_list args) { int redirect_log(const char *fmt, va_list args) {
//do nothing // do nothing
return 0; return 0;
} }
#endif #endif
@ -84,27 +92,25 @@ void reset_counters() {
macs_ble = 0; macs_ble = 0;
} }
/* begin LMIC specific parts ------------------------------------------------------------ */ /* begin LMIC specific parts
* ------------------------------------------------------------ */
#ifdef VERBOSE #ifdef VERBOSE
void printKeys(void); void printKeys(void);
#endif // VERBOSE #endif // VERBOSE
// LMIC callback functions // LMIC callback functions
void os_getDevKey (u1_t *buf) { void os_getDevKey(u1_t *buf) { memcpy(buf, APPKEY, 16); }
memcpy(buf, APPKEY, 16);
}
void os_getArtEui (u1_t *buf) { void os_getArtEui(u1_t *buf) {
memcpy(buf, APPEUI, 8); memcpy(buf, APPEUI, 8);
RevBytes(buf, 8); // TTN requires it in LSB First order, so we swap bytes RevBytes(buf, 8); // TTN requires it in LSB First order, so we swap bytes
} }
void os_getDevEui (u1_t* buf) { void os_getDevEui(u1_t *buf) {
int i=0, k=0; int i = 0, k = 0;
memcpy(buf, DEVEUI, 8); // get fixed DEVEUI from loraconf.h memcpy(buf, DEVEUI, 8); // get fixed DEVEUI from loraconf.h
for (i=0; i<8 ; i++) { for (i = 0; i < 8; i++) {
k += buf[i]; k += buf[i];
} }
if (k) { if (k) {
@ -113,65 +119,63 @@ void os_getDevEui (u1_t* buf) {
gen_lora_deveui(buf); // generate DEVEUI from device's MAC gen_lora_deveui(buf); // generate DEVEUI from device's MAC
} }
// Get MCP 24AA02E64 hardware DEVEUI (override default settings if found) // Get MCP 24AA02E64 hardware DEVEUI (override default settings if found)
#ifdef MCP_24AA02E64_I2C_ADDRESS #ifdef MCP_24AA02E64_I2C_ADDRESS
get_hard_deveui(buf); get_hard_deveui(buf);
RevBytes(buf, 8); // swap bytes to LSB format RevBytes(buf, 8); // swap bytes to LSB format
#endif #endif
} }
// LMIC enhanced Pin mapping // LMIC enhanced Pin mapping
const lmic_pinmap lmic_pins = { const lmic_pinmap lmic_pins = {.mosi = PIN_SPI_MOSI,
.mosi = PIN_SPI_MOSI,
.miso = PIN_SPI_MISO, .miso = PIN_SPI_MISO,
.sck = PIN_SPI_SCK, .sck = PIN_SPI_SCK,
.nss = PIN_SPI_SS, .nss = PIN_SPI_SS,
.rxtx = LMIC_UNUSED_PIN, .rxtx = LMIC_UNUSED_PIN,
.rst = RST, .rst = RST,
.dio = {DIO0, DIO1, DIO2} .dio = {DIO0, DIO1, DIO2}};
};
// LMIC FreeRTos Task // LMIC FreeRTos Task
void lorawan_loop(void * pvParameters) { void lorawan_loop(void *pvParameters) {
configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
while(1) { while (1) {
os_runloop_once(); // execute LMIC jobs os_runloop_once(); // execute LMIC jobs
vTaskDelay(1/portTICK_PERIOD_MS); // reset watchdog vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog
} }
} }
/* end LMIC specific parts --------------------------------------------------------------- */ /* end LMIC specific parts
* --------------------------------------------------------------- */
/* beginn hardware specific parts -------------------------------------------------------- */ /* beginn hardware specific parts
* -------------------------------------------------------- */
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
HAS_DISPLAY u8x8(OLED_RST, OLED_SCL, OLED_SDA); HAS_DISPLAY u8x8(OLED_RST, OLED_SCL, OLED_SDA);
// Display Refresh IRQ // Display Refresh IRQ
void IRAM_ATTR DisplayIRQ() { void IRAM_ATTR DisplayIRQ() {
portENTER_CRITICAL_ISR(&timerMux); portENTER_CRITICAL_ISR(&timerMux);
DisplayTimerIRQ++; DisplayTimerIRQ++;
portEXIT_CRITICAL_ISR(&timerMux); portEXIT_CRITICAL_ISR(&timerMux);
} }
#endif #endif
#ifdef HAS_ANTENNA_SWITCH #ifdef HAS_ANTENNA_SWITCH
// defined in antenna.cpp // defined in antenna.cpp
void antenna_init(); void antenna_init();
void antenna_select(const uint8_t _ant); void antenna_select(const uint8_t _ant);
#endif #endif
#ifndef BLECOUNTER #ifndef BLECOUNTER
bool btstop = btStop(); bool btstop = btStop();
#endif #endif
// Button IRQ Handler Routine, IRAM_ATTR necessary here, see https://github.com/espressif/arduino-esp32/issues/855 // Button IRQ Handler Routine, IRAM_ATTR necessary here, see
// https://github.com/espressif/arduino-esp32/issues/855
#ifdef HAS_BUTTON #ifdef HAS_BUTTON
void IRAM_ATTR ButtonIRQ() { void IRAM_ATTR ButtonIRQ() { ButtonPressedIRQ++; }
ButtonPressedIRQ++;
}
#endif #endif
// Wifi Channel Rotation Timer IRQ Handler Routine // Wifi Channel Rotation Timer IRQ Handler Routine
@ -181,15 +185,16 @@ void IRAM_ATTR ChannelSwitchIRQ() {
portEXIT_CRITICAL(&timerMux); portEXIT_CRITICAL(&timerMux);
} }
/* end hardware specific parts -------------------------------------------------------- */ /* end hardware specific parts
* -------------------------------------------------------- */
/* begin wifi specific parts
/* begin wifi specific parts ---------------------------------------------------------- */ * ---------------------------------------------------------- */
// Sniffer Task // Sniffer Task
void sniffer_loop(void * pvParameters) { void sniffer_loop(void *pvParameters) {
configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
while (1) { while (1) {
@ -202,36 +207,38 @@ void sniffer_loop(void * pvParameters) {
wifi_sniffer_set_channel(channel); wifi_sniffer_set_channel(channel);
ESP_LOGD(TAG, "Wifi set channel %d", channel); ESP_LOGD(TAG, "Wifi set channel %d", channel);
vTaskDelay(1/portTICK_PERIOD_MS); // reset watchdog vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog
} }
} // end of infinite wifi channel rotation loop } // end of infinite wifi channel rotation loop
} }
/* end wifi specific parts ------------------------------------------------------------ */ /* end wifi specific parts
* ------------------------------------------------------------ */
// uptime counter 64bit to prevent millis() rollover after 49 days // uptime counter 64bit to prevent millis() rollover after 49 days
uint64_t uptime() { uint64_t uptime() {
static uint32_t low32, high32; static uint32_t low32, high32;
uint32_t new_low32 = millis(); uint32_t new_low32 = millis();
if (new_low32 < low32) high32++; if (new_low32 < low32)
high32++;
low32 = new_low32; low32 = new_low32;
return (uint64_t) high32 << 32 | low32; return (uint64_t)high32 << 32 | low32;
} }
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
// Print a key on display // Print a key on display
void DisplayKey(const uint8_t * key, uint8_t len, bool lsb) { void DisplayKey(const uint8_t *key, uint8_t len, bool lsb) {
const uint8_t * p ; const uint8_t *p;
for (uint8_t i=0; i<len ; i++) { for (uint8_t i = 0; i < len; i++) {
p = lsb ? key+len-i-1 : key+i; p = lsb ? key + len - i - 1 : key + i;
u8x8.printf("%02X", *p); u8x8.printf("%02X", *p);
} }
u8x8.printf("\n"); u8x8.printf("\n");
} }
void init_display(const char *Productname, const char *Version) { void init_display(const char *Productname, const char *Version) {
uint8_t buf[32]; uint8_t buf[32];
u8x8.begin(); u8x8.begin();
u8x8.setFont(u8x8_font_chroma48medium8_r); u8x8.setFont(u8x8_font_chroma48medium8_r);
@ -253,78 +260,81 @@ uint64_t uptime() {
u8x8.setFlipMode(0); u8x8.setFlipMode(0);
u8x8.clear(); u8x8.clear();
#ifdef DISPLAY_FLIP #ifdef DISPLAY_FLIP
u8x8.setFlipMode(1); u8x8.setFlipMode(1);
#endif #endif
// Display chip information // Display chip information
#ifdef VERBOSE #ifdef VERBOSE
esp_chip_info_t chip_info; esp_chip_info_t chip_info;
esp_chip_info(&chip_info); esp_chip_info(&chip_info);
u8x8.printf("ESP32 %d cores\nWiFi%s%s\n", u8x8.printf("ESP32 %d cores\nWiFi%s%s\n", chip_info.cores,
chip_info.cores,
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
u8x8.printf("ESP Rev.%d\n", chip_info.revision); u8x8.printf("ESP Rev.%d\n", chip_info.revision);
u8x8.printf("%dMB %s Flash\n", spi_flash_get_chip_size() / (1024 * 1024), u8x8.printf("%dMB %s Flash\n", spi_flash_get_chip_size() / (1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int." : "ext."); (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int." : "ext.");
#endif // VERBOSE #endif // VERBOSE
u8x8.print(Productname); u8x8.print(Productname);
u8x8.print(" v"); u8x8.print(" v");
u8x8.println(PROGVERSION); u8x8.println(PROGVERSION);
u8x8.println("DEVEUI:"); u8x8.println("DEVEUI:");
os_getDevEui((u1_t*) buf); os_getDevEui((u1_t *)buf);
DisplayKey(buf, 8, true); DisplayKey(buf, 8, true);
delay(5000); delay(5000);
u8x8.clear(); u8x8.clear();
} }
void refreshDisplay() { void refreshDisplay() {
// update counter display (lines 0-4) // update counter display (lines 0-4)
char buff[16]; char buff[16];
snprintf(buff, sizeof(buff), "PAX:%-4d", (int) macs.size()); // convert 16-bit MAC counter to decimal counter value snprintf(
u8x8.draw2x2String(0, 0, buff); // display number on unique macs total Wifi + BLE buff, sizeof(buff), "PAX:%-4d",
u8x8.setCursor(0,4); (int)macs.size()); // convert 16-bit MAC counter to decimal counter value
u8x8.draw2x2String(0, 0,
buff); // display number on unique macs total Wifi + BLE
u8x8.setCursor(0, 4);
u8x8.printf("WIFI:%-4d", macs_wifi); u8x8.printf("WIFI:%-4d", macs_wifi);
#ifdef BLECOUNTER #ifdef BLECOUNTER
u8x8.setCursor(0,3); u8x8.setCursor(0, 3);
if (cfg.blescan) if (cfg.blescan)
u8x8.printf("BLTH:%-4d", macs_ble); u8x8.printf("BLTH:%-4d", macs_ble);
else else
u8x8.printf("%s", "BLTH:off"); u8x8.printf("%s", "BLTH:off");
#endif #endif
// update LoRa SF display (line 3) // update LoRa SF display (line 3)
u8x8.setCursor(11,3); u8x8.setCursor(11, 3);
u8x8.printf("SF:"); u8x8.printf("SF:");
if (cfg.adrmode) // if ADR=on then display SF value inverse if (cfg.adrmode) // if ADR=on then display SF value inverse
u8x8.setInverseFont(1); u8x8.setInverseFont(1);
u8x8.printf("%c%c", lora_datarate[LMIC.datarate * 2], lora_datarate[LMIC.datarate * 2 + 1]); u8x8.printf("%c%c", lora_datarate[LMIC.datarate * 2],
lora_datarate[LMIC.datarate * 2 + 1]);
if (cfg.adrmode) // switch off inverse if it was turned on if (cfg.adrmode) // switch off inverse if it was turned on
u8x8.setInverseFont(0); u8x8.setInverseFont(0);
// update wifi channel display (line 4) // update wifi channel display (line 4)
u8x8.setCursor(11,4); u8x8.setCursor(11, 4);
u8x8.printf("ch:%02d", channel); u8x8.printf("ch:%02d", channel);
// update RSSI limiter status & free memory display (line 5) // update RSSI limiter status & free memory display (line 5)
u8x8.setCursor(0,5); u8x8.setCursor(0, 5);
u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit); u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit);
u8x8.setCursor(10,5); u8x8.setCursor(10, 5);
u8x8.printf("%4dKB", ESP.getFreeHeap() / 1024); u8x8.printf("%4dKB", ESP.getFreeHeap() / 1024);
// update LoRa status display (line 6) // update LoRa status display (line 6)
u8x8.setCursor(0,6); u8x8.setCursor(0, 6);
u8x8.printf("%-16s", display_lora); u8x8.printf("%-16s", display_lora);
// update LMiC event display (line 7) // update LMiC event display (line 7)
u8x8.setCursor(0,7); u8x8.setCursor(0, 7);
u8x8.printf("%-16s", display_lmic); u8x8.printf("%-16s", display_lmic);
} }
void updateDisplay() { void updateDisplay() {
// refresh display according to refresh cycle setting // refresh display according to refresh cycle setting
if (DisplayTimerIRQ) { if (DisplayTimerIRQ) {
portENTER_CRITICAL(&timerMux); portENTER_CRITICAL(&timerMux);
@ -339,11 +349,11 @@ uint64_t uptime() {
u8x8.setPowerSave(!cfg.screenon); u8x8.setPowerSave(!cfg.screenon);
} }
} }
} // updateDisplay() } // updateDisplay()
#endif // HAS_DISPLAY #endif // HAS_DISPLAY
#ifdef HAS_BUTTON #ifdef HAS_BUTTON
void readButton() { void readButton() {
if (ButtonPressedIRQ) { if (ButtonPressedIRQ) {
portENTER_CRITICAL(&timerMux); portENTER_CRITICAL(&timerMux);
ButtonPressedIRQ--; ButtonPressedIRQ--;
@ -353,31 +363,31 @@ uint64_t uptime() {
eraseConfig(); eraseConfig();
esp_restart(); esp_restart();
} }
} }
#endif #endif
#if (HAS_LED != NOT_A_PIN) || defined (HAS_RGB_LED) #if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
void blink_LED(uint16_t set_color, uint16_t set_blinkduration) { void blink_LED(uint16_t set_color, uint16_t set_blinkduration) {
LEDColor = set_color; // set color for RGB LED LEDColor = set_color; // set color for RGB LED
LEDBlinkDuration = set_blinkduration; // duration LEDBlinkDuration = set_blinkduration; // duration
LEDBlinkStarted = millis(); // Time Start here LEDBlinkStarted = millis(); // Time Start here
LEDState = LED_ON; // Let main set LED on LEDState = LED_ON; // Let main set LED on
} }
void led_loop() { void led_loop() {
// Custom blink running always have priority other LoRaWAN led management // Custom blink running always have priority other LoRaWAN led management
if ( LEDBlinkStarted && LEDBlinkDuration) { if (LEDBlinkStarted && LEDBlinkDuration) {
//ESP_LOGI(TAG, "Start=%ld for %g",LEDBlinkStarted, LEDBlinkDuration ); // ESP_LOGI(TAG, "Start=%ld for %g",LEDBlinkStarted, LEDBlinkDuration );
// Custom blink is finished, let this order, avoid millis() overflow // Custom blink is finished, let this order, avoid millis() overflow
if ( (millis() - LEDBlinkStarted) >= LEDBlinkDuration) { if ((millis() - LEDBlinkStarted) >= LEDBlinkDuration) {
// Led becomes off, and stop blink // Led becomes off, and stop blink
LEDState = LED_OFF; LEDState = LED_OFF;
LEDBlinkStarted = 0; LEDBlinkStarted = 0;
LEDBlinkDuration = 0; LEDBlinkDuration = 0;
LEDColor = COLOR_NONE ; LEDColor = COLOR_NONE;
} else { } else {
// In case of LoRaWAN led management blinked off // In case of LoRaWAN led management blinked off
LEDState = LED_ON; LEDState = LED_ON;
@ -387,7 +397,7 @@ uint64_t uptime() {
} else { } else {
// LED indicators for viusalizing LoRaWAN state // LED indicators for viusalizing LoRaWAN state
if ( LMIC.opmode & (OP_JOINING | OP_REJOIN) ) { if (LMIC.opmode & (OP_JOINING | OP_REJOIN)) {
LEDColor = COLOR_YELLOW; LEDColor = COLOR_YELLOW;
// quick blink 20ms on each 1/5 second // quick blink 20ms on each 1/5 second
LEDState = ((millis() % 200) < 20) ? LED_ON : LED_OFF; // TX data pending LEDState = ((millis() % 200) < 20) ? LED_ON : LED_OFF; // TX data pending
@ -396,7 +406,8 @@ uint64_t uptime() {
// small blink 10ms on each 1/2sec (not when joining) // small blink 10ms on each 1/2sec (not when joining)
LEDState = ((millis() % 500) < 20) ? LED_ON : LED_OFF; LEDState = ((millis() % 500) < 20) ? LED_ON : LED_OFF;
// This should not happen so indicate a problem // This should not happen so indicate a problem
} else if ( LMIC.opmode & ((OP_TXDATA | OP_TXRXPEND | OP_JOINING | OP_REJOIN) == 0 ) ) { } else if (LMIC.opmode &
((OP_TXDATA | OP_TXRXPEND | OP_JOINING | OP_REJOIN) == 0)) {
LEDColor = COLOR_RED; LEDColor = COLOR_RED;
// heartbeat long blink 200ms on each 2 seconds // heartbeat long blink 200ms on each 2 seconds
LEDState = ((millis() % 2000) < 200) ? LED_ON : LED_OFF; LEDState = ((millis() % 2000) < 200) ? LED_ON : LED_OFF;
@ -407,31 +418,33 @@ uint64_t uptime() {
} }
} }
//ESP_LOGI(TAG, "state=%d previous=%d Color=%d",LEDState, previousLEDState, LEDColor ); // ESP_LOGI(TAG, "state=%d previous=%d Color=%d",LEDState, previousLEDState,
// LEDColor );
// led need to change state? avoid digitalWrite() for nothing // led need to change state? avoid digitalWrite() for nothing
if (LEDState != previousLEDState) { if (LEDState != previousLEDState) {
if (LEDState == LED_ON) { if (LEDState == LED_ON) {
rgb_set_color(LEDColor); rgb_set_color(LEDColor);
#ifdef LED_ACTIVE_LOW #ifdef LED_ACTIVE_LOW
digitalWrite(HAS_LED, LOW); digitalWrite(HAS_LED, LOW);
#else #else
digitalWrite(HAS_LED, HIGH); digitalWrite(HAS_LED, HIGH);
#endif #endif
} else { } else {
rgb_set_color(COLOR_NONE); rgb_set_color(COLOR_NONE);
#ifdef LED_ACTIVE_LOW #ifdef LED_ACTIVE_LOW
digitalWrite(HAS_LED, HIGH); digitalWrite(HAS_LED, HIGH);
#else #else
digitalWrite(HAS_LED, LOW); digitalWrite(HAS_LED, LOW);
#endif #endif
} }
previousLEDState = LEDState; previousLEDState = LEDState;
} }
}; // led_loop() }; // led_loop()
#endif #endif
/* begin Aruino SETUP ------------------------------------------------------------ */ /* begin Aruino SETUP
* ------------------------------------------------------------ */
void setup() { void setup() {
char features[64] = ""; char features[64] = "";
@ -439,7 +452,7 @@ void setup() {
// disable brownout detection // disable brownout detection
#ifdef DISABLE_BROWNOUT #ifdef DISABLE_BROWNOUT
// register with brownout is at address DR_REG_RTCCNTL_BASE + 0xd4 // register with brownout is at address DR_REG_RTCCNTL_BASE + 0xd4
(*((volatile uint32_t *)ETS_UNCACHED_ADDR((DR_REG_RTCCNTL_BASE+0xd4)))) = 0; (*((volatile uint32_t *)ETS_UNCACHED_ADDR((DR_REG_RTCCNTL_BASE + 0xd4)))) = 0;
#endif #endif
// setup debug output or silence device // setup debug output or silence device
@ -454,19 +467,22 @@ void setup() {
ESP_LOGI(TAG, "Starting %s %s", PROGNAME, PROGVERSION); ESP_LOGI(TAG, "Starting %s %s", PROGNAME, PROGVERSION);
// initialize system event handler for wifi task, needed for wifi_sniffer_init() // initialize system event handler for wifi task, needed for
// wifi_sniffer_init()
esp_event_loop_init(NULL, NULL); esp_event_loop_init(NULL, NULL);
// print chip information on startup if in verbose mode // print chip information on startup if in verbose mode
#ifdef VERBOSE #ifdef VERBOSE
esp_chip_info_t chip_info; esp_chip_info_t chip_info;
esp_chip_info(&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", ESP_LOGI(TAG,
chip_info.cores, "This is ESP32 chip with %d CPU cores, WiFi%s%s, silicon revision "
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "", "%d, %dMB %s Flash",
chip_info.cores, (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "", (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "",
chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024), chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded"
: "external");
ESP_LOGI(TAG, "ESP32 SDK: %s", ESP.getSdkVersion()); ESP_LOGI(TAG, "ESP32 SDK: %s", ESP.getSdkVersion());
#endif #endif
@ -491,17 +507,17 @@ void setup() {
// initialize button handling if needed // initialize button handling if needed
#ifdef HAS_BUTTON #ifdef HAS_BUTTON
strcat(features, " BTN_"); strcat(features, " BTN_");
#ifdef BUTTON_PULLUP #ifdef BUTTON_PULLUP
strcat(features, "PU"); strcat(features, "PU");
// install button interrupt (pullup mode) // install button interrupt (pullup mode)
pinMode(HAS_BUTTON, INPUT_PULLUP); pinMode(HAS_BUTTON, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, RISING); attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, RISING);
#else #else
strcat(features, "PD"); strcat(features, "PD");
// install button interrupt (pulldown mode) // install button interrupt (pulldown mode)
pinMode(HAS_BUTTON, INPUT_PULLDOWN); pinMode(HAS_BUTTON, INPUT_PULLDOWN);
attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, FALLING); attachInterrupt(digitalPinToInterrupt(HAS_BUTTON), ButtonIRQ, FALLING);
#endif #endif
#endif #endif
// initialize wifi antenna if needed // initialize wifi antenna if needed
@ -522,59 +538,69 @@ void setup() {
DisplayState = cfg.screenon; DisplayState = cfg.screenon;
u8x8.setPowerSave(!cfg.screenon); // set display off if disabled u8x8.setPowerSave(!cfg.screenon); // set display off if disabled
u8x8.draw2x2String(0, 0, "PAX:0"); u8x8.draw2x2String(0, 0, "PAX:0");
u8x8.setCursor(0,4); u8x8.setCursor(0, 4);
u8x8.printf("WIFI:0"); u8x8.printf("WIFI:0");
#ifdef BLECOUNTER #ifdef BLECOUNTER
u8x8.setCursor(0,3); u8x8.setCursor(0, 3);
u8x8.printf("BLTH:0"); u8x8.printf("BLTH:0");
#endif #endif
u8x8.setCursor(0,5); u8x8.setCursor(0, 5);
u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%d", cfg.rssilimit); u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%d", cfg.rssilimit);
sprintf(display_lora, "Join wait"); sprintf(display_lora, "Join wait");
// setup display refresh trigger IRQ using esp32 hardware timer 0 // setup display refresh trigger IRQ using esp32 hardware timer 0
// for explanation see https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/ // for explanation see
displaytimer = timerBegin(0, 80, true); // prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 0, count up // https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
timerAttachInterrupt(displaytimer, &DisplayIRQ, true); // interrupt handler DisplayIRQ, triggered by edge displaytimer = timerBegin(0, 80, true); // prescaler 80 -> divides 80 MHz CPU
timerAlarmWrite(displaytimer, DISPLAYREFRESH_MS * 1000, true); // reload interrupt after each trigger of display refresh cycle // 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 timerAlarmEnable(displaytimer); // enable display interrupt
#endif #endif
// setup channel rotation trigger IRQ using esp32 hardware timer 1 // setup channel rotation trigger IRQ using esp32 hardware timer 1
channelSwitch = timerBegin(1, 80, true); channelSwitch = timerBegin(1, 80, true);
timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true); timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true);
timerAlarmWrite(channelSwitch, cfg.wifichancycle * 10000, true); timerAlarmWrite(channelSwitch, cfg.wifichancycle * 10000, true);
timerAlarmEnable(channelSwitch); timerAlarmEnable(channelSwitch);
// show compiled features // show compiled features
ESP_LOGI(TAG, "Features %s", features); ESP_LOGI(TAG, "Features %s", features);
// output LoRaWAN keys to console // output LoRaWAN keys to console
#ifdef VERBOSE #ifdef VERBOSE
printKeys(); printKeys();
#endif #endif
// initialize LoRaWAN LMIC run-time environment // initialize LoRaWAN LMIC run-time environment
os_init(); os_init();
// reset LMIC MAC state // reset LMIC MAC state
LMIC_reset(); LMIC_reset();
// This tells LMIC to make the receive windows bigger, in case your clock is 1% faster or slower. // This tells LMIC to make the receive windows bigger, in case your clock is
LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100); // 1% faster or slower.
LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
// 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
// https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/ // core 1, too)
// https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/
ESP_LOGI(TAG, "Starting 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); xTaskCreatePinnedToCore(lorawan_loop, "loratask", 2048, (void *)1,
(5 | portPRIVILEGE_BIT), NULL, 1);
// start wifi in monitor mode and start channel rotation task on core 0 // start wifi in monitor mode and start channel rotation task on core 0
ESP_LOGI(TAG, "Starting Wifi task on core 0"); ESP_LOGI(TAG, "Starting Wifi task on core 0");
wifi_sniffer_init(); wifi_sniffer_init();
// initialize salt value using esp_random() called by random() in arduino-esp32 core // initialize salt value using esp_random() called by random() in
// note: do this *after* wifi has started, since function gets it's seed from RF noise // arduino-esp32 core note: do this *after* wifi has started, since function
reset_salt(); // get new 16bit for salting hashes // gets it's seed from RF noise
xTaskCreatePinnedToCore(sniffer_loop, "wifisniffer", 2048, ( void * ) 1, 1, NULL, 0); reset_salt(); // get new 16bit for salting hashes
xTaskCreatePinnedToCore(sniffer_loop, "wifisniffer", 2048, (void *)1, 1, NULL,
0);
// start BLE scan callback if BLE function is enabled in NVRAM configuration // start BLE scan callback if BLE function is enabled in NVRAM configuration
#ifdef BLECOUNTER #ifdef BLECOUNTER
@ -583,61 +609,70 @@ xTaskCreatePinnedToCore(sniffer_loop, "wifisniffer", 2048, ( void * ) 1, 1, NULL
} }
#endif #endif
// if device has GPS and GPS function is enabled, start GPS reader task on core 0 // if device has GPS and GPS function is enabled, start GPS reader task on core
// 0
#ifdef HAS_GPS #ifdef HAS_GPS
if (cfg.gpsmode) { if (cfg.gpsmode) {
ESP_LOGI(TAG, "Starting GPS task on core 0"); ESP_LOGI(TAG, "Starting GPS task on core 0");
xTaskCreatePinnedToCore(gps_loop, "gpsfeed", 2048, ( void * ) 1, 1, NULL, 0); xTaskCreatePinnedToCore(gps_loop, "gpsfeed", 2048, (void *)1, 1, NULL, 0);
} }
#endif #endif
// kickoff sendjob -> joins network and rescedules sendjob for cyclic transmitting payload // kickoff sendjob -> joins network and rescedules sendjob for cyclic
do_send(&sendjob); // transmitting payload
do_send(&sendjob);
} }
/* end Arduino SETUP ------------------------------------------------------------ */ /* end Arduino SETUP
* ------------------------------------------------------------ */
/* begin Arduino main loop ------------------------------------------------------ */ /* begin Arduino main loop
* ------------------------------------------------------ */
void loop() { void loop() {
while (1) { while (1) {
// simple state machine for controlling uptime, display, LED, button, memory. // simple state machine for controlling uptime, display, LED, button,
// memory.
uptimecounter = uptime() / 1000; // counts uptime in seconds (64bit) uptimecounter = uptime() / 1000; // counts uptime in seconds (64bit)
#if (HAS_LED != NOT_A_PIN) || defined (HAS_RGB_LED) #if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
led_loop(); led_loop();
#endif #endif
#ifdef HAS_BUTTON #ifdef HAS_BUTTON
readButton(); readButton();
#endif #endif
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
updateDisplay(); updateDisplay();
#endif #endif
// check free memory // check free memory
if (esp_get_minimum_free_heap_size() <= MEM_LOW) { if (esp_get_minimum_free_heap_size() <= MEM_LOW) {
ESP_LOGI(TAG, "Memory full, counter cleared (heap low water mark = %d Bytes / free heap = %d bytes)", \ ESP_LOGI(TAG,
"Memory full, counter cleared (heap low water mark = %d Bytes / "
"free heap = %d bytes)",
esp_get_minimum_free_heap_size(), ESP.getFreeHeap()); esp_get_minimum_free_heap_size(), ESP.getFreeHeap());
do_send(&sendjob); // send count do_send(&sendjob); // send count
reset_counters(); // clear macs container and reset all counters reset_counters(); // clear macs container and reset all counters
reset_salt(); // get new salt for salting hashes reset_salt(); // get new salt for salting hashes
} }
#ifdef HAS_GPS #ifdef HAS_GPS
// log NMEA status every 30 seconds, useful for debugging GPS connection // log NMEA status every 30 seconds, useful for debugging GPS connection
if ( (uptime() % 30000) == 0 ) if ((uptime() % 30000) == 0)
ESP_LOGD(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d", gps.passedChecksum(), gps.failedChecksum(), gps.sentencesWithFix()); ESP_LOGD(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d",
#endif gps.passedChecksum(), gps.failedChecksum(),
gps.sentencesWithFix());
#endif
vTaskDelay(1/portTICK_PERIOD_MS); // reset watchdog vTaskDelay(1 / portTICK_PERIOD_MS); // reset watchdog
} // end of infinite main loop } // end of infinite main loop
} }
/* end Arduino main loop ------------------------------------------------------------ */ /* end Arduino main loop
* ------------------------------------------------------------ */

View File

@ -3,21 +3,19 @@
#include "lorawan.h" #include "lorawan.h"
#include "macsniff.h" #include "macsniff.h"
// program version - note: increment version after modifications to configData_t struct!! // program version - note: increment version after modifications to configData_t
// struct!!
#define PROGVERSION "1.3.8" // use max 10 chars here! #define PROGVERSION "1.3.8" // use max 10 chars here!
#define PROGNAME "PAXCNT" #define PROGNAME "PAXCNT"
//--- Declarations --- //--- Declarations ---
enum led_states { enum led_states { LED_OFF, LED_ON };
LED_OFF,
LED_ON
};
#if defined(CFG_eu868) #if defined(CFG_eu868)
const char lora_datarate[] = {"1211100908077BFSNA"}; const char lora_datarate[] = {"1211100908077BFSNA"};
#elif defined(CFG_us915) #elif defined(CFG_us915)
const char lora_datarate[] = {"100908078CNA121110090807"}; const char lora_datarate[] = {"100908078CNA121110090807"};
#endif #endif
//--- Prototypes --- //--- Prototypes ---
@ -27,15 +25,14 @@ void reset_counters(void);
void blink_LED(uint16_t set_color, uint16_t set_blinkduration); void blink_LED(uint16_t set_color, uint16_t set_blinkduration);
void led_loop(void); void led_loop(void);
// defined in blescan.cpp // defined in blescan.cpp
#ifdef BLECOUNTER #ifdef BLECOUNTER
void start_BLEscan(void); void start_BLEscan(void);
void stop_BLEscan(void); void stop_BLEscan(void);
#endif #endif
//defined in gpsread.cpp // defined in gpsread.cpp
#ifdef HAS_GPS #ifdef HAS_GPS
void gps_read(void); void gps_read(void);
void gps_loop(void * pvParameters); void gps_loop(void *pvParameters);
#endif #endif

View File

@ -1,13 +1,14 @@
// remote command interpreter // remote command interpreter
// parses multiple number of command / value pairs from LoRaWAN remote command port (RCMDPORT) // parses multiple number of command / value pairs from LoRaWAN remote command
// checks commands and executes each command with 1 argument per command // port (RCMDPORT) checks commands and executes each command with 1 argument per
// command
// Basic Config // Basic Config
#include "globals.h" #include "globals.h"
// LMIC-Arduino LoRaWAN Stack // LMIC-Arduino LoRaWAN Stack
#include <lmic.h>
#include <hal/hal.h> #include <hal/hal.h>
#include <lmic.h>
// Local logging tag // Local logging tag
static const char TAG[] = "main"; static const char TAG[] = "main";
@ -21,56 +22,82 @@ typedef struct {
// function defined in antenna.cpp // function defined in antenna.cpp
#ifdef HAS_ANTENNA_SWITCH #ifdef HAS_ANTENNA_SWITCH
void antenna_select(const uint8_t _ant); void antenna_select(const uint8_t _ant);
#endif #endif
// function defined in adcread.cpp // function defined in adcread.cpp
#ifdef HAS_BATTERY_PROBE #ifdef HAS_BATTERY_PROBE
uint32_t read_voltage(void); uint32_t read_voltage(void);
#endif #endif
// function sends result of get commands to LoRaWAN network // function sends result of get commands to LoRaWAN network
void do_transmit(osjob_t* j){ void do_transmit(osjob_t *j) {
// check if there is a pending TX/RX job running, if yes then reschedule transmission // check if there is a pending TX/RX job running, if yes then reschedule
// transmission
if (LMIC.opmode & OP_TXRXPEND) { if (LMIC.opmode & OP_TXRXPEND) {
ESP_LOGI(TAG, "LoRa busy, rescheduling"); ESP_LOGI(TAG, "LoRa busy, rescheduling");
sprintf(display_lmic, "LORA BUSY"); sprintf(display_lmic, "LORA BUSY");
os_setTimedCallback(&rcmdjob, os_getTime()+sec2osticks(RETRANSMIT_RCMD), do_transmit); 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 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); ESP_LOGI(TAG, "%d bytes queued to send", rcmd_data_size);
sprintf(display_lmic, "PACKET QUEUED"); sprintf(display_lmic, "PACKET QUEUED");
} }
// help function to transmit result of get commands, since callback function do_transmit() cannot have params // help function to transmit result of get commands, since callback function
void transmit(xref2u1_t mydata, u1_t mydata_size){ // do_transmit() cannot have params
void transmit(xref2u1_t mydata, u1_t mydata_size) {
rcmd_data = mydata; rcmd_data = mydata;
rcmd_data_size = mydata_size; rcmd_data_size = mydata_size;
do_transmit(&rcmdjob); do_transmit(&rcmdjob);
} }
// help function to assign LoRa datarates to numeric spreadfactor values // help function to assign LoRa datarates to numeric spreadfactor values
void switch_lora (uint8_t sf, uint8_t tx) { void switch_lora(uint8_t sf, uint8_t tx) {
if ( tx > 20 ) return; if (tx > 20)
return;
cfg.txpower = tx; cfg.txpower = tx;
switch (sf) { switch (sf) {
case 7: LMIC_setDrTxpow(DR_SF7,tx); cfg.lorasf=sf; break; case 7:
case 8: LMIC_setDrTxpow(DR_SF8,tx); cfg.lorasf=sf; break; LMIC_setDrTxpow(DR_SF7, tx);
case 9: LMIC_setDrTxpow(DR_SF9,tx); cfg.lorasf=sf; break; cfg.lorasf = sf;
case 10: LMIC_setDrTxpow(DR_SF10,tx); cfg.lorasf=sf; break; 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: case 11:
#if defined(CFG_eu868) #if defined(CFG_eu868)
LMIC_setDrTxpow(DR_SF11,tx); cfg.lorasf=sf; break; LMIC_setDrTxpow(DR_SF11, tx);
#elif defined(CFG_us915) cfg.lorasf = sf;
LMIC_setDrTxpow(DR_SF11CR,tx); cfg.lorasf=sf; break; break;
#endif #elif defined(CFG_us915)
LMIC_setDrTxpow(DR_SF11CR, tx);
cfg.lorasf = sf;
break;
#endif
case 12: case 12:
#if defined(CFG_eu868) #if defined(CFG_eu868)
LMIC_setDrTxpow(DR_SF12,tx); cfg.lorasf=sf; break; LMIC_setDrTxpow(DR_SF12, tx);
#elif defined(CFG_us915) cfg.lorasf = sf;
LMIC_setDrTxpow(DR_SF12CR,tx); cfg.lorasf=sf; break; break;
#endif #elif defined(CFG_us915)
default: break; LMIC_setDrTxpow(DR_SF12CR, tx);
cfg.lorasf = sf;
break;
#endif
default:
break;
} }
} }
@ -80,7 +107,9 @@ void set_reset(uint8_t val) {
case 0: // restart device case 0: // restart device
ESP_LOGI(TAG, "Remote command: restart device"); ESP_LOGI(TAG, "Remote command: restart device");
sprintf(display_lora, "Reset pending"); sprintf(display_lora, "Reset pending");
vTaskDelay(10000/portTICK_PERIOD_MS); // wait for LMIC to confirm LoRa downlink to server vTaskDelay(
10000 /
portTICK_PERIOD_MS); // wait for LMIC to confirm LoRa downlink to server
esp_restart(); esp_restart();
break; break;
case 1: // reset MAC counter case 1: // reset MAC counter
@ -104,27 +133,32 @@ void set_rssi(uint8_t val) {
void set_sendcycle(uint8_t val) { void set_sendcycle(uint8_t val) {
cfg.sendcycle = val; cfg.sendcycle = val;
ESP_LOGI(TAG, "Remote command: set payload send cycle to %d seconds", cfg.sendcycle*2); ESP_LOGI(TAG, "Remote command: set payload send cycle to %d seconds",
cfg.sendcycle * 2);
}; };
void set_wifichancycle(uint8_t val) { void set_wifichancycle(uint8_t val) {
cfg.wifichancycle = val; cfg.wifichancycle = val;
// modify wifi channel rotation IRQ // modify wifi channel rotation IRQ
timerAlarmWrite(channelSwitch, cfg.wifichancycle * 10000, true); // reload interrupt after each trigger of channel switch cycle timerAlarmWrite(
ESP_LOGI(TAG, "Remote command: set Wifi channel switch interval to %.1f seconds", cfg.wifichancycle/float(100)); channelSwitch, cfg.wifichancycle * 10000,
true); // reload interrupt after each trigger of channel switch cycle
ESP_LOGI(TAG,
"Remote command: set Wifi channel switch interval to %.1f seconds",
cfg.wifichancycle / float(100));
}; };
void set_blescantime(uint8_t val) { void set_blescantime(uint8_t val) {
cfg.blescantime = val; cfg.blescantime = val;
ESP_LOGI(TAG, "Remote command: set BLE scan time to %.1f seconds", cfg.blescantime/float(100)); ESP_LOGI(TAG, "Remote command: set BLE scan time to %.1f seconds",
#ifdef BLECOUNTER cfg.blescantime / float(100));
#ifdef BLECOUNTER
// stop & restart BLE scan task to apply new parameter // stop & restart BLE scan task to apply new parameter
if (cfg.blescan) if (cfg.blescan) {
{
stop_BLEscan(); stop_BLEscan();
start_BLEscan(); start_BLEscan();
} }
#endif #endif
}; };
void set_countmode(uint8_t val) { void set_countmode(uint8_t val) {
@ -147,24 +181,36 @@ void set_countmode(uint8_t val) {
void set_screensaver(uint8_t val) { void set_screensaver(uint8_t val) {
ESP_LOGI(TAG, "Remote command: set screen saver to %s ", val ? "on" : "off"); ESP_LOGI(TAG, "Remote command: set screen saver to %s ", val ? "on" : "off");
switch (val) { switch (val) {
case 1: cfg.screensaver = val; break; case 1:
default: cfg.screensaver = 0; break; cfg.screensaver = val;
break;
default:
cfg.screensaver = 0;
break;
} }
}; };
void set_display(uint8_t val) { void set_display(uint8_t val) {
ESP_LOGI(TAG, "Remote command: set screen to %s", val ? "on" : "off"); ESP_LOGI(TAG, "Remote command: set screen to %s", val ? "on" : "off");
switch (val) { switch (val) {
case 1: cfg.screenon = val; break; case 1:
default: cfg.screenon = 0; break; cfg.screenon = val;
break;
default:
cfg.screenon = 0;
break;
} }
}; };
void set_gps(uint8_t val) { void set_gps(uint8_t val) {
ESP_LOGI(TAG, "Remote command: set GPS to %s", val ? "on" : "off"); ESP_LOGI(TAG, "Remote command: set GPS to %s", val ? "on" : "off");
switch (val) { switch (val) {
case 1: cfg.gpsmode = val; break; case 1:
default: cfg.gpsmode = 0; break; cfg.gpsmode = val;
break;
default:
cfg.gpsmode = 0;
break;
} }
}; };
@ -176,8 +222,12 @@ void set_lorasf(uint8_t val) {
void set_loraadr(uint8_t val) { void set_loraadr(uint8_t val) {
ESP_LOGI(TAG, "Remote command: set LoRa ADR mode to %s", val ? "on" : "off"); ESP_LOGI(TAG, "Remote command: set LoRa ADR mode to %s", val ? "on" : "off");
switch (val) { switch (val) {
case 1: cfg.adrmode = val; break; case 1:
default: cfg.adrmode = 0; break; cfg.adrmode = val;
break;
default:
cfg.adrmode = 0;
break;
} }
LMIC_setAdrMode(cfg.adrmode); LMIC_setAdrMode(cfg.adrmode);
}; };
@ -188,41 +238,51 @@ void set_blescan(uint8_t val) {
case 0: case 0:
cfg.blescan = 0; cfg.blescan = 0;
macs_ble = 0; // clear BLE counter macs_ble = 0; // clear BLE counter
#ifdef BLECOUNTER #ifdef BLECOUNTER
stop_BLEscan(); stop_BLEscan();
#endif #endif
break; break;
default: default:
cfg.blescan = 1; cfg.blescan = 1;
#ifdef BLECOUNTER #ifdef BLECOUNTER
start_BLEscan(); start_BLEscan();
#endif #endif
break; break;
} }
}; };
void set_wifiant(uint8_t val) { void set_wifiant(uint8_t val) {
ESP_LOGI(TAG, "Remote command: set Wifi antenna to %s", val ? "external" : "internal"); ESP_LOGI(TAG, "Remote command: set Wifi antenna to %s",
val ? "external" : "internal");
switch (val) { switch (val) {
case 1: cfg.wifiant = val; break; case 1:
default: cfg.wifiant = 0; break; cfg.wifiant = val;
break;
default:
cfg.wifiant = 0;
break;
} }
#ifdef HAS_ANTENNA_SWITCH #ifdef HAS_ANTENNA_SWITCH
antenna_select(cfg.wifiant); antenna_select(cfg.wifiant);
#endif #endif
}; };
void set_vendorfilter(uint8_t val) { void set_vendorfilter(uint8_t val) {
ESP_LOGI(TAG, "Remote command: set vendorfilter mode to %s", val ? "on" : "off"); ESP_LOGI(TAG, "Remote command: set vendorfilter mode to %s",
val ? "on" : "off");
switch (val) { switch (val) {
case 1: cfg.vendorfilter = val; break; case 1:
default: cfg.vendorfilter = 0; break; cfg.vendorfilter = val;
break;
default:
cfg.vendorfilter = 0;
break;
} }
}; };
void set_rgblum(uint8_t val) { void set_rgblum(uint8_t val) {
// Avoid wrong parameters // Avoid wrong parameters
cfg.rgblum = (val>=0 && val<=100) ? (uint8_t) val : RGBLUMINOSITY; cfg.rgblum = (val >= 0 && val <= 100) ? (uint8_t)val : RGBLUMINOSITY;
ESP_LOGI(TAG, "Remote command: set RGB Led luminosity %d", cfg.rgblum); ESP_LOGI(TAG, "Remote command: set RGB Led luminosity %d", cfg.rgblum);
}; };
@ -231,80 +291,75 @@ void set_lorapower(uint8_t val) {
switch_lora(cfg.lorasf, val); switch_lora(cfg.lorasf, val);
}; };
void get_config (uint8_t val) { void get_config(uint8_t val) {
ESP_LOGI(TAG, "Remote command: get configuration"); ESP_LOGI(TAG, "Remote command: get configuration");
transmit((byte*)&cfg, sizeof(cfg)); transmit((byte *)&cfg, sizeof(cfg));
}; };
void get_uptime (uint8_t val) { void get_uptime(uint8_t val) {
ESP_LOGI(TAG, "Remote command: get uptime"); ESP_LOGI(TAG, "Remote command: get uptime");
transmit((byte*)&uptimecounter, sizeof(uptimecounter)); transmit((byte *)&uptimecounter, sizeof(uptimecounter));
}; };
void get_cputemp (uint8_t val) { void get_cputemp(uint8_t val) {
ESP_LOGI(TAG, "Remote command: get cpu temperature"); ESP_LOGI(TAG, "Remote command: get cpu temperature");
float temp = temperatureRead(); float temp = temperatureRead();
transmit((byte*)&temp, sizeof(temp)); transmit((byte *)&temp, sizeof(temp));
}; };
void get_voltage (uint8_t val) { void get_voltage(uint8_t val) {
ESP_LOGI(TAG, "Remote command: get battery voltage"); ESP_LOGI(TAG, "Remote command: get battery voltage");
#ifdef HAS_BATTERY_PROBE #ifdef HAS_BATTERY_PROBE
uint16_t voltage = read_voltage(); uint16_t voltage = read_voltage();
#else #else
uint16_t voltage = 0; uint16_t voltage = 0;
#endif #endif
transmit((byte*)&voltage, sizeof(voltage)); transmit((byte *)&voltage, sizeof(voltage));
}; };
void get_gps (uint8_t val) { void get_gps(uint8_t val) {
ESP_LOGI(TAG, "Remote command: get gps status"); ESP_LOGI(TAG, "Remote command: get gps status");
#ifdef HAS_GPS #ifdef HAS_GPS
gps_read(); gps_read();
transmit((byte*)&gps_status, sizeof(gps_status)); 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); ESP_LOGI(TAG, "lat=%f / lon=%f | Sats=%u | HDOP=%u | Alti=%u",
#else gps_status.latitude / 1000000, gps_status.longitude / 1000000,
gps_status.satellites, gps_status.hdop, gps_status.altitude);
#else
ESP_LOGE(TAG, "GPS not present"); ESP_LOGE(TAG, "GPS not present");
#endif #endif
}; };
// assign previously defined functions to set of numeric remote commands // assign previously defined functions to set of numeric remote commands
// format: opcode, function, flag (1 = do make settings persistent / 0 = don't) // format: opcode, function, flag (1 = do make settings persistent / 0 = don't)
// //
cmd_t table[] = { cmd_t table[] = {{0x01, set_rssi, true}, {0x02, set_countmode, true},
{0x01, set_rssi, true}, {0x03, set_gps, true}, {0x04, set_display, true},
{0x02, set_countmode, true}, {0x05, set_lorasf, true}, {0x06, set_lorapower, true},
{0x03, set_gps, true}, {0x07, set_loraadr, true}, {0x08, set_screensaver, true},
{0x04, set_display, true}, {0x09, set_reset, false}, {0x0a, set_sendcycle, true},
{0x05, set_lorasf, true}, {0x0b, set_wifichancycle, true}, {0x0c, set_blescantime, true},
{0x06, set_lorapower, true}, {0x0d, set_vendorfilter, false}, {0x0e, set_blescan, true},
{0x07, set_loraadr, true}, {0x0f, set_wifiant, true}, {0x10, set_rgblum, true},
{0x08, set_screensaver, true}, {0x80, get_config, false}, {0x81, get_uptime, false},
{0x09, set_reset, false}, {0x82, get_cputemp, false}, {0x83, get_voltage, false},
{0x0a, set_sendcycle, true}, {0x84, get_gps, false}};
{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},
{0x84, get_gps, false}
};
// check and execute remote command // check and execute remote command
void rcommand(uint8_t cmd, uint8_t arg) { void rcommand(uint8_t cmd, uint8_t arg) {
int i = sizeof(table) / sizeof(table[0]); // number of commands in command table int i =
sizeof(table) / sizeof(table[0]); // number of commands in command table
bool store_flag = false; bool store_flag = false;
while(i--) { while (i--) {
if(cmd == table[i].nam) { // check if valid command if (cmd == table[i].nam) { // check if valid command
table[i].func(arg); // then execute assigned function table[i].func(arg); // then execute assigned function
if ( table[i].store ) store_flag = true; // set save flag if function needs to store configuration if (table[i].store)
store_flag =
true; // set save flag if function needs to store configuration
break; // exit check loop, since command was found 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 if (store_flag)
saveConfig(); // if save flag is set: store new configuration in NVS to make
// it persistent
} }

View File

@ -6,8 +6,7 @@
// RGB Led instance // RGB Led instance
SmartLed rgb_led(LED_WS2812, 1, HAS_RGB_LED); SmartLed rgb_led(LED_WS2812, 1, HAS_RGB_LED);
float rgb_CalcColor(float p, float q, float t) float rgb_CalcColor(float p, float q, float t) {
{
if (t < 0.0f) if (t < 0.0f)
t += 1.0f; t += 1.0f;
if (t > 1.0f) if (t > 1.0f)
@ -30,19 +29,15 @@ float rgb_CalcColor(float p, float q, float t)
// HslColor using H, S, L values (0.0 - 1.0) // HslColor using H, S, L values (0.0 - 1.0)
// L should be limited to between (0.0 - 0.5) // L should be limited to between (0.0 - 0.5)
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
RGBColor rgb_hsl2rgb(float h, float s, float l) RGBColor rgb_hsl2rgb(float h, float s, float l) {
{
RGBColor RGB_color; RGBColor RGB_color;
float r; float r;
float g; float g;
float b; float b;
if (s == 0.0f || l == 0.0f) if (s == 0.0f || l == 0.0f) {
{
r = g = b = l; // achromatic or black r = g = b = l; // achromatic or black
} } else {
else
{
float q = l < 0.5f ? l * (1.0f + s) : l + s - (l * s); float q = l < 0.5f ? l * (1.0f + s) : l + s - (l * s);
float p = 2.0f * l - q; float p = 2.0f * l - q;
r = rgb_CalcColor(p, q, h + 1.0f / 3.0f); r = rgb_CalcColor(p, q, h + 1.0f / 3.0f);
@ -60,15 +55,15 @@ RGBColor rgb_hsl2rgb(float h, float s, float l)
void rgb_set_color(uint16_t hue) { void rgb_set_color(uint16_t hue) {
if (hue == COLOR_NONE) { if (hue == COLOR_NONE) {
// Off // Off
rgb_led[0] = Rgb(0,0,0); rgb_led[0] = Rgb(0, 0, 0);
} else { } else {
// see http://www.workwithcolor.com/blue-color-hue-range-01.htm // see http://www.workwithcolor.com/blue-color-hue-range-01.htm
// H (is color from 0..360) should be between 0.0 and 1.0 // H (is color from 0..360) should be between 0.0 and 1.0
// S is saturation keep it to 1 // S is saturation keep it to 1
// L is brightness should be between 0.0 and 0.5 // L is brightness should be between 0.0 and 0.5
// cfg.rgblum is between 0 and 100 (percent) // cfg.rgblum is between 0 and 100 (percent)
RGBColor target = rgb_hsl2rgb( hue / 360.0f, 1.0f, 0.005f * cfg.rgblum); RGBColor target = rgb_hsl2rgb(hue / 360.0f, 1.0f, 0.005f * cfg.rgblum);
//uint32_t color = target.R<<16 | target.G<<8 | target.B; // uint32_t color = target.R<<16 | target.G<<8 | target.B;
rgb_led[0] = Rgb(target.R, target.G, target.B); rgb_led[0] = Rgb(target.R, target.G, target.B);
} }
// Show // Show

View File

@ -19,8 +19,7 @@
#define COLOR_WHITE 360 #define COLOR_WHITE 360
#define COLOR_NONE 999 #define COLOR_NONE 999
struct RGBColor struct RGBColor {
{
uint8_t R; uint8_t R;
uint8_t G; uint8_t G;
uint8_t B; uint8_t B;

View File

@ -36,37 +36,41 @@
#include <inttypes.h> #include <inttypes.h>
uint32_t rokkit(const char * data, int len) { uint32_t rokkit(const char *data, int len) {
uint32_t hash, tmp; uint32_t hash, tmp;
int rem; int rem;
if (len <= 0 || data == 0) return 0; if (len <= 0 || data == 0)
return 0;
hash = len; hash = len;
rem = len & 3; rem = len & 3;
len >>= 2; len >>= 2;
/* Main loop */ /* Main loop */
while (len > 0) { while (len > 0) {
hash += *((uint16_t*)data); hash += *((uint16_t *)data);
tmp = (*((uint16_t*)(data+2)) << 11) ^ hash; tmp = (*((uint16_t *)(data + 2)) << 11) ^ hash;
hash = (hash << 16) ^ tmp; hash = (hash << 16) ^ tmp;
data += 2*2; data += 2 * 2;
hash += hash >> 11; hash += hash >> 11;
len--; len--;
} }
/* Handle end cases */ /* Handle end cases */
switch (rem) { switch (rem) {
case 3: hash += *((uint16_t*)data); case 3:
hash += *((uint16_t *)data);
hash ^= hash << 16; hash ^= hash << 16;
hash ^= ((signed char)data[2]) << 18; hash ^= ((signed char)data[2]) << 18;
hash += hash >> 11; hash += hash >> 11;
break; break;
case 2: hash += *((uint16_t*)data); case 2:
hash += *((uint16_t *)data);
hash ^= hash << 11; hash ^= hash << 11;
hash += hash >> 17; hash += hash >> 17;
break; break;
case 1: hash += (signed char)*data; case 1:
hash += (signed char)*data;
hash ^= hash << 10; hash ^= hash << 10;
hash += hash >> 1; hash += hash >> 1;
} }

File diff suppressed because it is too large Load Diff