/* * * Oliver Brandmueller 2017/2018 * Klaus Wilting 2018 * * some lines of code taken from: * * Copyright (c) 2017, Ɓukasz Marcin Podkalicki * ESP32/016 WiFi Sniffer. * https://github.com/lpodkalicki/blog/tree/master/esp32/016_wifi_sniffer * * Arduino-LMIC Library * TTN OTAA Example * https://github.com/matthijskooijman/arduino-lmic/blob/master/examples/ttn-otaa/ * * nkolban esp32 snippets * BLE Scan * https://github.com/nkolban/esp32-snippets/tree/master/cpp_utils/tests/BLETests/Arduino/BLE_scan * * parts of code in lorawan.cpp has been grabbed from RadioHead Library */ // First things first #include "main.h" // std::set for unified array functions #include // OLED driver #include // LMIC-Arduino LoRaWAN Stack #include #include // Basic Config #include "loraconf.h" #include "globals.h" // WiFi Functions #include #include #include #include #include #include #include // we need this for ESP_LOGx on arduino framework configData_t cfg; // struct holds current device configuration osjob_t sendjob, initjob; // LMIC // Initialize global variables int macnum = 0, blenum = 0; uint64_t uptimecounter = 0; bool joinstate = false; std::set > macs; // storage holds MAC frames // this variable will be changed in the ISR, and read in main loop static volatile bool ButtonTriggered = false; // local Tag for logging static const char *TAG = "paxcnt"; // Note: Log level control seems not working during runtime, // so we need to switch loglevel by compiler build option in platformio.ini #ifndef VERBOSE int redirect_log(const char * fmt, va_list args) { //do nothing return 0; } #endif // defined in configmanager.cpp void eraseConfig(void); void saveConfig(void); void loadConfig(void); /* begin LMIC specific parts ------------------------------------------------------------ */ // defined in lorawan.cpp void gen_lora_deveui(uint8_t * pdeveui); #ifdef VERBOSE void printKeys(void); #endif // VERBOSE // LMIC callback functions void os_getArtEui (u1_t *buf) { memcpy(buf, APPEUI, 8);} void os_getDevKey (u1_t *buf) { memcpy(buf, APPKEY, 16);} #ifdef DEVEUI // if DEVEUI defined in loraconf.h use that and hardwire it in code ... void os_getDevEui (u1_t *buf) { memcpy(buf, DEVEUI, 8);} #else // ... otherwise generate DEVEUI at runtime from devices's MAC void os_getDevEui (u1_t *buf) { gen_lora_deveui(buf);} #endif // LMIC enhanced Pin mapping const lmic_pinmap lmic_pins = { .mosi = PIN_SPI_MOSI, .miso = PIN_SPI_MISO, .sck = PIN_SPI_SCK, .nss = PIN_SPI_SS, .rxtx = LMIC_UNUSED_PIN, .rst = RST, .dio = {DIO0, DIO1, DIO2} }; // LMIC functions void onEvent(ev_t ev); void do_send(osjob_t* j); // LoRaWAN Initjob static void lora_init (osjob_t* j) { // reset MAC state LMIC_reset(); // This tells LMIC to make the receive windows bigger, in case your clock is 1% faster or slower. LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100); // start joining LMIC_startJoining(); } // LMIC Task void lorawan_loop(void * pvParameters) { configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check while(1) { os_runloop_once(); vTaskDelay(10/portTICK_PERIOD_MS); yield(); } } /* end LMIC specific parts --------------------------------------------------------------- */ /* beginn hardware specific parts -------------------------------------------------------- */ #ifdef HAS_DISPLAY HAS_DISPLAY u8x8(OLED_RST, OLED_SCL, OLED_SDA); #else U8X8_NULL u8x8; #endif #ifdef LOPY // defined in antenna.cpp void antenna_init (void); void antenna_select (antenna_type_t antenna_type); #endif #if defined BLECOUNTER void BLECount(void); #else btStop(); #endif void set_onboard_led(int st){ #ifdef HAS_LED switch (st) { case 1: digitalWrite(HAS_LED, HIGH); break; case 0: digitalWrite(HAS_LED, LOW); break; } #endif }; #ifdef HAS_BUTTON // Button Handling, board dependent -> perhaps to be moved to new hal.cpp // IRAM_ATTR necessary here, see https://github.com/espressif/arduino-esp32/issues/855 void IRAM_ATTR isr_button_pressed(void) { ButtonTriggered++; } #endif /* end hardware specific parts -------------------------------------------------------- */ /* begin wifi specific parts ---------------------------------------------------------- */ // defined in wifisniffer.cpp void wifi_sniffer_init(void); void wifi_sniffer_set_channel(uint8_t channel); void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type); //WiFi Sniffer Task void wifi_sniffer_loop(void * pvParameters) { configASSERT( ( ( uint32_t ) pvParameters ) == 1 ); // FreeRTOS check uint8_t channel = 1; int nloop=0, lorawait=0; while (true) { nloop++; vTaskDelay(cfg.wifichancycle*10 / portTICK_PERIOD_MS); yield(); wifi_sniffer_set_channel(channel); channel = (channel % WIFI_CHANNEL_MAX) + 1; // duration of one wifi scan loop reached? then send data and begin new scan cycle if( nloop >= ((100 / cfg.wifichancycle) * (cfg.wifiscancycle * 2)) ) { u8x8.setPowerSave(!cfg.screenon); // set display on if enabled nloop = 0; // reset wlan sniffing loop counter // execute BLE count if BLE function is enabled #ifdef BLECOUNTER if ( cfg.blescan ) BLECount(); #endif // Prepare and execute LoRaWAN data upload u8x8.setCursor(0,4); u8x8.printf("MAC#: %4i", macnum); do_send(&sendjob); // send payload vTaskDelay(500/portTICK_PERIOD_MS); yield(); // clear counter if not in cumulative counter mode if ( cfg.countermode != 1 ) { macs.erase(macs.begin(), macs.end()); // clear RAM macnum = 0; u8x8.clearLine(0); u8x8.clearLine(1); // clear Display counter } // wait until payload is sent, while wifi scanning and mac counting task continues lorawait = 0; while(LMIC.opmode & OP_TXRXPEND) { if(!lorawait) u8x8.drawString(0,6,"LoRa wait "); lorawait++; // in case sending really fails: reset and rejoin network if( (lorawait % MAXLORARETRY ) == 0) { ESP_LOGI(TAG, "Payload not sent, trying reset and rejoin"); esp_restart(); }; vTaskDelay(1000/portTICK_PERIOD_MS); yield(); } u8x8.clearLine(6); if (cfg.screenon && cfg.screensaver) vTaskDelay(2000/portTICK_PERIOD_MS); // pause for displaying results yield(); u8x8.setPowerSave(1 && cfg.screensaver); // set display off if screensaver is enabled } } } /* end wifi specific parts ------------------------------------------------------------ */ // uptime counter 64bit to prevent millis() rollover after 49 days uint64_t uptime() { static uint32_t low32, high32; uint32_t new_low32 = millis(); if (new_low32 < low32) high32++; low32 = new_low32; return (uint64_t) high32 << 32 | low32; } // Print a key on display void DisplayKey(const uint8_t * key, uint8_t len, bool lsb) { uint8_t start=lsb?len:0; uint8_t end = lsb?0:len; const uint8_t * p ; for (uint8_t i=0; i