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:01:10 2017 +0100
Revision:
15:b7360c7e0f7f
Parent:
14:680c2a46cc8a
Child:
16:cb980bd39e32
Remove the keep_alive ticker from SimpleClient. Add Callback<void()> overloads for on_registered and on_unregistered.

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