From 76416b982ac764d0393ea862300d7e1308f550a8 Mon Sep 17 00:00:00 2001 From: Joseph Morrow Date: Sun, 2 Nov 2014 18:18:19 -0500 Subject: [PATCH] Adding example of a Simple Attribute use on a collection resource using C SDK. This involved forming proper JSON examples, as well as adding test cases to the application as the implementation of test cases were not fullfilled yet. Change-Id: I0b217a324334367bf3a923d7aadef5150e385821 Signed-off-by: Joseph Morrow --- .../linux/SimpleClientServer/occlientcoll.cpp | 106 ++++++++-- .../linux/SimpleClientServer/ocservercoll.cpp | 225 ++++++++++++++++----- 2 files changed, 260 insertions(+), 71 deletions(-) diff --git a/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp b/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp index 8ee05e6..2a93a6f 100644 --- a/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp +++ b/csdk/stack/samples/linux/SimpleClientServer/occlientcoll.cpp @@ -38,10 +38,41 @@ std::string getQueryStrForGetPut(unsigned const char * responsePayload); #define MAX_LENGTH_IPv4_ADDR 16 #endif -#define MAX_TEST_CASES 5 +typedef enum { + TEST_INVALID = 0, + TEST_GET_DEFAULT, + TEST_GET_BATCH, + TEST_GET_LINK_LIST, + TEST_PUT_DEFAULT, + TEST_PUT_BATCH, + TEST_PUT_LINK_LIST, + TEST_UNKNOWN_RESOURCE_GET_DEFAULT, + TEST_UNKNOWN_RESOURCE_GET_BATCH, + TEST_UNKNOWN_RESOURCE_GET_LINK_LIST, + MAX_TESTS +} CLIENT_TEST; + +unsigned static int TEST = TEST_INVALID; + +typedef struct +{ + unsigned char text[30]; + CLIENT_TEST test; +} testToTextMap; + +testToTextMap queryInterface[] = { + {"invalid", TEST_INVALID}, + {"?if=oc.mi.def", TEST_GET_DEFAULT}, + {"?if=oc.mi.b", TEST_GET_BATCH}, + {"?if=oc.mi.ll", TEST_GET_LINK_LIST}, + {"?if=oc.mi.def", TEST_UNKNOWN_RESOURCE_GET_DEFAULT}, + {"?if=oc.mi.b", TEST_UNKNOWN_RESOURCE_GET_BATCH}, + {"?if=oc.mi.ll", TEST_UNKNOWN_RESOURCE_GET_LINK_LIST}, + {"?if=oc.mi.def", TEST_PUT_DEFAULT}, + {"?if=oc.mi.b", TEST_PUT_BATCH}, + {"?if=oc.mi.ll", TEST_PUT_LINK_LIST}, +}; -static int UNICAST_DISCOVERY = 0; -static int TEST_CASE = 0; static std::string putPayload = "{\"state\":\"off\",\"power\":\"0\"}"; // The handle for the observe registration @@ -67,12 +98,25 @@ int InitDiscovery(); void PrintUsage() { - OC_LOG(INFO, TAG, "Usage : occlient "); - OC_LOG(INFO, TAG, "Test Case 1 : Discover Resources"); - OC_LOG(INFO, TAG, "Test Case 2 : Discover Resources and Initiate Get Request"); - OC_LOG(INFO, TAG, "Test Case 3 : Discover Resources and Initiate Get/Put Requests"); - OC_LOG(INFO, TAG, "Test Case 4 : Discover Resources and Initiate Observe Requests"); - OC_LOG(INFO, TAG, "Test Case 5 : Discover Resources and Initiate Get Request for a resource which is unavailable"); + OC_LOG(INFO, TAG, "Usage : occlient -t "); + OC_LOG(INFO, TAG, "Test Case 1 : Discover Resources && Initiate GET Request on an"\ + "available resource using default interface."); + OC_LOG(INFO, TAG, "Test Case 2 : Discover Resources && Initiate GET Request on an"\ + "available resource using batch interface."); + OC_LOG(INFO, TAG, "Test Case 3 : Discover Resources && Initiate GET Request on an"\ + "available resource using link list interface."); + OC_LOG(INFO, TAG, "Test Case 4 : Discover Resources && Initiate GET & PUT Request on an"\ + "available resource using default interface."); + OC_LOG(INFO, TAG, "Test Case 5 : Discover Resources && Initiate GET & PUT Request on an"\ + "available resource using batch interface."); + OC_LOG(INFO, TAG, "Test Case 6 : Discover Resources && Initiate GET & PUT Request on an"\ + "available resource using link list interface."); + OC_LOG(INFO, TAG, "Test Case 7 : Discover Resources && Initiate GET Request on an"\ + "unavailable resource using default interface."); + OC_LOG(INFO, TAG, "Test Case 8 : Discover Resources && Initiate GET Request on an"\ + "unavailable resource using batch interface."); + OC_LOG(INFO, TAG, "Test Case 9 : Discover Resources && Initiate GET Request on an"\ + "unavailable resource using link list interface."); } OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) { @@ -106,7 +150,10 @@ OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse } } } - InitPutRequest(clientResponse); + if(TEST == TEST_PUT_DEFAULT || TEST == TEST_PUT_BATCH || TEST == TEST_PUT_LINK_LIST) + { + InitPutRequest(clientResponse); + } return OC_STACK_KEEP_TRANSACTION; } @@ -136,8 +183,15 @@ OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle, remoteIpAddr[2], remoteIpAddr[3], remotePortNu); #endif - InitGetRequest(clientResponse); - + if(TEST == TEST_UNKNOWN_RESOURCE_GET_DEFAULT || TEST == TEST_UNKNOWN_RESOURCE_GET_BATCH ||\ + TEST == TEST_UNKNOWN_RESOURCE_GET_LINK_LIST) + { + InitGetRequestToUnavailableResource(clientResponse); + } + else + { + InitGetRequest(clientResponse); + } return OC_STACK_KEEP_TRANSACTION; } @@ -173,7 +227,7 @@ int InitObserveRequest(OCClientResponse * clientResponse) cbData.cb = getReqCB; cbData.context = (void*)CTX_VAL; cbData.cd = NULL; - OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str()); + OC_LOG_V(INFO, TAG, "OBSERVE payload from client = %s ", putPayload.c_str()); ret = OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(), 0, 0, OC_LOW_QOS, &cbData, NULL, 0); @@ -197,7 +251,7 @@ int InitPutRequest(OCClientResponse * clientResponse) //* Make a PUT query*/ std::ostringstream getQuery; getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << - "/a/sroom?if=oc.mi.b"; + "/a/room" << queryInterface[TEST].text; cbData.cb = putReqCB; cbData.context = (void*)CTX_VAL; cbData.cd = NULL; @@ -229,9 +283,7 @@ int InitGetRequest(OCClientResponse * clientResponse) //* Make a GET query*/ std::ostringstream getQuery; getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << - //"/a/sroom?if=oc.mi.def"; - //"/a/sroom?if=oc.mi.ll"; - "/a/sroom?if=oc.mi.b"; + "/a/room" << queryInterface[TEST].text; std::cout << "Get Query: " << getQuery.str() << std::endl; @@ -247,7 +299,6 @@ int InitGetRequest(OCClientResponse * clientResponse) return ret; } -#define TEST_APP_UNICAST_DISCOVERY_QUERY PCF("coap://0.0.0.0:5683/oc/core") int InitDiscovery() { OCStackResult ret; @@ -256,8 +307,7 @@ int InitDiscovery() /* Start a discovery query*/ char szQueryUri[64] = { 0 }; - //strcpy(szQueryUri, "coap://224.0.1.187:5683/oc/core");//?rt=core.sroom"); - strcpy(szQueryUri, "coap://0.0.0.0:5683/oc/core"); + strcpy(szQueryUri, OC_WELL_KNOWN_QUERY); cbData.cb = discoveryReqCB; cbData.context = (void*)CTX_VAL; @@ -272,6 +322,20 @@ int InitDiscovery() } int main(int argc, char* argv[]) { + if(argc >= 2 && strcmp(argv[1], "-t") == 0) + { + TEST = atoi(argv[2]); + if(TEST >= MAX_TESTS || TEST < 1) + { + PrintUsage(); + return 0; + } + } + else + { + PrintUsage(); + return 0; + } uint8_t addr[20] = {0}; uint8_t* paddr = NULL; uint16_t port = USE_RANDOM_PORT; @@ -342,5 +406,5 @@ std::string getQueryStrForGetPut(unsigned const char * responsePayload){ std::string jsonPayload(reinterpret_cast(const_cast(responsePayload))); - return "/a/sroom"; + return "/a/room"; } diff --git a/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp b/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp index 537e9c9..7a6d239 100644 --- a/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp +++ b/csdk/stack/samples/linux/SimpleClientServer/ocservercoll.cpp @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -33,27 +34,39 @@ const char *getResult(OCStackResult result); #define TAG PCF("ocservercontainer") int gQuitFlag = 0; -int gLEDUnderObservation = 0; +int gLightUnderObservation = 0; void createResources(); -typedef struct LEDRESOURCE{ +typedef struct LIGHTRESOURCE{ OCResourceHandle handle; bool state; int power; -} LEDResource; +} LightResource; -static LEDResource LED; +static LightResource light; + +// TODO : hard coded for now, change after Sprint10 +const char rspGetRoomDefault[] = "{\"href\":\"/a/room\",\"rep\":{\"name\":\"John's Room\"}}"; +const char rspGetRoomCollection[] = "{\"href\":\"/a/room\"}"; +// TODO : Needs to be changed to retrieve current status of room and return that in response +const char rspPutRoomDefault[] = "{\"href\":\"/a/room\",\"rep\":{\"name\":\"John's Room\"}}"; +const char rspPutRoomCollection[] = "{\"href\":\"/a/room\"}"; +const char rspFailureRoom[] = "{\"href\":\"/a/room\",\"rep\":{\"error\":\"ROOM_OP_FAIL\"}}"; // TODO : hard coded for now, change after Sprint4 -const char rspGetLed[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"on\",\"color\":\"yellow\"}}"; -// TODO : Needs to be changed to retrieve current status of led and return that in response -const char rspPutLed[] = "{\"href\":\"/a/led\",\"rep\":{\"state\":\"off\",\"color\":\"off\"}}"; -const char rspFailureLed[] = "{\"href\":\"/a/led\",\"rep\":{\"error\":\"LED_OP_FAIL\"}}"; +const char rspGetLightDefault[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"false\",\"color\":\"0\"}}"; +const char rspGetLightCollection[] = "{\"href\":\"/a/light\"}"; +// TODO : Needs to be changed to retrieve current status of light and return that in response +const char rspPutLightDefault[] = "{\"href\":\"/a/light\",\"rep\":{\"state\":\"true\",\"color\":\"0\"}}"; +const char rspPutLightCollection[] = "{\"href\":\"/a/light\"}"; +const char rspFailureLight[] = "{\"href\":\"/a/light\",\"rep\":{\"error\":\"LIGHT_OP_FAIL\"}}"; // TODO : hard coded for now, change after Sprint4 -const char rspGetFan[] = "{\"href\":\"/a/fan\",\"rep\":{\"state\":\"on\",\"speed\":10}}"; +const char rspGetFanDefault[] = "{\"href\":\"/a/fan\",\"rep\":{\"state\":\"true\",\"speed\":10}}"; +const char rspGetFanCollection[] = "{\"href\":\"/a/fan\"}"; // TODO : Needs to be changed to retrieve current status of fan and return that in response -const char rspPutFan[] = "{\"href\":\"/a/fan\",\"rep\":{\"state\":\"off\",\"speed\":0}}"; +const char rspPutFanDefault[] = "{\"href\":\"/a/fan\",\"rep\":{\"state\":\"false\",\"speed\":0}}"; +const char rspPutFanCollection[] = "{\"href\":\"/a/fan\"}"; const char rspFailureFan[] = "{\"href\":\"/a/fan\",\"rep\":{\"error\":\"FAN_OP_FAIL\"}}"; static OCEntityHandlerResult @@ -63,11 +76,11 @@ HandleCallback(OCEntityHandlerRequest * ehRequest, const char* opStr, const char if (strlen(opStr) < ehRequest->resJSONPayloadLen) { - strncpy((char*)ehRequest->resJSONPayload, opStr, ehRequest->resJSONPayloadLen); + strncat((char*)ehRequest->resJSONPayload, opStr, ehRequest->resJSONPayloadLen); } else if (strlen(errStr) < ehRequest->resJSONPayloadLen) { - strncpy((char*)ehRequest->resJSONPayload, errStr, ehRequest->resJSONPayloadLen); + strncat((char*)ehRequest->resJSONPayload, errStr, ehRequest->resJSONPayloadLen); ret = OC_EH_ERROR; } else @@ -102,26 +115,135 @@ PrintReceivedMsgInfo(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehReques (ehRequest->method == OC_REST_GET) ? "OC_REST_GET" : "OC_REST_PUT" ); } -OCEntityHandlerResult OCEntityHandlerLedCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest ) { +OCEntityHandlerResult OCEntityHandlerRoomCb(OCEntityHandlerFlag flag,\ + OCEntityHandlerRequest * ehRequest ) +{ + OCEntityHandlerResult ret = OC_EH_OK; + + OC_LOG_V(INFO, TAG, "Callback for Room"); + PrintReceivedMsgInfo(flag, ehRequest ); + + if(ehRequest && flag == OC_REQUEST_FLAG ) + { + std::string query = (const char*)ehRequest->query; + + if(OC_REST_GET == ehRequest->method) + { + if(query.find("oc.mi.def") != std::string::npos) + { + ret = HandleCallback(ehRequest, rspGetRoomDefault, rspFailureRoom); + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ","); + ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ","); + ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan); + } + } + else if(query.find("oc.mi.ll") != std::string::npos) + { + ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom); + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ","); + ret = HandleCallback(ehRequest, rspGetLightCollection, rspFailureLight); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ","); + ret = HandleCallback(ehRequest, rspGetFanCollection, rspFailureFan); + } + } + else if(query.find("oc.mi.b") != std::string::npos) + { + ret = HandleCallback(ehRequest, rspGetRoomCollection, rspFailureRoom); + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ","); + ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ","); + ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan); + } + } + } + if(OC_REST_PUT == ehRequest->method) + { + if(query.find("oc.mi.def") != std::string::npos) + { + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, rspPutRoomDefault, rspFailureRoom); + } + } + if(query.find("oc.mi.ll") != std::string::npos) + { + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ","); + ret = HandleCallback(ehRequest, rspPutLightCollection, rspFailureLight); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ","); + ret = HandleCallback(ehRequest, rspPutFanCollection, rspFailureFan); + } + } + if(query.find("oc.mi.b") != std::string::npos) + { + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, rspPutRoomCollection, rspFailureRoom); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ","); + ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight); + } + if(ret != OC_EH_ERROR) + { + ret = HandleCallback(ehRequest, ",", ","); + ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan); + } + } + } + } + else if (ehRequest && flag == OC_OBSERVE_FLAG) + { + gLightUnderObservation = 1; + } + return ret; +} + +OCEntityHandlerResult OCEntityHandlerLightCb(OCEntityHandlerFlag flag, OCEntityHandlerRequest * ehRequest ) { OCEntityHandlerResult ret = OC_EH_OK; - OC_LOG_V(INFO, TAG, "Callback for Led"); + OC_LOG_V(INFO, TAG, "Callback for Light"); PrintReceivedMsgInfo(flag, ehRequest ); if(ehRequest && flag == OC_REQUEST_FLAG) { if(OC_REST_GET == ehRequest->method) { - ret = HandleCallback(ehRequest, rspGetLed, rspFailureLed); + ret = HandleCallback(ehRequest, rspGetLightDefault, rspFailureLight); } if(OC_REST_PUT == ehRequest->method) { - ret = HandleCallback(ehRequest, rspPutLed, rspFailureLed); + ret = HandleCallback(ehRequest, rspPutLightDefault, rspFailureLight); } } else if (ehRequest && flag == OC_OBSERVE_FLAG) { - gLEDUnderObservation = 1; + gLightUnderObservation = 1; } return ret; @@ -137,16 +259,16 @@ OCEntityHandlerResult OCEntityHandlerFanCb(OCEntityHandlerFlag flag, OCEntityHan { if(OC_REST_GET == ehRequest->method) { - ret = HandleCallback(ehRequest, rspGetFan, rspFailureFan); + ret = HandleCallback(ehRequest, rspGetFanDefault, rspFailureFan); } if(OC_REST_PUT == ehRequest->method) { - ret = HandleCallback(ehRequest, rspPutFan, rspFailureFan); + ret = HandleCallback(ehRequest, rspPutFanDefault, rspFailureFan); } } else if (ehRequest && flag == OC_OBSERVE_FLAG) { - gLEDUnderObservation = 1; + gLightUnderObservation = 1; } return ret; @@ -159,7 +281,7 @@ void handleSigInt(int signum) { } } -void *ChangeLEDRepresentation (void *param) +void *ChangeLightRepresentation (void *param) { (void)param; OCStackResult result = OC_STACK_ERROR; @@ -167,14 +289,14 @@ void *ChangeLEDRepresentation (void *param) while (1) { sleep(10); - LED.power += 5; - if (gLEDUnderObservation) + light.power += 5; + if (gLightUnderObservation) { - OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", LED.power); - result = OCNotifyAllObservers (LED.handle, OC_NA_QOS); + OC_LOG_V(INFO, TAG, " =====> Notifying stack of new power level %d\n", light.power); + result = OCNotifyAllObservers (light.handle, OC_NA_QOS); if (OC_STACK_NO_OBSERVERS == result) { - gLEDUnderObservation = 0; + gLightUnderObservation = 0; } } } @@ -186,7 +308,7 @@ int main() { OC_LOG(DEBUG, TAG, "OCServer is starting..."); uint8_t addr[20] = {0}; uint8_t* paddr = NULL; - uint16_t port = 5683; + uint16_t port = 0; uint8_t ifname[] = "eth0"; pthread_t threadId; @@ -205,14 +327,14 @@ int main() { } /* - * Declare and create the example resource: LED + * Declare and create the example resource: light */ createResources(); /* - * Create a thread for changing the representation of the LED + * Create a thread for changing the representation of the light */ - pthread_create (&threadId, NULL, ChangeLEDRepresentation, (void *)NULL); + pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL); // Break from loop with Ctrl-C OC_LOG(INFO, TAG, "Entering ocserver main loop..."); @@ -226,7 +348,7 @@ int main() { } /* - * Cancel the LED thread and wait for it to terminate + * Cancel the light thread and wait for it to terminate */ pthread_cancel(threadId); pthread_join(threadId, NULL); @@ -240,27 +362,10 @@ int main() { return 0; } void createResources() { - LED.state = false; - OCResourceHandle room; - OCStackResult res = OCCreateResource(&room, - "core.sroom", - "oc.mi.ll", - "/a/sroom", - NULL, - OC_DISCOVERABLE); - OC_LOG_V(INFO, TAG, "Created room resource with result: %s", getResult(res)); - - OCResourceHandle light; - res = OCCreateResource(&light, - "core.light", - "oc.mi.def", - "/a/led", - OCEntityHandlerLedCb, - OC_DISCOVERABLE|OC_OBSERVABLE); - OC_LOG_V(INFO, TAG, "Created light resource with result: %s", getResult(res)); + light.state = false; OCResourceHandle fan; - res = OCCreateResource(&fan, + OCStackResult res = OCCreateResource(&fan, "core.fan", "oc.mi.def", "/a/fan", @@ -268,6 +373,26 @@ void createResources() { OC_DISCOVERABLE|OC_OBSERVABLE); OC_LOG_V(INFO, TAG, "Created fan resource with result: %s", getResult(res)); + OCResourceHandle light; + res = OCCreateResource(&light, + "core.light", + "oc.mi.def", + "/a/light", + OCEntityHandlerLightCb, + OC_DISCOVERABLE|OC_OBSERVABLE); + OC_LOG_V(INFO, TAG, "Created light resource with result: %s", getResult(res)); + + OCResourceHandle room; + res = OCCreateResource(&room, + "core.room", + "oc.mi.b", + "/a/room", + OCEntityHandlerRoomCb, + OC_DISCOVERABLE); + OC_LOG_V(INFO, TAG, "Created room resource with result: %s", getResult(res)); + OCBindResourceInterfaceToResource(room, "oc.mi.ll"); + OCBindResourceInterfaceToResource(room, "oc.mi.def"); + res = OCBindResource(room, light); OC_LOG_V(INFO, TAG, "OC Bind Contained Resource to resource: %s", getResult(res)); -- 2.7.4