modified OCAccountManager APIs
[platform/upstream/iotivity.git] / cloud / samples / client / group_invite / group_light_share.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 #include "rd_client.h"
13
14 #include <OCApi.h>
15 #include <OCPlatform.h>
16
17 #define maxSequenceNumber 0xFFFFFF
18
19 using namespace OC;
20 using namespace std;
21
22 string g_host = "coap+tcp://";
23 condition_variable g_callbackLock;
24
25 class LightResource
26 {
27 public:
28     /// Access this property from a TB client
29     std::string m_power;
30     std::string m_lightUri;
31     OCResourceHandle m_resourceHandle;
32     OCRepresentation m_lightRep;
33
34     /// Constructor
35     LightResource() :
36             m_power(""), m_lightUri("/a/light")
37     {
38         // Initialize representation
39         m_lightRep.setUri(m_lightUri);
40         m_lightRep.setValue("power", m_power);
41     }
42
43     /// This function internally calls registerResource API.
44     void createResource()
45     {
46         std::string resourceURI = m_lightUri; //URI of the resource
47         std::string resourceTypeName = "core.light"; //resource type name. In this case, it is light
48         std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
49
50         EntityHandler cb = std::bind(&LightResource::entityHandler, this, std::placeholders::_1);
51
52         // This will internally create and register the resource.
53         OCStackResult result = OCPlatform::registerResource(m_resourceHandle, resourceURI,
54                 resourceTypeName, resourceInterface, cb, OC_DISCOVERABLE | OC_OBSERVABLE);
55
56         if (OC_STACK_OK != result)
57         {
58             cout << "Resource creation was unsuccessful\n";
59         }
60     }
61
62     OCRepresentation post(OCRepresentation &rep)
63     {
64         m_power = rep.getValueToString("power");
65         return get();
66     }
67
68     // gets the updated representation.
69     // Updates the representation with latest internal state before
70     // sending out.
71     OCRepresentation get()
72     {
73         m_lightRep.setValue("power", m_power);
74
75         return m_lightRep;
76     }
77
78 private:
79     // This is just a sample implementation of entity handler.
80     // Entity handler can be implemented in several ways by the manufacturer
81     OCEntityHandlerResult entityHandler(std::shared_ptr< OCResourceRequest > request)
82     {
83         cout << "\tIn Server CPP entity handler:\n";
84         OCEntityHandlerResult ehResult = OC_EH_ERROR;
85         if (request)
86         {
87             // Get the request type and request flag
88             std::string requestType = request->getRequestType();
89             int requestFlag = request->getRequestHandlerFlag();
90
91             if (requestFlag & RequestHandlerFlag::RequestFlag)
92             {
93                 cout << "\t\trequestFlag : Request\n";
94                 auto pResponse = std::make_shared< OC::OCResourceResponse >();
95                 pResponse->setRequestHandle(request->getRequestHandle());
96                 pResponse->setResourceHandle(request->getResourceHandle());
97
98                 // If the request type is GET
99                 if (requestType == "GET")
100                 {
101                     cout << "\t\t\trequestType : GET\n";
102                     pResponse->setErrorCode(200);
103                     pResponse->setResponseResult(OC_EH_OK);
104                     pResponse->setResourceRepresentation(get());
105                     if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
106                     {
107                         ehResult = OC_EH_OK;
108                     }
109                 }
110                 else if (requestType == "POST")
111                 {
112                     cout << "\t\t\trequestType : POST\n";
113
114                     OCRepresentation rep = request->getResourceRepresentation();
115
116                     // Do related operations related to POST request
117                     OCRepresentation rep_post = post(rep);
118                     pResponse->setResourceRepresentation(rep_post);
119                     pResponse->setErrorCode(200);
120
121                     if (OC_STACK_OK == OCPlatform::sendResponse(pResponse))
122                     {
123                         ehResult = OC_EH_OK;
124                     }
125                 }
126                 else
127                 {
128                     std::cout << "Unhandled request type" << std::endl;
129                 }
130             }
131         }
132         else
133         {
134             std::cout << "Request invalid" << std::endl;
135         }
136
137         return ehResult;
138     }
139 };
140
141 void printRepresentation(OCRepresentation rep)
142 {
143     for (auto itr = rep.begin(); itr != rep.end(); ++itr)
144     {
145         cout << "\t" << itr->attrname() << ":\t" << itr->getValueToString() << endl;
146         if (itr->type() == AttributeType::Vector)
147         {
148             switch (itr->base_type())
149             {
150                 case AttributeType::OCRepresentation:
151                     for (auto itr2 : (*itr).getValue< vector< OCRepresentation > >())
152                     {
153                         printRepresentation(itr2);
154                     }
155                     break;
156
157                 case AttributeType::Integer:
158                     for (auto itr2 : (*itr).getValue< vector< int > >())
159                     {
160                         cout << "\t\t" << itr2 << endl;
161                     }
162                     break;
163
164                 case AttributeType::String:
165                     for (auto itr2 : (*itr).getValue< vector< string > >())
166                     {
167                         cout << "\t\t" << itr2 << endl;
168                     }
169                     break;
170
171                 default:
172                     cout << "Unhandled base type " << itr->base_type() << endl;
173                     break;
174             }
175         }
176         else if (itr->type() == AttributeType::OCRepresentation)
177         {
178             printRepresentation((*itr).getValue< OCRepresentation >());
179         }
180     }
181 }
182
183 void getResource(const HeaderOptions &, const OCRepresentation &rep, const int ecode)
184 {
185     cout << "Resource get: " << ecode << endl;
186
187     printRepresentation(rep);
188 }
189
190 void foundMyDevice(shared_ptr< OC::OCResource > resource)
191 {
192     cout << "Device found: " << resource->uri() << endl;
193     cout << "DI: " << resource->sid() << endl;
194
195     g_callbackLock.notify_all();
196 }
197
198 void foundDevice(shared_ptr< OC::OCResource > resource)
199 {
200     vector < string > rt = resource->getResourceTypes();
201
202     cout << "Device found: " << resource->uri() << endl;
203     cout << "DI: " << resource->sid() << endl;
204
205     QueryParamsMap query;
206     resource->get(query, &getResource);
207 }
208
209 void onObserveGroup(const HeaderOptions /*headerOptions*/, const OCRepresentation &rep,
210         const int &eCode, const int /*&sequenceNumber*/)
211 {
212     cout << "onObserveGroup response received code: " << eCode << endl;
213
214     if (eCode == OC_STACK_OK)
215     {
216         printRepresentation(rep);
217
218         vector < string > dilist = rep.getValue < vector< string > > ("dilist");
219
220         for (auto itr = dilist.begin(); itr != dilist.end(); ++itr)
221         {
222             cout << (*itr) << " discovered" << endl;
223             if ((*itr) != OCGetServerInstanceIDString())
224             {
225                 cout << "New device joined" << endl;
226                 string query = "/oic/res?di=";
227                 query += (*itr);
228                 OCStackResult result = OC_STACK_ERROR;
229
230                 cout << "find my resource : " << *itr << endl;
231                 result = OCPlatform::findResource(g_host, query,
232                         static_cast< OCConnectivityType >(CT_ADAPTER_TCP | CT_IP_USE_V4),
233                         &foundDevice);
234                 cout << " result: " << result << endl;
235                 break;
236             }
237         }
238     }
239     g_callbackLock.notify_all();
240 }
241
242 string g_invitedGroup;
243 void onInvite(const HeaderOptions /*headerOptions*/, const OCRepresentation &rep, const int &eCode,
244         const int &sequenceNumber)
245 {
246     cout << "onInvite response received code: " << eCode << endl;
247
248     if (eCode == OC_STACK_OK)
249     {
250         printRepresentation(rep);
251
252         if (sequenceNumber != OC_OBSERVE_REGISTER)
253         {
254             vector < OCRepresentation > invited = rep.getValue < vector< OCRepresentation >
255                     > ("invited");
256
257             g_invitedGroup = invited[0].getValueToString("gid");
258         }
259     }
260
261     g_callbackLock.notify_all();
262 }
263
264 string g_gid;
265 void onCreateGroup(const HeaderOptions &, const OCRepresentation &rep, const int ecode)
266 {
267     cout << "onCreateGroup response received code: " << ecode << endl;
268
269     if (ecode == 4)
270     {
271         printRepresentation(rep);
272         g_gid = rep.getValueToString("gid");
273     }
274
275     g_callbackLock.notify_all();
276 }
277
278 void onPublish(const OCRepresentation &, const int &eCode)
279 {
280     cout << "Publish resource response received, code: " << eCode << endl;
281     g_callbackLock.notify_all();
282 }
283
284 void onPost(const HeaderOptions & /*headerOptions*/, const OCRepresentation &rep, const int eCode)
285 {
286     if (eCode == OC_STACK_OK || eCode == OC_STACK_RESOURCE_CHANGED)
287     {
288         cout << "\tRequest was successful: " << eCode << endl;
289
290         printRepresentation(rep);
291     }
292     else
293     {
294         cout << "\tResponse error: " << eCode << endl;
295     }
296
297     g_callbackLock.notify_all();
298 }
299
300 string g_uid;
301 string g_accesstoken;
302
303 void handleLoginoutCB(const HeaderOptions &, const OCRepresentation &rep, const int ecode)
304 {
305     cout << "Auth response received code: " << ecode << endl;
306
307     if (rep.getPayload() != NULL)
308     {
309         printRepresentation(rep);
310     }
311
312     if (ecode == 4)
313     {
314         g_accesstoken = rep.getValueToString("accesstoken");
315
316         g_uid = rep.getValueToString("uid");
317     }
318
319     g_callbackLock.notify_all();
320 }
321
322 string g_option;
323
324 static FILE *client_open(const char * /*path*/, const char *mode)
325 {
326     string option = "./";
327     option += g_option;
328     option += ".dat";
329     return fopen(option.c_str(), mode);
330 }
331
332 int main(int argc, char **argv)
333 {
334     if (argc != 5)
335     {
336         cout
337                 << "Put \"[host-ipaddress:port] [authprovider] [authcode] [\'owner\'|\'member\']\" for sign-up and sign-in"
338                 << endl;
339         cout << "Put \"[host-ipaddress:port] [uid] [accessToken] 1\" for sign-in" << endl;
340         return 0;
341     }
342
343     g_option = argv[4];
344
345     OCPersistentStorage ps
346     { client_open, fread, fwrite, fclose, unlink };
347
348     PlatformConfig cfg
349     { ServiceType::InProc, ModeType::Both, "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
350             0, // Uses randomly available port
351             QualityOfService::LowQos, &ps };
352
353     OCPlatform::Configure(cfg);
354
355     OCStackResult result = OC_STACK_ERROR;
356
357     g_host += argv[1];
358
359     OCAccountManager::Ptr accountMgr = OCPlatform::constructAccountManagerObject(g_host,
360             CT_ADAPTER_TCP);
361
362     mutex blocker;
363     unique_lock < mutex > lock(blocker);
364
365     if (g_option == "1")
366     {
367         accountMgr->signIn(argv[2], argv[3], &handleLoginoutCB);
368         g_callbackLock.wait(lock);
369     }
370     else
371     {
372         accountMgr->signUp(argv[2], argv[3], &handleLoginoutCB);
373         g_callbackLock.wait(lock);
374         accountMgr->signIn(g_uid, g_accesstoken, &handleLoginoutCB);
375         g_callbackLock.wait(lock);
376     }
377
378     string cmd;
379
380     LightResource lightResource;
381     lightResource.createResource();
382
383     ResourceHandles resourceHandles;
384     resourceHandles.push_back(lightResource.m_resourceHandle);
385
386     OCPlatform::publishResourceToRD(g_host, OCConnectivityType::CT_ADAPTER_TCP, resourceHandles,
387             &onPublish);
388     g_callbackLock.wait(lock);
389 /* TODO: need to modify the below according to the OCAccountManager API changed.
390     if (g_option == "owner")
391     {
392         cout << "Creating group" << endl;
393         accountMgr->createGroup(AclGroupType::PUBLIC, &onCreateGroup);
394         g_callbackLock.wait(lock);
395         cout << "Adding device " << OCGetServerInstanceIDString() << " to group " << g_gid << endl;
396         accountMgr->addDeviceToGroup(g_gid,
397         { OCGetServerInstanceIDString() }, &onPost);
398         g_callbackLock.wait(lock);
399
400         accountMgr->observeGroup(g_gid, &onObserveGroup);
401         g_callbackLock.wait(lock);
402         cout << "Put userUUID to send invitation" << endl;
403         cin >> cmd;
404         cout << "Group id : " << g_gid << " send invitation to " << cmd << endl;
405         accountMgr->sendInvitation(g_gid, cmd, &onPost);
406         g_callbackLock.wait(lock);
407
408         cin >> cmd;
409     }
410     else if (g_option == "member")
411     {
412         cout << "Observing invitation" << endl;
413         accountMgr->observeInvitation(&onInvite);
414         g_callbackLock.wait(lock);
415         cout << "Waiting invitation" << endl;
416         g_callbackLock.wait(lock);
417         cout << "Joining group " << g_invitedGroup << endl;
418         accountMgr->joinGroup(g_invitedGroup, &onPost);
419         g_callbackLock.wait(lock);
420
421         cout << "find my resource " << cmd << endl;
422         result = OCPlatform::findResource(g_host, "/oic/res",
423                 static_cast< OCConnectivityType >(CT_ADAPTER_TCP | CT_IP_USE_V4), &foundMyDevice);
424         g_callbackLock.wait(lock);
425
426         accountMgr->observeGroup(g_invitedGroup, &onObserveGroup);
427         g_callbackLock.wait(lock);
428
429         cin >> cmd;
430     }
431 */
432     return 0;
433 }