leo hendrickson / Mbed OS example-Ethernet-mbed-Cloud-connect
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SimpleM2MResource.cpp Source File

SimpleM2MResource.cpp

00001 // ----------------------------------------------------------------------------
00002 // Copyright 2016-2017 ARM Ltd.
00003 //
00004 // SPDX-License-Identifier: Apache-2.0
00005 //
00006 // Licensed under the Apache License, Version 2.0 (the "License");
00007 // you may not use this file except in compliance with the License.
00008 // You may obtain a copy of the License at
00009 //
00010 //     http://www.apache.org/licenses/LICENSE-2.0
00011 //
00012 // Unless required by applicable law or agreed to in writing, software
00013 // distributed under the License is distributed on an "AS IS" BASIS,
00014 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 // See the License for the specific language governing permissions and
00016 // limitations under the License.
00017 // ----------------------------------------------------------------------------
00018 
00019 #include "mbed-cloud-client/SimpleM2MResource.h"
00020 
00021 #if MBED_CLOUD_CLIENT_STL_API
00022 
00023 #include "mbed-trace/mbed_trace.h"
00024 
00025 #include <ctype.h>
00026 #include <stdio.h>
00027 
00028 #define TRACE_GROUP "mClt"
00029 
00030 
00031 SimpleM2MResourceBase::SimpleM2MResourceBase()
00032 : _client(NULL), _route("")
00033 {
00034     tr_debug("SimpleM2MResourceBase::SimpleM2MResourceBase()");
00035 }
00036 
00037 SimpleM2MResourceBase::SimpleM2MResourceBase(MbedCloudClient* client, string route)
00038 : _client(client),_route(route)
00039 {
00040     tr_debug("SimpleM2MResourceBase::SimpleM2MResourceBase(), resource name %s\r\n", _route.c_str());
00041 }
00042 
00043 SimpleM2MResourceBase::~SimpleM2MResourceBase()
00044 {
00045 }
00046 
00047 bool SimpleM2MResourceBase::define_resource_internal(std::string v, M2MBase::Operation opr, bool observable)
00048 {
00049     tr_debug("SimpleM2MResourceBase::define_resource_internal(), resource name %s!\r\n", _route.c_str());
00050 
00051     vector<string> segments = parse_route(_route.c_str());
00052     if (segments.size() != 3) {
00053         tr_debug("[SimpleM2MResourceBase] [ERROR] define_resource_internal(), Route needs to have three segments, split by '/' (%s)\r\n", _route.c_str());
00054         return false;
00055     }
00056 
00057     // segments[1] should be one digit and numeric
00058     if (!isdigit(segments.at(1).c_str()[0])) {
00059         tr_debug("[SimpleM2MResourceBase] [ERROR] define_resource_internal(), second route segment should be numeric, but was not (%s)\r\n", _route.c_str());
00060         return false;
00061     }
00062 
00063     int inst_id = atoi(segments.at(1).c_str());
00064 
00065     // Check if object exists
00066     M2MObject* obj;
00067     map<string,M2MObject*>::iterator obj_it = _client->_objects.find(segments[0]) ;
00068     if(obj_it != _client->_objects.end()) {
00069       tr_debug("Found object... %s\r\n", segments.at(0).c_str());
00070       obj = obj_it->second;
00071     } else {
00072         tr_debug("Create new object... %s\r\n", segments.at(0).c_str());
00073         obj = M2MInterfaceFactory::create_object(segments.at(0).c_str());
00074         if (!obj) {
00075             return false;
00076         }
00077         _client->_objects.insert(std::pair<string, M2MObject*>(segments.at(0), obj));
00078     }
00079 
00080     // Check if object instance exists
00081     M2MObjectInstance* inst = obj->object_instance(inst_id);
00082     if(!inst) {
00083         tr_debug("Create new object instance... %s\r\n", segments.at(1).c_str());
00084         inst = obj->create_object_instance(inst_id);
00085         if(!inst) {
00086             return false;
00087         }
00088     }
00089 
00090     // @todo check if the resource exists yet
00091     M2MResource* res = inst->resource(segments.at(2).c_str());
00092     if(!res) {
00093         res = inst->create_dynamic_resource(segments.at(2).c_str(), "",
00094             M2MResourceInstance::STRING, observable);
00095         if(!res) {
00096             return false;
00097         }
00098         res->set_operation(opr);
00099         res->set_value((uint8_t*)v.c_str(), v.length());
00100 
00101         _client->_resources.insert(pair<string, M2MResource*>(_route, res));
00102         _client->register_update_callback(_route, this);
00103     }
00104 
00105     return true;
00106 }
00107 
00108 vector<string> SimpleM2MResourceBase::parse_route(const char* route)
00109 {
00110     string s(route);
00111     vector<string> v;
00112     std::size_t found = s.find_first_of("/");
00113 
00114     while (found!=std::string::npos) {
00115         v.push_back(s.substr(0,found));
00116         s = s.substr(found+1);
00117         found=s.find_first_of("/");
00118         if(found == std::string::npos) {
00119             v.push_back(s);
00120         }
00121     }
00122     return v;
00123 }
00124 
00125 string SimpleM2MResourceBase::get() const
00126 {
00127     tr_debug("SimpleM2MResourceBase::get() resource (%s)", _route.c_str());
00128     if (!_client->_resources.count(_route)) {
00129         tr_debug("[SimpleM2MResourceBase] [ERROR] No such route (%s)\r\n", _route.c_str());
00130         return string();
00131     }
00132 
00133     // otherwise ask mbed Client...
00134     uint8_t* buffIn = NULL;
00135     uint32_t sizeIn;
00136     _client->_resources[_route]->get_value(buffIn, sizeIn);
00137 
00138     string s((char*)buffIn, sizeIn);
00139     tr_debug("SimpleM2MResourceBase::get() resource value (%s)", s.c_str());
00140     free(buffIn);
00141     return s;
00142 }
00143 
00144 bool SimpleM2MResourceBase::set(string v)
00145 {
00146     // Potentially set() happens in InterruptContext. That's not good.
00147     tr_debug("SimpleM2MResourceBase::set() resource (%s)", _route.c_str());
00148     if (!_client->_resources.count(_route)) {
00149         tr_debug("[SimpleM2MResourceBase] [ERROR] No such route (%s)\r\n", _route.c_str());
00150         return false;
00151     }
00152 
00153     if (v.length() == 0) {
00154         _client->_resources[_route]->clear_value();
00155     }
00156     else {
00157         _client->_resources[_route]->set_value((uint8_t*)v.c_str(), v.length());
00158     }
00159 
00160     return true;
00161 }
00162 
00163 bool SimpleM2MResourceBase::set(const int& v)
00164 {
00165     char buffer[20];
00166     int size = sprintf(buffer,"%d",v);
00167     std::string stringified(buffer,size);
00168 
00169     return set(stringified);
00170 }
00171 
00172 bool SimpleM2MResourceBase::set_post_function(void(*fn)(void*))
00173 {
00174     //TODO: Check the resource exists with right operation being set or append the operation into it.
00175     M2MResource *resource = get_resource();
00176     if(!resource) {
00177         return false;
00178     }
00179     M2MBase::Operation op = resource->operation();
00180     op = (M2MBase::Operation)(op | M2MBase::POST_ALLOWED);
00181     resource->set_operation(op);
00182 
00183     _client->_resources[_route]->set_execute_function(execute_callback_2(fn));
00184     return true;
00185 }
00186 
00187 bool SimpleM2MResourceBase::set_post_function(execute_callback fn)
00188 {
00189     //TODO: Check the resource exists with right operation being set or append the operation into it.
00190     M2MResource *resource = get_resource();
00191     if(!resource) {
00192         return false;
00193     }
00194     M2MBase::Operation op = resource->operation();
00195     op = (M2MBase::Operation)(op | M2MBase::POST_ALLOWED);
00196     resource->set_operation(op);
00197 
00198     // No clue why this is not working?! It works with class member, but not with static function...
00199     _client->_resources[_route]->set_execute_function(fn);
00200     return true;
00201 }
00202 
00203 M2MResource* SimpleM2MResourceBase::get_resource()
00204 {
00205     if (!_client->_resources.count(_route)) {
00206         tr_debug("[SimpleM2MResourceBase] [ERROR] No such route (%s)\r\n", _route.c_str());
00207         return NULL;
00208     }
00209     return _client->_resources[_route];
00210 }
00211 
00212 SimpleM2MResourceString::SimpleM2MResourceString(MbedCloudClient* client,
00213                                const char* route,
00214                                string v,
00215                                M2MBase::Operation opr,
00216                                bool observable,
00217                                FP1<void, string>  on_update)
00218 : SimpleM2MResourceBase(client,route),_on_update(on_update)
00219 {
00220     tr_debug("SimpleM2MResourceString::SimpleM2MResourceString() creating (%s)\r\n", route);
00221     define_resource_internal(v, opr, observable);
00222 }
00223 
00224 SimpleM2MResourceString::SimpleM2MResourceString(MbedCloudClient* client,
00225                                const char* route,
00226                                string v,
00227                                M2MBase::Operation opr,
00228                                bool observable,
00229                                void(*on_update)(string))
00230 
00231 : SimpleM2MResourceBase(client,route)
00232 {
00233     tr_debug("SimpleM2MResourceString::SimpleM2MResourceString() overloaded creating (%s)\r\n", route);
00234     FP1<void, string>  fp;
00235     fp.attach(on_update);
00236     _on_update = fp;
00237     define_resource_internal(v, opr, observable);
00238 }
00239 
00240 SimpleM2MResourceString::~SimpleM2MResourceString()
00241 {
00242 }
00243 
00244 string SimpleM2MResourceString::operator=(const string& new_value)
00245 {
00246     tr_debug("SimpleM2MResourceString::operator=()");
00247     set(new_value);
00248     return new_value;
00249 }
00250 
00251 SimpleM2MResourceString::operator string() const
00252 {
00253     tr_debug("SimpleM2MResourceString::operator string()");
00254     string value = get();
00255     return value;
00256 }
00257 
00258 void SimpleM2MResourceString::update()
00259 {
00260     string v = get();
00261     _on_update(v);
00262 }
00263 
00264 SimpleM2MResourceInt::SimpleM2MResourceInt(MbedCloudClient* client,
00265                          const char* route,
00266                          int v,
00267                          M2MBase::Operation opr,
00268                          bool observable,
00269                          FP1<void, int>  on_update)
00270 : SimpleM2MResourceBase(client,route),_on_update(on_update)
00271 {
00272     tr_debug("SimpleM2MResourceInt::SimpleM2MResourceInt() creating (%s)\r\n", route);
00273     char buffer[20];
00274     int size = sprintf(buffer,"%d",v);
00275     std::string stringified(buffer,size);
00276     define_resource_internal(stringified, opr, observable);
00277 }
00278 
00279 SimpleM2MResourceInt::SimpleM2MResourceInt(MbedCloudClient* client,
00280                          const char* route,
00281                          int v,
00282                          M2MBase::Operation opr,
00283                          bool observable,
00284                          void(*on_update)(int))
00285 : SimpleM2MResourceBase(client,route)
00286 {
00287     tr_debug("SimpleM2MResourceInt::SimpleM2MResourceInt() overloaded creating (%s)\r\n", route);
00288     FP1<void, int>  fp;
00289     fp.attach(on_update);
00290     _on_update = fp;
00291     char buffer[20];
00292     int size = sprintf(buffer,"%d",v);
00293     std::string stringified(buffer,size);
00294     define_resource_internal(stringified, opr, observable);
00295 }
00296 
00297 SimpleM2MResourceInt::~SimpleM2MResourceInt()
00298 {
00299 }
00300 
00301 int SimpleM2MResourceInt::operator=(int new_value)
00302 {
00303     set(new_value);
00304     return new_value;
00305 }
00306 
00307 SimpleM2MResourceInt::operator int() const
00308 {
00309     string v = get();
00310     if (v.empty()) return 0;
00311 
00312     return atoi((const char*)v.c_str());
00313 }
00314 
00315 void SimpleM2MResourceInt::update()
00316 {
00317     string v = get();
00318     if (v.empty()) {
00319         _on_update(0);
00320     } else {
00321         _on_update(atoi((const char*)v.c_str()));
00322     }
00323 }
00324 #endif