pick up wakaama files from https://github.com/eclipse/wakaama

Committer:
terencez
Date:
Wed Apr 19 11:30:02 2017 +0000
Revision:
0:1fa43ab66921
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
terencez 0:1fa43ab66921 1 /*******************************************************************************
terencez 0:1fa43ab66921 2 *
terencez 0:1fa43ab66921 3 * Copyright (c) 2013, 2014 Intel Corporation and others.
terencez 0:1fa43ab66921 4 * All rights reserved. This program and the accompanying materials
terencez 0:1fa43ab66921 5 * are made available under the terms of the Eclipse Public License v1.0
terencez 0:1fa43ab66921 6 * and Eclipse Distribution License v1.0 which accompany this distribution.
terencez 0:1fa43ab66921 7 *
terencez 0:1fa43ab66921 8 * The Eclipse Public License is available at
terencez 0:1fa43ab66921 9 * http://www.eclipse.org/legal/epl-v10.html
terencez 0:1fa43ab66921 10 * The Eclipse Distribution License is available at
terencez 0:1fa43ab66921 11 * http://www.eclipse.org/org/documents/edl-v10.php.
terencez 0:1fa43ab66921 12 *
terencez 0:1fa43ab66921 13 * Contributors:
terencez 0:1fa43ab66921 14 * David Navarro, Intel Corporation - initial API and implementation
terencez 0:1fa43ab66921 15 * Toby Jaffey - Please refer to git log
terencez 0:1fa43ab66921 16 * Bosch Software Innovations GmbH - Please refer to git log
terencez 0:1fa43ab66921 17 *
terencez 0:1fa43ab66921 18 *******************************************************************************/
terencez 0:1fa43ab66921 19
terencez 0:1fa43ab66921 20 /*
terencez 0:1fa43ab66921 21 Copyright (c) 2013, 2014 Intel Corporation
terencez 0:1fa43ab66921 22
terencez 0:1fa43ab66921 23 Redistribution and use in source and binary forms, with or without modification,
terencez 0:1fa43ab66921 24 are permitted provided that the following conditions are met:
terencez 0:1fa43ab66921 25
terencez 0:1fa43ab66921 26 * Redistributions of source code must retain the above copyright notice,
terencez 0:1fa43ab66921 27 this list of conditions and the following disclaimer.
terencez 0:1fa43ab66921 28 * Redistributions in binary form must reproduce the above copyright notice,
terencez 0:1fa43ab66921 29 this list of conditions and the following disclaimer in the documentation
terencez 0:1fa43ab66921 30 and/or other materials provided with the distribution.
terencez 0:1fa43ab66921 31 * Neither the name of Intel Corporation nor the names of its contributors
terencez 0:1fa43ab66921 32 may be used to endorse or promote products derived from this software
terencez 0:1fa43ab66921 33 without specific prior written permission.
terencez 0:1fa43ab66921 34
terencez 0:1fa43ab66921 35 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
terencez 0:1fa43ab66921 36 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
terencez 0:1fa43ab66921 37 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
terencez 0:1fa43ab66921 38 IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
terencez 0:1fa43ab66921 39 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
terencez 0:1fa43ab66921 40 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
terencez 0:1fa43ab66921 41 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
terencez 0:1fa43ab66921 42 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
terencez 0:1fa43ab66921 43 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
terencez 0:1fa43ab66921 44 THE POSSIBILITY OF SUCH DAMAGE.
terencez 0:1fa43ab66921 45
terencez 0:1fa43ab66921 46 David Navarro <david.navarro@intel.com>
terencez 0:1fa43ab66921 47
terencez 0:1fa43ab66921 48 */
terencez 0:1fa43ab66921 49
terencez 0:1fa43ab66921 50 #include "internals.h"
terencez 0:1fa43ab66921 51 #include <stdio.h>
terencez 0:1fa43ab66921 52
terencez 0:1fa43ab66921 53
terencez 0:1fa43ab66921 54 #ifdef LWM2M_CLIENT_MODE
terencez 0:1fa43ab66921 55 static lwm2m_observed_t * prv_findObserved(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 56 lwm2m_uri_t * uriP)
terencez 0:1fa43ab66921 57 {
terencez 0:1fa43ab66921 58 lwm2m_observed_t * targetP;
terencez 0:1fa43ab66921 59
terencez 0:1fa43ab66921 60 targetP = contextP->observedList;
terencez 0:1fa43ab66921 61 while (targetP != NULL
terencez 0:1fa43ab66921 62 && (targetP->uri.objectId != uriP->objectId
terencez 0:1fa43ab66921 63 || targetP->uri.flag != uriP->flag
terencez 0:1fa43ab66921 64 || (LWM2M_URI_IS_SET_INSTANCE(uriP) && targetP->uri.instanceId != uriP->instanceId)
terencez 0:1fa43ab66921 65 || (LWM2M_URI_IS_SET_RESOURCE(uriP) && targetP->uri.resourceId != uriP->resourceId)))
terencez 0:1fa43ab66921 66 {
terencez 0:1fa43ab66921 67 targetP = targetP->next;
terencez 0:1fa43ab66921 68 }
terencez 0:1fa43ab66921 69
terencez 0:1fa43ab66921 70 return targetP;
terencez 0:1fa43ab66921 71 }
terencez 0:1fa43ab66921 72
terencez 0:1fa43ab66921 73 static void prv_unlinkObserved(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 74 lwm2m_observed_t * observedP)
terencez 0:1fa43ab66921 75 {
terencez 0:1fa43ab66921 76 if (contextP->observedList == observedP)
terencez 0:1fa43ab66921 77 {
terencez 0:1fa43ab66921 78 contextP->observedList = contextP->observedList->next;
terencez 0:1fa43ab66921 79 }
terencez 0:1fa43ab66921 80 else
terencez 0:1fa43ab66921 81 {
terencez 0:1fa43ab66921 82 lwm2m_observed_t * parentP;
terencez 0:1fa43ab66921 83
terencez 0:1fa43ab66921 84 parentP = contextP->observedList;
terencez 0:1fa43ab66921 85 while (parentP->next != NULL
terencez 0:1fa43ab66921 86 && parentP->next != observedP)
terencez 0:1fa43ab66921 87 {
terencez 0:1fa43ab66921 88 parentP = parentP->next;
terencez 0:1fa43ab66921 89 }
terencez 0:1fa43ab66921 90 if (parentP->next != NULL)
terencez 0:1fa43ab66921 91 {
terencez 0:1fa43ab66921 92 parentP->next = parentP->next->next;
terencez 0:1fa43ab66921 93 }
terencez 0:1fa43ab66921 94 }
terencez 0:1fa43ab66921 95 }
terencez 0:1fa43ab66921 96
terencez 0:1fa43ab66921 97 static lwm2m_watcher_t * prv_findWatcher(lwm2m_observed_t * observedP,
terencez 0:1fa43ab66921 98 lwm2m_server_t * serverP)
terencez 0:1fa43ab66921 99 {
terencez 0:1fa43ab66921 100 lwm2m_watcher_t * targetP;
terencez 0:1fa43ab66921 101
terencez 0:1fa43ab66921 102 targetP = observedP->watcherList;
terencez 0:1fa43ab66921 103 while (targetP != NULL
terencez 0:1fa43ab66921 104 && targetP->server != serverP)
terencez 0:1fa43ab66921 105 {
terencez 0:1fa43ab66921 106 targetP = targetP->next;
terencez 0:1fa43ab66921 107 }
terencez 0:1fa43ab66921 108
terencez 0:1fa43ab66921 109 return targetP;
terencez 0:1fa43ab66921 110 }
terencez 0:1fa43ab66921 111
terencez 0:1fa43ab66921 112 static lwm2m_watcher_t * prv_getWatcher(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 113 lwm2m_uri_t * uriP,
terencez 0:1fa43ab66921 114 lwm2m_server_t * serverP)
terencez 0:1fa43ab66921 115 {
terencez 0:1fa43ab66921 116 lwm2m_observed_t * observedP;
terencez 0:1fa43ab66921 117 bool allocatedObserver;
terencez 0:1fa43ab66921 118 lwm2m_watcher_t * watcherP;
terencez 0:1fa43ab66921 119
terencez 0:1fa43ab66921 120 allocatedObserver = false;
terencez 0:1fa43ab66921 121
terencez 0:1fa43ab66921 122 observedP = prv_findObserved(contextP, uriP);
terencez 0:1fa43ab66921 123 if (observedP == NULL)
terencez 0:1fa43ab66921 124 {
terencez 0:1fa43ab66921 125 observedP = (lwm2m_observed_t *)lwm2m_malloc(sizeof(lwm2m_observed_t));
terencez 0:1fa43ab66921 126 if (observedP == NULL) return NULL;
terencez 0:1fa43ab66921 127 allocatedObserver = true;
terencez 0:1fa43ab66921 128 memset(observedP, 0, sizeof(lwm2m_observed_t));
terencez 0:1fa43ab66921 129 memcpy(&(observedP->uri), uriP, sizeof(lwm2m_uri_t));
terencez 0:1fa43ab66921 130 observedP->next = contextP->observedList;
terencez 0:1fa43ab66921 131 contextP->observedList = observedP;
terencez 0:1fa43ab66921 132 }
terencez 0:1fa43ab66921 133
terencez 0:1fa43ab66921 134 watcherP = prv_findWatcher(observedP, serverP);
terencez 0:1fa43ab66921 135 if (watcherP == NULL)
terencez 0:1fa43ab66921 136 {
terencez 0:1fa43ab66921 137 watcherP = (lwm2m_watcher_t *)lwm2m_malloc(sizeof(lwm2m_watcher_t));
terencez 0:1fa43ab66921 138 if (watcherP == NULL)
terencez 0:1fa43ab66921 139 {
terencez 0:1fa43ab66921 140 if (allocatedObserver == true)
terencez 0:1fa43ab66921 141 {
terencez 0:1fa43ab66921 142 lwm2m_free(observedP);
terencez 0:1fa43ab66921 143 }
terencez 0:1fa43ab66921 144 return NULL;
terencez 0:1fa43ab66921 145 }
terencez 0:1fa43ab66921 146 memset(watcherP, 0, sizeof(lwm2m_watcher_t));
terencez 0:1fa43ab66921 147 watcherP->active = false;
terencez 0:1fa43ab66921 148 watcherP->server = serverP;
terencez 0:1fa43ab66921 149 watcherP->next = observedP->watcherList;
terencez 0:1fa43ab66921 150 observedP->watcherList = watcherP;
terencez 0:1fa43ab66921 151 }
terencez 0:1fa43ab66921 152
terencez 0:1fa43ab66921 153 return watcherP;
terencez 0:1fa43ab66921 154 }
terencez 0:1fa43ab66921 155
terencez 0:1fa43ab66921 156 coap_status_t observe_handleRequest(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 157 lwm2m_uri_t * uriP,
terencez 0:1fa43ab66921 158 lwm2m_server_t * serverP,
terencez 0:1fa43ab66921 159 int size,
terencez 0:1fa43ab66921 160 lwm2m_data_t * dataP,
terencez 0:1fa43ab66921 161 coap_packet_t * message,
terencez 0:1fa43ab66921 162 coap_packet_t * response)
terencez 0:1fa43ab66921 163 {
terencez 0:1fa43ab66921 164 lwm2m_watcher_t * watcherP;
terencez 0:1fa43ab66921 165 uint32_t count;
terencez 0:1fa43ab66921 166
terencez 0:1fa43ab66921 167 LOG_ARG("Code: %02X, server status: %s", message->code, STR_STATUS(serverP->status));
terencez 0:1fa43ab66921 168 LOG_URI(uriP);
terencez 0:1fa43ab66921 169
terencez 0:1fa43ab66921 170 coap_get_header_observe(message, &count);
terencez 0:1fa43ab66921 171
terencez 0:1fa43ab66921 172 switch (count)
terencez 0:1fa43ab66921 173 {
terencez 0:1fa43ab66921 174 case 0:
terencez 0:1fa43ab66921 175 if (!LWM2M_URI_IS_SET_INSTANCE(uriP) && LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 176 if (message->token_len == 0) return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 177
terencez 0:1fa43ab66921 178 watcherP = prv_getWatcher(contextP, uriP, serverP);
terencez 0:1fa43ab66921 179 if (watcherP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 180
terencez 0:1fa43ab66921 181 watcherP->tokenLen = message->token_len;
terencez 0:1fa43ab66921 182 memcpy(watcherP->token, message->token, message->token_len);
terencez 0:1fa43ab66921 183 watcherP->active = true;
terencez 0:1fa43ab66921 184 watcherP->lastTime = lwm2m_gettime();
terencez 0:1fa43ab66921 185
terencez 0:1fa43ab66921 186 if (LWM2M_URI_IS_SET_RESOURCE(uriP))
terencez 0:1fa43ab66921 187 {
terencez 0:1fa43ab66921 188 switch (dataP->type)
terencez 0:1fa43ab66921 189 {
terencez 0:1fa43ab66921 190 case LWM2M_TYPE_INTEGER:
terencez 0:1fa43ab66921 191 if (1 != lwm2m_data_decode_int(dataP, &(watcherP->lastValue.asInteger))) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 192 break;
terencez 0:1fa43ab66921 193 case LWM2M_TYPE_FLOAT:
terencez 0:1fa43ab66921 194 if (1 != lwm2m_data_decode_float(dataP, &(watcherP->lastValue.asFloat))) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 195 break;
terencez 0:1fa43ab66921 196 default:
terencez 0:1fa43ab66921 197 break;
terencez 0:1fa43ab66921 198 }
terencez 0:1fa43ab66921 199 }
terencez 0:1fa43ab66921 200
terencez 0:1fa43ab66921 201 coap_set_header_observe(response, watcherP->counter++);
terencez 0:1fa43ab66921 202
terencez 0:1fa43ab66921 203 return COAP_205_CONTENT;
terencez 0:1fa43ab66921 204
terencez 0:1fa43ab66921 205 case 1:
terencez 0:1fa43ab66921 206 // cancellation
terencez 0:1fa43ab66921 207 observe_cancel(contextP, LWM2M_MAX_ID, serverP->sessionH);
terencez 0:1fa43ab66921 208 return COAP_205_CONTENT;
terencez 0:1fa43ab66921 209
terencez 0:1fa43ab66921 210 default:
terencez 0:1fa43ab66921 211 return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 212 }
terencez 0:1fa43ab66921 213 }
terencez 0:1fa43ab66921 214
terencez 0:1fa43ab66921 215 void observe_cancel(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 216 uint16_t mid,
terencez 0:1fa43ab66921 217 void * fromSessionH)
terencez 0:1fa43ab66921 218 {
terencez 0:1fa43ab66921 219 lwm2m_observed_t * observedP;
terencez 0:1fa43ab66921 220
terencez 0:1fa43ab66921 221 LOG_ARG("mid: %d", mid);
terencez 0:1fa43ab66921 222
terencez 0:1fa43ab66921 223 for (observedP = contextP->observedList;
terencez 0:1fa43ab66921 224 observedP != NULL;
terencez 0:1fa43ab66921 225 observedP = observedP->next)
terencez 0:1fa43ab66921 226 {
terencez 0:1fa43ab66921 227 lwm2m_watcher_t * targetP = NULL;
terencez 0:1fa43ab66921 228
terencez 0:1fa43ab66921 229 if ((LWM2M_MAX_ID == mid || observedP->watcherList->lastMid == mid)
terencez 0:1fa43ab66921 230 && lwm2m_session_is_equal(observedP->watcherList->server->sessionH, fromSessionH, contextP->userData))
terencez 0:1fa43ab66921 231 {
terencez 0:1fa43ab66921 232 targetP = observedP->watcherList;
terencez 0:1fa43ab66921 233 observedP->watcherList = observedP->watcherList->next;
terencez 0:1fa43ab66921 234 }
terencez 0:1fa43ab66921 235 else
terencez 0:1fa43ab66921 236 {
terencez 0:1fa43ab66921 237 lwm2m_watcher_t * parentP;
terencez 0:1fa43ab66921 238
terencez 0:1fa43ab66921 239 parentP = observedP->watcherList;
terencez 0:1fa43ab66921 240 while (parentP->next != NULL
terencez 0:1fa43ab66921 241 && (parentP->next->lastMid != mid
terencez 0:1fa43ab66921 242 || lwm2m_session_is_equal(parentP->next->server->sessionH, fromSessionH, contextP->userData)))
terencez 0:1fa43ab66921 243 {
terencez 0:1fa43ab66921 244 parentP = parentP->next;
terencez 0:1fa43ab66921 245 }
terencez 0:1fa43ab66921 246 if (parentP->next != NULL)
terencez 0:1fa43ab66921 247 {
terencez 0:1fa43ab66921 248 targetP = parentP->next;
terencez 0:1fa43ab66921 249 parentP->next = parentP->next->next;
terencez 0:1fa43ab66921 250 }
terencez 0:1fa43ab66921 251 }
terencez 0:1fa43ab66921 252 if (targetP != NULL)
terencez 0:1fa43ab66921 253 {
terencez 0:1fa43ab66921 254 lwm2m_free(targetP);
terencez 0:1fa43ab66921 255 if (observedP->watcherList == NULL)
terencez 0:1fa43ab66921 256 {
terencez 0:1fa43ab66921 257 prv_unlinkObserved(contextP, observedP);
terencez 0:1fa43ab66921 258 lwm2m_free(observedP);
terencez 0:1fa43ab66921 259 }
terencez 0:1fa43ab66921 260 return;
terencez 0:1fa43ab66921 261 }
terencez 0:1fa43ab66921 262 }
terencez 0:1fa43ab66921 263 }
terencez 0:1fa43ab66921 264
terencez 0:1fa43ab66921 265 coap_status_t observe_setParameters(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 266 lwm2m_uri_t * uriP,
terencez 0:1fa43ab66921 267 lwm2m_server_t * serverP,
terencez 0:1fa43ab66921 268 lwm2m_attributes_t * attrP)
terencez 0:1fa43ab66921 269 {
terencez 0:1fa43ab66921 270 uint8_t result;
terencez 0:1fa43ab66921 271 lwm2m_watcher_t * watcherP;
terencez 0:1fa43ab66921 272
terencez 0:1fa43ab66921 273 LOG_URI(uriP);
terencez 0:1fa43ab66921 274 LOG_ARG("toSet: %08X, toClear: %08X, minPeriod: %d, maxPeriod: %d, greaterThan: %f, lessThan: %f, step: %f",
terencez 0:1fa43ab66921 275 attrP->toSet, attrP->toClear, attrP->minPeriod, attrP->maxPeriod, attrP->greaterThan, attrP->lessThan, attrP->step);
terencez 0:1fa43ab66921 276
terencez 0:1fa43ab66921 277 if (!LWM2M_URI_IS_SET_INSTANCE(uriP) && LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 278
terencez 0:1fa43ab66921 279 result = object_checkReadable(contextP, uriP);
terencez 0:1fa43ab66921 280 if (COAP_205_CONTENT != result) return result;
terencez 0:1fa43ab66921 281
terencez 0:1fa43ab66921 282 if (0 != (attrP->toSet & ATTR_FLAG_NUMERIC))
terencez 0:1fa43ab66921 283 {
terencez 0:1fa43ab66921 284 result = object_checkNumeric(contextP, uriP);
terencez 0:1fa43ab66921 285 if (COAP_205_CONTENT != result) return result;
terencez 0:1fa43ab66921 286 }
terencez 0:1fa43ab66921 287
terencez 0:1fa43ab66921 288 watcherP = prv_getWatcher(contextP, uriP, serverP);
terencez 0:1fa43ab66921 289 if (watcherP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 290
terencez 0:1fa43ab66921 291 // Check rule “lt” value + 2*”stp” values < “gt” value
terencez 0:1fa43ab66921 292 if ((((attrP->toSet | (watcherP->parameters?watcherP->parameters->toSet:0)) & ~attrP->toClear) & ATTR_FLAG_NUMERIC) == ATTR_FLAG_NUMERIC)
terencez 0:1fa43ab66921 293 {
terencez 0:1fa43ab66921 294 float gt;
terencez 0:1fa43ab66921 295 float lt;
terencez 0:1fa43ab66921 296 float stp;
terencez 0:1fa43ab66921 297
terencez 0:1fa43ab66921 298 if (0 != (attrP->toSet & LWM2M_ATTR_FLAG_GREATER_THAN))
terencez 0:1fa43ab66921 299 {
terencez 0:1fa43ab66921 300 gt = attrP->greaterThan;
terencez 0:1fa43ab66921 301 }
terencez 0:1fa43ab66921 302 else
terencez 0:1fa43ab66921 303 {
terencez 0:1fa43ab66921 304 gt = watcherP->parameters->greaterThan;
terencez 0:1fa43ab66921 305 }
terencez 0:1fa43ab66921 306 if (0 != (attrP->toSet & LWM2M_ATTR_FLAG_LESS_THAN))
terencez 0:1fa43ab66921 307 {
terencez 0:1fa43ab66921 308 lt = attrP->lessThan;
terencez 0:1fa43ab66921 309 }
terencez 0:1fa43ab66921 310 else
terencez 0:1fa43ab66921 311 {
terencez 0:1fa43ab66921 312 lt = watcherP->parameters->lessThan;
terencez 0:1fa43ab66921 313 }
terencez 0:1fa43ab66921 314 if (0 != (attrP->toSet & LWM2M_ATTR_FLAG_STEP))
terencez 0:1fa43ab66921 315 {
terencez 0:1fa43ab66921 316 stp = attrP->step;
terencez 0:1fa43ab66921 317 }
terencez 0:1fa43ab66921 318 else
terencez 0:1fa43ab66921 319 {
terencez 0:1fa43ab66921 320 stp = watcherP->parameters->step;
terencez 0:1fa43ab66921 321 }
terencez 0:1fa43ab66921 322
terencez 0:1fa43ab66921 323 if (lt + (2 * stp) >= gt) return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 324 }
terencez 0:1fa43ab66921 325
terencez 0:1fa43ab66921 326 if (watcherP->parameters == NULL)
terencez 0:1fa43ab66921 327 {
terencez 0:1fa43ab66921 328 if (attrP->toSet != 0)
terencez 0:1fa43ab66921 329 {
terencez 0:1fa43ab66921 330 watcherP->parameters = (lwm2m_attributes_t *)lwm2m_malloc(sizeof(lwm2m_attributes_t));
terencez 0:1fa43ab66921 331 if (watcherP->parameters == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 332 memcpy(watcherP->parameters, attrP, sizeof(lwm2m_attributes_t));
terencez 0:1fa43ab66921 333 }
terencez 0:1fa43ab66921 334 }
terencez 0:1fa43ab66921 335 else
terencez 0:1fa43ab66921 336 {
terencez 0:1fa43ab66921 337 watcherP->parameters->toSet &= ~attrP->toClear;
terencez 0:1fa43ab66921 338 if (attrP->toSet & LWM2M_ATTR_FLAG_MIN_PERIOD)
terencez 0:1fa43ab66921 339 {
terencez 0:1fa43ab66921 340 watcherP->parameters->minPeriod = attrP->minPeriod;
terencez 0:1fa43ab66921 341 }
terencez 0:1fa43ab66921 342 if (attrP->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD)
terencez 0:1fa43ab66921 343 {
terencez 0:1fa43ab66921 344 watcherP->parameters->maxPeriod = attrP->maxPeriod;
terencez 0:1fa43ab66921 345 }
terencez 0:1fa43ab66921 346 if (attrP->toSet & LWM2M_ATTR_FLAG_GREATER_THAN)
terencez 0:1fa43ab66921 347 {
terencez 0:1fa43ab66921 348 watcherP->parameters->greaterThan = attrP->greaterThan;
terencez 0:1fa43ab66921 349 }
terencez 0:1fa43ab66921 350 if (attrP->toSet & LWM2M_ATTR_FLAG_LESS_THAN)
terencez 0:1fa43ab66921 351 {
terencez 0:1fa43ab66921 352 watcherP->parameters->lessThan = attrP->lessThan;
terencez 0:1fa43ab66921 353 }
terencez 0:1fa43ab66921 354 if (attrP->toSet & LWM2M_ATTR_FLAG_STEP)
terencez 0:1fa43ab66921 355 {
terencez 0:1fa43ab66921 356 watcherP->parameters->step = attrP->step;
terencez 0:1fa43ab66921 357 }
terencez 0:1fa43ab66921 358 }
terencez 0:1fa43ab66921 359
terencez 0:1fa43ab66921 360 LOG_ARG("Final toSet: %08X, minPeriod: %d, maxPeriod: %d, greaterThan: %f, lessThan: %f, step: %f",
terencez 0:1fa43ab66921 361 watcherP->parameters->toSet, watcherP->parameters->minPeriod, watcherP->parameters->maxPeriod, watcherP->parameters->greaterThan, watcherP->parameters->lessThan, watcherP->parameters->step);
terencez 0:1fa43ab66921 362
terencez 0:1fa43ab66921 363 return COAP_204_CHANGED;
terencez 0:1fa43ab66921 364 }
terencez 0:1fa43ab66921 365
terencez 0:1fa43ab66921 366 lwm2m_observed_t * observe_findByUri(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 367 lwm2m_uri_t * uriP)
terencez 0:1fa43ab66921 368 {
terencez 0:1fa43ab66921 369 lwm2m_observed_t * targetP;
terencez 0:1fa43ab66921 370
terencez 0:1fa43ab66921 371 LOG_URI(uriP);
terencez 0:1fa43ab66921 372 targetP = contextP->observedList;
terencez 0:1fa43ab66921 373 while (targetP != NULL)
terencez 0:1fa43ab66921 374 {
terencez 0:1fa43ab66921 375 if (targetP->uri.objectId == uriP->objectId)
terencez 0:1fa43ab66921 376 {
terencez 0:1fa43ab66921 377 if ((!LWM2M_URI_IS_SET_INSTANCE(uriP) && !LWM2M_URI_IS_SET_INSTANCE(&(targetP->uri)))
terencez 0:1fa43ab66921 378 || (LWM2M_URI_IS_SET_INSTANCE(uriP) && LWM2M_URI_IS_SET_INSTANCE(&(targetP->uri)) && (uriP->instanceId == targetP->uri.instanceId)))
terencez 0:1fa43ab66921 379 {
terencez 0:1fa43ab66921 380 if ((!LWM2M_URI_IS_SET_RESOURCE(uriP) && !LWM2M_URI_IS_SET_RESOURCE(&(targetP->uri)))
terencez 0:1fa43ab66921 381 || (LWM2M_URI_IS_SET_RESOURCE(uriP) && LWM2M_URI_IS_SET_RESOURCE(&(targetP->uri)) && (uriP->resourceId == targetP->uri.resourceId)))
terencez 0:1fa43ab66921 382 {
terencez 0:1fa43ab66921 383 LOG_ARG("Found one with%s observers.", targetP->watcherList ? "" : " no");
terencez 0:1fa43ab66921 384 LOG_URI(&(targetP->uri));
terencez 0:1fa43ab66921 385 return targetP;
terencez 0:1fa43ab66921 386 }
terencez 0:1fa43ab66921 387 }
terencez 0:1fa43ab66921 388 }
terencez 0:1fa43ab66921 389 targetP = targetP->next;
terencez 0:1fa43ab66921 390 }
terencez 0:1fa43ab66921 391
terencez 0:1fa43ab66921 392 LOG("Found nothing");
terencez 0:1fa43ab66921 393 return NULL;
terencez 0:1fa43ab66921 394 }
terencez 0:1fa43ab66921 395
terencez 0:1fa43ab66921 396 void lwm2m_resource_value_changed(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 397 lwm2m_uri_t * uriP)
terencez 0:1fa43ab66921 398 {
terencez 0:1fa43ab66921 399 lwm2m_observed_t * targetP;
terencez 0:1fa43ab66921 400
terencez 0:1fa43ab66921 401 LOG_URI(uriP);
terencez 0:1fa43ab66921 402 targetP = contextP->observedList;
terencez 0:1fa43ab66921 403 while (targetP != NULL)
terencez 0:1fa43ab66921 404 {
terencez 0:1fa43ab66921 405 if (targetP->uri.objectId == uriP->objectId)
terencez 0:1fa43ab66921 406 {
terencez 0:1fa43ab66921 407 if (!LWM2M_URI_IS_SET_INSTANCE(uriP)
terencez 0:1fa43ab66921 408 || (targetP->uri.flag & LWM2M_URI_FLAG_INSTANCE_ID) == 0
terencez 0:1fa43ab66921 409 || uriP->instanceId == targetP->uri.instanceId)
terencez 0:1fa43ab66921 410 {
terencez 0:1fa43ab66921 411 if (!LWM2M_URI_IS_SET_RESOURCE(uriP)
terencez 0:1fa43ab66921 412 || (targetP->uri.flag & LWM2M_URI_FLAG_RESOURCE_ID) == 0
terencez 0:1fa43ab66921 413 || uriP->resourceId == targetP->uri.resourceId)
terencez 0:1fa43ab66921 414 {
terencez 0:1fa43ab66921 415 lwm2m_watcher_t * watcherP;
terencez 0:1fa43ab66921 416
terencez 0:1fa43ab66921 417 LOG("Found an observation");
terencez 0:1fa43ab66921 418 LOG_URI(&(targetP->uri));
terencez 0:1fa43ab66921 419
terencez 0:1fa43ab66921 420 for (watcherP = targetP->watcherList ; watcherP != NULL ; watcherP = watcherP->next)
terencez 0:1fa43ab66921 421 {
terencez 0:1fa43ab66921 422 if (watcherP->active == true)
terencez 0:1fa43ab66921 423 {
terencez 0:1fa43ab66921 424 LOG("Tagging a watcher");
terencez 0:1fa43ab66921 425 watcherP->update = true;
terencez 0:1fa43ab66921 426 }
terencez 0:1fa43ab66921 427 }
terencez 0:1fa43ab66921 428 }
terencez 0:1fa43ab66921 429 }
terencez 0:1fa43ab66921 430 }
terencez 0:1fa43ab66921 431 targetP = targetP->next;
terencez 0:1fa43ab66921 432 }
terencez 0:1fa43ab66921 433 }
terencez 0:1fa43ab66921 434
terencez 0:1fa43ab66921 435 void observe_step(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 436 time_t currentTime,
terencez 0:1fa43ab66921 437 time_t * timeoutP)
terencez 0:1fa43ab66921 438 {
terencez 0:1fa43ab66921 439 lwm2m_observed_t * targetP;
terencez 0:1fa43ab66921 440
terencez 0:1fa43ab66921 441 LOG("Entering");
terencez 0:1fa43ab66921 442 for (targetP = contextP->observedList ; targetP != NULL ; targetP = targetP->next)
terencez 0:1fa43ab66921 443 {
terencez 0:1fa43ab66921 444 lwm2m_watcher_t * watcherP;
terencez 0:1fa43ab66921 445 uint8_t * buffer = NULL;
terencez 0:1fa43ab66921 446 size_t length = 0;
terencez 0:1fa43ab66921 447 lwm2m_data_t * dataP = NULL;
terencez 0:1fa43ab66921 448 int size = 0;
terencez 0:1fa43ab66921 449 double floatValue = 0;
terencez 0:1fa43ab66921 450 int64_t integerValue = 0;
terencez 0:1fa43ab66921 451 bool storeValue = false;
terencez 0:1fa43ab66921 452 lwm2m_media_type_t format = LWM2M_CONTENT_TEXT;
terencez 0:1fa43ab66921 453 coap_packet_t message[1];
terencez 0:1fa43ab66921 454 time_t interval;
terencez 0:1fa43ab66921 455
terencez 0:1fa43ab66921 456 LOG_URI(&(targetP->uri));
terencez 0:1fa43ab66921 457 if (LWM2M_URI_IS_SET_RESOURCE(&targetP->uri))
terencez 0:1fa43ab66921 458 {
terencez 0:1fa43ab66921 459 if (COAP_205_CONTENT != object_readData(contextP, &targetP->uri, &size, &dataP)) continue;
terencez 0:1fa43ab66921 460 switch (dataP->type)
terencez 0:1fa43ab66921 461 {
terencez 0:1fa43ab66921 462 case LWM2M_TYPE_INTEGER:
terencez 0:1fa43ab66921 463 if (1 != lwm2m_data_decode_int(dataP, &integerValue)) continue;
terencez 0:1fa43ab66921 464 storeValue = true;
terencez 0:1fa43ab66921 465 break;
terencez 0:1fa43ab66921 466 case LWM2M_TYPE_FLOAT:
terencez 0:1fa43ab66921 467 if (1 != lwm2m_data_decode_float(dataP, &floatValue)) continue;
terencez 0:1fa43ab66921 468 storeValue = true;
terencez 0:1fa43ab66921 469 break;
terencez 0:1fa43ab66921 470 default:
terencez 0:1fa43ab66921 471 break;
terencez 0:1fa43ab66921 472 }
terencez 0:1fa43ab66921 473 }
terencez 0:1fa43ab66921 474 for (watcherP = targetP->watcherList ; watcherP != NULL ; watcherP = watcherP->next)
terencez 0:1fa43ab66921 475 {
terencez 0:1fa43ab66921 476 if (watcherP->active == true)
terencez 0:1fa43ab66921 477 {
terencez 0:1fa43ab66921 478 bool notify = false;
terencez 0:1fa43ab66921 479
terencez 0:1fa43ab66921 480 if (watcherP->update == true)
terencez 0:1fa43ab66921 481 {
terencez 0:1fa43ab66921 482 // value changed, should we notify the server ?
terencez 0:1fa43ab66921 483
terencez 0:1fa43ab66921 484 if (watcherP->parameters == NULL || watcherP->parameters->toSet == 0)
terencez 0:1fa43ab66921 485 {
terencez 0:1fa43ab66921 486 // no conditions
terencez 0:1fa43ab66921 487 notify = true;
terencez 0:1fa43ab66921 488 LOG("Notify with no conditions");
terencez 0:1fa43ab66921 489 LOG_URI(&(targetP->uri));
terencez 0:1fa43ab66921 490 }
terencez 0:1fa43ab66921 491
terencez 0:1fa43ab66921 492 if (notify == false
terencez 0:1fa43ab66921 493 && watcherP->parameters != NULL
terencez 0:1fa43ab66921 494 && (watcherP->parameters->toSet & ATTR_FLAG_NUMERIC) != 0)
terencez 0:1fa43ab66921 495 {
terencez 0:1fa43ab66921 496 if ((watcherP->parameters->toSet & LWM2M_ATTR_FLAG_LESS_THAN) != 0)
terencez 0:1fa43ab66921 497 {
terencez 0:1fa43ab66921 498 LOG("Checking lower treshold");
terencez 0:1fa43ab66921 499 // Did we cross the lower treshold ?
terencez 0:1fa43ab66921 500 switch (dataP->type)
terencez 0:1fa43ab66921 501 {
terencez 0:1fa43ab66921 502 case LWM2M_TYPE_INTEGER:
terencez 0:1fa43ab66921 503 if ((integerValue <= watcherP->parameters->lessThan
terencez 0:1fa43ab66921 504 && watcherP->lastValue.asInteger > watcherP->parameters->lessThan)
terencez 0:1fa43ab66921 505 || (integerValue >= watcherP->parameters->lessThan
terencez 0:1fa43ab66921 506 && watcherP->lastValue.asInteger < watcherP->parameters->lessThan))
terencez 0:1fa43ab66921 507 {
terencez 0:1fa43ab66921 508 LOG("Notify on lower treshold crossing");
terencez 0:1fa43ab66921 509 notify = true;
terencez 0:1fa43ab66921 510 }
terencez 0:1fa43ab66921 511 break;
terencez 0:1fa43ab66921 512 case LWM2M_TYPE_FLOAT:
terencez 0:1fa43ab66921 513 if ((floatValue <= watcherP->parameters->lessThan
terencez 0:1fa43ab66921 514 && watcherP->lastValue.asFloat > watcherP->parameters->lessThan)
terencez 0:1fa43ab66921 515 || (floatValue >= watcherP->parameters->lessThan
terencez 0:1fa43ab66921 516 && watcherP->lastValue.asFloat < watcherP->parameters->lessThan))
terencez 0:1fa43ab66921 517 {
terencez 0:1fa43ab66921 518 LOG("Notify on lower treshold crossing");
terencez 0:1fa43ab66921 519 notify = true;
terencez 0:1fa43ab66921 520 }
terencez 0:1fa43ab66921 521 break;
terencez 0:1fa43ab66921 522 default:
terencez 0:1fa43ab66921 523 break;
terencez 0:1fa43ab66921 524 }
terencez 0:1fa43ab66921 525 }
terencez 0:1fa43ab66921 526 if ((watcherP->parameters->toSet & LWM2M_ATTR_FLAG_GREATER_THAN) != 0)
terencez 0:1fa43ab66921 527 {
terencez 0:1fa43ab66921 528 LOG("Checking upper treshold");
terencez 0:1fa43ab66921 529 // Did we cross the upper treshold ?
terencez 0:1fa43ab66921 530 switch (dataP->type)
terencez 0:1fa43ab66921 531 {
terencez 0:1fa43ab66921 532 case LWM2M_TYPE_INTEGER:
terencez 0:1fa43ab66921 533 if ((integerValue <= watcherP->parameters->greaterThan
terencez 0:1fa43ab66921 534 && watcherP->lastValue.asInteger > watcherP->parameters->greaterThan)
terencez 0:1fa43ab66921 535 || (integerValue >= watcherP->parameters->greaterThan
terencez 0:1fa43ab66921 536 && watcherP->lastValue.asInteger < watcherP->parameters->greaterThan))
terencez 0:1fa43ab66921 537 {
terencez 0:1fa43ab66921 538 LOG("Notify on lower upper crossing");
terencez 0:1fa43ab66921 539 notify = true;
terencez 0:1fa43ab66921 540 }
terencez 0:1fa43ab66921 541 break;
terencez 0:1fa43ab66921 542 case LWM2M_TYPE_FLOAT:
terencez 0:1fa43ab66921 543 if ((floatValue <= watcherP->parameters->greaterThan
terencez 0:1fa43ab66921 544 && watcherP->lastValue.asFloat > watcherP->parameters->greaterThan)
terencez 0:1fa43ab66921 545 || (floatValue >= watcherP->parameters->greaterThan
terencez 0:1fa43ab66921 546 && watcherP->lastValue.asFloat < watcherP->parameters->greaterThan))
terencez 0:1fa43ab66921 547 {
terencez 0:1fa43ab66921 548 LOG("Notify on lower upper crossing");
terencez 0:1fa43ab66921 549 notify = true;
terencez 0:1fa43ab66921 550 }
terencez 0:1fa43ab66921 551 break;
terencez 0:1fa43ab66921 552 default:
terencez 0:1fa43ab66921 553 break;
terencez 0:1fa43ab66921 554 }
terencez 0:1fa43ab66921 555 }
terencez 0:1fa43ab66921 556 if ((watcherP->parameters->toSet & LWM2M_ATTR_FLAG_STEP) != 0)
terencez 0:1fa43ab66921 557 {
terencez 0:1fa43ab66921 558 LOG("Checking step");
terencez 0:1fa43ab66921 559
terencez 0:1fa43ab66921 560 switch (dataP->type)
terencez 0:1fa43ab66921 561 {
terencez 0:1fa43ab66921 562 case LWM2M_TYPE_INTEGER:
terencez 0:1fa43ab66921 563 {
terencez 0:1fa43ab66921 564 int64_t diff;
terencez 0:1fa43ab66921 565
terencez 0:1fa43ab66921 566 diff = integerValue - watcherP->lastValue.asInteger;
terencez 0:1fa43ab66921 567 if ((diff < 0 && (0 - diff) >= watcherP->parameters->step)
terencez 0:1fa43ab66921 568 || (diff >= 0 && diff >= watcherP->parameters->step))
terencez 0:1fa43ab66921 569 {
terencez 0:1fa43ab66921 570 LOG("Notify on step condition");
terencez 0:1fa43ab66921 571 notify = true;
terencez 0:1fa43ab66921 572 }
terencez 0:1fa43ab66921 573 }
terencez 0:1fa43ab66921 574 break;
terencez 0:1fa43ab66921 575 case LWM2M_TYPE_FLOAT:
terencez 0:1fa43ab66921 576 {
terencez 0:1fa43ab66921 577 double diff;
terencez 0:1fa43ab66921 578
terencez 0:1fa43ab66921 579 diff = floatValue - watcherP->lastValue.asFloat;
terencez 0:1fa43ab66921 580 if ((diff < 0 && (0 - diff) >= watcherP->parameters->step)
terencez 0:1fa43ab66921 581 || (diff >= 0 && diff >= watcherP->parameters->step))
terencez 0:1fa43ab66921 582 {
terencez 0:1fa43ab66921 583 LOG("Notify on step condition");
terencez 0:1fa43ab66921 584 notify = true;
terencez 0:1fa43ab66921 585 }
terencez 0:1fa43ab66921 586 }
terencez 0:1fa43ab66921 587 break;
terencez 0:1fa43ab66921 588 default:
terencez 0:1fa43ab66921 589 break;
terencez 0:1fa43ab66921 590 }
terencez 0:1fa43ab66921 591 }
terencez 0:1fa43ab66921 592 }
terencez 0:1fa43ab66921 593
terencez 0:1fa43ab66921 594 if (watcherP->parameters != NULL
terencez 0:1fa43ab66921 595 && (watcherP->parameters->toSet & LWM2M_ATTR_FLAG_MIN_PERIOD) != 0)
terencez 0:1fa43ab66921 596 {
terencez 0:1fa43ab66921 597 LOG_ARG("Checking minimal period (%d s)", watcherP->parameters->minPeriod);
terencez 0:1fa43ab66921 598
terencez 0:1fa43ab66921 599 if (watcherP->lastTime + watcherP->parameters->minPeriod > currentTime)
terencez 0:1fa43ab66921 600 {
terencez 0:1fa43ab66921 601 // Minimum Period did not elapse yet
terencez 0:1fa43ab66921 602 interval = watcherP->lastTime + watcherP->parameters->minPeriod - currentTime;
terencez 0:1fa43ab66921 603 if (*timeoutP > interval) *timeoutP = interval;
terencez 0:1fa43ab66921 604 notify = false;
terencez 0:1fa43ab66921 605 }
terencez 0:1fa43ab66921 606 else
terencez 0:1fa43ab66921 607 {
terencez 0:1fa43ab66921 608 LOG("Notify on minimal period");
terencez 0:1fa43ab66921 609 notify = true;
terencez 0:1fa43ab66921 610 }
terencez 0:1fa43ab66921 611 }
terencez 0:1fa43ab66921 612 }
terencez 0:1fa43ab66921 613
terencez 0:1fa43ab66921 614 // Is the Maximum Period reached ?
terencez 0:1fa43ab66921 615 if (notify == false
terencez 0:1fa43ab66921 616 && watcherP->parameters != NULL
terencez 0:1fa43ab66921 617 && (watcherP->parameters->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD) != 0)
terencez 0:1fa43ab66921 618 {
terencez 0:1fa43ab66921 619 LOG_ARG("Checking maximal period (%d s)", watcherP->parameters->minPeriod);
terencez 0:1fa43ab66921 620
terencez 0:1fa43ab66921 621 if (watcherP->lastTime + watcherP->parameters->maxPeriod <= currentTime)
terencez 0:1fa43ab66921 622 {
terencez 0:1fa43ab66921 623 LOG("Notify on maximal period");
terencez 0:1fa43ab66921 624 notify = true;
terencez 0:1fa43ab66921 625 }
terencez 0:1fa43ab66921 626 }
terencez 0:1fa43ab66921 627
terencez 0:1fa43ab66921 628 if (notify == true)
terencez 0:1fa43ab66921 629 {
terencez 0:1fa43ab66921 630 if (buffer == NULL)
terencez 0:1fa43ab66921 631 {
terencez 0:1fa43ab66921 632 if (dataP != NULL)
terencez 0:1fa43ab66921 633 {
terencez 0:1fa43ab66921 634 int res;
terencez 0:1fa43ab66921 635
terencez 0:1fa43ab66921 636 res = lwm2m_data_serialize(&targetP->uri, size, dataP, &format, &buffer);
terencez 0:1fa43ab66921 637 if (res < 0)
terencez 0:1fa43ab66921 638 {
terencez 0:1fa43ab66921 639 break;
terencez 0:1fa43ab66921 640 }
terencez 0:1fa43ab66921 641 else
terencez 0:1fa43ab66921 642 {
terencez 0:1fa43ab66921 643 length = (size_t)res;
terencez 0:1fa43ab66921 644 }
terencez 0:1fa43ab66921 645
terencez 0:1fa43ab66921 646 }
terencez 0:1fa43ab66921 647 else
terencez 0:1fa43ab66921 648 {
terencez 0:1fa43ab66921 649 if (COAP_205_CONTENT != object_read(contextP, &targetP->uri, &format, &buffer, &length))
terencez 0:1fa43ab66921 650 {
terencez 0:1fa43ab66921 651 buffer = NULL;
terencez 0:1fa43ab66921 652 break;
terencez 0:1fa43ab66921 653 }
terencez 0:1fa43ab66921 654 }
terencez 0:1fa43ab66921 655 coap_init_message(message, COAP_TYPE_NON, COAP_205_CONTENT, 0);
terencez 0:1fa43ab66921 656 coap_set_header_content_type(message, format);
terencez 0:1fa43ab66921 657 coap_set_payload(message, buffer, length);
terencez 0:1fa43ab66921 658 }
terencez 0:1fa43ab66921 659 watcherP->lastTime = currentTime;
terencez 0:1fa43ab66921 660 watcherP->lastMid = contextP->nextMID++;
terencez 0:1fa43ab66921 661 message->mid = watcherP->lastMid;
terencez 0:1fa43ab66921 662 coap_set_header_token(message, watcherP->token, watcherP->tokenLen);
terencez 0:1fa43ab66921 663 coap_set_header_observe(message, watcherP->counter++);
terencez 0:1fa43ab66921 664 (void)message_send(contextP, message, watcherP->server->sessionH);
terencez 0:1fa43ab66921 665 watcherP->update = false;
terencez 0:1fa43ab66921 666 }
terencez 0:1fa43ab66921 667
terencez 0:1fa43ab66921 668 // Store this value
terencez 0:1fa43ab66921 669 if (notify == true && storeValue == true)
terencez 0:1fa43ab66921 670 {
terencez 0:1fa43ab66921 671 switch (dataP->type)
terencez 0:1fa43ab66921 672 {
terencez 0:1fa43ab66921 673 case LWM2M_TYPE_INTEGER:
terencez 0:1fa43ab66921 674 watcherP->lastValue.asInteger = integerValue;
terencez 0:1fa43ab66921 675 break;
terencez 0:1fa43ab66921 676 case LWM2M_TYPE_FLOAT:
terencez 0:1fa43ab66921 677 watcherP->lastValue.asFloat = floatValue;
terencez 0:1fa43ab66921 678 break;
terencez 0:1fa43ab66921 679 default:
terencez 0:1fa43ab66921 680 break;
terencez 0:1fa43ab66921 681 }
terencez 0:1fa43ab66921 682 }
terencez 0:1fa43ab66921 683
terencez 0:1fa43ab66921 684 if (watcherP->parameters != NULL && (watcherP->parameters->toSet & LWM2M_ATTR_FLAG_MAX_PERIOD) != 0)
terencez 0:1fa43ab66921 685 {
terencez 0:1fa43ab66921 686 // update timers
terencez 0:1fa43ab66921 687 interval = watcherP->lastTime + watcherP->parameters->maxPeriod - currentTime;
terencez 0:1fa43ab66921 688 if (*timeoutP > interval) *timeoutP = interval;
terencez 0:1fa43ab66921 689 }
terencez 0:1fa43ab66921 690 }
terencez 0:1fa43ab66921 691 }
terencez 0:1fa43ab66921 692 if (dataP != NULL) lwm2m_data_free(size, dataP);
terencez 0:1fa43ab66921 693 if (buffer != NULL) lwm2m_free(buffer);
terencez 0:1fa43ab66921 694 }
terencez 0:1fa43ab66921 695 }
terencez 0:1fa43ab66921 696
terencez 0:1fa43ab66921 697 #endif
terencez 0:1fa43ab66921 698
terencez 0:1fa43ab66921 699 #ifdef LWM2M_SERVER_MODE
terencez 0:1fa43ab66921 700
terencez 0:1fa43ab66921 701 typedef struct
terencez 0:1fa43ab66921 702 {
terencez 0:1fa43ab66921 703 lwm2m_observation_t * observationP;
terencez 0:1fa43ab66921 704 lwm2m_result_callback_t callbackP;
terencez 0:1fa43ab66921 705 void * userDataP;
terencez 0:1fa43ab66921 706 } cancellation_data_t;
terencez 0:1fa43ab66921 707
terencez 0:1fa43ab66921 708 static lwm2m_observation_t * prv_findObservationByURI(lwm2m_client_t * clientP,
terencez 0:1fa43ab66921 709 lwm2m_uri_t * uriP)
terencez 0:1fa43ab66921 710 {
terencez 0:1fa43ab66921 711 lwm2m_observation_t * targetP;
terencez 0:1fa43ab66921 712
terencez 0:1fa43ab66921 713 targetP = clientP->observationList;
terencez 0:1fa43ab66921 714 while (targetP != NULL)
terencez 0:1fa43ab66921 715 {
terencez 0:1fa43ab66921 716 if (targetP->uri.objectId == uriP->objectId
terencez 0:1fa43ab66921 717 && targetP->uri.flag == uriP->flag
terencez 0:1fa43ab66921 718 && targetP->uri.instanceId == uriP->instanceId
terencez 0:1fa43ab66921 719 && targetP->uri.resourceId == uriP->resourceId)
terencez 0:1fa43ab66921 720 {
terencez 0:1fa43ab66921 721 return targetP;
terencez 0:1fa43ab66921 722 }
terencez 0:1fa43ab66921 723
terencez 0:1fa43ab66921 724 targetP = targetP->next;
terencez 0:1fa43ab66921 725 }
terencez 0:1fa43ab66921 726
terencez 0:1fa43ab66921 727 return targetP;
terencez 0:1fa43ab66921 728 }
terencez 0:1fa43ab66921 729
terencez 0:1fa43ab66921 730 void observe_remove(lwm2m_observation_t * observationP)
terencez 0:1fa43ab66921 731 {
terencez 0:1fa43ab66921 732 LOG("Entering");
terencez 0:1fa43ab66921 733 observationP->clientP->observationList = (lwm2m_observation_t *) LWM2M_LIST_RM(observationP->clientP->observationList, observationP->id, NULL);
terencez 0:1fa43ab66921 734 lwm2m_free(observationP);
terencez 0:1fa43ab66921 735 }
terencez 0:1fa43ab66921 736
terencez 0:1fa43ab66921 737 static void prv_obsRequestCallback(lwm2m_transaction_t * transacP,
terencez 0:1fa43ab66921 738 void * message)
terencez 0:1fa43ab66921 739 {
terencez 0:1fa43ab66921 740 lwm2m_observation_t * observationP = (lwm2m_observation_t *)transacP->userData;
terencez 0:1fa43ab66921 741 coap_packet_t * packet = (coap_packet_t *)message;
terencez 0:1fa43ab66921 742 uint8_t code;
terencez 0:1fa43ab66921 743
terencez 0:1fa43ab66921 744 switch (observationP->status)
terencez 0:1fa43ab66921 745 {
terencez 0:1fa43ab66921 746 case STATE_DEREG_PENDING:
terencez 0:1fa43ab66921 747 // Observation was canceled by the user.
terencez 0:1fa43ab66921 748 observe_remove(observationP);
terencez 0:1fa43ab66921 749 return;
terencez 0:1fa43ab66921 750
terencez 0:1fa43ab66921 751 case STATE_REG_PENDING:
terencez 0:1fa43ab66921 752 observationP->status = STATE_REGISTERED;
terencez 0:1fa43ab66921 753 break;
terencez 0:1fa43ab66921 754
terencez 0:1fa43ab66921 755 default:
terencez 0:1fa43ab66921 756 break;
terencez 0:1fa43ab66921 757 }
terencez 0:1fa43ab66921 758
terencez 0:1fa43ab66921 759 if (message == NULL)
terencez 0:1fa43ab66921 760 {
terencez 0:1fa43ab66921 761 code = COAP_503_SERVICE_UNAVAILABLE;
terencez 0:1fa43ab66921 762 }
terencez 0:1fa43ab66921 763 else if (packet->code == COAP_205_CONTENT
terencez 0:1fa43ab66921 764 && !IS_OPTION(packet, COAP_OPTION_OBSERVE))
terencez 0:1fa43ab66921 765 {
terencez 0:1fa43ab66921 766 code = COAP_405_METHOD_NOT_ALLOWED;
terencez 0:1fa43ab66921 767 }
terencez 0:1fa43ab66921 768 else
terencez 0:1fa43ab66921 769 {
terencez 0:1fa43ab66921 770 code = packet->code;
terencez 0:1fa43ab66921 771 }
terencez 0:1fa43ab66921 772
terencez 0:1fa43ab66921 773 if (code != COAP_205_CONTENT)
terencez 0:1fa43ab66921 774 {
terencez 0:1fa43ab66921 775 observationP->callback(observationP->clientP->internalID,
terencez 0:1fa43ab66921 776 &observationP->uri,
terencez 0:1fa43ab66921 777 code,
terencez 0:1fa43ab66921 778 LWM2M_CONTENT_TEXT, NULL, 0,
terencez 0:1fa43ab66921 779 observationP->userData);
terencez 0:1fa43ab66921 780 observe_remove(observationP);
terencez 0:1fa43ab66921 781 }
terencez 0:1fa43ab66921 782 else
terencez 0:1fa43ab66921 783 {
terencez 0:1fa43ab66921 784 observationP->callback(observationP->clientP->internalID,
terencez 0:1fa43ab66921 785 &observationP->uri,
terencez 0:1fa43ab66921 786 0,
terencez 0:1fa43ab66921 787 packet->content_type, packet->payload, packet->payload_len,
terencez 0:1fa43ab66921 788 observationP->userData);
terencez 0:1fa43ab66921 789 }
terencez 0:1fa43ab66921 790 }
terencez 0:1fa43ab66921 791
terencez 0:1fa43ab66921 792
terencez 0:1fa43ab66921 793 static void prv_obsCancelRequestCallback(lwm2m_transaction_t * transacP,
terencez 0:1fa43ab66921 794 void * message)
terencez 0:1fa43ab66921 795 {
terencez 0:1fa43ab66921 796 cancellation_data_t * cancelP = (cancellation_data_t *)transacP->userData;
terencez 0:1fa43ab66921 797 coap_packet_t * packet = (coap_packet_t *)message;
terencez 0:1fa43ab66921 798 uint8_t code;
terencez 0:1fa43ab66921 799
terencez 0:1fa43ab66921 800 if (message == NULL)
terencez 0:1fa43ab66921 801 {
terencez 0:1fa43ab66921 802 code = COAP_503_SERVICE_UNAVAILABLE;
terencez 0:1fa43ab66921 803 }
terencez 0:1fa43ab66921 804 else
terencez 0:1fa43ab66921 805 {
terencez 0:1fa43ab66921 806 code = packet->code;
terencez 0:1fa43ab66921 807 }
terencez 0:1fa43ab66921 808
terencez 0:1fa43ab66921 809 if (code != COAP_205_CONTENT)
terencez 0:1fa43ab66921 810 {
terencez 0:1fa43ab66921 811 cancelP->callbackP(cancelP->observationP->clientP->internalID,
terencez 0:1fa43ab66921 812 &cancelP->observationP->uri,
terencez 0:1fa43ab66921 813 code,
terencez 0:1fa43ab66921 814 LWM2M_CONTENT_TEXT, NULL, 0,
terencez 0:1fa43ab66921 815 cancelP->userDataP);
terencez 0:1fa43ab66921 816 }
terencez 0:1fa43ab66921 817 else
terencez 0:1fa43ab66921 818 {
terencez 0:1fa43ab66921 819 cancelP->callbackP(cancelP->observationP->clientP->internalID,
terencez 0:1fa43ab66921 820 &cancelP->observationP->uri,
terencez 0:1fa43ab66921 821 0,
terencez 0:1fa43ab66921 822 packet->content_type, packet->payload, packet->payload_len,
terencez 0:1fa43ab66921 823 cancelP->userDataP);
terencez 0:1fa43ab66921 824 }
terencez 0:1fa43ab66921 825
terencez 0:1fa43ab66921 826 observe_remove(cancelP->observationP);
terencez 0:1fa43ab66921 827
terencez 0:1fa43ab66921 828 lwm2m_free(cancelP);
terencez 0:1fa43ab66921 829 }
terencez 0:1fa43ab66921 830
terencez 0:1fa43ab66921 831
terencez 0:1fa43ab66921 832 int lwm2m_observe(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 833 uint16_t clientID,
terencez 0:1fa43ab66921 834 lwm2m_uri_t * uriP,
terencez 0:1fa43ab66921 835 lwm2m_result_callback_t callback,
terencez 0:1fa43ab66921 836 void * userData)
terencez 0:1fa43ab66921 837 {
terencez 0:1fa43ab66921 838 lwm2m_client_t * clientP;
terencez 0:1fa43ab66921 839 lwm2m_transaction_t * transactionP;
terencez 0:1fa43ab66921 840 lwm2m_observation_t * observationP;
terencez 0:1fa43ab66921 841 uint8_t token[4];
terencez 0:1fa43ab66921 842
terencez 0:1fa43ab66921 843 LOG_ARG("clientID: %d", clientID);
terencez 0:1fa43ab66921 844 LOG_URI(uriP);
terencez 0:1fa43ab66921 845
terencez 0:1fa43ab66921 846 if (!LWM2M_URI_IS_SET_INSTANCE(uriP) && LWM2M_URI_IS_SET_RESOURCE(uriP)) return COAP_400_BAD_REQUEST;
terencez 0:1fa43ab66921 847
terencez 0:1fa43ab66921 848 clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID);
terencez 0:1fa43ab66921 849 if (clientP == NULL) return COAP_404_NOT_FOUND;
terencez 0:1fa43ab66921 850
terencez 0:1fa43ab66921 851 observationP = (lwm2m_observation_t *)lwm2m_malloc(sizeof(lwm2m_observation_t));
terencez 0:1fa43ab66921 852 if (observationP == NULL) return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 853 memset(observationP, 0, sizeof(lwm2m_observation_t));
terencez 0:1fa43ab66921 854
terencez 0:1fa43ab66921 855 observationP->id = lwm2m_list_newId((lwm2m_list_t *)clientP->observationList);
terencez 0:1fa43ab66921 856 memcpy(&observationP->uri, uriP, sizeof(lwm2m_uri_t));
terencez 0:1fa43ab66921 857 observationP->clientP = clientP;
terencez 0:1fa43ab66921 858 observationP->status = STATE_REG_PENDING;
terencez 0:1fa43ab66921 859 observationP->callback = callback;
terencez 0:1fa43ab66921 860 observationP->userData = userData;
terencez 0:1fa43ab66921 861
terencez 0:1fa43ab66921 862 token[0] = clientP->internalID >> 8;
terencez 0:1fa43ab66921 863 token[1] = clientP->internalID & 0xFF;
terencez 0:1fa43ab66921 864 token[2] = observationP->id >> 8;
terencez 0:1fa43ab66921 865 token[3] = observationP->id & 0xFF;
terencez 0:1fa43ab66921 866
terencez 0:1fa43ab66921 867 transactionP = transaction_new(clientP->sessionH, COAP_GET, clientP->altPath, uriP, contextP->nextMID++, 4, token);
terencez 0:1fa43ab66921 868 if (transactionP == NULL)
terencez 0:1fa43ab66921 869 {
terencez 0:1fa43ab66921 870 lwm2m_free(observationP);
terencez 0:1fa43ab66921 871 return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 872 }
terencez 0:1fa43ab66921 873
terencez 0:1fa43ab66921 874 observationP->clientP->observationList = (lwm2m_observation_t *)LWM2M_LIST_ADD(observationP->clientP->observationList, observationP);
terencez 0:1fa43ab66921 875
terencez 0:1fa43ab66921 876 coap_set_header_observe(transactionP->message, 0);
terencez 0:1fa43ab66921 877 coap_set_header_token(transactionP->message, token, sizeof(token));
terencez 0:1fa43ab66921 878
terencez 0:1fa43ab66921 879 transactionP->callback = prv_obsRequestCallback;
terencez 0:1fa43ab66921 880 transactionP->userData = (void *)observationP;
terencez 0:1fa43ab66921 881
terencez 0:1fa43ab66921 882 contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transactionP);
terencez 0:1fa43ab66921 883
terencez 0:1fa43ab66921 884 return transaction_send(contextP, transactionP);
terencez 0:1fa43ab66921 885 }
terencez 0:1fa43ab66921 886
terencez 0:1fa43ab66921 887 int lwm2m_observe_cancel(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 888 uint16_t clientID,
terencez 0:1fa43ab66921 889 lwm2m_uri_t * uriP,
terencez 0:1fa43ab66921 890 lwm2m_result_callback_t callback,
terencez 0:1fa43ab66921 891 void * userData)
terencez 0:1fa43ab66921 892 {
terencez 0:1fa43ab66921 893 lwm2m_client_t * clientP;
terencez 0:1fa43ab66921 894 lwm2m_observation_t * observationP;
terencez 0:1fa43ab66921 895
terencez 0:1fa43ab66921 896 LOG_ARG("clientID: %d", clientID);
terencez 0:1fa43ab66921 897 LOG_URI(uriP);
terencez 0:1fa43ab66921 898
terencez 0:1fa43ab66921 899 clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID);
terencez 0:1fa43ab66921 900 if (clientP == NULL) return COAP_404_NOT_FOUND;
terencez 0:1fa43ab66921 901
terencez 0:1fa43ab66921 902 observationP = prv_findObservationByURI(clientP, uriP);
terencez 0:1fa43ab66921 903 if (observationP == NULL) return COAP_404_NOT_FOUND;
terencez 0:1fa43ab66921 904
terencez 0:1fa43ab66921 905 switch (observationP->status)
terencez 0:1fa43ab66921 906 {
terencez 0:1fa43ab66921 907 case STATE_REGISTERED:
terencez 0:1fa43ab66921 908 {
terencez 0:1fa43ab66921 909 lwm2m_transaction_t * transactionP;
terencez 0:1fa43ab66921 910 cancellation_data_t * cancelP;
terencez 0:1fa43ab66921 911
terencez 0:1fa43ab66921 912 transactionP = transaction_new(clientP->sessionH, COAP_GET, clientP->altPath, uriP, contextP->nextMID++, 0, NULL);
terencez 0:1fa43ab66921 913 if (transactionP == NULL)
terencez 0:1fa43ab66921 914 {
terencez 0:1fa43ab66921 915 return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 916 }
terencez 0:1fa43ab66921 917 cancelP = (cancellation_data_t *)lwm2m_malloc(sizeof(cancellation_data_t));
terencez 0:1fa43ab66921 918 if (cancelP == NULL)
terencez 0:1fa43ab66921 919 {
terencez 0:1fa43ab66921 920 lwm2m_free(transactionP);
terencez 0:1fa43ab66921 921 return COAP_500_INTERNAL_SERVER_ERROR;
terencez 0:1fa43ab66921 922 }
terencez 0:1fa43ab66921 923
terencez 0:1fa43ab66921 924 coap_set_header_observe(transactionP->message, 1);
terencez 0:1fa43ab66921 925
terencez 0:1fa43ab66921 926 cancelP->observationP = observationP;
terencez 0:1fa43ab66921 927 cancelP->callbackP = callback;
terencez 0:1fa43ab66921 928 cancelP->userDataP = userData;
terencez 0:1fa43ab66921 929
terencez 0:1fa43ab66921 930 transactionP->callback = prv_obsCancelRequestCallback;
terencez 0:1fa43ab66921 931 transactionP->userData = (void *)cancelP;
terencez 0:1fa43ab66921 932
terencez 0:1fa43ab66921 933 contextP->transactionList = (lwm2m_transaction_t *)LWM2M_LIST_ADD(contextP->transactionList, transactionP);
terencez 0:1fa43ab66921 934
terencez 0:1fa43ab66921 935 return transaction_send(contextP, transactionP);
terencez 0:1fa43ab66921 936 }
terencez 0:1fa43ab66921 937
terencez 0:1fa43ab66921 938 case STATE_REG_PENDING:
terencez 0:1fa43ab66921 939 observationP->status = STATE_DEREG_PENDING;
terencez 0:1fa43ab66921 940 break;
terencez 0:1fa43ab66921 941
terencez 0:1fa43ab66921 942 default:
terencez 0:1fa43ab66921 943 // Should not happen
terencez 0:1fa43ab66921 944 break;
terencez 0:1fa43ab66921 945 }
terencez 0:1fa43ab66921 946
terencez 0:1fa43ab66921 947 return COAP_NO_ERROR;
terencez 0:1fa43ab66921 948 }
terencez 0:1fa43ab66921 949
terencez 0:1fa43ab66921 950 bool observe_handleNotify(lwm2m_context_t * contextP,
terencez 0:1fa43ab66921 951 void * fromSessionH,
terencez 0:1fa43ab66921 952 coap_packet_t * message,
terencez 0:1fa43ab66921 953 coap_packet_t * response)
terencez 0:1fa43ab66921 954 {
terencez 0:1fa43ab66921 955 uint8_t * tokenP;
terencez 0:1fa43ab66921 956 int token_len;
terencez 0:1fa43ab66921 957 uint16_t clientID;
terencez 0:1fa43ab66921 958 uint16_t obsID;
terencez 0:1fa43ab66921 959 lwm2m_client_t * clientP;
terencez 0:1fa43ab66921 960 lwm2m_observation_t * observationP;
terencez 0:1fa43ab66921 961 uint32_t count;
terencez 0:1fa43ab66921 962
terencez 0:1fa43ab66921 963 LOG("Entering");
terencez 0:1fa43ab66921 964 token_len = coap_get_header_token(message, (const uint8_t **)&tokenP);
terencez 0:1fa43ab66921 965 if (token_len != sizeof(uint32_t)) return false;
terencez 0:1fa43ab66921 966
terencez 0:1fa43ab66921 967 if (1 != coap_get_header_observe(message, &count)) return false;
terencez 0:1fa43ab66921 968
terencez 0:1fa43ab66921 969 clientID = (tokenP[0] << 8) | tokenP[1];
terencez 0:1fa43ab66921 970 obsID = (tokenP[2] << 8) | tokenP[3];
terencez 0:1fa43ab66921 971
terencez 0:1fa43ab66921 972 clientP = (lwm2m_client_t *)lwm2m_list_find((lwm2m_list_t *)contextP->clientList, clientID);
terencez 0:1fa43ab66921 973 if (clientP == NULL) return false;
terencez 0:1fa43ab66921 974
terencez 0:1fa43ab66921 975 observationP = (lwm2m_observation_t *)lwm2m_list_find((lwm2m_list_t *)clientP->observationList, obsID);
terencez 0:1fa43ab66921 976 if (observationP == NULL)
terencez 0:1fa43ab66921 977 {
terencez 0:1fa43ab66921 978 coap_init_message(response, COAP_TYPE_RST, 0, message->mid);
terencez 0:1fa43ab66921 979 message_send(contextP, response, fromSessionH);
terencez 0:1fa43ab66921 980 }
terencez 0:1fa43ab66921 981 else
terencez 0:1fa43ab66921 982 {
terencez 0:1fa43ab66921 983 if (message->type == COAP_TYPE_CON ) {
terencez 0:1fa43ab66921 984 coap_init_message(response, COAP_TYPE_ACK, 0, message->mid);
terencez 0:1fa43ab66921 985 message_send(contextP, response, fromSessionH);
terencez 0:1fa43ab66921 986 }
terencez 0:1fa43ab66921 987 observationP->callback(clientID,
terencez 0:1fa43ab66921 988 &observationP->uri,
terencez 0:1fa43ab66921 989 (int)count,
terencez 0:1fa43ab66921 990 message->content_type, message->payload, message->payload_len,
terencez 0:1fa43ab66921 991 observationP->userData);
terencez 0:1fa43ab66921 992 }
terencez 0:1fa43ab66921 993 return true;
terencez 0:1fa43ab66921 994 }
terencez 0:1fa43ab66921 995 #endif