A simple interface to mbed Device Connector, where you just declare variables to push them to the cloud.

Dependents:   Wifi_Get_Test_V1 simple-mbed-client-example simple-client-app-shield simple-sensor-client

Fork of simple-mbed-client by Jan Jongboom

TL;DR? See simple-mbed-client-example to get started immediately.

This library is a simpler interface to mbed Client, making it trivial to expose sensors, actuators and other variables to the cloud. It does not require you to change how you write your code. You can take any local variable, swap it out for a call to Simple Mbed Client, and the variable will automatically be synchronised with mbed Cloud.

For example, here's how you expose the value of a light sensor to the cloud:

SimpleMbedClient client;

SimpleResourceInt light_value = client.define_resource("light/0/value", 0);     // create the var

AnalogIn light(A1);

void read_light_sensor() {
    // light_value behaves just like a normal variable that you can read and write to!
    light_value = light.read_u16();
}

// update every second
Ticker t;
t.attach(&read_light_sensor, 1.0f);

Setting up

First import this library to your project. As Simple Mbed Client also needs a way to talk to the outside world, you'll need a NetworkInterface-object. The easiest way is by using the easy-connect library, so add that to your project as well. See the easy-connect docs on how to specify the connectivity method.

We also need a way of authenticating with mbed Cloud. For this we need a security certificate. Go to mbed Cloud, and select 'GET MY DEVICE SECURITY CREDENTIALS'. Save the certificate as security.h in your project folder.

Now we can initiate Simple Mbed Client and connect it to the internet.

#include "mbed.h"
#include "security.h"
#include "easy-connect.h"
#include "simple-mbed-client.h"

SimpleMbedClient client;

DigitalOut led(LED1, 0);

void registered() {
    led = 1;
}

int main() {
    NetworkInterface* network = connect_to_network(); // if connection failed, network will be NULL
    client.setup(network); // returns a bool, check if it's true

    client.on_registered(&registered);

    while (1) {
        wait_ms(25000);
        client.keep_alive();
    }
}

Defining variables

You can define a new variable by a call to client.define_resource. This function takes five arguments:

  1. path - The URL on which your variable is exposed in mbed Cloud. Needs to be three (3) segments, split by a slash (/) in the form of 'sensor/0/value'. The second segment always needs to be numeric.
  2. defaultValue - The default value of the variable. Needs to be either a string or an integer. Depending on the type that you pass in here the type of the variable is defined.
  3. operation - Some variables might be read-only or write-only (seen from the cloud). Use the operation to define these constraints. It's of type M2MBase::Operation. Default is GET_PUT_ALLOWED.
  4. observable - If set to false, cloud applications cannot subscribe to updates on this variable. Default is true.
  5. callback - Function pointer which is called whenever the value of the variable is changed from the cloud.

The type returned by the function is either SimpleResourceInt or SimpleResourceString. You can assign and read from these variables like any normal local variable.

void name_updated(string new_value) {
    printf("Value is now %s\n", new_value.c_str());
}

SimpleResourceString name = client.define_resource("device/0/name", "jan", M2MBase::GET_PUT_ALLOWED, true, &name_updated);

// we can read and write to this variable, e.g.:
stringstream ss;
ss << name;

// or
name = "pietje";

// are all valid

Defining functions

You can define functions, which do not have a value, but can just be invoked from the cloud, by a call to client.define_function. This function takes two arguments:

  1. path - The URL on which your variable is exposed in mbed Cloud. Needs to be three (3) segments, split by a slash (/) in the form of 'sensor/0/value'. The second segment always needs to be numeric.
  2. callback - Function pointer which is invoked when the function is called. Takes in a pointer, which contains the data being passed in from the cloud.

void play(void* data) {
    if (data) { // data can be NULL!
        // cast it to something useful
    }
}

client.define_function("music/0/play", &play);

Accessing the underlying M2MResource

If you need access to the underlying M2MResource you can do so by calling get_resource on a variable, or by calling client.get_resource if it's a function.

SimpleResourceInt led = client.define_resource("led/0/value", true);

client.define_function("led/0/toggle", &toggleLed);

// now to get the resource
M2MResource* ledResource = led.get_resource();
M2MResource* toggleResource = client.get_resource("led/0/toggle");

Printing variables

Unfortunately printf is kind of dumb, and does not automatically cast the variables. If you want to print any of the Simple Mbed Client variables you'll need to cast yourself.

SimpleResourceInt led = client.define_resource("led/0/value", true);

printf("Value is currently %d\n", static_cast<int>(led));

Event Queue

Simple Mbed Client uses an mbed-events EventQueue - running on a separate RTOS thread - to handle incoming events without blocking the main loop. Both the thread and event queue are created when initializing the library. You can override this behavior by providing your own event queue. In this case no thread is created.

EventQueue myQueue;
SimpleMbedClient client(&myQueue);

You can also use the queue to process your own events, which is very useful when dealing with ISRs. The queue is accessible through the eventQueue() function on the client object and returns a pointer to the queue.

SimpleMbedClient client;

InterruptIn btn(D2);

int main() {
  btn.fall(client.eventQueue()->event(&fall));
}
Committer:
Jan Jongboom
Date:
Mon Feb 06 17:31:43 2017 +0100
Revision:
16:cb980bd39e32
Parent:
15:b7360c7e0f7f
Child:
17:200624714d15
Get rid of stringstream. Save 130K flash and 4K of RAM

Who changed what in which revision?

UserRevisionLine numberNew contents of line
janjongboom 0:9fa3f3028773 1 /*
janjongboom 0:9fa3f3028773 2 * Copyright (c) 2015 ARM Limited. All rights reserved.
janjongboom 0:9fa3f3028773 3 * SPDX-License-Identifier: Apache-2.0
janjongboom 0:9fa3f3028773 4 * Licensed under the Apache License, Version 2.0 (the License); you may
janjongboom 0:9fa3f3028773 5 * not use this file except in compliance with the License.
janjongboom 0:9fa3f3028773 6 * You may obtain a copy of the License at
janjongboom 0:9fa3f3028773 7 *
janjongboom 0:9fa3f3028773 8 * http://www.apache.org/licenses/LICENSE-2.0
janjongboom 0:9fa3f3028773 9 *
janjongboom 0:9fa3f3028773 10 * Unless required by applicable law or agreed to in writing, software
janjongboom 0:9fa3f3028773 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
janjongboom 0:9fa3f3028773 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
janjongboom 0:9fa3f3028773 13 * See the License for the specific language governing permissions and
janjongboom 0:9fa3f3028773 14 * limitations under the License.
janjongboom 0:9fa3f3028773 15 */
janjongboom 0:9fa3f3028773 16
janjongboom 0:9fa3f3028773 17 #ifndef __SIMPLE_MBED_CLIENT_H__
janjongboom 0:9fa3f3028773 18 #define __SIMPLE_MBED_CLIENT_H__
janjongboom 0:9fa3f3028773 19
Jan Jongboom 3:ce2322965a27 20 #define debug_msg(...) if (debug) output.printf(__VA_ARGS__)
Jan Jongboom 3:ce2322965a27 21
janjongboom 0:9fa3f3028773 22 #include <map>
janjongboom 0:9fa3f3028773 23 #include <string>
janjongboom 0:9fa3f3028773 24 #include <vector>
janjongboom 0:9fa3f3028773 25 #include "mbed-client-wrapper.h"
janjongboom 0:9fa3f3028773 26
janjongboom 0:9fa3f3028773 27 using namespace std;
janjongboom 0:9fa3f3028773 28
Jan Jongboom 3:ce2322965a27 29 class SimpleResourceBase {
Jan Jongboom 3:ce2322965a27 30 public:
janjongboom 10:3fecd642d506 31 virtual void update(string v) {}
Jan Jongboom 3:ce2322965a27 32 };
Jan Jongboom 3:ce2322965a27 33
janjongboom 0:9fa3f3028773 34 class SimpleMbedClientBase {
janjongboom 0:9fa3f3028773 35 public:
Jan Jongboom 3:ce2322965a27 36 SimpleMbedClientBase(bool aDebug = true)
Jan Jongboom 3:ce2322965a27 37 : output(USBTX, USBRX), debug(aDebug)
Jan Jongboom 3:ce2322965a27 38 {
Jan Jongboom 3:ce2322965a27 39
janjongboom 0:9fa3f3028773 40 }
Jan Jongboom 3:ce2322965a27 41
janjongboom 0:9fa3f3028773 42 ~SimpleMbedClientBase() {}
janjongboom 0:9fa3f3028773 43
janjongboom 0:9fa3f3028773 44 struct MbedClientOptions get_default_options() {
janjongboom 0:9fa3f3028773 45 struct MbedClientOptions options;
janjongboom 0:9fa3f3028773 46 options.Manufacturer = "Manufacturer_String";
janjongboom 0:9fa3f3028773 47 options.Type = "Type_String";
janjongboom 0:9fa3f3028773 48 options.ModelNumber = "ModelNumber_String";
janjongboom 0:9fa3f3028773 49 options.SerialNumber = "SerialNumber_String";
janjongboom 0:9fa3f3028773 50 options.DeviceType = "test";
Jan Jongboom 14:680c2a46cc8a 51 options.SocketMode = M2MInterface::TCP;
janjongboom 0:9fa3f3028773 52 options.ServerAddress = "coap://api.connector.mbed.com:5684";
Jan Jongboom 3:ce2322965a27 53
janjongboom 0:9fa3f3028773 54 return options;
janjongboom 0:9fa3f3028773 55 }
janjongboom 0:9fa3f3028773 56
Jan Jongboom 4:0f9eae5739dd 57 bool init(NetworkInterface* iface) {
Jan Jongboom 3:ce2322965a27 58 debug_msg("[SMC] Device name %s\r\n", MBED_ENDPOINT_NAME);
Jan Jongboom 3:ce2322965a27 59
janjongboom 0:9fa3f3028773 60 // Create endpoint interface to manage register and unregister
Jan Jongboom 3:ce2322965a27 61 client->create_interface(iface);
Jan Jongboom 3:ce2322965a27 62
janjongboom 0:9fa3f3028773 63 // Create Objects of varying types, see simpleclient.h for more details on implementation.
janjongboom 0:9fa3f3028773 64 M2MSecurity* register_object = client->create_register_object(); // server object specifying connector info
janjongboom 0:9fa3f3028773 65 M2MDevice* device_object = client->create_device_object(); // device resources object
Jan Jongboom 3:ce2322965a27 66
janjongboom 0:9fa3f3028773 67 // Create list of Objects to register
janjongboom 0:9fa3f3028773 68 M2MObjectList object_list;
Jan Jongboom 3:ce2322965a27 69
janjongboom 0:9fa3f3028773 70 // Add objects to list
janjongboom 0:9fa3f3028773 71 object_list.push_back(device_object);
Jan Jongboom 3:ce2322965a27 72
janjongboom 0:9fa3f3028773 73 map<string, M2MObject*>::iterator it;
janjongboom 0:9fa3f3028773 74 for (it = objects.begin(); it != objects.end(); it++)
janjongboom 0:9fa3f3028773 75 {
janjongboom 0:9fa3f3028773 76 object_list.push_back(it->second);
janjongboom 0:9fa3f3028773 77 }
Jan Jongboom 3:ce2322965a27 78
janjongboom 0:9fa3f3028773 79 // Set endpoint registration object
janjongboom 0:9fa3f3028773 80 client->set_register_object(register_object);
Jan Jongboom 3:ce2322965a27 81
janjongboom 0:9fa3f3028773 82 // Issue register command.
janjongboom 0:9fa3f3028773 83 client->test_register(register_object, object_list);
Jan Jongboom 3:ce2322965a27 84
janjongboom 0:9fa3f3028773 85 return true;
janjongboom 0:9fa3f3028773 86 }
janjongboom 0:9fa3f3028773 87
Jan Jongboom 4:0f9eae5739dd 88 bool setup(NetworkInterface* iface) {
Jan Jongboom 3:ce2322965a27 89 debug_msg("[SMC] In mbed_client_setup\r\n");
janjongboom 0:9fa3f3028773 90 if (client) {
Jan Jongboom 3:ce2322965a27 91 debug_msg("[SMC] [ERROR] mbed_client_setup called, but mbed_client is already instantiated\r\n");
janjongboom 0:9fa3f3028773 92 return false;
janjongboom 0:9fa3f3028773 93 }
Jan Jongboom 3:ce2322965a27 94
janjongboom 0:9fa3f3028773 95 struct MbedClientOptions options = get_default_options();
Jan Jongboom 3:ce2322965a27 96
Jan Jongboom 12:26810c6b58e1 97 Callback<void(string)> updateFp(this, &SimpleMbedClientBase::resource_updated);
Jan Jongboom 3:ce2322965a27 98 client = new MbedClient(options, updateFp, debug);
Jan Jongboom 3:ce2322965a27 99
janjongboom 0:9fa3f3028773 100 return init(iface);
janjongboom 0:9fa3f3028773 101 }
janjongboom 0:9fa3f3028773 102
Jan Jongboom 4:0f9eae5739dd 103 bool setup(MbedClientOptions options, NetworkInterface* iface) {
janjongboom 0:9fa3f3028773 104 if (client) {
Jan Jongboom 3:ce2322965a27 105 debug_msg("[SMC] [ERROR] mbed_client_setup called, but mbed_client is already instantiated\r\n");
janjongboom 0:9fa3f3028773 106 return false;
janjongboom 0:9fa3f3028773 107 }
Jan Jongboom 3:ce2322965a27 108
Jan Jongboom 12:26810c6b58e1 109 Callback<void(string)> updateFp(this, &SimpleMbedClientBase::resource_updated);
Jan Jongboom 3:ce2322965a27 110 client = new MbedClient(options, updateFp, debug);
Jan Jongboom 3:ce2322965a27 111
janjongboom 0:9fa3f3028773 112 return init(iface);
janjongboom 0:9fa3f3028773 113 }
janjongboom 0:9fa3f3028773 114
janjongboom 0:9fa3f3028773 115 void on_registered(void(*fn)(void)) {
Jan Jongboom 12:26810c6b58e1 116 Callback<void()> fp(fn);
janjongboom 0:9fa3f3028773 117 client->set_registered_function(fp);
janjongboom 0:9fa3f3028773 118 }
janjongboom 0:9fa3f3028773 119
Jan Jongboom 15:b7360c7e0f7f 120 void on_registered(Callback<void()> fp) {
Jan Jongboom 15:b7360c7e0f7f 121 client->set_registered_function(fp);
Jan Jongboom 15:b7360c7e0f7f 122 }
Jan Jongboom 15:b7360c7e0f7f 123
janjongboom 0:9fa3f3028773 124 template<typename T>
Jan Jongboom 3:ce2322965a27 125 void on_registered(T *object, void (T::*member)(void)) {
Jan Jongboom 12:26810c6b58e1 126 Callback<void()> fp(object, member);
janjongboom 0:9fa3f3028773 127 client->set_registered_function(fp);
janjongboom 0:9fa3f3028773 128 }
janjongboom 0:9fa3f3028773 129
janjongboom 0:9fa3f3028773 130 void on_unregistered(void(*fn)(void)) {
Jan Jongboom 12:26810c6b58e1 131 Callback<void()> fp(fn);
janjongboom 0:9fa3f3028773 132 client->set_unregistered_function(fp);
janjongboom 0:9fa3f3028773 133 }
janjongboom 0:9fa3f3028773 134
Jan Jongboom 15:b7360c7e0f7f 135 void on_unregistered(Callback<void()> fp) {
Jan Jongboom 15:b7360c7e0f7f 136 client->set_unregistered_function(fp);
Jan Jongboom 15:b7360c7e0f7f 137 }
Jan Jongboom 15:b7360c7e0f7f 138
janjongboom 0:9fa3f3028773 139 template<typename T>
Jan Jongboom 3:ce2322965a27 140 void on_unregistered(T *object, void (T::*member)(void)) {
Jan Jongboom 12:26810c6b58e1 141 Callback<void()> fp(object, member);
janjongboom 0:9fa3f3028773 142 client->set_unregistered_function(fp);
janjongboom 0:9fa3f3028773 143 }
janjongboom 0:9fa3f3028773 144
janjongboom 0:9fa3f3028773 145 bool define_function(const char* route, void(*fn)(void*)) {
janjongboom 0:9fa3f3028773 146 if (!define_resource_internal(route, string(), M2MBase::POST_ALLOWED, false)) {
janjongboom 0:9fa3f3028773 147 return false;
janjongboom 0:9fa3f3028773 148 }
Jan Jongboom 3:ce2322965a27 149
janjongboom 0:9fa3f3028773 150 string route_str(route);
janjongboom 0:9fa3f3028773 151 if (!resources.count(route_str)) {
Jan Jongboom 3:ce2322965a27 152 debug_msg("[SMC] [ERROR] Should be created, but no such route (%s)\r\n", route);
janjongboom 0:9fa3f3028773 153 return false;
janjongboom 0:9fa3f3028773 154 }
Jan Jongboom 3:ce2322965a27 155
Jan Jongboom 3:ce2322965a27 156 resources[route_str]->set_execute_function(execute_callback_2(fn));
janjongboom 0:9fa3f3028773 157 return true;
janjongboom 0:9fa3f3028773 158 }
janjongboom 0:9fa3f3028773 159
janjongboom 0:9fa3f3028773 160 bool define_function(const char* route, execute_callback fn) {
janjongboom 0:9fa3f3028773 161 if (!define_resource_internal(route, string(), M2MBase::POST_ALLOWED, false)) {
janjongboom 0:9fa3f3028773 162 return false;
janjongboom 0:9fa3f3028773 163 }
Jan Jongboom 3:ce2322965a27 164
janjongboom 0:9fa3f3028773 165 string route_str(route);
janjongboom 0:9fa3f3028773 166 if (!resources.count(route_str)) {
Jan Jongboom 3:ce2322965a27 167 debug_msg("[SMC] [ERROR] Should be created, but no such route (%s)\r\n", route);
janjongboom 0:9fa3f3028773 168 return false;
janjongboom 0:9fa3f3028773 169 }
janjongboom 0:9fa3f3028773 170 // No clue why this is not working?! It works with class member, but not with static function...
janjongboom 0:9fa3f3028773 171 resources[route_str]->set_execute_function(fn);
janjongboom 0:9fa3f3028773 172 return true;
janjongboom 0:9fa3f3028773 173 }
Jan Jongboom 3:ce2322965a27 174
janjongboom 0:9fa3f3028773 175 string get(string route_str) {
janjongboom 0:9fa3f3028773 176 if (!resources.count(route_str)) {
Jan Jongboom 3:ce2322965a27 177 debug_msg("[SMC] [ERROR] No such route (%s)\r\n", route_str.c_str());
janjongboom 0:9fa3f3028773 178 return string();
janjongboom 0:9fa3f3028773 179 }
Jan Jongboom 3:ce2322965a27 180
janjongboom 2:0a015df677a4 181 // otherwise ask mbed Client...
janjongboom 2:0a015df677a4 182 uint8_t* buffIn = NULL;
janjongboom 0:9fa3f3028773 183 uint32_t sizeIn;
janjongboom 0:9fa3f3028773 184 resources[route_str]->get_value(buffIn, sizeIn);
Jan Jongboom 3:ce2322965a27 185
janjongboom 2:0a015df677a4 186 string s((char*)buffIn, sizeIn);
janjongboom 0:9fa3f3028773 187 return s;
janjongboom 0:9fa3f3028773 188 }
janjongboom 0:9fa3f3028773 189
janjongboom 0:9fa3f3028773 190 bool set(string route_str, string v) {
janjongboom 2:0a015df677a4 191 // Potentially set() happens in InterruptContext. That's not good.
janjongboom 0:9fa3f3028773 192 if (!resources.count(route_str)) {
Jan Jongboom 3:ce2322965a27 193 debug_msg("[SMC] [ERROR] No such route (%s)\r\n", route_str.c_str());
janjongboom 0:9fa3f3028773 194 return false;
janjongboom 0:9fa3f3028773 195 }
Jan Jongboom 3:ce2322965a27 196
Jan Jongboom 4:0f9eae5739dd 197 if (v.length() == 0) {
Jan Jongboom 4:0f9eae5739dd 198 resources[route_str]->clear_value();
Jan Jongboom 4:0f9eae5739dd 199 }
Jan Jongboom 4:0f9eae5739dd 200 else {
Jan Jongboom 4:0f9eae5739dd 201 resources[route_str]->set_value((uint8_t*)v.c_str(), v.length());
Jan Jongboom 4:0f9eae5739dd 202 }
janjongboom 2:0a015df677a4 203
janjongboom 0:9fa3f3028773 204 return true;
janjongboom 0:9fa3f3028773 205 }
janjongboom 0:9fa3f3028773 206
janjongboom 0:9fa3f3028773 207 bool set(string route, const int& v) {
Jan Jongboom 16:cb980bd39e32 208 char str[13];
Jan Jongboom 16:cb980bd39e32 209 sprintf(str, "%d", v);
Jan Jongboom 3:ce2322965a27 210
Jan Jongboom 16:cb980bd39e32 211 return set(route, string(str));
janjongboom 0:9fa3f3028773 212 }
janjongboom 0:9fa3f3028773 213
Jan Jongboom 16:cb980bd39e32 214 bool define_resource_internal(const char* route, string v, M2MBase::Operation opr, bool observable) {
janjongboom 0:9fa3f3028773 215 if (client) {
Jan Jongboom 3:ce2322965a27 216 debug_msg("[SMC] [ERROR] mbed_client_define_resource, Can only define resources before mbed_client_setup is called!\r\n");
janjongboom 0:9fa3f3028773 217 return false;
janjongboom 0:9fa3f3028773 218 }
Jan Jongboom 3:ce2322965a27 219
janjongboom 0:9fa3f3028773 220 vector<string> segments = parse_route(route);
janjongboom 0:9fa3f3028773 221 if (segments.size() != 3) {
Jan Jongboom 3:ce2322965a27 222 debug_msg("[SMC] [ERROR] mbed_client_define_resource, Route needs to have three segments, split by '/' (%s)\r\n", route);
janjongboom 0:9fa3f3028773 223 return false;
janjongboom 0:9fa3f3028773 224 }
janjongboom 0:9fa3f3028773 225
Jan Jongboom 3:ce2322965a27 226 // segments[1] should be one digit and numeric
janjongboom 10:3fecd642d506 227 char n = segments.at(1).c_str()[0];
janjongboom 10:3fecd642d506 228 if (n < '0' || n > '9') {
Jan Jongboom 3:ce2322965a27 229 debug_msg("[SMC] [ERROR] mbed_client_define_resource, second route segment should be numeric, but was not (%s)\r\n", route);
Jan Jongboom 3:ce2322965a27 230 return false;
Jan Jongboom 3:ce2322965a27 231 }
Jan Jongboom 3:ce2322965a27 232
Jan Jongboom 3:ce2322965a27 233 int inst_id = atoi(segments.at(1).c_str());
Jan Jongboom 3:ce2322965a27 234
janjongboom 0:9fa3f3028773 235 M2MObjectInstance* inst;
janjongboom 0:9fa3f3028773 236 if (objectInstances.count(segments.at(0))) {
janjongboom 0:9fa3f3028773 237 inst = objectInstances[segments.at(0)];
janjongboom 0:9fa3f3028773 238 }
janjongboom 0:9fa3f3028773 239 else {
janjongboom 0:9fa3f3028773 240 M2MObject* obj = M2MInterfaceFactory::create_object(segments.at(0).c_str());
janjongboom 0:9fa3f3028773 241 inst = obj->create_object_instance(inst_id);
janjongboom 0:9fa3f3028773 242 objects.insert(std::pair<string, M2MObject*>(segments.at(0), obj));
janjongboom 0:9fa3f3028773 243 objectInstances.insert(std::pair<string, M2MObjectInstance*>(segments.at(0), inst));
janjongboom 0:9fa3f3028773 244 }
Jan Jongboom 3:ce2322965a27 245
janjongboom 0:9fa3f3028773 246 // @todo check if the resource exists yet
janjongboom 0:9fa3f3028773 247 M2MResource* res = inst->create_dynamic_resource(segments.at(2).c_str(), "",
janjongboom 0:9fa3f3028773 248 M2MResourceInstance::STRING, observable);
janjongboom 0:9fa3f3028773 249 res->set_operation(opr);
janjongboom 0:9fa3f3028773 250 res->set_value((uint8_t*)v.c_str(), v.length());
Jan Jongboom 3:ce2322965a27 251
janjongboom 0:9fa3f3028773 252 string route_str(route);
janjongboom 2:0a015df677a4 253 resources.insert(pair<string, M2MResource*>(route_str, res));
Jan Jongboom 3:ce2322965a27 254
janjongboom 0:9fa3f3028773 255 return true;
janjongboom 0:9fa3f3028773 256 }
Jan Jongboom 3:ce2322965a27 257
janjongboom 2:0a015df677a4 258 void keep_alive() {
janjongboom 2:0a015df677a4 259 client->test_update_register();
janjongboom 2:0a015df677a4 260 }
Jan Jongboom 3:ce2322965a27 261
Jan Jongboom 3:ce2322965a27 262 void register_update_callback(string route, SimpleResourceBase* simpleResource) {
Jan Jongboom 3:ce2322965a27 263 updateValues[route] = simpleResource;
Jan Jongboom 3:ce2322965a27 264 }
Jan Jongboom 3:ce2322965a27 265
Jan Jongboom 6:a1a766d45957 266 M2MResource* get_resource(string route) {
Jan Jongboom 6:a1a766d45957 267 if (!resources.count(route)) {
Jan Jongboom 6:a1a766d45957 268 debug_msg("[SMC] [ERROR] No such route (%s)\r\n", route.c_str());
Jan Jongboom 6:a1a766d45957 269 return NULL;
Jan Jongboom 6:a1a766d45957 270 }
Jan Jongboom 6:a1a766d45957 271
Jan Jongboom 6:a1a766d45957 272 return resources[route];
Jan Jongboom 6:a1a766d45957 273 }
Jan Jongboom 6:a1a766d45957 274
janjongboom 0:9fa3f3028773 275 private:
janjongboom 0:9fa3f3028773 276 vector<string> parse_route(const char* route) {
Jan Jongboom 16:cb980bd39e32 277 const string s(route);
janjongboom 0:9fa3f3028773 278 vector<string> v;
Jan Jongboom 16:cb980bd39e32 279
Jan Jongboom 16:cb980bd39e32 280 split(s, '/', v);
Jan Jongboom 16:cb980bd39e32 281
Jan Jongboom 16:cb980bd39e32 282 return v;
Jan Jongboom 16:cb980bd39e32 283 }
Jan Jongboom 16:cb980bd39e32 284
Jan Jongboom 16:cb980bd39e32 285 void split(const string& s, char delim, vector<string>& v) {
Jan Jongboom 16:cb980bd39e32 286 size_t i = 0;
Jan Jongboom 16:cb980bd39e32 287 size_t pos = s.find(delim);
Jan Jongboom 16:cb980bd39e32 288 while (pos != string::npos) {
Jan Jongboom 16:cb980bd39e32 289 v.push_back(s.substr(i, pos - i));
Jan Jongboom 16:cb980bd39e32 290 i = ++pos;
Jan Jongboom 16:cb980bd39e32 291 pos = s.find(delim, pos);
Jan Jongboom 16:cb980bd39e32 292
Jan Jongboom 16:cb980bd39e32 293 if (pos == string::npos) {
Jan Jongboom 16:cb980bd39e32 294 v.push_back(s.substr(i, s.length()));
Jan Jongboom 16:cb980bd39e32 295 }
janjongboom 0:9fa3f3028773 296 }
janjongboom 0:9fa3f3028773 297 }
janjongboom 0:9fa3f3028773 298
Jan Jongboom 3:ce2322965a27 299 void resource_updated(string uri) {
Jan Jongboom 3:ce2322965a27 300 if (updateValues.count(uri) == 0) return;
Jan Jongboom 3:ce2322965a27 301
Jan Jongboom 3:ce2322965a27 302 string v = get(uri);
Jan Jongboom 3:ce2322965a27 303 if (v.empty()) return;
Jan Jongboom 3:ce2322965a27 304
Jan Jongboom 3:ce2322965a27 305 updateValues[uri]->update(v);
Jan Jongboom 3:ce2322965a27 306 }
Jan Jongboom 3:ce2322965a27 307
janjongboom 0:9fa3f3028773 308 Serial output;
Jan Jongboom 3:ce2322965a27 309
janjongboom 0:9fa3f3028773 310 MbedClient* client;
janjongboom 0:9fa3f3028773 311 map<string, M2MObject*> objects;
janjongboom 0:9fa3f3028773 312 map<string, M2MObjectInstance*> objectInstances;
janjongboom 0:9fa3f3028773 313 map<string, M2MResource*> resources;
janjongboom 2:0a015df677a4 314
Jan Jongboom 3:ce2322965a27 315 bool debug;
Jan Jongboom 3:ce2322965a27 316
Jan Jongboom 3:ce2322965a27 317 map<string, SimpleResourceBase*> updateValues;
janjongboom 0:9fa3f3028773 318 };
janjongboom 0:9fa3f3028773 319
Jan Jongboom 3:ce2322965a27 320 class SimpleResourceString : public SimpleResourceBase {
janjongboom 0:9fa3f3028773 321 public:
Jan Jongboom 12:26810c6b58e1 322 SimpleResourceString(SimpleMbedClientBase* aSimpleClient, string aRoute, Callback<void(string)> aOnUpdate) :
Jan Jongboom 3:ce2322965a27 323 simpleClient(aSimpleClient), route(aRoute), onUpdate(aOnUpdate) {}
janjongboom 0:9fa3f3028773 324
janjongboom 0:9fa3f3028773 325 string operator=(const string& newValue) {
janjongboom 0:9fa3f3028773 326 simpleClient->set(route, newValue);
janjongboom 0:9fa3f3028773 327 return newValue;
janjongboom 0:9fa3f3028773 328 };
janjongboom 0:9fa3f3028773 329 operator string() const {
janjongboom 0:9fa3f3028773 330 return simpleClient->get(route);
janjongboom 0:9fa3f3028773 331 };
janjongboom 0:9fa3f3028773 332
Jan Jongboom 3:ce2322965a27 333 virtual void update(string v) {
Jan Jongboom 3:ce2322965a27 334 if (onUpdate) onUpdate(v);
Jan Jongboom 3:ce2322965a27 335 }
Jan Jongboom 3:ce2322965a27 336
Jan Jongboom 6:a1a766d45957 337 M2MResource* get_resource() {
Jan Jongboom 6:a1a766d45957 338 return simpleClient->get_resource(route);
Jan Jongboom 6:a1a766d45957 339 }
Jan Jongboom 6:a1a766d45957 340
janjongboom 0:9fa3f3028773 341 private:
janjongboom 0:9fa3f3028773 342 SimpleMbedClientBase* simpleClient;
janjongboom 0:9fa3f3028773 343 string route;
Jan Jongboom 12:26810c6b58e1 344 Callback<void(string)> onUpdate;
janjongboom 0:9fa3f3028773 345 };
janjongboom 0:9fa3f3028773 346
Jan Jongboom 3:ce2322965a27 347 class SimpleResourceInt : public SimpleResourceBase {
janjongboom 0:9fa3f3028773 348 public:
Jan Jongboom 12:26810c6b58e1 349 SimpleResourceInt(SimpleMbedClientBase* aSimpleClient, string aRoute, Callback<void(int)> aOnUpdate) :
Jan Jongboom 3:ce2322965a27 350 simpleClient(aSimpleClient), route(aRoute), onUpdate(aOnUpdate) {}
janjongboom 0:9fa3f3028773 351
janjongboom 0:9fa3f3028773 352 int operator=(int newValue) {
janjongboom 0:9fa3f3028773 353 simpleClient->set(route, newValue);
janjongboom 0:9fa3f3028773 354 return newValue;
janjongboom 0:9fa3f3028773 355 };
janjongboom 0:9fa3f3028773 356 operator int() const {
janjongboom 0:9fa3f3028773 357 string v = simpleClient->get(route);
janjongboom 0:9fa3f3028773 358 if (v.empty()) return 0;
Jan Jongboom 3:ce2322965a27 359
janjongboom 0:9fa3f3028773 360 return atoi((const char*)v.c_str());
janjongboom 0:9fa3f3028773 361 };
janjongboom 0:9fa3f3028773 362
Jan Jongboom 3:ce2322965a27 363 virtual void update(string v) {
Jan Jongboom 3:ce2322965a27 364 if (!onUpdate) return;
Jan Jongboom 3:ce2322965a27 365
Jan Jongboom 3:ce2322965a27 366 onUpdate(atoi((const char*)v.c_str()));
Jan Jongboom 3:ce2322965a27 367 }
Jan Jongboom 3:ce2322965a27 368
Jan Jongboom 6:a1a766d45957 369 M2MResource* get_resource() {
Jan Jongboom 6:a1a766d45957 370 return simpleClient->get_resource(route);
Jan Jongboom 6:a1a766d45957 371 }
Jan Jongboom 6:a1a766d45957 372
janjongboom 0:9fa3f3028773 373 private:
janjongboom 0:9fa3f3028773 374 SimpleMbedClientBase* simpleClient;
janjongboom 0:9fa3f3028773 375 string route;
Jan Jongboom 12:26810c6b58e1 376 Callback<void(int)> onUpdate;
janjongboom 0:9fa3f3028773 377 };
janjongboom 0:9fa3f3028773 378
janjongboom 0:9fa3f3028773 379 class SimpleMbedClient : public SimpleMbedClientBase {
janjongboom 0:9fa3f3028773 380 public:
janjongboom 1:75015f627e89 381
janjongboom 1:75015f627e89 382 // @todo: macro this up
janjongboom 1:75015f627e89 383
janjongboom 1:75015f627e89 384 SimpleResourceString define_resource(
Jan Jongboom 3:ce2322965a27 385 const char* route,
Jan Jongboom 3:ce2322965a27 386 string v,
Jan Jongboom 3:ce2322965a27 387 M2MBase::Operation opr = M2MBase::GET_PUT_ALLOWED,
janjongboom 1:75015f627e89 388 bool observable = true,
Jan Jongboom 12:26810c6b58e1 389 Callback<void(string)> onUpdate = NULL)
janjongboom 1:75015f627e89 390 {
Jan Jongboom 3:ce2322965a27 391 SimpleResourceString* simpleResource = new SimpleResourceString(this, route, onUpdate);
janjongboom 0:9fa3f3028773 392 bool res = define_resource_internal(route, v, opr, observable);
Jan Jongboom 3:ce2322965a27 393 if (!res) {
Jan Jongboom 3:ce2322965a27 394 printf("Error while creating %s\n", route);
Jan Jongboom 3:ce2322965a27 395 }
Jan Jongboom 3:ce2322965a27 396 else {
Jan Jongboom 3:ce2322965a27 397 register_update_callback(route, simpleResource);
Jan Jongboom 3:ce2322965a27 398 }
Jan Jongboom 3:ce2322965a27 399 return *simpleResource;
janjongboom 0:9fa3f3028773 400 }
janjongboom 1:75015f627e89 401
janjongboom 1:75015f627e89 402 SimpleResourceString define_resource(
Jan Jongboom 3:ce2322965a27 403 const char* route,
Jan Jongboom 3:ce2322965a27 404 string v,
Jan Jongboom 3:ce2322965a27 405 M2MBase::Operation opr,
janjongboom 1:75015f627e89 406 bool observable,
Jan Jongboom 3:ce2322965a27 407 void(*onUpdate)(string))
janjongboom 1:75015f627e89 408 {
Jan Jongboom 12:26810c6b58e1 409 Callback<void(string)> fp;
janjongboom 1:75015f627e89 410 fp.attach(onUpdate);
janjongboom 1:75015f627e89 411 return define_resource(route, v, opr, observable, fp);
janjongboom 1:75015f627e89 412 }
Jan Jongboom 3:ce2322965a27 413
janjongboom 1:75015f627e89 414 SimpleResourceString define_resource(
Jan Jongboom 3:ce2322965a27 415 const char* route,
janjongboom 1:75015f627e89 416 string v,
Jan Jongboom 12:26810c6b58e1 417 Callback<void(string)> onUpdate)
janjongboom 1:75015f627e89 418 {
janjongboom 1:75015f627e89 419 return define_resource(route, v, M2MBase::GET_PUT_ALLOWED, true, onUpdate);
janjongboom 1:75015f627e89 420 }
janjongboom 1:75015f627e89 421
janjongboom 1:75015f627e89 422 SimpleResourceString define_resource(
Jan Jongboom 3:ce2322965a27 423 const char* route,
janjongboom 1:75015f627e89 424 string v,
Jan Jongboom 3:ce2322965a27 425 void(*onUpdate)(string))
janjongboom 1:75015f627e89 426 {
Jan Jongboom 12:26810c6b58e1 427 Callback<void(string)> fp;
janjongboom 1:75015f627e89 428 fp.attach(onUpdate);
janjongboom 1:75015f627e89 429 return define_resource(route, v, M2MBase::GET_PUT_ALLOWED, true, fp);
janjongboom 1:75015f627e89 430 }
Jan Jongboom 3:ce2322965a27 431
janjongboom 1:75015f627e89 432 SimpleResourceInt define_resource(
Jan Jongboom 3:ce2322965a27 433 const char* route,
Jan Jongboom 3:ce2322965a27 434 int v,
Jan Jongboom 3:ce2322965a27 435 M2MBase::Operation opr = M2MBase::GET_PUT_ALLOWED,
janjongboom 1:75015f627e89 436 bool observable = true,
Jan Jongboom 12:26810c6b58e1 437 Callback<void(int)> onUpdate = NULL)
janjongboom 1:75015f627e89 438 {
Jan Jongboom 3:ce2322965a27 439 SimpleResourceInt* simpleResource = new SimpleResourceInt(this, route, onUpdate);
Jan Jongboom 3:ce2322965a27 440
Jan Jongboom 16:cb980bd39e32 441 char str[13];
Jan Jongboom 16:cb980bd39e32 442 sprintf(str, "%d", v);
Jan Jongboom 16:cb980bd39e32 443
Jan Jongboom 16:cb980bd39e32 444 bool res = define_resource_internal(route, string(str), opr, observable);
Jan Jongboom 3:ce2322965a27 445 if (!res) {
Jan Jongboom 3:ce2322965a27 446 printf("Error while creating %s\n", route);
Jan Jongboom 3:ce2322965a27 447 }
Jan Jongboom 3:ce2322965a27 448 else {
Jan Jongboom 3:ce2322965a27 449 register_update_callback(route, simpleResource);
Jan Jongboom 3:ce2322965a27 450 }
Jan Jongboom 3:ce2322965a27 451 return *simpleResource;
janjongboom 0:9fa3f3028773 452 }
Jan Jongboom 3:ce2322965a27 453
janjongboom 1:75015f627e89 454 SimpleResourceInt define_resource(
Jan Jongboom 3:ce2322965a27 455 const char* route,
Jan Jongboom 3:ce2322965a27 456 int v,
Jan Jongboom 3:ce2322965a27 457 M2MBase::Operation opr,
janjongboom 1:75015f627e89 458 bool observable,
Jan Jongboom 3:ce2322965a27 459 void(*onUpdate)(int))
janjongboom 1:75015f627e89 460 {
Jan Jongboom 12:26810c6b58e1 461 Callback<void(int)> fp;
janjongboom 1:75015f627e89 462 fp.attach(onUpdate);
janjongboom 1:75015f627e89 463 return define_resource(route, v, opr, observable, fp);
janjongboom 1:75015f627e89 464 }
Jan Jongboom 3:ce2322965a27 465
janjongboom 1:75015f627e89 466 SimpleResourceInt define_resource(
Jan Jongboom 3:ce2322965a27 467 const char* route,
janjongboom 1:75015f627e89 468 int v,
Jan Jongboom 12:26810c6b58e1 469 Callback<void(int)> onUpdate)
janjongboom 1:75015f627e89 470 {
janjongboom 1:75015f627e89 471 return define_resource(route, v, M2MBase::GET_PUT_ALLOWED, true, onUpdate);
janjongboom 1:75015f627e89 472 }
janjongboom 1:75015f627e89 473
janjongboom 1:75015f627e89 474 SimpleResourceInt define_resource(
Jan Jongboom 3:ce2322965a27 475 const char* route,
janjongboom 1:75015f627e89 476 int v,
Jan Jongboom 3:ce2322965a27 477 void(*onUpdate)(int))
janjongboom 1:75015f627e89 478 {
Jan Jongboom 12:26810c6b58e1 479 Callback<void(int)> fp;
janjongboom 1:75015f627e89 480 fp.attach(onUpdate);
janjongboom 1:75015f627e89 481 return define_resource(route, v, M2MBase::GET_PUT_ALLOWED, true, fp);
janjongboom 1:75015f627e89 482 }
janjongboom 0:9fa3f3028773 483 };
janjongboom 0:9fa3f3028773 484
Jan Jongboom 3:ce2322965a27 485 #endif // __SIMPLE_MBED_CLIENT_H__