1 //******************************************************************
3 // Copyright 2014 Intel Corporation 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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
30 char *getResult(OCStackResult result);
31 std::string getIPAddrTBServer(OCClientResponse * clientResponse);
32 std::string getPortTBServer(OCClientResponse * clientResponse);
33 std::string getQueryStrForGetPut(unsigned const char * responsePayload);
35 #define TAG PCF("occlient")
37 #ifndef MAX_LENGTH_IPv4_ADDR
38 #define MAX_LENGTH_IPv4_ADDR 16
41 #define MAX_TEST_CASES 5
43 static int UNICAST_DISCOVERY = 0;
44 static int TEST_CASE = 0;
45 static std::string putPayload = "{\"state\":\"off\",\"power\":\"0\"}";
47 // The handle for the observe registration
48 OCDoHandle gObserveDoHandle;
49 // After this crosses a threshold client deregisters for further observations
53 /* SIGINT handler: set gQuitFlag to 1 for graceful termination */
54 void handleSigInt(int signum) {
55 if (signum == SIGINT) {
60 // Forward Declaration
61 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse);
62 int InitGetRequestToUnavailableResource(OCClientResponse * clientResponse);
63 int InitObserveRequest(OCClientResponse * clientResponse);
64 int InitPutRequest(OCClientResponse * clientResponse);
65 int InitGetRequest(OCClientResponse * clientResponse);
70 OC_LOG(INFO, TAG, "Usage : occlient <Unicast Discovery> <Test Case>");
71 OC_LOG(INFO, TAG, "Test Case 1 : Discover Resources");
72 OC_LOG(INFO, TAG, "Test Case 2 : Discover Resources and Initiate Get Request");
73 OC_LOG(INFO, TAG, "Test Case 3 : Discover Resources and Initiate Get/Put Requests");
74 OC_LOG(INFO, TAG, "Test Case 4 : Discover Resources and Initiate Observe Requests");
75 OC_LOG(INFO, TAG, "Test Case 5 : Discover Resources and Initiate Get Request for a resource which is unavailable");
78 OCStackApplicationResult putReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
80 if(ctx == (void*)CTX_VAL) {
81 OC_LOG_V(INFO, TAG, "Callback Context for PUT query recvd successfully");
82 OC_LOG_V(INFO, TAG, "JSON = %s =============> Discovered", clientResponse->resJSONPayload);
85 return OC_STACK_KEEP_TRANSACTION;
88 OCStackApplicationResult getReqCB(void* ctx, OCDoHandle handle, OCClientResponse * clientResponse) {
89 OC_LOG_V(INFO, TAG, "StackResult: %s",
90 getResult(clientResponse->result));
91 if(ctx == (void*)CTX_VAL) {
92 OC_LOG_V(INFO, TAG, "SEQUENCE NUMBER: %d", clientResponse->sequenceNumber);
93 if(clientResponse->sequenceNumber == 0) {
94 OC_LOG_V(INFO, TAG, "Callback Context for GET query recvd successfully");
95 OC_LOG_V(INFO, TAG, "Fnd' Rsrc': %s", clientResponse->resJSONPayload);
98 OC_LOG_V(INFO, TAG, "Callback Context for OBSERVE notification recvd successfully %d", gNumNotifies);
99 OC_LOG_V(INFO, TAG, "Fnd' Rsrc': %s", clientResponse->resJSONPayload);
101 if (gNumNotifies == 3)
103 if (OCCancel (gObserveDoHandle) != OC_STACK_OK){
104 OC_LOG(ERROR, TAG, "Observe cancel error");
109 return OC_STACK_KEEP_TRANSACTION;
113 // This is a function called back when a device is discovered
114 OCStackApplicationResult discoveryReqCB(void* ctx, OCDoHandle handle,
115 OCClientResponse * clientResponse) {
116 uint8_t remoteIpAddr[4];
117 uint16_t remotePortNu;
120 "Entering discoveryReqCB (Application Layer CB)");
121 OC_LOG_V(INFO, TAG, "StackResult: %s",
122 getResult(clientResponse->result));
124 if (ctx == (void*) CTX_VAL) {
125 OC_LOG_V(INFO, TAG, "Callback Context recvd successfully");
128 OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr,
129 remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
130 OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu);
133 "Device =============> Discovered %s @ %d.%d.%d.%d:%d",
134 clientResponse->resJSONPayload, remoteIpAddr[0], remoteIpAddr[1],
135 remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
139 InitGetRequest(clientResponse);
141 else if (TEST_CASE == 3)
143 InitPutRequest(clientResponse);
145 else if (TEST_CASE == 4)
147 InitObserveRequest(clientResponse);
149 else if (TEST_CASE == 5)
151 InitGetRequestToUnavailableResource(clientResponse);
153 return OC_STACK_KEEP_TRANSACTION;
157 int InitGetRequestToUnavailableResource(OCClientResponse * clientResponse)
160 OCCallbackData cbData;
162 std::ostringstream getQuery;
163 getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << "/SomeUnknownResource";
164 cbData.cb = getReqCB;
165 cbData.context = (void*)CTX_VAL;
166 ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_NON_CONFIRMABLE, &cbData);
167 if (ret != OC_STACK_OK)
169 OC_LOG(ERROR, TAG, "OCStack resource error");
175 int InitObserveRequest(OCClientResponse * clientResponse)
178 OCCallbackData cbData;
180 std::ostringstream obsReg;
181 obsReg << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << getQueryStrForGetPut(clientResponse->resJSONPayload);
182 cbData.cb = getReqCB;
183 cbData.context = (void*)CTX_VAL;
184 OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str());
185 ret = OCDoResource(&handle, OC_REST_OBSERVE, obsReg.str().c_str(), 0, 0, OC_NON_CONFIRMABLE, &cbData);
186 if (ret != OC_STACK_OK)
188 OC_LOG(ERROR, TAG, "OCStack resource error");
192 gObserveDoHandle = handle;
198 int InitPutRequest(OCClientResponse * clientResponse)
201 OCCallbackData cbData;
203 //* Make a PUT query*/
204 std::ostringstream getQuery;
205 getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << getQueryStrForGetPut(clientResponse->resJSONPayload);
206 cbData.cb = putReqCB;
207 cbData.context = (void*)CTX_VAL;
208 OC_LOG_V(INFO, TAG, "PUT payload from client = %s ", putPayload.c_str());
209 ret = OCDoResource(&handle, OC_REST_PUT, getQuery.str().c_str(), 0, putPayload.c_str(), OC_NON_CONFIRMABLE, &cbData);
210 if (ret != OC_STACK_OK)
212 OC_LOG(ERROR, TAG, "OCStack resource error");
218 int InitGetRequest(OCClientResponse * clientResponse)
221 OCCallbackData cbData;
223 //* Make a GET query*/
224 std::ostringstream getQuery;
225 getQuery << "coap://" << getIPAddrTBServer(clientResponse) << ":" << getPortTBServer(clientResponse) << getQueryStrForGetPut(clientResponse->resJSONPayload);
226 cbData.cb = getReqCB;
227 cbData.context = (void*)CTX_VAL;
228 ret = OCDoResource(&handle, OC_REST_GET, getQuery.str().c_str(), 0, 0, OC_NON_CONFIRMABLE, &cbData);
229 if (ret != OC_STACK_OK)
231 OC_LOG(ERROR, TAG, "OCStack resource error");
236 #define TEST_APP_UNICAST_DISCOVERY_QUERY PCF("coap://0.0.0.0:5683/oc/core")
240 OCCallbackData cbData;
242 /* Start a discovery query*/
243 char szQueryUri[64] = { 0 };
244 if (UNICAST_DISCOVERY)
246 strcpy(szQueryUri, TEST_APP_UNICAST_DISCOVERY_QUERY);
250 strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
252 cbData.cb = discoveryReqCB;
253 cbData.context = (void*)CTX_VAL;
254 ret = OCDoResource(&handle, OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData);
255 if (ret != OC_STACK_OK)
257 OC_LOG(ERROR, TAG, "OCStack resource error");
262 int main(int argc, char* argv[]) {
263 uint8_t addr[20] = {0};
264 uint8_t* paddr = NULL;
265 uint16_t port = USE_RANDOM_PORT;
266 uint8_t ifname[] = "eth0";
270 UNICAST_DISCOVERY = atoi(argv[1]);
271 TEST_CASE = atoi(argv[2]);
272 if ((UNICAST_DISCOVERY != 0 && UNICAST_DISCOVERY != 1) ||
273 (TEST_CASE < 1 || TEST_CASE > MAX_TEST_CASES) )
286 /*Get Ip address on defined interface and initialize coap on it with random port number
287 * this port number will be used as a source port in all coap communications*/
288 if ( OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr,
289 sizeof(addr)) == ERR_SUCCESS)
291 OC_LOG_V(INFO, TAG, "Starting occlient on address %s",addr);
295 /* Initialize OCStack*/
296 if (OCInit((char *) paddr, port, OC_CLIENT) != OC_STACK_OK) {
297 OC_LOG(ERROR, TAG, "OCStack init error");
303 // Break from loop with Ctrl+C
304 OC_LOG(INFO, TAG, "Entering occlient main loop...");
305 signal(SIGINT, handleSigInt);
308 if (OCProcess() != OC_STACK_OK) {
309 OC_LOG(ERROR, TAG, "OCStack process error");
315 OC_LOG(INFO, TAG, "Exiting occlient main loop...");
317 if (OCStop() != OC_STACK_OK) {
318 OC_LOG(ERROR, TAG, "OCStack stop error");
324 char *getResult(OCStackResult result) {
325 char *resString = new char[40];
326 memset(resString, 0, 40);
327 strcpy(resString, "Result: ");
330 strcat(resString, "OC_STACK_OK");
332 case OC_STACK_INVALID_URI:
333 strcat(resString, "OC_STACK_INVALID_URI");
335 case OC_STACK_INVALID_QUERY:
336 strcat(resString, "OC_STACK_INVALID_QUERY");
338 case OC_STACK_INVALID_IP:
339 strcat(resString, "OC_STACK_INVALID_IP");
341 case OC_STACK_INVALID_PORT:
342 strcat(resString, "OC_STACK_INVALID_PORT");
344 case OC_STACK_INVALID_CALLBACK:
345 strcat(resString, "OC_STACK_INVALID_CALLBACK");
347 case OC_STACK_INVALID_METHOD:
348 strcat(resString, "OC_STACK_INVALID_METHOD");
350 case OC_STACK_NO_MEMORY:
351 strcat(resString, "OC_STACK_NO_MEMORY");
353 case OC_STACK_COMM_ERROR:
354 strcat(resString, "OC_STACK_COMM_ERROR");
356 case OC_STACK_INVALID_PARAM:
357 strcat(resString, "OC_STACK_INVALID_PARAM");
359 case OC_STACK_NOTIMPL:
360 strcat(resString, "OC_STACK_NOTIMPL");
362 case OC_STACK_NO_RESOURCE:
363 strcat(resString, "OC_STACK_NO_RESOURCE");
365 case OC_STACK_RESOURCE_ERROR:
366 strcat(resString, "OC_STACK_RESOURCE_ERROR");
368 case OC_STACK_SLOW_RESOURCE:
369 strcat(resString, "OC_STACK_SLOW_RESOURCE");
372 strcat(resString, "OC_STACK_ERROR");
375 strcat(resString, "UNKNOWN");
381 std::string getIPAddrTBServer(OCClientResponse * clientResponse) {
382 if(!clientResponse) return "";
383 if(!clientResponse->addr) return "";
384 uint8_t a, b, c, d = 0;
385 if(0 != OCDevAddrToIPv4Addr(clientResponse->addr, &a, &b, &c, &d) ) return "";
387 char ipaddr[16] = {'\0'};
388 snprintf(ipaddr, sizeof(ipaddr), "%d.%d.%d.%d", a,b,c,d); // ostringstream not working correctly here, hence snprintf
389 //printf("IP address string of the TB server = %s\n", *out_ipaddr);
390 return std::string (ipaddr);
394 std::string getPortTBServer(OCClientResponse * clientResponse){
395 if(!clientResponse) return "";
396 if(!clientResponse->addr) return "";
398 if(0 != OCDevAddrToPort(clientResponse->addr, &p) ) return "";
399 std::ostringstream ss;
404 std::string getQueryStrForGetPut(unsigned const char * responsePayload){
405 // JSON = {"oc":{"payload":[{"href":"/a/led","rt":["core.led"],"if":["core.rw"],"obs":1}]}}
407 //std::string jsonPayload(responsePayload, responsePayload + sizeof responsePayload / sizeof responsePayload[0]);
408 std::string jsonPayload(reinterpret_cast<char*>(const_cast<unsigned char*>(responsePayload)));
409 //std::cout << jsonPayload << std::endl;