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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
32 #include "ocpayload.h"
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];
53 pthread_t threadId_observe;
54 pthread_t threadId_presence;
56 static bool observeThreadStarted = false;
59 #define numPresenceResources (2)
62 char *gResourceUri= (char *)"/a/light";
63 const char *dateOfManufacture = "myDateOfManufacture";
64 const char *deviceName = "myDeviceName";
65 const char *deviceUUID = "myDeviceUUID";
66 const char *firmwareVersion = "myFirmwareVersion";
67 const char *manufacturerName = "myName";
68 const char *operatingSystemVersion = "myOS";
69 const char *hardwareVersion = "myHardwareVersion";
70 const char* platformID = "myPlatformID";
71 const char *manufacturerUrl = "myManufacturerUrl";
72 const char *modelNumber = "myModelNumber";
73 const char *platformVersion = "myPlatformVersion";
74 const char *supportUrl = "mySupportUrl";
75 const char *version = "myVersion";
76 const char *systemTime = "2015-05-15T11.04";
78 // Entity handler should check for resourceTypeName and ResourceInterface in order to GET
79 // the existence of a known resource
80 const char *resourceTypeName = "core.light";
81 const char *resourceInterface = OC_RSRVD_INTERFACE_DEFAULT;
83 OCPlatformInfo platformInfo;
84 OCDeviceInfo deviceInfo;
86 OCRepPayload* getPayload(const char* uri, int64_t power, bool state)
88 OCRepPayload* payload = OCRepPayloadCreate();
91 OC_LOG(ERROR, TAG, PCF("Failed to allocate Payload"));
95 OCRepPayloadSetUri(payload, uri);
96 OCRepPayloadSetPropBool(payload, "state", state);
97 OCRepPayloadSetPropInt(payload, "power", power);
102 //This function takes the request as an input and returns the response
103 OCRepPayload* constructResponse(OCEntityHandlerRequest *ehRequest)
105 if(ehRequest->payload && ehRequest->payload->type != PAYLOAD_TYPE_REPRESENTATION)
107 OC_LOG(ERROR, TAG, PCF("Incoming payload not a representation"));
111 OCRepPayload* input = reinterpret_cast<OCRepPayload*>(ehRequest->payload);
113 LightResource *currLightResource = &Light;
115 if (ehRequest->resource == gLightInstance[0].handle)
117 currLightResource = &gLightInstance[0];
118 gResourceUri = (char *) "a/light/0";
120 else if (ehRequest->resource == gLightInstance[1].handle)
122 currLightResource = &gLightInstance[1];
123 gResourceUri = (char *) "a/light/1";
126 if(OC_REST_PUT == ehRequest->method)
128 // Get pointer to query
130 if(OCRepPayloadGetPropInt(input, "power", &pow))
132 currLightResource->power =pow;
136 if(OCRepPayloadGetPropBool(input, "state", &state))
138 currLightResource->state = state;
142 return getPayload(gResourceUri, currLightResource->power, currLightResource->state);
146 * Very simple example of query parsing.
147 * The query may have multiple filters separated by ';'.
148 * It is upto the entity handler to parse the query for the individual filters,
149 * VALIDATE them and respond as it sees fit.
151 * This function only returns false if the query is exactly "power<X" and
152 * current power is greater than X. If X cannot be parsed for an int,
155 bool checkIfQueryForPowerPassed(char * query)
157 if (query && strncmp(query, "power<", strlen("power<")) == 0)
159 char * pointerToOperator = strstr(query, "<");
161 if (pointerToOperator)
163 int powerRequested = atoi(pointerToOperator + 1);
164 if (Light.power > powerRequested)
166 OC_LOG_V(INFO, TAG, "Current power: %d. Requested: <%d", Light.power
176 * Application should validate and process these as desired.
178 OCEntityHandlerResult ValidateQueryParams (OCEntityHandlerRequest *entityHandlerRequest)
180 OC_LOG_V(INFO, TAG, PCF("Received query %s"), entityHandlerRequest->query);
181 OC_LOG(INFO, TAG, PCF("Not processing query"));
185 OCEntityHandlerResult ProcessGetRequest (OCEntityHandlerRequest *ehRequest,
186 OCRepPayload **payload)
188 OCEntityHandlerResult ehResult;
189 bool queryPassed = checkIfQueryForPowerPassed(ehRequest->query);
191 // Empty payload if the query has no match.
194 OCRepPayload *getResp = constructResponse(ehRequest);
197 OC_LOG(ERROR, TAG, "constructResponse failed");
212 OCEntityHandlerResult ProcessPutRequest (OCEntityHandlerRequest *ehRequest,
213 OCRepPayload** payload)
215 OCEntityHandlerResult ehResult;
216 OCRepPayload *putResp = constructResponse(ehRequest);
220 OC_LOG(ERROR, TAG, "Failed to construct Json response");
230 OCEntityHandlerResult ProcessPostRequest (OCEntityHandlerRequest *ehRequest,
231 OCEntityHandlerResponse *response, OCRepPayload** payload)
233 OCEntityHandlerResult ehResult = OC_EH_OK;
234 OCRepPayload *respPLPost_light = nullptr;
237 * The entity handler determines how to process a POST request.
238 * Per the REST paradigm, POST can also be used to update representation of existing
239 * resource or create a new resource.
240 * In the sample below, if the POST is for /a/light then a new instance of the Light
241 * resource is created with default representation (if representation is included in
242 * POST payload it can be used as initial values) as long as the instance is
243 * lesser than max new instance count. Once max instance count is reached, POST on
244 * /a/light updated the representation of /a/light (just like PUT)
247 if (ehRequest->resource == Light.handle)
249 if (gCurrLightInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
251 // Create new Light instance
252 char newLightUri[URI_MAXSIZE];
253 snprintf(newLightUri, URI_MAXSIZE, "/a/light/%d", gCurrLightInstance);
255 respPLPost_light = OCRepPayloadCreate();
256 OCRepPayloadSetUri(respPLPost_light, gResourceUri);
257 OCRepPayloadSetPropString(respPLPost_light, "createduri", newLightUri);
259 if (0 == createLightResource (newLightUri, &gLightInstance[gCurrLightInstance]))
261 OC_LOG (INFO, TAG, "Created new Light instance\n");
262 gLightInstance[gCurrLightInstance].state = 0;
263 gLightInstance[gCurrLightInstance].power = 0;
264 gCurrLightInstance++;
265 strncpy ((char *)response->resourceUri, newLightUri, MAX_URI_LENGTH);
266 ehResult = OC_EH_RESOURCE_CREATED;
271 // Update repesentation of /a/light
274 respPLPost_light = constructResponse(ehRequest);
279 for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
281 if (ehRequest->resource == gLightInstance[i].handle)
283 gLightInstance[i].state = true;
284 gLightInstance[i].power = 22;
287 respPLPost_light = constructResponse(ehRequest);
292 respPLPost_light = constructResponse(ehRequest);
298 if ((respPLPost_light != NULL))
300 *payload = respPLPost_light;
304 OC_LOG(INFO, TAG, "Payload was NULL");
305 ehResult = OC_EH_ERROR;
311 OCEntityHandlerResult ProcessDeleteRequest (OCEntityHandlerRequest *ehRequest)
313 if(ehRequest == NULL)
315 OC_LOG(INFO, TAG, "The ehRequest is NULL");
318 OCEntityHandlerResult ehResult = OC_EH_OK;
320 OC_LOG_V(INFO, TAG, "\n\nExecuting %s for resource %p ", __func__, ehRequest->resource);
323 * In the sample below, the application will:
324 * 1a. pass the delete request to the c stack
325 * 1b. internally, the c stack figures out what needs to be done and does it accordingly
326 * (e.g. send observers notification, remove observers...)
327 * 1c. the c stack returns with the result whether the request is fullfilled.
328 * 2. optionally, app removes observers out of its array 'interestedObservers'
331 if ((ehRequest != NULL) && (ehRequest->resource == Light.handle))
333 //Step 1: Ask stack to do the work.
334 OCStackResult result = OCDeleteResource(ehRequest->resource);
336 if (result == OC_STACK_OK)
338 OC_LOG (INFO, TAG, "\n\nDelete Resource operation succeeded.");
341 //Step 2: clear observers who wanted to observe this resource at the app level.
342 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
344 if (interestedObservers[i].resourceHandle == ehRequest->resource)
346 interestedObservers[i].valid = false;
347 interestedObservers[i].observationId = 0;
348 interestedObservers[i].resourceHandle = NULL;
352 else if (result == OC_STACK_NO_RESOURCE)
354 OC_LOG(INFO, TAG, "\n\nThe resource doesn't exist or it might have been deleted.");
355 ehResult = OC_EH_RESOURCE_DELETED;
359 OC_LOG(INFO, TAG, "\n\nEncountered error from OCDeleteResource().");
360 ehResult = OC_EH_ERROR;
363 else if (ehRequest->resource != Light.handle)
365 //Let's this app not supporting DELETE on some resources so
366 //consider the DELETE request is received for a non-support resource.
367 OC_LOG_V(INFO, TAG, "\n\nThe request is received for a non-support resource.");
368 ehResult = OC_EH_FORBIDDEN;
374 OCEntityHandlerResult ProcessNonExistingResourceRequest(OCEntityHandlerRequest * /*ehRequest*/)
376 OC_LOG_V(INFO, TAG, "\n\nExecuting %s ", __func__);
378 return OC_EH_RESOURCE_NOT_FOUND;
381 void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
383 OC_LOG_V (INFO, TAG, "Received observation registration request with observation Id %d",
384 ehRequest->obsInfo.obsId);
386 if (!observeThreadStarted)
388 pthread_create (&threadId_observe, NULL, ChangeLightRepresentation, (void *)NULL);
389 observeThreadStarted = 1;
391 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
393 if (interestedObservers[i].valid == false)
395 interestedObservers[i].observationId = ehRequest->obsInfo.obsId;
396 interestedObservers[i].valid = true;
397 gLightUnderObservation = 1;
403 void ProcessObserveDeregister (OCEntityHandlerRequest *ehRequest)
405 bool clientStillObserving = false;
407 OC_LOG_V (INFO, TAG, "Received observation deregistration request for observation Id %d",
408 ehRequest->obsInfo.obsId);
409 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
411 if (interestedObservers[i].observationId == ehRequest->obsInfo.obsId)
413 interestedObservers[i].valid = false;
415 if (interestedObservers[i].valid == true)
417 // Even if there is one single client observing we continue notifying entity handler
418 clientStillObserving = true;
421 if (clientStillObserving == false)
422 gLightUnderObservation = 0;
425 OCEntityHandlerResult
426 OCDeviceEntityHandlerCb (OCEntityHandlerFlag flag,
427 OCEntityHandlerRequest *entityHandlerRequest,
429 void* /*callbackParam*/)
431 OC_LOG_V (INFO, TAG, "Inside device default entity handler - flags: 0x%x, uri: %s", flag, uri);
433 OCEntityHandlerResult ehResult = OC_EH_OK;
434 OCEntityHandlerResponse response;
437 if (!entityHandlerRequest)
439 OC_LOG (ERROR, TAG, "Invalid request pointer");
442 // Initialize certain response fields
443 response.numSendVendorSpecificHeaderOptions = 0;
444 memset(response.sendVendorSpecificHeaderOptions, 0,
445 sizeof response.sendVendorSpecificHeaderOptions);
446 memset(response.resourceUri, 0, sizeof response.resourceUri);
447 OCRepPayload* payload = nullptr;
450 if (flag & OC_REQUEST_FLAG)
452 OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
454 if (entityHandlerRequest->resource == NULL)
456 OC_LOG (INFO, TAG, "Received request from client to a non-existing resource");
457 ehResult = ProcessNonExistingResourceRequest(entityHandlerRequest);
459 else if (OC_REST_GET == entityHandlerRequest->method)
461 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
462 ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
464 else if (OC_REST_PUT == entityHandlerRequest->method)
466 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
467 ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
469 else if (OC_REST_DELETE == entityHandlerRequest->method)
471 OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
472 ehResult = ProcessDeleteRequest (entityHandlerRequest);
476 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
477 entityHandlerRequest->method);
478 ehResult = OC_EH_ERROR;
480 // If the result isn't an error or forbidden, send response
481 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
483 // Format the response. Note this requires some info about the request
484 response.requestHandle = entityHandlerRequest->requestHandle;
485 response.resourceHandle = entityHandlerRequest->resource;
486 response.ehResult = ehResult;
487 response.payload = reinterpret_cast<OCPayload*>(payload);
488 // Indicate that response is NOT in a persistent buffer
489 response.persistentBufferFlag = 0;
492 if (OCDoResponse(&response) != OC_STACK_OK)
494 OC_LOG(ERROR, TAG, "Error sending response");
495 ehResult = OC_EH_ERROR;
499 if (flag & OC_OBSERVE_FLAG)
501 OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
502 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
504 OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
506 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
508 OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
515 OCEntityHandlerResult
516 OCNOPEntityHandlerCb (OCEntityHandlerFlag /*flag*/,
517 OCEntityHandlerRequest * /*entityHandlerRequest*/,
518 void* /*callbackParam*/)
520 // This is callback is associated with the 2 presence notification
521 // resources. They are non-operational.
525 OCEntityHandlerResult
526 OCEntityHandlerCb (OCEntityHandlerFlag flag,
527 OCEntityHandlerRequest *entityHandlerRequest, void* /*callback*/)
529 OC_LOG_V (INFO, TAG, "Inside entity handler - flags: 0x%x", flag);
531 OCEntityHandlerResult ehResult = OC_EH_OK;
532 OCEntityHandlerResponse response = { 0, 0, OC_EH_ERROR, 0, 0, { },{ 0 }, false };
535 if (!entityHandlerRequest)
537 OC_LOG (ERROR, TAG, "Invalid request pointer");
541 // Initialize certain response fields
542 response.numSendVendorSpecificHeaderOptions = 0;
543 memset(response.sendVendorSpecificHeaderOptions,
544 0, sizeof response.sendVendorSpecificHeaderOptions);
545 memset(response.resourceUri, 0, sizeof response.resourceUri);
546 OCRepPayload* payload = nullptr;
548 if (flag & OC_REQUEST_FLAG)
550 OC_LOG (INFO, TAG, "Flag includes OC_REQUEST_FLAG");
552 if (OC_REST_GET == entityHandlerRequest->method)
554 OC_LOG (INFO, TAG, "Received OC_REST_GET from client");
555 ehResult = ProcessGetRequest (entityHandlerRequest, &payload);
557 else if (OC_REST_PUT == entityHandlerRequest->method)
559 OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
560 ehResult = ProcessPutRequest (entityHandlerRequest, &payload);
562 else if (OC_REST_POST == entityHandlerRequest->method)
564 OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
565 ehResult = ProcessPostRequest (entityHandlerRequest, &response, &payload);
567 else if (OC_REST_DELETE == entityHandlerRequest->method)
569 OC_LOG (INFO, TAG, "Received OC_REST_DELETE from client");
570 ehResult = ProcessDeleteRequest (entityHandlerRequest);
574 OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
575 entityHandlerRequest->method);
576 ehResult = OC_EH_ERROR;
578 // If the result isn't an error or forbidden, send response
579 if (!((ehResult == OC_EH_ERROR) || (ehResult == OC_EH_FORBIDDEN)))
581 // Format the response. Note this requires some info about the request
582 response.requestHandle = entityHandlerRequest->requestHandle;
583 response.resourceHandle = entityHandlerRequest->resource;
584 response.ehResult = ehResult;
585 response.payload = reinterpret_cast<OCPayload*>(payload);
586 // Indicate that response is NOT in a persistent buffer
587 response.persistentBufferFlag = 0;
589 // Handle vendor specific options
590 if(entityHandlerRequest->rcvdVendorSpecificHeaderOptions &&
591 entityHandlerRequest->numRcvdVendorSpecificHeaderOptions)
593 OC_LOG (INFO, TAG, "Received vendor specific options");
595 OCHeaderOption * rcvdOptions =
596 entityHandlerRequest->rcvdVendorSpecificHeaderOptions;
597 for( i = 0; i < entityHandlerRequest->numRcvdVendorSpecificHeaderOptions; i++)
599 if(((OCHeaderOption)rcvdOptions[i]).protocolID == OC_COAP_ID)
601 OC_LOG_V(INFO, TAG, "Received option with OC_COAP_ID and ID %u with",
602 ((OCHeaderOption)rcvdOptions[i]).optionID );
604 OC_LOG_BUFFER(INFO, TAG, ((OCHeaderOption)rcvdOptions[i]).optionData,
605 MAX_HEADER_OPTION_DATA_LENGTH);
608 OCHeaderOption * sendOptions = response.sendVendorSpecificHeaderOptions;
609 uint8_t option2[] = {21,22,23,24,25,26,27,28,29,30};
610 uint8_t option3[] = {31,32,33,34,35,36,37,38,39,40};
611 sendOptions[0].protocolID = OC_COAP_ID;
612 sendOptions[0].optionID = 2248;
613 memcpy(sendOptions[0].optionData, option2, sizeof(option2));
614 sendOptions[0].optionLength = 10;
615 sendOptions[1].protocolID = OC_COAP_ID;
616 sendOptions[1].optionID = 2600;
617 memcpy(sendOptions[1].optionData, option3, sizeof(option3));
618 sendOptions[1].optionLength = 10;
619 response.numSendVendorSpecificHeaderOptions = 2;
623 if (OCDoResponse(&response) != OC_STACK_OK)
625 OC_LOG(ERROR, TAG, "Error sending response");
626 ehResult = OC_EH_ERROR;
630 if (flag & OC_OBSERVE_FLAG)
632 OC_LOG(INFO, TAG, "Flag includes OC_OBSERVE_FLAG");
634 if (OC_OBSERVE_REGISTER == entityHandlerRequest->obsInfo.action)
636 OC_LOG (INFO, TAG, "Received OC_OBSERVE_REGISTER from client");
637 ProcessObserveRegister (entityHandlerRequest);
639 else if (OC_OBSERVE_DEREGISTER == entityHandlerRequest->obsInfo.action)
641 OC_LOG (INFO, TAG, "Received OC_OBSERVE_DEREGISTER from client");
642 ProcessObserveDeregister (entityHandlerRequest);
646 OCPayloadDestroy(response.payload);
650 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
651 void handleSigInt(int signum)
653 if (signum == SIGINT)
659 void *ChangeLightRepresentation (void *param)
662 OCStackResult result = OC_STACK_ERROR;
665 uint8_t numNotifies = (SAMPLE_MAX_NUM_OBSERVATIONS)/2;
666 OCObservationId obsNotify[numNotifies];
672 if (gLightUnderObservation)
674 OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", Light.power);
675 if (gObserveNotifyType == 1)
677 // Notify list of observers. Alternate observers on the list will be notified.
679 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; (i=i+2))
681 if (interestedObservers[i].valid == true)
683 obsNotify[j] = interestedObservers[i].observationId;
688 OCRepPayload* payload = getPayload(gResourceUri, Light.power, Light.state);
689 result = OCNotifyListOfObservers (Light.handle, obsNotify, j,
691 OCRepPayloadDestroy(payload);
693 else if (gObserveNotifyType == 0)
695 // Notifying all observers
696 result = OCNotifyAllObservers (Light.handle, OC_NA_QOS);
697 if (OC_STACK_NO_OBSERVERS == result)
700 "=======> No more observers exist, stop sending observations");
701 gLightUnderObservation = 0;
706 OC_LOG (ERROR, TAG, "Incorrect notification type selected");
714 void *presenceNotificationGenerator(void *param)
716 uint8_t secondsBeforePresence = 10;
717 OC_LOG_V(INFO, TAG, "Will send out presence in %u seconds", secondsBeforePresence);
718 sleep(secondsBeforePresence);
720 OCDoHandle presenceNotificationHandles[numPresenceResources];
721 OCStackResult res = OC_STACK_OK;
723 std::array<std::string, numPresenceResources> presenceNotificationResources { {
724 std::string("core.fan"),
725 std::string("core.led") } };
726 std::array<std::string, numPresenceResources> presenceNotificationUris { {
727 std::string("/a/fan"),
728 std::string("/a/led") } };
730 for(int i=0; i<numPresenceResources; i++)
732 if(res == OC_STACK_OK)
735 res = OCCreateResource(&presenceNotificationHandles[i],
736 presenceNotificationResources.at(i).c_str(),
737 OC_RSRVD_INTERFACE_DEFAULT,
738 presenceNotificationUris.at(i).c_str(),
739 OCNOPEntityHandlerCb,
741 OC_DISCOVERABLE|OC_OBSERVABLE);
743 if(res != OC_STACK_OK)
745 OC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to create resource "
746 "%s with result %s.", presenceNotificationResources.at(i).c_str(),
750 OC_LOG_V(INFO, TAG, PCF("Created %s for presence notification"),
751 presenceNotificationUris[i].c_str());
754 for(int i=0; i<numPresenceResources; i++)
756 if(res == OC_STACK_OK)
758 res = OCDeleteResource(presenceNotificationHandles[i]);
760 if(res != OC_STACK_OK)
762 OC_LOG_V(ERROR, TAG, "\"Presence Notification Generator\" failed to delete "\
763 "resource %s.", presenceNotificationResources.at(i).c_str());
766 OC_LOG_V(INFO, TAG, PCF("Deleted %s for presence notification"),
767 presenceNotificationUris[i].c_str());
770 OC_LOG(INFO, TAG, "================ stopping presence");
777 int createLightResource (char *uri, LightResource *lightResource)
781 OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
785 lightResource->state = false;
786 lightResource->power= 0;
787 OCStackResult res = OCCreateResource(&(lightResource->handle),
793 OC_DISCOVERABLE|OC_OBSERVABLE);
794 OC_LOG_V(INFO, TAG, "Created Light resource with result: %s", getResult(res));
799 void DeletePlatformInfo()
801 free (platformInfo.platformID);
802 free (platformInfo.manufacturerName);
803 free (platformInfo.manufacturerUrl);
804 free (platformInfo.modelNumber);
805 free (platformInfo.dateOfManufacture);
806 free (platformInfo.platformVersion);
807 free (platformInfo.operatingSystemVersion);
808 free (platformInfo.hardwareVersion);
809 free (platformInfo.firmwareVersion);
810 free (platformInfo.supportUrl);
811 free (platformInfo.systemTime);
814 void DeleteDeviceInfo()
816 free (deviceInfo.deviceName);
819 bool DuplicateString(char** targetString, const char* sourceString)
827 *targetString = (char *) malloc(strlen(sourceString) + 1);
831 strncpy(*targetString, sourceString, (strlen(sourceString) + 1));
838 OCStackResult SetPlatformInfo(const char* platformID, const char *manufacturerName,
839 const char *manufacturerUrl, const char *modelNumber, const char *dateOfManufacture,
840 const char *platformVersion, const char* operatingSystemVersion, const char* hardwareVersion,
841 const char *firmwareVersion, const char* supportUrl, const char* systemTime)
846 if(manufacturerName != NULL && (strlen(manufacturerName) > MAX_MANUFACTURER_NAME_LENGTH))
848 return OC_STACK_INVALID_PARAM;
851 if(manufacturerUrl != NULL && (strlen(manufacturerUrl) > MAX_MANUFACTURER_URL_LENGTH))
853 return OC_STACK_INVALID_PARAM;
856 if(!DuplicateString(&platformInfo.platformID, platformID))
861 if(!DuplicateString(&platformInfo.manufacturerName, manufacturerName))
866 if(!DuplicateString(&platformInfo.manufacturerUrl, manufacturerUrl))
871 if(!DuplicateString(&platformInfo.modelNumber, modelNumber))
876 if(!DuplicateString(&platformInfo.dateOfManufacture, dateOfManufacture))
881 if(!DuplicateString(&platformInfo.platformVersion, platformVersion))
886 if(!DuplicateString(&platformInfo.operatingSystemVersion, operatingSystemVersion))
891 if(!DuplicateString(&platformInfo.hardwareVersion, hardwareVersion))
896 if(!DuplicateString(&platformInfo.firmwareVersion, firmwareVersion))
901 if(!DuplicateString(&platformInfo.supportUrl, supportUrl))
906 if(!DuplicateString(&platformInfo.systemTime, systemTime))
916 DeletePlatformInfo();
917 return OC_STACK_ERROR;
920 OCStackResult SetDeviceInfo(const char* deviceName)
922 if(!DuplicateString(&deviceInfo.deviceName, deviceName))
924 return OC_STACK_ERROR;
929 static void PrintUsage()
931 OC_LOG(INFO, TAG, "Usage : ocserver -o <0|1>");
932 OC_LOG(INFO, TAG, "-o 0 : Notify all observers");
933 OC_LOG(INFO, TAG, "-o 1 : Notify list of observers");
937 static void jidbound(char *jid)
939 OC_LOG_V(INFO, TAG, "\n\n Bound JID: %s\n\n", jid);
943 int main(int argc, char* argv[])
947 char host[] = "localhost";
948 char user[] = "test1";
949 char pass[] = "intel123";
951 OCRAInfo_t rainfo = {};
953 rainfo.hostname = host;
955 rainfo.xmpp_domain = host;
956 rainfo.username = user;
957 rainfo.password = pass;
958 rainfo.resource = empstr;
959 rainfo.user_jid = empstr;
960 rainfo.jidbound = jidbound;
964 while ((opt = getopt(argc, argv, "o:s:p:d:u:w:r:j:")) != -1)
969 gObserveNotifyType = atoi(optarg);
973 rainfo.hostname = optarg;
976 rainfo.port = atoi(optarg);
979 rainfo.xmpp_domain = optarg;
982 rainfo.username = optarg;
985 rainfo.password = optarg;
988 rainfo.user_jid = optarg;
991 rainfo.resource = optarg;
1000 if ((gObserveNotifyType != 0) && (gObserveNotifyType != 1))
1007 OCSetRAInfo(&rainfo);
1010 OC_LOG(DEBUG, TAG, "OCServer is starting...");
1012 if (OCInit(NULL, 0, OC_SERVER) != OC_STACK_OK)
1014 OC_LOG(ERROR, TAG, "OCStack init error");
1017 #ifdef WITH_PRESENCE
1018 if (OCStartPresence(0) != OC_STACK_OK)
1020 OC_LOG(ERROR, TAG, "OCStack presence/discovery error");
1025 OCSetDefaultDeviceEntityHandler(OCDeviceEntityHandlerCb, NULL);
1027 OCStackResult registrationResult =
1028 SetPlatformInfo(platformID, manufacturerName, manufacturerUrl, modelNumber,
1029 dateOfManufacture, platformVersion, operatingSystemVersion, hardwareVersion,
1030 firmwareVersion, supportUrl, systemTime);
1032 if (registrationResult != OC_STACK_OK)
1034 OC_LOG(INFO, TAG, "Platform info setting failed locally!");
1035 exit (EXIT_FAILURE);
1038 registrationResult = OCSetPlatformInfo(platformInfo);
1040 if (registrationResult != OC_STACK_OK)
1042 OC_LOG(INFO, TAG, "Platform Registration failed!");
1043 exit (EXIT_FAILURE);
1046 registrationResult = SetDeviceInfo(deviceName);
1048 if (registrationResult != OC_STACK_OK)
1050 OC_LOG(INFO, TAG, "Device info setting failed locally!");
1051 exit (EXIT_FAILURE);
1054 registrationResult = OCSetDeviceInfo(deviceInfo);
1056 if (registrationResult != OC_STACK_OK)
1058 OC_LOG(INFO, TAG, "Device Registration failed!");
1059 exit (EXIT_FAILURE);
1063 * Declare and create the example resource: Light
1065 createLightResource(gResourceUri, &Light);
1067 // Initialize observations data structure for the resource
1068 for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
1070 interestedObservers[i].valid = false;
1075 * Create a thread for generating changes that cause presence notifications
1076 * to be sent to clients
1079 #ifdef WITH_PRESENCE
1080 pthread_create(&threadId_presence, NULL, presenceNotificationGenerator, (void *)NULL);
1083 // Break from loop with Ctrl-C
1084 OC_LOG(INFO, TAG, "Entering ocserver main loop...");
1086 DeletePlatformInfo();
1089 signal(SIGINT, handleSigInt);
1093 if (OCProcess() != OC_STACK_OK)
1095 OC_LOG(ERROR, TAG, "OCStack process error");
1100 if (observeThreadStarted)
1102 pthread_cancel(threadId_observe);
1103 pthread_join(threadId_observe, NULL);
1106 pthread_cancel(threadId_presence);
1107 pthread_join(threadId_presence, NULL);
1109 OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
1111 if (OCStop() != OC_STACK_OK)
1113 OC_LOG(ERROR, TAG, "OCStack process error");