mdot UDK & STMicro MEMS Shield Sensor packet example
Dependencies: libmDot-mbed5 DOGS102 ISL29011 MMA845x MPL3115A2 NCP5623B X_NUCLEO_IKS01A1 Senet_Packet
Fork of MTDOT-UDKDemo_Senet by
main.cpp
- Committer:
- Shaun Nelson
- Date:
- 2017-08-30
- Revision:
- 43:55e7bb4d9b60
- Parent:
- 39:022b327d6bf0
File content as of revision 43:55e7bb4d9b60:
/* _____ _ * / ____| | | * | (___ ___ _ __ ___ | |_ * \___ \ / _ \ | '_ \ / _ \ | __| * ____) | | __/ | | | | | __/ | |_ * |_____/ \___| |_| |_| \___| \__| * (C) 2016 Senet, Inc * */ #include "board.h" #include "senet_packet.h" /****************************************************************************** * LoRaWAN Configuration * ******************************************************************************/ // Senet Developer Portal Application EUI static uint8_t APP_EUI[8] = {0x00,0x25,0x0C,0x00,0x00,0x01,0x00,0x01}; // Get Application Key from Senet Developer Portal Device Edit page static uint8_t APP_KEY[16] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; #define DATARATE mDot::DR0 #define TXPOWER 20 #define JOIN_RETRIES 1 static std::vector<uint8_t> appEUI(APP_EUI,APP_EUI+sizeof(APP_EUI)/sizeof(uint8_t)); static std::vector<uint8_t> appKey(APP_KEY,APP_KEY+sizeof(APP_KEY)/sizeof(uint8_t)); static uint8_t fsb = 0; static bool adrOn = true; /******************************************************************************/ /****************************************************************************** * Application Configuration * ******************************************************************************/ #define APP_TX_DUTY_CYCLE_NORMAL 300000 // 5 min #define APP_TX_DUTY_CYCLE_ALARM 15000 // 15 s // Backend configured state. Set true to enable alarm rate transmits until backend response static bool BackendEnabled = false; /******************************************************************************/ // Transmitted orientation values #define HORIZONTAL_ORIENTATION_VALUE 1 // transmitted value when device is horizontal #define VERTICAL_ORIENTATION_VALUE 2 // transmitted value when device is vertical // Set to true when backend is synchronized static bool BackendSynchronized = true; // Set to true to force backend resync static bool OrientationInit = true; static bool DisplayBackendState = true; static BoardOrientation BackendOrientation; static Ticker joinTicker; static Ticker nextTxTimer; static BoardSensorData sensorData; static BoardOrientation txOrientation; static BoardOrientation lastOrientation; static bool NextTx = true; static uint32_t AppTxDutyCycle = APP_TX_DUTY_CYCLE_NORMAL; static uint32_t orientationChangeCount = 0; // Orientation comparison inline bool orientationIsEqual(BoardOrientation &a, BoardOrientation &b) { // For this application only vertical/horizontal state is tested return ( a.vertical == b.vertical ); } static void log_error(mDot* dot, const char* msg, int32_t retval); static void joinLedToggle(); static void onNextTxTimerEvent(); static void ReceiveData(std::vector<uint8_t> frame); void JoinNetwork() { bool ok; int32_t mdot_ret; do{ ok = true; // reset to default config so we know what state we're in mDotPtr->resetConfig(); mDotPtr->setLogLevel(6); mDotPtr->setAntennaGain(-3); // Read node ID std::vector<uint8_t> mdot_EUI; mdot_EUI = mDotPtr->getDeviceId(); printf("mDot EUI = "); for (uint8_t i=0; i<mdot_EUI.size(); i++) printf("%02x ", mdot_EUI[i]); printf("\n\r"); /* * This call sets up private or public mode on the MTDOT. Set the function to true if * connecting to a public network */ printf("setting Public Network Mode\r\n"); if ((mdot_ret = mDotPtr->setPublicNetwork(true)) != mDot::MDOT_OK) log_error(mDotPtr, "failed to set Public Network Mode", mdot_ret); mDotPtr->setTxDataRate(DATARATE); mDotPtr->setTxPower(TXPOWER); mDotPtr->setJoinRetries(JOIN_RETRIES); mDotPtr->setJoinMode(mDot::OTA); /* * Frequency sub-band is valid for NAM only and for Private networks should be set to a value * between 1-8 that matches the the LoRa gateway setting. Public networks use sub-band 0 only. * This function can be commented out for EU networks */ printf("setting frequency sub band\r\n"); if ((mdot_ret = mDotPtr->setFrequencySubBand(fsb)) != mDot::MDOT_OK) { log_error(mDotPtr, "failed to set frequency sub band", mdot_ret); ok = false; } printf("setting ADR\r\n"); if ((mdot_ret = mDotPtr->setAdr(adrOn)) != mDot::MDOT_OK) { log_error(mDotPtr, "failed to set ADR", mdot_ret); ok = false; } /* * setNetworkName is used for private networks. * Use setNetworkID(AppID) for public networks */ printf("setting network name\r\n"); if ((mdot_ret = mDotPtr->setNetworkId(appEUI)) != mDot::MDOT_OK) { log_error(mDotPtr, "failed to set network name", mdot_ret); ok = false; } /* * setNetworkPassphrase is used for private networks * Use setNetworkKey for public networks */ printf("setting network key\r\n"); if ((mdot_ret = mDotPtr->setNetworkKey(appKey)) != mDot::MDOT_OK) { log_error(mDotPtr, "failed to set network password", mdot_ret); ok = false; } } while(ok == false); joinTicker.attach(joinLedToggle, 5); // attempt to join the network printf("joining network\r\n"); while ((mdot_ret = mDotPtr->joinNetwork()) != mDot::MDOT_OK) { log_error(mDotPtr,"failed to join network:", mdot_ret); uint32_t delay_s = (mDotPtr->getNextTxMs() / 1000) + 1; wait(delay_s); } printf("network joined\r\n"); joinTicker.detach(); CBoard::SetLED(1, false); } void SendFrame() { std::vector<uint8_t> frame; int32_t mdot_ret; uint8_t buffer[20]; SensorPacket packet(buffer, sizeof(buffer)); // Sensor packet type serialized to the frame buffer packet.setPrimarySensor(txOrientation.vertical ? VERTICAL_ORIENTATION_VALUE : HORIZONTAL_ORIENTATION_VALUE); packet.setTemperature(sensorData.temperature); packet.setPressure(sensorData.pressure); packet.serialize(); frame.assign(packet.payload(), packet.payload() + packet.length()); if ((mdot_ret = mDotPtr->send(frame)) != mDot::MDOT_OK) { log_error(mDotPtr, "failed to send", mdot_ret); } else { printf("successfully sent data\r\n"); frame.clear(); if ((mdot_ret = mDotPtr->recv(frame)) == mDot::MDOT_OK) { printf("recv data: "); for(uint32_t i = 0;i < frame.size();i++) printf("%02X",frame[i]); printf("\r\n"); ReceiveData(frame); } } } void ReceiveData(std::vector<uint8_t> frame) { BackendOrientation.vertical = (frame[0] == VERTICAL_ORIENTATION_VALUE); BackendSynchronized = !BackendEnabled || orientationIsEqual(BackendOrientation, txOrientation); // Blink LED bool ledState = false; for(uint8_t i=0; i<3; i++) { CBoard::SetLED(1, ledState); ledState = !ledState; osDelay(500); } } static void onButtonPress(uint8_t buttonNum) { DisplayBackendState = true; if(buttonNum == 1) { OrientationInit = true; BackendEnabled = !BackendEnabled; // Start next transmit immediately if( BackendEnabled && !NextTx ) { nextTxTimer.detach(); nextTxTimer.attach_us(onNextTxTimerEvent, 1000); } } } int main() { time_t lastTxT; // Initialize Board BoardInit(); // Register pushbutton handler CBoard::SetButtonCallback(onButtonPress); // Join Network JoinNetwork(); // Start Board sensors CBoard::Start(); while( true ) { // Read sensors if( CBoard::ReadSensors(sensorData) == Board_Ok ) { if( !orientationIsEqual(sensorData.orientation, lastOrientation) || OrientationInit) { orientationChangeCount++; lastOrientation = sensorData.orientation; } } // Initialize orientation state if( OrientationInit ) { OrientationInit = false; orientationChangeCount = 1; // Set tx orientation to opposite of current as it will be toggled before transmit txOrientation.vertical = !lastOrientation.vertical; // Set backend to be out of sync BackendOrientation.vertical = txOrientation.vertical; } // Display backend enabled state if(DisplayBackendState) { DisplayBackendState = false; uint8_t ledToggleCount = BackendEnabled ? 3 : 2; CBoard::SetLED(1, false); // blink LED to indicate backend state for(uint32_t i=0; i < ledToggleCount*2; i++) { osDelay(1000); CBoard::ToggleLED(1); } // Set LED to reflect Backend synchronized state CBoard::SetLED(1, BackendOrientation.vertical != txOrientation.vertical); } // Get next orientation change to transmit after backend sync of the last transmitted orientation is finished if( ( BackendSynchronized == true ) && ( orientationChangeCount != 0 ) ) { BackendSynchronized = false; // Set transmit orientation txOrientation.vertical = !txOrientation.vertical; orientationChangeCount--; // Turn on out-of-sync LED CBoard::SetLED(1, true); // Get elapsed time since last transmit time_t currT = time(NULL); time_t elapsedT = ( currT - lastTxT ) * 1e3; // Stop transmit timer AppTxDutyCycle = 0; nextTxTimer.detach(); // Wait to transmit until elapsed time is greater than alarm mode dutycycle NextTx = ( elapsedT >= APP_TX_DUTY_CYCLE_ALARM ); if( !NextTx ) { AppTxDutyCycle = APP_TX_DUTY_CYCLE_ALARM - elapsedT; nextTxTimer.attach_us(onNextTxTimerEvent, AppTxDutyCycle * 1e3); } } if ( NextTx == true ) { NextTx = false; /* Backend synchronized flag set true when * o Backend not enabled * o Backend in sync */ BackendSynchronized = !BackendEnabled || orientationIsEqual(BackendOrientation, txOrientation); // Transmit application frame SendFrame(); // Update transmit timestamp lastTxT = time(NULL); // Set next transmit time if( BackendSynchronized == false ) { if( ( AppTxDutyCycle != APP_TX_DUTY_CYCLE_ALARM ) ) { AppTxDutyCycle = APP_TX_DUTY_CYCLE_ALARM; nextTxTimer.detach(); nextTxTimer.attach_us(onNextTxTimerEvent, AppTxDutyCycle * 1e3); } } else if( AppTxDutyCycle != APP_TX_DUTY_CYCLE_NORMAL ) { AppTxDutyCycle = APP_TX_DUTY_CYCLE_NORMAL; nextTxTimer.detach(); nextTxTimer.attach_us(onNextTxTimerEvent, AppTxDutyCycle * 1e3); } // Set LED to reflect Backend synchronized state CBoard::SetLED(1, BackendOrientation.vertical != txOrientation.vertical); } // Delay before next sensor poll osDelay(2000); } } /* * prints of mDot error */ void log_error(mDot* dot, const char* msg, int32_t retval) { printf("%s - %ld:%s, %s\r\n", msg, retval, mDot::getReturnCodeString(retval).c_str(), dot->getLastError().c_str()); } void joinLedToggle() { CBoard::ToggleLED(1); } void onNextTxTimerEvent( void ) { NextTx = true; }