/******************************************************************************* * Copyright (c) 2015 Thomas Telkamp and Matthijs Kooijman * * Permission is hereby granted, free of charge, to anyone * obtaining a copy of this document and accompanying files, * to do whatever they want with them without any restriction, * including, but not limited to, copying, modification and redistribution. * NO WARRANTY OF ANY KIND IS PROVIDED. * * This uses ABP (Activation-by-personalisation), where a DevAddr and * Session keys are preconfigured (unlike OTAA, where a DevEUI and * application key is configured, while the DevAddr and session keys are * assigned/generated in the over-the-air-activation procedure). * * Note: LoRaWAN per sub-band duty-cycle limitation is enforced (1% in * g1, 0.1% in g2), but not the TTN fair usage policy (which is probably * violated by this sketch when left running for longer)! * * To use this sketch, first register your application and device with * the things network, to set or generate a DevAddr, NwkSKey and * AppSKey. Each device should have their own unique values for these * fields. * * Do not forget to define the radio type correctly in config.h. * ******************************************************************************* * * The Things Conference Workshop - WiFi Localisation * by Frank Beks * * This sketch will check it's location by listening to surrounding WiFi networks. * It will run on Wemos ESP8266 / RFM95 Ch2i board * * Therefore use this LMIC library: https://github.com/ch2i/arduino-lmic * this because of the special DIO settings (all pins tied together with diodes) * * Payload function on TTN: * * var hexChar = ["0", "1", "2", "3", "4", "5", "6", "7","8", "9", "A", "B", "C", "D", "E", "F"]; function byteToHex(b) { return hexChar[(b >> 4) & 0x0f] + hexChar[b & 0x0f]; } function hexToInt(hex) { var num=hex; if (num>0x7F) { num=num-0x100; } return num; } function Decoder(bytes) { var mac1=""; for (i = 0; i < 6; i++) { mac1 += byteToHex(bytes[i]); if (i<5) { mac1+=':';} } var rssi1=hexToInt(bytes[6]); var mac2=""; for (i = 0; i < 6; i++) { mac2 += byteToHex(bytes[i+7]); if (i<5) { mac2+=':';} } var rssi2=hexToInt(bytes[13]); return { macaddress: { mac_1: mac1, rssi_1:rssi1, mac_2: mac2, rssi_2:rssi2, }, }; } *********************************************************************************/ #include #include #include #include /* Serial Baud Rate */ #define SERIAL_BAUD 115200 /* Delay paramter for connection. */ #define WIFI_DELAY 500 /* Max SSID octets. */ #define MAX_SSID_LEN 32 /* Wait this much until device gets IP. */ #define MAX_CONNECT_TIME 30000 /* SSID that to be stored to connect. */ char ssid[MAX_SSID_LEN] = ""; // LoRaWAN NwkSKey, network session key static const PROGMEM u1_t NWKSKEY[16] = { }; // LoRaWAN AppSKey, application session key // This is the default Semtech key, which is used by the early prototype TTN // network. static const u1_t PROGMEM APPSKEY[16] = { }; // LoRaWAN end-device address (DevAddr) static const u4_t DEVADDR = 0x ; // <-- Change this address for every node! // These callbacks are only used in over-the-air activation, so they are // left empty here (we cannot leave them out completely unless // DISABLE_JOIN is set in config.h, otherwise the linker will complain). void os_getArtEui (u1_t* buf) { } void os_getDevEui (u1_t* buf) { } void os_getDevKey (u1_t* buf) { } #define MAX_MAC 2 // number of MAC addresses to sent static uint8_t mydata[MAX_MAC*7] ; static osjob_t sendjob; // Schedule TX every this many seconds (might become longer due to duty // cycle limitations). const unsigned TX_INTERVAL = 60; const lmic_pinmap lmic_pins = { .nss = 16, .rxtx = LMIC_UNUSED_PIN, .rst = LMIC_UNUSED_PIN, .dio = {15, LMIC_UNUSED_PIN, LMIC_UNUSED_PIN}, }; void onEvent (ev_t ev) { Serial.print(os_getTime()); Serial.print(": "); switch(ev) { case EV_SCAN_TIMEOUT: Serial.println(F("EV_SCAN_TIMEOUT")); break; case EV_BEACON_FOUND: Serial.println(F("EV_BEACON_FOUND")); break; case EV_BEACON_MISSED: Serial.println(F("EV_BEACON_MISSED")); break; case EV_BEACON_TRACKED: Serial.println(F("EV_BEACON_TRACKED")); break; case EV_JOINING: Serial.println(F("EV_JOINING")); break; case EV_JOINED: Serial.println(F("EV_JOINED")); break; case EV_RFU1: Serial.println(F("EV_RFU1")); break; case EV_JOIN_FAILED: Serial.println(F("EV_JOIN_FAILED")); break; case EV_REJOIN_FAILED: Serial.println(F("EV_REJOIN_FAILED")); break; case EV_TXCOMPLETE: Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)")); if (LMIC.txrxFlags & TXRX_ACK) Serial.println(F("Received ack")); if (LMIC.dataLen) { Serial.println(F("Received ")); Serial.println(LMIC.dataLen); Serial.println(F(" bytes of payload")); } // Schedule next transmission os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send); break; case EV_LOST_TSYNC: Serial.println(F("EV_LOST_TSYNC")); break; case EV_RESET: Serial.println(F("EV_RESET")); break; case EV_RXCOMPLETE: // data received in ping slot Serial.println(F("EV_RXCOMPLETE")); break; case EV_LINK_DEAD: Serial.println(F("EV_LINK_DEAD")); break; case EV_LINK_ALIVE: Serial.println(F("EV_LINK_ALIVE")); break; case EV_SCAN_FOUND: Serial.println(F("EV_SCAN_FOUND")); break; case EV_TXSTART: Serial.println(F("EV_TXSTART")); break; default: Serial.print(F("Unknown event: ")); Serial.println(ev); break; } } void do_send(osjob_t* j){ // Check if there is not a current TX/RX job running if (LMIC.opmode & OP_TXRXPEND) { Serial.println(F("OP_TXRXPEND, not sending")); } else { // Prepare upstream data transmission at the next possible time. scanAndSort(); LMIC_setTxData2(1, mydata, MAX_MAC*7, 0); //Sent packet to TTN Serial.println(F("Packet queued")); } // Next TX is scheduled after TX_COMPLETE event. } /* Scan available networks and sort them in order to their signal strength. */ void scanAndSort() { memset(ssid, 0, MAX_SSID_LEN); uint8_t * macptr; int n = WiFi.scanNetworks(); Serial.println("Scan done, sort starting!"); if (n == 0) { Serial.println("No networks found!"); } else { Serial.print(n); Serial.println(" networks found."); int indices[n]; for (int i = 0; i < n; i++) { indices[i] = i; } for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (WiFi.RSSI(indices[j]) > WiFi.RSSI(indices[i])) { std::swap(indices[i], indices[j]); } } } for (int i = 0; i < n; ++i) { Serial.print(WiFi.SSID(indices[i])); Serial.print(" "); Serial.print(WiFi.RSSI(indices[i])); Serial.print(" "); Serial.print(WiFi.BSSIDstr(indices[i])); Serial.print(" "); Serial.print(WiFi.encryptionType(indices[i])); Serial.println(); } Serial.println("Best BSSID: "); for(int i=0;i