1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
24 #include "RemoteEnrolleeResource.h"
26 #include "OCPlatform.h"
27 #include "ESException.h"
28 #include "OCResource.h"
35 #define ES_REMOTE_ENROLLEE_RES_TAG "ES_REMOTE_ENROLLEE_RES"
36 #define DISCOVERY_TIMEOUT 5
38 static const char ES_BASE_RES_URI[] = "/oic/res";
39 static const char ES_PROV_RES_URI[] = "/oic/prov";
40 static const char ES_PROV_RES_TYPE[] = "oic.r.prov";
42 RemoteEnrolleeResource::RemoteEnrolleeResource(ProvConfig provConfig,
43 WiFiOnboadingConnection onboardingconn)
45 m_ProvConfig = provConfig;
46 m_wifiOnboardingconn = onboardingconn;
47 m_discoveryResponse = false;
50 void RemoteEnrolleeResource::checkProvInformationCb(const HeaderOptions& /*headerOptions*/,
51 const OCRepresentation& rep, const int eCode)
53 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "checkProvInformationCb : %s, eCode = %d",
59 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
60 "checkProvInformationCb : Provisioning is failed ");
61 std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<
62 ProvisioningStatus >(ESResult::ES_ERROR, ESState::ES_PROVISIONING_ERROR);
63 m_provStatusCb(provStatus);
71 rep.getValue(OC_RSRVD_ES_PS, ps);
72 rep.getValue(OC_RSRVD_ES_TNN, tnn);
73 rep.getValue(OC_RSRVD_ES_CD, cd);
75 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "checkProvInformationCb : ps - %d", ps);
76 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
77 "checkProvInformationCb : tnn - %s", tnn.c_str());
78 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
79 "checkProvInformationCb : cd - %s", cd.c_str());
81 //Provisioning status check
82 if (ps == ES_PS_PROVISIONING_COMPLETED)
84 if (tnn != std::string(m_ProvConfig.provData.WIFI.ssid))
86 OC_LOG_V (ERROR, ES_REMOTE_ENROLLEE_RES_TAG,
87 "checkProvInformationCb : Network SSID is not the same as the "
89 std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<
90 ProvisioningStatus >(ESResult::ES_ERROR,
91 ESState::ES_PROVISIONING_ERROR);
92 m_provStatusCb(provStatus);
96 if (cd != std::string(m_ProvConfig.provData.WIFI.pwd))
98 OC_LOG_V (ERROR, ES_REMOTE_ENROLLEE_RES_TAG,
99 "checkProvInformationCb : Network PWD is not the same as the "
101 std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<
102 ProvisioningStatus >(ESResult::ES_ERROR,
103 ESState::ES_PROVISIONING_ERROR);
104 m_provStatusCb(provStatus);
108 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
109 "checkProvInformationCb : Provisioning is success ");
110 std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<
111 ProvisioningStatus >(ESResult::ES_OK, ESState::ES_PROVISIONING_SUCCESS);
112 m_provStatusCb(provStatus);
117 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
118 "checkProvInformationCb : Provisioning is failed ");
119 std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<
120 ProvisioningStatus >(ESResult::ES_ERROR, ESState::ES_PROVISIONING_ERROR);
121 m_provStatusCb(provStatus);
126 void RemoteEnrolleeResource::getProvStatusResponse(const HeaderOptions& /*headerOptions*/,
127 const OCRepresentation& rep, const int eCode)
129 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "getProvStatusResponse : %s, eCode = %d",
130 rep.getUri().c_str(),
135 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
136 "getProvStatusResponse : Provisioning is failed ");
137 std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<
138 ProvisioningStatus >(ESResult::ES_ERROR, ESState::ES_PROVISIONING_ERROR);
139 m_provStatusCb(provStatus);
144 std::string tnn = "";
147 rep.getValue(OC_RSRVD_ES_PS, ps);
148 rep.getValue(OC_RSRVD_ES_TNN, tnn);
149 rep.getValue(OC_RSRVD_ES_CD, cd);
151 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "getProvStatusResponse : ps - %d",
153 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "getProvStatusResponse : tnn - %s",
155 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "getProvStatusResponse : cd - %s",
158 if (ps == ES_PS_NEED_PROVISIONING) //Indicates the need for provisioning
160 OCRepresentation provisioningRepresentation;
162 provisioningRepresentation.setValue(OC_RSRVD_ES_TNN,
163 std::string(m_ProvConfig.provData.WIFI.ssid));
164 provisioningRepresentation.setValue(OC_RSRVD_ES_CD,
165 std::string(m_ProvConfig.provData.WIFI.pwd));
167 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "getProvStatusResponse : ssid - %s",
168 m_ProvConfig.provData.WIFI.ssid);
169 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "getProvStatusResponse : pwd - %s",
170 m_ProvConfig.provData.WIFI.pwd);
172 m_ocResource->put(provisioningRepresentation, QueryParamsMap(),
174 void(const HeaderOptions& headerOptions,
175 const OCRepresentation& rep, const int eCode) >(
176 std::bind(&RemoteEnrolleeResource::checkProvInformationCb, this,
177 std::placeholders::_1, std::placeholders::_2,
178 std::placeholders::_3)));
180 else if (ps == ES_PS_PROVISIONING_COMPLETED) //Indicates that provisioning is completed
182 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
183 "getProvStatusResponse : Provisioning is successful");
184 std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<
185 ProvisioningStatus >(ESResult::ES_OK, ESState::ES_PROVISIONED_ALREADY);
186 m_provStatusCb(provStatus);
190 void RemoteEnrolleeResource::registerProvStatusCallback(ProvStatusCb provStatusCb)
192 m_provStatusCb = provStatusCb;
195 ESResult RemoteEnrolleeResource::ESDiscoveryTimeout(unsigned short waittime)
197 struct timespec startTime;
200 struct timespec currTime;
204 ESResult res = ES_OK;
205 #ifdef _POSIX_MONOTONIC_CLOCK
206 int clock_res = clock_gettime(CLOCK_MONOTONIC, &startTime);
208 int clock_res = clock_gettime(CLOCK_REALTIME, &startTime);
216 while (ES_OK == res || m_discoveryResponse == false)
218 #ifdef _POSIX_MONOTONIC_CLOCK
219 clock_res = clock_gettime(CLOCK_MONOTONIC, &currTime);
221 clock_res = clock_gettime(CLOCK_REALTIME, &currTime);
228 long elapsed = (currTime.tv_sec - startTime.tv_sec);
229 if (elapsed > waittime)
233 if (m_discoveryResponse)
241 void RemoteEnrolleeResource::onDeviceDiscovered(std::shared_ptr<OC::OCResource> resource)
243 OC_LOG (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "onDeviceDiscovered");
245 std::string resourceURI;
246 std::string hostAddress;
251 // Get the resource URI
252 resourceURI = resource->uri();
253 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
254 "URI of the resource: %s", resourceURI.c_str());
256 // Get the resource host address
257 hostAddress = resource->host();
258 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
259 "Host address of the resource: %s", hostAddress.c_str());
261 std::size_t foundIP =
263 std::string(m_wifiOnboardingconn.ipAddress));
265 if(resourceURI == ES_PROV_RES_URI && foundIP!=std::string::npos)
267 m_ocResource = resource;
268 m_discoveryResponse = true;
270 OC_LOG (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
271 "Found the device with the resource");
277 OC_LOG (ERROR, ES_REMOTE_ENROLLEE_RES_TAG, "NOT the intended resource.");
282 OC_LOG (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "Resource is invalid");
286 catch(std::exception& e)
288 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
289 "Exception in foundResource: %s", e.what());
294 ESResult RemoteEnrolleeResource::constructResourceObject()
296 if (m_ocResource != nullptr)
298 throw ESBadRequestException("Remote resource is already created");
301 #ifdef REMOTE_ARDUINO_ENROLEE
302 //This process will create OCResource with port 55555 which is specific
303 // to Arduino WiFi enrollee
307 std::vector< std::string > interface =
308 { DEFAULT_INTERFACE};
309 std::vector< std::string > resTypes =
312 OC_LOG(DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "Before OCPlatform::constructResourceObject");
314 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "m_host = %s",
315 m_wifiOnboardingconn.ipAddress);
316 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "ES_PROV_RES_URI = %s", ES_PROV_RES_URI);
317 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "m_connectivityType = %d",
318 m_ProvConfig.connType);
319 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "resTypes = %s",
320 resTypes.at(0).c_str());
321 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "interface = %s", interface.at(0).c_str());
324 if(m_wifiOnboardingconn.isSecured)
326 host.append("coaps://");
330 host.append("coap://");
333 if(m_ProvConfig.connType == CT_ADAPTER_IP)
335 // TODO : RemoteEnrollee is current handling easysetup on IP transport.
336 // WiFiRemoteEnrollee need to extend RemoteEnrollee for providing IP specific
337 // Enrollee easysetup.
339 host.append(m_wifiOnboardingconn.ipAddress);
340 //TODO : If the target Enrollee is not a Arduino Wi-Fi device,
341 // then the port number will be found during resource discovery instead of
343 host.append(":55555");
346 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "HOST = %s", host.c_str());
348 m_ocResource = OC::OCPlatform::constructResourceObject(host,
350 m_ProvConfig.connType,
354 OC_LOG_V(DEBUG, ES_REMOTE_ENROLLEE_RES_TAG,
355 "created OCResource : %s", m_ocResource->uri().c_str());
359 catch (OCException & e)
361 OC_LOG_V(ERROR, ES_REMOTE_ENROLLEE_RES_TAG,
362 "Exception for constructResourceObject : %s", e.reason().c_str());
366 std::string host("");
367 std::string query("");
369 if (m_wifiOnboardingconn.isSecured)
371 host.append("coaps://");
375 host.append("coap://");
378 if (m_ProvConfig.connType == CT_ADAPTER_IP)
380 // TODO : RemoteEnrollee is current handling easysetup on IP transport.
381 // WiFiRemoteEnrollee need to extend RemoteEnrollee for providing IP specific
382 // Enrollee easysetup.
384 host.append(m_wifiOnboardingconn.ipAddress);
387 query.append(ES_BASE_RES_URI);
388 query.append("?rt=");
389 query.append(ES_PROV_RES_TYPE);
391 OC_LOG(DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "Before OCPlatform::constructResourceObject");
393 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "host = %s",
395 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "query = %s", query.c_str());
396 OC_LOG_V (DEBUG, ES_REMOTE_ENROLLEE_RES_TAG, "m_connectivityType = %d",
397 m_ProvConfig.connType);
399 m_discoveryResponse = false;
400 std::function< void (std::shared_ptr<OC::OCResource>) > onDeviceDiscoveredCb =
401 std::bind(&RemoteEnrolleeResource::onDeviceDiscovered, this,
402 std::placeholders::_1);
403 OCStackResult result = OC::OCPlatform::findResource("", query, CT_DEFAULT,
404 onDeviceDiscoveredCb);
406 if (result != OCStackResult::OC_STACK_OK)
408 OC_LOG(ERROR,ES_REMOTE_ENROLLEE_RES_TAG,
409 "Failed to create device using constructResourceObject");
414 ESResult foundResponse = ESDiscoveryTimeout (DISCOVERY_TIMEOUT);
416 if (!m_discoveryResponse)
418 OC_LOG(ERROR,ES_REMOTE_ENROLLEE_RES_TAG,
419 "Failed to create device using constructResourceObject");
427 void RemoteEnrolleeResource::provisionEnrollee()
430 if (m_ocResource == nullptr)
432 throw ESBadRequestException("Resource is not initialized");
435 OC::QueryParamsMap query;
436 OC::OCRepresentation rep;
438 std::function< OCStackResult(void) > getProvisioingStatus = [&]
439 { return m_ocResource->get(m_ocResource->getResourceTypes().at(0),
440 m_ocResource->getResourceInterfaces().at(0), query,
442 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
444 std::bind(&RemoteEnrolleeResource::getProvStatusResponse, this,
445 std::placeholders::_1, std::placeholders::_2,
446 std::placeholders::_3)));
449 OCStackResult result = getProvisioingStatus();
451 if (result != OCStackResult::OC_STACK_OK)
453 std::shared_ptr< ProvisioningStatus > provStatus = std::make_shared<
454 ProvisioningStatus >(ESResult::ES_ERROR, ESState::ES_PROVISIONING_ERROR);
455 m_provStatusCb(provStatus);
460 void RemoteEnrolleeResource::unprovisionEnrollee()
462 if (m_ocResource == nullptr)
464 throw ESBadRequestException("Resource is not initialized");
467 OCRepresentation provisioningRepresentation;
469 provisioningRepresentation.setValue(OC_RSRVD_ES_TNN, "");
470 provisioningRepresentation.setValue(OC_RSRVD_ES_CD, "");
472 m_ocResource->post(provisioningRepresentation, QueryParamsMap(),
474 void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
476 std::bind(&RemoteEnrolleeResource::checkProvInformationCb, this,
477 std::placeholders::_1, std::placeholders::_2,
478 std::placeholders::_3)));