Update snapshot(2017-12-14)
[platform/upstream/iotivity.git] / resource / examples / presenceserver.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 ///
22 /// This sample provides steps to define an interface for a resource
23 /// (properties and methods) and host this resource on the server.
24 ///
25
26 #include "iotivity_config.h"
27 #include <functional>
28
29 #ifdef HAVE_PTHREAD_H
30 #include <pthread.h>
31 #endif
32 #include <array>
33 #include <mutex>
34 #include <condition_variable>
35
36 #include "OCPlatform.h"
37 #include "OCApi.h"
38 #include "ocpayload.h"
39
40 #ifdef HAVE_WINDOWS_H
41 #include <windows.h>
42 #endif
43
44 using namespace OC;
45 using namespace std;
46
47 #define numPresenceResources (2)
48
49 // Set of strings for each of platform Info fields
50 std::string  platformId = "0A3E0D6F-DBF5-404E-8719-D6880042463A";
51 std::string  manufacturerName = "OCF";
52 std::string  manufacturerLink = "https://www.iotivity.org";
53 std::string  modelNumber = "myModelNumber";
54 std::string  dateOfManufacture = "2016-01-15";
55 std::string  platformVersion = "myPlatformVersion";
56 std::string  operatingSystemVersion = "myOS";
57 std::string  hardwareVersion = "myHardwareVersion";
58 std::string  firmwareVersion = "1.0";
59 std::string  supportLink = "https://www.iotivity.org";
60 std::string  systemTime = "2016-01-15T11.01";
61
62 // Set of strings for each of device info fields
63 std::string  deviceName = "IoTivity Presence Server";
64 std::string  specVersion = "core.1.1.0";
65 std::string  dataModelVersions = "res.1.1.0";
66
67 // OCPlatformInfo Contains all the platform info to be stored
68 OCPlatformInfo platformInfo;
69
70 // OCDeviceInfo Contains all the device info to be stored
71 OCDeviceInfo deviceInfo;
72
73 // Forward declaring the entityHandler
74 OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
75
76 /// This class represents a single resource named 'lightResource'. This resource has
77 /// two simple properties named 'state' and 'power'
78
79 class LightResource
80 {
81 public:
82     /// Access this property from a TB client
83     bool m_state;
84     int m_power;
85     std::string m_lightUri;
86     std::string m_lightUri2;
87     std::string m_lightUri3;
88     OCResourceHandle m_resourceHandle;
89     OCResourceHandle m_resourceHandle2;
90     OCResourceHandle m_resourceHandle3;
91
92 public:
93     /// Constructor
94     LightResource(): m_state(false), m_power(0), m_lightUri("/a/light"),
95                      m_lightUri2("/a/light2"),m_lightUri3("/a/light3") {}
96
97     /* Note that this does not need to be a member function: for classes you do not have
98     access to, you can accomplish this with a free function: */
99
100     /// This function internally calls registerResource API.
101     void createResource()
102     {
103         std::string resourceURI = m_lightUri; // URI of the resource
104         std::string resourceTypeName = "core.light"; // resource type name.
105         std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
106
107         // OCResourceProperty is defined ocstack.h
108         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
109
110         // This will internally create and register the resource.
111         OCStackResult result = OCPlatform::registerResource(
112                                     m_resourceHandle, resourceURI, resourceTypeName,
113                                     resourceInterface, &entityHandler, resourceProperty);
114
115         if (OC_STACK_OK != result)
116         {
117             cout << "Resource creation was unsuccessful\n";
118         }
119     }
120
121     /// This function internally calls registerResource API.
122     void createResource2()
123     {
124         std::string resourceURI = m_lightUri2; // URI of the resource
125         std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light
126         std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
127
128         // OCResourceProperty is defined ocstack.h
129         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
130
131         // This will internally create and register the resource.
132         OCStackResult result = OCPlatform::registerResource(
133                                     m_resourceHandle2, resourceURI, resourceTypeName,
134                                     resourceInterface, &entityHandler, resourceProperty);
135
136         if (OC_STACK_OK != result)
137         {
138             cout << "Resource creation was unsuccessful\n";
139         }
140     }
141
142     void createResource3()
143     {
144         std::string resourceURI = m_lightUri3; // URI of the resource
145         std::string resourceTypeName = "core.light";
146         std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
147
148         // OCResourceProperty is defined ocstack.h
149         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
150
151         // This will internally create and register the resource.
152         OCStackResult result = OCPlatform::registerResource(
153                                     m_resourceHandle3, resourceURI, resourceTypeName,
154                                     resourceInterface, &entityHandler, resourceProperty);
155
156         if (OC_STACK_OK != result)
157         {
158             cout << "Resource creation was unsuccessful\n";
159         }
160     }
161
162     OCResourceHandle getHandle()
163     {
164         return m_resourceHandle;
165     }
166
167     void addType(const std::string& type) const
168     {
169         OCStackResult result = OC::OCPlatform::bindTypeToResource(m_resourceHandle, type);
170         if (OC_STACK_OK != result)
171         {
172             cout << "Binding TypeName to Resource was unsuccessful\n";
173         }
174     }
175
176     void addInterface(const std::string& iface) const
177     {
178         OCStackResult result = OC::OCPlatform::bindInterfaceToResource(m_resourceHandle, iface);
179         if (OC_STACK_OK != result)
180         {
181             cout << "Binding TypeName to Resource was unsuccessful\n";
182         }
183     }
184
185 };
186
187 void createPresenceResources()
188 {
189     std::array<std::string, numPresenceResources> resourceURI { {
190         "/a/fan",
191         "/a/led" } };
192     std::array<std::string, numPresenceResources> resourceTypeName { {
193         "core.fan",
194         "core.led" } };
195
196     std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
197     OCResourceHandle handle;
198     // OCResourceProperty is defined ocstack.h
199     uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
200
201     // This will internally create and register the resource.
202     OCStackResult result = OC_STACK_OK;
203     for(int i=0; i<numPresenceResources; i++)
204     {
205         result = OCPlatform::registerResource(handle,
206                 resourceURI.at(i), resourceTypeName.at(i), resourceInterface,
207                 &entityHandler, resourceProperty);
208         if (result != OC_STACK_OK)
209         {
210             cout << "Resource creation was unsuccessful with resource URI "
211                     << resourceURI.at(i);
212         }
213     }
214 }
215
216 // Create the instance of the resource class (in this case instance of class 'LightResource').
217 LightResource myLightResource;
218
219 OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> /*request*/)
220 {
221     cout << "\tIn Server CPP entity handler:\n";
222     return OC_EH_OK;
223 }
224
225 void DeletePlatformInfo()
226 {
227     delete[] platformInfo.platformID;
228     delete[] platformInfo.manufacturerName;
229     delete[] platformInfo.manufacturerUrl;
230     delete[] platformInfo.modelNumber;
231     delete[] platformInfo.dateOfManufacture;
232     delete[] platformInfo.platformVersion;
233     delete[] platformInfo.operatingSystemVersion;
234     delete[] platformInfo.hardwareVersion;
235     delete[] platformInfo.firmwareVersion;
236     delete[] platformInfo.supportUrl;
237     delete[] platformInfo.systemTime;
238 }
239
240 void DeleteDeviceInfo()
241 {
242     delete[] deviceInfo.deviceName;
243     delete[] deviceInfo.specVersion;
244     OCFreeOCStringLL(deviceInfo.dataModelVersions);
245 }
246
247 void DuplicateString(char ** targetString, std::string sourceString)
248 {
249     *targetString = new char[sourceString.length() + 1];
250     strncpy(*targetString, sourceString.c_str(), (sourceString.length() + 1));
251 }
252
253 OCStackResult SetPlatformInfo(std::string platformID, std::string manufacturerName,
254         std::string manufacturerUrl, std::string modelNumber, std::string dateOfManufacture,
255         std::string platformVersion, std::string operatingSystemVersion,
256         std::string hardwareVersion, std::string firmwareVersion, std::string supportUrl,
257         std::string systemTime)
258 {
259     DuplicateString(&platformInfo.platformID, platformID);
260     DuplicateString(&platformInfo.manufacturerName, manufacturerName);
261     DuplicateString(&platformInfo.manufacturerUrl, manufacturerUrl);
262     DuplicateString(&platformInfo.modelNumber, modelNumber);
263     DuplicateString(&platformInfo.dateOfManufacture, dateOfManufacture);
264     DuplicateString(&platformInfo.platformVersion, platformVersion);
265     DuplicateString(&platformInfo.operatingSystemVersion, operatingSystemVersion);
266     DuplicateString(&platformInfo.hardwareVersion, hardwareVersion);
267     DuplicateString(&platformInfo.firmwareVersion, firmwareVersion);
268     DuplicateString(&platformInfo.supportUrl, supportUrl);
269     DuplicateString(&platformInfo.systemTime, systemTime);
270
271     return OC_STACK_OK;
272 }
273
274 OCStackResult SetDeviceInfo(std::string deviceName, std::string specVersion, std::string dataModelVersions)
275 {
276     DuplicateString(&deviceInfo.deviceName, deviceName);
277
278     if (!specVersion.empty())
279     {
280         DuplicateString(&deviceInfo.specVersion, specVersion);
281     }
282
283     if (!dataModelVersions.empty())
284     {
285         OCResourcePayloadAddStringLL(&deviceInfo.dataModelVersions, dataModelVersions.c_str());
286     }
287
288     return OC_STACK_OK;
289 }
290
291 int main()
292 {
293     // Create PlatformConfig object
294     PlatformConfig cfg {
295         OC::ServiceType::InProc,
296         OC::ModeType::Server,
297         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
298         0,         // Uses randomly available port
299         OC::QualityOfService::LowQos
300     };
301
302     OCPlatform::Configure(cfg);
303     std::cout << "Starting server & setting platform info\n";
304
305     OCStackResult result = SetPlatformInfo(platformId, manufacturerName, manufacturerLink,
306             modelNumber, dateOfManufacture, platformVersion, operatingSystemVersion,
307             hardwareVersion, firmwareVersion, supportLink, systemTime);
308
309     result = OCPlatform::registerPlatformInfo(platformInfo);
310
311     if (result != OC_STACK_OK)
312     {
313         std::cout << "Platform Registration failed\n";
314         return -1;
315     }
316
317     result = SetDeviceInfo(deviceName, specVersion, dataModelVersions);
318     OCResourcePayloadAddStringLL(&deviceInfo.types, "oic.wk.d");
319
320     result = OCPlatform::registerDeviceInfo(deviceInfo);
321
322     if (result != OC_STACK_OK)
323     {
324         std::cout << "Device Registration failed\n";
325         return -1;
326     }
327     try
328     {
329         using namespace OC::OCPlatform;
330         // Time to Live is 30 seconds
331         startPresence(30);
332
333         // Invoke createResource function of class light.
334         myLightResource.createResource();
335         std :: cout << "Creating first resource of type \"core.light\"" << std :: endl;
336
337         std :: cout << "Will start creating/deleting resources for presence in 10 seconds.\n";
338
339         sleep(10);
340
341         std :: cout << "\nCreating the second resource of type \"core.light\"" <<  std :: endl;
342         sleep(1);
343
344         myLightResource.createResource2();
345
346         std :: cout << "Stopping presence\n" << std :: endl;
347         sleep(1);
348         stopPresence();
349
350         std :: cout << "Restarting presence\n" << std :: endl;
351         sleep(1);
352
353         startPresence(30);
354
355         std :: cout << "Creating a third resource of type \"core.light\"\n" << std :: endl;
356         sleep(1);
357
358         myLightResource.createResource3();
359
360         std :: cout << "Creating two non-operational resources.\"\n" << std :: endl;
361         sleep(1);
362
363         createPresenceResources();
364
365         DeletePlatformInfo();
366         DeleteDeviceInfo();
367
368         // A condition variable will free the mutex it is given, then do a non-
369         // intensive block until 'notify' is called on it.  In this case, since we
370         // don't ever call cv.notify, this should be a non-processor intensive version
371         // of while(true);
372         std::mutex blocker;
373         std::condition_variable cv;
374         std::unique_lock<std::mutex> lock(blocker);
375         cv.wait(lock);
376     }
377     catch(OCException& e)
378     {
379         oclog() << "Exception in main: "<< e.what();
380     }
381
382     // No explicit call to stop the platform.
383     // When OCPlatform destructor is invoked, internally we do platform cleanup
384
385     return 0;
386 }
387