Modified sample apps for easier and automated testing.
[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 <functional>
27
28 #include <pthread.h>
29 #include <array>
30 #include <mutex>
31 #include <condition_variable>
32
33 #include "OCPlatform.h"
34 #include "OCApi.h"
35
36 using namespace OC;
37 using namespace std;
38
39 #define numPresenceResources (2)
40
41 // Forward declaring the entityHandler
42 OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
43
44 /// This class represents a single resource named 'lightResource'. This resource has
45 /// two simple properties named 'state' and 'power'
46
47 class LightResource
48 {
49 public:
50     /// Access this property from a TB client
51     bool m_state;
52     int m_power;
53     std::string m_lightUri;
54     std::string m_lightUri2;
55     std::string m_lightUri3;
56     OCResourceHandle m_resourceHandle;
57     OCResourceHandle m_resourceHandle2;
58     OCResourceHandle m_resourceHandle3;
59
60 public:
61     /// Constructor
62     LightResource(): m_state(false), m_power(0), m_lightUri("/a/light"),
63                      m_lightUri2("/a/light2"),m_lightUri3("/a/light3") {}
64
65     /* Note that this does not need to be a member function: for classes you do not have
66     access to, you can accomplish this with a free function: */
67
68     /// This function internally calls registerResource API.
69     void createResource()
70     {
71         std::string resourceURI = m_lightUri; // URI of the resource
72         std::string resourceTypeName = "core.light"; // resource type name.
73         std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
74
75         // OCResourceProperty is defined ocstack.h
76         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
77
78         // This will internally create and register the resource.
79         OCStackResult result = OCPlatform::registerResource(
80                                     m_resourceHandle, resourceURI, resourceTypeName,
81                                     resourceInterface, &entityHandler, resourceProperty);
82
83         if (OC_STACK_OK != result)
84         {
85             cout << "Resource creation was unsuccessful\n";
86         }
87     }
88
89     /// This function internally calls registerResource API.
90     void createResource2()
91     {
92         std::string resourceURI = m_lightUri2; // URI of the resource
93         std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light
94         std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
95
96         // OCResourceProperty is defined ocstack.h
97         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
98
99         // This will internally create and register the resource.
100         OCStackResult result = OCPlatform::registerResource(
101                                     m_resourceHandle2, resourceURI, resourceTypeName,
102                                     resourceInterface, &entityHandler, resourceProperty);
103
104         if (OC_STACK_OK != result)
105         {
106             cout << "Resource creation was unsuccessful\n";
107         }
108     }
109
110     void createResource3()
111     {
112         std::string resourceURI = m_lightUri3; // URI of the resource
113         std::string resourceTypeName = "core.light";
114         std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
115
116         // OCResourceProperty is defined ocstack.h
117         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
118
119         // This will internally create and register the resource.
120         OCStackResult result = OCPlatform::registerResource(
121                                     m_resourceHandle3, resourceURI, resourceTypeName,
122                                     resourceInterface, &entityHandler, resourceProperty);
123
124         if (OC_STACK_OK != result)
125         {
126             cout << "Resource creation was unsuccessful\n";
127         }
128     }
129
130     OCResourceHandle getHandle()
131     {
132         return m_resourceHandle;
133     }
134
135     void addType(const std::string& type) const
136     {
137         OCStackResult result = OC::OCPlatform::bindTypeToResource(m_resourceHandle, type);
138         if (OC_STACK_OK != result)
139         {
140             cout << "Binding TypeName to Resource was unsuccessful\n";
141         }
142     }
143
144     void addInterface(const std::string& interface) const
145     {
146         OCStackResult result = OC::OCPlatform::bindInterfaceToResource(m_resourceHandle, interface);
147         if (OC_STACK_OK != result)
148         {
149             cout << "Binding TypeName to Resource was unsuccessful\n";
150         }
151     }
152
153 };
154
155 void createPresenceResources()
156 {
157     std::array<std::string, numPresenceResources> resourceURI { {
158         "/a/fan",
159         "/a/led" } };
160     std::array<std::string, numPresenceResources> resourceTypeName { {
161         "core.fan",
162         "core.led" } };
163
164     std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
165     OCResourceHandle handle;
166     // OCResourceProperty is defined ocstack.h
167     uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
168
169     // This will internally create and register the resource.
170     OCStackResult result = OC_STACK_OK;
171     for(int i=0; i<numPresenceResources; i++)
172     {
173         result = OCPlatform::registerResource(handle,
174                 resourceURI.at(i), resourceTypeName.at(i), resourceInterface,
175                 &entityHandler, resourceProperty);
176         if (result != OC_STACK_OK)
177         {
178             cout << "Resource creation was unsuccessful with resource URI "
179                     << resourceURI.at(i);
180         }
181     }
182 }
183
184 // Create the instance of the resource class (in this case instance of class 'LightResource').
185 LightResource myLightResource;
186
187 OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
188 {
189     cout << "\tIn Server CPP entity handler:\n";
190     return OC_EH_OK;
191 }
192
193 int main()
194 {
195     // Create PlatformConfig object
196     PlatformConfig cfg {
197         OC::ServiceType::InProc,
198         OC::ModeType::Server,
199         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
200         0,         // Uses randomly available port
201         OC::QualityOfService::LowQos
202     };
203
204     OCPlatform::Configure(cfg);
205     try
206     {
207         using namespace OC::OCPlatform;
208         // Time to Live is 30 seconds
209         startPresence(30);
210
211         // Invoke createResource function of class light.
212         myLightResource.createResource();
213         std :: cout << "Creating first resource of type \"core.light\"" << std :: endl;
214
215         std :: cout << "Will start creating/deleting resources for presence in 10 seconds.\n";
216
217         sleep(10);
218
219         std :: cout << "\nCreating the second resource of type \"core.light\"" <<  std :: endl;
220         sleep(1);
221
222         myLightResource.createResource2();
223
224         std :: cout << "Stopping presence\n" << std :: endl;
225         sleep(1);
226         stopPresence();
227
228         std :: cout << "Restarting presence\n" << std :: endl;
229         sleep(1);
230
231         startPresence(30);
232
233         std :: cout << "Creating a third resource of type \"core.light\"\n" << std :: endl;
234         sleep(1);
235
236         myLightResource.createResource3();
237
238         std :: cout << "Creating two non-operational resources.\"\n" << std :: endl;
239         sleep(1);
240
241         createPresenceResources();
242
243         // A condition variable will free the mutex it is given, then do a non-
244         // intensive block until 'notify' is called on it.  In this case, since we
245         // don't ever call cv.notify, this should be a non-processor intensive version
246         // of while(true);
247         std::mutex blocker;
248         std::condition_variable cv;
249         std::unique_lock<std::mutex> lock(blocker);
250         cv.wait(lock);
251     }
252     catch(OCException& e)
253     {
254         oclog() << "Exception in main: "<< e.what();
255     }
256
257     // No explicit call to stop the platform.
258     // When OCPlatform destructor is invoked, internally we do platform cleanup
259
260     return 0;
261 }
262