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