Simulated product dispenser

Dependencies:   HTS221

Fork of mbed-cloud-workshop-connect-HTS221 by Jim Carver

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