...
Application/notecard_config.h
Provides
#define
variables that can be used to force override Notecard specific settings.Application/Framework/sched.h
Declares application callback signatures and the scheduled application configuration structure,
schedAppConfig
.Application/Framework/sched.c
Contains application array, implements the Sparrow task scheduler functions, and performs application callbacks (”Application Host”).
Application/Gateway/auth.c
Used by the gateway to receive/process Notes by adding additional information before forwarding to the Notecard.
Application/Sensor/init.c
Implements the weakly linked
schedAppInit()
function, which loads the example applications into the “Application Host”.
...
NOTE: In order to interact with the Scheduler, you must know your application ID,
appID
. This can and should be captured when you first register your application with the scheduler. However, theappID
is also provided as a form of context with each callback invocation.
**schedAppConfig**
Code Block |
---|
// App Configuration definition
typedef struct {
// General
const char *name;
// How often we get activated
uint32_t activationPeriodSecs;
// While app is active, how often it's polled
uint32_t pollIntervalSecs;
// Handlers
schedActivateFunc activateFn;
schedInterruptFunc interruptFn;
schedPollFunc pollFn;
schedResponseFunc responseFn;
// Application Context
void *appContext;
} schedAppConfig;
|
Name Field
...
activationPeriodSecs
The activation period is the time that passes between activations. Each time the scheduler awakens an application from it's deactivated state, it will invoke the
.activateFn
function. The primary concern addressed by the activation period is power management. The longer the activation period, the more time spent sleeping and better battery performance a Sparrow node can achieve.pollIntervalSecs
The polling function is only called when the application is in an active state, and the poll interval is frequency at which the
.pollFn
function is invoked. At a high level, the polling function should be thought of as a "check-in" from the underlying state machine to the main control body of the application logic. Ideally, you would not request the poll function to be invoked faster than the rate of change associated with whatever external factors for which the application has been designed (i.e. there is no reason to pay for the poll unless it is able to capture or respond to some change in state).
...
Applications can take advantage of dynamic queue file naming, to create node and/or application specific queue files. For example, *#myapp.qo
will evaluate to 2037335832365003001b0037#myapp012345678901234567890123#myapp.qo
. The Gateway will automatically transform the *
into the node id associated with the originating Sparrow board.
*
is a special character that will be replaced with the Sparrow node's ID by the Gateway.
Callbacks
**.activateFn**
-typedef bool (*schedActivateFunc) (int appID);
Called on activation; you may return
false
to cancel any given activation.NOTE: that this method must NOT send messages to the gateway; it's only allowed to do local operations.
**.interruptFn**
-typedef void (*schedInterruptFunc) (int appID, uint16_t pins);
An A shared ISR that is called for ANY interrupt on ANY and ALL interruptsapplications; the
pins
parameter indicates[exti
lines ] (https://wiki.st.com/stm32mcu/wiki/EXTI_feature_overview ) that changed. Due to the shared nature of the pin, you must filter to the pin you are expecting to handle in your application.**.pollFn**
Example: Filtering on the
PAIR
buttonCode Block language c if (!(pins & BUTTON1_Pin)) { return; }
.pollFn
-typedef void (*schedPollFunc) (int appID, int state);
Called repeatedly while activated. This function implements the application's state machine, where negative states are reserved. Only when this function sends a message using the
noteSendToGatewayAsync()
function, or manually submitsSTATE_DEACTIVATE
to the scheduler, will the application will be deactivated.**.responseFn**
-typedef void (*schedResponseFunc) (int appID, J *rsp);
Called after an application sent a Notecard request and is asynchronously receiving a reply. This will be called when a response comes back or when it times out; if timeout the
rsp
field will beNULL
.
Callback Timing
Here is a diagram to illustrate the callback timing of a typical Sparrow application that was expecting a response from the Notecard.
...
Application Context
appContext
Application context exists in two forms, which can work in tandem.
static global variables (singleton model)
When application context is supplied as static global variables, then it is available to everything in the containing.c
file. This is suitable for most single purpose applications (e.g. an interface to specific hardware, performs a unique operation, etc.). To use a static global variable, you only need to define a variable asstatic
in the global space of your application’s.c
file.appContext
- a portable struct (multiple instances)
However, there are several instances where a portable struct can facilitate code reuse and enable higher level abstractions (e.g. using one source file to interface to an array of identical sensors, enabling a context based language, etc.). To use a portable struct, you would define it in your application’s.c
file, allocate it from the heap in an initialization function, and provide a pointer to theappContext
field of the application configuration struct,schedAppConfig
.
Application Run Time
Your application “runs” inside the callbacks. The closest thing to a run loop would be the intermittent calls to pollFn
at pollIntervalSecs
. Upon the execution of pollFn
the state of the application will be passed in as a parameter, and will cycle through STATE_ACTIVATED
, STATE_SENDING_REQUEST
, and STATE_RECEIVING_RESPONSE
. The application will remain active until it sends a message using the noteSendToGatewayAsync()
function, or until it manually sets the scheduler's state to STATE_DEACTIVATED
.
...