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-29
- Branch:
- develop
- Revision:
- 39:022b327d6bf0
- Parent:
- 36:cd1077f40dbf
- Child:
- 43:55e7bb4d9b60
File content as of revision 39:022b327d6bf0:
/* _____ _ * / ____| | | * | (___ ___ _ __ ___ | |_ * \___ \ / _ \ | '_ \ / _ \ | __| * ____) | | __/ | | | | | __/ | |_ * |_____/ \___| |_| |_| \___| \__| * (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 static bool BackendSynchronized = true; static BoardOrientation BackendOrientation; static Ticker joinTicker; static Ticker nextTxTimer; static BoardSensorData sensorData; static BoardOrientation txOrientation; static bool NextTx = true; static uint32_t AppTxDutyCycle = APP_TX_DUTY_CYCLE_NORMAL; // Board Orientation enum EOrientationType { Orientation_Horizontal = 0, Orientation_Vertical, Orientation_Max, }; //orientation change count uint32_t orientationCount[Orientation_Max]; // orientation transmit count uint32_t orientationTxCount[Orientation_Max]; // Orientation comparison inline bool orientationIsEqual(BoardOrientation &a, BoardOrientation &b) { // For this application only vertical/horizontal state is tested return ( a.vertical == b.vertical ); } // Next orientation change to transmit inline uint8_t getNextTxOrientation(BoardOrientation &orientation) { static uint8_t txOrientationType = Orientation_Max; if (++txOrientationType >= Orientation_Max) txOrientationType = 0; for( ; txOrientationType < Orientation_Max; txOrientationType++) { if( orientationTxCount[txOrientationType] < orientationCount[txOrientationType] ) { orientationTxCount[txOrientationType]++; switch(txOrientationType) { case Orientation_Horizontal: orientation.vertical = false; break; case Orientation_Vertical: orientation.vertical = true; break; default: break; } break; } } return txOrientationType; } inline void incrementOrientation(BoardOrientation &orientation) { orientation.vertical ? orientationCount[Orientation_Vertical]++ : orientationCount[Orientation_Horizontal]++; } 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 = orientationIsEqual(BackendOrientation, txOrientation); } int main() { time_t lastTxT; BoardOrientation lastOrientation; memset(orientationCount, 0, sizeof(orientationCount)); memset(orientationTxCount, 0, sizeof(orientationTxCount)); // Initialize Board BoardInit(); // Join Network JoinNetwork(); // Start Board sensors CBoard::Start(); // Send initial state if( CBoard::ReadSensors(sensorData) == Board_Ok ) { lastOrientation = sensorData.orientation; incrementOrientation(lastOrientation); //Initialize backend state to opposite of current to trigger // backend synchronization if enabled BackendOrientation.vertical = !lastOrientation.vertical; } while( true ) { // Read sensors if( CBoard::ReadSensors(sensorData) == Board_Ok ) { if( !orientationIsEqual(sensorData.orientation, lastOrientation) ) { lastOrientation = sensorData.orientation; incrementOrientation(lastOrientation); } } // Determine next orientation to transmit after backend sync of the last transmitted orientation is finished if( ( BackendSynchronized == true ) && ( getNextTxOrientation(txOrientation) < Orientation_Max ) ) { BackendSynchronized = false; 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 if( !( NextTx = ( elapsedT >= APP_TX_DUTY_CYCLE_ALARM ) ) ) { 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 state == current orientation */ 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); } if(BackendSynchronized == true) CBoard::SetLED(1, false); } // 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; }