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

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;
}