Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
- Committer:
- Jan Jongboom
- Date:
- 2017-01-03
- Revision:
- 3:ac5101a47080
- Parent:
- 2:ff17ce021cfb
- Child:
- 4:0fd5e5e121ea
File content as of revision 3:ac5101a47080:
#include "mbed.h"
#include "mDot.h"
#include "MTSLog.h"
#include <string>
#include <vector>
#include <algorithm>
#include "mbed.h"
#include "parse_keys.h"
#define BUILTIN_LED_ON 0
#define BUILTIN_LED_OFF 1
static const char APP_EUI[] = "BE7A000000000393";
static const char APP_KEY[] = "3FE0040E234141A08A583D5F508B5781";
static mDot* dot;
// so we have some state
static uint16_t counter = 0; // always persisted to non-volatile mem
static bool woke_from_interrupt = false;
static InterruptIn btn(PA_1); /* D6 */
static DigitalOut led(PC_13, BUILTIN_LED_OFF); /* D2 */
static void read_counter() {
char buffer[2];
bool res = dot->readUserFile("counter", &buffer, 2);
if (res) {
counter = (buffer[0] << 8) + buffer[1];
}
else {
counter = 0;
}
}
static void up_counter() {
logInfo("up counter");
read_counter();
counter++;
char buffer[2];
buffer[0] = counter >> 8 & 0xff;
buffer[1] = counter & 0xff;
logInfo("new counter value is: %d", counter);
dot->saveUserFile("counter", &buffer, 2);
}
static void btn_rise() {
woke_from_interrupt = true; // will be woken by STM32
}
static bool send_data(void) {
int32_t ret;
std::vector<uint8_t> data;
data.push_back(counter >> 8 & 0xff);
data.push_back(counter & 0xff);
logInfo("sending %d bytes", data.size());
if ((ret = dot->send(data)) != mDot::MDOT_OK) {
logError("failed to send %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
return false;
} else {
logInfo("successfully sent data to gateway");
std::vector<uint8_t> recv_data;
if ((ret = dot->recv(recv_data)) != mDot::MDOT_OK) {
logError("failed to recv %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
return true; // sending succeeded, just recv failed
}
if (recv_data.size() > 0) {
printf("[INFO] received %d bytes:", recv_data.size());
for (size_t ix = 0; ix < recv_data.size(); ix++) {
printf(" %02x", recv_data[ix]);
}
printf("\r\n");
if (recv_data[0] == 1) {
led = BUILTIN_LED_ON;
}
else {
led = BUILTIN_LED_OFF;
}
}
return true;
}
}
static void wakeUpCallback() {
logInfo("woke up, fromInterrupt=%d", woke_from_interrupt);
bool wfi = woke_from_interrupt;
// if we were woken up by RTC_ALARM, first up the counter
if (wfi) {
// reset the interrupt var
woke_from_interrupt = false;
up_counter();
}
bool sent = send_data();
// not sent? try again in 5 minutes...
if (!sent) {
uint32_t sleep_time = 5 * 60;
// if woke from button press, check duty cycle first...
if (wfi) {
// hmm.. something went wrong. Probably duty cycle, see next Tx frame
// get the next transmission frame (in whole seconds)
sleep_time = ceil(static_cast<float>(dot->getNextTxMs()) / 1000.0f);
// Tx window open, but no success? Try again in 30s.
if (sleep_time == 0) sleep_time = 30;
}
logInfo("Going back to sleep (RTC_ALARM), time=%d", sleep_time);
dot->sleep(sleep_time, mDot::RTC_ALARM, false);
}
else {
logInfo("Going back to sleep (INTERRUPT)");
// go back to sleep (wait for an interrupt to happen)
dot->sleep(0, mDot::INTERRUPT, false);
}
}
int main() {
int32_t ret;
printf("Entering main()\r\n");
btn.rise(&btn_rise);
// get a mDot handle
dot = mDot::getInstance();
dot->setLogLevel(mts::MTSLog::DEBUG_LEVEL);
// print library version information
logInfo("version: %s", dot->getId().c_str());
std::vector<uint8_t> devEui = dot->getDeviceId();
logInfo("device eui: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
devEui[0], devEui[1], devEui[2], devEui[3], devEui[4], devEui[5], devEui[6], devEui[7]);
//*******************************************
// configuration
//*******************************************
// reset to default config so we know what state we're in
dot->resetConfig();
logInfo("frequencyBand: %d", dot->getFrequencyBand());
// set up the mDot with our network information: frequency sub band, network name, and network password
// these can all be saved in NVM so they don't need to be set every time - see mDot::saveConfig()
logInfo("setting public network");
if ((ret = dot->setPublicNetwork(true)) != mDot::MDOT_OK) {
logError("failed to set public network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
}
logInfo("setting tx power to 20");
if ((ret = dot->setTxPower(18)) != mDot::MDOT_OK) {
logError("failed to set tx power %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
}
// set up the network keys
ParseKeys::initializeOta(dot, APP_EUI, APP_KEY);
// a higher spreading factor allows for longer range but lower throughput
// in the 915 (US) frequency band, spreading factors 7 - 10 are available
// in the 868 (EU) frequency band, spreading factors 7 - 12 are available
logInfo("setting TX spreading factor");
if ((ret = dot->setTxDataRate(mDot::SF_9)) != mDot::MDOT_OK) {
logError("failed to set TX datarate %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
}
// request receive confirmation of packets from the gateway
logInfo("enabling ACKs");
if ((ret = dot->setAck(1)) != mDot::MDOT_OK) {
logError("failed to enable ACKs %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
}
logInfo("enabling ADR");
if ((ret = dot->setAdr(1)) != mDot::MDOT_OK) {
logError("failed to enable ADR %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
}
// save this configuration to the mDot's NVM
logInfo("saving config");
if (! dot->saveConfig()) {
logError("failed to save configuration");
}
// OTA JOIN sequence, remove when using personalized mode
logInfo("joining network");
if ((ret = dot->joinNetwork()) != mDot::MDOT_OK ) {
logError("failed to join network %d:%s", ret, mDot::getReturnCodeString(ret).c_str());
return false;
}
logInfo("joined network successfully");
//*******************************************
// end of configuration
//*******************************************
read_counter();
dot->setWakeupCallback(&wakeUpCallback);
dot->sleep(0, mDot::INTERRUPT, false);
while (true) {
wait_ms(1000);
}
}