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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
35 //string length of "/a/light/" + std::numeric_limits<int>::digits10 + '\0'"
37 const int URI_MAXSIZE = 19;
39 static int gObserveNotifyType = 3;
42 int gLightUnderObservation = 0;
44 static LightResource Light;
45 // This variable determines instance number of the Light resource.
46 // Used by POST method to create a new instance of Light resource.
47 static int gCurrLightInstance = 0;
49 static LightResource gLightInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
51 Observers interestedObservers[SAMPLE_MAX_NUM_OBSERVATIONS];
54 static int stopPresenceCount = 10;
55 #define numPresenceResources (2)
58 //TODO: Follow the pattern used in constructJsonResponse() when the payload is decided.
59 const char responsePayloadDeleteOk[] =
60 "{App determines payload: Delete Resource operation succeeded.}";
61 const char responsePayloadDeleteNotOK[] =
62 "{App determines payload: Delete Resource operation failed.}";
63 const char responsePayloadResourceDoesNotExist[] =
64 "{App determines payload: The resource does not exist.}";
65 const char responsePayloadDeleteResourceNotSupported[] =
66 "{App determines payload: The request is received for a non-support resource.}";
69 char *gResourceUri= (char *)"/a/light";
70 const char *dateOfManufacture = "myDateOfManufacture";
71 const char *deviceName = "myDeviceName";
72 const char *deviceUUID = "myDeviceUUID";
73 const char *firmwareVersion = "myFirmwareVersion";
74 const char *manufacturerName = "myName";
75 const char *operatingSystemVersion = "myOS";
76 const char *hardwareVersion = "myHardwareVersion";
77 const char* platformID = "myPlatformID";
78 const char *manufacturerUrl = "myManufacturerUrl";
79 const char *modelNumber = "myModelNumber";
80 const char *platformVersion = "myPlatformVersion";
81 const char *supportUrl = "mySupportUrl";
82 const char *version = "myVersion";
83 const char *systemTime = "2015-05-15T11.04";
85 // Entity handler should check for resourceTypeName and ResourceInterface in order to GET
86 // the existence of a known resource
87 const char *resourceTypeName = "core.light";
88 const char *resourceInterface = OC_RSRVD_INTERFACE_DEFAULT;
90 OCPlatformInfo platformInfo;
91 OCDeviceInfo deviceInfo;
93 //This function takes the request as an input and returns the response
95 char* constructJsonResponse (OCEntityHandlerRequest *ehRequest)
97 cJSON *json = cJSON_CreateObject();
100 LightResource *currLightResource = &Light;
102 if (ehRequest->resource == gLightInstance[0].handle)
104 currLightResource = &gLightInstance[0];
105 gResourceUri = (char *) "a/light/0";
107 else if (ehRequest->resource == gLightInstance[1].handle)
109 currLightResource = &gLightInstance[1];
110 gResourceUri = (char *) "a/light/1";
113 if(OC_REST_PUT == ehRequest->method)
115 // Get cJSON pointer to query
116 cJSON *putJson = cJSON_Parse(ehRequest->reqJSONPayload);
120 OC_LOG_V(ERROR, TAG, "Failed to parse JSON: %s", ehRequest->reqJSONPayload);
124 // Get root of JSON payload, then the 1st resource.
125 cJSON* carrier = cJSON_GetObjectItem(putJson, "oic");
128 carrier = cJSON_GetArrayItem(carrier, 0);
129 carrier = cJSON_GetObjectItem(carrier, "rep");
131 cJSON* prop = cJSON_GetObjectItem(carrier,"power");
134 currLightResource->power =prop->valueint;
137 prop = cJSON_GetObjectItem(carrier,"state");
140 currLightResource->state = prop->valueint;
145 OC_LOG_V(WARNING, TAG, "Failed to find oic node");
148 cJSON_Delete(putJson);
151 cJSON_AddStringToObject(json,"href",gResourceUri);
152 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
153 cJSON_AddBoolToObject(format, "state", currLightResource->state);
154 cJSON_AddNumberToObject(format, "power", currLightResource->power);
156 jsonResponse = cJSON_Print(json);
163 * Very simple example of query parsing.
164 * The query may have multiple filters separated by ';'.
165 * It is upto the entity handler to parse the query for the individual filters,
166 * VALIDATE them and respond as it sees fit.
168 * This function only returns false if the query is exactly "power<X" and
169 * current power is greater than X. If X cannot be parsed for an int,
172 bool checkIfQueryForPowerPassed(char * query)
174 if (query && strncmp(query, "power<", strlen("power<")) == 0)
176 char * pointerToOperator = strstr(query, "<");
178 if (pointerToOperator)
180 int powerRequested = atoi(pointerToOperator + 1);
181 if (Light.power > powerRequested)
183 OC_LOG_V(INFO, TAG, "Current power: %d. Requested: <%d", Light.power
193 * Application should validate and process these as desired.
195 OCEntityHandlerResult ValidateQueryParams (OCEntityHandlerRequest *entityHandlerRequest)
197 OC_LOG_V(INFO, TAG, PCF("Received query %s"), entityHandlerRequest->query);
198 OC_LOG(INFO, TAG, PCF("Not processing query"));
202 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
203 char *payload, uint16_t maxPayloadSize)
205 OCEntityHandlerResult ehResult;
206 bool queryPassed = checkIfQueryForPowerPassed(ehRequest->query);
208 // Empty payload if the query has no match.
211 char *getResp = constructJsonResponse(ehRequest);
214 OC_LOG(ERROR, TAG, "constructJsonResponse failed");
218 if (maxPayloadSize > strlen (getResp))
220 strncpy(payload, getResp, strlen(getResp));
225 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
227 ehResult = OC_EH_ERROR;
240 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
241 char *payload, uint16_t maxPayloadSize)
243 OCEntityHandlerResult ehResult;
244 char *putResp = constructJsonResponse(ehRequest);
248 OC_LOG(ERROR, TAG, "Failed to construct Json response");
252 if (maxPayloadSize > strlen ((char *)putResp))
254 strncpy(payload, putResp, strlen((char *)putResp));
259 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
261 ehResult = OC_EH_ERROR;
269 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
270 OCEntityHandlerResponse *response, char *payload, uint16_t maxPayloadSize)
272 OCEntityHandlerResult ehResult = OC_EH_OK;
273 char *respPLPost_light = NULL;
278 * The entity handler determines how to process a POST request.
279 * Per the REST paradigm, POST can also be used to update representation of existing
280 * resource or create a new resource.
281 * In the sample below, if the POST is for /a/light then a new instance of the Light
282 * resource is created with default representation (if representation is included in
283 * POST payload it can be used as initial values) as long as the instance is
284 * lesser than max new instance count. Once max instance count is reached, POST on
285 * /a/light updated the representation of /a/light (just like PUT)
288 if (ehRequest->resource == Light.handle)
290 if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
292 // Create new Light instance
293 char newLightUri[URI_MAXSIZE];
294 snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance);
296 json = cJSON_CreateObject();
297 cJSON_AddStringToObject(json,"href",gResourceUri);
298 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
299 cJSON_AddStringToObject(format, "createduri", (char *) newLightUri);
301 if (0 == createLightResource (newLightUri, &gLightInstance[gCurrLightInstance]))
303 OC_LOG (INFO, TAG, "Created new Light instance\n");
304 gLightInstance[gCurrLightInstance].state = 0;
305 gLightInstance[gCurrLightInstance].power = 0;
306 gCurrLightInstance++;
307 respPLPost_light = cJSON_Print(json);
308 strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
309 ehResult = OC_EH_RESOURCE_CREATED;
316 // Update repesentation of /a/light
319 respPLPost_light = constructJsonResponse(ehRequest);
324 for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
326 if (ehRequest->resource == gLightInstance[i].handle)
328 gLightInstance[i].state = true;
329 gLightInstance[i].power = 22;
332 respPLPost_light = constructJsonResponse(ehRequest);
337 respPLPost_light = constructJsonResponse(ehRequest);
343 if ((respPLPost_light != NULL) && (maxPayloadSize > strlen ((char *)respPLPost_light)))
345 strncpy(payload, respPLPost_light, strlen((char *)respPLPost_light));
349 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
351 ehResult = OC_EH_ERROR;
354 free(respPLPost_light);
358 OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest,
359 char *payload, uint16_t maxPayloadSize)
361 if(ehRequest == NULL)
363 OC_LOG(INFO, TAG, "The ehRequest is NULL");
366 OCEntityHandlerResult ehResult = OC_EH_OK;
368 OC_LOG_V(INFO, TAG, "\n\nExecuting %s for resource %d ", __func__, ehRequest->resource);
371 * In the sample below, the application will:
372 * 1a. pass the delete request to the c stack
373 * 1b. internally, the c stack figures out what needs to be done and does it accordingly
374 * (e.g. send observers notification, remove observers...)
375 * 1c. the c stack returns with the result whether the request is fullfilled.
376 * 2. optionally, app removes observers out of its array 'interestedObservers'
379 const char* deleteResponse = NULL;
381 if ((ehRequest != NULL) && (ehRequest->resource == Light.handle))
383 //Step 1: Ask stack to do the work.
384 OCStackResult result = OCDeleteResource(ehRequest->resource);
386 if (result == OC_STACK_OK)
388 OC_LOG (INFO, TAG, "\n\nDelete Resource operation succeeded.");
390 deleteResponse = responsePayloadDeleteOk;
392 //Step 2: clear observers who wanted to observe this resource at the app level.
393 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
395 if (interestedObservers[i].resourceHandle == ehRequest->resource)
397 interestedObservers[i].valid = false;
398 interestedObservers[i].observationId = 0;
399 interestedObservers[i].resourceHandle = NULL;
403 else if (result == OC_STACK_NO_RESOURCE)
405 OC_LOG(INFO, TAG, "\n\nThe resource doesn't exist or it might have been deleted.");
406 deleteResponse = responsePayloadResourceDoesNotExist;
407 ehResult = OC_EH_RESOURCE_DELETED;
411 OC_LOG(INFO, TAG, "\n\nEncountered error from OCDeleteResource().");
412 deleteResponse = responsePayloadDeleteNotOK;
413 ehResult = OC_EH_ERROR;
416 else if (ehRequest->resource != Light.handle)
418 //Let's this app not supporting DELETE on some resources so
419 //consider the DELETE request is received for a non-support resource.
420 OC_LOG_V(INFO, TAG, "\n\nThe request is received for a non-support resource.");
421 deleteResponse = responsePayloadDeleteResourceNotSupported;
422 ehResult = OC_EH_FORBIDDEN;
425 if (maxPayloadSize > strlen ((char *)deleteResponse))
427 strncpy(payload, deleteResponse, strlen((char *)deleteResponse));
431 OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
433 ehResult = OC_EH_ERROR;
439 OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest *ehRequest,
440 char *payload, uint16_t maxPayloadSize)
442 OC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__);
444 const char* response = NULL;
445 response = responsePayloadResourceDoesNotExist;
447 if ( (ehRequest != NULL) &&
448 (maxPayloadSize > strlen ((char *)response)) )
450 strncpy((char *)payload, response, strlen((char *)response));
454 OC_LOG_V (ERROR, TAG, "Response buffer: %d bytes is too small",
458 return OC_EH_RESOURCE_NOT_FOUND;
461 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
463 OC_LOG_V (INFO, TAG, "Received observation registration request with observation Id %d",
464 ehRequest->obsInfo.obsId);
465 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
467 if (interestedObservers[i].valid == false)
469 interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
470 interestedObservers[i].valid = true;
471 gLightUnderObservation = 1;
477 void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest)
479 bool clientStillObserving = false;
481 OC_LOG_V (INFO, TAG, "Received observation deregistration request for observation Id %d",
482 ehRequest->obsInfo.obsId);
483 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
485 if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
487 interestedObservers[i].valid = false;
489 if (interestedObservers[i].valid == true)
491 // Even if there is one single client observing we continue notifying entity handler
492 clientStillObserving = true;
495 if (clientStillObserving == false)
496 gLightUnderObservation = 0;
499 OCEntityHandlerResult
500 OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
501 OCEntityHandlerRequest *entityHandlerRequest, char* uri, void* callbackParam)
503 OC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
505 OCEntityHandlerResult ehResult = OC_EH_OK;
506 OCEntityHandlerResponse response;
507 char payload[MAX_RESPONSE_LENGTH] = {0};
510 if (!entityHandlerRequest)
512 OC_LOG (ERROR, TAG, "Invalid request pointer");
515 // Initialize certain response fields
516 response.numSendVendorSpecificHeaderOptions = 0;
517 memset(response.sendVendorSpecificHeaderOptions, 0,
518 sizeof response.sendVendorSpecificHeaderOptions);
519 memset(response.resourceUri, 0, sizeof response.resourceUri);
522 if (flag & OC_REQUEST_FLAG)
524 OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
526 if (entityHandlerRequest->resource == NULL)
528 OC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
529 ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest,
530 payload, sizeof(payload) - 1);
532 else if (OC_REST_GET == entityHandlerRequest->method)
534 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
535 ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
537 else if (OC_REST_PUT == entityHandlerRequest->method)
539 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
540 ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
542 else if (OC_REST_DELETE == entityHandlerRequest->method)
544 OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
545 ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
549 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
550 entityHandlerRequest->method);
551 ehResult = OC_EH_ERROR;
553 // If the result isn't an error or forbidden, send response
554 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
556 // Format the response. Note this requires some info about the request
557 response.requestHandle = entityHandlerRequest->requestHandle;
558 response.resourceHandle = entityHandlerRequest->resource;
559 response.ehResult = ehResult;
560 response.payload = payload;
561 response.payloadSize = strlen(payload);
562 // Indicate that response is NOT in a persistent buffer
563 response.persistentBufferFlag = 0;
566 if (OCDoResponse(&response) != OC_STACK_OK)
568 OC_LOG(ERROR, TAG, "Error sending response");
569 ehResult = OC_EH_ERROR;
573 if (flag & OC_OBSERVE_FLAG)
575 OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
576 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
578 OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
580 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
582 OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
589 OCEntityHandlerResult
590 OCNOPEntityHandlerCb (OCEntityHandlerFlag flag,
591 OCEntityHandlerRequest *entityHandlerRequest, void* callbackParam)
593 // This is callback is associated with the 2 presence notification
594 // resources. They are non-operational.
598 OCEntityHandlerResult
599 OCEntityHandlerCb (OCEntityHandlerFlag flag,
600 OCEntityHandlerRequest *entityHandlerRequest, void* callback)
602 OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
604 OCEntityHandlerResult ehResult = OC_EH_OK;
605 OCEntityHandlerResponse response;
606 char payload[MAX_RESPONSE_LENGTH] = {0};
609 if (!entityHandlerRequest)
611 OC_LOG (ERROR, TAG, "Invalid request pointer");
615 // Initialize certain response fields
616 response.numSendVendorSpecificHeaderOptions = 0;
617 memset(response.sendVendorSpecificHeaderOptions,
618 0, sizeof response.sendVendorSpecificHeaderOptions);
619 memset(response.resourceUri, 0, sizeof response.resourceUri);
621 if (flag & OC_REQUEST_FLAG)
623 OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
625 if (OC_REST_GET == entityHandlerRequest->method)
627 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
628 ehResult = ProcessGetRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
630 else if (OC_REST_PUT == entityHandlerRequest->method)
632 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
633 ehResult = ProcessPutRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
635 else if (OC_REST_POST == entityHandlerRequest->method)
637 OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
638 ehResult = ProcessPostRequest (entityHandlerRequest, &response, payload, sizeof(payload) - 1);
640 else if (OC_REST_DELETE == entityHandlerRequest->method)
642 OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
643 ehResult = ProcessDeleteRequest (entityHandlerRequest, payload, sizeof(payload) - 1);
647 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
648 entityHandlerRequest->method);
649 ehResult = OC_EH_ERROR;
651 // If the result isn't an error or forbidden, send response
652 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
654 // Format the response. Note this requires some info about the request
655 response.requestHandle = entityHandlerRequest->requestHandle;
656 response.resourceHandle = entityHandlerRequest->resource;
657 response.ehResult = ehResult;
658 response.payload = payload;
659 response.payloadSize = strlen(payload);
660 // Indicate that response is NOT in a persistent buffer
661 response.persistentBufferFlag = 0;
663 // Handle vendor specific options
664 if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
665 entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
667 OC_LOG (INFO, TAG, "Received vendor specific options");
669 OCHeaderOption * rcvdOptions =
670 entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
671 for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
673 if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
675 OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
676 ((OCHeaderOption)rcvdOptions[i]).optionID );
678 OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
679 MAX_HEADER_OPTION_DATA_LENGTH);
682 OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions;
683 uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
684 uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
685 sendOptions[0].protocolID = OC_COAP_ID;
686 sendOptions[0].optionID = 2248;
687 memcpy(sendOptions[0].optionData, option2, sizeof(option2));
688 sendOptions[0].optionLength = 10;
689 sendOptions[1].protocolID = OC_COAP_ID;
690 sendOptions[1].optionID = 2600;
691 memcpy(sendOptions[1].optionData, option3, sizeof(option3));
692 sendOptions[1].optionLength = 10;
693 response.numSendVendorSpecificHeaderOptions = 2;
697 if (OCDoResponse(&response) != OC_STACK_OK)
699 OC_LOG(ERROR, TAG, "Error sending response");
700 ehResult = OC_EH_ERROR;
704 if (flag & OC_OBSERVE_FLAG)
706 OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
708 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
710 OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
711 ProcessObserveRegister (entityHandlerRequest);
713 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
715 OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
716 ProcessObserveDeregister (entityHandlerRequest);
723 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
724 void handleSigInt(int signum)
726 if (signum == SIGINT)
732 void *ChangeLightRepresentation (void *param)
735 OCStackResult result = OC_STACK_ERROR;
738 uint8_t numNotifies = (SAMPLE_MAX_NUM_OBSERVATIONS)/2;
739 OCObservationId obsNotify[numNotifies];
745 if (gLightUnderObservation)
747 OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
748 if (gObserveNotifyType == 1)
750 // Notify list of observers. Alternate observers on the list will be notified.
752 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; (i=i+2))
754 if (interestedObservers[i].valid == true)
756 obsNotify[j] = interestedObservers[i].observationId;
761 cJSON *json = cJSON_CreateObject();
763 cJSON_AddStringToObject(json,"href",gResourceUri);
764 cJSON_AddItemToObject(json, "rep", format=cJSON_CreateObject());
765 cJSON_AddBoolToObject(format, "state", Light.state);
766 cJSON_AddNumberToObject(format, "power", Light.power);
768 char * obsResp = cJSON_Print(json);
770 result = OCNotifyListOfObservers (Light.handle, obsNotify, j,
774 else if (gObserveNotifyType == 0)
776 // Notifying all observers
777 result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
778 if (OC_STACK_NO_OBSERVERS == result)
781 "=======> No more observers exist, stop sending observations");
782 gLightUnderObservation = 0;
787 OC_LOG (ERROR, TAG, "Incorrect notification type selected");
791 if(stopPresenceCount > 0)
793 OC_LOG_V(INFO, TAG, "================ Counting down to stop presence %d", stopPresenceCount);
795 if(!stopPresenceCount--)
797 OC_LOG(INFO, TAG, "================ stopping presence");
806 void *presenceNotificationGenerator(void *param)
810 OCDoHandle presenceNotificationHandles[numPresenceResources];
811 OCStackResult res = OC_STACK_OK;
813 std::array<std::string, numPresenceResources> presenceNotificationResources { {
814 std::string("core.fan"),
815 std::string("core.led") } };
816 std::array<std::string, numPresenceResources> presenceNotificationUris { {
817 std::string("/a/fan"),
818 std::string("/a/led") } };
820 for(int i=0; i<numPresenceResources; i++)
822 if(res == OC_STACK_OK)
825 res = OCCreateResource(&presenceNotificationHandles[i],
826 presenceNotificationResources.at(i).c_str(),
827 OC_RSRVD_INTERFACE_DEFAULT,
828 presenceNotificationUris.at(i).c_str(),
829 OCNOPEntityHandlerCb,
831 OC_DISCOVERABLE|OC_OBSERVABLE);
833 if(res != OC_STACK_OK)
835 OC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to create resource "
836 "%s with result %s.", presenceNotificationResources.at(i).c_str(),
840 OC_LOG_V(INFO, TAG, PCF("Created %s for presence notification"),
841 presenceNotificationUris[i].c_str());
844 for(int i=0; i<numPresenceResources; i++)
846 if(res == OC_STACK_OK)
848 res = OCDeleteResource(presenceNotificationHandles[i]);
850 if(res != OC_STACK_OK)
852 OC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to delete "\
853 "resource %s.", presenceNotificationResources.at(i).c_str());
856 OC_LOG_V(INFO, TAG, PCF("Deleted %s for presence notification"),
857 presenceNotificationUris[i].c_str());
863 int createLightResource (char *uri, LightResource *lightResource)
867 OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
871 lightResource->state = false;
872 lightResource->power= 0;
873 OCStackResult res = OCCreateResource(&(lightResource->handle),
879 OC_DISCOVERABLE|OC_OBSERVABLE);
880 OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
885 void DeletePlatformInfo()
887 free (platformInfo.platformID);
888 free (platformInfo.manufacturerName);
889 free (platformInfo.manufacturerUrl);
890 free (platformInfo.modelNumber);
891 free (platformInfo.dateOfManufacture);
892 free (platformInfo.platformVersion);
893 free (platformInfo.operatingSystemVersion);
894 free (platformInfo.hardwareVersion);
895 free (platformInfo.firmwareVersion);
896 free (platformInfo.supportUrl);
897 free (platformInfo.systemTime);
900 void DeleteDeviceInfo()
902 free (deviceInfo.deviceName);
905 bool DuplicateString(char** targetString, const char* sourceString)
913 *targetString = (char *) malloc(strlen(sourceString) + 1);
917 strncpy(*targetString, sourceString, (strlen(sourceString) + 1));
924 OCStackResult SetPlatformInfo(const char* platformID, const char *manufacturerName,
925 const char *manufacturerUrl, const char *modelNumber, const char *dateOfManufacture,
926 const char *platformVersion, const char* operatingSystemVersion, const char* hardwareVersion,
927 const char *firmwareVersion, const char* supportUrl, const char* systemTime)
932 if(manufacturerName != NULL && (strlen(manufacturerName) > MAX_MANUFACTURER_NAME_LENGTH))
934 return OC_STACK_INVALID_PARAM;
937 if(manufacturerUrl != NULL && (strlen(manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH))
939 return OC_STACK_INVALID_PARAM;
942 if(!DuplicateString(&platformInfo.platformID, platformID))
947 if(!DuplicateString(&platformInfo.manufacturerName, manufacturerName))
952 if(!DuplicateString(&platformInfo.manufacturerUrl, manufacturerUrl))
957 if(!DuplicateString(&platformInfo.modelNumber, modelNumber))
962 if(!DuplicateString(&platformInfo.dateOfManufacture, dateOfManufacture))
967 if(!DuplicateString(&platformInfo.platformVersion, platformVersion))
972 if(!DuplicateString(&platformInfo.operatingSystemVersion, operatingSystemVersion))
977 if(!DuplicateString(&platformInfo.hardwareVersion, hardwareVersion))
982 if(!DuplicateString(&platformInfo.firmwareVersion, firmwareVersion))
987 if(!DuplicateString(&platformInfo.supportUrl, supportUrl))
992 if(!DuplicateString(&platformInfo.systemTime, systemTime))
1002 DeletePlatformInfo();
1003 return OC_STACK_ERROR;
1006 OCStackResult SetDeviceInfo(const char* deviceName)
1008 if(!DuplicateString(&deviceInfo.deviceName, deviceName))
1010 return OC_STACK_ERROR;
1015 static void PrintUsage()
1017 OC_LOG(INFO, TAG, "Usage : ocserver -o <0|1>");
1018 OC_LOG(INFO, TAG, "-o 0 : Notify all observers");
1019 OC_LOG(INFO, TAG, "-o 1 : Notify list of observers");
1022 int main(int argc, char* argv[])
1025 pthread_t threadId_presence;
1028 while ((opt = getopt(argc, argv, "o:")) != -1)
1033 gObserveNotifyType = atoi(optarg);
1041 if ((gObserveNotifyType != 0) && (gObserveNotifyType != 1))
1047 OC_LOG(DEBUG, TAG, "OCServer is starting...");
1049 if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
1051 OC_LOG(ERROR, TAG, "OCStack init error");
1054 #ifdef WITH_PRESENCE
1055 if (OCStartPresence(0) != OC_STACK_OK)
1057 OC_LOG(ERROR, TAG, "OCStack presence/discovery error");
1062 OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb, NULL);
1064 OCStackResult registrationResult =
1065 SetPlatformInfo(platformID, manufacturerName, manufacturerUrl, modelNumber,
1066 dateOfManufacture, platformVersion, operatingSystemVersion, hardwareVersion,
1067 firmwareVersion, supportUrl, systemTime);
1069 if (registrationResult != OC_STACK_OK)
1071 OC_LOG(INFO, TAG, "Platform info setting failed locally!");
1072 exit (EXIT_FAILURE);
1075 registrationResult = OCSetPlatformInfo(platformInfo);
1077 if (registrationResult != OC_STACK_OK)
1079 OC_LOG(INFO, TAG, "Platform Registration failed!");
1080 exit (EXIT_FAILURE);
1083 registrationResult = SetDeviceInfo(deviceName);
1085 if (registrationResult != OC_STACK_OK)
1087 OC_LOG(INFO, TAG, "Device info setting failed locally!");
1088 exit (EXIT_FAILURE);
1091 registrationResult = OCSetDeviceInfo(deviceInfo);
1093 if (registrationResult != OC_STACK_OK)
1095 OC_LOG(INFO, TAG, "Device Registration failed!");
1096 exit (EXIT_FAILURE);
1100 * Declare and create the example resource: Light
1102 createLightResource(gResourceUri, &Light);
1104 // Initialize observations data structure for the resource
1105 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
1107 interestedObservers[i].valid = false;
1111 * Create a thread for changing the representation of the Light
1113 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
1116 * Create a thread for generating changes that cause presence notifications
1117 * to be sent to clients
1120 #ifdef WITH_PRESENCE
1121 pthread_create(&threadId_presence, NULL, presenceNotificationGenerator, (void *)NULL);
1124 // Break from loop with Ctrl-C
1125 OC_LOG(INFO, TAG, "Entering ocserver main loop...");
1127 DeletePlatformInfo();
1130 signal(SIGINT, handleSigInt);
1134 if (OCProcess() != OC_STACK_OK)
1136 OC_LOG(ERROR, TAG, "OCStack process error");
1144 * Cancel the Light thread and wait for it to terminate
1146 pthread_cancel(threadId);
1147 pthread_join(threadId, NULL);
1148 pthread_cancel(threadId_presence);
1149 pthread_join(threadId_presence, NULL);
1151 OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
1153 if (OCStop() != OC_STACK_OK)
1155 OC_LOG(ERROR, TAG, "OCStack process error");