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:
Fri Jul 01 13:56:44 2016 +0200
Revision:
6:a1a766d45957
Parent:
4:0f9eae5739dd
Child:
7:8a05fbad93d1
Add a way of accessing underlying M2MResource

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:
Jan Jongboom 3:ce2322965a27 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";
janjongboom 0:9fa3f3028773 52 options.SocketMode = M2MInterface::UDP;
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 // @todo: no idea if this works
janjongboom 0:9fa3f3028773 87 Ticker updateRegister;
janjongboom 0:9fa3f3028773 88 updateRegister.attach(client, &MbedClient::test_update_register, 25.0f);
Jan Jongboom 3:ce2322965a27 89
janjongboom 0:9fa3f3028773 90 return true;
janjongboom 0:9fa3f3028773 91 }
janjongboom 0:9fa3f3028773 92
Jan Jongboom 4:0f9eae5739dd 93 bool setup(NetworkInterface* iface) {
Jan Jongboom 3:ce2322965a27 94 debug_msg("[SMC] In mbed_client_setup\r\n");
janjongboom 0:9fa3f3028773 95 if (client) {
Jan Jongboom 3:ce2322965a27 96 debug_msg("[SMC] [ERROR] mbed_client_setup called, but mbed_client is already instantiated\r\n");
janjongboom 0:9fa3f3028773 97 return false;
janjongboom 0:9fa3f3028773 98 }
Jan Jongboom 3:ce2322965a27 99
janjongboom 0:9fa3f3028773 100 struct MbedClientOptions options = get_default_options();
Jan Jongboom 3:ce2322965a27 101
Jan Jongboom 3:ce2322965a27 102 FP1<void, string> updateFp(this, &SimpleMbedClientBase::resource_updated);
Jan Jongboom 3:ce2322965a27 103 client = new MbedClient(options, updateFp, debug);
Jan Jongboom 3:ce2322965a27 104
janjongboom 0:9fa3f3028773 105 return init(iface);
janjongboom 0:9fa3f3028773 106 }
janjongboom 0:9fa3f3028773 107
Jan Jongboom 4:0f9eae5739dd 108 bool setup(MbedClientOptions options, NetworkInterface* iface) {
janjongboom 0:9fa3f3028773 109 if (client) {
Jan Jongboom 3:ce2322965a27 110 debug_msg("[SMC] [ERROR] mbed_client_setup called, but mbed_client is already instantiated\r\n");
janjongboom 0:9fa3f3028773 111 return false;
janjongboom 0:9fa3f3028773 112 }
Jan Jongboom 3:ce2322965a27 113
Jan Jongboom 3:ce2322965a27 114 FP1<void, string> updateFp(this, &SimpleMbedClientBase::resource_updated);
Jan Jongboom 3:ce2322965a27 115 client = new MbedClient(options, updateFp, debug);
Jan Jongboom 3:ce2322965a27 116
janjongboom 0:9fa3f3028773 117 return init(iface);
janjongboom 0:9fa3f3028773 118 }
janjongboom 0:9fa3f3028773 119
janjongboom 0:9fa3f3028773 120 void on_registered(void(*fn)(void)) {
janjongboom 0:9fa3f3028773 121 FunctionPointer fp(fn);
janjongboom 0:9fa3f3028773 122 client->set_registered_function(fp);
janjongboom 0:9fa3f3028773 123 }
janjongboom 0:9fa3f3028773 124
janjongboom 0:9fa3f3028773 125 template<typename T>
Jan Jongboom 3:ce2322965a27 126 void on_registered(T *object, void (T::*member)(void)) {
janjongboom 0:9fa3f3028773 127 FunctionPointer 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)) {
janjongboom 0:9fa3f3028773 132 FunctionPointer fp(fn);
janjongboom 0:9fa3f3028773 133 client->set_unregistered_function(fp);
janjongboom 0:9fa3f3028773 134 }
janjongboom 0:9fa3f3028773 135
janjongboom 0:9fa3f3028773 136 template<typename T>
Jan Jongboom 3:ce2322965a27 137 void on_unregistered(T *object, void (T::*member)(void)) {
janjongboom 0:9fa3f3028773 138 FunctionPointer fp(object, member);
janjongboom 0:9fa3f3028773 139 client->set_unregistered_function(fp);
janjongboom 0:9fa3f3028773 140 }
janjongboom 0:9fa3f3028773 141
janjongboom 0:9fa3f3028773 142 bool define_function(const char* route, void(*fn)(void*)) {
janjongboom 0:9fa3f3028773 143 if (!define_resource_internal(route, string(), M2MBase::POST_ALLOWED, false)) {
janjongboom 0:9fa3f3028773 144 return false;
janjongboom 0:9fa3f3028773 145 }
Jan Jongboom 3:ce2322965a27 146
janjongboom 0:9fa3f3028773 147 string route_str(route);
janjongboom 0:9fa3f3028773 148 if (!resources.count(route_str)) {
Jan Jongboom 3:ce2322965a27 149 debug_msg("[SMC] [ERROR] Should be created, but no such route (%s)\r\n", route);
janjongboom 0:9fa3f3028773 150 return false;
janjongboom 0:9fa3f3028773 151 }
Jan Jongboom 3:ce2322965a27 152
Jan Jongboom 3:ce2322965a27 153 resources[route_str]->set_execute_function(execute_callback_2(fn));
janjongboom 0:9fa3f3028773 154 return true;
janjongboom 0:9fa3f3028773 155 }
janjongboom 0:9fa3f3028773 156
janjongboom 0:9fa3f3028773 157 bool define_function(const char* route, execute_callback fn) {
janjongboom 0:9fa3f3028773 158 if (!define_resource_internal(route, string(), M2MBase::POST_ALLOWED, false)) {
janjongboom 0:9fa3f3028773 159 return false;
janjongboom 0:9fa3f3028773 160 }
Jan Jongboom 3:ce2322965a27 161
janjongboom 0:9fa3f3028773 162 string route_str(route);
janjongboom 0:9fa3f3028773 163 if (!resources.count(route_str)) {
Jan Jongboom 3:ce2322965a27 164 debug_msg("[SMC] [ERROR] Should be created, but no such route (%s)\r\n", route);
janjongboom 0:9fa3f3028773 165 return false;
janjongboom 0:9fa3f3028773 166 }
janjongboom 0:9fa3f3028773 167 // No clue why this is not working?! It works with class member, but not with static function...
janjongboom 0:9fa3f3028773 168 resources[route_str]->set_execute_function(fn);
janjongboom 0:9fa3f3028773 169 return true;
janjongboom 0:9fa3f3028773 170 }
Jan Jongboom 3:ce2322965a27 171
janjongboom 0:9fa3f3028773 172 string get(string route_str) {
janjongboom 0:9fa3f3028773 173 if (!resources.count(route_str)) {
Jan Jongboom 3:ce2322965a27 174 debug_msg("[SMC] [ERROR] No such route (%s)\r\n", route_str.c_str());
janjongboom 0:9fa3f3028773 175 return string();
janjongboom 0:9fa3f3028773 176 }
Jan Jongboom 3:ce2322965a27 177
janjongboom 2:0a015df677a4 178 // otherwise ask mbed Client...
janjongboom 2:0a015df677a4 179 uint8_t* buffIn = NULL;
janjongboom 0:9fa3f3028773 180 uint32_t sizeIn;
janjongboom 0:9fa3f3028773 181 resources[route_str]->get_value(buffIn, sizeIn);
Jan Jongboom 3:ce2322965a27 182
janjongboom 2:0a015df677a4 183 string s((char*)buffIn, sizeIn);
janjongboom 0:9fa3f3028773 184 return s;
janjongboom 0:9fa3f3028773 185 }
janjongboom 0:9fa3f3028773 186
janjongboom 0:9fa3f3028773 187 bool set(string route_str, string v) {
janjongboom 2:0a015df677a4 188 // Potentially set() happens in InterruptContext. That's not good.
janjongboom 0:9fa3f3028773 189 if (!resources.count(route_str)) {
Jan Jongboom 3:ce2322965a27 190 debug_msg("[SMC] [ERROR] No such route (%s)\r\n", route_str.c_str());
janjongboom 0:9fa3f3028773 191 return false;
janjongboom 0:9fa3f3028773 192 }
Jan Jongboom 3:ce2322965a27 193
Jan Jongboom 4:0f9eae5739dd 194 if (v.length() == 0) {
Jan Jongboom 4:0f9eae5739dd 195 resources[route_str]->clear_value();
Jan Jongboom 4:0f9eae5739dd 196 }
Jan Jongboom 4:0f9eae5739dd 197 else {
Jan Jongboom 4:0f9eae5739dd 198 resources[route_str]->set_value((uint8_t*)v.c_str(), v.length());
Jan Jongboom 4:0f9eae5739dd 199 }
janjongboom 2:0a015df677a4 200
janjongboom 0:9fa3f3028773 201 return true;
janjongboom 0:9fa3f3028773 202 }
janjongboom 0:9fa3f3028773 203
janjongboom 0:9fa3f3028773 204 bool set(string route, const int& v) {
janjongboom 0:9fa3f3028773 205 stringstream ss;
janjongboom 0:9fa3f3028773 206 ss << v;
janjongboom 0:9fa3f3028773 207 std::string stringified = ss.str();
Jan Jongboom 3:ce2322965a27 208
janjongboom 0:9fa3f3028773 209 return set(route, stringified);
janjongboom 0:9fa3f3028773 210 }
janjongboom 0:9fa3f3028773 211
janjongboom 0:9fa3f3028773 212 bool define_resource_internal(const char* route, std::string v, M2MBase::Operation opr, bool observable) {
janjongboom 0:9fa3f3028773 213 if (client) {
Jan Jongboom 3:ce2322965a27 214 debug_msg("[SMC] [ERROR] mbed_client_define_resource, Can only define resources before mbed_client_setup is called!\r\n");
janjongboom 0:9fa3f3028773 215 return false;
janjongboom 0:9fa3f3028773 216 }
Jan Jongboom 3:ce2322965a27 217
janjongboom 0:9fa3f3028773 218 vector<string> segments = parse_route(route);
janjongboom 0:9fa3f3028773 219 if (segments.size() != 3) {
Jan Jongboom 3:ce2322965a27 220 debug_msg("[SMC] [ERROR] mbed_client_define_resource, Route needs to have three segments, split by '/' (%s)\r\n", route);
janjongboom 0:9fa3f3028773 221 return false;
janjongboom 0:9fa3f3028773 222 }
janjongboom 0:9fa3f3028773 223
Jan Jongboom 3:ce2322965a27 224 // segments[1] should be one digit and numeric
Jan Jongboom 3:ce2322965a27 225 if (!isdigit(segments.at(1).c_str()[0])) {
Jan Jongboom 3:ce2322965a27 226 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 227 return false;
Jan Jongboom 3:ce2322965a27 228 }
Jan Jongboom 3:ce2322965a27 229
Jan Jongboom 3:ce2322965a27 230 int inst_id = atoi(segments.at(1).c_str());
Jan Jongboom 3:ce2322965a27 231
janjongboom 0:9fa3f3028773 232 M2MObjectInstance* inst;
janjongboom 0:9fa3f3028773 233 if (objectInstances.count(segments.at(0))) {
Jan Jongboom 3:ce2322965a27 234 debug_msg("Found object... %s\r\n", segments.at(0).c_str());
janjongboom 0:9fa3f3028773 235 inst = objectInstances[segments.at(0)];
janjongboom 0:9fa3f3028773 236 }
janjongboom 0:9fa3f3028773 237 else {
Jan Jongboom 3:ce2322965a27 238 debug_msg("Create new object... %s\r\n", segments.at(0).c_str());
janjongboom 0:9fa3f3028773 239 M2MObject* obj = M2MInterfaceFactory::create_object(segments.at(0).c_str());
janjongboom 0:9fa3f3028773 240 inst = obj->create_object_instance(inst_id);
janjongboom 0:9fa3f3028773 241 objects.insert(std::pair<string, M2MObject*>(segments.at(0), obj));
janjongboom 0:9fa3f3028773 242 objectInstances.insert(std::pair<string, M2MObjectInstance*>(segments.at(0), inst));
janjongboom 0:9fa3f3028773 243 }
Jan Jongboom 3:ce2322965a27 244
janjongboom 0:9fa3f3028773 245 // @todo check if the resource exists yet
janjongboom 0:9fa3f3028773 246 M2MResource* res = inst->create_dynamic_resource(segments.at(2).c_str(), "",
janjongboom 0:9fa3f3028773 247 M2MResourceInstance::STRING, observable);
janjongboom 0:9fa3f3028773 248 res->set_operation(opr);
janjongboom 0:9fa3f3028773 249 res->set_value((uint8_t*)v.c_str(), v.length());
Jan Jongboom 3:ce2322965a27 250
janjongboom 0:9fa3f3028773 251 string route_str(route);
janjongboom 2:0a015df677a4 252 resources.insert(pair<string, M2MResource*>(route_str, res));
Jan Jongboom 3:ce2322965a27 253
janjongboom 0:9fa3f3028773 254 return true;
janjongboom 0:9fa3f3028773 255 }
Jan Jongboom 3:ce2322965a27 256
janjongboom 2:0a015df677a4 257 void keep_alive() {
janjongboom 2:0a015df677a4 258 client->test_update_register();
janjongboom 2:0a015df677a4 259 }
Jan Jongboom 3:ce2322965a27 260
Jan Jongboom 3:ce2322965a27 261 void register_update_callback(string route, SimpleResourceBase* simpleResource) {
Jan Jongboom 3:ce2322965a27 262 updateValues[route] = simpleResource;
Jan Jongboom 3:ce2322965a27 263 }
Jan Jongboom 3:ce2322965a27 264
Jan Jongboom 6:a1a766d45957 265 M2MResource* get_resource(string route) {
Jan Jongboom 6:a1a766d45957 266 if (!resources.count(route)) {
Jan Jongboom 6:a1a766d45957 267 debug_msg("[SMC] [ERROR] No such route (%s)\r\n", route.c_str());
Jan Jongboom 6:a1a766d45957 268 return NULL;
Jan Jongboom 6:a1a766d45957 269 }
Jan Jongboom 6:a1a766d45957 270
Jan Jongboom 6:a1a766d45957 271 return resources[route];
Jan Jongboom 6:a1a766d45957 272 }
Jan Jongboom 6:a1a766d45957 273
janjongboom 0:9fa3f3028773 274 private:
janjongboom 0:9fa3f3028773 275 vector<string> parse_route(const char* route) {
janjongboom 0:9fa3f3028773 276 string s(route);
janjongboom 0:9fa3f3028773 277 vector<string> v;
janjongboom 0:9fa3f3028773 278 stringstream ss(s);
janjongboom 0:9fa3f3028773 279 string item;
janjongboom 0:9fa3f3028773 280 while (getline(ss, item, '/')) {
janjongboom 0:9fa3f3028773 281 v.push_back(item);
janjongboom 0:9fa3f3028773 282 }
janjongboom 0:9fa3f3028773 283 return v;
janjongboom 0:9fa3f3028773 284 }
janjongboom 0:9fa3f3028773 285
Jan Jongboom 3:ce2322965a27 286 void resource_updated(string uri) {
Jan Jongboom 3:ce2322965a27 287 if (updateValues.count(uri) == 0) return;
Jan Jongboom 3:ce2322965a27 288
Jan Jongboom 3:ce2322965a27 289 string v = get(uri);
Jan Jongboom 3:ce2322965a27 290 if (v.empty()) return;
Jan Jongboom 3:ce2322965a27 291
Jan Jongboom 3:ce2322965a27 292 updateValues[uri]->update(v);
Jan Jongboom 3:ce2322965a27 293 }
Jan Jongboom 3:ce2322965a27 294
janjongboom 0:9fa3f3028773 295 Serial output;
Jan Jongboom 3:ce2322965a27 296
janjongboom 0:9fa3f3028773 297 MbedClient* client;
janjongboom 0:9fa3f3028773 298 map<string, M2MObject*> objects;
janjongboom 0:9fa3f3028773 299 map<string, M2MObjectInstance*> objectInstances;
janjongboom 0:9fa3f3028773 300 map<string, M2MResource*> resources;
janjongboom 2:0a015df677a4 301
Jan Jongboom 3:ce2322965a27 302 bool debug;
Jan Jongboom 3:ce2322965a27 303
Jan Jongboom 3:ce2322965a27 304 map<string, SimpleResourceBase*> updateValues;
janjongboom 0:9fa3f3028773 305 };
janjongboom 0:9fa3f3028773 306
Jan Jongboom 3:ce2322965a27 307 class SimpleResourceString : public SimpleResourceBase {
janjongboom 0:9fa3f3028773 308 public:
Jan Jongboom 3:ce2322965a27 309 SimpleResourceString(SimpleMbedClientBase* aSimpleClient, string aRoute, FunctionPointerArg1<void, string> aOnUpdate) :
Jan Jongboom 3:ce2322965a27 310 simpleClient(aSimpleClient), route(aRoute), onUpdate(aOnUpdate) {}
janjongboom 0:9fa3f3028773 311
janjongboom 0:9fa3f3028773 312 string operator=(const string& newValue) {
janjongboom 0:9fa3f3028773 313 simpleClient->set(route, newValue);
janjongboom 0:9fa3f3028773 314 return newValue;
janjongboom 0:9fa3f3028773 315 };
janjongboom 0:9fa3f3028773 316 operator string() const {
janjongboom 0:9fa3f3028773 317 return simpleClient->get(route);
janjongboom 0:9fa3f3028773 318 };
janjongboom 0:9fa3f3028773 319
Jan Jongboom 3:ce2322965a27 320 virtual void update(string v) {
Jan Jongboom 3:ce2322965a27 321 if (onUpdate) onUpdate(v);
Jan Jongboom 3:ce2322965a27 322 }
Jan Jongboom 3:ce2322965a27 323
Jan Jongboom 6:a1a766d45957 324 M2MResource* get_resource() {
Jan Jongboom 6:a1a766d45957 325 return simpleClient->get_resource(route);
Jan Jongboom 6:a1a766d45957 326 }
Jan Jongboom 6:a1a766d45957 327
janjongboom 0:9fa3f3028773 328 private:
janjongboom 0:9fa3f3028773 329 SimpleMbedClientBase* simpleClient;
janjongboom 0:9fa3f3028773 330 string route;
Jan Jongboom 3:ce2322965a27 331 FunctionPointerArg1<void, string> onUpdate;
janjongboom 0:9fa3f3028773 332 };
janjongboom 0:9fa3f3028773 333
Jan Jongboom 3:ce2322965a27 334 class SimpleResourceInt : public SimpleResourceBase {
janjongboom 0:9fa3f3028773 335 public:
Jan Jongboom 3:ce2322965a27 336 SimpleResourceInt(SimpleMbedClientBase* aSimpleClient, string aRoute, FunctionPointerArg1<void, int> aOnUpdate) :
Jan Jongboom 3:ce2322965a27 337 simpleClient(aSimpleClient), route(aRoute), onUpdate(aOnUpdate) {}
janjongboom 0:9fa3f3028773 338
janjongboom 0:9fa3f3028773 339 int operator=(int newValue) {
janjongboom 0:9fa3f3028773 340 simpleClient->set(route, newValue);
janjongboom 0:9fa3f3028773 341 return newValue;
janjongboom 0:9fa3f3028773 342 };
janjongboom 0:9fa3f3028773 343 operator int() const {
janjongboom 0:9fa3f3028773 344 string v = simpleClient->get(route);
janjongboom 0:9fa3f3028773 345 if (v.empty()) return 0;
Jan Jongboom 3:ce2322965a27 346
janjongboom 0:9fa3f3028773 347 return atoi((const char*)v.c_str());
janjongboom 0:9fa3f3028773 348 };
janjongboom 0:9fa3f3028773 349
Jan Jongboom 3:ce2322965a27 350 virtual void update(string v) {
Jan Jongboom 3:ce2322965a27 351 if (!onUpdate) return;
Jan Jongboom 3:ce2322965a27 352
Jan Jongboom 3:ce2322965a27 353 onUpdate(atoi((const char*)v.c_str()));
Jan Jongboom 3:ce2322965a27 354 }
Jan Jongboom 3:ce2322965a27 355
Jan Jongboom 6:a1a766d45957 356 M2MResource* get_resource() {
Jan Jongboom 6:a1a766d45957 357 return simpleClient->get_resource(route);
Jan Jongboom 6:a1a766d45957 358 }
Jan Jongboom 6:a1a766d45957 359
janjongboom 0:9fa3f3028773 360 private:
janjongboom 0:9fa3f3028773 361 SimpleMbedClientBase* simpleClient;
janjongboom 0:9fa3f3028773 362 string route;
Jan Jongboom 3:ce2322965a27 363 FunctionPointerArg1<void, int> onUpdate;
janjongboom 0:9fa3f3028773 364 };
janjongboom 0:9fa3f3028773 365
janjongboom 0:9fa3f3028773 366 class SimpleMbedClient : public SimpleMbedClientBase {
janjongboom 0:9fa3f3028773 367 public:
janjongboom 1:75015f627e89 368
janjongboom 1:75015f627e89 369 // @todo: macro this up
janjongboom 1:75015f627e89 370
janjongboom 1:75015f627e89 371 SimpleResourceString define_resource(
Jan Jongboom 3:ce2322965a27 372 const char* route,
Jan Jongboom 3:ce2322965a27 373 string v,
Jan Jongboom 3:ce2322965a27 374 M2MBase::Operation opr = M2MBase::GET_PUT_ALLOWED,
janjongboom 1:75015f627e89 375 bool observable = true,
janjongboom 1:75015f627e89 376 FunctionPointerArg1<void, string> onUpdate = NULL)
janjongboom 1:75015f627e89 377 {
Jan Jongboom 3:ce2322965a27 378 SimpleResourceString* simpleResource = new SimpleResourceString(this, route, onUpdate);
janjongboom 0:9fa3f3028773 379 bool res = define_resource_internal(route, v, opr, observable);
Jan Jongboom 3:ce2322965a27 380 if (!res) {
Jan Jongboom 3:ce2322965a27 381 printf("Error while creating %s\n", route);
Jan Jongboom 3:ce2322965a27 382 }
Jan Jongboom 3:ce2322965a27 383 else {
Jan Jongboom 3:ce2322965a27 384 register_update_callback(route, simpleResource);
Jan Jongboom 3:ce2322965a27 385 }
Jan Jongboom 3:ce2322965a27 386 return *simpleResource;
janjongboom 0:9fa3f3028773 387 }
janjongboom 1:75015f627e89 388
janjongboom 1:75015f627e89 389 SimpleResourceString define_resource(
Jan Jongboom 3:ce2322965a27 390 const char* route,
Jan Jongboom 3:ce2322965a27 391 string v,
Jan Jongboom 3:ce2322965a27 392 M2MBase::Operation opr,
janjongboom 1:75015f627e89 393 bool observable,
Jan Jongboom 3:ce2322965a27 394 void(*onUpdate)(string))
janjongboom 1:75015f627e89 395 {
janjongboom 1:75015f627e89 396 FunctionPointerArg1<void, string> fp;
janjongboom 1:75015f627e89 397 fp.attach(onUpdate);
janjongboom 1:75015f627e89 398 return define_resource(route, v, opr, observable, fp);
janjongboom 1:75015f627e89 399 }
Jan Jongboom 3:ce2322965a27 400
janjongboom 1:75015f627e89 401 SimpleResourceString define_resource(
Jan Jongboom 3:ce2322965a27 402 const char* route,
janjongboom 1:75015f627e89 403 string v,
Jan Jongboom 3:ce2322965a27 404 FunctionPointerArg1<void, string> onUpdate = NULL)
janjongboom 1:75015f627e89 405 {
janjongboom 1:75015f627e89 406 return define_resource(route, v, M2MBase::GET_PUT_ALLOWED, true, onUpdate);
janjongboom 1:75015f627e89 407 }
janjongboom 1:75015f627e89 408
janjongboom 1:75015f627e89 409 SimpleResourceString define_resource(
Jan Jongboom 3:ce2322965a27 410 const char* route,
janjongboom 1:75015f627e89 411 string v,
Jan Jongboom 3:ce2322965a27 412 void(*onUpdate)(string))
janjongboom 1:75015f627e89 413 {
janjongboom 1:75015f627e89 414 FunctionPointerArg1<void, string> fp;
janjongboom 1:75015f627e89 415 fp.attach(onUpdate);
janjongboom 1:75015f627e89 416 return define_resource(route, v, M2MBase::GET_PUT_ALLOWED, true, fp);
janjongboom 1:75015f627e89 417 }
Jan Jongboom 3:ce2322965a27 418
janjongboom 1:75015f627e89 419 SimpleResourceInt define_resource(
Jan Jongboom 3:ce2322965a27 420 const char* route,
Jan Jongboom 3:ce2322965a27 421 int v,
Jan Jongboom 3:ce2322965a27 422 M2MBase::Operation opr = M2MBase::GET_PUT_ALLOWED,
janjongboom 1:75015f627e89 423 bool observable = true,
Jan Jongboom 3:ce2322965a27 424 FunctionPointerArg1<void, int> onUpdate = NULL)
janjongboom 1:75015f627e89 425 {
Jan Jongboom 3:ce2322965a27 426 SimpleResourceInt* simpleResource = new SimpleResourceInt(this, route, onUpdate);
Jan Jongboom 3:ce2322965a27 427
janjongboom 0:9fa3f3028773 428 stringstream ss;
janjongboom 0:9fa3f3028773 429 ss << v;
janjongboom 0:9fa3f3028773 430 std::string stringified = ss.str();
janjongboom 0:9fa3f3028773 431 bool res = define_resource_internal(route, stringified, opr, observable);
Jan Jongboom 3:ce2322965a27 432 if (!res) {
Jan Jongboom 3:ce2322965a27 433 printf("Error while creating %s\n", route);
Jan Jongboom 3:ce2322965a27 434 }
Jan Jongboom 3:ce2322965a27 435 else {
Jan Jongboom 3:ce2322965a27 436 register_update_callback(route, simpleResource);
Jan Jongboom 3:ce2322965a27 437 }
Jan Jongboom 3:ce2322965a27 438 return *simpleResource;
janjongboom 0:9fa3f3028773 439 }
Jan Jongboom 3:ce2322965a27 440
janjongboom 1:75015f627e89 441 SimpleResourceInt define_resource(
Jan Jongboom 3:ce2322965a27 442 const char* route,
Jan Jongboom 3:ce2322965a27 443 int v,
Jan Jongboom 3:ce2322965a27 444 M2MBase::Operation opr,
janjongboom 1:75015f627e89 445 bool observable,
Jan Jongboom 3:ce2322965a27 446 void(*onUpdate)(int))
janjongboom 1:75015f627e89 447 {
janjongboom 1:75015f627e89 448 FunctionPointerArg1<void, int> fp;
janjongboom 1:75015f627e89 449 fp.attach(onUpdate);
janjongboom 1:75015f627e89 450 return define_resource(route, v, opr, observable, fp);
janjongboom 1:75015f627e89 451 }
Jan Jongboom 3:ce2322965a27 452
janjongboom 1:75015f627e89 453 SimpleResourceInt define_resource(
Jan Jongboom 3:ce2322965a27 454 const char* route,
janjongboom 1:75015f627e89 455 int v,
Jan Jongboom 3:ce2322965a27 456 FunctionPointerArg1<void, int> onUpdate = NULL)
janjongboom 1:75015f627e89 457 {
janjongboom 1:75015f627e89 458 return define_resource(route, v, M2MBase::GET_PUT_ALLOWED, true, onUpdate);
janjongboom 1:75015f627e89 459 }
janjongboom 1:75015f627e89 460
janjongboom 1:75015f627e89 461 SimpleResourceInt define_resource(
Jan Jongboom 3:ce2322965a27 462 const char* route,
janjongboom 1:75015f627e89 463 int v,
Jan Jongboom 3:ce2322965a27 464 void(*onUpdate)(int))
janjongboom 1:75015f627e89 465 {
janjongboom 1:75015f627e89 466 FunctionPointerArg1<void, int> fp;
janjongboom 1:75015f627e89 467 fp.attach(onUpdate);
janjongboom 1:75015f627e89 468 return define_resource(route, v, M2MBase::GET_PUT_ALLOWED, true, fp);
janjongboom 1:75015f627e89 469 }
janjongboom 0:9fa3f3028773 470 };
janjongboom 0:9fa3f3028773 471
Jan Jongboom 3:ce2322965a27 472 #endif // __SIMPLE_MBED_CLIENT_H__