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-24
- Branch:
- develop
- Revision:
- 27:1753a44fa9ec
- Child:
- 28:4fd8a894a403
File content as of revision 27:1753a44fa9ec:
/***
* _____ _
* / ____| | |
* | (___ ___ _ __ ___ | |_
* \___ \ / _ \ | '_ \ / _ \ | __|
* ____) | | __/ | | | | | __/ | |_
* |_____/ \___| |_| |_| \___| \__|
* (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;
/******************************************************************************/
#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;
#define HORIZONTAL_ORIENTATION_VALUE 1 // transmitted value when device is horizontal
#define VERTICAL_ORIENTATION_VALUE 2 // transmitted value when device is vertical
// Transmit rate related variables
static bool NextTx = true;
static uint32_t AppTxDutyCycle = APP_TX_DUTY_CYCLE_NORMAL;
static Ticker joinTicker;
static Ticker nextTxTimer;
static BoardSensorData sensorData;
static BoardOrientation orientation;
// Backend service state (set to false if backend is not configured)
static bool BackendSynchronized = true;
BoardOrientation BackendOrientation;
// Forward
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;
}
BoardCheckForExit(true);
} while(ok == false);
joinTicker.attach(joinLedToggle,1);
// attempt to join the network
printf("joining network\r\n");
while ((mdot_ret = mDotPtr->joinNetwork()) != mDot::MDOT_OK)
{
BoardCheckForExit(true);
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();
appLED=1;
}
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(orientation.horizontal ? HORIZONTAL_ORIENTATION_VALUE : VERTICAL_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.horizontal = (frame[0] == HORIZONTAL_ORIENTATION_VALUE);
if( BackendOrientation.horizontal == orientation.horizontal )
BackendSynchronized = true;
}
int main()
{
time_t lastTxT;
// Initialize Board
BoardSetState(Board_init);
// Join Network
JoinNetwork();
// Start Board sensors
BoardSetState(Board_start);
// Initialize board orientation
BoardReadSensors(sensorData);
orientation = sensorData.orientation;
BackendSynchronized = false;
// Start transmit timer
nextTxTimer.attach_us(onNextTxTimerEvent, AppTxDutyCycle * 1e3);
while( !BoardCheckForExit(false) )
{
// Update device orientation
if( ( BackendSynchronized == true ) && ( sensorData.orientation.horizontal != orientation.horizontal ) )
{
BackendSynchronized = false;
orientation = sensorData.orientation;
// Get elapsed time since last transmit
time_t currT = time(NULL);
time_t elapsedT = ( currT - lastTxT ) * 1e3;
// Transmit now if elapsed time since last tx is greater than alarm mode dutycycle
if( elapsedT >= APP_TX_DUTY_CYCLE_ALARM )
{
nextTxTimer.detach();
NextTx = true;
}
// Otherwise wait until alarm dutycycle time has elapased
else
{
nextTxTimer.detach();
nextTxTimer.attach_us(onNextTxTimerEvent, (APP_TX_DUTY_CYCLE_ALARM - elapsedT)* 1e3);
}
AppTxDutyCycle = APP_TX_DUTY_CYCLE_ALARM;
}
if ( NextTx == true )
{
/* Backend synchronized flag set true when
* - backend not enabled
* - Downlink received containing last known orientation
*/
BackendSynchronized = !BackendEnabled;
// Transmit application frame
SendFrame();
lastTxT = time(NULL);
NextTx = false;
// Fast transmit rate while backend is out of sync with device state
if(BackendSynchronized == false)
{
if( ( AppTxDutyCycle != APP_TX_DUTY_CYCLE_ALARM ) )
{
AppTxDutyCycle = APP_TX_DUTY_CYCLE_ALARM;
nextTxTimer.detach();
nextTxTimer.attach_us(onNextTxTimerEvent, APP_TX_DUTY_CYCLE_ALARM * 1e3);
}
}
else if( AppTxDutyCycle != APP_TX_DUTY_CYCLE_NORMAL )
{
AppTxDutyCycle = APP_TX_DUTY_CYCLE_NORMAL;
nextTxTimer.detach();
nextTxTimer.attach_us(onNextTxTimerEvent, APP_TX_DUTY_CYCLE_NORMAL * 1e3);
}
}
// Delay before next sensor poll
osDelay(2000);
// Read sensors
BoardReadSensors(sensorData);
}
BoardSetState(Board_stop);
return 0;
}
/*
* 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()
{
appLED= !appLED;
}
void onNextTxTimerEvent( void )
{
NextTx = true;
}
