Implement [] and iteration for OCRepresentation
[platform/upstream/iotivity.git] / resource / examples / garageserver.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 using varous json types in the representation.
23 ///
24
25 #include <functional>
26
27 #include <pthread.h>
28 #include <mutex>
29 #include <condition_variable>
30
31 #include "OCPlatform.h"
32 #include "OCApi.h"
33
34 using namespace OC;
35 using namespace std;
36
37 // Forward declaring the entityHandler
38 OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request);
39
40 /// This class represents a single resource named 'lightResource'. This resource has
41
42 class GarageResource
43 {
44 public:
45     /// Access this property from a TB client
46     std::string m_name;
47     bool m_state;
48     std::string m_garageUri;
49     OCResourceHandle m_resourceHandle;
50     OCRepresentation m_garageRep;
51     ObservationIds m_interestedObservers;
52
53     // array of lights representation with in GarageResource
54     OCRepresentation m_lightRep;
55     std::vector<OCRepresentation> m_reps;
56     std::vector<std::vector<int>> m_hingeStates;
57
58 public:
59     /// Constructor
60     GarageResource(): m_name("John's Garage"), m_state(false), m_garageUri("/a/garage"),
61         m_hingeStates{{1,2,3},{4,5,6}}
62     {
63         // Initialize representation
64         m_garageRep.setUri(m_garageUri);
65
66         m_garageRep["state"] = m_state;
67         m_garageRep["name"] = m_name;
68
69         // For demonstration purpose we are setting x to nullptr here.
70         // In reality it may happen else where.
71         m_garageRep["nullAttribute"] = nullptr;
72
73         std::vector<bool> lightStates;
74         std::vector<int>  lightPowers;
75
76         for(int i = 0; i <= 9; i++)
77         {
78             lightStates.push_back(i % 2 == 0);
79             lightPowers.push_back(i);
80         }
81
82         m_lightRep["states"] = lightStates;
83         m_lightRep["powers"] = lightPowers;
84
85         // Storing another representation within a representation
86         m_garageRep["light"] = m_lightRep;
87
88         OCRepresentation rep1;
89         int value1 = 5;
90         rep1["key1"] = value1;
91         OCRepresentation rep2;
92         int value2 = 10;
93         rep2["key2"] = value2;
94
95         m_reps.push_back(rep1);
96         m_reps.push_back(rep2);
97
98         // storing array of representations
99         m_garageRep["reps"] =  m_reps;
100
101
102         // setting json string
103         std::string json = "{\"num\":10,\"rno\":23.5,\"aoa\":[[1,2],[3]],\"str\":\"john\",\
104 \"object\":{\"bl1\":false,\"ar\":[2,3]}, \"objects\":[{\"bl2\":true,\"nl\":null},{\"ar1\":[1,2]}]}";
105         m_garageRep["json"] = json;
106
107         m_garageRep["hinges"] = m_hingeStates;
108     }
109
110     /* Note that this does not need to be a member function: for classes you do not have
111     access to, you can accomplish this with a free function: */
112
113     /// This function internally calls registerResource API.
114     void createResource()
115     {
116         std::string resourceURI = m_garageUri; // URI of the resource
117         std::string resourceTypeName = "core.garage"; // resource type name.
118         std::string resourceInterface = DEFAULT_INTERFACE; // resource interface.
119
120         // OCResourceProperty is defined ocstack.h
121         uint8_t resourceProperty = OC_DISCOVERABLE | OC_OBSERVABLE;
122
123         // This will internally create and register the resource.
124         OCStackResult result = OCPlatform::registerResource(
125                                     m_resourceHandle, resourceURI, resourceTypeName,
126                                     resourceInterface, &entityHandler, resourceProperty);
127
128         if (OC_STACK_OK != result)
129         {
130             cout << "Resource creation was unsuccessful\n";
131         }
132     }
133
134     OCResourceHandle getHandle()
135     {
136         return m_resourceHandle;
137     }
138
139     // Puts representation.
140     // Gets values from the representation and
141     // updates the internal state
142     void put(OCRepresentation& rep)
143     {
144         try {
145             if (rep.getValue("state", m_state))
146             {
147                 cout << "\t\t\t\t" << "state: " << m_state << endl;
148             }
149             else
150             {
151                 cout << "\t\t\t\t" << "state not found in the representation" << endl;
152             }
153         }
154         catch (exception& e)
155         {
156             cout << e.what() << endl;
157         }
158
159     }
160
161     // gets the updated representation.
162     // Updates the representation with latest internal state before
163     // sending out.
164     OCRepresentation get()
165     {
166         m_garageRep["state"] = m_state;
167
168         return m_garageRep;
169     }
170
171 };
172
173 // Create the instance of the resource class (in this case instance of class 'GarageResource').
174 GarageResource myGarage;
175
176 OCStackResult sendResponse(std::shared_ptr<OCResourceRequest> pRequest)
177 {
178     auto pResponse = std::make_shared<OC::OCResourceResponse>();
179     pResponse->setRequestHandle(pRequest->getRequestHandle());
180     pResponse->setResourceHandle(pRequest->getResourceHandle());
181     pResponse->setResourceRepresentation(myGarage.get());
182     pResponse->setErrorCode(200);
183     pResponse->setResponseResult(OC_EH_OK);
184
185     return OCPlatform::sendResponse(pResponse);
186 }
187
188 OCEntityHandlerResult entityHandler(std::shared_ptr<OCResourceRequest> request)
189 {
190     cout << "\tIn Server CPP entity handler:\n";
191     OCEntityHandlerResult ehResult = OC_EH_ERROR;
192
193     if(request)
194     {
195         // Get the request type and request flag
196         std::string requestType = request->getRequestType();
197         int requestFlag = request->getRequestHandlerFlag();
198
199         if(requestFlag & RequestHandlerFlag::InitFlag)
200         {
201             cout << "\t\trequestFlag : Init\n";
202
203             // entity handler to perform resource initialization operations
204         }
205         if(requestFlag & RequestHandlerFlag::RequestFlag)
206         {
207             cout << "\t\trequestFlag : Request\n";
208
209             // If the request type is GET
210             if(requestType == "GET")
211             {
212                 cout << "\t\t\trequestType : GET\n";
213                 if(OC_STACK_OK == sendResponse(request))
214                 {
215                     ehResult = OC_EH_OK;
216                 }
217             }
218             else if(requestType == "PUT")
219             {
220                 cout << "\t\t\trequestType : PUT\n";
221                 OCRepresentation rep = request->getResourceRepresentation();
222                 // Do related operations related to PUT request
223                 myGarage.put(rep);
224                 if(OC_STACK_OK == sendResponse(request))
225                 {
226                     ehResult = OC_EH_OK;
227                 }
228             }
229             else if(requestType == "POST")
230             {
231                 // POST request operations
232             }
233             else if(requestType == "DELETE")
234             {
235                 // DELETE request operations
236             }
237         }
238         if(requestFlag & RequestHandlerFlag::ObserverFlag)
239         {
240             // OBSERVE operations
241         }
242     }
243     else
244     {
245         std::cout << "Request invalid" << std::endl;
246     }
247
248     return ehResult;
249 }
250
251 int main(int argc, char* argv[1])
252 {
253     // Create PlatformConfig object
254     PlatformConfig cfg {
255         OC::ServiceType::InProc,
256         OC::ModeType::Server,
257         "0.0.0.0", // By setting to "0.0.0.0", it binds to all available interfaces
258         0,         // Uses randomly available port
259         OC::QualityOfService::LowQos
260     };
261
262     OCPlatform::Configure(cfg);
263     try
264     {
265         // Invoke createResource function of class light.
266         myGarage.createResource();
267
268         // A condition variable will free the mutex it is given, then do a non-
269         // intensive block until 'notify' is called on it.  In this case, since we
270         // don't ever call cv.notify, this should be a non-processor intensive version
271         // of while(true);
272         std::mutex blocker;
273         std::condition_variable cv;
274         std::unique_lock<std::mutex> lock(blocker);
275         cv.wait(lock);
276     }
277     catch(OCException e)
278     {
279         //log(e.what());
280     }
281
282     // No explicit call to stop the OCPlatform
283     // When OCPlatform destructor is invoked, internally we do Platform cleanup
284
285     return 0;
286 }