1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
34 static int gObserveNotifyType = 3;
37 int gLightUnderObservation = 0;
39 static LightResource Light;
40 // This variable determines instance number of the Light resource.
41 // Used by POST method to create a new instance of Light resource.
42 static int gCurrLightInstance = 0;
44 static LightResource gLightInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
46 Observers interestedObservers[SAMPLE_MAX_NUM_OBSERVATIONS];
49 static int stopPresenceCount = 10;
52 //TODO: Follow the pattern used in constructJsonResponse() when the payload is decided.
53 const char responsePayloadDeleteOk[] = "{App determines payload: Delete Resource operation succeeded.}";
54 const char responsePayloadDeleteNotOK[] = "{App determines payload: Delete Resource operation failed.}";
55 const char responsePayloadResourceDoesNotExist[] = "{App determines payload: The resource does not exist.}";
56 const char responsePayloadDeleteResourceNotSupported[] =
57 "{App determines payload: The request is received for a non-support resource.}";
60 char *gResourceUri= (char *)"/a/light";
62 static uint16_t OC_WELL_KNOWN_PORT = 5683;
64 //This function takes the request as an input and returns the response
66 char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
68 cJSON *json = cJSON_CreateObject();
71 LightResource *currLightResource = &Light;
73 if (ehRequest->resource == gLightInstance[0].handle)
75 currLightResource = &gLightInstance[0];
76 gResourceUri = (char *) "a/light/0";
78 else if (ehRequest->resource == gLightInstance[1].handle)
80 currLightResource = &gLightInstance[1];
81 gResourceUri = (char *) "a/light/1";
84 if(OC_REST_PUT == ehRequest->method)
86 cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload);
87 currLightResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring,
89 currLightResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble;
90 cJSON_Delete(putJson);
93 cJSON_AddStringToObject(json,"href",gResourceUri);
94 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
95 cJSON_AddStringToObject(format, "state", (char *) (currLightResource->state ? "on":"off"));
96 cJSON_AddNumberToObject(format, "power", currLightResource->power);
98 jsonResponse = cJSON_Print(json);
104 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
106 OCEntityHandlerResult ehResult;
107 char *getResp = constructJsonResponse(ehRequest);
109 if (maxPayloadSize > strlen ((char *)getResp))
111 strncpy(payload, getResp, strlen((char *)getResp));
116 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
118 ehResult = OC_EH_ERROR;
126 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
128 OCEntityHandlerResult ehResult;
129 char *putResp = constructJsonResponse(ehRequest);
131 if (maxPayloadSize > strlen ((char *)putResp))
133 strncpy(payload, putResp, strlen((char *)putResp));
138 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
140 ehResult = OC_EH_ERROR;
148 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, OCEntityHandlerResponse *response, char *payload, uint16_t maxPayloadSize)
150 OCEntityHandlerResult ehResult = OC_EH_OK;
151 char *respPLPost_light = NULL;
156 * The entity handler determines how to process a POST request.
157 * Per the REST paradigm, POST can also be used to update representation of existing
158 * resource or create a new resource.
159 * In the sample below, if the POST is for /a/light then a new instance of the Light
160 * resource is created with default representation (if representation is included in
161 * POST payload it can be used as initial values) as long as the instance is
162 * lesser than max new instance count. Once max instance count is reached, POST on
163 * /a/light updated the representation of /a/light (just like PUT)
166 if (ehRequest->resource == Light.handle)
168 if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
170 // Create new Light instance
171 char newLightUri[15] = "/a/light/";
172 sprintf (newLightUri + strlen(newLightUri), "%d", gCurrLightInstance);
173 json = cJSON_CreateObject();
174 cJSON_AddStringToObject(json,"href",gResourceUri);
175 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
176 cJSON_AddStringToObject(format, "createduri", (char *) newLightUri);
178 if (0 == createLightResource (newLightUri, &gLightInstance[gCurrLightInstance]))
180 OC_LOG (INFO, TAG, "Created new Light instance\n");
181 gLightInstance[gCurrLightInstance].state = 0;
182 gLightInstance[gCurrLightInstance].power = 0;
183 gCurrLightInstance++;
184 respPLPost_light = cJSON_Print(json);
185 strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
186 ehResult = OC_EH_RESOURCE_CREATED;
193 // Update repesentation of /a/light
196 respPLPost_light = constructJsonResponse(ehRequest);
201 for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
203 if (ehRequest->resource == gLightInstance[i].handle)
205 gLightInstance[i].state = true;
206 gLightInstance[i].power = 22;
209 respPLPost_light = constructJsonResponse(ehRequest);
214 respPLPost_light = constructJsonResponse(ehRequest);
220 if ((respPLPost_light != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_light)))
222 strncpy(payload, respPLPost_light, strlen((char *)respPLPost_light));
226 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
228 ehResult = OC_EH_ERROR;
231 free(respPLPost_light);
235 OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
237 OCEntityHandlerResult ehResult = OC_EH_OK;
239 OC_LOG_V(INFO, TAG, "\n\nExecuting %s for resource %d ", __func__, ehRequest->resource);
242 * In the sample below, the application will:
243 * 1a. pass the delete request to the c stack
244 * 1b. internally, the c stack figures out what needs to be done and does it accordingly
245 * (e.g. send observers notification, remove observers...)
246 * 1c. the c stack returns with the result whether the request is fullfilled.
247 * 2. optionally, app removes observers out of its array 'interestedObservers'
250 const char* deleteResponse = NULL;
252 if ((ehRequest != NULL) && (ehRequest->resource == Light.handle))
254 //Step 1: Ask stack to do the work.
255 OCStackResult result = OCDeleteResource(ehRequest->resource);
257 if (result == OC_STACK_OK)
259 OC_LOG (INFO, TAG, "\n\nDelete Resource operation succeeded.");
261 deleteResponse = responsePayloadDeleteOk;
263 //Step 2: clear observers who wanted to observe this resource at the app level.
264 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
266 if (interestedObservers[i].resourceHandle == ehRequest->resource)
268 interestedObservers[i].valid = false;
269 interestedObservers[i].observationId = 0;
270 interestedObservers[i].resourceHandle = NULL;
274 else if (result == OC_STACK_NO_RESOURCE)
276 OC_LOG(INFO, TAG, "\n\nThe resource doesn't exist or it might have been deleted.");
277 deleteResponse = responsePayloadResourceDoesNotExist;
278 ehResult = OC_EH_RESOURCE_DELETED;
282 OC_LOG(INFO, TAG, "\n\nEncountered error from OCDeleteResource().");
283 deleteResponse = responsePayloadDeleteNotOK;
284 ehResult = OC_EH_ERROR;
287 else if (ehRequest->resource != Light.handle)
289 //Let's this app not supporting DELETE on some resources so
290 //consider the DELETE request is received for a non-support resource.
291 OC_LOG_V(INFO, TAG, "\n\nThe request is received for a non-support resource.");
292 deleteResponse = responsePayloadDeleteResourceNotSupported;
293 ehResult = OC_EH_FORBIDDEN;
296 if (maxPayloadSize > strlen ((char *)deleteResponse))
298 strncpy(payload, deleteResponse, strlen((char *)deleteResponse));
302 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
304 ehResult = OC_EH_ERROR;
310 OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
312 OC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__);
314 const char* response = NULL;
315 response = responsePayloadResourceDoesNotExist;
317 if ( (ehRequest != NULL) &&
318 (maxPayloadSize > strlen ((char *)response)) )
320 strncpy((char *)payload, response, strlen((char *)response));
324 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
328 return OC_EH_RESOURCE_DELETED;
331 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
333 OC_LOG_V (INFO, TAG, "Received observation registration request with observation Id %d",
334 ehRequest->obsInfo.obsId);
335 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
337 if (interestedObservers[i].valid == false)
339 interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
340 interestedObservers[i].valid = true;
341 gLightUnderObservation = 1;
347 void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest)
349 bool clientStillObserving = false;
351 OC_LOG_V (INFO, TAG, "Received observation deregistration request for observation Id %d",
352 ehRequest->obsInfo.obsId);
353 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
355 if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
357 interestedObservers[i].valid = false;
359 if (interestedObservers[i].valid == true)
361 // Even if there is one single client observing we continue notifying entity handler
362 clientStillObserving = true;
365 if (clientStillObserving == false)
366 gLightUnderObservation = 0;
369 OCEntityHandlerResult
370 OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
371 OCEntityHandlerRequest *entityHandlerRequest, char* uri)
373 OC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
375 OCEntityHandlerResult ehResult = OC_EH_OK;
376 OCEntityHandlerResponse response;
377 char payload[MAX_RESPONSE_LENGTH] = {0};
380 if (!entityHandlerRequest)
382 OC_LOG (ERROR, TAG, "Invalid request pointer");
386 // Initialize certain response fields
387 response.numSendVendorSpecificHeaderOptions = 0;
388 memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
389 memset(response.resourceUri, 0, sizeof response.resourceUri);
391 if (flag & OC_INIT_FLAG)
393 OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
395 if (flag & OC_REQUEST_FLAG)
397 OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
398 if (entityHandlerRequest->resource == NULL) {
399 OC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
400 ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest, payload, sizeof(payload) - 1);
402 else if (OC_REST_GET == entityHandlerRequest->method)
404 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
405 ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
407 else if (OC_REST_PUT == entityHandlerRequest->method)
409 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
410 ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
412 else if (OC_REST_DELETE == entityHandlerRequest->method)
414 OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
415 ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
419 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
420 entityHandlerRequest->method);
421 ehResult = OC_EH_ERROR;
424 // If the result isn't an error or forbidden, send response
425 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
427 // Format the response. Note this requires some info about the request
428 response.requestHandle = entityHandlerRequest->requestHandle;
429 response.resourceHandle = entityHandlerRequest->resource;
430 response.ehResult = ehResult;
431 response.payload = (unsigned char *)payload;
432 response.payloadSize = strlen(payload);
433 // Indicate that response is NOT in a persistent buffer
434 response.persistentBufferFlag = 0;
437 if (OCDoResponse(&response) != OC_STACK_OK)
439 OC_LOG(ERROR, TAG, "Error sending response");
440 ehResult = OC_EH_ERROR;
444 if (flag & OC_OBSERVE_FLAG)
446 OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
447 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
449 OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
451 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
453 OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
461 OCEntityHandlerResult
462 OCEntityHandlerCb (OCEntityHandlerFlag flag,
463 OCEntityHandlerRequest *entityHandlerRequest)
465 OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
467 OCEntityHandlerResult ehResult = OC_EH_OK;
468 OCEntityHandlerResponse response;
469 char payload[MAX_RESPONSE_LENGTH] = {0};
472 if (!entityHandlerRequest)
474 OC_LOG (ERROR, TAG, "Invalid request pointer");
478 // Initialize certain response fields
479 response.numSendVendorSpecificHeaderOptions = 0;
480 memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
481 memset(response.resourceUri, 0, sizeof response.resourceUri);
483 if (flag & OC_INIT_FLAG)
485 OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
487 if (flag & OC_REQUEST_FLAG)
489 OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
490 if (OC_REST_GET == entityHandlerRequest->method)
492 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
493 ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
495 else if (OC_REST_PUT == entityHandlerRequest->method)
497 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
498 ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
500 else if (OC_REST_POST == entityHandlerRequest->method)
502 OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
503 ehResult = ProcessPostRequest (entityHandlerRequest, &response, payload, sizeof(payload) - 1);
505 else if (OC_REST_DELETE == entityHandlerRequest->method)
507 OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
508 ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
512 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
513 entityHandlerRequest->method);
516 // If the result isn't an error or forbidden, send response
517 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
519 // Format the response. Note this requires some info about the request
520 response.requestHandle = entityHandlerRequest->requestHandle;
521 response.resourceHandle = entityHandlerRequest->resource;
522 response.ehResult = ehResult;
523 response.payload = (unsigned char *)payload;
524 response.payloadSize = strlen(payload);
525 // Indicate that response is NOT in a persistent buffer
526 response.persistentBufferFlag = 0;
528 // Handle vendor specific options
529 if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
530 entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
532 OC_LOG (INFO, TAG, "Received vendor specific options");
534 OCHeaderOption * rcvdOptions = entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
535 for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
537 if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
539 OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
540 ((OCHeaderOption)rcvdOptions[i]).optionID );
541 OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
542 ((OCHeaderOption)rcvdOptions[i]).optionLength);
545 OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions;
546 uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
547 uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
548 sendOptions[0].protocolID = OC_COAP_ID;
549 sendOptions[0].optionID = 2248;
550 memcpy(sendOptions[0].optionData, option2, sizeof(option2));
551 sendOptions[0].optionLength = 10;
552 sendOptions[1].protocolID = OC_COAP_ID;
553 sendOptions[1].optionID = 2600;
554 memcpy(sendOptions[1].optionData, option3, sizeof(option3));
555 sendOptions[1].optionLength = 10;
556 response.numSendVendorSpecificHeaderOptions = 2;
560 if (OCDoResponse(&response) != OC_STACK_OK)
562 OC_LOG(ERROR, TAG, "Error sending response");
563 ehResult = OC_EH_ERROR;
567 if (flag & OC_OBSERVE_FLAG)
569 OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
571 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
573 OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
574 ProcessObserveRegister (entityHandlerRequest);
576 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
578 OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
579 ProcessObserveDeregister (entityHandlerRequest);
586 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
587 void handleSigInt(int signum) {
588 if (signum == SIGINT) {
593 void *ChangeLightRepresentation (void *param)
596 OCStackResult result = OC_STACK_ERROR;
599 uint8_t numNotifies = (SAMPLE_MAX_NUM_OBSERVATIONS)/2;
600 OCObservationId obsNotify[numNotifies];
606 if (gLightUnderObservation)
608 OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
609 if (gObserveNotifyType == 1)
611 // Notify list of observers. Alternate observers on the list will be notified.
613 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; (i=i+2))
615 if (interestedObservers[i].valid == true)
617 obsNotify[j] = interestedObservers[i].observationId;
622 cJSON *json = cJSON_CreateObject();
624 cJSON_AddStringToObject(json,"href",gResourceUri);
625 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
626 cJSON_AddStringToObject(format, "state", (char *) (Light.state ? "on":"off"));
627 cJSON_AddNumberToObject(format, "power", Light.power);
628 char * obsResp = cJSON_Print(json);
630 result = OCNotifyListOfObservers (Light.handle, obsNotify, j,
631 (unsigned char *)obsResp, OC_NA_QOS);
634 else if (gObserveNotifyType == 0)
636 // Notifying all observers
637 result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
638 if (OC_STACK_NO_OBSERVERS == result)
641 "=======> No more observers exist, stop sending observations");
642 gLightUnderObservation = 0;
647 OC_LOG (ERROR, TAG, "Incorrect notification type selected");
651 if(stopPresenceCount > 0)
653 OC_LOG_V(INFO, TAG, "================ presence count %d", stopPresenceCount);
655 if(!stopPresenceCount--)
657 OC_LOG(INFO, TAG, "================ stopping presence");
665 static void PrintUsage()
667 OC_LOG(INFO, TAG, "Usage : ocserver -o <0|1>");
668 OC_LOG(INFO, TAG, "-o 0 : Notify all observers");
669 OC_LOG(INFO, TAG, "-o 1 : Notify list of observers");
672 int main(int argc, char* argv[])
674 uint8_t addr[20] = {0};
675 uint8_t* paddr = NULL;
676 uint16_t port = OC_WELL_KNOWN_PORT;
677 uint8_t ifname[] = "eth0";
681 while ((opt = getopt(argc, argv, "o:")) != -1)
686 gObserveNotifyType = atoi(optarg);
694 if ((gObserveNotifyType != 0) && (gObserveNotifyType != 1))
700 OC_LOG(DEBUG, TAG, "OCServer is starting...");
701 /*Get Ip address on defined interface and initialize coap on it with random port number
702 * this port number will be used as a source port in all coap communications*/
703 if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
704 sizeof(addr)) == ERR_SUCCESS)
706 OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
710 if (OCInit((char *) paddr, port, OC_SERVER) != OC_STACK_OK) {
711 OC_LOG(ERROR, TAG, "OCStack init error");
715 if (OCStartPresence(0) != OC_STACK_OK) {
716 OC_LOG(ERROR, TAG, "OCStack presence/discovery error");
721 OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb);
724 * Declare and create the example resource: Light
726 createLightResource(gResourceUri, &Light);
728 // Initialize observations data structure for the resource
729 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
731 interestedObservers[i].valid = false;
735 * Create a thread for changing the representation of the Light
737 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
739 // Break from loop with Ctrl-C
740 OC_LOG(INFO, TAG, "Entering ocserver main loop...");
741 signal(SIGINT, handleSigInt);
743 if (OCProcess() != OC_STACK_OK) {
744 OC_LOG(ERROR, TAG, "OCStack process error");
752 * Cancel the Light thread and wait for it to terminate
754 pthread_cancel(threadId);
755 pthread_join(threadId, NULL);
757 OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
759 if (OCStop() != OC_STACK_OK) {
760 OC_LOG(ERROR, TAG, "OCStack process error");
766 int createLightResource (char *uri, LightResource *lightResource)
770 OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
774 lightResource->state = false;
775 lightResource->power= 0;
776 OCStackResult res = OCCreateResource(&(lightResource->handle),
781 OC_DISCOVERABLE|OC_OBSERVABLE);
782 OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));