Correct observe callback function in occlient.
[platform/upstream/iotivity.git] / cloud / samples / client / airconditioner / aircon_controller.cpp
1 #include <memory>
2 #include <iostream>
3 #include <stdexcept>
4 #include <condition_variable>
5 #include <map>
6 #include <vector>
7 #include <string>
8 #include <unistd.h>
9
10 #include "ocstack.h"
11 #include "ocpayload.h"
12
13 #include <OCApi.h>
14 #include <OCPlatform.h>
15
16 using namespace OC;
17 using namespace std;
18
19
20 condition_variable  g_callbackLock;
21 string         g_uid;
22 string         g_accesstoken;
23
24 string              g_host;
25 OC::OCResource::Ptr g_binaryswitchResource;
26
27 void printRepresentation(OCRepresentation rep)
28 {
29     for (auto itr = rep.begin(); itr != rep.end(); ++itr)
30     {
31         cout << "\t" << itr->attrname() << ":\t" << itr->getValueToString() << endl;
32         if (itr->type() == AttributeType::Vector)
33         {
34             switch (itr->base_type())
35             {
36                 case AttributeType::OCRepresentation:
37                     for (auto itr2 : (*itr).getValue<vector<OCRepresentation> >())
38                     {
39                         printRepresentation(itr2);
40                     }
41                     break;
42
43                 case AttributeType::Integer:
44                     for (auto itr2 : (*itr).getValue<vector<int> >())
45                     {
46                         cout << "\t\t" << itr2 << endl;
47                     }
48                     break;
49
50                 case AttributeType::String:
51                     for (auto itr2 : (*itr).getValue<vector<string> >())
52                     {
53                         cout << "\t\t" << itr2 << endl;
54                     }
55                     break;
56
57                 default:
58                     cout << "Unhandled base type " << itr->base_type() << endl;
59                     break;
60             }
61         }
62         else if (itr->type() == AttributeType::OCRepresentation)
63         {
64             printRepresentation((*itr).getValue<OCRepresentation>());
65         }
66     }
67 }
68
69 void handleLoginoutCB(const HeaderOptions &,
70                       const OCRepresentation &rep, const int ecode)
71 {
72     cout << "Login/out response received code: " << ecode << endl;
73
74     if (rep.getPayload() != NULL)
75     {
76         printRepresentation(rep);
77     }
78
79     if (ecode == 4)
80     {
81         g_accesstoken = rep.getValueToString("accesstoken");
82
83         g_uid = rep.getValueToString("uid");
84     }
85
86     g_callbackLock.notify_all();
87 }
88
89 void printResource(const OCRepresentation &rep)
90 {
91     cout << "URI: " << rep.getUri() << endl;
92
93     vector<string> rt = rep.getResourceTypes();
94     for (auto it = rt.begin(); it != rt.end(); it++)
95     {
96         cout << "RT: " << (*it) << endl;
97     }
98
99     for (auto it = rep.begin();
100          it != rep.end(); it++)
101     {
102         cout << it->attrname() << " : " << it->getValueToString() << endl;
103     }
104
105     vector<OCRepresentation> children = rep.getChildren();
106
107     for (auto it = children.begin();
108          it != children.end(); it++)
109     {
110         printResource(*it);
111     }
112 }
113
114 void onObserve(const HeaderOptions /*headerOptions*/, const OCRepresentation &rep,
115                const int &eCode, const int &sequenceNumber)
116 {
117     try
118     {
119         if (eCode == OC_STACK_OK && sequenceNumber <= MAX_SEQUENCE_NUMBER)
120         {
121             if (sequenceNumber == OC_OBSERVE_REGISTER)
122             {
123                 cout << "Observe registration action is successful" << endl;
124             }
125
126             cout << "OBSERVE RESULT:" << endl;
127             printRepresentation(rep);
128         }
129         else
130         {
131             if (eCode == OC_STACK_OK)
132             {
133                 cout << "Observe registration failed or de-registration action failed/succeeded" << endl;
134             }
135             else
136             {
137                 cout << "onObserve Response error: " << eCode << endl;
138                 exit(-1);
139             }
140         }
141     }
142     catch (exception &e)
143     {
144         cout << "Exception: " << e.what() << " in onObserve" << endl;
145     }
146 }
147
148 void onPost(const HeaderOptions & /*headerOptions*/, const OCRepresentation &rep, const int eCode)
149 {
150     cout << "POST response: " << eCode << endl;
151
152     printRepresentation(rep);
153 }
154
155 void turnOnOffSwitch(bool toTurn)
156 {
157     OCRepresentation binarySwitch;
158     binarySwitch.setValue("value", toTurn);
159
160     QueryParamsMap      query;
161     g_binaryswitchResource->post("oic.r.switch.binary", DEFAULT_INTERFACE, binarySwitch, query,
162                                  &onPost);
163 }
164
165 void getCollectionResource(const HeaderOptions &,
166                            const OCRepresentation &rep, const int ecode)
167 {
168     cout << "Resource get: " << ecode << endl;
169
170     printResource(rep);
171
172     vector<OCRepresentation> children = rep.getChildren();
173
174     cout << "Constructing binary switch" << endl;
175
176     for (auto it = children.begin(); it != children.end(); it++)
177     {
178         cout << "RT: " << it->getResourceTypes().at(0) << endl;
179
180         if (it->getResourceTypes().at(0).compare("oic.r.switch.binary") == 0)
181         {
182             cout << "Observing " << it->getUri() << endl;
183             g_binaryswitchResource = OCPlatform::constructResourceObject(g_host,
184                                      it->getUri(),
185                                      static_cast<OCConnectivityType>(CT_ADAPTER_TCP | CT_IP_USE_V4), true,
186             { string("oic.r.switch.binary") }, { string(DEFAULT_INTERFACE) });
187
188             QueryParamsMap      query;
189             g_binaryswitchResource->observe(ObserveType::Observe, query, &onObserve);
190         }
191     }
192 }
193
194 void foundAirconditionerResource(shared_ptr<OC::OCResource> resource)
195 {
196     vector<string> rt = resource->getResourceTypes();
197
198     cout << "Aircondition resource found: " << resource->uri() << endl;
199
200     g_callbackLock.notify_all();
201
202     for (auto it = rt.begin(); it != rt.end(); it++)
203     {
204         cout << "RT: " << *it << endl;
205
206         if (it->compare("x.com.samsung.da.device") == 0)
207         {
208             cout << "Found Samsung Airconditioner" << endl;
209
210             QueryParamsMap      query;
211             query["if"] = string(LINK_INTERFACE);
212             //Request to collection resource
213             resource->get(query, &getCollectionResource);
214         }
215     }
216 }
217
218 void foundDevice(shared_ptr<OC::OCResource> resource)
219 {
220     vector<string> rt = resource->getResourceTypes();
221
222     cout << "Device found: " << resource->uri() << endl;
223     cout << "DI: " << resource->sid() << endl;
224
225     g_callbackLock.notify_all();
226
227     for (auto it = rt.begin(); it != rt.end(); it++)
228     {
229         cout << "RT: " << *it << endl;
230
231         if (it->compare("oic.d.airconditioner") == 0)
232         {
233             string searchQuery = "/oic/res?di=";
234             searchQuery += resource->sid();
235             cout << "Airconditioner found" << endl;
236             OCPlatform::findResource(g_host, searchQuery,
237                                      static_cast<OCConnectivityType>(CT_ADAPTER_TCP | CT_IP_USE_V4),
238                                      &foundAirconditionerResource);
239
240             OCPlatform::OCPresenceHandle    handle;
241             if (OCPlatform::subscribeDevicePresence(handle, g_host, { resource->sid() },
242                                                     static_cast<OCConnectivityType>
243                                                     (CT_ADAPTER_TCP | CT_IP_USE_V4), &onObserve) != OC_STACK_OK)
244             {
245                 cout << "Device presence failed" << endl;
246             }
247         }
248     }
249 }
250
251 void presenceDevice(OCStackResult , const unsigned int i, const string &str)
252 {
253     cout << "Presence received, i=" << i << " str=" << str << endl;
254 }
255
256 static FILE *client_open(const char * /*path*/, const char *mode)
257 {
258     return fopen("./aircon_controller.dat", mode);
259 }
260
261 int main(int argc, char *argv[])
262 {
263     if (argc != 4 && argc != 5)
264     {
265         cout << "Put \"[host-ipaddress:port] [authprovider] [authcode]\" for sign-up and sign-in and discover resources"
266              << endl;
267         cout << "Put \"[host-ipaddress:port] [uid] [accessToken] 1\" for sign-in and discover resources" <<
268              endl;
269         return 0;
270     }
271
272     OCPersistentStorage ps{ client_open, fread, fwrite, fclose, unlink };
273
274     PlatformConfig cfg
275     {
276         ServiceType::InProc,
277         ModeType::Both,
278         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
279         0,         // Uses randomly available port
280         QualityOfService::LowQos,
281         &ps
282     };
283
284     OCPlatform::Configure(cfg);
285
286     OCStackResult result = OC_STACK_ERROR;
287
288     g_host = "coap+tcp://";
289     g_host += argv[1];
290
291     OCAccountManager::Ptr accountMgr = OCPlatform::constructAccountManagerObject(g_host,
292                                        CT_ADAPTER_TCP);
293
294
295     mutex blocker;
296     unique_lock<mutex> lock(blocker);
297
298     if (argc == 5)
299     {
300         accountMgr->signIn(argv[2], argv[3], &handleLoginoutCB);
301         g_callbackLock.wait(lock);
302     }
303     else
304     {
305         accountMgr->signUp(argv[2], argv[3], &handleLoginoutCB);
306         g_callbackLock.wait(lock);
307         accountMgr->signIn(g_uid, g_accesstoken, &handleLoginoutCB);
308         g_callbackLock.wait(lock);
309     }
310
311     /*
312     cout << "Subscribing resource presence ";
313
314     string query = "oic.wk.d&di=F0FDE28F-36BF-49BC-89F1-6AFB8D73E93C";
315
316     OCPlatform::OCPresenceHandle presenceHandle;
317
318     result = OCPlatform::subscribePresence(presenceHandle, g_host, query,
319                                            static_cast<OCConnectivityType>(CT_ADAPTER_TCP | CT_IP_USE_V4), &presenceDevice);
320
321     cout << " result: " << result << endl;
322     */
323
324     cout << "Finding airconditioner ";
325
326     result = OCPlatform::findResource(g_host, "/oic/res?rt=oic.wk.d",
327                                       static_cast<OCConnectivityType>(CT_ADAPTER_TCP | CT_IP_USE_V4),
328                                       &foundDevice);
329
330     cout << " result: " << result << endl;
331
332     g_callbackLock.wait(lock);
333
334     cout << "PUT 1/0 to turn on/off air conditioner, q to terminate" << endl;
335
336     string cmd;
337
338     while (true)
339     {
340         cin >> cmd;
341         OCRepresentation    rep;
342
343         switch (cmd[0])
344         {
345             case '1':
346                 turnOnOffSwitch(true);
347                 break;
348
349             case '0':
350                 turnOnOffSwitch(false);
351                 break;
352
353             case 'q':
354                 goto exit;
355                 break;
356         }
357     }
358
359 exit:
360     return 0;
361 }