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_resourceHandle(NULL),
31 m_interfaces {OC::DEFAULT_INTERFACE}
33 m_requestTypes[OC::DEFAULT_INTERFACE] = {"GET", "PUT", "POST"};
34 m_requestTypes[OC::READ_INTERFACE] = {"GET"};
35 m_requestTypes[OC::READWRITE_INTERFACE] = {"GET", "PUT", "POST"};
36 m_requestTypes[OC::ACTUATOR_INTERFACE] = {"GET", "PUT", "POST"};
37 m_requestTypes[OC::SENSOR_INTERFACE] = {"GET"};
38 m_property = static_cast<OCResourceProperty>(OC_DISCOVERABLE | OC_OBSERVABLE);
41 std::string SimulatorSingleResourceImpl::getName() const
46 SimulatorResource::Type SimulatorSingleResourceImpl::getType() const
51 std::string SimulatorSingleResourceImpl::getURI() const
56 std::string SimulatorSingleResourceImpl::getResourceType() const
58 return m_resourceType;
61 std::vector<std::string> SimulatorSingleResourceImpl::getInterface() const
66 void SimulatorSingleResourceImpl::setInterface(const std::vector<std::string> &interfaces)
68 // Replace m_interfaces if the list is not empty
69 if (!interfaces.empty())
70 m_interfaces = interfaces;
73 void SimulatorSingleResourceImpl::setName(const std::string &name)
75 VALIDATE_INPUT(name.empty(), "Name is empty!")
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 cannot be set when resource is started!");
105 m_resourceType = resourceType;
108 void SimulatorSingleResourceImpl::addInterface(const std::string &interfaceType)
110 VALIDATE_INPUT(interfaceType.empty(), "Interface type is empty!")
112 if (interfaceType == OC::READ_INTERFACE
113 || interfaceType == OC::READWRITE_INTERFACE
114 || interfaceType == OC::ACTUATOR_INTERFACE
115 || interfaceType == OC::SENSOR_INTERFACE
116 || interfaceType == OC::DEFAULT_INTERFACE)
118 if (m_interfaces.end() != std::find(m_interfaces.begin(), m_interfaces.end(), interfaceType))
120 SIM_LOG(ILogger::ERROR, "Interface " << interfaceType << " is already supported!");
124 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
125 typedef OCStackResult (*bindInterfaceToResource)(const OCResourceHandle &,
126 const std::string &);
130 invokeocplatform(static_cast<bindInterfaceToResource>(
131 OC::OCPlatform::bindInterfaceToResource), m_resourceHandle,
134 catch (SimulatorException &e)
141 throw NoSupportException("Interface is not supported!");
144 m_interfaces.push_back(interfaceType);
147 void SimulatorSingleResourceImpl::removeInterface(const std::string &interfaceType)
149 if (m_interfaces.end() == std::find(m_interfaces.begin(), m_interfaces.end(), interfaceType))
151 SIM_LOG(ILogger::ERROR, "Interface " << interfaceType << " is not being supported currently!");
155 m_interfaces.erase(std::remove(m_interfaces.begin(), m_interfaces.end(), interfaceType), m_interfaces.end());
158 void SimulatorSingleResourceImpl::addInterface(const std::vector<std::string> &interfaceList)
160 VALIDATE_INPUT(!interfaceList.size(), "Interface list is empty!")
162 for (auto interfaceType : interfaceList)
164 addInterface(interfaceType);
168 void SimulatorSingleResourceImpl::removeInterface(const std::vector<std::string> &interfaceList)
170 VALIDATE_INPUT(!interfaceList.size(), "Interface list is empty!")
172 for (auto interfaceType : interfaceList)
174 removeInterface(interfaceType);
178 void SimulatorSingleResourceImpl::setObservable(bool state)
180 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
181 if (m_resourceHandle)
183 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
184 "Observation state can not be changed when resource is started!");
188 m_property = static_cast<OCResourceProperty>(m_property | OC_OBSERVABLE);
190 m_property = static_cast<OCResourceProperty>(m_property ^ OC_OBSERVABLE);
193 void SimulatorSingleResourceImpl::setObserverCallback(ObserverCallback callback)
195 VALIDATE_CALLBACK(callback)
196 m_observeCallback = callback;
199 bool SimulatorSingleResourceImpl::isObservable()
201 return (m_property & OC_OBSERVABLE);
204 bool SimulatorSingleResourceImpl::isStarted()
206 return (nullptr != m_resourceHandle);
209 void SimulatorSingleResourceImpl::start()
211 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
212 if (m_resourceHandle)
214 SIM_LOG(ILogger::INFO, "[" << m_name << "] " << "Resource already registered!")
217 if (m_uri.empty() || m_resourceType.empty())
219 throw SimulatorException(SIMULATOR_ERROR, "Found incomplete data to start resource!");
222 typedef OCStackResult (*RegisterResource)(OCResourceHandle &, std::string &, const std::string &,
223 const std::string &, OC::EntityHandler, uint8_t);
225 invokeocplatform(static_cast<RegisterResource>(OC::OCPlatform::registerResource),
226 m_resourceHandle, m_uri, m_resourceType, m_interfaces[0],
227 std::bind(&SimulatorSingleResourceImpl::handleRequests,
228 this, std::placeholders::_1), m_property);
230 for (size_t index = 1; m_interfaces.size() > 1 && index < m_interfaces.size(); index++)
232 typedef OCStackResult (*bindInterfaceToResource)(const OCResourceHandle &,
233 const std::string &);
237 invokeocplatform(static_cast<bindInterfaceToResource>(
238 OC::OCPlatform::bindInterfaceToResource), m_resourceHandle,
239 m_interfaces[index]);
241 catch (SimulatorException &e)
249 void SimulatorSingleResourceImpl::stop()
251 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
252 if (!m_resourceHandle)
255 // Stop all the update automation of this resource
256 m_updateAutomationMgr.stopAll();
258 // Clear all the observers
259 removeAllObservers();
261 // Unregister the resource from stack
262 typedef OCStackResult (*UnregisterResource)(const OCResourceHandle &);
264 invokeocplatform(static_cast<UnregisterResource>(OC::OCPlatform::unregisterResource),
267 m_resourceHandle = nullptr;
270 std::vector<ObserverInfo> SimulatorSingleResourceImpl::getObserversList()
272 return m_observersList;
275 void SimulatorSingleResourceImpl::notify(int id, SimulatorResourceModel &resModel)
277 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
278 if (!m_resourceHandle)
281 std::shared_ptr<OC::OCResourceResponse> resourceResponse =
282 {std::make_shared<OC::OCResourceResponse>()};
284 resourceResponse->setErrorCode(200);
285 resourceResponse->setResponseResult(OC_EH_OK);
286 resourceResponse->setResourceRepresentation(resModel.getOCRepresentation(),
287 OC::DEFAULT_INTERFACE);
289 OC::ObservationIds observers;
290 observers.push_back(id);
292 typedef OCStackResult (*NotifyListOfObservers)(OCResourceHandle, OC::ObservationIds &,
293 const std::shared_ptr<OC::OCResourceResponse>);
295 invokeocplatform(static_cast<NotifyListOfObservers>(OC::OCPlatform::notifyListOfObservers),
296 m_resourceHandle, observers, resourceResponse);
299 void SimulatorSingleResourceImpl::notifyAll(SimulatorResourceModel &resModel)
301 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
302 if (!m_resourceHandle)
305 if (!m_observersList.size())
308 std::shared_ptr<OC::OCResourceResponse> resourceResponse =
309 {std::make_shared<OC::OCResourceResponse>()};
311 resourceResponse->setErrorCode(200);
312 resourceResponse->setResponseResult(OC_EH_OK);
313 resourceResponse->setResourceRepresentation(resModel.getOCRepresentation(),
314 OC::DEFAULT_INTERFACE);
316 OC::ObservationIds observers;
317 for (auto &observer : m_observersList)
318 observers.push_back(observer.id);
320 typedef OCStackResult (*NotifyListOfObservers)(OCResourceHandle, OC::ObservationIds &,
321 const std::shared_ptr<OC::OCResourceResponse>);
323 invokeocplatform(static_cast<NotifyListOfObservers>(OC::OCPlatform::notifyListOfObservers),
324 m_resourceHandle, observers, resourceResponse);
327 void SimulatorSingleResourceImpl::notify(int id)
329 notify(id, m_resModel);
332 void SimulatorSingleResourceImpl::notifyAll()
334 notifyAll(m_resModel);
337 bool SimulatorSingleResourceImpl::getAttribute(const std::string &attrName,
338 SimulatorResourceModel::Attribute &attribute)
340 VALIDATE_INPUT(attrName.empty(), "Attribute name is empty!")
342 std::lock_guard<std::mutex> lock(m_modelLock);
343 return m_resModel.getAttribute(attrName, attribute);
346 void SimulatorSingleResourceImpl::addAttribute(const SimulatorResourceModel::Attribute &attribute,
349 std::lock_guard<std::mutex> lock(m_modelLock);
350 if (m_resModel.containsAttribute(attribute.getName()))
351 throw SimulatorException(SIMULATOR_ERROR, "Attribute exist with same name!");
353 if (!m_resModel.add(attribute))
354 throw SimulatorException(SIMULATOR_ERROR, "Failed to add attribute!");
356 if (notify && isStarted())
360 bool SimulatorSingleResourceImpl::getAttributeProperty(const std::string &attrName,
361 SimulatorResourceModel::AttributeProperty &property)
363 VALIDATE_INPUT(attrName.empty(), "Attribute name is empty!")
365 std::lock_guard<std::mutex> lock(m_modelLock);
366 return m_resModel.getAttributeProperty(attrName, property);
369 bool SimulatorSingleResourceImpl::setAttributeProperty(const std::string &attrName,
370 const SimulatorResourceModel::AttributeProperty &property)
372 VALIDATE_INPUT(attrName.empty(), "Attribute name is empty!")
374 std::lock_guard<std::mutex> lock(m_modelLock);
375 return m_resModel.setAttributeProperty(attrName, property);
378 bool SimulatorSingleResourceImpl::updateAttributeValue(
379 const SimulatorResourceModel::Attribute &attribute,
382 std::lock_guard<std::mutex> lock(m_modelLock);
383 if (m_resModel.updateValue(attribute))
385 if (notify && isStarted())
393 bool SimulatorSingleResourceImpl::removeAttribute(const std::string &attrName, bool notify)
395 VALIDATE_INPUT(attrName.empty(), "Attribute name is empty!")
397 std::lock_guard<std::mutex> lock(m_modelLock);
398 if (m_resModel.removeAttribute(attrName))
400 if (notify && isStarted())
408 SimulatorResourceModel SimulatorSingleResourceImpl::getResourceModel()
410 std::lock_guard<std::mutex> lock(m_modelLock);
414 void SimulatorSingleResourceImpl::setModelChangeCallback(ResourceModelChangedCallback callback)
416 VALIDATE_CALLBACK(callback)
417 m_modelCallback = callback;
420 int SimulatorSingleResourceImpl::startResourceUpdation(AutomationType type,
421 int updateInterval, updateCompleteCallback callback)
423 VALIDATE_CALLBACK(callback)
425 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
426 if (!m_resourceHandle)
427 throw SimulatorException(SIMULATOR_NO_RESOURCE, "Resource is not registered!");
429 return m_updateAutomationMgr.startResourceAutomation(this, type, updateInterval, callback);
432 int SimulatorSingleResourceImpl::startAttributeUpdation(const std::string &attrName,
433 AutomationType type, int updateInterval, updateCompleteCallback callback)
435 VALIDATE_CALLBACK(callback)
437 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
438 if (!m_resourceHandle)
439 throw SimulatorException(SIMULATOR_NO_RESOURCE, "Resource is not registered!");
441 return m_updateAutomationMgr.startAttributeAutomation(this, attrName, type,
442 updateInterval, callback);
445 std::vector<int> SimulatorSingleResourceImpl::getResourceUpdationIds()
447 return m_updateAutomationMgr.getResourceAutomationIds();
450 std::vector<int> SimulatorSingleResourceImpl::getAttributeUpdationIds()
452 return m_updateAutomationMgr.getAttributeAutomationIds();
455 void SimulatorSingleResourceImpl::stopUpdation(const int id)
457 m_updateAutomationMgr.stop(id);
460 void SimulatorSingleResourceImpl::setResourceModel(const SimulatorResourceModel &resModel)
462 std::lock_guard<std::mutex> lock(m_modelLock);
463 m_resModel = resModel;
466 void SimulatorSingleResourceImpl::setPutErrorResponseModel(const SimulatorResourceModel &resModel)
468 m_putErrorResModel = resModel;
471 void SimulatorSingleResourceImpl::setPostErrorResponseModel(const SimulatorResourceModel &resModel)
473 m_postErrorResModel = resModel;
476 void SimulatorSingleResourceImpl::setActionType(std::map<RAML::ActionType, RAML::ActionPtr> &actionType)
478 m_actionTypes = actionType;
481 void SimulatorSingleResourceImpl::notifyApp(SimulatorResourceModel &resModel)
485 m_modelCallback(m_uri, resModel);
489 void SimulatorSingleResourceImpl::notifyApp()
491 notifyApp(m_resModel);
494 bool SimulatorSingleResourceImpl::updateResourceModel(OC::OCRepresentation &ocRep,
495 SimulatorResourceModel &resModel)
497 std::lock_guard<std::mutex> lock(m_modelLock);
498 if (m_resModel.update(ocRep))
500 resModel = m_resModel;
506 OCEntityHandlerResult SimulatorSingleResourceImpl::handleRequests(
507 std::shared_ptr<OC::OCResourceRequest> request)
509 OCEntityHandlerResult errCode = OC_EH_ERROR;
513 if (OC::RequestHandlerFlag::RequestFlag & request->getRequestHandlerFlag())
516 OC::OCRepresentation rep = request->getResourceRepresentation();
517 std::string payload = getPayloadString(rep);
518 SIM_LOG(ILogger::INFO, "[" << m_name << "] " << request->getRequestType()
519 << " request received. \n**Payload details**\n" << payload)
522 std::string interfaceType(OC::DEFAULT_INTERFACE);
523 OC::QueryParamsMap queryParams = request->getQueryParameters();
524 if (queryParams.end() != queryParams.find("if"))
526 interfaceType = queryParams["if"];
529 std::shared_ptr<OC::OCResourceResponse> response;
531 // Check if the interface type is supported by the resource
532 if (m_interfaces.end() == std::find(m_interfaces.begin(), m_interfaces.end(), interfaceType))
534 return sendErrorResponse(request, 403, OC_EH_FORBIDDEN);
537 //Check if requestType is supported by interface.
538 std::map<std::string, std::vector<std::string>>::iterator it = m_requestTypes.find(interfaceType);
539 if (it != m_requestTypes.end())
541 if (it->second.end() == std::find(it->second.begin(), it->second.end(), request->getRequestType()))
543 return sendErrorResponse(request, 405, OC_EH_ERROR);
547 if ("GET" == request->getRequestType())
549 response = handleReadRequest(request, interfaceType);
551 else if ("PUT" == request->getRequestType()
552 || "POST" == request->getRequestType())
554 response = handleWriteRequest(request, interfaceType);
556 else if ("DELETE" == request->getRequestType())
558 SIM_LOG(ILogger::ERROR, "[" << m_name << "] " << "Unsupported request received!")
562 // Send response if the request handled by resource
565 response->setRequestHandle(request->getRequestHandle());
566 response->setResourceHandle(request->getResourceHandle());
567 if (OC_STACK_OK != OC::OCPlatform::sendResponse(response))
572 if (OC::RequestHandlerFlag::ObserverFlag & request->getRequestHandlerFlag())
574 if (false == isObservable())
576 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE request received")
577 SIM_LOG(ILogger::INFO, "[" << m_uri << "] Sending error as resource is in unobservable state")
581 OC::ObservationInfo observationInfo = request->getObservationInfo();
582 if (OC::ObserveAction::ObserveRegister == observationInfo.action)
584 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE REGISTER request received");
585 addObserver(observationInfo);
587 else if (OC::ObserveAction::ObserveUnregister == observationInfo.action)
589 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE UNREGISTER request received");
590 removeObserver(observationInfo);
597 void SimulatorSingleResourceImpl::addObserver(OC::ObservationInfo ocObserverInfo)
599 ObserverInfo info {ocObserverInfo.obsId, ocObserverInfo.address, ocObserverInfo.port};
600 m_observersList.push_back(info);
602 if (m_observeCallback)
603 m_observeCallback(m_uri, ObservationStatus::REGISTER, info);
606 void SimulatorSingleResourceImpl::removeObserver(OC::ObservationInfo ocObserverInfo)
609 for (auto iter = m_observersList.begin(); iter != m_observersList.end(); iter++)
611 if ((info = *iter), info.id == ocObserverInfo.obsId)
613 m_observersList.erase(iter);
618 if (m_observeCallback)
619 m_observeCallback(m_uri, ObservationStatus::UNREGISTER, info);
622 void SimulatorSingleResourceImpl::removeAllObservers()
624 std::vector<ObserverInfo> observerList = m_observersList;
625 m_observersList.clear();
626 for (int index = 0; index < observerList.size(); index++)
628 if (m_observeCallback)
629 m_observeCallback(m_uri, ObservationStatus::UNREGISTER, observerList[index]);
633 RAML::ActionType SimulatorSingleResourceImpl::getActionType(std::string requestType)
635 if (!requestType.compare("GET"))
636 return RAML::ActionType::GET;
638 if (!requestType.compare("PUT"))
639 return RAML::ActionType::PUT;
641 if (!requestType.compare("POST"))
642 return RAML::ActionType::POST;
644 if (!requestType.compare("DELETE"))
645 return RAML::ActionType::DELETE;
647 return RAML::ActionType::NONE;
650 OCEntityHandlerResult SimulatorSingleResourceImpl::sendErrorResponse
651 (std::shared_ptr<OC::OCResourceRequest> request, const int errCode,
652 OCEntityHandlerResult responseCode)
654 std::shared_ptr<OC::OCResourceResponse> response;
656 response = std::make_shared<OC::OCResourceResponse>();
657 response->setErrorCode(errCode);
658 response->setResponseResult(responseCode);
660 // Setting error response body as representation in response if available in RAML file
661 if ("PUT" == request->getRequestType())
663 if (!m_putErrorResModel.getOCRepresentation().empty())
664 response->setResourceRepresentation(m_putErrorResModel.getOCRepresentation());
667 if ("POST" == request->getRequestType())
669 if (!m_postErrorResModel.getOCRepresentation().empty())
670 response->setResourceRepresentation(m_postErrorResModel.getOCRepresentation());
673 response->setRequestHandle(request->getRequestHandle());
674 response->setResourceHandle(request->getResourceHandle());
675 if (OC_STACK_OK != OC::OCPlatform::sendResponse(response))
681 std::shared_ptr<OC::OCResourceResponse> SimulatorSingleResourceImpl::handleReadRequest
682 (std::shared_ptr<OC::OCResourceRequest> request, const std::string &interfaceType)
684 std::shared_ptr<OC::OCResourceResponse> response;
685 OC::OCRepresentation ocRep;
687 response = std::make_shared<OC::OCResourceResponse>();
688 response->setErrorCode(200);
689 response->setResponseResult(OC_EH_OK);
691 if (OC::ACTUATOR_INTERFACE == interfaceType ||
692 OC::SENSOR_INTERFACE == interfaceType)
694 // Only send the representation without the common properties.
695 ocRep = m_resModel.getOCRepresentation();
696 response->setResourceRepresentation(ocRep, interfaceType);
700 // Send the representation along with common properties for the resource.
701 SimulatorResourceModel resModel = m_resModel;
702 setCommonProperties(resModel);
703 ocRep = resModel.getOCRepresentation();
704 response->setResourceRepresentation(ocRep, interfaceType);
707 std::string resPayload = getPayloadString(ocRep);
708 SIM_LOG(ILogger::INFO, "[" << m_uri <<
709 "] Sending response for GET request. \n**Payload details**" << resPayload)
714 std::shared_ptr<OC::OCResourceResponse> SimulatorSingleResourceImpl::handleWriteRequest
715 (std::shared_ptr<OC::OCResourceRequest> request, const std::string &interfaceType)
717 std::shared_ptr<OC::OCResourceResponse> response;
718 OC::OCRepresentation requestRep = request->getResourceRepresentation();
719 SimulatorResourceModel resModel;
720 if (true == updateResourceModel(requestRep, resModel))
725 response = std::make_shared<OC::OCResourceResponse>();
726 response->setErrorCode(200);
727 response->setResponseResult(OC_EH_OK);
728 response->setResourceRepresentation(resModel.getOCRepresentation(), interfaceType);
729 std::string resPayload = getPayloadString(resModel.getOCRepresentation());
730 SIM_LOG(ILogger::INFO, "[" << m_uri <<
731 "] Sending response for " << request->getRequestType() << " request. \n**Payload details**" <<
736 sendErrorResponse(request, 400, OC_EH_ERROR);
742 void SimulatorSingleResourceImpl::setCommonProperties(SimulatorResourceModel &resModel)
744 resModel.add("rt", m_resourceType);
745 resModel.add("if", m_interfaces);
746 resModel.add("p", m_property);
747 resModel.add("n", m_name);