Whiteboard
In simplified terms Whiteboard is an asyncronous communication library for handling internal and external communication in Movesense (excluding the Gatt service communication with mobile client). Full description of the Movesense API with some examples can be found here. See also Getting started for an example of creating a simple new data resource provider. More elaborate functional examples can be found under Sample Applications.
Following are the key components of using the Whiteboard REST-like services in sensor software via the Whiteboard C++ programming interface.
LaunchableModule
A launchable module is a component that allows its running state to be controlled by the system through the StartupProvider. Typically a launchable module initializes providers and clients of some feature. The interface can be used without any service provider or client if only initialization is needed and there is no need to use the messaging system for operation.
The StarupProvider interface for starting and stopping services is also accessible from outside the sensor over any active communication route. This may be usefull in e.g. some system testing scenarios.
Interface
A new launchable module needs to inherit the whiteboard::LaunchableModule interface.
#include <whiteboard/LaunchableModule.h>
class TestService FINAL : private whiteboard::LaunchableModule
These pure virtual method implementations are required:
virtual bool initModule() = 0;
virtual void deinitModule() = 0;
virtual bool startModule() = 0;
virtual void stopModule() = 0;
Construction
#include <app_execution_contexts/resources.h>
const char* const TestService::LAUNCHABLE_NAME = "TestSvc";
TestService::TestService()
: LaunchableModule(LAUNCHABLE_NAME, WB_EXEC_CTX_APPLICATION)
{}
Execution contexts are defined under the "executionContexts" section in the application's yaml files (app_root.yaml in most of the provided examples). Each context is a separate thread and Whiteboard provides a safe event based framework for switching between contexts.
By default two execution contexts are available in the examples:
- application general context for other than measurement services
- meas this context is connected to measurements like accelerometer or HR and should NOT block the context (ex. delays).
It must be noted that the pre-built system library expects the first execution context to be "application" and the second "meas". The order or naming of these cannot be changed or otherwise the application project will not copile. The properties of these execution contexts may however be adjusted according to needs. Also more execution contexts can be added by defining them in YAML but they will consume RAM for the thread's stack memory and the messaging queues.
Adding new launchable modules
In App.cpp file a new launchable module can be added as follows:
#include "TestService.h"
MOVESENSE_PROVIDERS_BEGIN(1)
MOVESENSE_PROVIDER_DEF(TestService)
MOVESENSE_PROVIDERS_END(1)
RTT logs can be used to verify the module is loaded correctly.
Operation
Life cycle of the module
Launchable modules use two stage startup (initialization and start) and shutdown (stop and deinitialization) procedures. Upon bootup a system wide initialization is done after which the secondary start methods are called to put the system in a ready state. In a service provider's case the provider should be ready for e.g. client subscriptions to the service interface specifiend in YAML. These C++ interface methods should be properly implemented for correct operation of the module.
Virtual bool initModule() method
The startup service provider will call this method to trigger the initialization of the module (hardware configuration etc.). No API resources can be used during the execution of this method as the system is still initialising.
Return true if initialization was successful, false otherwise.
Example implementation:
bool TestService::initModule()
{
bool result = initalizeTestHarware();
mModuleState = WB_RES::ModuleStateValues::INITIALIZED;
return result;
}
Virtual bool startModule() method
Startup service provider will call this method to indicate the operation of the module can be started.
Return true if startup was successful, false otherwise.
Example implementation:
bool TestService::startModule()
{
// read configuration that is accessible after initialization
readDefaultConfig();
acquireTimingResources();
mModuleState = WB_RES::ModuleStateValues::STARTED;
return true;
}
Virtual void stopModule() method
Startup service provider will call this method to indicate the operation of the module is not allowed.
Example implementation:
void TestService::stopModule()
{
if (mIsActive)
{
fullStop();
}
releaseTimingResources();
mModuleState = WB_RES::ModuleStateValues::STOPPED;
}
Virtual void deinitModule() method
Startup service provider will call this method to trigger the de-initialization of the module. No API resources can be used during the execution of this method as the system may be e.g. deinitialising to power down.
Example implementation:
void TestService::deinitModule()
{
deinitalizeTestHarware();
mModuleState = WB_RES::ModuleStateValues::UNINITIALIZED;
}
Functions
These are mainly for the system to query the state of the modules, but may be used by the modules if needed.
const char* getLaunchableName()
Get the name of the module.
Returns Pointer to the module name.
WB_RES::ModuleState getModuleState() const
Get current state of the module
Returns State of the module.
ExecutionContextId getExecutionContextId() const
Get the execution context of the launchable module.
Returns The execution contxet ID.
ResourceProvider
Base class for creating new service providers. Via this interface class new resources can be registered for client usage. For interfaces designed to be used over BLE power consumption consideration should be made for performing some data calculation on the sensor. This is to avoid sending all of the raw data and using lot of BLE bandwidth.
Interface
The interface is a two way interface, the system features available for resource providers can be accessed via the member functions. On the other hand, callback methods for required specific service operation types (GET, PUT, POST, DELETE) need to be overridden.
Extend the class with ResourceProvider.
#include <whiteboard/LaunchableModule.h>
#include <whiteboard/ResourceProvider.h>
class TestService FINAL : private whiteboard::ResourceProvider,
public whiteboard::LaunchableModule
Construction
Service providers operate in their designated execution contexts (threads) and the context defintion given to the constructor must be the same as what is specifiend in YAML for the resources that are registered for the provider. Trying to operate on a resource that is specified for some other execution context will result in an error.
const char* const TestService::LAUNCHABLE_NAME = "TestSvc";
TestService::TestService()
: ResourceProvider(WBDEBUG_NAME(__FUNCTION__), WB_RES::LOCAL::SAMPLE_TEST1::EXECUTION_CONTEXT),
LaunchableModule(LAUNCHABLE_NAME, WB_RES::LOCAL::SAMPLE_TEST1::EXECUTION_CONTEXT)
{}
Registering and unregistering resources
Even though it's possible to register resources one by one, it is a good practise to create an array of local resource IDs and register the whole array at once.
static const whiteboard::LocalResourceId sProviderResources[] =
{
WB_RES::LOCAL::SAMPLE_TEST1::LID,
WB_RES::LOCAL::SAMPLE_TEST2::LID,
};
Registration of the resources should be done in the initModule so that clients can subscribe to them in the startModule() method.
bool TestService::initModule()
{
if (registerProviderResources(sProviderResources) != whiteboard::HTTP_CODE_OK)
{
mModuleState = WB_RES::ModuleStateValues::INITFAILED;
return false;
}
mModuleState = WB_RES::ModuleStateValues::INITIALIZED;
return true;
}
Also it is a good practise to unregister resources during deinitialization.
void TestService::deinitModule()
{
unregisterProviderResources(sProviderResources);
mModuleState = WB_RES::ModuleStateValues::UNINITIALIZED;
}
Handling incoming requests
There are several types of requests. The operations that are specified in the YAML interface must be implemented by the service provider. All required callbacks of the following need to be overridden:
virtual void onGetRequest(const Request& rRequest, const ParameterList& rParameters)
virtual void onPutRequest(const Request& rRequest, const ParameterList& rParameters)
virtual void onPostRequest(const Request& rRequest, const ParameterList& rParameters)
virtual void onDeleteRequest(const Request& rRequest, const ParameterList& rParameters)
Default implementation: Returns whiteboard::HTTP_CODE_NOT_IMPLEMENTED
Example implementation:
void TestService::onGetRequest(const whiteboard::Request& request,
const whiteboard::ParameterList& parameters)
{
// in order to save ROM, this could also be:
// ASSERT(mModuleState == WB_RES::ModuleStateValues::STARTED);
if (mModuleState != WB_RES::ModuleStateValues::STARTED)
{
return returnResult(request, wb::HTTP_CODE_SERVICE_UNAVAILABLE);
}
switch (request.getResourceId().localResourceId)
{
case WB_RES::LOCAL::SAMPLE_TEST1::LID:
{
WB_RES::Test test;
test.value = 1;
return returnResult(request, whiteboard::HTTP_CODE_OK, ResponseOptions::Empty, test);
}
break;
case WB_RES::LOCAL::SAMPLE_TEST2::LID:
{
WB_RES::Test test;
test.value = 2;
return returnResult(request, whiteboard::HTTP_CODE_OK, ResponseOptions::Empty, test);
}
break;
default:
return returnResult(request, whiteboard::HTTP_CODE_NOT_FOUND);
}
}
Subcriptions and notifications are a special case of operation. The standard REST operation is that one request is followed by an response to it. Subscriptions allow multiple responses (notifications) without new requests. Notifications may be periodic or event based.
Override these methods only if subscribers and their subscription parameters need to be tracked. Check "Updating resource" to see how to send data.
virtual void onSubscribe(const Request& rRequest, const ParameterList& rParameters)
virtual void onUnubscribe(const Request& rRequest, const ParameterList& rParameters)
Default implementation: Returns whiteboard::HTTP_CODE_OK
Any incoming request must be closed with a call returnResult(...) within the scope of the callback if the request object is not stored for later processing.
template <typename V = NoType>
void returnResult(const Request& rRequest, Result resultCode, const ResponseOptions& rOptions = ResponseOptions::Empty, const V& result = NoType::NoValue)
template <typename RESPONSE, typename V = NoType, typename EnableIf<!IsSame<RESPONSE, Result>::value, int>::type = 0>
void returnResult(const Request& rRequest, const RESPONSE& rResponse, const ResponseOptions& rOptions = ResponseOptions::Empty, const V& result = NoType::NoValue)
Returns result for a request
- V Native type for the result to be returned
- rRequest Request information
- resultCode Result code of the request
- rOptions Options for the response delivery - see whiteboard::ResourceProvider::ResponseOptions
- rResult Result data of the request
Updating resource - notification to subscribers
template <typename V, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
inline Result updateResource(LocalResourceId localResourceId, const ResponseOptions& rOptions, const V& rValue, const P1& rP1, const P2& rP2, const P3& rP3, const P4& rP4, const P5& rP5, const P6& rP6, const P7& rP7, const P8& rP8)
Sends resource changed notification for all subscribed clients. Data format must be as specified in YAML.
- V Native type for the updateResource result.
- P1 .. P8 Optional. Native type for the update resource parameters.
- resourceId ID of the associated resource
- rOptions Options for the response delivery - @see whiteboard::ResourceProvider::ResponseOptions
- rValue Current value of the resource
- rP1 .. rP8 If path variables are used, add the path variables as a parameter. Path variable closest to the root shall be given first
May not be called from onSubscribe() nor onUnsubscribe().
Example implementation
char buf[32];
counter++;
snprintf(buf, 32, "Hello World #%u!", counter);
WB_RES::HelloWorldValue hello;
hello.greeting = buf;
// and update the resources/resources
updateResource(WB_RES::LOCAL::SAMPLE_HELLOWORLD(), ResponseOptions::Empty, hello);
Other callback options
Functions handling Diconnections
virtual void onClientUnavailable(ClientId clientId);
Local client has become unavailable. It is the client's responsibility to e.g. renew subscriptions.
virtual void onRemoteWhiteboardDisconnected(WhiteboardId whiteboardId);
Connection to remote whiteboard lost. Remote clients will resubscribe if needed.
Functions
const char* getName() const
Returns the name of a resource provider.
ProviderId getId() const
Returns ID of the registered provider
LocalProviderId getLocalProviderId() const
Returns local ID of the registered provider
ExecutionContextId getExecutionContextId() const
Returns Reference to the provider's execution context
Result getLocalResource(const char* pFullPath, ResourceId& rResourceId)
Resolves local resource from path string.
- pFullPath Path of the resource
- rResourceId On successful output contains the resource identifier
Returns result of the operation
Result isResourceSubscribed(ResourceId resourceId)
Query if a given resource has any active subscribers. It is good practise to stop operation to save power if no active subscribers.
Result enumerateSubscriptions(ResourceId resourceId, IEnumerateSubscriptionsFunctor& rFunctor)
Helper function for reiterating through all remaining subscribers.
ResourceClient
Services provided by the provider modules can be accessed via the ResourceClient interface class. Examples can be found in the samples direcory. One of the simplest examples is the blinky_app sample.
Interface
Client class should inherit the ResourceClient class, and also the LaunchableModule class if any startup time initialisation needs to get done.
#include <whiteboard/ResourceClient.h>
class TestClient FINAL : private whiteboard::ResourceClient
Constructor
ResourceClient(const char* pClientName, ExecutionContextId executionContextId);
const char* const TestService::LAUNCHABLE_NAME = "TestSvc";
TestService::TestService()
: ResourceClient(WBDEBUG_NAME(__FUNCTION__), WB_EXEC_CTX_APPLICATION)
{}
Resource IDs
All resources have unique IDs which can be found in the source files generated from YAML files. IDs can be queried by the resource paths, but for local resources it is recommed to directly use the generated explicit constant ID values. When using path paramers ({param name} in the path string) with device local resources the getResource(...) or asyncGetResource(...) path string based resolver method must be used in conjunction with releaseResource(...). This is because the path paramerters need to be stored by the system for the duration of the usage of the resource. A call to releaseResource(...) then releases also the stored path parameters.
Local resources
Result getResource(const char* pFullPath, ResourceId& rResourceId, const RequestOptions& rOptions = RequestOptions::Empty)
Resolves resource from path string. Only for local paths. Use asyncGetResource to resolve external paths.
- pFullPath Path of the resource
- rResourceId On successful output contains the resource identifier
- rOptions Optional. The options for the request
Returns Result of the operation
Result releaseResource(ResourceId resourceId, const RequestOptions& rOptions = RequestOptions::Empty);
Performs resource release. Release is intented to indicate to the provider's whiteboard, that this client does not use the resource anymore. Only for local paths, use asyncReleaseResource for external resourceIds.
- resourceId ID of the associated resource
- rOptions Optional. The options for the request
Returns Result of the operation
External resources
Result asyncGetResource(const char* pFullPath, const AsyncRequestOptions& rOptions = AsyncRequestOptions::Empty);
Performs asynchronous resource resolving
- pFullPath Path of the resource
- rOptions Optional. The options for the request
Returns result of the operation
virtual void onGetResourceResult(RequestId requestId, ResourceId resourceId, Result resultCode);
Callback for asynchronous resource requests
- requestId ID of the request
- resourceId Successful request contains ID of the resource
- resultCode Result code of the request
Result asyncReleaseResource(ResourceId resourceId, const AsyncRequestOptions& rOptions = AsyncRequestOptions::Empty);
Performs asynchronous resource release. Release is intented to indicate to the provider's whiteboard, that this client does not use the resource anymore.
- resourceId ID of the associated resource
- rOptions Optional. The options for the request
Returns Result of the operation
virtual void onReleaseResourceResult(RequestId requestId, ResourceId resourceId, Result resultCode);
Callback for asynchronous resource requests
- requestId ID of the request
- resourceId Successful request contains ID of the resource
- resultCode Result code of the request
Request types
GET
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
inline Result asyncGet(ResourceId resourceId, const AsyncRequestOptions& rOptions, const P1& rP1, const P2& rP2, const P3& rP3, const P4& rP4, const P5& rP5, const P6& rP6, const P7& rP7, const P8& rP8)
Performs asynchronous GET request. P1 .. P8 are optional.
- resourceId ID of the associated resource
- rOptions Optional. The options for the request
- rP1 .. rP8 Optional. List of request parameters
Returns Result of the operation.
virtual void onGetResult(RequestId requestId, ResourceId resourceId, Result resultCode, const Value& rResultData)
Callback for asynchronous resource GET requests
- requestId ID of the request
- resourceId Successful request contains ID of the resource
- resultCode Result code of the request
- rResultData Successful result contains the request result
PUT
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
inline Result asyncPut(ResourceId resourceId, const AsyncRequestOptions& rOptions, const P1& rP1, const P2& rP2, const P3& rP3, const P4& rP4, const P5& rP5, const P6& rP6, const P7& rP7, const P8& rP8)
Performs asynchronous PUT request. P1 .. P8 are Optional.
- resourceId ID of the associated resource
- rOptions Optional. The options for the request
- rP1 .. rP8 Optional. List of request parameters
Returns Result of the operation
virtual void onPutResult(RequestId requestId, ResourceId resourceId, Result resultCode, const Value& rResultData);
Callback for asynchronous resource PUT requests
- requestId ID of the request
- resourceId Successful request contains ID of the resource
- resultCode Result code of the request
- rResultData Successful result contains the request result
POST
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
inline Result asyncPost(ResourceId resourceId, const AsyncRequestOptions& rOptions, const P1& rP1, const P2& rP2, const P3& rP3, const P4& rP4, const P5& rP5, const P6& rP6, const P7& rP7, const P8& rP8)
Performs asynchronous POST request. P1 .. P8 are optional.
- resourceId ID of the associated resource
- rOptions Optional. The options for the request
- rP1 .. rP8 Optional. List of request parameters
Returns Result of the operation
virtual void onPostResult(RequestId requestId, ResourceId resourceId, Result resultCode, const Value& rResultData);
Callback for POST operation result
- requestId ID of the request
- resourceId Successful request contains ID of the resource
- resultCode Result code of the request
- rResultData Successful result contains the request result
DELETE
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
inline Result asyncDelete(ResourceId resourceId, const AsyncRequestOptions& rOptions, const P1& rP1, const P2& rP2, const P3& rP3, const P4& rP4, const P5& rP5, const P6& rP6, const P7& rP7, const P8& rP8)
Performs asynchronous DELETE request. P1 .. P8 are optional
- resourceId ID of the associated resource
- rOptions Optional. The options for the request
- rP1 .. rP8 Optional. List of request parameters
Returns Result of the operation
virtual void onDeleteResult(RequestId requestId, ResourceId resourceId, Result resultCode, const Value& rResultData);
Callback for DELETE operation result
- requestId ID of the request
- resourceId Successful request contains ID of the resource
- resultCode Result code of the request
- rResultData Successful result contains the request result
Subscriptions fo continuous data transfer
Resource subscriptions allow for continuously sending data from the service provider to any number of clients. Fundamentally the provider controls the frequency of notifications. Subscription parameters may be used for clients requesting specific frequencies for the updates.
Subscribe
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
inline Result asyncSubscribe(ResourceId resourceId, const AsyncRequestOptions& rOptions, const P1& rP1, const P2& rP2, const P3& rP3, const P4& rP4, const P5& rP5, const P6& rP6, const P7& rP7, const P8& rP8)
Performs asynchronous SUBSCRIBE request. P1 .. P8 are optional.
- resourceId ID of the associated resource
- rOptions Optional. The options for the request
- rP1 .. rP8 Optional. List of request parameters
Returns Result of the operation
virtual void onSubscribeResult(RequestId requestId, ResourceId resourceId, Result resultCode, const Value& rResultData);
Callback for asynchronous SUBSCRIBE requests
- requestId ID of the request
- resourceId Successful request contains ID of the resource
- resultCode Result code of the request
- rResultData Successful result contains the request result
void asyncSubscribeLocalResources(size_t numberOfResources, const LocalResourceId* const pResourceIds, bool isCriticalSubscription = true, bool noResponseExpected = false)
template <size_t NUMBER_OF_RESOURCES>
inline void asyncSubscribeLocalResources(const LocalResourceId(&rResourceIds)[NUMBER_OF_RESOURCES], bool isCriticalSubscription = true, bool noResponseExpected = false)
inline void asyncSubscribeLocalResource(const LocalResourceId localResourceId, bool isCriticalSubscription = true, bool noResponseExpected = false)
Subscribes array of local Whiteboard resources
This function asserts if asynchronous dispatch fails or if any synchronous (same event thread) subscriptions fail.
- numberOfResources Number of resources to subscribe
- pResourceIds Array of resources to subscribe
- isCriticalSubscription A value indicating whether subscriptions are critical
- noResponseExpected A value indicating if subscription operation response is required (for optimization purposes)
Unsubscribe
template <typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7, typename P8>
inline Result asyncUnsubscribe(ResourceId resourceId, const AsyncRequestOptions& rOptions, const P1& rP1, const P2& rP2, const P3& rP3, const P4& rP4, const P5& rP5, const P6& rP6, const P7& rP7, const P8& rP8)
Performs asynchronous UNSUBSCRIBE request. P1 .. P8 are optional
- resourceId ID of the associated resource
- rOptions Optional. The options for the request
- rP1 .. rP8 Optional. List of request parameters
Returns Result of the operation
virtual void onUnsubscribeResult(RequestId requestId, ResourceId resourceId, Result resultCode, const Value& rResultData);
Callback for asynchronous UNSUBSCRIBE requests
- requestId ID of the request
- resourceId Successful request contains ID of the resource
- resultCode Result code of the request
- rResultData Successful result contains the request result
void asyncUnsubscribeLocalResources(size_t numberOfResources, const LocalResourceId* const pResourceIds, bool noResponseExpected = false);
template <size_t NUMBER_OF_RESOURCES>
inline void asyncUnsubscribeLocalResources(const LocalResourceId(&rResourceIds)[NUMBER_OF_RESOURCES], bool noResponseExpected = false)
inline void asyncUnsubscribeLocalResource(const LocalResourceId localResourceId, bool noResponseExpected = false)
Unubscribes array of local Whiteboard resources
-
This function asserts if asynchronous dispatch fails or if any synchronous (same event thread) unsubscriptions fail except for missing subscriptions.*
-
numberOfResources Number of resources to unsubscribe
- pResourceIds Array of resources to unsubscribe
- noResponseExpected A value indicating if unsubscription operation response is required (for optimization purposes)
Notify
virtual void onNotify(ResourceId resourceId, const Value& rValue, const ParameterList& rParameters);
Callback for resource notifications.
- resourceId Resource id associated with the update
- rValue Current value of the resource
- rParameters Notification parameters
Other callback options
Detect disconnection
Same disconnection notification is available for both clients and providers.
virtual void onRemoteWhiteboardDisconnected(WhiteboardId whiteboardId);
Remote whiteboard disconnect notification handler.
This can be used for example to cleanup possible subscription related state in the client-end. Whiteboard automatically cleans subscriptions and path variable allocations related to the disconnected whiteboard, so the client will not get further notifications and does not need to call unsubscribe or releaseResource either.
- whiteboardId ID of the whiteboard that has been disconnected.
virtual void onResourceUnavailable(ResourceId resourceId);
Local resource unavailability handler.
This can be used for example to cleanup possible subscription related state in the client-end. Whiteboard automatically cleans subscriptions and path variable allocations related to the removed resource, so the client will not get further notifications and does not need to call unsubscribe or releaseResource either.
- resourceId ID of the resource that is no longer available
Functions
const char* getName() const;
Gets name of the client
ClientId getId() const;
Gets ID of the client
Returns ID of the registered client or ID_INVALID_CLIENT if client has not been registered
LocalClientId getLocalClientId() const;
Gets local client ID of the client
Returns Local ID of the registered client or ID_INVALID_LOCAL_CLIENT if client has not been registered
ExecutionContextId getExecutionContextId() const;
Gets ID of client's execution context
Returns ID of client's execution context
Timers
A common use case for timers is periodic measurements from which the results are sent to subscribers as notifications. Timers are available via the the ResourceClient and ResourceProvider interfaces. They can be used to do delayed or recurring work.
TimerId startTimer(size_t periodMs, bool isContinuous = false);
Starts a continuous timer with given period. Override whiteboard::ResourceClient::onTimer to handle timer notifications.
If previous timer message has not been processed, for example due to execution context blocking on long operation - and short interval continuous timer is in use, the timer messages might be filtered out to prevent flooding the message queues.
Starting a timer from interrupt is not supported.
- periodMs Period in milliseconds how often the timer should fire.
- isContinous If true, continuous timer, else single shot.
Returns ID of the started timer or ID_INVALID_TIMER, if starting a new timer fails.
bool rescheduleTimer(TimerId timerId, size_t periodMs);
Reschedules the continuous timer with a new period; The existing timer is stopped and restarted (but not deallocated).
A timer message with the previous timer interval might have been queued before processing the rescheduling and hence the first time might fire in period less than the new period.
- timerId Id of the timer that is running
- periodMs New period in milliseconds how often the timer should fire.
bool stopTimer(TimerId timerId);
Stops a timer started with startTimer. No notifications of the given timer are received after this call returns.
In case of continuous timer, a notification might be received after the stop if the stop is called from another thread than the clients execution context. Hence using timer start / stop from another thread is discouraged.
Stopping a timer from interrupt is not supported.
- timerId Id of the timer to stop
Returns true on success, false if timer was already stopped or this provider did not own the timer, or if id was illegal.
virtual void onTimer(TimerId timerId);
Callback for timer notifications. It is call in the provider or client context. It is safe to use ex. updateResource(...)
- timerId ID of the timer that has expired.
This sample shows how to create a continuous work in a few steps.
Creating a timer
The new member whiteboard::TimerId is needed and will be used for timer.
class TestClient FINAL : private whiteboard::ResourceClient,
public whiteboard::LaunchableModule
{
...
private:
whiteboard::TimerId mTimer;
};
Good practise it to set variable to whiteboard::ID_INVALID_TIMER
TestClient::TestClient()
: ResourceClient(WBDEBUG_NAME(__FUNCTION__), WB_EXEC_CTX_APPLICATION),
LaunchableModule(LAUNCHABLE_NAME, WB_EXEC_CTX_APPLICATION)
{
mTimer = whiteboard::ID_INVALID_TIMER;
}
Usage
Starting the timer
If timer should be started right after module is started, then the best location will be startModule()
bool TestClient::startModule()
{
mModuleState = WB_RES::ModuleStateValues::STARTED;
mTimer = startTimer(1000, true);
return true;
}
Stopping the timer
Timer should be stopped when stopModule will be called or before that in any part of the application.
void TestClient::stopModule()
{
stopTimer(mTimer);
mTimer == whiteboard::ID_INVALID_TIMER;
}
The timer's callback
Timer will be calling onTimer. If there are more than one timer it can be recognized by timerId.
void TestClient::onTimer(whiteboard::TimerId timerId)
{
if (timerId == mTimer)
{
// DO SOME WORK HERE
}
}