Fork to see if I can get working
Dependencies: BufferedSerial OneWire WinbondSPIFlash libxDot-dev-mbed5-deprecated
Fork of xDotBridge_update_test20180823 by
Revision 61:8d9efd33cac9, committed 2017-03-09
- Comitter:
- Matt Briggs
- Date:
- Thu Mar 09 16:47:42 2017 -0700
- Parent:
- 60:5179449a684f
- Child:
- 62:9751a8504c82
- Commit message:
- Slight modification of pair code and documentation. Also some test code to all xDot dev boards to act like bridges.
Changed in this revision
--- a/xDotBridge/README.md Mon Mar 06 15:16:58 2017 -0700 +++ b/xDotBridge/README.md Thu Mar 09 16:47:42 2017 -0700 @@ -65,6 +65,57 @@ and data session keys. This guarantees by design that all message sent can only be received and decoded by units in the pair group. +### Brute force algorithm +TODO + +#### Brute force alert message +============================================== += Offset | Size (in Bytes) | Name = +============================================== += 0x00 | 2 Bytes | Alert Msg Flag (0xEF10) = +============================================== += 0x02 | 8 Bytes | xDot EUI = +============================================== += 0x0A | 2 Bytes | Alert Data = +============================================== += 0x0C | 4 Bytes | Alert Sequence Number = +============================================== +Total of 16 bytes + +#### Brute force pair request message +============================================== += Offset | Size (in Bytes) | Name = +============================================== += 0x00 | 2 Bytes | Pair Request Flag (0xFE01)= +============================================== += 0x02 | 8 Bytes | xDot EUI (requester) = +============================================== += 0x0A | 6 Bytes | Reserved = +============================================== +* Total of 16 Bytes + +Ideas for reserved: + * Network type desired + * Messages generated + +#### Brute force pair accept message +============================================== += Offset | Size (in Bytes) | Name = +============================================== += 0x00 | 2 Bytes | Pair Accept Flag (0xFD02) = +============================================== += 0x02 | 8 Bytes | xDot EUI (RX Master) = +============================================== += 0x0A | 4 Bytes | Reserved for Frequency = +============================================== += 0x0D | 4 Bytes | Network ID = +============================================== += 0x12 | 8 Bytes | Network Key = +============================================== += 0x1A | 8 Bytes | Data session Key = +============================================== +* Total of 34 Bytes + ## Peer to Peer Pair Pairing needs to support many topologies including one TX to one RX, many TX to one RX, and finally many TX to many RX. The pairing process not only has the @@ -107,7 +158,9 @@ track of the copies. * This scheme does not support hybrid pairing where two RX can receive one TX and one of the two can receive additional TX messages the other cannot. It might be -possible to support this but the pairing process would become more complex. +possible to support this but the pairing process would become more complex. + +#### Pair message details ## LoRaWAN Just use the xDots and the conduit as they are designed to be used. No pairing just straight LoRaWAN.
--- a/xDotBridge/config.h Mon Mar 06 15:16:58 2017 -0700 +++ b/xDotBridge/config.h Thu Mar 09 16:47:42 2017 -0700 @@ -5,12 +5,13 @@ #ifndef CONFIG_H_ #define CONFIG_H_ -//#define __TEST__ 1 // Comment out for main application +#define __TEST__ 1 // Comment out for main application // Manual test. Comment out for main application. Or uncomment for individual test. //#define __TEST_BBIO__ //#define __TEST_LRR__ //#define __TEST_PVD__ +#define __TEST_XDOT_DEV_COMM__ // These define which wireless bridge you are generating code for #define LED_FEEDBACK 1 // If 1 then LED is shown and 0 LED is not shown to conserve power
--- a/xDotBridge/inc/CommProtocolPeerBrute.h Mon Mar 06 15:16:58 2017 -0700
+++ b/xDotBridge/inc/CommProtocolPeerBrute.h Thu Mar 09 16:47:42 2017 -0700
@@ -177,6 +177,8 @@
*/
CmdResult sendPairAccepted();
+ CmdResult waitForAccept(float waitTime);
+
// xDot Peer to Peer Specific
/**
* Convenience function to get the internal downlink count from radio
@@ -240,7 +242,10 @@
* Generates new encryption keys for radio
* @return
*/
- CmdResult genEncypKeys();
+ CmdResult genEncypKey(std::vector<uint8_t> &newKey, uint8_t keySize);
+
+ CmdResult configForPairingNetwork();
+ CmdResult configForSavedNetwork();
};
--- a/xDotBridge/manualTest/testBaseboardIO/testBaseboardIO.cpp Mon Mar 06 15:16:58 2017 -0700
+++ b/xDotBridge/manualTest/testBaseboardIO/testBaseboardIO.cpp Thu Mar 09 16:47:42 2017 -0700
@@ -9,7 +9,7 @@
mDot* dot = NULL; // Used by dot-utils
Serial pc(USBTX, USBRX); // Externally defined
-const int VERSION = 4;
+const int VERSION = 5;
char* bool2Str(bool in) {
if (in) {
@@ -35,8 +35,6 @@
pairBtnIntCnt++;
}
-// TODO Add in later after I figure out how
-
class MenuManager
{
private:
@@ -118,8 +116,8 @@
bool2Str(0), ccInIntCnt);
pc.printf("= PVD (BROKEN). State: N/A IntCnt: %02d =\r\n",
pvdIntCnt);
+ pc.printf("= CC Normally Closed. State: %s =\r\n", bool2Str(mBbio->isCCNC()));
pc.printf("= Is TX. State: %s =\r\n", bool2Str(mBbio->isTx()));
- pc.printf("= CC Normally Closed. State: %s =\r\n", bool2Str(mBbio->isCCNC()));
pc.printf("= Is LoraWAN. State: %s =\r\n", bool2Str(mBbio->isLoRaWANMode()));
pc.printf("= Is Serial En. State: %s =\r\n", bool2Str(mBbio->isSerialEnabled()));
pc.printf("= Rotary Switch 1. Value: %02d =\r\n", mBbio->rotarySwitch1());
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xDotBridge/manualTest/testXDotDevComm/testXDotDevComm.cpp Thu Mar 09 16:47:42 2017 -0700
@@ -0,0 +1,98 @@
+#include "mbed.h"
+#include "../../config.h"
+#include "CommProtocolPeerBrute.h"
+//#include "BaseboardIO.h"
+//#include "MTSLog.h"
+#include "RadioEvent.h"
+#include "dot_util.h"
+#include "mDot.h"
+
+#ifdef __TEST_XDOT_DEV_COMM__
+Serial pc(USBTX, USBRX); // Externally defined
+mDot* dot = NULL; // Used by dot-utils
+
+const int VERSION = 0;
+
+volatile bool ccInIntFlag; // Wake pin
+
+void ccInIntCallback () {
+ ccInIntFlag = true;
+}
+
+InterruptIn mCCIn(WAKE);
+DigitalOut led(GPIO0);
+/**
+ * Checks that in idle state all the IOs are pulled up.
+ */
+int main ()
+{
+ CommProtocolPeerBrute *protocol = new CommProtocolPeerBrute();
+ unsigned int loopCnt = 0;
+ uint16_t txSeqNum=0;
+ uint16_t rxSeqNum=0;
+ CmdResult result;
+ std::vector<uint8_t> data;
+ pc.baud(115200);
+ RadioEvent events; // Custom event handler for automatically displaying RX data
+ mts::MTSLog::setLogLevel(mts::MTSLog::TRACE_LEVEL);
+ dot = mDot::getInstance();
+
+ dot->setLogLevel(mts::MTSLog::INFO_LEVEL); // This actually is very important
+
+ dot->setEvents(&events); // Little bonus event debug information
+
+ protocol->init();
+ dot->setWakeMode(mDot::RTC_ALARM_OR_INTERRUPT);
+ dot->setWakePin(UART_CTS);
+
+ ccInIntFlag = false;
+
+ Callback<void()> ccInIntObj (&ccInIntCallback);
+ mCCIn.rise(ccInIntCallback);
+ mCCIn.mode(PullDown);
+ mCCIn.enable_irq();
+
+ uint8_t waitCharIdx = 0;
+
+ logInfo("Version %d. Setup complete. Starting main loop.", VERSION);
+
+ while (true) {
+ if (ccInIntFlag) { // TX
+ led = 1;
+ data.clear();
+ data.push_back((txSeqNum >> 8) & 0xFF);
+ data.push_back(txSeqNum & 0xFF);
+ std::string dataStr(data.begin(), data.end());
+ logInfo("Sent msg num: %d, payload: %s", txSeqNum, dataStr.c_str());
+ protocol->send(data);
+ txSeqNum++;
+ ccInIntFlag = false;
+ }
+ else { // RX
+ bool msgPending;
+ protocol->listen(msgPending);
+ logInfo("Loop Cnt %d. Listening.", loopCnt);
+ if (msgPending) {
+ protocol->recv(data);
+ std::string dataStr(data.begin(), data.end());
+ logInfo("Got msg num: %d, payload: %s", rxSeqNum, dataStr.c_str());
+ rxSeqNum++;
+ led = 1;
+ wait(0.5);
+ protocol->sampleDLC();
+ }
+ }
+
+ loopCnt++;
+
+ led = 0;
+ sleep_save_io();
+ sleep_configure_io();
+ dot->sleep(2, mDot::RTC_ALARM_OR_INTERRUPT, false); // Go to sleep until wake button
+ sleep_restore_io();
+ logInfo("\r\n================================");
+ }
+ return 0;
+}
+
+#endif
--- a/xDotBridge/src/BaseboardIO.cpp Mon Mar 06 15:16:58 2017 -0700 +++ b/xDotBridge/src/BaseboardIO.cpp Thu Mar 09 16:47:42 2017 -0700 @@ -10,7 +10,11 @@ #include "dot_util.h" // FIXME just need the reference to dot somehow #include "xdot_low_power.h" -const float COIL_ON_TIME = 0.030; // 30 ms +// Original +const float COIL_ON_TIME = 0.060; // 30 ms +// Test +//const float COIL_ON_TIME = 0.30; // 300 ms + // Port expander 0 (Currently U7) const uint8_t pEx0232En = 0x01;
--- a/xDotBridge/src/CommProtocolPeerBrute.cpp Mon Mar 06 15:16:58 2017 -0700
+++ b/xDotBridge/src/CommProtocolPeerBrute.cpp Thu Mar 09 16:47:42 2017 -0700
@@ -21,8 +21,7 @@
logInfo("RX_SLEEP_TIME %f, timeOnAir %lu, nTimesToTx %lu", RX_SLEEP_TIME, TX_TIME, nTimesToTx);
mIsTx = true; // default to TX
- mPrevDownLinkCnt = dot->getDownLinkCounter();
-// dot = mDot::getInstance();
+// mPrevDownLinkCnt = dot->getDownLinkCounter();
}
CmdResult CommProtocolPeerBrute::init()
@@ -30,6 +29,7 @@
// FIXME add NVM stuff
dotDefaults();
+ return cmdSuccess;
}
CmdResult CommProtocolPeerBrute::dotDefaults()
{
@@ -43,7 +43,7 @@
dot->setAck(0); // Disable Ack
dot->setClass("C"); // Set class C
dot->setTxPower(TX_PWR);
- dot->setPreserveSession(true); // TODO need to better handle counters
+ dot->setPreserveSession(false); // TODO need to better handle counters
// TODO break out in a utility function
// update configuration if necessary
@@ -93,6 +93,44 @@
dot->saveConfig();
return cmdSuccess;
}
+CmdResult CommProtocolPeerBrute::configForPairingNetwork()
+{
+ uint8_t tx_power;
+ uint8_t tx_datarate;
+ uint32_t tx_frequency;
+ uint8_t frequency_band = dot->getFrequencyBand();
+ switch (frequency_band) {
+ case mDot::FB_EU868:
+ // 250kHz channels achieve higher throughput
+ // DR6 : SF7 @ 250kHz
+ // DR0 - DR5 (125kHz channels) available but much slower
+ tx_frequency = 869850000;
+ tx_datarate = mDot::DR6;
+ // the 869850000 frequency is 100% duty cycle if the total power is under 7 dBm - tx power 4 + antenna gain 3 = 7
+ tx_power = 4;
+ break;
+ case mDot::FB_US915:
+ case mDot::FB_AU915:
+ default:
+ // 500kHz channels achieve highest throughput
+ // DR8 : SF12 @ 500kHz
+ // DR9 : SF11 @ 500kHz
+ // DR10 : SF10 @ 500kHz
+ // DR11 : SF9 @ 500kHz
+ // DR12 : SF8 @ 500kHz
+ // DR13 : SF7 @ 500kHz
+ // DR0 - DR3 (125kHz channels) available but much slower
+ tx_frequency = 915500000;
+ tx_datarate = mDot::DR13;
+ // 915 bands have no duty cycle restrictions, set tx power to max
+ tx_power = 20;
+ break;
+ }
+ update_peer_to_peer_config(pair_network_address, pair_network_session_key, pair_data_session_key, tx_frequency, tx_datarate, tx_power);
+ // TODO experiment if we need to save as I will need to save off previous settings to revert back
+// dot->saveConfig();
+ return cmdSuccess;
+}
void CommProtocolPeerBrute::setTx(bool isTx)
{
mIsTx = isTx;
@@ -103,8 +141,34 @@
}
CmdResult CommProtocolPeerBrute::clearPair()
{
- logError("Not implemented yet!!!");
- return cmdError;
+ CmdResult result;
+
+ // TODO generate possibly random channel for new pair
+ std::vector<uint8_t> key;
+ key.reserve(16);
+
+ result = genEncypKey(key, 8);
+ if (result != cmdSuccess) {
+ logError("Error generating network ID.");
+ return cmdError;
+ }
+ dot->setNetworkId(key);
+
+ result = genEncypKey(key, 16);
+ if (result != cmdSuccess) {
+ logError("Error generating network encryption keys.");
+ return cmdError;
+ }
+ dot->setNetworkKey(key);
+
+ result = genEncypKey(key, 16);
+ if (result != cmdSuccess) {
+ logError("Error generating data session encryption keys.");
+ return cmdError;
+ }
+ dot->setDataSessionKey(key);
+
+ return cmdSuccess;
}
// TX focused
@@ -126,8 +190,21 @@
if (!dot->getNetworkJoinStatus()) {
join_network();
}
- logError("Not implemented yet!!!");
- return cmdError;
+ // Request Message
+ std::vector<uint8_t> msg;
+ msg.reserve(16);
+ // Flag 2 Bytes
+ msg.push_back(0xFE);
+ msg.push_back(0x01);
+ // EUI 8 Bytes
+ std::vector<uint8_t> eui(dot->getDeviceId());
+ msg.insert(msg.end(), eui.begin(), eui.end());
+ // Reserved 6 Bytes
+ for (uint8_t i=0;i<6;i++) {
+ msg.push_back(0x00);
+ }
+ dot->send(msg); // Can just send once since the RX should be always listening
+ return cmdSuccess;
}
// RX focused
@@ -164,14 +241,88 @@
CmdResult CommProtocolPeerBrute::waitForPairing(float waitTime)
{
- logError("Not implemented yet!!!");
- return cmdError;
+ float t = 0.0;
+ bool msgPending;
+ do {
+ listen(msgPending);
+ t += TX_TIME/1000.0;
+ }
+ while (t < waitTime && !msgPending);
+
+ if (!msgPending) {
+ return cmdTimeout;
+ }
+ // TODO check request
+
+ wait(1.0); // Wait just a little so it is clear for requester that it is a pair message
+ return sendPairAccepted();
}
CmdResult CommProtocolPeerBrute::sendPairAccepted()
{
- logError("Not implemented yet!!!");
- return cmdError;
+ bool sendResult;
+ // Request Message
+ std::vector<uint8_t> *msg = new std::vector<uint8_t>;
+ msg->reserve(34);
+ // Flag
+ msg->push_back(0xFD);
+ msg->push_back(0x02);
+ logInfo("flag msg size %d", msg->size());
+ // EUI
+ std::vector<uint8_t> *eui = new std::vector<uint8_t>(dot->getDeviceId());
+ msg->insert(msg->end(),eui->begin(), eui->end());
+ delete eui;
+ logInfo("eui msg size %d", msg->size());
+
+ // Reserved for Freq
+ for(uint8_t i=0;i<4;i++) {
+ msg->push_back(0x00);
+ }
+ logInfo("freq msg size %d", msg->size());
+
+ // Network ID
+ std::vector<uint8_t> *networkId = new std::vector<uint8_t>(dot->getNetworkId());
+ msg->insert(msg->end(),networkId->begin(), networkId->end());
+ delete networkId;
+ logInfo("netid msg size %d", msg->size());
+
+ // Network key
+ std::vector<uint8_t> *networkKey = new std::vector<uint8_t>(dot->getNetworkKey());
+ msg->insert(msg->end(),networkKey->begin(), networkKey->end());
+ delete networkKey;
+ logInfo("netKey msg size %d", msg->size());
+
+ // Data session key
+ std::vector<uint8_t> *dataSessionKey = new std::vector<uint8_t>(dot->getDataSessionKey());
+ msg->insert(msg->end(),dataSessionKey->begin(), dataSessionKey->end());
+ delete dataSessionKey;
+
+ logInfo("msg size %d", msg->size());
+ // Only send once since requester should be listening always
+ sendResult = mDot::MDOT_OK == dot->send(*msg);
+ delete msg;
+ if (sendResult)
+ return cmdSuccess;
+ else
+ return cmdError;
+}
+
+CmdResult CommProtocolPeerBrute::waitForAccept(float waitTime)
+{
+ float t = 0.0;
+ bool msgPending = false;
+ do {
+ listen(msgPending);
+ t += TX_TIME/1000.0;
+ }
+ while (t < waitTime && !msgPending);
+
+ if (!msgPending) {
+ return cmdTimeout;
+ }
+ // TODO check request
+
+ return cmdSuccess;
}
// xDot Peer to Peer Specific
@@ -231,10 +382,13 @@
return cmdSuccess;
}
-CmdResult CommProtocolPeerBrute::genEncypKeys()
+CmdResult CommProtocolPeerBrute::genEncypKey(std::vector<uint8_t> &newKey, uint8_t keySize)
{
- logError("Not implemented yet!!!");
- return cmdError;
+ newKey.clear();
+ for (uint8_t i=0;i<keySize; i++){
+ newKey.push_back(dot->getRadioRandom());
+ }
+ return cmdSuccess;
}
// NvmProtocolObj
--- a/xDotBridge/src/main.cpp Mon Mar 06 15:16:58 2017 -0700
+++ b/xDotBridge/src/main.cpp Thu Mar 09 16:47:42 2017 -0700
@@ -49,10 +49,6 @@
logInfo("mbed-os library version: %d", MBED_LIBRARY_VERSION);
logInfo(" libxDot-mbed5 library ID: %s", dot->getId().c_str());
- // start from a well-known state
-// logInfo("defaulting Dot configuration");
-// dot->resetConfig();
-
// make sure library logging is turned on
dot->setLogLevel(mts::MTSLog::INFO_LEVEL);
@@ -120,6 +116,7 @@
unsigned int loopCnt = 0; // Just a quick temp varaible to keep track of loopNums
bool prevCCNormallyOpen;
+ PairBtnState pairBtnState;
/**
* Main Loop
*/
@@ -141,23 +138,56 @@
protocol->setTx(false);
}
// End sample and update
+ // Pair logic
+ if (pairBtnIntFlag) {
+ pairBtnState = PairBtnInterp::read(bbio);
+ if (protocol->isTx()) {
+ if (pairBtnState == pairBtnMediumPress) {
+ protocol->sampleDLC();
+ protocol->sendPairReq();
+ logInfo("Sent pair request. Waiting %f secs for accept.", TX_ACCEPT_WAIT_TIME);
+ result = protocol->waitForAccept(TX_ACCEPT_WAIT_TIME);
+ if (result == cmdSuccess) {
+ logInfo("Got accept");
+ }
+ else {
+ logInfo("Did not receive accept");
+ }
+ }
+ }
+ if (protocol->isRx()) {
+ if (pairBtnState == pairBtnMediumPress) {
+ protocol->sampleDLC();
+ bbio->ledOn();
+ logInfo("Waiting for pair request for %f seconds", RX_PAIR_WAIT_TIME);
+ result = protocol->waitForPairing(RX_PAIR_WAIT_TIME);
+ bbio->ledOff();
+ if (result == cmdSuccess) {
+ logInfo("Got pair request and responded");
+ }
+ else if (result == cmdTimeout) {
+ logInfo("Did not receive request");
+ }
+ else {
+ logInfo("Unknown pair error");
+ }
+ }
+ else if (pairBtnState == pairBtnLongPress) {
+ logInfo("Clearing pair values and generating new ones.");
+ protocol->clearPair();
+ // Maybe add Nvm save commands here
+ }
+ }
+ }
+ // Alert code
if (protocol->isTx()) {
logInfo("Loop #%d. CCFlag %d, CCAlertState %d, TamperFlag %d, PairBtnFlag %d",
loopCnt, ccIntFlag, bbio->isCCInAlert(), tamperIntFlag, pairBtnIntFlag);
// TODO add tamper
- if (pairBtnIntFlag) { // Wait up to 1 second for short button hit
- for (int i=0; i<10;i++) {
- if (bbio->isPairBtn() == false){ // Button released
- break;
- }
- wait(0.1);
- }
- }
if (ccIntFlag || // If contact closure in
bbio->isCCInAlert() || // If closure remains in effect
- (pairBtnIntFlag && (bbio->isPairBtn() == false))) { // If short pair btn hit
-
+ (pairBtnIntFlag && (pairBtnState == pairBtnShortPress))) {
ccIntFlag = false;
pairBtnIntFlag = false;
tamperIntFlag = false;
@@ -165,6 +195,7 @@
bbio->ledOn();
#endif
+ data.clear();
data.push_back((txSeqNum >> 8) & 0xFF);
data.push_back(txSeqNum & 0xFF);
std::string dataStr(data.begin(), data.end());
@@ -212,10 +243,8 @@
bbio->exitSleep();
}
- // TODO maybe a good place to put pairing logic
-
logInfo("\r\n================================");
- wait(1.0); // May want to remove
+// wait(1.0); // May want to remove
loopCnt++;
}
