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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
22 #include "iotivity_config.h"
38 #include "oic_malloc.h"
42 #include "ocpayload.h"
46 //string length of "/a/light/" + std::numeric_limits<int>::digits10 + '\0'"
48 const int URI_MAXSIZE = 19;
50 static int gObserveNotifyType = 3;
53 int gLightUnderObservation = 0;
55 static LightResource Light;
56 // This variable determines instance number of the Light resource.
57 // Used by POST method to create a new instance of Light resource.
58 static int gCurrLightInstance = 0;
60 static LightResource gLightInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
62 Observers interestedObservers[SAMPLE_MAX_NUM_OBSERVATIONS];
64 pthread_t threadId_observe;
65 pthread_t threadId_presence;
67 static bool observeThreadStarted = false;
70 #define numPresenceResources (2)
73 char *gResourceUri= (char *)"/a/light";
74 const char *dateOfManufacture = "2016-01-15";
75 const char *deviceName = "myDeviceName";
76 const char *deviceUUID = "51b55ddc-ccbb-4cb3-a57f-494eeca13a21";
77 const char *firmwareVersion = "myFirmwareVersion";
78 const char *manufacturerName = "myName";
79 const char *operatingSystemVersion = "myOS";
80 const char *hardwareVersion = "myHardwareVersion";
81 const char *platformID = "0A3E0D6F-DBF5-404E-8719-D6880042463A";
82 const char *manufacturerLink = "https://www.iotivity.org";
83 const char *modelNumber = "myModelNumber";
84 const char *platformVersion = "myPlatformVersion";
85 const char *supportLink = "https://www.iotivity.org";
86 const char *version = "myVersion";
87 const char *systemTime = "2015-05-15T11.04";
88 const char *specVersion = "core.1.1.0";
89 const char *dataModelVersions = "res.1.1.0,sh.1.1.0";
91 // Entity handler should check for resourceTypeName and ResourceInterface in order to GET
92 // the existence of a known resource
93 const char *resourceTypeName = "core.light";
94 const char *resourceInterface = OC_RSRVD_INTERFACE_DEFAULT;
96 OCPlatformInfo platformInfo;
97 OCDeviceInfo deviceInfo;
99 OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
101 OCRepPayload* payload = OCRepPayloadCreate();
104 OIC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
108 OCRepPayloadSetUri(payload, uri);
109 OCRepPayloadSetPropBool(payload, "state", state);
110 OCRepPayloadSetPropInt(payload, "power", power);
115 //This function takes the request as an input and returns the response
116 OCRepPayload* constructResponse(OCEntityHandlerRequest *ehRequest)
118 if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
120 OIC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
124 OCRepPayload* input = reinterpret_cast<OCRepPayload*>(ehRequest->payload);
126 LightResource *currLightResource = &Light;
128 if (ehRequest->resource == gLightInstance[0].handle)
130 currLightResource = &gLightInstance[0];
131 gResourceUri = (char *) "a/light/0";
133 else if (ehRequest->resource == gLightInstance[1].handle)
135 currLightResource = &gLightInstance[1];
136 gResourceUri = (char *) "a/light/1";
139 if(OC_REST_PUT == ehRequest->method)
141 // Get pointer to query
143 if(OCRepPayloadGetPropInt(input, "power", &pow))
145 currLightResource->power =pow;
149 if(OCRepPayloadGetPropBool(input, "state", &state))
151 currLightResource->state = state;
155 return getPayload(gResourceUri, currLightResource->power, currLightResource->state);
159 * Very simple example of query parsing.
160 * The query may have multiple filters separated by ';'.
161 * It is upto the entity handler to parse the query for the individual filters,
162 * VALIDATE them and respond as it sees fit.
164 * This function only returns false if the query is exactly "power<X" and
165 * current power is greater than X. If X cannot be parsed for an int,
168 bool checkIfQueryForPowerPassed(char * query)
170 if (query && strncmp(query, "power<", strlen("power<")) == 0)
172 char * pointerToOperator = strstr(query, "<");
174 if (pointerToOperator)
176 int powerRequested = atoi(pointerToOperator + 1);
177 if (Light.power > powerRequested)
179 OIC_LOG_V(INFO, TAG, "Current power: %d. Requested: <%d", Light.power
189 * Application should validate and process these as desired.
191 OCEntityHandlerResult ValidateQueryParams (OCEntityHandlerRequest *entityHandlerRequest)
193 OIC_LOG_V(INFO, TAG, PCF("Received query %s"), entityHandlerRequest->query);
194 OIC_LOG(INFO, TAG, PCF("Not processing query"));
198 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
199 OCRepPayload **payload)
201 OCEntityHandlerResult ehResult;
202 bool queryPassed = checkIfQueryForPowerPassed(ehRequest->query);
204 // Empty payload if the query has no match.
207 OCRepPayload *getResp = constructResponse(ehRequest);
210 OIC_LOG(ERROR, TAG, "constructResponse failed");
225 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
226 OCRepPayload** payload)
228 OCEntityHandlerResult ehResult;
229 OCRepPayload *putResp = constructResponse(ehRequest);
233 OIC_LOG(ERROR, TAG, "Failed to construct Json response");
243 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
244 OCEntityHandlerResponse *response, OCRepPayload** payload)
246 OCEntityHandlerResult ehResult = OC_EH_OK;
247 OCRepPayload *respPLPost_light = nullptr;
250 * The entity handler determines how to process a POST request.
251 * Per the REST paradigm, POST can also be used to update representation of existing
252 * resource or create a new resource.
253 * In the sample below, if the POST is for /a/light then a new instance of the Light
254 * resource is created with default representation (if representation is included in
255 * POST payload it can be used as initial values) as long as the instance is
256 * lesser than max new instance count. Once max instance count is reached, POST on
257 * /a/light updated the representation of /a/light (just like PUT)
260 if (ehRequest->resource == Light.handle)
262 if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
264 // Create new Light instance
265 char newLightUri[URI_MAXSIZE];
266 snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance);
268 respPLPost_light = OCRepPayloadCreate();
269 OCRepPayloadSetUri(respPLPost_light, gResourceUri);
270 OCRepPayloadSetPropString(respPLPost_light, "createduri", newLightUri);
272 if (0 == createLightResource (newLightUri, &gLightInstance[gCurrLightInstance]))
274 OIC_LOG (INFO, TAG, "Created new Light instance\n");
275 gLightInstance[gCurrLightInstance].state = 0;
276 gLightInstance[gCurrLightInstance].power = 0;
277 gCurrLightInstance++;
278 strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
279 ehResult = OC_EH_RESOURCE_CREATED;
284 // Update repesentation of /a/light
287 respPLPost_light = constructResponse(ehRequest);
292 for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
294 if (ehRequest->resource == gLightInstance[i].handle)
296 gLightInstance[i].state = true;
297 gLightInstance[i].power = 22;
300 respPLPost_light = constructResponse(ehRequest);
305 respPLPost_light = constructResponse(ehRequest);
311 if ((respPLPost_light != NULL))
313 *payload = respPLPost_light;
317 OIC_LOG(INFO, TAG, "Payload was NULL");
318 ehResult = OC_EH_ERROR;
324 OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest)
326 if(ehRequest == NULL)
328 OIC_LOG(INFO, TAG, "The ehRequest is NULL");
331 OCEntityHandlerResult ehResult = OC_EH_OK;
333 OIC_LOG_V(INFO, TAG, "\n\nExecuting %s for resource %p ", __func__, ehRequest->resource);
336 * In the sample below, the application will:
337 * 1a. pass the delete request to the c stack
338 * 1b. internally, the c stack figures out what needs to be done and does it accordingly
339 * (e.g. send observers notification, remove observers...)
340 * 1c. the c stack returns with the result whether the request is fullfilled.
341 * 2. optionally, app removes observers out of its array 'interestedObservers'
344 if ((ehRequest != NULL) && (ehRequest->resource == Light.handle))
346 //Step 1: Ask stack to do the work.
347 OCStackResult result = OCDeleteResource(ehRequest->resource);
349 if (result == OC_STACK_OK)
351 OIC_LOG (INFO, TAG, "\n\nDelete Resource operation succeeded.");
354 //Step 2: clear observers who wanted to observe this resource at the app level.
355 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
357 if (interestedObservers[i].resourceHandle == ehRequest->resource)
359 interestedObservers[i].valid = false;
360 interestedObservers[i].observationId = 0;
361 interestedObservers[i].resourceHandle = NULL;
365 else if (result == OC_STACK_NO_RESOURCE)
367 OIC_LOG(INFO, TAG, "\n\nThe resource doesn't exist or it might have been deleted.");
368 ehResult = OC_EH_RESOURCE_DELETED;
372 OIC_LOG(INFO, TAG, "\n\nEncountered error from OCDeleteResource().");
373 ehResult = OC_EH_ERROR;
376 else if (ehRequest->resource != Light.handle)
378 //Let's this app not supporting DELETE on some resources so
379 //consider the DELETE request is received for a non-support resource.
380 OIC_LOG_V(INFO, TAG, "\n\nThe request is received for a non-support resource.");
381 ehResult = OC_EH_FORBIDDEN;
387 OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest * /*ehRequest*/)
389 OIC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__);
391 return OC_EH_RESOURCE_NOT_FOUND;
394 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
396 OIC_LOG_V (INFO, TAG, "Received observation registration request with observation Id %d",
397 ehRequest->obsInfo.obsId);
399 if (!observeThreadStarted)
401 pthread_create (&threadId_observe, NULL, ChangeLightRepresentation, (void *)NULL);
402 observeThreadStarted = 1;
404 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
406 if (interestedObservers[i].valid == false)
408 interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
409 interestedObservers[i].valid = true;
410 gLightUnderObservation = 1;
416 void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest)
418 bool clientStillObserving = false;
420 OIC_LOG_V (INFO, TAG, "Received observation deregistration request for observation Id %d",
421 ehRequest->obsInfo.obsId);
422 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
424 if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
426 interestedObservers[i].valid = false;
428 if (interestedObservers[i].valid == true)
430 // Even if there is one single client observing we continue notifying entity handler
431 clientStillObserving = true;
434 if (clientStillObserving == false)
435 gLightUnderObservation = 0;
438 OCEntityHandlerResult
439 OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
440 OCEntityHandlerRequest *entityHandlerRequest,
442 void* /*callbackParam*/)
444 OIC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
446 OCEntityHandlerResult ehResult = OC_EH_OK;
447 OCEntityHandlerResponse response;
450 if (!entityHandlerRequest)
452 OIC_LOG (ERROR, TAG, "Invalid request pointer");
455 // Initialize certain response fields
456 response.numSendVendorSpecificHeaderOptions = 0;
457 memset(response.sendVendorSpecificHeaderOptions, 0,
458 sizeof response.sendVendorSpecificHeaderOptions);
459 memset(response.resourceUri, 0, sizeof response.resourceUri);
460 OCRepPayload* payload = nullptr;
463 if (flag & OC_REQUEST_FLAG)
465 OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
467 if (entityHandlerRequest->resource == NULL)
469 OIC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
470 ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest);
472 else if (OC_REST_GET == entityHandlerRequest->method)
474 OIC_LOG (INFO, TAG, "Received OC_REST_GET from client");
475 ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
477 else if (OC_REST_PUT == entityHandlerRequest->method)
479 OIC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
480 ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
482 else if (OC_REST_DELETE == entityHandlerRequest->method)
484 OIC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
485 ehResult = ProcessDeleteRequest (entityHandlerRequest);
489 OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
490 entityHandlerRequest->method);
491 ehResult = OC_EH_ERROR;
493 // If the result isn't an error or forbidden, send response
494 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
496 // Format the response. Note this requires some info about the request
497 response.requestHandle = entityHandlerRequest->requestHandle;
498 response.resourceHandle = entityHandlerRequest->resource;
499 response.ehResult = ehResult;
500 response.payload = reinterpret_cast<OCPayload*>(payload);
501 // Indicate that response is NOT in a persistent buffer
502 response.persistentBufferFlag = 0;
505 if (OCDoResponse(&response) != OC_STACK_OK)
507 OIC_LOG(ERROR, TAG, "Error sending response");
508 ehResult = OC_EH_ERROR;
512 if (flag & OC_OBSERVE_FLAG)
514 OIC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
515 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
517 OIC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
519 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
521 OIC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
525 OCPayloadDestroy(response.payload);
529 OCEntityHandlerResult
530 OCNOPEntityHandlerCb (OCEntityHandlerFlag /*flag*/,
531 OCEntityHandlerRequest * /*entityHandlerRequest*/,
532 void* /*callbackParam*/)
534 // This is callback is associated with the 2 presence notification
535 // resources. They are non-operational.
539 OCEntityHandlerResult
540 OCEntityHandlerCb (OCEntityHandlerFlag flag,
541 OCEntityHandlerRequest *entityHandlerRequest, void* /*callback*/)
543 OIC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
545 OCEntityHandlerResult ehResult = OC_EH_OK;
546 OCEntityHandlerResponse response = { 0, 0, OC_EH_ERROR, 0, 0, { },{ 0 }, false };
549 if (!entityHandlerRequest)
551 OIC_LOG (ERROR, TAG, "Invalid request pointer");
555 // Initialize certain response fields
556 response.numSendVendorSpecificHeaderOptions = 0;
557 memset(response.sendVendorSpecificHeaderOptions,
558 0, sizeof response.sendVendorSpecificHeaderOptions);
559 memset(response.resourceUri, 0, sizeof response.resourceUri);
560 OCRepPayload* payload = nullptr;
562 if (flag & OC_REQUEST_FLAG)
564 OIC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
566 if (OC_REST_GET == entityHandlerRequest->method)
568 OIC_LOG (INFO, TAG, "Received OC_REST_GET from client");
569 ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
571 else if (OC_REST_PUT == entityHandlerRequest->method)
573 OIC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
574 ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
576 else if (OC_REST_POST == entityHandlerRequest->method)
578 OIC_LOG (INFO, TAG, "Received OC_REST_POST from client");
579 ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
581 else if (OC_REST_DELETE == entityHandlerRequest->method)
583 OIC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
584 ehResult = ProcessDeleteRequest (entityHandlerRequest);
588 OIC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
589 entityHandlerRequest->method);
590 ehResult = OC_EH_ERROR;
592 // If the result isn't an error or forbidden, send response
593 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
595 // Format the response. Note this requires some info about the request
596 response.requestHandle = entityHandlerRequest->requestHandle;
597 response.resourceHandle = entityHandlerRequest->resource;
598 response.ehResult = ehResult;
599 response.payload = reinterpret_cast<OCPayload*>(payload);
600 // Indicate that response is NOT in a persistent buffer
601 response.persistentBufferFlag = 0;
603 // Handle vendor specific options
604 if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
605 entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
607 OIC_LOG (INFO, TAG, "Received vendor specific options");
609 OCHeaderOption * rcvdOptions =
610 entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
611 for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
613 if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
615 OIC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
616 ((OCHeaderOption)rcvdOptions[i]).optionID );
618 OIC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
619 MAX_HEADER_OPTION_DATA_LENGTH);
623 OCHeaderOption* sendOptions = response.sendVendorSpecificHeaderOptions;
624 size_t numOptions = response.numSendVendorSpecificHeaderOptions;
625 // Check if the option header has already existed before adding it in.
626 uint8_t optionData[MAX_HEADER_OPTION_DATA_LENGTH];
627 size_t optionDataSize = sizeof(optionData);
628 uint16_t actualDataSize = 0;
629 OCGetHeaderOption(response.sendVendorSpecificHeaderOptions,
630 response.numSendVendorSpecificHeaderOptions,
635 if (actualDataSize == 0)
637 uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
638 uint16_t optionID2 = 2248;
639 size_t optionDataSize2 = sizeof(option2);
640 OCSetHeaderOption(sendOptions,
647 OCGetHeaderOption(response.sendVendorSpecificHeaderOptions,
648 response.numSendVendorSpecificHeaderOptions,
653 if (actualDataSize == 0)
655 uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
656 uint16_t optionID3 = 2600;
657 size_t optionDataSize3 = sizeof(option3);
658 OCSetHeaderOption(sendOptions,
664 response.numSendVendorSpecificHeaderOptions = 2;
668 if (OCDoResponse(&response) != OC_STACK_OK)
670 OIC_LOG(ERROR, TAG, "Error sending response");
671 ehResult = OC_EH_ERROR;
675 if (flag & OC_OBSERVE_FLAG)
677 OIC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
679 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
681 OIC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
682 ProcessObserveRegister (entityHandlerRequest);
684 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
686 OIC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
687 ProcessObserveDeregister (entityHandlerRequest);
691 OCPayloadDestroy(response.payload);
695 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
696 void handleSigInt(int signum)
698 if (signum == SIGINT)
704 void *ChangeLightRepresentation (void *param)
707 OCStackResult result = OC_STACK_ERROR;
710 OCObservationId obsNotify[(SAMPLE_MAX_NUM_OBSERVATIONS)/2];
716 if (gLightUnderObservation)
718 OIC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
719 if (gObserveNotifyType == 1)
721 // Notify list of observers. Alternate observers on the list will be notified.
723 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; (i=i+2))
725 if (interestedObservers[i].valid == true)
727 obsNotify[j] = interestedObservers[i].observationId;
732 OCRepPayload* payload = getPayload(gResourceUri, Light.power, Light.state);
733 result = OCNotifyListOfObservers (Light.handle, obsNotify, j,
735 OCRepPayloadDestroy(payload);
737 else if (gObserveNotifyType == 0)
739 // Notifying all observers
740 result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
741 if (OC_STACK_NO_OBSERVERS == result)
744 "=======> No more observers exist, stop sending observations");
745 gLightUnderObservation = 0;
750 OIC_LOG (ERROR, TAG, "Incorrect notification type selected");
758 void *presenceNotificationGenerator(void *param)
760 uint8_t secondsBeforePresence = 10;
761 OIC_LOG_V(INFO, TAG, "Will send out presence in %u seconds", secondsBeforePresence);
762 sleep(secondsBeforePresence);
764 OCDoHandle presenceNotificationHandles[numPresenceResources];
765 OCStackResult res = OC_STACK_OK;
767 std::array<std::string, numPresenceResources> presenceNotificationResources { {
768 std::string("core.fan"),
769 std::string("core.led") } };
770 std::array<std::string, numPresenceResources> presenceNotificationUris { {
771 std::string("/a/fan"),
772 std::string("/a/led") } };
774 for(int i=0; i<numPresenceResources; i++)
776 if(res == OC_STACK_OK)
779 res = OCCreateResource(&presenceNotificationHandles[i],
780 presenceNotificationResources.at(i).c_str(),
781 OC_RSRVD_INTERFACE_DEFAULT,
782 presenceNotificationUris.at(i).c_str(),
783 OCNOPEntityHandlerCb,
785 OC_DISCOVERABLE|OC_OBSERVABLE);
787 if(res != OC_STACK_OK)
789 OIC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to create resource "
790 "%s with result %s.", presenceNotificationResources.at(i).c_str(),
794 OIC_LOG_V(INFO, TAG, PCF("Created %s for presence notification"),
795 presenceNotificationUris[i].c_str());
798 for(int i=0; i<numPresenceResources; i++)
800 if(res == OC_STACK_OK)
802 res = OCDeleteResource(presenceNotificationHandles[i]);
804 if(res != OC_STACK_OK)
806 OIC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to delete "\
807 "resource %s.", presenceNotificationResources.at(i).c_str());
810 OIC_LOG_V(INFO, TAG, PCF("Deleted %s for presence notification"),
811 presenceNotificationUris[i].c_str());
814 OIC_LOG(INFO, TAG, "================ stopping presence");
821 int createLightResource (char *uri, LightResource *lightResource)
825 OIC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
829 lightResource->state = false;
830 lightResource->power= 0;
831 OCStackResult res = OCCreateResource(&(lightResource->handle),
837 OC_DISCOVERABLE|OC_OBSERVABLE);
838 OIC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
843 void DeletePlatformInfo()
845 free (platformInfo.platformID);
846 free (platformInfo.manufacturerName);
847 free (platformInfo.manufacturerUrl);
848 free (platformInfo.modelNumber);
849 free (platformInfo.dateOfManufacture);
850 free (platformInfo.platformVersion);
851 free (platformInfo.operatingSystemVersion);
852 free (platformInfo.hardwareVersion);
853 free (platformInfo.firmwareVersion);
854 free (platformInfo.supportUrl);
855 free (platformInfo.systemTime);
858 void DeleteDeviceInfo()
860 free (deviceInfo.deviceName);
861 free (deviceInfo.specVersion);
862 OCFreeOCStringLL (deviceInfo.dataModelVersions);
865 bool DuplicateString(char** targetString, const char* sourceString)
873 *targetString = (char *) malloc(strlen(sourceString) + 1);
877 strncpy(*targetString, sourceString, (strlen(sourceString) + 1));
884 OCStackResult SetPlatformInfo(const char* platformID, const char *manufacturerName,
885 const char *manufacturerUrl, const char *modelNumber, const char *dateOfManufacture,
886 const char *platformVersion, const char* operatingSystemVersion, const char* hardwareVersion,
887 const char *firmwareVersion, const char* supportUrl, const char* systemTime)
892 if(manufacturerName != NULL && (strlen(manufacturerName) > MAX_PLATFORM_NAME_LENGTH))
894 return OC_STACK_INVALID_PARAM;
897 if(manufacturerUrl != NULL && (strlen(manufacturerUrl) > MAX_PLATFORM_URL_LENGTH))
899 return OC_STACK_INVALID_PARAM;
902 if(!DuplicateString(&platformInfo.platformID, platformID))
907 if(!DuplicateString(&platformInfo.manufacturerName, manufacturerName))
912 if(!DuplicateString(&platformInfo.manufacturerUrl, manufacturerUrl))
917 if(!DuplicateString(&platformInfo.modelNumber, modelNumber))
922 if(!DuplicateString(&platformInfo.dateOfManufacture, dateOfManufacture))
927 if(!DuplicateString(&platformInfo.platformVersion, platformVersion))
932 if(!DuplicateString(&platformInfo.operatingSystemVersion, operatingSystemVersion))
937 if(!DuplicateString(&platformInfo.hardwareVersion, hardwareVersion))
942 if(!DuplicateString(&platformInfo.firmwareVersion, firmwareVersion))
947 if(!DuplicateString(&platformInfo.supportUrl, supportUrl))
952 if(!DuplicateString(&platformInfo.systemTime, systemTime))
962 DeletePlatformInfo();
963 return OC_STACK_ERROR;
966 OCStackResult SetDeviceInfo(const char* deviceName, const char* specVersion, const char* dataModelVersions)
968 if(!DuplicateString(&deviceInfo.deviceName, deviceName))
970 return OC_STACK_ERROR;
972 if(!DuplicateString(&deviceInfo.specVersion, specVersion))
974 return OC_STACK_ERROR;
976 OCFreeOCStringLL(deviceInfo.dataModelVersions);
977 deviceInfo.dataModelVersions = OCCreateOCStringLL(dataModelVersions);
978 if (!deviceInfo.dataModelVersions)
980 return OC_STACK_ERROR;
985 static void PrintUsage()
987 OIC_LOG(INFO, TAG, "Usage : ocserver -o <0|1>");
988 OIC_LOG(INFO, TAG, "-o 0 : Notify all observers");
989 OIC_LOG(INFO, TAG, "-o 1 : Notify list of observers");
993 static void jidbound(char *jid)
995 OIC_LOG_V(INFO, TAG, "\n\n Bound JID: %s\n\n", jid);
999 int main(int argc, char* argv[])
1003 char host[] = "localhost";
1004 char user[] = "test1";
1005 char pass[] = "intel123";
1007 OCRAInfo_t rainfo = {};
1009 rainfo.hostname = host;
1011 rainfo.xmpp_domain = host;
1012 rainfo.username = user;
1013 rainfo.password = pass;
1014 rainfo.resource = empstr;
1015 rainfo.user_jid = empstr;
1016 rainfo.jidbound = jidbound;
1020 while ((opt = getopt(argc, argv, "o:s:p:d:u:w:r:j:")) != -1)
1025 gObserveNotifyType = atoi(optarg);
1029 rainfo.hostname = optarg;
1032 rainfo.port = atoi(optarg);
1035 rainfo.xmpp_domain = optarg;
1038 rainfo.username = optarg;
1041 rainfo.password = optarg;
1044 rainfo.user_jid = optarg;
1047 rainfo.resource = optarg;
1056 if ((gObserveNotifyType != 0) && (gObserveNotifyType != 1))
1063 OCSetRAInfo(&rainfo);
1066 OIC_LOG(DEBUG, TAG, "OCServer is starting...");
1068 if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
1070 OIC_LOG(ERROR, TAG, "OCStack init error");
1073 #ifdef WITH_PRESENCE
1074 if (OCStartPresence(0) != OC_STACK_OK)
1076 OIC_LOG(ERROR, TAG, "OCStack presence/discovery error");
1081 OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb, NULL);
1083 OCStackResult registrationResult =
1084 SetPlatformInfo(platformID, manufacturerName, manufacturerLink, modelNumber,
1085 dateOfManufacture, platformVersion, operatingSystemVersion, hardwareVersion,
1086 firmwareVersion, supportLink, systemTime);
1088 if (registrationResult != OC_STACK_OK)
1090 OIC_LOG(INFO, TAG, "Platform info setting failed locally!");
1091 exit (EXIT_FAILURE);
1094 registrationResult = OCSetPlatformInfo(platformInfo);
1096 if (registrationResult != OC_STACK_OK)
1098 OIC_LOG(INFO, TAG, "Platform Registration failed!");
1099 exit (EXIT_FAILURE);
1102 registrationResult = SetDeviceInfo(deviceName, specVersion, dataModelVersions);
1104 if (registrationResult != OC_STACK_OK)
1106 OIC_LOG(INFO, TAG, "Device info setting failed locally!");
1107 exit (EXIT_FAILURE);
1110 OCResourcePayloadAddStringLL(&deviceInfo.types, "oic.d.tv");
1112 registrationResult = OCSetDeviceInfo(deviceInfo);
1114 if (registrationResult != OC_STACK_OK)
1116 OIC_LOG(INFO, TAG, "Device Registration failed!");
1117 exit (EXIT_FAILURE);
1121 * Declare and create the example resource: Light
1123 createLightResource(gResourceUri, &Light);
1125 // Initialize observations data structure for the resource
1126 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
1128 interestedObservers[i].valid = false;
1133 * Create a thread for generating changes that cause presence notifications
1134 * to be sent to clients
1137 #ifdef WITH_PRESENCE
1138 pthread_create(&threadId_presence, NULL, presenceNotificationGenerator, (void *)NULL);
1141 // Break from loop with Ctrl-C
1142 OIC_LOG(INFO, TAG, "Entering ocserver main loop...");
1144 DeletePlatformInfo();
1147 signal(SIGINT, handleSigInt);
1151 if (OCProcess() != OC_STACK_OK)
1153 OIC_LOG(ERROR, TAG, "OCStack process error");
1158 if (observeThreadStarted)
1160 #ifdef HAVE_PTHREAD_H
1161 pthread_cancel(threadId_observe);
1162 pthread_join(threadId_observe, NULL);
1166 #ifdef HAVE_PTHREAD_H
1167 pthread_cancel(threadId_presence);
1168 pthread_join(threadId_presence, NULL);
1171 OIC_LOG(INFO, TAG, "Exiting ocserver main loop...");
1173 if (OCStop() != OC_STACK_OK)
1175 OIC_LOG(ERROR, TAG, "OCStack process error");