FRDM K64F Metronome

Committer:
ram54288
Date:
Sun May 14 18:35:07 2017 +0000
Revision:
0:a2cb7295a1f7
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ram54288 0:a2cb7295a1f7 1 /*
ram54288 0:a2cb7295a1f7 2 * Copyright (c) 2015 ARM Limited. All rights reserved.
ram54288 0:a2cb7295a1f7 3 * SPDX-License-Identifier: Apache-2.0
ram54288 0:a2cb7295a1f7 4 * Licensed under the Apache License, Version 2.0 (the License); you may
ram54288 0:a2cb7295a1f7 5 * not use this file except in compliance with the License.
ram54288 0:a2cb7295a1f7 6 * You may obtain a copy of the License at
ram54288 0:a2cb7295a1f7 7 *
ram54288 0:a2cb7295a1f7 8 * http://www.apache.org/licenses/LICENSE-2.0
ram54288 0:a2cb7295a1f7 9 *
ram54288 0:a2cb7295a1f7 10 * Unless required by applicable law or agreed to in writing, software
ram54288 0:a2cb7295a1f7 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
ram54288 0:a2cb7295a1f7 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ram54288 0:a2cb7295a1f7 13 * See the License for the specific language governing permissions and
ram54288 0:a2cb7295a1f7 14 * limitations under the License.
ram54288 0:a2cb7295a1f7 15 */
ram54288 0:a2cb7295a1f7 16 #include <stdlib.h>
ram54288 0:a2cb7295a1f7 17 #include "mbed-client/m2mresource.h"
ram54288 0:a2cb7295a1f7 18 #include "mbed-client/m2mconstants.h"
ram54288 0:a2cb7295a1f7 19 #include "mbed-client/m2mobservationhandler.h"
ram54288 0:a2cb7295a1f7 20 #include "mbed-client/m2mobject.h"
ram54288 0:a2cb7295a1f7 21 #include "mbed-client/m2mobjectinstance.h"
ram54288 0:a2cb7295a1f7 22 #include "include/m2mreporthandler.h"
ram54288 0:a2cb7295a1f7 23 #include "include/nsdllinker.h"
ram54288 0:a2cb7295a1f7 24 #include "mbed-client/m2mblockmessage.h"
ram54288 0:a2cb7295a1f7 25 #include "mbed-trace/mbed_trace.h"
ram54288 0:a2cb7295a1f7 26
ram54288 0:a2cb7295a1f7 27 #define TRACE_GROUP "mClt"
ram54288 0:a2cb7295a1f7 28
ram54288 0:a2cb7295a1f7 29 M2MResourceInstance::M2MResourceInstance(M2MResource &parent,
ram54288 0:a2cb7295a1f7 30 const String &res_name,
ram54288 0:a2cb7295a1f7 31 const String &resource_type,
ram54288 0:a2cb7295a1f7 32 M2MResourceInstance::ResourceType type,
ram54288 0:a2cb7295a1f7 33 const uint16_t object_instance_id,
ram54288 0:a2cb7295a1f7 34 char* path,
ram54288 0:a2cb7295a1f7 35 bool external_blockwise_store)
ram54288 0:a2cb7295a1f7 36 : M2MBase(res_name,
ram54288 0:a2cb7295a1f7 37 M2MBase::Dynamic,
ram54288 0:a2cb7295a1f7 38 resource_type,
ram54288 0:a2cb7295a1f7 39 path,
ram54288 0:a2cb7295a1f7 40 external_blockwise_store),
ram54288 0:a2cb7295a1f7 41 _parent_resource(parent),
ram54288 0:a2cb7295a1f7 42 _value(NULL),
ram54288 0:a2cb7295a1f7 43 _value_length(0),
ram54288 0:a2cb7295a1f7 44 _block_message_data(NULL),
ram54288 0:a2cb7295a1f7 45 _execute_callback(NULL),
ram54288 0:a2cb7295a1f7 46 _resource_callback(NULL),
ram54288 0:a2cb7295a1f7 47 _execute_function_pointer(NULL),
ram54288 0:a2cb7295a1f7 48 _notification_sent_function_pointer(NULL),
ram54288 0:a2cb7295a1f7 49 _incoming_block_message_cb(NULL),
ram54288 0:a2cb7295a1f7 50 _outgoing_block_message_cb(NULL),
ram54288 0:a2cb7295a1f7 51 _notification_sent_callback(NULL),
ram54288 0:a2cb7295a1f7 52 _object_instance_id(object_instance_id),
ram54288 0:a2cb7295a1f7 53 _resource_type(type)
ram54288 0:a2cb7295a1f7 54 {
ram54288 0:a2cb7295a1f7 55 M2MBase::set_base_type(M2MBase::ResourceInstance);
ram54288 0:a2cb7295a1f7 56 }
ram54288 0:a2cb7295a1f7 57
ram54288 0:a2cb7295a1f7 58 M2MResourceInstance::M2MResourceInstance(M2MResource &parent,
ram54288 0:a2cb7295a1f7 59 const String &res_name,
ram54288 0:a2cb7295a1f7 60 const String &resource_type,
ram54288 0:a2cb7295a1f7 61 M2MResourceInstance::ResourceType type,
ram54288 0:a2cb7295a1f7 62 const uint8_t *value,
ram54288 0:a2cb7295a1f7 63 const uint8_t value_length,
ram54288 0:a2cb7295a1f7 64 const uint16_t object_instance_id,
ram54288 0:a2cb7295a1f7 65 char* path,
ram54288 0:a2cb7295a1f7 66 bool external_blockwise_store)
ram54288 0:a2cb7295a1f7 67 : M2MBase(res_name,
ram54288 0:a2cb7295a1f7 68 M2MBase::Static,
ram54288 0:a2cb7295a1f7 69 resource_type,
ram54288 0:a2cb7295a1f7 70 path,
ram54288 0:a2cb7295a1f7 71 external_blockwise_store),
ram54288 0:a2cb7295a1f7 72 _parent_resource(parent),
ram54288 0:a2cb7295a1f7 73 _value(NULL),
ram54288 0:a2cb7295a1f7 74 _value_length(0),
ram54288 0:a2cb7295a1f7 75 _block_message_data(NULL),
ram54288 0:a2cb7295a1f7 76 _execute_callback(NULL),
ram54288 0:a2cb7295a1f7 77 _resource_callback(NULL),
ram54288 0:a2cb7295a1f7 78 _execute_function_pointer(NULL),
ram54288 0:a2cb7295a1f7 79 _notification_sent_function_pointer(NULL),
ram54288 0:a2cb7295a1f7 80 _incoming_block_message_cb(NULL),
ram54288 0:a2cb7295a1f7 81 _outgoing_block_message_cb(NULL),
ram54288 0:a2cb7295a1f7 82 _notification_sent_callback(NULL),
ram54288 0:a2cb7295a1f7 83 _object_instance_id(object_instance_id),
ram54288 0:a2cb7295a1f7 84 _resource_type(type)
ram54288 0:a2cb7295a1f7 85 {
ram54288 0:a2cb7295a1f7 86 M2MBase::set_base_type(M2MBase::Resource);
ram54288 0:a2cb7295a1f7 87 if (mode() == M2MBase::Dynamic) {
ram54288 0:a2cb7295a1f7 88 if( value != NULL && value_length > 0 ) {
ram54288 0:a2cb7295a1f7 89 _value = alloc_string_copy(value, value_length);
ram54288 0:a2cb7295a1f7 90 if(_value) {
ram54288 0:a2cb7295a1f7 91 _value_length = value_length;
ram54288 0:a2cb7295a1f7 92 }
ram54288 0:a2cb7295a1f7 93 }
ram54288 0:a2cb7295a1f7 94 }
ram54288 0:a2cb7295a1f7 95 // Copy resource value to struct since static resources are handled in mbed-client-c
ram54288 0:a2cb7295a1f7 96 else if (mode() == M2MBase::Static) {
ram54288 0:a2cb7295a1f7 97 sn_nsdl_dynamic_resource_parameters_s* res = get_nsdl_resource();
ram54288 0:a2cb7295a1f7 98 sn_nsdl_static_resource_parameters_s* params = (sn_nsdl_static_resource_parameters_s*)res->static_resource_parameters;
ram54288 0:a2cb7295a1f7 99 params->resource = alloc_string_copy(value, value_length);
ram54288 0:a2cb7295a1f7 100 params->resourcelen = value_length;
ram54288 0:a2cb7295a1f7 101 }
ram54288 0:a2cb7295a1f7 102 else {
ram54288 0:a2cb7295a1f7 103 // Directory, not supported
ram54288 0:a2cb7295a1f7 104 }
ram54288 0:a2cb7295a1f7 105 }
ram54288 0:a2cb7295a1f7 106
ram54288 0:a2cb7295a1f7 107 M2MResourceInstance::M2MResourceInstance(M2MResource &parent,
ram54288 0:a2cb7295a1f7 108 const lwm2m_parameters_s* s,
ram54288 0:a2cb7295a1f7 109 M2MResourceInstance::ResourceType type,
ram54288 0:a2cb7295a1f7 110 const uint16_t object_instance_id)
ram54288 0:a2cb7295a1f7 111 : M2MBase(s),
ram54288 0:a2cb7295a1f7 112 _parent_resource(parent),
ram54288 0:a2cb7295a1f7 113 _value(NULL),
ram54288 0:a2cb7295a1f7 114 _value_length(0),
ram54288 0:a2cb7295a1f7 115 _block_message_data(NULL),
ram54288 0:a2cb7295a1f7 116 _execute_callback(NULL),
ram54288 0:a2cb7295a1f7 117 _resource_callback(NULL),
ram54288 0:a2cb7295a1f7 118 _execute_function_pointer(NULL),
ram54288 0:a2cb7295a1f7 119 _notification_sent_function_pointer(NULL),
ram54288 0:a2cb7295a1f7 120 _incoming_block_message_cb(NULL),
ram54288 0:a2cb7295a1f7 121 _outgoing_block_message_cb(NULL),
ram54288 0:a2cb7295a1f7 122 _notification_sent_callback(NULL),
ram54288 0:a2cb7295a1f7 123 _object_instance_id(object_instance_id),
ram54288 0:a2cb7295a1f7 124 _resource_type(type)
ram54288 0:a2cb7295a1f7 125 {
ram54288 0:a2cb7295a1f7 126 //TBD: put to flash, or parse from the uri_path!!!!
ram54288 0:a2cb7295a1f7 127 //same for the _object_instance_id.
ram54288 0:a2cb7295a1f7 128 // TBD: we dont need _value here, because in c-struct there is resource field!!!!
ram54288 0:a2cb7295a1f7 129 if( s->dynamic_resource_params->static_resource_parameters->resource != NULL &&
ram54288 0:a2cb7295a1f7 130 s->dynamic_resource_params->static_resource_parameters->resourcelen > 0 ) {
ram54288 0:a2cb7295a1f7 131 _value = alloc_string_copy(s->dynamic_resource_params->static_resource_parameters->resource,
ram54288 0:a2cb7295a1f7 132 s->dynamic_resource_params->static_resource_parameters->resourcelen);
ram54288 0:a2cb7295a1f7 133 if(_value) {
ram54288 0:a2cb7295a1f7 134 _value_length = s->dynamic_resource_params->static_resource_parameters->resourcelen;
ram54288 0:a2cb7295a1f7 135 }
ram54288 0:a2cb7295a1f7 136 }
ram54288 0:a2cb7295a1f7 137 //M2MBase::set_base_type(M2MBase::ResourceInstance);
ram54288 0:a2cb7295a1f7 138 }
ram54288 0:a2cb7295a1f7 139
ram54288 0:a2cb7295a1f7 140 M2MResourceInstance::~M2MResourceInstance()
ram54288 0:a2cb7295a1f7 141 {
ram54288 0:a2cb7295a1f7 142 free(_value);
ram54288 0:a2cb7295a1f7 143 delete _execute_function_pointer;
ram54288 0:a2cb7295a1f7 144 delete _execute_callback;
ram54288 0:a2cb7295a1f7 145 delete _notification_sent_function_pointer;
ram54288 0:a2cb7295a1f7 146 delete _incoming_block_message_cb;
ram54288 0:a2cb7295a1f7 147 delete _outgoing_block_message_cb;
ram54288 0:a2cb7295a1f7 148 delete _notification_sent_callback;
ram54288 0:a2cb7295a1f7 149 delete _block_message_data;
ram54288 0:a2cb7295a1f7 150 }
ram54288 0:a2cb7295a1f7 151
ram54288 0:a2cb7295a1f7 152 M2MBase::BaseType M2MResourceInstance::base_type() const
ram54288 0:a2cb7295a1f7 153 {
ram54288 0:a2cb7295a1f7 154 return M2MBase::base_type();
ram54288 0:a2cb7295a1f7 155 }
ram54288 0:a2cb7295a1f7 156
ram54288 0:a2cb7295a1f7 157 M2MResourceInstance::ResourceType M2MResourceInstance::resource_instance_type() const
ram54288 0:a2cb7295a1f7 158 {
ram54288 0:a2cb7295a1f7 159 return _resource_type;
ram54288 0:a2cb7295a1f7 160 }
ram54288 0:a2cb7295a1f7 161
ram54288 0:a2cb7295a1f7 162 bool M2MResourceInstance::handle_observation_attribute(const char *query)
ram54288 0:a2cb7295a1f7 163 {
ram54288 0:a2cb7295a1f7 164 tr_debug("M2MResourceInstance::handle_observation_attribute - is_under_observation(%d)", is_under_observation());
ram54288 0:a2cb7295a1f7 165 bool success = false;
ram54288 0:a2cb7295a1f7 166
ram54288 0:a2cb7295a1f7 167 M2MReportHandler *handler = M2MBase::report_handler();
ram54288 0:a2cb7295a1f7 168 if (!handler) {
ram54288 0:a2cb7295a1f7 169 handler = M2MBase::create_report_handler();
ram54288 0:a2cb7295a1f7 170 }
ram54288 0:a2cb7295a1f7 171
ram54288 0:a2cb7295a1f7 172 if (handler) {
ram54288 0:a2cb7295a1f7 173 success = handler->parse_notification_attribute(query,
ram54288 0:a2cb7295a1f7 174 M2MBase::base_type(), _resource_type);
ram54288 0:a2cb7295a1f7 175 if(success) {
ram54288 0:a2cb7295a1f7 176 if (is_under_observation()) {
ram54288 0:a2cb7295a1f7 177 handler->set_under_observation(true);
ram54288 0:a2cb7295a1f7 178 }
ram54288 0:a2cb7295a1f7 179 } else {
ram54288 0:a2cb7295a1f7 180 handler->set_default_values();
ram54288 0:a2cb7295a1f7 181 }
ram54288 0:a2cb7295a1f7 182 }
ram54288 0:a2cb7295a1f7 183 return success;
ram54288 0:a2cb7295a1f7 184 }
ram54288 0:a2cb7295a1f7 185
ram54288 0:a2cb7295a1f7 186 void M2MResourceInstance::set_execute_function(execute_callback callback)
ram54288 0:a2cb7295a1f7 187 {
ram54288 0:a2cb7295a1f7 188 delete _execute_callback;
ram54288 0:a2cb7295a1f7 189 _execute_callback = new execute_callback(callback);
ram54288 0:a2cb7295a1f7 190 }
ram54288 0:a2cb7295a1f7 191
ram54288 0:a2cb7295a1f7 192 void M2MResourceInstance::set_execute_function(execute_callback_2 callback)
ram54288 0:a2cb7295a1f7 193 {
ram54288 0:a2cb7295a1f7 194 delete _execute_function_pointer;
ram54288 0:a2cb7295a1f7 195
ram54288 0:a2cb7295a1f7 196 _execute_function_pointer = new FP1<void, void*>(callback);
ram54288 0:a2cb7295a1f7 197 set_execute_function(execute_callback(_execute_function_pointer, &FP1<void, void*>::call));
ram54288 0:a2cb7295a1f7 198 }
ram54288 0:a2cb7295a1f7 199
ram54288 0:a2cb7295a1f7 200 void M2MResourceInstance::clear_value()
ram54288 0:a2cb7295a1f7 201 {
ram54288 0:a2cb7295a1f7 202 tr_debug("M2MResourceInstance::clear_value");
ram54288 0:a2cb7295a1f7 203
ram54288 0:a2cb7295a1f7 204 free(_value);
ram54288 0:a2cb7295a1f7 205 _value = NULL;
ram54288 0:a2cb7295a1f7 206 _value_length = 0;
ram54288 0:a2cb7295a1f7 207
ram54288 0:a2cb7295a1f7 208 report();
ram54288 0:a2cb7295a1f7 209 }
ram54288 0:a2cb7295a1f7 210
ram54288 0:a2cb7295a1f7 211 bool M2MResourceInstance::set_value(int64_t value)
ram54288 0:a2cb7295a1f7 212 {
ram54288 0:a2cb7295a1f7 213 bool success;
ram54288 0:a2cb7295a1f7 214 // max len of "-9223372036854775808" plus zero termination
ram54288 0:a2cb7295a1f7 215 char buffer[20+1];
ram54288 0:a2cb7295a1f7 216 uint32_t size = m2m::itoa_c(value, buffer);
ram54288 0:a2cb7295a1f7 217
ram54288 0:a2cb7295a1f7 218 success = set_value((const uint8_t*)buffer, size);
ram54288 0:a2cb7295a1f7 219
ram54288 0:a2cb7295a1f7 220 return success;
ram54288 0:a2cb7295a1f7 221 }
ram54288 0:a2cb7295a1f7 222
ram54288 0:a2cb7295a1f7 223 bool M2MResourceInstance::set_value(const uint8_t *value,
ram54288 0:a2cb7295a1f7 224 const uint32_t value_length)
ram54288 0:a2cb7295a1f7 225 {
ram54288 0:a2cb7295a1f7 226 tr_debug("M2MResourceInstance::set_value()");
ram54288 0:a2cb7295a1f7 227 bool success = false;
ram54288 0:a2cb7295a1f7 228 bool value_changed = false;
ram54288 0:a2cb7295a1f7 229 if(is_value_changed(value,value_length)) {
ram54288 0:a2cb7295a1f7 230 value_changed = true;
ram54288 0:a2cb7295a1f7 231 }
ram54288 0:a2cb7295a1f7 232 if( value != NULL && value_length > 0 ) {
ram54288 0:a2cb7295a1f7 233 success = true;
ram54288 0:a2cb7295a1f7 234
ram54288 0:a2cb7295a1f7 235 free(_value);
ram54288 0:a2cb7295a1f7 236 _value_length = 0;
ram54288 0:a2cb7295a1f7 237
ram54288 0:a2cb7295a1f7 238 _value = alloc_string_copy(value, value_length);
ram54288 0:a2cb7295a1f7 239 if(_value) {
ram54288 0:a2cb7295a1f7 240 _value_length = value_length;
ram54288 0:a2cb7295a1f7 241 if( value_changed ) { //
ram54288 0:a2cb7295a1f7 242 if (_resource_type == M2MResourceInstance::STRING) {
ram54288 0:a2cb7295a1f7 243 M2MReportHandler *report_handler = M2MBase::report_handler();
ram54288 0:a2cb7295a1f7 244 if(report_handler && is_under_observation()) {
ram54288 0:a2cb7295a1f7 245 report_handler->set_notification_trigger();
ram54288 0:a2cb7295a1f7 246 }
ram54288 0:a2cb7295a1f7 247 }
ram54288 0:a2cb7295a1f7 248 else {
ram54288 0:a2cb7295a1f7 249 report();
ram54288 0:a2cb7295a1f7 250 }
ram54288 0:a2cb7295a1f7 251 }
ram54288 0:a2cb7295a1f7 252 }
ram54288 0:a2cb7295a1f7 253 }
ram54288 0:a2cb7295a1f7 254 return success;
ram54288 0:a2cb7295a1f7 255 }
ram54288 0:a2cb7295a1f7 256
ram54288 0:a2cb7295a1f7 257 void M2MResourceInstance::report()
ram54288 0:a2cb7295a1f7 258 {
ram54288 0:a2cb7295a1f7 259 tr_debug("M2MResourceInstance::report()");
ram54288 0:a2cb7295a1f7 260 M2MBase::Observation observation_level = M2MBase::observation_level();
ram54288 0:a2cb7295a1f7 261 tr_debug("M2MResourceInstance::report() - level %d", observation_level);
ram54288 0:a2cb7295a1f7 262 if((M2MBase::O_Attribute & observation_level) == M2MBase::O_Attribute ||
ram54288 0:a2cb7295a1f7 263 (M2MBase::OI_Attribute & observation_level) == M2MBase::OI_Attribute) {
ram54288 0:a2cb7295a1f7 264 tr_debug("M2MResourceInstance::report() -- object/instance level");
ram54288 0:a2cb7295a1f7 265 M2MObjectInstance& object_instance = get_parent_resource().get_parent_object_instance();
ram54288 0:a2cb7295a1f7 266 object_instance.notification_update(observation_level);
ram54288 0:a2cb7295a1f7 267 }
ram54288 0:a2cb7295a1f7 268
ram54288 0:a2cb7295a1f7 269 if(M2MBase::Dynamic == mode() &&
ram54288 0:a2cb7295a1f7 270 (M2MBase::R_Attribute & observation_level) == M2MBase::R_Attribute) {
ram54288 0:a2cb7295a1f7 271 tr_debug("M2MResourceInstance::report() - resource level");
ram54288 0:a2cb7295a1f7 272 if(!_resource_callback && _resource_type != M2MResourceInstance::STRING) {
ram54288 0:a2cb7295a1f7 273 M2MReportHandler *report_handler = M2MBase::report_handler();
ram54288 0:a2cb7295a1f7 274 if (report_handler && is_observable()) {
ram54288 0:a2cb7295a1f7 275 if(_value) {
ram54288 0:a2cb7295a1f7 276 report_handler->set_value(atof((const char*)_value));
ram54288 0:a2cb7295a1f7 277 } else {
ram54288 0:a2cb7295a1f7 278 report_handler->set_value(0);
ram54288 0:a2cb7295a1f7 279 }
ram54288 0:a2cb7295a1f7 280 }
ram54288 0:a2cb7295a1f7 281 }
ram54288 0:a2cb7295a1f7 282 else {
ram54288 0:a2cb7295a1f7 283 if (_resource_callback && base_type() == M2MBase::ResourceInstance) {
ram54288 0:a2cb7295a1f7 284 _resource_callback->notification_update();
ram54288 0:a2cb7295a1f7 285 }
ram54288 0:a2cb7295a1f7 286 }
ram54288 0:a2cb7295a1f7 287 } else if(M2MBase::Static == mode()) {
ram54288 0:a2cb7295a1f7 288 M2MObservationHandler *observation_handler = M2MBase::observation_handler();
ram54288 0:a2cb7295a1f7 289 if(observation_handler) {
ram54288 0:a2cb7295a1f7 290 observation_handler->value_updated(this);
ram54288 0:a2cb7295a1f7 291 }
ram54288 0:a2cb7295a1f7 292 } else {
ram54288 0:a2cb7295a1f7 293 tr_debug("M2MResourceInstance::report() - mode = %d, is_observable = %d", mode(), is_observable());
ram54288 0:a2cb7295a1f7 294 }
ram54288 0:a2cb7295a1f7 295 }
ram54288 0:a2cb7295a1f7 296
ram54288 0:a2cb7295a1f7 297 bool M2MResourceInstance::is_value_changed(const uint8_t* value, const uint32_t value_len)
ram54288 0:a2cb7295a1f7 298 {
ram54288 0:a2cb7295a1f7 299 bool changed = false;
ram54288 0:a2cb7295a1f7 300 if(value_len != _value_length) {
ram54288 0:a2cb7295a1f7 301 changed = true;
ram54288 0:a2cb7295a1f7 302 } else if(value && !_value) {
ram54288 0:a2cb7295a1f7 303 changed = true;
ram54288 0:a2cb7295a1f7 304 } else if(_value && !value) {
ram54288 0:a2cb7295a1f7 305 changed = true;
ram54288 0:a2cb7295a1f7 306 } else {
ram54288 0:a2cb7295a1f7 307 if (_value) {
ram54288 0:a2cb7295a1f7 308 if (strcmp((char*)value, (char*)_value) != 0) {
ram54288 0:a2cb7295a1f7 309 changed = true;
ram54288 0:a2cb7295a1f7 310 }
ram54288 0:a2cb7295a1f7 311 }
ram54288 0:a2cb7295a1f7 312 }
ram54288 0:a2cb7295a1f7 313 tr_debug("M2MResourceInstance::is_value_changed() -- %s", changed ? "true" : "false");
ram54288 0:a2cb7295a1f7 314 return changed;
ram54288 0:a2cb7295a1f7 315 }
ram54288 0:a2cb7295a1f7 316
ram54288 0:a2cb7295a1f7 317 void M2MResourceInstance::execute(void *arguments)
ram54288 0:a2cb7295a1f7 318 {
ram54288 0:a2cb7295a1f7 319 tr_debug("M2MResourceInstance::execute");
ram54288 0:a2cb7295a1f7 320 if(_execute_callback) {
ram54288 0:a2cb7295a1f7 321 (*_execute_callback)(arguments);
ram54288 0:a2cb7295a1f7 322 }
ram54288 0:a2cb7295a1f7 323 }
ram54288 0:a2cb7295a1f7 324
ram54288 0:a2cb7295a1f7 325 void M2MResourceInstance::get_value(uint8_t *&value, uint32_t &value_length)
ram54288 0:a2cb7295a1f7 326 {
ram54288 0:a2cb7295a1f7 327 value_length = 0;
ram54288 0:a2cb7295a1f7 328 if(value) {
ram54288 0:a2cb7295a1f7 329 free(value);
ram54288 0:a2cb7295a1f7 330 value = NULL;
ram54288 0:a2cb7295a1f7 331 }
ram54288 0:a2cb7295a1f7 332 if(_value && _value_length > 0) {
ram54288 0:a2cb7295a1f7 333 value = alloc_string_copy(_value, _value_length);
ram54288 0:a2cb7295a1f7 334 if(value) {
ram54288 0:a2cb7295a1f7 335 value_length = _value_length;
ram54288 0:a2cb7295a1f7 336 }
ram54288 0:a2cb7295a1f7 337 }
ram54288 0:a2cb7295a1f7 338 }
ram54288 0:a2cb7295a1f7 339
ram54288 0:a2cb7295a1f7 340 int M2MResourceInstance::get_value_int()
ram54288 0:a2cb7295a1f7 341 {
ram54288 0:a2cb7295a1f7 342 int value_int = 0;
ram54288 0:a2cb7295a1f7 343 // Get the value and convert it into integer. This is not the most
ram54288 0:a2cb7295a1f7 344 // efficient way, as it takes pointless heap copy to get the zero termination.
ram54288 0:a2cb7295a1f7 345 uint8_t* buffer = NULL;
ram54288 0:a2cb7295a1f7 346 uint32_t length;
ram54288 0:a2cb7295a1f7 347 get_value(buffer,length);
ram54288 0:a2cb7295a1f7 348 if(buffer) {
ram54288 0:a2cb7295a1f7 349 value_int = atoi((const char*)buffer);
ram54288 0:a2cb7295a1f7 350 free(buffer);
ram54288 0:a2cb7295a1f7 351 }
ram54288 0:a2cb7295a1f7 352 return value_int;
ram54288 0:a2cb7295a1f7 353 }
ram54288 0:a2cb7295a1f7 354
ram54288 0:a2cb7295a1f7 355 String M2MResourceInstance::get_value_string() const
ram54288 0:a2cb7295a1f7 356 {
ram54288 0:a2cb7295a1f7 357 // XXX: do a better constructor to avoid pointless malloc
ram54288 0:a2cb7295a1f7 358 String value;
ram54288 0:a2cb7295a1f7 359 if (_value) {
ram54288 0:a2cb7295a1f7 360 value.append_raw((char*)_value, _value_length);
ram54288 0:a2cb7295a1f7 361 }
ram54288 0:a2cb7295a1f7 362
ram54288 0:a2cb7295a1f7 363 return value;
ram54288 0:a2cb7295a1f7 364 }
ram54288 0:a2cb7295a1f7 365
ram54288 0:a2cb7295a1f7 366 uint8_t* M2MResourceInstance::value() const
ram54288 0:a2cb7295a1f7 367 {
ram54288 0:a2cb7295a1f7 368 return _value;
ram54288 0:a2cb7295a1f7 369 }
ram54288 0:a2cb7295a1f7 370
ram54288 0:a2cb7295a1f7 371 uint32_t M2MResourceInstance::value_length() const
ram54288 0:a2cb7295a1f7 372 {
ram54288 0:a2cb7295a1f7 373 return _value_length;
ram54288 0:a2cb7295a1f7 374 }
ram54288 0:a2cb7295a1f7 375
ram54288 0:a2cb7295a1f7 376 sn_coap_hdr_s* M2MResourceInstance::handle_get_request(nsdl_s *nsdl,
ram54288 0:a2cb7295a1f7 377 sn_coap_hdr_s *received_coap_header,
ram54288 0:a2cb7295a1f7 378 M2MObservationHandler *observation_handler)
ram54288 0:a2cb7295a1f7 379 {
ram54288 0:a2cb7295a1f7 380 tr_debug("M2MResourceInstance::handle_get_request()");
ram54288 0:a2cb7295a1f7 381 sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CONTENT;
ram54288 0:a2cb7295a1f7 382 sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl,
ram54288 0:a2cb7295a1f7 383 received_coap_header,
ram54288 0:a2cb7295a1f7 384 msg_code);
ram54288 0:a2cb7295a1f7 385 if(received_coap_header) {
ram54288 0:a2cb7295a1f7 386 // process the GET if we have registered a callback for it
ram54288 0:a2cb7295a1f7 387 if ((operation() & SN_GRS_GET_ALLOWED) != 0) {
ram54288 0:a2cb7295a1f7 388 if(coap_response) {
ram54288 0:a2cb7295a1f7 389 if(_resource_type == M2MResourceInstance::OPAQUE) {
ram54288 0:a2cb7295a1f7 390 coap_response->content_format = sn_coap_content_format_e(COAP_CONTENT_OMA_OPAQUE_TYPE);
ram54288 0:a2cb7295a1f7 391 } else {
ram54288 0:a2cb7295a1f7 392 coap_response->content_format = sn_coap_content_format_e(0);
ram54288 0:a2cb7295a1f7 393 }
ram54288 0:a2cb7295a1f7 394 // fill in the CoAP response payload
ram54288 0:a2cb7295a1f7 395 coap_response->payload_ptr = NULL;
ram54288 0:a2cb7295a1f7 396 uint32_t payload_len = 0;
ram54288 0:a2cb7295a1f7 397
ram54288 0:a2cb7295a1f7 398 //If handler exists it means that resource value is stored in application side
ram54288 0:a2cb7295a1f7 399 if (block_message() && block_message()->is_block_message()) {
ram54288 0:a2cb7295a1f7 400 if(_outgoing_block_message_cb) {
ram54288 0:a2cb7295a1f7 401 String name = "";
ram54288 0:a2cb7295a1f7 402 if (received_coap_header->uri_path_ptr != NULL &&
ram54288 0:a2cb7295a1f7 403 received_coap_header->uri_path_len > 0) {
ram54288 0:a2cb7295a1f7 404 name.append_raw((char *)received_coap_header->uri_path_ptr,
ram54288 0:a2cb7295a1f7 405 received_coap_header->uri_path_len);
ram54288 0:a2cb7295a1f7 406 }
ram54288 0:a2cb7295a1f7 407 (*_outgoing_block_message_cb)(name, coap_response->payload_ptr, payload_len);
ram54288 0:a2cb7295a1f7 408 }
ram54288 0:a2cb7295a1f7 409 } else {
ram54288 0:a2cb7295a1f7 410 get_value(coap_response->payload_ptr,payload_len);
ram54288 0:a2cb7295a1f7 411 }
ram54288 0:a2cb7295a1f7 412
ram54288 0:a2cb7295a1f7 413 coap_response->payload_len = payload_len;
ram54288 0:a2cb7295a1f7 414 coap_response->options_list_ptr = sn_nsdl_alloc_options_list(nsdl, coap_response);
ram54288 0:a2cb7295a1f7 415
ram54288 0:a2cb7295a1f7 416 coap_response->options_list_ptr->max_age = max_age();
ram54288 0:a2cb7295a1f7 417
ram54288 0:a2cb7295a1f7 418 if(received_coap_header->options_list_ptr) {
ram54288 0:a2cb7295a1f7 419 if(received_coap_header->options_list_ptr->observe != -1) {
ram54288 0:a2cb7295a1f7 420 if (is_observable()) {
ram54288 0:a2cb7295a1f7 421 uint32_t number = 0;
ram54288 0:a2cb7295a1f7 422 uint8_t observe_option = 0;
ram54288 0:a2cb7295a1f7 423 observe_option = received_coap_header->options_list_ptr->observe;
ram54288 0:a2cb7295a1f7 424
ram54288 0:a2cb7295a1f7 425 if(START_OBSERVATION == observe_option) {
ram54288 0:a2cb7295a1f7 426 tr_debug("M2MResourceInstance::handle_get_request - Starts Observation");
ram54288 0:a2cb7295a1f7 427 // If the observe length is 0 means register for observation.
ram54288 0:a2cb7295a1f7 428 if(received_coap_header->options_list_ptr->observe != -1) {
ram54288 0:a2cb7295a1f7 429 number = received_coap_header->options_list_ptr->observe;
ram54288 0:a2cb7295a1f7 430 }
ram54288 0:a2cb7295a1f7 431 if(received_coap_header->token_ptr) {
ram54288 0:a2cb7295a1f7 432 tr_debug("M2MResourceInstance::handle_get_request - Sets Observation Token to resource");
ram54288 0:a2cb7295a1f7 433 set_observation_token(received_coap_header->token_ptr,
ram54288 0:a2cb7295a1f7 434 received_coap_header->token_len);
ram54288 0:a2cb7295a1f7 435 }
ram54288 0:a2cb7295a1f7 436 // If the observe value is 0 means register for observation.
ram54288 0:a2cb7295a1f7 437 if(number == 0) {
ram54288 0:a2cb7295a1f7 438 tr_debug("M2MResourceInstance::handle_get_request - Put Resource under Observation");
ram54288 0:a2cb7295a1f7 439 set_under_observation(true,observation_handler);
ram54288 0:a2cb7295a1f7 440 M2MBase::add_observation_level(M2MBase::R_Attribute);
ram54288 0:a2cb7295a1f7 441 coap_response->options_list_ptr->observe = observation_number();
ram54288 0:a2cb7295a1f7 442 }
ram54288 0:a2cb7295a1f7 443 } else if (STOP_OBSERVATION == observe_option) {
ram54288 0:a2cb7295a1f7 444 tr_debug("M2MResourceInstance::handle_get_request - Stops Observation");
ram54288 0:a2cb7295a1f7 445 set_under_observation(false,NULL);
ram54288 0:a2cb7295a1f7 446 M2MBase::remove_observation_level(M2MBase::R_Attribute);
ram54288 0:a2cb7295a1f7 447 }
ram54288 0:a2cb7295a1f7 448 } else {
ram54288 0:a2cb7295a1f7 449 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
ram54288 0:a2cb7295a1f7 450 }
ram54288 0:a2cb7295a1f7 451 }
ram54288 0:a2cb7295a1f7 452 }
ram54288 0:a2cb7295a1f7 453 }
ram54288 0:a2cb7295a1f7 454 }else {
ram54288 0:a2cb7295a1f7 455 tr_error("M2MResourceInstance::handle_get_request - Return COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
ram54288 0:a2cb7295a1f7 456 // Operation is not allowed.
ram54288 0:a2cb7295a1f7 457 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
ram54288 0:a2cb7295a1f7 458 }
ram54288 0:a2cb7295a1f7 459 } else {
ram54288 0:a2cb7295a1f7 460 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
ram54288 0:a2cb7295a1f7 461 }
ram54288 0:a2cb7295a1f7 462 if(coap_response) {
ram54288 0:a2cb7295a1f7 463 coap_response->msg_code = msg_code;
ram54288 0:a2cb7295a1f7 464 }
ram54288 0:a2cb7295a1f7 465 return coap_response;
ram54288 0:a2cb7295a1f7 466 }
ram54288 0:a2cb7295a1f7 467
ram54288 0:a2cb7295a1f7 468 sn_coap_hdr_s* M2MResourceInstance::handle_put_request(nsdl_s *nsdl,
ram54288 0:a2cb7295a1f7 469 sn_coap_hdr_s *received_coap_header,
ram54288 0:a2cb7295a1f7 470 M2MObservationHandler *observation_handler,
ram54288 0:a2cb7295a1f7 471 bool &execute_value_updated)
ram54288 0:a2cb7295a1f7 472 {
ram54288 0:a2cb7295a1f7 473 tr_debug("M2MResourceInstance::handle_put_request()");
ram54288 0:a2cb7295a1f7 474
ram54288 0:a2cb7295a1f7 475
ram54288 0:a2cb7295a1f7 476 sn_coap_msg_code_e msg_code = COAP_MSG_CODE_RESPONSE_CHANGED; // 2.04
ram54288 0:a2cb7295a1f7 477 sn_coap_hdr_s *coap_response = sn_nsdl_build_response(nsdl,
ram54288 0:a2cb7295a1f7 478 received_coap_header,
ram54288 0:a2cb7295a1f7 479 msg_code);
ram54288 0:a2cb7295a1f7 480 // process the PUT if we have registered a callback for it
ram54288 0:a2cb7295a1f7 481 if(received_coap_header && coap_response) {
ram54288 0:a2cb7295a1f7 482 uint16_t coap_content_type = 0;
ram54288 0:a2cb7295a1f7 483 if(received_coap_header->content_format != COAP_CT_NONE) {
ram54288 0:a2cb7295a1f7 484 coap_content_type = received_coap_header->content_format;
ram54288 0:a2cb7295a1f7 485 }
ram54288 0:a2cb7295a1f7 486 if(received_coap_header->options_list_ptr &&
ram54288 0:a2cb7295a1f7 487 received_coap_header->options_list_ptr->uri_query_ptr) {
ram54288 0:a2cb7295a1f7 488 char *query = (char*)alloc_string_copy(received_coap_header->options_list_ptr->uri_query_ptr,
ram54288 0:a2cb7295a1f7 489 received_coap_header->options_list_ptr->uri_query_len);
ram54288 0:a2cb7295a1f7 490 if (query){
ram54288 0:a2cb7295a1f7 491 tr_debug("M2MResourceInstance::handle_put_request() - Query %s", query);
ram54288 0:a2cb7295a1f7 492
ram54288 0:a2cb7295a1f7 493 // if anything was updated, re-initialize the stored notification attributes
ram54288 0:a2cb7295a1f7 494 if (!handle_observation_attribute(query)){
ram54288 0:a2cb7295a1f7 495 tr_debug("M2MResourceInstance::handle_put_request() - Invalid query");
ram54288 0:a2cb7295a1f7 496 msg_code = COAP_MSG_CODE_RESPONSE_BAD_REQUEST; // 4.00
ram54288 0:a2cb7295a1f7 497 }
ram54288 0:a2cb7295a1f7 498 free(query);
ram54288 0:a2cb7295a1f7 499 }
ram54288 0:a2cb7295a1f7 500 } else if ((operation() & SN_GRS_PUT_ALLOWED) != 0) {
ram54288 0:a2cb7295a1f7 501 tr_debug("M2MResourceInstance::handle_put_request() - Request Content-Type %d", coap_content_type);
ram54288 0:a2cb7295a1f7 502
ram54288 0:a2cb7295a1f7 503 if(COAP_CONTENT_OMA_TLV_TYPE == coap_content_type) {
ram54288 0:a2cb7295a1f7 504 msg_code = COAP_MSG_CODE_RESPONSE_UNSUPPORTED_CONTENT_FORMAT;
ram54288 0:a2cb7295a1f7 505 } else {
ram54288 0:a2cb7295a1f7 506 bool external_block_store = false;
ram54288 0:a2cb7295a1f7 507 if (block_message()) {
ram54288 0:a2cb7295a1f7 508 block_message()->set_message_info(received_coap_header);
ram54288 0:a2cb7295a1f7 509 if (block_message()->is_block_message()) {
ram54288 0:a2cb7295a1f7 510 external_block_store = true;
ram54288 0:a2cb7295a1f7 511 if(_incoming_block_message_cb) {
ram54288 0:a2cb7295a1f7 512 (*_incoming_block_message_cb)(_block_message_data);
ram54288 0:a2cb7295a1f7 513 }
ram54288 0:a2cb7295a1f7 514 if (block_message()->is_last_block()) {
ram54288 0:a2cb7295a1f7 515 block_message()->clear_values();
ram54288 0:a2cb7295a1f7 516 coap_response->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVED;
ram54288 0:a2cb7295a1f7 517 } else {
ram54288 0:a2cb7295a1f7 518 coap_response->coap_status = COAP_STATUS_PARSER_BLOCKWISE_MSG_RECEIVING;
ram54288 0:a2cb7295a1f7 519 }
ram54288 0:a2cb7295a1f7 520 if (block_message()->error_code() != M2MBlockMessage::ErrorNone) {
ram54288 0:a2cb7295a1f7 521 block_message()->clear_values();
ram54288 0:a2cb7295a1f7 522 }
ram54288 0:a2cb7295a1f7 523 }
ram54288 0:a2cb7295a1f7 524 }
ram54288 0:a2cb7295a1f7 525 if (!external_block_store) {
ram54288 0:a2cb7295a1f7 526 set_value(received_coap_header->payload_ptr, received_coap_header->payload_len);
ram54288 0:a2cb7295a1f7 527 }
ram54288 0:a2cb7295a1f7 528 if(received_coap_header->payload_ptr) {
ram54288 0:a2cb7295a1f7 529 tr_debug("M2MResourceInstance::handle_put_request() - Update Resource with new values");
ram54288 0:a2cb7295a1f7 530 if(observation_handler) {
ram54288 0:a2cb7295a1f7 531 String value = "";
ram54288 0:a2cb7295a1f7 532 if (received_coap_header->uri_path_ptr != NULL &&
ram54288 0:a2cb7295a1f7 533 received_coap_header->uri_path_len > 0) {
ram54288 0:a2cb7295a1f7 534 value.append_raw((char*)received_coap_header->uri_path_ptr, received_coap_header->uri_path_len);
ram54288 0:a2cb7295a1f7 535 }
ram54288 0:a2cb7295a1f7 536 execute_value_updated = true;
ram54288 0:a2cb7295a1f7 537 }
ram54288 0:a2cb7295a1f7 538 }
ram54288 0:a2cb7295a1f7 539 }
ram54288 0:a2cb7295a1f7 540 } else {
ram54288 0:a2cb7295a1f7 541 // Operation is not allowed.
ram54288 0:a2cb7295a1f7 542 tr_error("M2MResourceInstance::handle_put_request() - COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED");
ram54288 0:a2cb7295a1f7 543 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
ram54288 0:a2cb7295a1f7 544 }
ram54288 0:a2cb7295a1f7 545 } else {
ram54288 0:a2cb7295a1f7 546 msg_code = COAP_MSG_CODE_RESPONSE_METHOD_NOT_ALLOWED;
ram54288 0:a2cb7295a1f7 547 }
ram54288 0:a2cb7295a1f7 548 if(coap_response) {
ram54288 0:a2cb7295a1f7 549 coap_response->msg_code = msg_code;
ram54288 0:a2cb7295a1f7 550 }
ram54288 0:a2cb7295a1f7 551
ram54288 0:a2cb7295a1f7 552 return coap_response;
ram54288 0:a2cb7295a1f7 553 }
ram54288 0:a2cb7295a1f7 554
ram54288 0:a2cb7295a1f7 555 void M2MResourceInstance::set_resource_observer(M2MResourceCallback *resource)
ram54288 0:a2cb7295a1f7 556 {
ram54288 0:a2cb7295a1f7 557 _resource_callback = resource;
ram54288 0:a2cb7295a1f7 558 }
ram54288 0:a2cb7295a1f7 559
ram54288 0:a2cb7295a1f7 560 uint16_t M2MResourceInstance::object_instance_id() const
ram54288 0:a2cb7295a1f7 561 {
ram54288 0:a2cb7295a1f7 562 return _object_instance_id;
ram54288 0:a2cb7295a1f7 563 }
ram54288 0:a2cb7295a1f7 564
ram54288 0:a2cb7295a1f7 565 M2MBlockMessage* M2MResourceInstance::block_message() const
ram54288 0:a2cb7295a1f7 566 {
ram54288 0:a2cb7295a1f7 567 return _block_message_data;
ram54288 0:a2cb7295a1f7 568 }
ram54288 0:a2cb7295a1f7 569
ram54288 0:a2cb7295a1f7 570 void M2MResourceInstance::set_incoming_block_message_callback(incoming_block_message_callback callback)
ram54288 0:a2cb7295a1f7 571 {
ram54288 0:a2cb7295a1f7 572 // copy the callback object. This will change on next version to be a direct pointer to a interface class,
ram54288 0:a2cb7295a1f7 573 // this FPn<> is just too heavy for this usage.
ram54288 0:a2cb7295a1f7 574 delete _incoming_block_message_cb;
ram54288 0:a2cb7295a1f7 575 _incoming_block_message_cb = new incoming_block_message_callback(callback);
ram54288 0:a2cb7295a1f7 576
ram54288 0:a2cb7295a1f7 577 delete _block_message_data;
ram54288 0:a2cb7295a1f7 578 _block_message_data = NULL;
ram54288 0:a2cb7295a1f7 579 _block_message_data = new M2MBlockMessage();
ram54288 0:a2cb7295a1f7 580 }
ram54288 0:a2cb7295a1f7 581
ram54288 0:a2cb7295a1f7 582 void M2MResourceInstance::set_outgoing_block_message_callback(outgoing_block_message_callback callback)
ram54288 0:a2cb7295a1f7 583 {
ram54288 0:a2cb7295a1f7 584 delete _outgoing_block_message_cb;
ram54288 0:a2cb7295a1f7 585 _outgoing_block_message_cb = new outgoing_block_message_callback(callback);
ram54288 0:a2cb7295a1f7 586 }
ram54288 0:a2cb7295a1f7 587
ram54288 0:a2cb7295a1f7 588 void M2MResourceInstance::set_notification_sent_callback(notification_sent_callback callback)
ram54288 0:a2cb7295a1f7 589 {
ram54288 0:a2cb7295a1f7 590 delete _notification_sent_callback;
ram54288 0:a2cb7295a1f7 591 _notification_sent_callback = new notification_sent_callback(callback);
ram54288 0:a2cb7295a1f7 592 }
ram54288 0:a2cb7295a1f7 593
ram54288 0:a2cb7295a1f7 594 void M2MResourceInstance::set_notification_sent_callback(notification_sent_callback_2 callback)
ram54288 0:a2cb7295a1f7 595 {
ram54288 0:a2cb7295a1f7 596 delete _notification_sent_function_pointer;
ram54288 0:a2cb7295a1f7 597
ram54288 0:a2cb7295a1f7 598 _notification_sent_function_pointer = new FP0<void>(callback);
ram54288 0:a2cb7295a1f7 599 set_notification_sent_callback(
ram54288 0:a2cb7295a1f7 600 notification_sent_callback(_notification_sent_function_pointer, &FP0<void>::call));
ram54288 0:a2cb7295a1f7 601 }
ram54288 0:a2cb7295a1f7 602
ram54288 0:a2cb7295a1f7 603 void M2MResourceInstance::notification_sent()
ram54288 0:a2cb7295a1f7 604 {
ram54288 0:a2cb7295a1f7 605 if (_notification_sent_callback) {
ram54288 0:a2cb7295a1f7 606 (*_notification_sent_callback)();
ram54288 0:a2cb7295a1f7 607 }
ram54288 0:a2cb7295a1f7 608 }
ram54288 0:a2cb7295a1f7 609
ram54288 0:a2cb7295a1f7 610 M2MResource& M2MResourceInstance::get_parent_resource() const
ram54288 0:a2cb7295a1f7 611 {
ram54288 0:a2cb7295a1f7 612 return _parent_resource;
ram54288 0:a2cb7295a1f7 613 }
ram54288 0:a2cb7295a1f7 614
ram54288 0:a2cb7295a1f7 615 const char* M2MResourceInstance::object_name() const
ram54288 0:a2cb7295a1f7 616 {
ram54288 0:a2cb7295a1f7 617 const M2MObjectInstance& parent_object_instance = _parent_resource.get_parent_object_instance();
ram54288 0:a2cb7295a1f7 618 const M2MObject& parent_object = parent_object_instance.get_parent_object();
ram54288 0:a2cb7295a1f7 619
ram54288 0:a2cb7295a1f7 620 return parent_object.name();
ram54288 0:a2cb7295a1f7 621 }