2. Supporting POST operation in CPP Stack.
3. Updates to C sample application
4. Rebase
5. Fixed build issue.
Change-Id: I00b70a5eb8f4c1c911416d703e3c739b2a80ff7b
coap_list_t *optList = NULL;
uint8_t mediaType = COAP_MEDIATYPE_APPLICATION_JSON;
uint32_t maxAge = 0x2ffff;
+ OCMethod ocMethod;
unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
unsigned char rcvdQuery[MAX_QUERY_LENGTH] = { 0 };
// fill OCCoAPToken structure
RetrieveOCCoAPToken(recvPdu, &rcvdToken);
+ switch (recvPdu->hdr->code)
+ {
+ case COAP_REQUEST_GET:
+ {
+ ocMethod = OC_REST_GET;
+ break;
+ }
+ case COAP_REQUEST_POST:
+ {
+ ocMethod = OC_REST_POST;
+ break;
+ }
+ case COAP_REQUEST_PUT:
+ {
+ ocMethod = OC_REST_PUT;
+ break;
+ }
+ default:
+ {
+ OC_LOG_V(ERROR, TAG, "Received CoAP method %d not supported",
+ recvPdu->hdr->code);
+ goto exit;
+ }
+ }
+
// fill OCEntityHandlerRequest structure
- result = FormOCEntityHandlerRequest(&entityHandlerRequest,
- (recvPdu->hdr->code == COAP_REQUEST_GET) ?
- OC_REST_GET : OC_REST_PUT, bufRes, bufReqPayload, rcvdQuery);
+ result = FormOCEntityHandlerRequest(&entityHandlerRequest, ocMethod,
+ bufRes, bufReqPayload, rcvdQuery);
VERIFY_SUCCESS(result, OC_STACK_OK);
// fill OCObserveReq
case OC_REST_PUT:
coapMethod = COAP_REQUEST_PUT;
break;
+ case OC_REST_POST:
+ coapMethod = COAP_REQUEST_POST;
+ break;
case OC_REST_OBSERVE_ALL:
case OC_REST_OBSERVE:
case OC_REST_CANCEL_OBSERVE:
TEST_DISCOVER_REQ = 1,
TEST_GET_REQ_NON,
TEST_PUT_REQ_NON,
+ TEST_POST_REQ_NON,
TEST_OBS_REQ_NON,
TEST_GET_UNAVAILABLE_RES_REQ_NON,
TEST_GET_REQ_CON,
+ TEST_POST_REQ_CON,
TEST_OBS_REQ_CON,
#ifdef WITH_PRESENCE
TEST_OBS_PRESENCE,
int InitObserveRequest(OCQualityOfService qos);
int InitPutRequest();
int InitGetRequest(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptions);
+int InitPostRequest(OCQualityOfService qos);
+int InitGetRequest(OCQualityOfService qos);
int InitDiscovery();
void parseClientResponse(OCClientResponse * clientResponse);
OC_LOG(INFO, TAG, "-t 1 : Discover Resources");
OC_LOG(INFO, TAG, "-t 2 : Discover Resources and Initiate Nonconfirmable Get Request");
OC_LOG(INFO, TAG, "-t 3 : Discover Resources and Initiate Nonconfirmable Put Requests");
- OC_LOG(INFO, TAG, "-t 4 : Discover Resources and Initiate Nonconfirmable Observe Requests");
- OC_LOG(INFO, TAG, "-t 5 : Discover Resources and Initiate Nonconfirmable Get Request for a resource which is unavailable");
- OC_LOG(INFO, TAG, "-t 6 : Discover Resources and Initiate Confirmable Get Request");
- OC_LOG(INFO, TAG, "-t 7 : Discover Resources and Initiate Confirmable Observe Requests");
+ OC_LOG(INFO, TAG, "-t 4 : Discover Resources and Initiate Nonconfirmable Post Requests");
+ OC_LOG(INFO, TAG, "-t 5 : Discover Resources and Initiate Nonconfirmable Observe Requests");
+ OC_LOG(INFO, TAG, "-t 6 : Discover Resources and Initiate Nonconfirmable Get Request for a resource which is unavailable");
+ OC_LOG(INFO, TAG, "-t 7 : Discover Resources and Initiate Confirmable Get Request");
+ OC_LOG(INFO, TAG, "-t 8 : Discover Resources and Initiate Confirmable Post Request");
+ OC_LOG(INFO, TAG, "-t 9 : Discover Resources and Initiate Confirmable Observe Requests");
#ifdef WITH_PRESENCE
- OC_LOG(INFO, TAG, "-t 8 : Discover Resources and Initiate Nonconfirmable presence");
+ OC_LOG(INFO, TAG, "-t 10 : Discover Resources and Initiate Nonconfirmable presence");
#endif
- OC_LOG(INFO, TAG, "-t 9 : Discover Resources and Initiate Nonconfirmable Observe Requests then cancel immediately");
- OC_LOG(INFO, TAG, "-t 10: Discover Resources and Initiate Nonconfirmable Get Request and add vendor specific header options");
+ OC_LOG(INFO, TAG, "-t 11 : Discover Resources and Initiate Nonconfirmable Observe Requests then cancel immediately");
+ OC_LOG(INFO, TAG, "-t 12: Discover Resources and Initiate Nonconfirmable Get Request and add vendor specific header options");
}
OCStackResult InvokeOCDoResource(std::ostringstream &query,
OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
if(ctx == (void*)CTX_VAL)
{
- OC_LOG_V(INFO, TAG, "Callback Context for PUT query recvd successfully");
+ OC_LOG_V(INFO, TAG, "Callback Context for PUT recvd successfully");
}
if(clientResponse)
return OC_STACK_DELETE_TRANSACTION;
}
+OCStackApplicationResult postReqCB(void *ctx, OCDoHandle handle, OCClientResponse *clientResponse)
+{
+ if(ctx == (void*)CTX_VAL)
+ {
+ OC_LOG_V(INFO, TAG, "Callback Context for POST recvd successfully");
+ }
+
+ if(clientResponse)
+ {
+ OC_LOG_V(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+ OC_LOG_V(INFO, TAG, "JSON = %s =============> Post Response", clientResponse->resJSONPayload);
+ }
+ return OC_STACK_DELETE_TRANSACTION;
+}
+
OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
if(ctx == (void*)CTX_VAL)
{
case TEST_PUT_REQ_NON:
InitPutRequest();
break;
+ case TEST_POST_REQ_NON:
+ InitPostRequest(OC_NON_CONFIRMABLE);
+ break;
case TEST_OBS_REQ_NON:
case TEST_OBS_REQ_NON_CANCEL_IMM:
InitObserveRequest(OC_NON_CONFIRMABLE);
case TEST_GET_REQ_CON:
InitGetRequest(OC_CONFIRMABLE, 0);
break;
+ case TEST_POST_REQ_CON:
+ InitPostRequest(OC_CONFIRMABLE);
+ break;
case TEST_OBS_REQ_CON:
InitObserveRequest(OC_CONFIRMABLE);
break;
return (InvokeOCDoResource(query, OC_REST_GET, OC_NON_CONFIRMABLE, getReqCB, NULL, 0));
}
-
int InitObserveRequest(OCQualityOfService qos)
{
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
return (InvokeOCDoResource(query, OC_REST_OBSERVE, (qos == OC_CONFIRMABLE)? OC_CONFIRMABLE:OC_NON_CONFIRMABLE, obsReqCB, NULL, 0));
}
-
int InitPutRequest()
{
OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
return (InvokeOCDoResource(query, OC_REST_PUT, OC_NON_CONFIRMABLE, putReqCB, NULL, 0));
}
+int InitPostRequest(OCQualityOfService qos)
+{
+ OCStackResult result;
+ OC_LOG_V(INFO, TAG, "\n\nExecuting %s", __func__);
+ std::ostringstream query;
+ query << "coap://" << coapServerIP << ":" << coapServerPort << coapServerResource;
+
+ // First POST operation (to create an LED instance)
+ result = InvokeOCDoResource(query, OC_REST_POST,
+ ((qos == OC_CONFIRMABLE) ? OC_CONFIRMABLE: OC_NON_CONFIRMABLE),
+ postReqCB, NULL, 0);
+ if (OC_STACK_OK != result)
+ {
+ // Error can happen if for example, network connectivity is down
+ OC_LOG_V(INFO, TAG, "First POST call did not succeed");
+ }
+
+ // Second POST operation (to create an LED instance)
+ result = InvokeOCDoResource(query, OC_REST_POST,
+ ((qos == OC_CONFIRMABLE) ? OC_CONFIRMABLE: OC_NON_CONFIRMABLE),
+ postReqCB, NULL, 0);
+ if (OC_STACK_OK != result)
+ {
+ OC_LOG_V(INFO, TAG, "Second POST call did not succeed");
+ }
+
+ // This POST operation will update the original resourced /a/led
+ return (InvokeOCDoResource(query, OC_REST_POST,
+ ((qos == OC_CONFIRMABLE) ? OC_CONFIRMABLE: OC_NON_CONFIRMABLE),
+ postReqCB, NULL, 0));
+}
int InitGetRequest(OCQualityOfService qos, uint8_t withVendorSpecificHeaderOptions)
{
int gQuitFlag = 0;
int gLEDUnderObservation = 0;
-void createLEDResource();
+
typedef struct LEDRESOURCE{
OCResourceHandle handle;
bool state;
} LEDResource;
static LEDResource LED;
+// This variable determines instance number of the LED resource
+// Used by POST method to create a new instance of LED resource
+static int gCurrLedInstance = 0;
+#define SAMPLE_MAX_NUM_POST_INSTANCE 2
+static LEDResource gLedInstance[SAMPLE_MAX_NUM_POST_INSTANCE];
+int createLEDResource (char *uri, LEDResource *ledResource);
typedef struct {
OCObservationId observationId;
bool valid;
} Observers;
-
#define SAMPLE_MAX_NUM_OBSERVATIONS 8
Observers interestedObservers[SAMPLE_MAX_NUM_OBSERVATIONS];
static int stopPresenceCount = 10;
#endif
-// TODO: hard coded for now, change after Sprint4
-const char responsePayloadGet[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"on\",\"power\":10}}";
+// TODO: Hardcoded JSON strings. Request/response JSON payloads have to be parsed/generated.
+const char respPLGet_led[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"on\",\"power\":10}}";
+const char respPLGet_ledInst0[] = "{\"href\":\"/a/led/0\",\"rep\":{\"state\":\"on\",\"power\":20}}";
+const char respPLGet_ledInst1[] = "{\"href\":\"/a/led/1\",\"rep\":{\"state\":\"on\",\"power\":30}}";
const char responsePayloadPut[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"off\",\"power\":0}}";
static uint16_t OC_WELL_KNOWN_PORT = 5683;
void ProcessGetRequest (OCEntityHandlerRequest *ehRequest)
{
- if (ehRequest->resJSONPayloadLen > strlen ((char *)responsePayloadGet))
+ const char *getResp;
+
+ if (ehRequest->resource == LED.handle)
+ {
+ getResp = respPLGet_led;
+ }
+ else if (ehRequest->resource == gLedInstance[0].handle)
+ {
+ getResp = respPLGet_ledInst0;
+ }
+ else if (ehRequest->resource == gLedInstance[1].handle)
{
- strncpy((char *)ehRequest->resJSONPayload, responsePayloadGet,
- strlen((char *)responsePayloadGet));
+ getResp = respPLGet_ledInst1;
+ }
+
+ if (ehRequest->resJSONPayloadLen > strlen ((char *)getResp))
+ {
+ strncpy((char *)ehRequest->resJSONPayload, getResp,
+ strlen((char *)getResp));
}
else
{
}
}
+void ProcessPostRequest (OCEntityHandlerRequest *ehRequest)
+{
+ char respPLPost_newLed[100] = "{\"href\":\"/a/led\",\"rep\":{\"createduri\":\"/a/led/";
+ const char postPLSuffix[] = "\"}}";
+ char *respPLPost_led;
+
+ /*
+ * The entity handler determines how to process a POST request.
+ * Per the REST paradigm, POST can also be used to update representation of existing
+ * resource or create a new resource.
+ * In the sample below, if the POST is for /a/led then a new instance of the LED
+ * resource is created with default representation (if representation is included in
+ * POST payload it can be used as initial values) as long as the instance is
+ * lesser than max new instance count. Once max instance count is reached, POST on
+ * /a/led updated the representation of /a/led (just like PUT).
+ */
+
+ if (ehRequest->resource == LED.handle)
+ {
+ if (gCurrLedInstance < SAMPLE_MAX_NUM_POST_INSTANCE)
+ {
+ // Create new LED instance
+ char newLedUri[15] = "/a/led/";
+ sprintf (newLedUri + strlen(newLedUri), "%d", gCurrLedInstance);
+ printf ("\n New resource URI: %s\n", newLedUri);
+ if (0 == createLEDResource (newLedUri, &gLedInstance[gCurrLedInstance]))
+ {
+ OC_LOG_V (INFO, TAG, "Created new LED instance\n");
+ gLedInstance[gCurrLedInstance].state = 0;
+ gLedInstance[gCurrLedInstance].power = 0;
+ sprintf (respPLPost_newLed + strlen(respPLPost_newLed), "%d", gCurrLedInstance);
+ memcpy (respPLPost_newLed + strlen(respPLPost_newLed), postPLSuffix,
+ strlen(postPLSuffix) + 1);
+ gCurrLedInstance++;
+ respPLPost_led = respPLPost_newLed;
+ }
+ }
+ else
+ {
+ // Update repesentation of /a/led
+ LED.state = true;
+ LED.power = 11;
+ respPLPost_led = (char *)responsePayloadPut;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < SAMPLE_MAX_NUM_POST_INSTANCE; i++)
+ {
+ if (ehRequest->resource == gLedInstance[i].handle)
+ {
+ gLedInstance[i].state = true;
+ gLedInstance[i].power = 22;
+ if (i == 0)
+ {
+ respPLPost_led = (char *)respPLGet_ledInst0;
+ }
+ else if (i == 1)
+ {
+ respPLPost_led = (char *)respPLGet_ledInst1;
+ }
+ }
+ }
+ }
+
+ if (ehRequest->resJSONPayloadLen > strlen ((char *)respPLPost_led))
+ {
+ strncpy((char *)ehRequest->resJSONPayload, respPLPost_led,
+ strlen((char *)respPLPost_led));
+ }
+ else
+ {
+ OC_LOG_V (INFO, TAG, "Response buffer: %d bytes is too small",
+ ehRequest->resJSONPayloadLen);
+ }
+}
+
void ProcessObserveRegister (OCEntityHandlerRequest *ehRequest)
{
OC_LOG_V (INFO, TAG, "Received observation registration request with observation Id %d",
OC_LOG (INFO, TAG, "Received OC_REST_PUT from client");
ProcessPutRequest (entityHandlerRequest);
}
+ else if (OC_REST_POST == entityHandlerRequest->method)
+ {
+ OC_LOG (INFO, TAG, "Received OC_REST_POST from client");
+ ProcessPostRequest (entityHandlerRequest);
+ }
else
{
OC_LOG_V (INFO, TAG, "Received unsupported method %d from client",
}
}
result = OCNotifyListOfObservers (LED.handle, obsNotify, j,
- (unsigned char *)responsePayloadGet);
+ (unsigned char *)respPLGet_led);
}
else if (gObserveNotifyType == 0)
{
/*
* Declare and create the example resource: LED
*/
- createLEDResource();
+ createLEDResource("/a/led", &LED);
// Initialize observations data structure for the resource
for (uint8_t i = 0; i < SAMPLE_MAX_NUM_OBSERVATIONS; i++)
return 0;
}
-void createLEDResource() {
- LED.state = false;
- OCStackResult res = OCCreateResource(&LED.handle,
+
+int createLEDResource (char *uri, LEDResource *ledResource)
+{
+ if (!uri)
+ {
+ OC_LOG(ERROR, TAG, "Resource URI cannot be NULL");
+ return -1;
+ }
+
+ ledResource->state = false;
+ ledResource->power= 0;
+ OCStackResult res = OCCreateResource(&(ledResource->handle),
"core.led",
"core.rw",
- "/a/led",
+ uri,
OCEntityHandlerCb,
OC_DISCOVERABLE|OC_OBSERVABLE);
OC_LOG_V(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+
+ return 0;
}
//This function will be called back by occoap layer when a request is received
OCStackResult HandleStackRequests(OCRequest * request)
{
- OC_LOG(INFO, TAG, PCF("Entering OCStackHandleReceiveRequest (OCStack Layer)"));
+ OC_LOG(INFO, TAG, PCF("Entering HandleStackRequests (OCStack Layer)"));
OCStackResult result = OC_STACK_ERROR;
ResourceHandling resHandling;
{
case OC_REST_GET:
case OC_REST_PUT:
- break;
+ case OC_REST_POST:
case OC_REST_OBSERVE:
case OC_REST_OBSERVE_ALL:
case OC_REST_CANCEL_OBSERVE:
}
}
-// callback handler on PUT request
-void onPut(const OCRepresentation& rep, const int eCode)
+void onPost2(const OCRepresentation& rep, const int eCode)
{
if(eCode == SUCCESS_RESPONSE)
{
- std::cout << "PUT request was successful" << std::endl;
+ std::cout << "POST request was successful" << std::endl;
rep.getValue("state", mylight.m_state);
rep.getValue("power", mylight.m_power);
}
else
{
+ std::cout << "onPost Response error: " << eCode << std::endl;
+ std::exit(-1);
+ }
+}
+
+void onPost(const OCRepresentation& rep, const int eCode)
+{
+ if(eCode == SUCCESS_RESPONSE)
+ {
+ std::cout << "POST request was successful" << std::endl;
+
+ rep.getValue("state", mylight.m_state);
+ rep.getValue("power", mylight.m_power);
+ rep.getValue("name", mylight.m_name);
+
+ std::cout << "\tstate: " << mylight.m_state << std::endl;
+ std::cout << "\tpower: " << mylight.m_power << std::endl;
+ std::cout << "\tname: " << mylight.m_name << std::endl;
+
+ OCRepresentation rep2;
+
+ std::cout << "Posting light representation..."<<std::endl;
+
+ mylight.m_state = true;
+ mylight.m_power = 55;
+
+ rep2.setValue("state", mylight.m_state);
+ rep2.setValue("power", mylight.m_power);
+
+ curResource->post(rep2, QueryParamsMap(), &onPost2);
+ }
+ else
+ {
+ std::cout << "onPost Response error: " << eCode << std::endl;
+ std::exit(-1);
+ }
+}
+
+// Local function to put a different state for this resource
+void postLightRepresentation(std::shared_ptr<OCResource> resource)
+{
+ if(resource)
+ {
+ OCRepresentation rep;
+
+ std::cout << "Posting light representation..."<<std::endl;
+
+ mylight.m_state = false;
+ mylight.m_power = 105;
+
+ rep.setValue("state", mylight.m_state);
+ rep.setValue("power", mylight.m_power);
+
+ // Invoke resource's post API with rep, query map and the callback parameter
+ resource->post(rep, QueryParamsMap(), &onPost);
+ }
+}
+
+// callback handler on PUT request
+void onPut(const OCRepresentation& rep, const int eCode)
+{
+ if(eCode == SUCCESS_RESPONSE)
+ {
+ std::cout << "PUT request was successful" << std::endl;
+
+ rep.getValue("state", mylight.m_state);
+ rep.getValue("power", mylight.m_power);
+ rep.getValue("name", mylight.m_name);
+
+ std::cout << "\tstate: " << mylight.m_state << std::endl;
+ std::cout << "\tpower: " << mylight.m_power << std::endl;
+ std::cout << "\tname: " << mylight.m_name << std::endl;
+
+ postLightRepresentation(curResource);
+ }
+ else
+ {
std::cout << "onPut Response error: " << eCode << std::endl;
std::exit(-1);
}
rep.setValue("state", mylight.m_state);
rep.setValue("power", mylight.m_power);
- // Create QueryParameters Map and add query params (if any)
- QueryParamsMap queryParamsMap;
-
- // Invoke resource's pit API with rep, query map and the callback parameter
- resource->put(rep, queryParamsMap, &onPut);
+ // Invoke resource's put API with rep, query map and the callback parameter
+ resource->put(rep, QueryParamsMap(), &onPut);
}
}
using namespace OC;
using namespace std;
+namespace PH = std::placeholders;
int gObservation = 0;
+void * ChangeLightRepresentation (void *param);
// Specifies where to notify all observers or list of observers
// 0 - notifies all observers
int isListOfObservers = 0;
// Forward declaring the entityHandler
-void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
/// This class represents a single resource named 'lightResource'. This resource has
/// two simple properties named 'state' and 'power'
class LightResource
{
+
public:
/// Access this property from a TB client
std::string m_name;
// OCResourceProperty is defined ocstack.h
uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
+ EntityHandler cb = std::bind(&LightResource::entityHandler, this,PH::_1, PH::_2);
+
// This will internally create and register the resource.
OCStackResult result = platform.registerResource(
m_resourceHandle, resourceURI, resourceTypeName,
- resourceInterface, &entityHandler, resourceProperty);
+ resourceInterface, cb, resourceProperty);
if (OC_STACK_OK != result)
{
}
+ // Post representation.
+ // Post can create new resource or simply act like put.
+ // Gets values from the representation and
+ // updates the internal state
+ OCRepresentation post(OCRepresentation& rep)
+ {
+ put(rep);
+ return m_lightRep;
+ }
+
+
// gets the updated representation.
// Updates the representation with latest internal state before
// sending out.
cout << "Binding TypeName to Resource was unsuccessful\n";
}
}
-};
-
-// Create the instance of the resource class (in this case instance of class 'LightResource').
-LightResource myLight;
-
-// ChangeLightRepresentaion is an observation function,
-// which notifies any changes to the resource to stack
-// via notifyObservers
-void * ChangeLightRepresentation (void *param)
-{
- // This function continuously monitors for the changes
- while (1)
- {
- sleep (5);
-
- if (gObservation)
- {
- // If under observation if there are any changes to the light resource
- // we call notifyObservors
- //
- // For demostration we are changing the power value and notifying.
- myLight.m_power += 10;
-
- cout << "\nPower updated to : " << myLight.m_power << endl;
- cout << "Notifying observers with resource handle: " << myLight.getHandle() << endl;
-
- OCStackResult result = OC_STACK_OK;
-
- if(isListOfObservers)
- {
- std::shared_ptr<OCResourceResponse> resourceResponse(new OCResourceResponse());
-
- resourceResponse->setErrorCode(200);
- resourceResponse->setResourceRepresentation(myLight.get(), DEFAULT_INTERFACE);
-
- result = OCPlatform::notifyListOfObservers( myLight.getHandle(),
- myLight.m_interestedObservers,
- resourceResponse);
- }
- else
- {
- result = OCPlatform::notifyAllObservers(myLight.getHandle());
- }
-
- if(OC_STACK_NO_OBSERVERS == result)
- {
- cout << "No More observers, stopping notifications" << endl;
- gObservation = 0;
- }
- }
- }
-
- return NULL;
-}
+private:
// This is just a sample implementation of entity handler.
// Entity handler can be implemented in several ways by the manufacturer
void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
// TODO Error Code
response->setErrorCode(200);
- response->setResourceRepresentation(myLight.get());
+ response->setResourceRepresentation(get());
}
}
else if(requestType == "PUT")
// Do related operations related to PUT request
// Update the lightResource
- myLight.put(rep);
+ put(rep);
if(response)
{
// TODO Error Code
response->setErrorCode(200);
- response->setResourceRepresentation(myLight.get());
+ response->setResourceRepresentation(get());
}
}
else if(requestType == "POST")
{
+ cout << "\t\t\trequestType : POST\n";
+
+ OCRepresentation rep = request->getResourceRepresentation();
+
+ // Do related operations related to POST request
+
+ // Update the lightResource
+ post(rep);
+
+ if(response)
+ {
+ // TODO Error Code
+ response->setErrorCode(200);
+
+ response->setResourceRepresentation(get());
+ }
+
// POST request operations
}
else if(requestType == "DELETE")
// DELETE request operations
}
}
+
if(requestFlag & RequestHandlerFlag::ObserverFlag)
{
ObservationInfo observationInfo = request->getObservationInfo();
if(ObserveAction::ObserveRegister == observationInfo.action)
{
- myLight.m_interestedObservers.push_back(observationInfo.obsId);
+ m_interestedObservers.push_back(observationInfo.obsId);
}
else if(ObserveAction::ObserveUnregister == observationInfo.action)
{
- myLight.m_interestedObservers.erase(std::remove(
- myLight.m_interestedObservers.begin(),
- myLight.m_interestedObservers.end(),
+ m_interestedObservers.erase(std::remove(
+ m_interestedObservers.begin(),
+ m_interestedObservers.end(),
observationInfo.obsId),
- myLight.m_interestedObservers.end());
+ m_interestedObservers.end());
}
pthread_t threadId;
cout << "\t\trequestFlag : Observer\n";
gObservation = 1;
-
static int startedThread = 0;
// Observation happens on a different thread in ChangeLightRepresentation function.
// If we have not created the thread already, we will create one here.
if(!startedThread)
{
- pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
+ pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)this);
startedThread = 1;
}
}
}
}
+};
+
+// ChangeLightRepresentaion is an observation function,
+// which notifies any changes to the resource to stack
+// via notifyObservers
+void * ChangeLightRepresentation (void *param)
+{
+ LightResource* lightPtr = (LightResource*) param;
+
+ // This function continuously monitors for the changes
+ while (1)
+ {
+ sleep (5);
+
+ if (gObservation)
+ {
+ // If under observation if there are any changes to the light resource
+ // we call notifyObservors
+ //
+ // For demostration we are changing the power value and notifying.
+ lightPtr->m_power += 10;
+
+ cout << "\nPower updated to : " << lightPtr->m_power << endl;
+ cout << "Notifying observers with resource handle: " << lightPtr->getHandle() << endl;
+
+ OCStackResult result = OC_STACK_OK;
+
+ if(isListOfObservers)
+ {
+ std::shared_ptr<OCResourceResponse> resourceResponse(new OCResourceResponse());
+
+ resourceResponse->setErrorCode(200);
+ resourceResponse->setResourceRepresentation(lightPtr->get(), DEFAULT_INTERFACE);
+
+ result = OCPlatform::notifyListOfObservers( lightPtr->getHandle(),
+ lightPtr->m_interestedObservers,
+ resourceResponse);
+ }
+ else
+ {
+ result = OCPlatform::notifyAllObservers(lightPtr->getHandle());
+ }
+
+ if(OC_STACK_NO_OBSERVERS == result)
+ {
+ cout << "No More observers, stopping notifications" << endl;
+ gObservation = 0;
+ }
+ }
+ }
+
+ return NULL;
+}
+
void PrintUsage()
{
std::cout << std::endl;
{
OCPlatform platform(cfg);
+ // Create the instance of the resource class (in this case instance of class 'LightResource').
+ LightResource myLight;
+
// Invoke createResource function of class light.
myLight.createResource(platform);
{
protected:
OCPlatform& m_owner;
-
+
public:
typedef std::shared_ptr<IClientWrapper> Ptr;
: m_owner(owner)
{}
- virtual OCStackResult ListenForResource(const std::string& serviceUrl, const std::string& resourceType,
- FindCallback& callback) = 0;
-
- virtual OCStackResult GetResourceAttributes(const std::string& host, const std::string& uri, const QueryParamsMap& queryParams,
- GetCallback& callback)=0;
+ virtual OCStackResult ListenForResource(const std::string& serviceUrl,
+ const std::string& resourceType, FindCallback& callback) = 0;
+
+ virtual OCStackResult GetResourceRepresentation(const std::string& host,
+ const std::string& uri, const QueryParamsMap& queryParams,
+ GetCallback& callback)=0;
+
+ virtual OCStackResult PutResourceRepresentation(const std::string& host,
+ const std::string& uri, const OCRepresentation& rep,
+ const QueryParamsMap& queryParams,
+ PutCallback& callback) = 0;
- virtual OCStackResult SetResourceAttributes(const std::string& host, const std::string& uri, const OCRepresentation& attributes,
- const QueryParamsMap& queryParams, PutCallback& callback) = 0;
+ virtual OCStackResult PostResourceRepresentation(const std::string& host,
+ const std::string& uri, const OCRepresentation& rep,
+ const QueryParamsMap& queryParams,
+ PutCallback& callback) = 0;
- virtual OCStackResult ObserveResource(ObserveType observeType, OCDoHandle* handle,
- const std::string& host, const std::string& uri, const QueryParamsMap& queryParams,
- ObserveCallback& callback)=0;
-
- virtual OCStackResult CancelObserveResource(OCDoHandle handle, const std::string& host, const std::string& uri)=0;
-
- virtual OCStackResult SubscribePresence(OCDoHandle* handle, const std::string& host,
- SubscribeCallback& presenceHandler)=0;
+ virtual OCStackResult ObserveResource(ObserveType observeType, OCDoHandle* handle,
+ const std::string& host, const std::string& uri,
+ const QueryParamsMap& queryParams,
+ ObserveCallback& callback)=0;
+
+ virtual OCStackResult CancelObserveResource(OCDoHandle handle, const std::string& host,
+ const std::string& uri)=0;
+
+ virtual OCStackResult SubscribePresence(OCDoHandle* handle, const std::string& host,
+ SubscribeCallback& presenceHandler)=0;
virtual OCStackResult UnsubscribePresence(OCDoHandle handle) =0;
virtual ~IClientWrapper(){}
-
- // Note: this should never be called by anyone but the handler for the listen command. It is public becuase that needs to be a non-instance callback
- virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper, const std::string& host, const boost::property_tree::ptree resourceNode)=0;
+
+ // Note: this should never be called by anyone but the handler for the listen command.
+ // It is public becuase that needs to be a non-instance callback
+ virtual std::shared_ptr<OCResource> parseOCResource(IClientWrapper::Ptr clientWrapper,
+ const std::string& host, const boost::property_tree::ptree resourceNode)=0;
private:
};
}
class InProcClientWrapper : public IClientWrapper
{
public:
- InProcClientWrapper(OC::OCPlatform& owner, std::weak_ptr<std::mutex> csdkLock, PlatformConfig cfg);
+ InProcClientWrapper(OC::OCPlatform& owner, std::weak_ptr<std::mutex> csdkLock,
+ PlatformConfig cfg);
virtual ~InProcClientWrapper();
virtual OCStackResult ListenForResource(const std::string& serviceUrl,
const std::string& resourceType, FindCallback& callback);
- virtual OCStackResult GetResourceAttributes(const std::string& host, const std::string& uri,
- const QueryParamsMap& queryParams, GetCallback& callback);
+ virtual OCStackResult GetResourceRepresentation(const std::string& host,
+ const std::string& uri, const QueryParamsMap& queryParams,
+ GetCallback& callback);
- virtual OCStackResult SetResourceAttributes(const std::string& host, const std::string& uri,
- const OCRepresentation& attributes, const QueryParamsMap& queryParams,
- PutCallback& callback);
+ virtual OCStackResult PutResourceRepresentation(const std::string& host,
+ const std::string& uri, const OCRepresentation& attributes,
+ const QueryParamsMap& queryParams, PutCallback& callback);
+
+ virtual OCStackResult PostResourceRepresentation(const std::string& host,
+ const std::string& uri, const OCRepresentation& attributes,
+ const QueryParamsMap& queryParams, PostCallback& callback);
virtual OCStackResult ObserveResource(ObserveType observeType, OCDoHandle* handle,
const std::string& host, const std::string& uri, const QueryParamsMap& queryParams,
typedef std::function<void(OCStackResult, const unsigned int)> SubscribeCallback;
typedef std::function<void(const OCRepresentation&, const int)> GetCallback;
typedef std::function<void(const OCRepresentation&, const int)> PutCallback;
+ typedef std::function<void(const OCRepresentation&, const int)> PostCallback;
typedef std::function<void(const OCRepresentation&, const int, const int)> ObserveCallback;
} // namespace OC
/// @file OCResource.h
-/// @brief This file contains the declaration of classes and its members related to
+/// @brief This file contains the declaration of classes and its members related to
/// Resource.
#ifndef __OCRESOURCE_H
namespace OC
{
/**
- * @brief OCResource represents an OC resource. A resource could be a light controller,
- * temperature sensor, smoke detector, etc. A resource comes with a well-defined
- * contract or interface onto which you can perform different operations, such as
- * turning on the light, getting the current temperature or subscribing for event
+ * @brief OCResource represents an OC resource. A resource could be a light controller,
+ * temperature sensor, smoke detector, etc. A resource comes with a well-defined
+ * contract or interface onto which you can perform different operations, such as
+ * turning on the light, getting the current temperature or subscribing for event
* notifications from the smoke detector. A resource can be composed of one or
- * more resources.
+ * more resources.
*/
class OCResource
{
* Virtual destructor
*/
virtual ~OCResource(void);
-
+
/**
- * Function to get the attributes of a resource.
+ * Function to get the attributes of a resource.
* @param queryParametersMap map which can have the query parameter name and value
* @param attributeHandler handles callback
- * The callback function will be invoked with a map of attribute name and values.
- * The callback function will also have the result from this Get operation
+ * The callback function will be invoked with a map of attribute name and values.
+ * The callback function will also have the result from this Get operation
* This will have error codes
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
* NOTE: OCStackResult is defined in ocstack.h.
*/
OCStackResult get(const QueryParamsMap& queryParametersMap, GetCallback attributeHandler);
-
+
/**
- * Function to get the attributes of a resource.
+ * Function to get the attributes of a resource.
*
* @param resourceType resourceType of the resource operate on
* @param resourceInterface interface type of the resource to operate on
* @param queryParametersMap map which can have the query parameter name and value
* @param attributeHandler handles callback
- * The callback function will be invoked with a map of attribute name and values.
- * The callback function will be invoked with a list of URIs if 'get' is invoked on a resource container
+ * The callback function will be invoked with a map of attribute name and values.
+ * The callback function will be invoked with a list of URIs if 'get' is invoked on a resource container
* (list will be empty if not a container)
* The callback function will also have the result from this Get operation. This will have error codes
* @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
* NOTE: OCStackResult is defined in ocstack.h.<br>
* <b>Example:</b><br>
- * Consider resource "a/home" (with link interface and resource type as home) contains links to "a/kitchen" and "a/room".
+ * Consider resource "a/home" (with link interface and resource type as home) contains links to "a/kitchen" and "a/room".
* Step 1: get("home", Link_Interface, &onGet)<br>
- * Callback onGet will receive a) Empty attribute map because there are no attributes for a/home b) list with
+ * Callback onGet will receive a) Empty attribute map because there are no attributes for a/home b) list with
* full URI of "a/kitchen" and "a/room" resources and their properties c) error code for GET operation<br>
* NOTE: A resource may contain single or multiple resource types. Also, a resource may contain single or multiple interfaces.<br>
* Currently, single GET request is allowed to do operate on single resource type or resource interface. In future, a single GET <br>
* can operate on multiple resource types and interfaces. <br>
* NOTE: A client can traverse a tree or graph by doing successive GETs on the returned resources at a node.<br>
*/
- OCStackResult get(const std::string& resourceType, const std::string& resourceInterface, const QueryParamsMap& queryParametersMap, GetCallback attributeHandler);
+ OCStackResult get(const std::string& resourceType, const std::string& resourceInterface, const QueryParamsMap& queryParametersMap, GetCallback attributeHandler);
/**
- * Function to set the attributes of a resource (via PUT)
- * @param attributeMap Map which can either have all the attribute names and values
+ * Function to set the representation of a resource (via PUT)
+ * @param representation which can either have all the attribute names and values
(which will represent entire state of the resource) or a
* set of attribute names and values which needs to be modified
* The callback function will be invoked with a map of attribute name and values.
* This will have error codes
* @param queryParametersMap map which can have the query parameter name and value
* @param attributeHandler attribute handler
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
* NOTE: OCStackResult is defined in ocstack.h.
*/
- OCStackResult put(const OCRepresentation& attributeMap, const QueryParamsMap& queryParametersMap,
- PutCallback attributeHandler);
+ OCStackResult put(const OCRepresentation& representation,
+ const QueryParamsMap& queryParametersMap, PutCallback attributeHandler);
/**
* Function to set the attributes of a resource (via PUT)
* @param resourceType resource type of the resource to operate on
* @param resourceInterface interface type of the resource to operate on
- * @param attributeMap attribute map
+ * @param representation representation of the resource
* @param queryParametersMap Map which can have the query parameter name and value
* @param attributeHandler attribute handler
* The callback function will be invoked with a map of attribute name and values.
* The callback function will also have the result from this Put operation
* This will have error codes.
- * The AttributeMap parameter maps which can either have all the attribute names and values
+ * The Representation parameter maps which can either have all the attribute names
+ * and values
* (which will represent entire state of the resource) or a
* set of attribute names and values which needs to be modified
* @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
* NOTE: OCStackResult is defined in ocstack.h. <br>
*/
OCStackResult put(const std::string& resourceType, const std::string& resourceInterface,
- const OCRepresentation& attributeMap, const QueryParamsMap& queryParametersMap,
+ const OCRepresentation& representation, const QueryParamsMap& queryParametersMap,
PutCallback attributeHandler);
/**
+ * Function to post on a resource
+ * @param representation which can either have all the attribute names and values
+ (which will represent entire state of the resource) or a
+ * set of attribute names and values which needs to be modified
+ * The callback function will be invoked with a map of attribute name and values.
+ * The callback function will also have the result from this Put operation
+ * This will have error codes
+ * @param queryParametersMap map which can have the query parameter name and value
+ * @param attributeHandler attribute handler
+ * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * NOTE: OCStackResult is defined in ocstack.h.
+ */
+ OCStackResult post(const OCRepresentation& representation,
+ const QueryParamsMap& queryParametersMap, PostCallback attributeHandler);
+
+ /**
+ * Function to post on a resource
+ * @param resourceType resource type of the resource to operate on
+ * @param resourceInterface interface type of the resource to operate on
+ * @param representation representation of the resource
+ * @param queryParametersMap Map which can have the query parameter name and value
+ * @param attributeHandler attribute handler
+ * The callback function will be invoked with a map of attribute name and values.
+ * The callback function will also have the result from this Put operation
+ * This will have error codes.
+ * The Representation parameter maps which can either have all the attribute names
+ * and values
+ * (which will represent entire state of the resource) or a
+ * set of attribute names and values which needs to be modified
+ * @return OCStackResult return value of this API. Returns OC_STACK_OK if success. <br>
+ * NOTE: OCStackResult is defined in ocstack.h. <br>
+ */
+ OCStackResult post(const std::string& resourceType, const std::string& resourceInterface,
+ const OCRepresentation& representation, const QueryParamsMap& queryParametersMap,
+ PostCallback attributeHandler);
+
+ /**
* Function to set observation on the resource
* @param observeType allows the client to specify how it wants to observe.
* @param queryParametersMap map which can have the query parameter name and value
* The callback function will be invoked with a map of attribute name and values.
* The callback function will also have the result from this observe operation
* This will have error codes
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
* NOTE: OCStackResult is defined in ocstack.h.
*/
- OCStackResult observe(ObserveType observeType, const QueryParamsMap& queryParametersMap,
+ OCStackResult observe(ObserveType observeType, const QueryParamsMap& queryParametersMap,
ObserveCallback observeHandler);
/**
* Function to cancel the observation on the resource
- * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
+ * @return OCStackResult return value of this API. Returns OC_STACK_OK if success.
* NOTE: OCStackResult is defined in ocstack.h.
*/
OCStackResult cancelObserve();
/**
* Function to get the list of resource types
- * @return vector of resource types
+ * @return vector of resource types
*/
std::vector<std::string> getResourceTypes() const
{
return m_resourceTypes;
}
-
+
/**
* Function to get the list of resource interfaces
* @return vector of resource interface
OCDoHandle m_observeHandle;
private:
- OCResource(std::weak_ptr<IClientWrapper> clientWrapper, const std::string& host, const std::string& uri,
- bool observable, const std::vector<std::string>& resourceTypes, const std::vector<std::string>& interfaces);
+ OCResource(std::weak_ptr<IClientWrapper> clientWrapper, const std::string& host, const std::string& uri,
+ bool observable, const std::vector<std::string>& resourceTypes, const std::vector<std::string>& interfaces);
};
} // namespace OC
class OutOfProcClientWrapper : public IClientWrapper
{
public:
- OutOfProcClientWrapper(OC::OCPlatform& owner, std::weak_ptr<std::mutex> csdkLock, PlatformConfig cfg)
+ OutOfProcClientWrapper(OC::OCPlatform& owner, std::weak_ptr<std::mutex> csdkLock,
+ PlatformConfig cfg)
: IClientWrapper(owner)
{}
virtual OCStackResult ListenForResource(const std::string& serviceUrl,
const std::string& resourceType, FindCallback& callback) {return OC_STACK_NOTIMPL;}
- virtual OCStackResult GetResourceAttributes(const std::string& host, const std::string& uri,
- const QueryParamsMap& queryParams, GetCallback& callback){return OC_STACK_NOTIMPL;}
+ virtual OCStackResult GetResourceRepresentation(const std::string& host,
+ const std::string& uri, const QueryParamsMap& queryParams, GetCallback& callback)
+ {return OC_STACK_NOTIMPL;}
- virtual OCStackResult SetResourceAttributes(const std::string& host, const std::string& uri,
- const OCRepresentation& attributes, const QueryParamsMap& queryParams,
- PutCallback& callback){return OC_STACK_NOTIMPL;}
+ virtual OCStackResult PutResourceRepresentation(const std::string& host,
+ const std::string& uri, const OCRepresentation& attributes,
+ const QueryParamsMap& queryParams, PutCallback& callback)
+ {return OC_STACK_NOTIMPL;}
+
+ virtual OCStackResult PostResourceRepresentation(const std::string& host,
+ const std::string& uri, const OCRepresentation& attributes,
+ const QueryParamsMap& queryParams, PostCallback& callback)
+ {return OC_STACK_NOTIMPL;}
virtual OCStackResult ObserveResource(ObserveType observeType, OCDoHandle* handle,
const std::string& host, const std::string& uri, const QueryParamsMap& queryParams,
exec.detach();
return OC_STACK_DELETE_TRANSACTION;
}
- OCStackResult InProcClientWrapper::GetResourceAttributes(const std::string& host,
+ OCStackResult InProcClientWrapper::GetResourceRepresentation(const std::string& host,
const std::string& uri, const QueryParamsMap& queryParams, GetCallback& callback)
{
OCStackResult result;
return payload.str();
}
- OCStackResult InProcClientWrapper::SetResourceAttributes(const std::string& host,
+ OCStackResult InProcClientWrapper::PostResourceRepresentation(const std::string& host,
+ const std::string& uri, const OCRepresentation& rep,
+ const QueryParamsMap& queryParams, PostCallback& callback)
+ {
+ OCStackResult result;
+ OCCallbackData cbdata = {0};
+
+ SetContext* ctx = new SetContext();
+ ctx->callback = callback;
+ cbdata.cb = &setResourceCallback;
+ cbdata.cd = [](void* c){delete static_cast<SetContext*>(c);};
+ cbdata.context = static_cast<void*>(ctx);
+
+ // TODO: in the future the cstack should be combining these two strings!
+ ostringstream os;
+ os << host << assembleSetResourceUri(uri, queryParams).c_str();
+ // TODO: end of above
+
+ auto cLock = m_csdkLock.lock();
+
+ if(cLock)
+ {
+ std::lock_guard<std::mutex> lock(*cLock);
+ OCDoHandle handle;
+ result = OCDoResource(&handle, OC_REST_POST,
+ os.str().c_str(), nullptr,
+ assembleSetResourcePayload(rep).c_str(),
+ static_cast<OCQualityOfService>(m_cfg.QoS),
+ &cbdata, NULL, 0);
+ }
+ else
+ {
+ result = OC_STACK_ERROR;
+ }
+
+ return result;
+ }
+
+
+ OCStackResult InProcClientWrapper::PutResourceRepresentation(const std::string& host,
const std::string& uri, const OCRepresentation& rep,
const QueryParamsMap& queryParams, PutCallback& callback)
{
pRequest->setQueryParams(qp);
}
}
+
if(OC_REST_GET == entityHandlerRequest->method)
{
// TODO Why strings : "GET"??
pRequest->setRequestType("GET");
}
-
- if(OC_REST_PUT == entityHandlerRequest->method)
+ else if(OC_REST_PUT == entityHandlerRequest->method)
{
pRequest->setRequestType("PUT");
pRequest->setPayload(std::string(reinterpret_cast<const char*>
(entityHandlerRequest->reqJSONPayload)));
}
+ else if(OC_REST_POST == entityHandlerRequest->method)
+ {
+ pRequest->setRequestType("POST");
+ pRequest->setPayload(std::string(reinterpret_cast<const char*>
+ (entityHandlerRequest->reqJSONPayload)));
+ }
}
}
if(cw)
{
- return cw->GetResourceAttributes(m_host, m_uri, queryParametersMap, attributeHandler);
+ return cw->GetResourceRepresentation(m_host, m_uri, queryParametersMap, attributeHandler);
}
else
{
if(cw)
{
- return cw->SetResourceAttributes(m_host, m_uri, rep, queryParametersMap,
+ return cw->PutResourceRepresentation(m_host, m_uri, rep, queryParametersMap,
attributeHandler);
}
else
}
}
+
OCStackResult OCResource::put(const std::string& resourceType,
const std::string& resourceInterface, const OCRepresentation& rep,
const QueryParamsMap& queryParametersMap,
}
}
+ OCStackResult OCResource::post(const OCRepresentation& rep,
+ const QueryParamsMap& queryParametersMap, PostCallback attributeHandler)
+ {
+ auto cw = m_clientWrapper.lock();
+
+ if(cw)
+ {
+ return cw->PostResourceRepresentation(m_host, m_uri, rep, queryParametersMap,
+ attributeHandler);
+ }
+ else
+ {
+ return OC_STACK_ERROR;
+ }
+ }
+
+ OCStackResult OCResource::post(const std::string& resourceType,
+ const std::string& resourceInterface, const OCRepresentation& rep,
+ const QueryParamsMap& queryParametersMap,
+ PostCallback attributeHandler)
+ {
+ auto cw = m_clientWrapper.lock();
+
+ if(cw)
+ {
+ QueryParamsMap mapCpy(queryParametersMap);
+
+ if(!resourceType.empty())
+ {
+ mapCpy["rt"]=resourceType;
+ }
+ if(!resourceInterface.empty())
+ {
+ mapCpy["if"]=resourceInterface;
+ }
+
+ return post(rep, mapCpy, attributeHandler);
+ }
+ else
+ {
+ return OC_STACK_ERROR;
+ }
+ }
+
+
OCStackResult OCResource::observe(ObserveType observeType,
const QueryParamsMap& queryParametersMap, ObserveCallback observeHandler)
{