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 canuck lehead

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001  /*       _____                         _
00002  *      / ____|                       | |  
00003  *     | (___     ___   _ __     ___  | |_ 
00004  *      \___ \   / _ \ | '_ \   / _ \ | __|
00005  *      ____) | |  __/ | | | | |  __/ | |_ 
00006  *     |_____/   \___| |_| |_|  \___|  \__|
00007  *         (C) 2016 Senet, Inc                                
00008  *                                         
00009  */
00010 
00011 #include "board.h"
00012 #include "senet_packet.h"
00013 
00014 
00015 /******************************************************************************
00016  * LoRaWAN Configuration                                                      *
00017  ******************************************************************************/
00018  // Senet Developer Portal Application EUI
00019 static uint8_t APP_EUI[8]  = {0x00,0x25,0x0C,0x00,0x00,0x01,0x00,0x01};
00020 
00021 // Get Application Key from Senet Developer Portal Device Edit page
00022 static uint8_t APP_KEY[16] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
00023 
00024 #define DATARATE            mDot::DR0
00025 #define TXPOWER             20
00026 #define JOIN_RETRIES        1
00027 
00028 static std::vector<uint8_t> appEUI(APP_EUI,APP_EUI+sizeof(APP_EUI)/sizeof(uint8_t));
00029 static std::vector<uint8_t> appKey(APP_KEY,APP_KEY+sizeof(APP_KEY)/sizeof(uint8_t));
00030 static uint8_t              fsb     = 0;
00031 static bool                 adrOn   = true;
00032 /******************************************************************************/
00033 
00034 
00035 /******************************************************************************
00036  * Application Configuration                                                      *
00037  ******************************************************************************/
00038 #define APP_TX_DUTY_CYCLE_NORMAL 300000 // 5 min
00039 #define APP_TX_DUTY_CYCLE_ALARM  15000  // 15 s
00040 
00041 // Backend configured state. Set true to enable alarm rate transmits until backend response
00042 static bool  BackendEnabled = false;
00043 /******************************************************************************/
00044 
00045 // Transmitted orientation values
00046 #define HORIZONTAL_ORIENTATION_VALUE 1 // transmitted value when device is horizontal
00047 #define VERTICAL_ORIENTATION_VALUE   2 // transmitted value when device is vertical
00048 
00049 
00050 // Set to true when backend is synchronized
00051 static bool             BackendSynchronized   = true;
00052 // Set to true to force backend resync
00053 static bool             OrientationInit       = true;
00054 static bool             DisplayBackendState   = true;
00055 static BoardOrientation BackendOrientation;
00056 static Ticker           joinTicker;
00057 static Ticker           nextTxTimer;
00058 static BoardSensorData  sensorData;
00059 static BoardOrientation txOrientation;
00060 static BoardOrientation lastOrientation;
00061 static bool             NextTx  = true;
00062 static uint32_t         AppTxDutyCycle = APP_TX_DUTY_CYCLE_NORMAL;
00063 static uint32_t         orientationChangeCount = 0;
00064 
00065 // Orientation comparison
00066 inline bool orientationIsEqual(BoardOrientation &a, BoardOrientation &b)
00067 {
00068     // For this application only vertical/horizontal state is tested
00069     return ( a.vertical == b.vertical );
00070 }
00071 
00072 static void log_error(mDot* dot, const char* msg, int32_t retval);
00073 static void joinLedToggle();
00074 static void onNextTxTimerEvent();
00075 static void ReceiveData(std::vector<uint8_t> frame);
00076 
00077 
00078 void JoinNetwork()
00079 {
00080     bool    ok;
00081     int32_t mdot_ret;
00082 
00083     do{
00084         ok = true;
00085 
00086         // reset to default config so we know what state we're in
00087         mDotPtr->resetConfig();
00088         mDotPtr->setLogLevel(6);
00089         mDotPtr->setAntennaGain(-3);
00090 
00091         // Read node ID
00092         std::vector<uint8_t> mdot_EUI;
00093         mdot_EUI = mDotPtr->getDeviceId();
00094         printf("mDot EUI = ");
00095 
00096         for (uint8_t i=0; i<mdot_EUI.size(); i++)
00097             printf("%02x ", mdot_EUI[i]);
00098         printf("\n\r");
00099 
00100       /*
00101        * This call sets up private or public mode on the MTDOT. Set the function to true if
00102        * connecting to a public network
00103        */
00104         printf("setting Public Network Mode\r\n");
00105         if ((mdot_ret = mDotPtr->setPublicNetwork(true)) != mDot::MDOT_OK)
00106             log_error(mDotPtr, "failed to set Public Network Mode", mdot_ret);
00107 
00108         mDotPtr->setTxDataRate(DATARATE);
00109         mDotPtr->setTxPower(TXPOWER);
00110         mDotPtr->setJoinRetries(JOIN_RETRIES);
00111         mDotPtr->setJoinMode(mDot::OTA);
00112 
00113       /*
00114        * Frequency sub-band is valid for NAM only and for Private networks should be set to a value
00115        * between 1-8 that matches the the LoRa gateway setting. Public networks use sub-band 0 only.
00116        * This function can be commented out for EU networks
00117        */
00118         printf("setting frequency sub band\r\n");
00119         if ((mdot_ret = mDotPtr->setFrequencySubBand(fsb)) != mDot::MDOT_OK) {
00120             log_error(mDotPtr, "failed to set frequency sub band", mdot_ret);
00121             ok = false;
00122         }
00123 
00124         printf("setting ADR\r\n");
00125         if ((mdot_ret = mDotPtr->setAdr(adrOn)) != mDot::MDOT_OK) {
00126             log_error(mDotPtr, "failed to set ADR", mdot_ret);
00127             ok = false;
00128         }
00129 
00130        /*
00131         * setNetworkName is used for private networks.
00132         * Use setNetworkID(AppID) for public networks
00133         */
00134         printf("setting network name\r\n");
00135         if ((mdot_ret = mDotPtr->setNetworkId(appEUI)) != mDot::MDOT_OK) {
00136             log_error(mDotPtr, "failed to set network name", mdot_ret);
00137             ok = false;
00138         }
00139 
00140        /*
00141         * setNetworkPassphrase is used for private networks
00142         * Use setNetworkKey for public networks
00143         */
00144         printf("setting network key\r\n");
00145         if ((mdot_ret = mDotPtr->setNetworkKey(appKey)) != mDot::MDOT_OK) {
00146             log_error(mDotPtr, "failed to set network password", mdot_ret);
00147             ok = false;
00148         }
00149 
00150     } while(ok == false);
00151 
00152     joinTicker.attach(joinLedToggle, 5);
00153 
00154     // attempt to join the network
00155     printf("joining network\r\n");
00156     while ((mdot_ret = mDotPtr->joinNetwork()) != mDot::MDOT_OK)
00157     {
00158         log_error(mDotPtr,"failed to join network:", mdot_ret);
00159         uint32_t delay_s = (mDotPtr->getNextTxMs() / 1000) + 1;
00160         wait(delay_s);
00161     }
00162 
00163     printf("network joined\r\n");
00164 
00165     joinTicker.detach();
00166     CBoard::SetLED(1, false);
00167 }
00168 
00169 void SendFrame()
00170 {
00171     std::vector<uint8_t> frame;
00172     int32_t              mdot_ret;
00173     uint8_t              buffer[20];
00174     SensorPacket         packet(buffer, sizeof(buffer));
00175 
00176     // Sensor packet type serialized to the frame buffer
00177     packet.setPrimarySensor(txOrientation.vertical ? VERTICAL_ORIENTATION_VALUE : HORIZONTAL_ORIENTATION_VALUE);
00178     packet.setTemperature(sensorData.temperature);
00179     packet.setPressure(sensorData.pressure);
00180     packet.serialize();
00181 
00182     frame.assign(packet.payload(), packet.payload() + packet.length());
00183     if ((mdot_ret = mDotPtr->send(frame)) != mDot::MDOT_OK)
00184     {
00185         log_error(mDotPtr, "failed to send", mdot_ret);
00186     }
00187     else
00188     {
00189         printf("successfully sent data\r\n");
00190         frame.clear();
00191         if ((mdot_ret = mDotPtr->recv(frame)) == mDot::MDOT_OK)
00192         {
00193             printf("recv data: ");
00194             for(uint32_t i = 0;i < frame.size();i++)
00195                 printf("%02X",frame[i]);
00196             printf("\r\n");
00197 
00198             ReceiveData(frame);
00199         }
00200     }
00201 }
00202 
00203 void ReceiveData(std::vector<uint8_t> frame)
00204 {
00205     BackendOrientation.vertical = (frame[0] == VERTICAL_ORIENTATION_VALUE);
00206     BackendSynchronized = !BackendEnabled || orientationIsEqual(BackendOrientation, txOrientation);
00207 
00208     // Blink LED
00209     bool ledState = false;
00210     for(uint8_t i=0; i<3; i++)
00211     {
00212         CBoard::SetLED(1, ledState);
00213         ledState = !ledState;
00214         osDelay(500);
00215     }
00216 }
00217 
00218 static void onButtonPress(uint8_t buttonNum)
00219 {
00220     DisplayBackendState = true;
00221 
00222     if(buttonNum == 1)
00223     {
00224         OrientationInit = true;
00225         BackendEnabled  = !BackendEnabled;
00226 
00227         // Start next transmit immediately
00228         if( BackendEnabled && !NextTx )
00229         {
00230             nextTxTimer.detach();
00231             nextTxTimer.attach_us(onNextTxTimerEvent, 1000);
00232         }
00233     }
00234 }
00235 
00236 int main()
00237 {
00238     time_t lastTxT;
00239 
00240     // Initialize Board
00241     BoardInit();
00242 
00243     // Register pushbutton handler
00244     CBoard::SetButtonCallback(onButtonPress);
00245 
00246     // Join Network
00247     JoinNetwork();
00248 
00249     // Start Board sensors
00250     CBoard::Start();
00251 
00252     while( true )
00253     {
00254         // Read sensors
00255         if( CBoard::ReadSensors(sensorData) == Board_Ok )
00256         {
00257             if( !orientationIsEqual(sensorData.orientation, lastOrientation) || OrientationInit)
00258             {
00259                 orientationChangeCount++;
00260                 lastOrientation = sensorData.orientation;
00261             }
00262         }
00263 
00264         // Initialize orientation state
00265         if( OrientationInit )
00266         {
00267             OrientationInit             = false;
00268             orientationChangeCount      = 1;
00269             // Set tx orientation to opposite of current as it will be toggled  before transmit
00270             txOrientation.vertical      = !lastOrientation.vertical;
00271             // Set backend to be out of sync
00272             BackendOrientation.vertical =  txOrientation.vertical;
00273         }
00274 
00275         // Display backend enabled state
00276         if(DisplayBackendState)
00277         {
00278             DisplayBackendState = false;
00279 
00280             uint8_t ledToggleCount = BackendEnabled ? 3 : 2;
00281             CBoard::SetLED(1, false);
00282             // blink LED to indicate backend state
00283             for(uint32_t i=0; i < ledToggleCount*2; i++)
00284             {
00285                 osDelay(1000);
00286                 CBoard::ToggleLED(1);
00287             }
00288 
00289             // Set LED to reflect Backend synchronized state
00290             CBoard::SetLED(1, BackendOrientation.vertical != txOrientation.vertical);
00291         }
00292 
00293         // Get next orientation change to transmit after backend sync of the last transmitted orientation is finished
00294         if( ( BackendSynchronized == true ) && ( orientationChangeCount != 0 ) )
00295         {
00296             BackendSynchronized = false;
00297 
00298             // Set transmit orientation
00299             txOrientation.vertical = !txOrientation.vertical;
00300             orientationChangeCount--;
00301 
00302             // Turn on out-of-sync LED
00303             CBoard::SetLED(1, true);
00304 
00305             // Get elapsed time since last transmit
00306             time_t currT    = time(NULL);
00307             time_t elapsedT = ( currT - lastTxT ) * 1e3;
00308 
00309             // Stop transmit timer
00310             AppTxDutyCycle = 0;
00311             nextTxTimer.detach();
00312 
00313             // Wait to transmit until elapsed time is greater than alarm mode dutycycle
00314             NextTx = ( elapsedT >= APP_TX_DUTY_CYCLE_ALARM );
00315             if( !NextTx )
00316             {
00317                 AppTxDutyCycle = APP_TX_DUTY_CYCLE_ALARM - elapsedT;
00318                 nextTxTimer.attach_us(onNextTxTimerEvent, AppTxDutyCycle * 1e3);
00319             }
00320         }
00321 
00322         if ( NextTx == true )
00323         {
00324             NextTx = false;
00325 
00326             /*  Backend synchronized flag set true when
00327              *    o  Backend not enabled
00328              *    o  Backend in sync
00329              */
00330             BackendSynchronized = !BackendEnabled || orientationIsEqual(BackendOrientation, txOrientation);
00331 
00332             // Transmit application frame
00333             SendFrame();
00334 
00335             // Update transmit timestamp
00336             lastTxT = time(NULL);
00337 
00338             // Set next transmit time
00339             if( BackendSynchronized == false )
00340             {
00341                 if( ( AppTxDutyCycle != APP_TX_DUTY_CYCLE_ALARM ) )
00342                 {
00343                     AppTxDutyCycle = APP_TX_DUTY_CYCLE_ALARM;
00344                     nextTxTimer.detach();
00345                     nextTxTimer.attach_us(onNextTxTimerEvent, AppTxDutyCycle * 1e3);
00346                 }
00347             }
00348             else if( AppTxDutyCycle != APP_TX_DUTY_CYCLE_NORMAL )
00349             {
00350                 AppTxDutyCycle = APP_TX_DUTY_CYCLE_NORMAL;
00351                 nextTxTimer.detach();
00352                 nextTxTimer.attach_us(onNextTxTimerEvent, AppTxDutyCycle * 1e3);
00353             }
00354 
00355             // Set LED to reflect Backend synchronized state
00356             CBoard::SetLED(1, BackendOrientation.vertical != txOrientation.vertical);
00357         }
00358 
00359         // Delay before next sensor poll
00360         osDelay(2000);
00361     }
00362 }
00363 
00364 
00365 /*
00366  *  prints of mDot error
00367  */
00368 void log_error(mDot* dot, const char* msg, int32_t retval)
00369 {
00370     printf("%s - %ld:%s, %s\r\n", msg, retval, mDot::getReturnCodeString(retval).c_str(), dot->getLastError().c_str());
00371 }
00372 
00373 void joinLedToggle() { CBoard::ToggleLED(1); }
00374 
00375 void onNextTxTimerEvent( void ) { NextTx = true; }