BigW Consortium Gitlab

Commit 5b910dba by David Frey

Create wakeupAndTweet tutorial app

This app will be presented at the tutorial session at Sierra Wireless Developer Day 2016.
parent cc4ccf2d
version: 1.0
sandboxed: true
start: auto
executables:
{
wakeupAndTweet = (wakeupAndTweet)
}
processes:
{
envVars:
{
// Enable output of LE_DEBUG() messages
LE_LOG_LEVEL = DEBUG
}
run:
{
(wakeupAndTweet)
}
// During development it is convenient to stop the app if a process fails. In production, it
// usually makes more sense too use the "restart" option to restart the process that failed or
// "restartApp" to restart all processes in the app.
faultAction: stopApp
}
bindings:
{
wakeupAndTweet.wakeupAndTweet.twitter -> socialService.twitter
wakeupAndTweet.wakeupAndTweet.le_ulpm -> powerMgr.le_ulpm
wakeupAndTweet.wakeupAndTweet.le_bootReason -> powerMgr.le_bootReason
wakeupAndTweet.wakeupAndTweet.le_adc -> modemService.le_adc
wakeupAndTweet.wakeupAndTweet.le_data -> dataConnectionService.le_data
}
\ No newline at end of file
requires:
{
api:
{
${MANGOH_ROOT}/apps/SocialService/interfaces/twitter.api
le_ulpm.api
le_bootReason.api
le_adc.api
le_data.api
}
}
sources:
{
src/main.cpp
src/connectAndRun.cpp
}
cxxflags:
{
-std=c++11
}
\ No newline at end of file
//--------------------------------------------------------------------------------------------------
/**
* This module provides the ability to execute a function upon successfully establishing a data
* connection.
*
* Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.
*/
//--------------------------------------------------------------------------------------------------
#include "connectAndRun.h"
#include "interfaces.h"
#include "legato.h"
//--------------------------------------------------------------------------------------------------
/**
* The context data of a connectAndRun call.
*/
//--------------------------------------------------------------------------------------------------
struct ConnectAndRunRecord
{
le_data_ConnectionStateHandlerRef_t connectionStateHandlerRef;
le_data_RequestObjRef_t dataConnection;
std::function<void()> onConnect;
};
//--------------------------------------------------------------------------------------------------
/**
* Handles data connection state events. The onConnect function stored within the
* ConnectAndRunRecord is executed when a connection is established.
*/
//--------------------------------------------------------------------------------------------------
static void DataConnectionStateHandler
(
const char* interfaceName,
bool isConnected,
void* contextPtr
)
{
struct ConnectAndRunRecord* record = static_cast<struct ConnectAndRunRecord*>(contextPtr);
LE_DEBUG("Data connection state event received. connected=%d", isConnected);
if (isConnected)
{
record->onConnect();
// Deregister the connection state handler and release the data connection now that the
// onConnect action has been completed.
le_data_RemoveConnectionStateHandler(record->connectionStateHandlerRef);
le_data_Release(record->dataConnection);
delete record;
}
}
//--------------------------------------------------------------------------------------------------
/**
* Establish an internet connection using the data connection service and then run the provided
* function.
*
* @return
* - LE_OK if the data connection is attempting to be established
* - LE_COMM_ERROR if the data connection request was rejected
*/
//--------------------------------------------------------------------------------------------------
le_result_t wakeupAndTweet_ConnectAndRun
(
std::function<void()> onConnect
)
{
// This record will be deleted by DataConnectionStateHandler once the connection is established
// and onConnect has been run.
auto record = new ConnectAndRunRecord();
record->onConnect = onConnect;
record->connectionStateHandlerRef =
le_data_AddConnectionStateHandler(DataConnectionStateHandler, record);
record->dataConnection = le_data_Request();
if (record->dataConnection == NULL)
{
LE_WARN("Couldn't establish a data connection");
le_data_RemoveConnectionStateHandler(record->connectionStateHandlerRef);
delete record;
return LE_COMM_ERROR;
}
return LE_OK;
}
//--------------------------------------------------------------------------------------------------
/**
* This module provides the ability to execute a function upon successfully establishing a data
* connection.
*
* Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.
*/
//--------------------------------------------------------------------------------------------------
#ifndef CONNECT_AND_RUN_H
#define CONNECT_AND_RUN_H
#include <functional>
#include "legato.h"
//--------------------------------------------------------------------------------------------------
/**
* Establish an internet connection using the data connection service and then run the provided
* function.
*
* @return
* - LE_OK if the data connection is attempting to be established
* - LE_COMM_ERROR if the data connection request was rejected
*/
//--------------------------------------------------------------------------------------------------
le_result_t wakeupAndTweet_ConnectAndRun
(
std::function<void()> onConnect ///< Function to run once the connection is established
);
#endif // CONNECT_AND_RUN_H
//--------------------------------------------------------------------------------------------------
/**
* This application demonstrates reading the ADC-based light sensor on the mangOH Red and using the
* same sensor as the boot source to wake up from low power mode. The app sends out a tweet using
* the socialService api. The twitter client must have been previously configured for the tweet to
* be transmitted successfully.
*
* Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.
*/
//--------------------------------------------------------------------------------------------------
#include "legato.h"
#include "interfaces.h"
#include <sstream>
#include <memory>
#include "connectAndRun.h"
#define LIGHT_SENSOR_ADC_NUM 3
#define ADC_LEVEL_WAKEUP 900
#define ADC_LEVEL_SLEEP 600
#define LIGHT_SENSOR_SAMPLE_INTERVAL_MS 2000
static const uint32_t UnicodeTiredFace = 0x1F62B;
static const uint32_t UnicodeSleepingFace = 0x1F634;
static le_timer_Ref_t LightSensorSampleTimer;
//--------------------------------------------------------------------------------------------------
/**
* Attempts to send out the given tweet and logs errors if it is unsuccessful.
*/
//--------------------------------------------------------------------------------------------------
static void SendTweet
(
const char* tweet ///< [IN] text to send out in the tweet
)
{
LE_DEBUG("Sending out tweet");
int attempts = 0;
do
{
const auto r = twitter_Tweet(tweet);
attempts++;
if (r == LE_OK)
{
break;
}
else if (r == LE_OVERFLOW)
{
LE_ERROR("Wakeup tweet was too long");
break;
}
else if (r == LE_FORMAT_ERROR)
{
LE_ERROR("Wakeup tweet was not utf-8 encoded");
break;
}
else if (r == LE_COMM_ERROR)
{
LE_DEBUG("Communication error during wakeup tweet on attempt %d", attempts);
}
else if (r == LE_NOT_PERMITTED)
{
LE_ERROR("Twitter service is not configured");
break;
}
else
{
LE_FATAL("Unhandled tweet result (%d)", r);
}
} while (attempts < 3);
}
//--------------------------------------------------------------------------------------------------
/**
* Timer expiry handler which reads the ADC that is connected to the light sensor and places the
* device into a low power state if the light level reading is below ADC_LEVEL_SLEEP.
*/
//--------------------------------------------------------------------------------------------------
static void LightSensorSampleTimerHandler
(
le_timer_Ref_t sampleTimer ///< Handle of the expired timer
)
{
int32_t lightSensorReading;
auto adcResult = le_adc_ReadValue("EXT_ADC3", &lightSensorReading);
if (adcResult != LE_OK)
{
LE_WARN("Failed to read light sensor. ADC read failed with result code (%d)", adcResult);
return;
}
else
{
LE_DEBUG("Light sensor reports value %d", lightSensorReading);
}
if (lightSensorReading < ADC_LEVEL_SLEEP)
{
LE_INFO(
"Initiating shutdown due to light sensor value %d which is below the minimum %d",
lightSensorReading,
ADC_LEVEL_SLEEP);
if (le_ulpm_BootOnAdcConfigure(
LIGHT_SENSOR_ADC_NUM,
LIGHT_SENSOR_SAMPLE_INTERVAL_MS,
0,
ADC_LEVEL_WAKEUP) != LE_OK)
{
LE_ERROR("Failed to configure ADC3 as a wakeup source");
return;
}
if (le_ulpm_BootOnAdcSetEnabled(LIGHT_SENSOR_ADC_NUM, true) != LE_OK)
{
LE_ERROR("Couldn't enable ADC3 as wakeup source");
return;
}
auto shutdownResult = le_ulpm_ShutDown();
switch (shutdownResult)
{
case LE_OK:
LE_DEBUG("Shutdown initiated successfully");
break;
case LE_NOT_POSSIBLE:
LE_WARN("Can't shutdown the system right now");
break;
case LE_FAULT:
LE_ERROR("Failed to initiate shutdown");
break;
default:
LE_FATAL("Unhandled shutdown result (%d)", shutdownResult);
break;
}
}
}
COMPONENT_INIT
{
LE_DEBUG("wakeupAndTweetApp started");
if (le_bootReason_WasAdc(LIGHT_SENSOR_ADC_NUM))
{
LE_DEBUG("Boot reason was ADC %u", LIGHT_SENSOR_ADC_NUM);
size_t emojiLength = 4;
char emoji[emojiLength] = {0};
LE_ASSERT_OK(le_utf8_EncodeUnicodeCodePoint(UnicodeTiredFace, emoji, &emojiLength));
std::ostringstream tweetStream;
tweetStream << emoji << " I'm just waking up at #SierraWirelessDevDay";
auto tweet = std::make_shared<std::string>(tweetStream.str());
if (wakeupAndTweet_ConnectAndRun([tweet]{SendTweet(tweet->c_str());}) != LE_OK)
{
LE_ERROR("Couldn't create data connection to send tweet");
}
}
else
{
LE_DEBUG("Boot reason was not ADC %u", LIGHT_SENSOR_ADC_NUM);
}
LightSensorSampleTimer = le_timer_Create("light sensor");
LE_ASSERT_OK(le_timer_SetHandler(LightSensorSampleTimer, LightSensorSampleTimerHandler));
LE_ASSERT_OK(le_timer_SetMsInterval(LightSensorSampleTimer, LIGHT_SENSOR_SAMPLE_INTERVAL_MS));
LE_ASSERT_OK(le_timer_SetRepeat(LightSensorSampleTimer, 0));
LE_ASSERT_OK(le_timer_Start(LightSensorSampleTimer));
}
//--------------------------------------------------------------------------------------------------
// System definition for a tutorial app which uses an ADC based light sensor as a means to wake up
// from low power sleep and send a tweet. Also goes back to sleep if it gets dark.
//
// Copyright (C) Sierra Wireless Inc. Use of this work is subject to license.
//--------------------------------------------------------------------------------------------------
apps:
{
// Platform services.
$LEGATO_ROOT/apps/platformServices/airVantage/avcService
$LEGATO_ROOT/apps/platformServices/cellNetService
$LEGATO_ROOT/apps/platformServices/dataConnectionService
$LEGATO_ROOT/apps/platformServices/fwupdateService
$LEGATO_ROOT/apps/platformServices/modemService
$LEGATO_ROOT/apps/platformServices/positioningService
$LEGATO_ROOT/apps/platformServices/powerMgr
$LEGATO_ROOT/apps/platformServices/secStore
$LEGATO_ROOT/apps/platformServices/gpioService
$MANGOH_ROOT/apps/SocialService/socialService.adef
// Command-line tools.
$LEGATO_ROOT/apps/tools/tools
$MANGOH_ROOT/samples/tutorials/developerDay2016/apps/wakeupAndTweet.adef
}
commands:
{
cm = tools:/bin/cm
fwupdate = tools:/bin/fwupdate
secstore = tools:/bin/secstore
pmtool = tools:/bin/pmtool
twitter = socialService:/bin/twitter
}
bindings:
{
<root>.le_fwupdate -> fwupdateService.le_fwupdate
}
interfaceSearch:
{
interfaces/modemServices
interfaces/positioning
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment