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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
33 //string length of "/a/light/" + std::numeric_limits<int>::digits10 + '\0'"
35 const int URI_MAXSIZE = 19;
37 static int gObserveNotifyType = 3;
40 int gLightUnderObservation = 0;
42 static LightResource Light;
43 // This variable determines instance number of the Light resource.
44 // Used by POST method to create a new instance of Light resource.
45 static int gCurrLightInstance = 0;
47 static LightResource gLightInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
49 Observers interestedObservers[SAMPLE_MAX_NUM_OBSERVATIONS];
52 static int stopPresenceCount = 10;
55 //TODO: Follow the pattern used in constructJsonResponse() when the payload is decided.
56 const char responsePayloadDeleteOk[] = "{App determines payload: Delete Resource operation succeeded.}";
57 const char responsePayloadDeleteNotOK[] = "{App determines payload: Delete Resource operation failed.}";
58 const char responsePayloadResourceDoesNotExist[] = "{App determines payload: The resource does not exist.}";
59 const char responsePayloadDeleteResourceNotSupported[] =
60 "{App determines payload: The request is received for a non-support resource.}";
63 char *gResourceUri= (char *)"/a/light";
65 static uint16_t OC_WELL_KNOWN_PORT = 5683;
67 //This function takes the request as an input and returns the response
69 char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
71 cJSON *json = cJSON_CreateObject();
74 LightResource *currLightResource = &Light;
76 if (ehRequest->resource == gLightInstance[0].handle)
78 currLightResource = &gLightInstance[0];
79 gResourceUri = (char *) "a/light/0";
81 else if (ehRequest->resource == gLightInstance[1].handle)
83 currLightResource = &gLightInstance[1];
84 gResourceUri = (char *) "a/light/1";
87 if(OC_REST_PUT == ehRequest->method)
89 cJSON *putJson = cJSON_Parse((char *)ehRequest->reqJSONPayload);
90 currLightResource->state = ( !strcmp(cJSON_GetObjectItem(putJson,"state")->valuestring,
92 currLightResource->power = cJSON_GetObjectItem(putJson,"power")->valuedouble;
93 cJSON_Delete(putJson);
96 cJSON_AddStringToObject(json,"href",gResourceUri);
97 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
98 cJSON_AddStringToObject(format, "state", (char *) (currLightResource->state ? "on":"off"));
99 cJSON_AddNumberToObject(format, "power", currLightResource->power);
101 jsonResponse = cJSON_Print(json);
107 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
109 OCEntityHandlerResult ehResult;
110 char *getResp = constructJsonResponse(ehRequest);
112 if (maxPayloadSize > strlen ((char *)getResp))
114 strncpy(payload, getResp, strlen((char *)getResp));
119 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
121 ehResult = OC_EH_ERROR;
129 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
131 OCEntityHandlerResult ehResult;
132 char *putResp = constructJsonResponse(ehRequest);
134 if (maxPayloadSize > strlen ((char *)putResp))
136 strncpy(payload, putResp, strlen((char *)putResp));
141 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
143 ehResult = OC_EH_ERROR;
151 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest, OCEntityHandlerResponse *response, char *payload, uint16_t maxPayloadSize)
153 OCEntityHandlerResult ehResult = OC_EH_OK;
154 char *respPLPost_light = NULL;
159 * The entity handler determines how to process a POST request.
160 * Per the REST paradigm, POST can also be used to update representation of existing
161 * resource or create a new resource.
162 * In the sample below, if the POST is for /a/light then a new instance of the Light
163 * resource is created with default representation (if representation is included in
164 * POST payload it can be used as initial values) as long as the instance is
165 * lesser than max new instance count. Once max instance count is reached, POST on
166 * /a/light updated the representation of /a/light (just like PUT)
169 if (ehRequest->resource == Light.handle)
171 if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
173 // Create new Light instance
174 char newLightUri[URI_MAXSIZE];
175 snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance);
177 json = cJSON_CreateObject();
178 cJSON_AddStringToObject(json,"href",gResourceUri);
179 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
180 cJSON_AddStringToObject(format, "createduri", (char *) newLightUri);
182 if (0 == createLightResource (newLightUri, &gLightInstance[gCurrLightInstance]))
184 OC_LOG (INFO, TAG, "Created new Light instance\n");
185 gLightInstance[gCurrLightInstance].state = 0;
186 gLightInstance[gCurrLightInstance].power = 0;
187 gCurrLightInstance++;
188 respPLPost_light = cJSON_Print(json);
189 strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
190 ehResult = OC_EH_RESOURCE_CREATED;
197 // Update repesentation of /a/light
200 respPLPost_light = constructJsonResponse(ehRequest);
205 for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
207 if (ehRequest->resource == gLightInstance[i].handle)
209 gLightInstance[i].state = true;
210 gLightInstance[i].power = 22;
213 respPLPost_light = constructJsonResponse(ehRequest);
218 respPLPost_light = constructJsonResponse(ehRequest);
224 if ((respPLPost_light != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_light)))
226 strncpy(payload, respPLPost_light, strlen((char *)respPLPost_light));
230 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
232 ehResult = OC_EH_ERROR;
235 free(respPLPost_light);
239 OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
241 if(ehRequest == NULL)
243 OC_LOG(INFO, TAG, "The ehRequest is NULL");
246 OCEntityHandlerResult ehResult = OC_EH_OK;
248 OC_LOG_V(INFO, TAG, "\n\nExecuting %s for resource %d ", __func__, ehRequest->resource);
251 * In the sample below, the application will:
252 * 1a. pass the delete request to the c stack
253 * 1b. internally, the c stack figures out what needs to be done and does it accordingly
254 * (e.g. send observers notification, remove observers...)
255 * 1c. the c stack returns with the result whether the request is fullfilled.
256 * 2. optionally, app removes observers out of its array 'interestedObservers'
259 const char* deleteResponse = NULL;
261 if ((ehRequest != NULL) && (ehRequest->resource == Light.handle))
263 //Step 1: Ask stack to do the work.
264 OCStackResult result = OCDeleteResource(ehRequest->resource);
266 if (result == OC_STACK_OK)
268 OC_LOG (INFO, TAG, "\n\nDelete Resource operation succeeded.");
270 deleteResponse = responsePayloadDeleteOk;
272 //Step 2: clear observers who wanted to observe this resource at the app level.
273 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
275 if (interestedObservers[i].resourceHandle == ehRequest->resource)
277 interestedObservers[i].valid = false;
278 interestedObservers[i].observationId = 0;
279 interestedObservers[i].resourceHandle = NULL;
283 else if (result == OC_STACK_NO_RESOURCE)
285 OC_LOG(INFO, TAG, "\n\nThe resource doesn't exist or it might have been deleted.");
286 deleteResponse = responsePayloadResourceDoesNotExist;
287 ehResult = OC_EH_RESOURCE_DELETED;
291 OC_LOG(INFO, TAG, "\n\nEncountered error from OCDeleteResource().");
292 deleteResponse = responsePayloadDeleteNotOK;
293 ehResult = OC_EH_ERROR;
296 else if (ehRequest->resource != Light.handle)
298 //Let's this app not supporting DELETE on some resources so
299 //consider the DELETE request is received for a non-support resource.
300 OC_LOG_V(INFO, TAG, "\n\nThe request is received for a non-support resource.");
301 deleteResponse = responsePayloadDeleteResourceNotSupported;
302 ehResult = OC_EH_FORBIDDEN;
305 if (maxPayloadSize > strlen ((char *)deleteResponse))
307 strncpy(payload, deleteResponse, strlen((char *)deleteResponse));
311 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
313 ehResult = OC_EH_ERROR;
319 OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest, char *payload, uint16_t maxPayloadSize)
321 OC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__);
323 const char* response = NULL;
324 response = responsePayloadResourceDoesNotExist;
326 if ( (ehRequest != NULL) &&
327 (maxPayloadSize > strlen ((char *)response)) )
329 strncpy((char *)payload, response, strlen((char *)response));
333 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
337 return OC_EH_RESOURCE_DELETED;
340 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
342 OC_LOG_V (INFO, TAG, "Received observation registration request with observation Id %d",
343 ehRequest->obsInfo.obsId);
344 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
346 if (interestedObservers[i].valid == false)
348 interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
349 interestedObservers[i].valid = true;
350 gLightUnderObservation = 1;
356 void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest)
358 bool clientStillObserving = false;
360 OC_LOG_V (INFO, TAG, "Received observation deregistration request for observation Id %d",
361 ehRequest->obsInfo.obsId);
362 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
364 if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
366 interestedObservers[i].valid = false;
368 if (interestedObservers[i].valid == true)
370 // Even if there is one single client observing we continue notifying entity handler
371 clientStillObserving = true;
374 if (clientStillObserving == false)
375 gLightUnderObservation = 0;
378 OCEntityHandlerResult
379 OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
380 OCEntityHandlerRequest *entityHandlerRequest, char* uri)
382 OC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
384 OCEntityHandlerResult ehResult = OC_EH_OK;
385 OCEntityHandlerResponse response;
386 char payload[MAX_RESPONSE_LENGTH] = {0};
389 if (!entityHandlerRequest)
391 OC_LOG (ERROR, TAG, "Invalid request pointer");
395 // Initialize certain response fields
396 response.numSendVendorSpecificHeaderOptions = 0;
397 memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
398 memset(response.resourceUri, 0, sizeof response.resourceUri);
400 if (flag & OC_INIT_FLAG)
402 OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
404 if (flag & OC_REQUEST_FLAG)
406 OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
407 if (entityHandlerRequest->resource == NULL) {
408 OC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
409 ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest, payload, sizeof(payload) - 1);
411 else if (OC_REST_GET == entityHandlerRequest->method)
413 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
414 ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
416 else if (OC_REST_PUT == entityHandlerRequest->method)
418 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
419 ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
421 else if (OC_REST_DELETE == entityHandlerRequest->method)
423 OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
424 ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
428 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
429 entityHandlerRequest->method);
430 ehResult = OC_EH_ERROR;
433 // If the result isn't an error or forbidden, send response
434 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
436 // Format the response. Note this requires some info about the request
437 response.requestHandle = entityHandlerRequest->requestHandle;
438 response.resourceHandle = entityHandlerRequest->resource;
439 response.ehResult = ehResult;
440 response.payload = (unsigned char *)payload;
441 response.payloadSize = strlen(payload);
442 // Indicate that response is NOT in a persistent buffer
443 response.persistentBufferFlag = 0;
446 if (OCDoResponse(&response) != OC_STACK_OK)
448 OC_LOG(ERROR, TAG, "Error sending response");
449 ehResult = OC_EH_ERROR;
453 if (flag & OC_OBSERVE_FLAG)
455 OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
456 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
458 OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
460 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
462 OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
470 OCEntityHandlerResult
471 OCEntityHandlerCb (OCEntityHandlerFlag flag,
472 OCEntityHandlerRequest *entityHandlerRequest)
474 OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
476 OCEntityHandlerResult ehResult = OC_EH_OK;
477 OCEntityHandlerResponse response;
478 char payload[MAX_RESPONSE_LENGTH] = {0};
481 if (!entityHandlerRequest)
483 OC_LOG (ERROR, TAG, "Invalid request pointer");
487 // Initialize certain response fields
488 response.numSendVendorSpecificHeaderOptions = 0;
489 memset(response.sendVendorSpecificHeaderOptions, 0, sizeof response.sendVendorSpecificHeaderOptions);
490 memset(response.resourceUri, 0, sizeof response.resourceUri);
492 if (flag & OC_INIT_FLAG)
494 OC_LOG (INFO, TAG, "Flag includes OC_INIT_FLAG");
496 if (flag & OC_REQUEST_FLAG)
498 OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
499 if (OC_REST_GET == entityHandlerRequest->method)
501 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
502 ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
504 else if (OC_REST_PUT == entityHandlerRequest->method)
506 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
507 ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
509 else if (OC_REST_POST == entityHandlerRequest->method)
511 OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
512 ehResult = ProcessPostRequest (entityHandlerRequest, &response, payload, sizeof(payload) - 1);
514 else if (OC_REST_DELETE == entityHandlerRequest->method)
516 OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
517 ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
521 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
522 entityHandlerRequest->method);
525 // If the result isn't an error or forbidden, send response
526 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
528 // Format the response. Note this requires some info about the request
529 response.requestHandle = entityHandlerRequest->requestHandle;
530 response.resourceHandle = entityHandlerRequest->resource;
531 response.ehResult = ehResult;
532 response.payload = (unsigned char *)payload;
533 response.payloadSize = strlen(payload);
534 // Indicate that response is NOT in a persistent buffer
535 response.persistentBufferFlag = 0;
537 // Handle vendor specific options
538 if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
539 entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
541 OC_LOG (INFO, TAG, "Received vendor specific options");
543 OCHeaderOption * rcvdOptions = entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
544 for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
546 if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
548 OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
549 ((OCHeaderOption)rcvdOptions[i]).optionID );
550 OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
551 ((OCHeaderOption)rcvdOptions[i]).optionLength);
554 OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions;
555 uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
556 uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
557 sendOptions[0].protocolID = OC_COAP_ID;
558 sendOptions[0].optionID = 2248;
559 memcpy(sendOptions[0].optionData, option2, sizeof(option2));
560 sendOptions[0].optionLength = 10;
561 sendOptions[1].protocolID = OC_COAP_ID;
562 sendOptions[1].optionID = 2600;
563 memcpy(sendOptions[1].optionData, option3, sizeof(option3));
564 sendOptions[1].optionLength = 10;
565 response.numSendVendorSpecificHeaderOptions = 2;
569 if (OCDoResponse(&response) != OC_STACK_OK)
571 OC_LOG(ERROR, TAG, "Error sending response");
572 ehResult = OC_EH_ERROR;
576 if (flag & OC_OBSERVE_FLAG)
578 OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
580 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
582 OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
583 ProcessObserveRegister (entityHandlerRequest);
585 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
587 OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
588 ProcessObserveDeregister (entityHandlerRequest);
595 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
596 void handleSigInt(int signum) {
597 if (signum == SIGINT) {
602 void *ChangeLightRepresentation (void *param)
605 OCStackResult result = OC_STACK_ERROR;
608 uint8_t numNotifies = (SAMPLE_MAX_NUM_OBSERVATIONS)/2;
609 OCObservationId obsNotify[numNotifies];
615 if (gLightUnderObservation)
617 OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
618 if (gObserveNotifyType == 1)
620 // Notify list of observers. Alternate observers on the list will be notified.
622 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; (i=i+2))
624 if (interestedObservers[i].valid == true)
626 obsNotify[j] = interestedObservers[i].observationId;
631 cJSON *json = cJSON_CreateObject();
633 cJSON_AddStringToObject(json,"href",gResourceUri);
634 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
635 cJSON_AddStringToObject(format, "state", (char *) (Light.state ? "on":"off"));
636 cJSON_AddNumberToObject(format, "power", Light.power);
637 char * obsResp = cJSON_Print(json);
639 result = OCNotifyListOfObservers (Light.handle, obsNotify, j,
640 (unsigned char *)obsResp, OC_NA_QOS);
643 else if (gObserveNotifyType == 0)
645 // Notifying all observers
646 result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
647 if (OC_STACK_NO_OBSERVERS == result)
650 "=======> No more observers exist, stop sending observations");
651 gLightUnderObservation = 0;
656 OC_LOG (ERROR, TAG, "Incorrect notification type selected");
660 if(stopPresenceCount > 0)
662 OC_LOG_V(INFO, TAG, "================ presence count %d", stopPresenceCount);
664 if(!stopPresenceCount--)
666 OC_LOG(INFO, TAG, "================ stopping presence");
674 static void PrintUsage()
676 OC_LOG(INFO, TAG, "Usage : ocserver -o <0|1>");
677 OC_LOG(INFO, TAG, "-o 0 : Notify all observers");
678 OC_LOG(INFO, TAG, "-o 1 : Notify list of observers");
681 int main(int argc, char* argv[])
683 uint8_t addr[20] = {0};
684 uint8_t* paddr = NULL;
685 uint16_t port = OC_WELL_KNOWN_PORT;
686 uint8_t ifname[] = "eth0";
690 while ((opt = getopt(argc, argv, "o:")) != -1)
695 gObserveNotifyType = atoi(optarg);
703 if ((gObserveNotifyType != 0) && (gObserveNotifyType != 1))
709 OC_LOG(DEBUG, TAG, "OCServer is starting...");
710 /*Get Ip address on defined interface and initialize coap on it with random port number
711 * this port number will be used as a source port in all coap communications*/
712 if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
713 sizeof(addr)) == ERR_SUCCESS)
715 OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
719 if (OCInit((char *) paddr, port, OC_SERVER) != OC_STACK_OK) {
720 OC_LOG(ERROR, TAG, "OCStack init error");
724 if (OCStartPresence(0) != OC_STACK_OK) {
725 OC_LOG(ERROR, TAG, "OCStack presence/discovery error");
730 OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb);
733 * Declare and create the example resource: Light
735 createLightResource(gResourceUri, &Light);
737 // Initialize observations data structure for the resource
738 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
740 interestedObservers[i].valid = false;
744 * Create a thread for changing the representation of the Light
746 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
748 // Break from loop with Ctrl-C
749 OC_LOG(INFO, TAG, "Entering ocserver main loop...");
750 signal(SIGINT, handleSigInt);
752 if (OCProcess() != OC_STACK_OK) {
753 OC_LOG(ERROR, TAG, "OCStack process error");
761 * Cancel the Light thread and wait for it to terminate
763 pthread_cancel(threadId);
764 pthread_join(threadId, NULL);
766 OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
768 if (OCStop() != OC_STACK_OK) {
769 OC_LOG(ERROR, TAG, "OCStack process error");
775 int createLightResource (char *uri, LightResource *lightResource)
779 OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
783 lightResource->state = false;
784 lightResource->power= 0;
785 OCStackResult res = OCCreateResource(&(lightResource->handle),
790 OC_DISCOVERABLE|OC_OBSERVABLE);
791 OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));