Implementation of APIs for managing resource list and callback
[platform/upstream/iotivity.git] / service / simulator / src / simulator_resource_server.cpp
1 /******************************************************************
2  *
3  * Copyright 2015 Samsung Electronics 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 #include "simulator_resource_server.h"
22 #include "simulator_attribute_automation.h"
23 #include "simulator_logger.h"
24
25 SimulatorResourceServer::SimulatorResourceServer()
26     : m_resourceHandle(NULL),
27       m_property((OCResourceProperty) (OC_DISCOVERABLE | OC_OBSERVABLE)) {}
28
29 SimulatorResult SimulatorResourceServer::setURI(const std::string &uri)
30 {
31     if (m_resourceHandle)
32         return SIMULATOR_OPERATION_NOT_ALLOWED;
33     m_uri = uri;
34     return SIMULATOR_SUCCESS;
35 }
36
37 std::string SimulatorResourceServer::getURI() const
38 {
39     return m_uri;
40 }
41
42 SimulatorResult SimulatorResourceServer::setResourceType(const std::string &resourceType)
43 {
44     if (m_resourceHandle)
45         return SIMULATOR_OPERATION_NOT_ALLOWED;
46     m_resourceType = resourceType;
47     return SIMULATOR_SUCCESS;
48 }
49
50 std::string SimulatorResourceServer::getResourceType() const
51 {
52     return m_resourceType;
53 }
54
55 SimulatorResult SimulatorResourceServer::setInterfaceType(const std::string &interfaceType)
56 {
57     if (m_resourceHandle)
58         return SIMULATOR_OPERATION_NOT_ALLOWED;
59     m_interfaceType = interfaceType;
60     return SIMULATOR_SUCCESS;
61 }
62
63 std::string SimulatorResourceServer::getInterfaceType() const
64 {
65     return m_interfaceType;
66 }
67
68 void SimulatorResourceServer::setName(const std::string &name)
69 {
70     m_name = name;
71 }
72
73 std::string SimulatorResourceServer::getName() const
74 {
75     return m_name;
76 }
77
78 SimulatorResult SimulatorResourceServer::setObservable(bool state)
79 {
80     if (m_resourceHandle)
81         return SIMULATOR_OPERATION_NOT_ALLOWED;
82
83     if (true == state)
84         m_property = static_cast<OCResourceProperty>(m_property | OC_OBSERVABLE);
85     else
86         m_property = static_cast<OCResourceProperty>(m_property ^ OC_OBSERVABLE);
87
88     return SIMULATOR_SUCCESS;
89 }
90
91 bool SimulatorResourceServer::isObservable() const
92 {
93     return (m_property & OC_OBSERVABLE);
94 }
95
96 SimulatorResult SimulatorResourceServer::start()
97 {
98     if (m_resourceHandle)
99         return SIMULATOR_RESOURCE_ALREADY_REGISTERED;
100
101     if (m_uri.empty() || m_resourceType.empty() || m_interfaceType.empty()
102         || !m_callback)
103     {
104         return SIMULATOR_BAD_INPUT;
105     }
106
107     OCStackResult result = OC::OCPlatform::registerResource(m_resourceHandle,
108                            m_uri,
109                            m_resourceType,
110                            m_interfaceType,
111                            std::bind(&SimulatorResourceServer::entityHandler,
112                                      this, std::placeholders::_1), m_property);
113
114     if (OC_STACK_OK != result)
115         return SIMULATOR_ERROR;
116     return SIMULATOR_SUCCESS;
117 }
118
119 SimulatorResult SimulatorResourceServer::stop()
120 {
121     if (nullptr == m_resourceHandle)
122     {
123         SIM_LOG(ILogger::ERROR, "Resourece is not registered!");
124         return SIMULATOR_RESOURCE_NOT_REGISTERED;
125     }
126
127     OCStackResult result = OC::OCPlatform::unregisterResource(m_resourceHandle);
128     if (OC_STACK_OK != result)
129         return SIMULATOR_ERROR;
130
131     m_resourceHandle = nullptr;
132     return SIMULATOR_SUCCESS;
133 }
134
135 void SimulatorResourceServer::setRange(const std::string &attrName, const int min, const int max)
136 {
137     m_resModel.setRange(attrName, min, max);
138 }
139
140 void SimulatorResourceServer::setUpdateInterval(const std::string &attrName, int interval)
141 {
142     m_resModel.setUpdateInterval(attrName, interval);
143 }
144
145 void SimulatorResourceServer::removeAttribute(const std::string &attrName)
146 {
147     m_resModel.removeAttribute(attrName);
148     notifyListOfObservers();
149 }
150
151 void SimulatorResourceServer::updateAttributeFromAllowedValues(const std::string &attrName,
152         const int allowedValueIndex)
153 {
154     m_resModel.updateAttributeFromAllowedValues(attrName, allowedValueIndex);
155     notifyListOfObservers();
156 }
157
158 SimulatorResourceModel SimulatorResourceServer::getModel() const
159 {
160     return m_resModel;
161 }
162
163 void SimulatorResourceServer::setModelChangeCallback(ResourceModelChangedCB callback)
164 {
165     m_callback = callback;
166 }
167
168 SimulatorResult SimulatorResourceServer::startUpdateAutomation(AutomationType type,
169         updateCompleteCallback callback, int &id)
170 {
171     return m_updateAutomationMgr.startResourceAutomation(this, id, callback, type);
172 }
173
174 SimulatorResult SimulatorResourceServer::startUpdateAutomation(const std::string &attrName,
175         AutomationType type, updateCompleteCallback callback, int &id)
176 {
177     return m_updateAutomationMgr.startAttributeAutomation(this, attrName, id, callback, type);
178 }
179
180 std::vector<int> SimulatorResourceServer::getResourceAutomationIds()
181 {
182     return m_updateAutomationMgr.getResourceAutomationIds();
183 }
184
185 std::vector<int> SimulatorResourceServer::getAttributeAutomationIds()
186 {
187     return m_updateAutomationMgr.getAttributeAutomationIds();
188 }
189
190 void SimulatorResourceServer::stopUpdateAutomation(const int id)
191 {
192     m_updateAutomationMgr.stop(id);
193 }
194
195 OC::OCRepresentation SimulatorResourceServer::getOCRepresentation()
196 {
197     return m_resModel.getOCRepresentation();
198 }
199
200 bool SimulatorResourceServer::modifyResourceModel(OC::OCRepresentation &ocRep)
201 {
202     bool status = m_resModel.update(ocRep);
203     if (true == status)
204     {
205         notifyListOfObservers();
206     }
207     return status;
208 }
209
210 OCEntityHandlerResult SimulatorResourceServer::entityHandler(std::shared_ptr<OC::OCResourceRequest>
211         request)
212 {
213     OCEntityHandlerResult errCode = OC_EH_ERROR;
214     if (!request)
215     {
216         return OC_EH_ERROR;
217     }
218
219     if (OC::RequestHandlerFlag::RequestFlag & request->getRequestHandlerFlag())
220     {
221         auto response = std::make_shared<OC::OCResourceResponse>();
222         response->setRequestHandle(request->getRequestHandle());
223         response->setResourceHandle(request->getResourceHandle());
224
225         if ("GET" == request->getRequestType())
226         {
227             SIM_LOG(ILogger::INFO, "[" << m_uri << "] GET request received");
228             response->setErrorCode(200);
229             response->setResponseResult(OC_EH_OK);
230             response->setResourceRepresentation(getOCRepresentation());
231
232             if (OC_STACK_OK == OC::OCPlatform::sendResponse(response))
233             {
234                 errCode = OC_EH_OK;
235             }
236         }
237         else if ("PUT" == request->getRequestType())
238         {
239             SIM_LOG(ILogger::INFO, "[" << m_uri << "] PUT request received");
240             OC::OCRepresentation rep = request->getResourceRepresentation();
241             if (true == modifyResourceModel(rep))
242             {
243                 response->setErrorCode(200);
244                 response->setResponseResult(OC_EH_OK);
245                 response->setResourceRepresentation(getOCRepresentation());
246             }
247             else
248             {
249                 response->setErrorCode(400);
250                 response->setResponseResult(OC_EH_ERROR);
251             }
252
253             if (OC_STACK_OK == OC::OCPlatform::sendResponse(response))
254             {
255                 errCode = OC_EH_OK;
256             }
257         }
258         else if ("POST" == request->getRequestType())
259         {
260             SIM_LOG(ILogger::INFO, "[" << m_uri << "] POST request received");
261             OC::OCRepresentation rep = request->getResourceRepresentation();
262             if (true == modifyResourceModel(rep))
263             {
264                 response->setErrorCode(200);
265                 response->setResponseResult(OC_EH_OK);
266                 response->setResourceRepresentation(getOCRepresentation());
267             }
268             else
269             {
270                 response->setErrorCode(400);
271                 response->setResponseResult(OC_EH_ERROR);
272             }
273
274             if (OC_STACK_OK == OC::OCPlatform::sendResponse(response))
275             {
276                 errCode = OC_EH_OK;
277             }
278         }
279         else if ("DELETE" == request->getRequestType())
280         {
281             SIM_LOG(ILogger::INFO, "[" << m_uri << "] DELETE request received!");
282             OC::OCRepresentation rep = request->getResourceRepresentation();
283
284             // DELETE request handling not supported right now
285             response->setErrorCode(400);
286             response->setResponseResult(OC_EH_ERROR);
287             if (OC_STACK_OK == OC::OCPlatform::sendResponse(response))
288             {
289                 errCode = OC_EH_OK;
290             }
291         }
292         else
293         {
294             SIM_LOG(ILogger::INFO, "[" << m_uri << "] UNKNOWN type request received");
295             response->setResponseResult(OC_EH_ERROR);
296             OC::OCPlatform::sendResponse(response);
297             errCode = OC_EH_ERROR;
298         }
299     }
300
301     if (OC::RequestHandlerFlag::ObserverFlag & request->getRequestHandlerFlag())
302     {
303         if (false == isObservable())
304         {
305             SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE request received");
306             SIM_LOG(ILogger::INFO, "[" << m_uri << "] Sending error as resource is in unobservable state");
307             return OC_EH_ERROR;
308         }
309
310         OC::ObservationInfo observationInfo = request->getObservationInfo();
311         if (OC::ObserveAction::ObserveRegister == observationInfo.action)
312         {
313             SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE REGISTER request received");
314             m_interestedObservers.push_back(observationInfo.obsId);
315         }
316         else if (OC::ObserveAction::ObserveUnregister == observationInfo.action)
317         {
318             SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE UNREGISTER request received");
319             m_interestedObservers.erase(std::remove(m_interestedObservers.begin(),
320                                                     m_interestedObservers.end(),
321                                                     observationInfo.obsId),
322                                         m_interestedObservers.end());
323         }
324         errCode = OC_EH_OK;
325     }
326
327     return errCode;
328 }
329
330 void SimulatorResourceServer::notifyListOfObservers ()
331 {
332     if (!m_resourceHandle)
333     {
334         return;
335     }
336
337     if (m_interestedObservers.size())
338     {
339         std::shared_ptr<OC::OCResourceResponse> resourceResponse =
340         {std::make_shared<OC::OCResourceResponse>()};
341
342         resourceResponse->setErrorCode(200);
343         resourceResponse->setResponseResult(OC_EH_OK);
344         resourceResponse->setResourceRepresentation(getOCRepresentation(), OC::DEFAULT_INTERFACE);
345
346         SIM_LOG(ILogger::INFO, "[" << m_uri << "] Sending notification to all observers" << m_uri);
347         OC::OCPlatform::notifyListOfObservers(m_resourceHandle, m_interestedObservers, resourceResponse);
348     }
349
350     if (m_callback)
351     {
352         m_callback(m_uri, m_resModel);
353     }
354 }