Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
simple-mbed-cloud-client/mbed-cloud-client/source/SimpleM2MResource.cpp
- Committer:
- JimCarver
- Date:
- 2018-10-12
- Revision:
- 0:6b753f761943
File content as of revision 0:6b753f761943:
// ----------------------------------------------------------------------------
// Copyright 2016-2017 ARM Ltd.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------------------------------------------------------
#include "mbed-cloud-client/SimpleM2MResource.h"
#include "mbed-trace/mbed_trace.h"
#include <ctype.h>
#include<stdio.h>
#define TRACE_GROUP "mClt"
SimpleM2MResourceBase::SimpleM2MResourceBase()
: _client(NULL), _route("")
{
tr_debug("SimpleM2MResourceBase::SimpleM2MResourceBase()");
}
SimpleM2MResourceBase::SimpleM2MResourceBase(MbedCloudClient* client, string route)
: _client(client),_route(route)
{
tr_debug("SimpleM2MResourceBase::SimpleM2MResourceBase(), resource name %s\r\n", _route.c_str());
}
SimpleM2MResourceBase::~SimpleM2MResourceBase()
{
}
bool SimpleM2MResourceBase::define_resource_internal(std::string v, M2MBase::Operation opr, bool observable)
{
tr_debug("SimpleM2MResourceBase::define_resource_internal(), resource name %s!\r\n", _route.c_str());
vector<string> segments = parse_route(_route.c_str());
if (segments.size() != 3) {
tr_debug("[SimpleM2MResourceBase] [ERROR] define_resource_internal(), Route needs to have three segments, split by '/' (%s)\r\n", _route.c_str());
return false;
}
// segments[1] should be one digit and numeric
if (!isdigit(segments.at(1).c_str()[0])) {
tr_debug("[SimpleM2MResourceBase] [ERROR] define_resource_internal(), second route segment should be numeric, but was not (%s)\r\n", _route.c_str());
return false;
}
int inst_id = atoi(segments.at(1).c_str());
// Check if object exists
M2MObject* obj;
map<string,M2MObject*>::iterator obj_it = _client->_objects.find(segments[0]) ;
if(obj_it != _client->_objects.end()) {
tr_debug("Found object... %s\r\n", segments.at(0).c_str());
obj = obj_it->second;
} else {
tr_debug("Create new object... %s\r\n", segments.at(0).c_str());
obj = M2MInterfaceFactory::create_object(segments.at(0).c_str());
if (!obj) {
return false;
}
_client->_objects.insert(std::pair<string, M2MObject*>(segments.at(0), obj));
}
// Check if object instance exists
M2MObjectInstance* inst = obj->object_instance(inst_id);
if(!inst) {
tr_debug("Create new object instance... %s\r\n", segments.at(1).c_str());
inst = obj->create_object_instance(inst_id);
if(!inst) {
return false;
}
}
// @todo check if the resource exists yet
M2MResource* res = inst->resource(segments.at(2).c_str());
if(!res) {
res = inst->create_dynamic_resource(segments.at(2).c_str(), "",
M2MResourceInstance::STRING, observable);
if(!res) {
return false;
}
res->set_operation(opr);
res->set_value((uint8_t*)v.c_str(), v.length());
_client->_resources.insert(pair<string, M2MResource*>(_route, res));
_client->register_update_callback(_route, this);
}
return true;
}
vector<string> SimpleM2MResourceBase::parse_route(const char* route)
{
string s(route);
vector<string> v;
std::size_t found = s.find_first_of("/");
while (found!=std::string::npos) {
v.push_back(s.substr(0,found));
s = s.substr(found+1);
found=s.find_first_of("/");
if(found == std::string::npos) {
v.push_back(s);
}
}
return v;
}
string SimpleM2MResourceBase::get() const
{
tr_debug("SimpleM2MResourceBase::get() resource (%s)", _route.c_str());
if (!_client->_resources.count(_route)) {
tr_debug("[SimpleM2MResourceBase] [ERROR] No such route (%s)\r\n", _route.c_str());
return string();
}
// otherwise ask mbed Client...
uint8_t* buffIn = NULL;
uint32_t sizeIn;
_client->_resources[_route]->get_value(buffIn, sizeIn);
string s((char*)buffIn, sizeIn);
tr_debug("SimpleM2MResourceBase::get() resource value (%s)", s.c_str());
free(buffIn);
return s;
}
bool SimpleM2MResourceBase::set(string v)
{
// Potentially set() happens in InterruptContext. That's not good.
tr_debug("SimpleM2MResourceBase::set() resource (%s)", _route.c_str());
if (!_client->_resources.count(_route)) {
tr_debug("[SimpleM2MResourceBase] [ERROR] No such route (%s)\r\n", _route.c_str());
return false;
}
if (v.length() == 0) {
_client->_resources[_route]->clear_value();
}
else {
_client->_resources[_route]->set_value((uint8_t*)v.c_str(), v.length());
}
return true;
}
bool SimpleM2MResourceBase::set(const int& v)
{
char buffer[20];
int size = sprintf(buffer,"%d",v);
std::string stringified(buffer,size);
return set(stringified);
}
bool SimpleM2MResourceBase::set_post_function(void(*fn)(void*))
{
//TODO: Check the resource exists with right operation being set or append the operation into it.
M2MResource *resource = get_resource();
if(!resource) {
return false;
}
M2MBase::Operation op = resource->operation();
op = (M2MBase::Operation)(op | M2MBase::POST_ALLOWED);
resource->set_operation(op);
_client->_resources[_route]->set_execute_function(execute_callback_2(fn));
return true;
}
bool SimpleM2MResourceBase::set_post_function(execute_callback fn)
{
//TODO: Check the resource exists with right operation being set or append the operation into it.
M2MResource *resource = get_resource();
if(!resource) {
return false;
}
M2MBase::Operation op = resource->operation();
op = (M2MBase::Operation)(op | M2MBase::POST_ALLOWED);
resource->set_operation(op);
// No clue why this is not working?! It works with class member, but not with static function...
_client->_resources[_route]->set_execute_function(fn);
return true;
}
M2MResource* SimpleM2MResourceBase::get_resource()
{
if (!_client->_resources.count(_route)) {
tr_debug("[SimpleM2MResourceBase] [ERROR] No such route (%s)\r\n", _route.c_str());
return NULL;
}
return _client->_resources[_route];
}
SimpleM2MResourceString::SimpleM2MResourceString(MbedCloudClient* client,
const char* route,
string v,
M2MBase::Operation opr,
bool observable,
FP1<void, string> on_update)
: SimpleM2MResourceBase(client,route),_on_update(on_update)
{
tr_debug("SimpleM2MResourceString::SimpleM2MResourceString() creating (%s)\r\n", route);
define_resource_internal(v, opr, observable);
}
SimpleM2MResourceString::SimpleM2MResourceString(MbedCloudClient* client,
const char* route,
string v,
M2MBase::Operation opr,
bool observable,
void(*on_update)(string))
: SimpleM2MResourceBase(client,route)
{
tr_debug("SimpleM2MResourceString::SimpleM2MResourceString() overloaded creating (%s)\r\n", route);
FP1<void, string> fp;
fp.attach(on_update);
_on_update = fp;
define_resource_internal(v, opr, observable);
}
SimpleM2MResourceString::~SimpleM2MResourceString()
{
}
string SimpleM2MResourceString::operator=(const string& new_value)
{
tr_debug("SimpleM2MResourceString::operator=()");
set(new_value);
return new_value;
}
SimpleM2MResourceString::operator string() const
{
tr_debug("SimpleM2MResourceString::operator string()");
string value = get();
return value;
}
void SimpleM2MResourceString::update()
{
string v = get();
_on_update(v);
}
SimpleM2MResourceInt::SimpleM2MResourceInt(MbedCloudClient* client,
const char* route,
int v,
M2MBase::Operation opr,
bool observable,
FP1<void, int> on_update)
: SimpleM2MResourceBase(client,route),_on_update(on_update)
{
tr_debug("SimpleM2MResourceInt::SimpleM2MResourceInt() creating (%s)\r\n", route);
char buffer[20];
int size = sprintf(buffer,"%d",v);
std::string stringified(buffer,size);
define_resource_internal(stringified, opr, observable);
}
SimpleM2MResourceInt::SimpleM2MResourceInt(MbedCloudClient* client,
const char* route,
int v,
M2MBase::Operation opr,
bool observable,
void(*on_update)(int))
: SimpleM2MResourceBase(client,route)
{
tr_debug("SimpleM2MResourceInt::SimpleM2MResourceInt() overloaded creating (%s)\r\n", route);
FP1<void, int> fp;
fp.attach(on_update);
_on_update = fp;
char buffer[20];
int size = sprintf(buffer,"%d",v);
std::string stringified(buffer,size);
define_resource_internal(stringified, opr, observable);
}
SimpleM2MResourceInt::~SimpleM2MResourceInt()
{
}
int SimpleM2MResourceInt::operator=(int new_value)
{
set(new_value);
return new_value;
}
SimpleM2MResourceInt::operator int() const
{
string v = get();
if (v.empty()) return 0;
return atoi((const char*)v.c_str());
}
void SimpleM2MResourceInt::update()
{
string v = get();
if (v.empty()) {
_on_update(0);
} else {
_on_update(atoi((const char*)v.c_str()));
}
}