1 /******************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
21 #include "simulator_single_resource_impl.h"
22 #include "simulator_utils.h"
23 #include "simulator_logger.h"
26 #define TAG "SIM_SINGLE_RESOURCE"
28 SimulatorSingleResourceImpl::SimulatorSingleResourceImpl()
29 : m_type(SimulatorResource::Type::SINGLE_RESOURCE),
30 m_interfaces {OC::DEFAULT_INTERFACE},
31 m_resourceHandle(NULL)
33 m_property = static_cast<OCResourceProperty>(OC_DISCOVERABLE | OC_OBSERVABLE);
36 std::string SimulatorSingleResourceImpl::getName() const
41 SimulatorResource::Type SimulatorSingleResourceImpl::getType() const
46 std::string SimulatorSingleResourceImpl::getURI() const
51 std::string SimulatorSingleResourceImpl::getResourceType() const
53 return m_resourceType;
56 std::vector<std::string> SimulatorSingleResourceImpl::getInterface() const
61 void SimulatorSingleResourceImpl::setInterface(const std::vector<std::string> &interfaces)
63 m_interfaces = interfaces;
66 void SimulatorSingleResourceImpl::setName(const std::string &name)
68 VALIDATE_INPUT(name.empty(), "Name is empty!")
70 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
73 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
74 "Name can not be set when resource is started!");
80 void SimulatorSingleResourceImpl::setURI(const std::string &uri)
82 VALIDATE_INPUT(uri.empty(), "Uri is empty!")
84 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
87 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
88 "URI can not be set when resource is started!");
94 void SimulatorSingleResourceImpl::setResourceType(const std::string &resourceType)
96 VALIDATE_INPUT(resourceType.empty(), "Resource type is empty!")
98 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
101 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
102 "Resource type can not be set when resource is started!");
105 m_resourceType = resourceType;
108 void SimulatorSingleResourceImpl::addInterface(std::string interfaceType)
110 VALIDATE_INPUT(interfaceType.empty(), "Interface type is empty!")
112 if (interfaceType == OC::LINK_INTERFACE
113 || interfaceType == OC::BATCH_INTERFACE
114 || interfaceType == OC::GROUP_INTERFACE)
116 throw NoSupportException("Single type resource does not support this interface!");
119 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
120 if (m_resourceHandle)
122 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
123 "Interface type can not be set when resource is started!");
126 auto found = std::find(m_interfaces.begin(), m_interfaces.end(), interfaceType);
127 if (found != m_interfaces.end())
128 m_interfaces.push_back(interfaceType);
131 void SimulatorSingleResourceImpl::setObservable(bool state)
133 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
134 if (m_resourceHandle)
136 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
137 "Observation state can not be changed when resource is started!");
141 m_property = static_cast<OCResourceProperty>(m_property | OC_OBSERVABLE);
143 m_property = static_cast<OCResourceProperty>(m_property ^ OC_OBSERVABLE);
146 void SimulatorSingleResourceImpl::setObserverCallback(ObserverCallback callback)
148 VALIDATE_CALLBACK(callback)
149 m_observeCallback = callback;
152 bool SimulatorSingleResourceImpl::isObservable()
154 return (m_property & OC_OBSERVABLE);
157 bool SimulatorSingleResourceImpl::isStarted()
159 return (nullptr != m_resourceHandle);
162 void SimulatorSingleResourceImpl::start()
164 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
165 if (m_resourceHandle)
167 SIM_LOG(ILogger::INFO, "[" << m_name << "] " << "Resource already registered!")
170 if (m_uri.empty() || m_resourceType.empty())
172 throw SimulatorException(SIMULATOR_ERROR, "Found incomplete data to start resource!");
175 typedef OCStackResult (*RegisterResource)(OCResourceHandle &, std::string &, const std::string &,
176 const std::string &, OC::EntityHandler, uint8_t);
178 invokeocplatform(static_cast<RegisterResource>(OC::OCPlatform::registerResource),
179 m_resourceHandle, m_uri, m_resourceType, m_interfaces[0],
180 std::bind(&SimulatorSingleResourceImpl::handleRequests,
181 this, std::placeholders::_1), m_property);
183 for (size_t index = 1; m_interfaces.size() > 1 && index < m_interfaces.size(); index++)
185 typedef OCStackResult (*bindInterfaceToResource)(const OCResourceHandle &,
186 const std::string &);
190 invokeocplatform(static_cast<bindInterfaceToResource>(
191 OC::OCPlatform::bindInterfaceToResource), m_resourceHandle,
192 m_interfaces[index]);
194 catch (SimulatorException &e)
202 void SimulatorSingleResourceImpl::stop()
204 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
205 if (!m_resourceHandle)
208 // Stop all the update automation of this resource
209 m_updateAutomationMgr.stopAll();
211 // Clear all the observers
212 removeAllObservers();
214 // Unregister the resource from stack
215 typedef OCStackResult (*UnregisterResource)(const OCResourceHandle &);
217 invokeocplatform(static_cast<UnregisterResource>(OC::OCPlatform::unregisterResource),
220 m_resourceHandle = nullptr;
223 std::vector<ObserverInfo> SimulatorSingleResourceImpl::getObserversList()
225 return m_observersList;
228 void SimulatorSingleResourceImpl::notify(int id, SimulatorResourceModel &resModel)
230 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
231 if (!m_resourceHandle)
234 std::shared_ptr<OC::OCResourceResponse> resourceResponse =
235 {std::make_shared<OC::OCResourceResponse>()};
237 resourceResponse->setErrorCode(200);
238 resourceResponse->setResponseResult(OC_EH_OK);
239 resourceResponse->setResourceRepresentation(resModel.getOCRepresentation(),
240 OC::DEFAULT_INTERFACE);
242 OC::ObservationIds observers;
243 observers.push_back(id);
245 typedef OCStackResult (*NotifyListOfObservers)(OCResourceHandle, OC::ObservationIds &,
246 const std::shared_ptr<OC::OCResourceResponse>);
248 invokeocplatform(static_cast<NotifyListOfObservers>(OC::OCPlatform::notifyListOfObservers),
249 m_resourceHandle, observers, resourceResponse);
252 void SimulatorSingleResourceImpl::notifyAll(SimulatorResourceModel &resModel)
254 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
255 if (!m_resourceHandle)
258 if (!m_observersList.size())
261 std::shared_ptr<OC::OCResourceResponse> resourceResponse =
262 {std::make_shared<OC::OCResourceResponse>()};
264 resourceResponse->setErrorCode(200);
265 resourceResponse->setResponseResult(OC_EH_OK);
266 resourceResponse->setResourceRepresentation(resModel.getOCRepresentation(),
267 OC::DEFAULT_INTERFACE);
269 OC::ObservationIds observers;
270 for (auto &observer : m_observersList)
271 observers.push_back(observer.id);
273 typedef OCStackResult (*NotifyListOfObservers)(OCResourceHandle, OC::ObservationIds &,
274 const std::shared_ptr<OC::OCResourceResponse>);
276 invokeocplatform(static_cast<NotifyListOfObservers>(OC::OCPlatform::notifyListOfObservers),
277 m_resourceHandle, observers, resourceResponse);
280 void SimulatorSingleResourceImpl::notify(int id)
282 notify(id, m_resModel);
285 void SimulatorSingleResourceImpl::notifyAll()
287 notifyAll(m_resModel);
290 bool SimulatorSingleResourceImpl::getAttribute(const std::string &attrName,
291 SimulatorResourceModel::Attribute &attribute)
293 VALIDATE_INPUT(attrName.empty(), "Attribute name is empty!")
295 std::lock_guard<std::mutex> lock(m_modelLock);
296 return m_resModel.getAttribute(attrName, attribute);
299 void SimulatorSingleResourceImpl::addAttribute(const SimulatorResourceModel::Attribute &attribute,
302 std::lock_guard<std::mutex> lock(m_modelLock);
303 if (m_resModel.containsAttribute(attribute.getName()))
304 throw SimulatorException(SIMULATOR_ERROR, "Attribute exist with same name!");
306 if (!m_resModel.add(attribute))
307 throw SimulatorException(SIMULATOR_ERROR, "Failed to add attribute!");
309 if (notify && isStarted())
313 bool SimulatorSingleResourceImpl::getAttributeProperty(const std::string &attrName,
314 SimulatorResourceModel::AttributeProperty &property)
316 VALIDATE_INPUT(attrName.empty(), "Attribute name is empty!")
318 std::lock_guard<std::mutex> lock(m_modelLock);
319 return m_resModel.getAttributeProperty(attrName, property);
322 bool SimulatorSingleResourceImpl::setAttributeProperty(const std::string &attrName,
323 const SimulatorResourceModel::AttributeProperty &property)
325 VALIDATE_INPUT(attrName.empty(), "Attribute name is empty!")
327 std::lock_guard<std::mutex> lock(m_modelLock);
328 return m_resModel.setAttributeProperty(attrName, property);
331 bool SimulatorSingleResourceImpl::updateAttributeValue(
332 const SimulatorResourceModel::Attribute &attribute,
335 std::lock_guard<std::mutex> lock(m_modelLock);
336 if (m_resModel.updateValue(attribute))
338 if (notify && isStarted())
346 bool SimulatorSingleResourceImpl::removeAttribute(const std::string &attrName, bool notify)
348 VALIDATE_INPUT(attrName.empty(), "Attribute name is empty!")
350 std::lock_guard<std::mutex> lock(m_modelLock);
351 if (m_resModel.removeAttribute(attrName))
353 if (notify && isStarted())
361 SimulatorResourceModel SimulatorSingleResourceImpl::getResourceModel()
363 std::lock_guard<std::mutex> lock(m_modelLock);
367 void SimulatorSingleResourceImpl::setModelChangeCallback(ResourceModelChangedCallback callback)
369 VALIDATE_CALLBACK(callback)
370 m_modelCallback = callback;
373 int SimulatorSingleResourceImpl::startResourceUpdation(AutomationType type,
374 int updateInterval, updateCompleteCallback callback)
376 VALIDATE_CALLBACK(callback)
378 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
379 if (!m_resourceHandle)
380 throw SimulatorException(SIMULATOR_NO_RESOURCE, "Resource is not registered!");
382 return m_updateAutomationMgr.startResourceAutomation(this, type, updateInterval, callback);
385 int SimulatorSingleResourceImpl::startAttributeUpdation(const std::string &attrName,
386 AutomationType type, int updateInterval, updateCompleteCallback callback)
388 VALIDATE_CALLBACK(callback)
390 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
391 if (!m_resourceHandle)
392 throw SimulatorException(SIMULATOR_NO_RESOURCE, "Resource is not registered!");
394 return m_updateAutomationMgr.startAttributeAutomation(this, attrName, type,
395 updateInterval, callback);
398 std::vector<int> SimulatorSingleResourceImpl::getResourceUpdationIds()
400 return m_updateAutomationMgr.getResourceAutomationIds();
403 std::vector<int> SimulatorSingleResourceImpl::getAttributeUpdationIds()
405 return m_updateAutomationMgr.getAttributeAutomationIds();
408 void SimulatorSingleResourceImpl::stopUpdation(const int id)
410 m_updateAutomationMgr.stop(id);
413 void SimulatorSingleResourceImpl::setResourceModel(const SimulatorResourceModel &resModel)
415 std::lock_guard<std::mutex> lock(m_modelLock);
416 m_resModel = resModel;
419 void SimulatorSingleResourceImpl::setPutErrorResponseModel(const SimulatorResourceModel &resModel)
421 m_putErrorResModel = resModel;
424 void SimulatorSingleResourceImpl::setPostErrorResponseModel(const SimulatorResourceModel &resModel)
426 m_postErrorResModel = resModel;
429 void SimulatorSingleResourceImpl::notifyApp(SimulatorResourceModel &resModel)
433 m_modelCallback(m_uri, resModel);
437 void SimulatorSingleResourceImpl::notifyApp()
439 notifyApp(m_resModel);
442 bool SimulatorSingleResourceImpl::updateResourceModel(OC::OCRepresentation &ocRep,
443 SimulatorResourceModel &resModel)
445 std::lock_guard<std::mutex> lock(m_modelLock);
446 if (m_resModel.update(ocRep))
448 resModel = m_resModel;
454 OCEntityHandlerResult SimulatorSingleResourceImpl::handleRequests(
455 std::shared_ptr<OC::OCResourceRequest> request)
457 OCEntityHandlerResult errCode = OC_EH_ERROR;
461 if (OC::RequestHandlerFlag::RequestFlag & request->getRequestHandlerFlag())
464 OC::OCRepresentation rep = request->getResourceRepresentation();
465 std::string payload = getPayloadString(rep);
466 SIM_LOG(ILogger::INFO, "[" << m_name << "] " << request->getRequestType()
467 << " request received. \n**Payload details**\n" << payload)
470 // Handover the request to appropriate interface handler
471 std::string interfaceType(OC::DEFAULT_INTERFACE);
472 OC::QueryParamsMap queryParams = request->getQueryParameters();
473 if (queryParams.end() != queryParams.find("if"))
474 interfaceType = queryParams["if"];
476 std::shared_ptr<OC::OCResourceResponse> response;
477 if (interfaceType == OC::DEFAULT_INTERFACE)
479 response = requestOnBaseLineInterface(request);
482 // Send response if the request handled by resource
485 if (OC_STACK_OK != OC::OCPlatform::sendResponse(response))
490 SIM_LOG(ILogger::ERROR, "[" << m_name << "] " << "Unsupported request received!")
495 if (OC::RequestHandlerFlag::ObserverFlag & request->getRequestHandlerFlag())
497 if (false == isObservable())
499 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE request received")
500 SIM_LOG(ILogger::INFO, "[" << m_uri << "] Sending error as resource is in unobservable state")
504 OC::ObservationInfo observationInfo = request->getObservationInfo();
505 if (OC::ObserveAction::ObserveRegister == observationInfo.action)
507 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE REGISTER request received");
508 addObserver(observationInfo);
510 else if (OC::ObserveAction::ObserveUnregister == observationInfo.action)
512 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE UNREGISTER request received");
513 removeObserver(observationInfo);
521 std::shared_ptr<OC::OCResourceResponse> SimulatorSingleResourceImpl::requestOnBaseLineInterface(
522 std::shared_ptr<OC::OCResourceRequest> request)
524 std::shared_ptr<OC::OCResourceResponse> response;
525 if ("GET" == request->getRequestType())
527 OC::OCRepresentation ocRep = m_resModel.getOCRepresentation();
528 response = std::make_shared<OC::OCResourceResponse>();
529 response->setErrorCode(200);
530 response->setResponseResult(OC_EH_OK);
531 response->setResourceRepresentation(ocRep);
532 std::string resPayload = getPayloadString(ocRep);
533 SIM_LOG(ILogger::INFO, "[" << m_uri <<
534 "] Sending response for GET request. \n**Payload details**" << resPayload)
536 else if ("PUT" == request->getRequestType()
537 || "POST" == request->getRequestType())
539 OC::OCRepresentation requestRep = request->getResourceRepresentation();
540 SimulatorResourceModel resModel;
541 if (true == updateResourceModel(requestRep, resModel))
546 response = std::make_shared<OC::OCResourceResponse>();
547 response->setErrorCode(200);
548 response->setResponseResult(OC_EH_OK);
549 response->setResourceRepresentation(resModel.getOCRepresentation());
550 std::string resPayload = getPayloadString(resModel.getOCRepresentation());
551 SIM_LOG(ILogger::INFO, "[" << m_uri <<
552 "] Sending response for " << request->getRequestType() << " request. \n**Payload details**" <<
557 response = std::make_shared<OC::OCResourceResponse>();
558 response->setErrorCode(400);
559 response->setResponseResult(OC_EH_ERROR);
560 if ("PUT" == request->getRequestType())
562 if (m_putErrorResModel.getOCRepresentation().empty())
563 response->setResourceRepresentation(m_resModel.getOCRepresentation());
565 response->setResourceRepresentation(m_putErrorResModel.getOCRepresentation());
569 if (m_postErrorResModel.getOCRepresentation().empty())
570 response->setResourceRepresentation(m_resModel.getOCRepresentation());
572 response->setResourceRepresentation(m_postErrorResModel.getOCRepresentation());
576 else if ("DELETE" == request->getRequestType())
578 // TODO: Handle this request
583 response->setRequestHandle(request->getRequestHandle());
584 response->setResourceHandle(request->getResourceHandle());
590 void SimulatorSingleResourceImpl::addObserver(OC::ObservationInfo ocObserverInfo)
592 ObserverInfo info {ocObserverInfo.obsId, ocObserverInfo.address, ocObserverInfo.port};
593 m_observersList.push_back(info);
595 if (m_observeCallback)
596 m_observeCallback(m_uri, ObservationStatus::REGISTER, info);
599 void SimulatorSingleResourceImpl::removeObserver(OC::ObservationInfo ocObserverInfo)
602 for (auto iter = m_observersList.begin(); iter != m_observersList.end(); iter++)
604 if ((info = *iter), info.id == ocObserverInfo.obsId)
606 m_observersList.erase(iter);
611 if (m_observeCallback)
612 m_observeCallback(m_uri, ObservationStatus::UNREGISTER, info);
615 void SimulatorSingleResourceImpl::removeAllObservers()
617 std::vector<ObserverInfo> observerList = m_observersList;
618 m_observersList.clear();
619 for (int index = 0; index < observerList.size(); index++)
621 if (m_observeCallback)
622 m_observeCallback(m_uri, ObservationStatus::UNREGISTER, observerList[index]);