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::setActionType(std::map<RAML::ActionType, RAML::ActionPtr> &actionType)
431 m_actionTypes = actionType;
434 void SimulatorSingleResourceImpl::notifyApp(SimulatorResourceModel &resModel)
438 m_modelCallback(m_uri, resModel);
442 void SimulatorSingleResourceImpl::notifyApp()
444 notifyApp(m_resModel);
447 bool SimulatorSingleResourceImpl::updateResourceModel(OC::OCRepresentation &ocRep,
448 SimulatorResourceModel &resModel)
450 std::lock_guard<std::mutex> lock(m_modelLock);
451 if (m_resModel.update(ocRep))
453 resModel = m_resModel;
459 OCEntityHandlerResult SimulatorSingleResourceImpl::handleRequests(
460 std::shared_ptr<OC::OCResourceRequest> request)
462 OCEntityHandlerResult errCode = OC_EH_ERROR;
466 if (OC::RequestHandlerFlag::RequestFlag & request->getRequestHandlerFlag())
469 OC::OCRepresentation rep = request->getResourceRepresentation();
470 std::string payload = getPayloadString(rep);
471 SIM_LOG(ILogger::INFO, "[" << m_name << "] " << request->getRequestType()
472 << " request received. \n**Payload details**\n" << payload)
475 // TODO: Handover the request to appropriate interface handler
477 std::shared_ptr<OC::OCResourceResponse> response;
478 response = requestOnBaseLineInterface(request);
480 // Send response if the request handled by resource
483 if (OC_STACK_OK != OC::OCPlatform::sendResponse(response))
488 SIM_LOG(ILogger::ERROR, "[" << m_name << "] " << "Unsupported request received!")
493 if (OC::RequestHandlerFlag::ObserverFlag & request->getRequestHandlerFlag())
495 if (false == isObservable())
497 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE request received")
498 SIM_LOG(ILogger::INFO, "[" << m_uri << "] Sending error as resource is in unobservable state")
502 OC::ObservationInfo observationInfo = request->getObservationInfo();
503 if (OC::ObserveAction::ObserveRegister == observationInfo.action)
505 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE REGISTER request received");
506 addObserver(observationInfo);
508 else if (OC::ObserveAction::ObserveUnregister == observationInfo.action)
510 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE UNREGISTER request received");
511 removeObserver(observationInfo);
519 std::shared_ptr<OC::OCResourceResponse> SimulatorSingleResourceImpl::requestOnBaseLineInterface(
520 std::shared_ptr<OC::OCResourceRequest> request)
522 std::shared_ptr<OC::OCResourceResponse> response;
524 RAML::ActionType type = getActionType(request->getRequestType());
526 if (!m_actionTypes.empty())
528 if (m_actionTypes.end() == m_actionTypes.find(type))
532 if ("GET" == request->getRequestType())
534 OC::OCRepresentation ocRep = m_resModel.getOCRepresentation();
535 response = std::make_shared<OC::OCResourceResponse>();
536 response->setErrorCode(200);
537 response->setResponseResult(OC_EH_OK);
538 response->setResourceRepresentation(ocRep);
539 std::string resPayload = getPayloadString(ocRep);
540 SIM_LOG(ILogger::INFO, "[" << m_uri <<
541 "] Sending response for GET request. \n**Payload details**" << resPayload)
543 else if ("PUT" == request->getRequestType()
544 || "POST" == request->getRequestType())
546 OC::OCRepresentation requestRep = request->getResourceRepresentation();
547 SimulatorResourceModel resModel;
548 if (true == updateResourceModel(requestRep, resModel))
553 response = std::make_shared<OC::OCResourceResponse>();
554 response->setErrorCode(200);
555 response->setResponseResult(OC_EH_OK);
556 response->setResourceRepresentation(resModel.getOCRepresentation());
557 std::string resPayload = getPayloadString(resModel.getOCRepresentation());
558 SIM_LOG(ILogger::INFO, "[" << m_uri <<
559 "] Sending response for " << request->getRequestType() << " request. \n**Payload details**" <<
564 response = std::make_shared<OC::OCResourceResponse>();
565 response->setErrorCode(403);
566 response->setResponseResult(OC_EH_ERROR);
567 if ("PUT" == request->getRequestType())
569 if (m_putErrorResModel.getOCRepresentation().empty())
570 response->setResourceRepresentation(m_resModel.getOCRepresentation());
572 response->setResourceRepresentation(m_putErrorResModel.getOCRepresentation());
576 if (m_postErrorResModel.getOCRepresentation().empty())
577 response->setResourceRepresentation(m_resModel.getOCRepresentation());
579 response->setResourceRepresentation(m_postErrorResModel.getOCRepresentation());
583 else if ("DELETE" == request->getRequestType())
585 // TODO: Handle this request
590 response->setRequestHandle(request->getRequestHandle());
591 response->setResourceHandle(request->getResourceHandle());
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;