CPP Collection
[platform/upstream/iotivity.git] / examples / simpleserver.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Corporation 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
30 #include "OCPlatform.h"
31 #include "OCApi.h"
32
33 using namespace OC;
34 using namespace std;
35
36 int gObservation = 0;
37
38 // Forward declaring the entityHandler
39 void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response);
40
41 /// This class represents a single resource named 'lightResource'. This resource has
42 /// two simple properties named 'state' and 'power'
43
44 class LightResource
45 {
46 public:
47     /// Access this property from a TB client
48     bool m_state;
49     int m_power;
50     OCResourceHandle m_resourceHandle;
51
52 public:
53     /// Constructor
54     LightResource(): m_state(false), m_power(0){}
55
56     /* Note that this does not need to be a member function: for classes you do not have
57     access to, you can accomplish this with a free function: */
58
59     /// This function internally calls registerResource API.
60     void createResource(OC::OCPlatform& platform)
61     {
62         std::string resourceURI = "/a/light"; // URI of the resource
63         std::string resourceTypeName = "core.light"; // resource type name. In this case, it is light
64         std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
65
66         // OCResourceProperty is defined ocstack.h
67         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
68
69         // This will internally create and register the resource.
70         OCStackResult result = platform.registerResource(
71                                     m_resourceHandle, resourceURI, resourceTypeName,
72                                     resourceInterface, &entityHandler, resourceProperty);
73
74         if (OC_STACK_OK != result)
75         {
76             cout << "Resource creation was unsuccessful\n";
77         }
78     }
79
80     OCResourceHandle getHandle()
81     {
82         return m_resourceHandle;
83     }
84
85     void setRepresentation(AttributeMap& attributeMap)
86     {
87         cout << "\t\t\t" << "Received representation: " << endl;
88         cout << "\t\t\t\t" << "power: " << attributeMap["power"][0] << endl;
89         cout << "\t\t\t\t" << "state: " << attributeMap["state"][0] << endl;
90
91         m_state = attributeMap["state"][0].compare("true") == 0;
92         m_power = std::stoi(attributeMap["power"][0]);
93     }
94
95     void getRepresentation(AttributeMap& attributeMap)
96     {
97         AttributeValues stateVal;
98         if(m_state)
99         {
100             stateVal.push_back("true");
101         }
102         else
103         {
104             stateVal.push_back("false");
105         }
106
107         AttributeValues powerVal;
108         powerVal.push_back(to_string(m_power));
109
110         attributeMap["state"] = stateVal;
111         attributeMap["power"] = powerVal;
112     }
113
114     void addType(const OC::OCPlatform& platform, const std::string& type) const
115     {
116         OCStackResult result = platform.bindTypeToResource(m_resourceHandle, type);
117         if (OC_STACK_OK != result)
118         {
119             cout << "Binding TypeName to Resource was unsuccessful\n";
120         }
121     }
122
123     void addInterface(const OC::OCPlatform& platform, const std::string& interface) const
124     {
125         OCStackResult result = platform.bindInterfaceToResource(m_resourceHandle, interface);
126         if (OC_STACK_OK != result)
127         {
128             cout << "Binding TypeName to Resource was unsuccessful\n";
129         }
130     }
131 };
132
133 // Create the instance of the resource class (in this case instance of class 'LightResource').
134 LightResource myLightResource;
135
136 // ChangeLightRepresentaion is an observation function,
137 // which notifies any changes to the resource to stack
138 // via notifyObservers
139 void * ChangeLightRepresentation (void *param)
140 {
141     // This function continuously monitors for the changes
142     while (1)
143     {
144         sleep (5);
145
146         if (gObservation)
147         {
148             // If under observation if there are any changes to the light resource
149             // we call notifyObservors
150             //
151             // For demostration we are changing the power value and notifying.
152             myLightResource.m_power += 10;
153
154             cout << "\nPower updated to : " << myLightResource.m_power << endl;
155             cout << "Notifying observers with resource handle: " << myLightResource.getHandle() << endl;
156
157             OCStackResult result = OCPlatform::notifyObservers(myLightResource.getHandle());
158
159             if(OC_STACK_NO_OBSERVERS == result)
160             {
161                 cout << "No More observers, stopping notifications" << endl;
162                 gObservation = 0;
163             }
164         }
165     }
166
167     return NULL;
168 }
169
170
171 // This is just a sample implementation of entity handler.
172 // Entity handler can be implemented in several ways by the manufacturer
173 void entityHandler(std::shared_ptr<OCResourceRequest> request, std::shared_ptr<OCResourceResponse> response)
174 {
175     cout << "\tIn Server CPP entity handler:\n";
176
177     if(request)
178     {
179         // Get the request type and request flag
180         std::string requestType = request->getRequestType();
181         RequestHandlerFlag requestFlag = request->getRequestHandlerFlag();
182
183         if(requestFlag == RequestHandlerFlag::InitFlag)
184         {
185             cout << "\t\trequestFlag : Init\n";
186
187             // entity handler to perform resource initialization operations
188         }
189         else if(requestFlag == RequestHandlerFlag::RequestFlag)
190         {
191             cout << "\t\trequestFlag : Request\n";
192
193             // If the request type is GET
194             if(requestType == "GET")
195             {
196                 cout << "\t\t\trequestType : GET\n";
197
198                 // Check for query params (if any)
199                 QueryParamsMap queryParamsMap = request->getQueryParameters();
200
201                 cout << "\t\t\tquery params: \n";
202                 for(QueryParamsMap::iterator it = queryParamsMap.begin(); it != queryParamsMap.end(); it++)
203                 {
204                     cout << "\t\t\t\t" << it->first << ":" << it->second << endl;
205                 }
206
207                 // Process query params and do required operations ..
208
209                 // Get the representation of this resource at this point and send it as response
210                 AttributeMap attributeMap;
211
212                 myLightResource.getRepresentation(attributeMap);
213
214                 if(response)
215                 {
216                     // TODO Error Code
217                     response->setErrorCode(200);
218                     response->setResourceRepresentation(attributeMap);
219                 }
220             }
221             else if(requestType == "PUT")
222             {
223                 cout << "\t\t\trequestType : PUT\n";
224
225                 // Check for query params (if any)
226                 QueryParamsMap queryParamsMap = request->getQueryParameters();
227
228                 // Check queryParamsMap and do required operations ..
229
230                 // Get the representation from the request
231                 AttributeMap attributeMap = request->getAttributeRepresentation();
232
233                 myLightResource.setRepresentation(attributeMap);
234
235                 // Do related operations related to PUT request
236
237                 myLightResource.getRepresentation(attributeMap);
238
239                 if(response)
240                 {
241                     response->setErrorCode(200);
242                     response->setResourceRepresentation(attributeMap);
243                 }
244             }
245             else if(requestType == "POST")
246             {
247                 // POST request operations
248             }
249             else if(requestType == "DELETE")
250             {
251                 // DELETE request operations
252             }
253         }
254         else if(requestFlag == RequestHandlerFlag::ObserverFlag)
255         {
256             pthread_t threadId;
257
258             cout << "\t\trequestFlag : Observer\n";
259             gObservation = 1;
260
261             static int startedThread = 0;
262
263             // Observation happens on a different thread in ChangeLightRepresentation function.
264             // If we have not created the thread already, we will create one here.
265             if(!startedThread)
266             {
267                 pthread_create (&threadId, NULL, ChangeLightRepresentation, (void *)NULL);
268                 startedThread = 1;
269             }
270
271         }
272     }
273     else
274     {
275         std::cout << "Request invalid" << std::endl;
276     }
277 }
278
279 int main()
280 {
281     // Create PlatformConfig object
282
283     PlatformConfig cfg;
284     cfg.ipAddress = "134.134.161.33";
285     cfg.port = 56832;
286     cfg.mode = ModeType::Server;
287     cfg.serviceType = ServiceType::InProc;
288
289     // Create a OCPlatform instance.
290     // Note: Platform creation is synchronous call.
291     try
292     {
293         OCPlatform platform(cfg);
294
295         // Invoke createResource function of class light.
296
297         myLightResource.createResource(platform);
298         myLightResource.addType(platform, std::string("core.brightlight"));
299         myLightResource.addInterface(platform, std::string("oc.mi.ll"));
300         // Perform app tasks
301         while(true)
302         {
303             // some tasks
304         }
305     }
306     catch(OCException e)
307     {
308         //log(e.what());
309     }
310
311
312     // No explicit call to stop the platform.
313     // When OCPlatform destructor is invoked, internally we do platform cleanup
314 }