1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH 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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 /// This fridgeclient represents a client trying to discover the associated
22 /// fridgeserver. The device resource is the only one available for discovery
23 /// on the server, so we have to take the fact that we know the device tag
24 /// to then generate a Resource object
28 #include <condition_variable>
31 #include "OCPlatform.h"
35 namespace PH = std::placeholders;
37 // Option ID for API version and client token
38 const uint16_t API_VERSION = 2048;
39 const uint16_t TOKEN = 3000;
41 static void printUsage()
43 std::cout << "Usage: fridgeclient <0|1>" <<std::endl;
44 std::cout << "connectivityType: Default IP" << std::endl;
45 std::cout << "connectivityType 0: IP" << std::endl;
50 ClientFridge(OCConnectivityType ct): m_callbackCount(0),
51 m_callsMade(0),m_connectivityType(ct)
53 std::ostringstream requestURI;
54 requestURI << OC_RSRVD_WELL_KNOWN_URI << "?rt=intel.fridge";
55 std::cout << "Fridge Client has started " <<std::endl;
56 FindCallback f (std::bind(&ClientFridge::foundDevice, this, PH::_1));
57 OCStackResult result = OCPlatform::findResource(
58 "", requestURI.str(), CT_DEFAULT, f);
60 if(OC_STACK_OK != result)
62 throw new std::runtime_error("Fridge Find Resource Failed");
65 std::cout << "Waiting to discover fridge... "<<std::endl;
67 // we want to block this thread until the client has finished
68 // its duties, so we block on the CV until we have completed
69 // what we are looking to do
70 std::unique_lock<std::mutex> lk(m_mutex);
71 m_cv.wait(lk, [this]{ return m_callbackCount!=0 && m_callbackCount == m_callsMade;});
76 void foundDevice(std::shared_ptr<OCResource> resource)
78 using namespace OC::OCPlatform;
79 std::string platformDiscoveryURI = "/oic/p";
80 std::string deviceDiscoveryURI = "/oic/d";
81 if(resource && resource->uri() == "/device")
83 std::cout << "Discovered a device object"<<std::endl;
84 std::cout << "\tHost: "<<resource->host()<<std::endl;
85 std::cout << "\tURI: "<<resource->uri() <<std::endl;
90 std::cout << "Querying for platform information... " << std::endl;
92 ret = OCPlatform::getPlatformInfo("", platformDiscoveryURI, CT_ADAPTER_IP, NULL);
94 if (ret == OC_STACK_OK)
96 std::cout << "Get platform information is done." << std::endl;
100 std::cout << "Get platform information failed." << std::endl;
103 std::cout << "Querying for device information... " << std::endl;
105 ret = OCPlatform::getDeviceInfo(resource->host(), deviceDiscoveryURI,
106 resource->connectivityType(), NULL);
108 if (ret == OC_STACK_OK)
110 std::cout << "Getting device information is done." << std::endl;
114 std::cout << "Getting device information failed." << std::endl;
117 // we have now found a resource, so lets create a few resource objects
118 // for the other resources that we KNOW are associated with the intel.fridge
119 // server, and query them.
120 std::vector<std::string> lightTypes = {"intel.fridge.light"};
121 std::vector<std::string> ifaces = {DEFAULT_INTERFACE};
122 OCResource::Ptr light = constructResourceObject(resource->host(),
123 "/light", m_connectivityType, false, lightTypes, ifaces);
127 std::cout << "Error: Light Resource Object construction returned null\n";
131 std::vector<std::string> doorTypes = {"intel.fridge.door"};
132 OCResource::Ptr leftdoor = constructResourceObject(resource->host(),
133 "/door/left", m_connectivityType, false, doorTypes, ifaces);
137 std::cout << "Error: Left Door Resource Object construction returned null\n";
141 OCResource::Ptr rightdoor = constructResourceObject(resource->host(),
142 "/door/right", m_connectivityType, false, doorTypes, ifaces);
146 std::cout << "Error: Right Door Resource Object construction returned null\n";
150 OCResource::Ptr randomdoor = constructResourceObject(resource->host(),
151 "/door/random", m_connectivityType, false, doorTypes, ifaces);
154 std::cout << "Error: Random Door Resource Object construction returned null\n";
158 // Set header options with API version and token
159 HeaderOptions headerOptions;
162 // Set API version and client token
163 HeaderOption::OCHeaderOption apiVersion(API_VERSION, "v.1.0");
164 HeaderOption::OCHeaderOption clientToken(TOKEN, "21ae43gf");
165 headerOptions.push_back(apiVersion);
166 headerOptions.push_back(clientToken);
168 catch(OCException& e)
170 std::cout << "Error creating HeaderOption: " << e.what() << std::endl;
174 // Setting header options will send above options in all requests
175 // Header options are set per resource.
176 // Below, header options are set only for device resource
177 resource->setHeaderOptions(headerOptions);
180 resource->get(QueryParamsMap(), GetCallback(
181 std::bind(&ClientFridge::getResponse, this, "Device", PH::_1,
182 PH::_2, PH::_3, resource, 0)
185 light->get(QueryParamsMap(), GetCallback(
186 std::bind(&ClientFridge::getResponse, this, "Fridge Light", PH::_1,
187 PH::_2, PH::_3, light, 1)
190 leftdoor->get(QueryParamsMap(), GetCallback(
191 std::bind(&ClientFridge::getResponse, this, "Left Door", PH::_1,
192 PH::_2, PH::_3, leftdoor, 2)
195 rightdoor->get(QueryParamsMap(), GetCallback(
196 std::bind(&ClientFridge::getResponse, this, "Right Door", PH::_1,
197 PH::_2, PH::_3, rightdoor, 3)
200 randomdoor->get(QueryParamsMap(), GetCallback(
201 std::bind(&ClientFridge::getResponse, this, "Random Door", PH::_1,
202 PH::_2, PH::_3, randomdoor, 4)
205 resource->deleteResource(DeleteCallback(
206 std::bind(&ClientFridge::deleteResponse, this, "Device", PH::_1,
211 // Note that resourceName, resource, and getId are all bound via the std::bind mechanism.
212 // it is possible to attach ANY arbitrary data to do whatever you would like here. It may,
213 // however be a better fit to wrap each call in an object so a fuller context (and additional
214 // requests) can be easily made inside of a simple context
215 void getResponse(const std::string& resourceName, const HeaderOptions& headerOptions,
216 const OCRepresentation& rep, const int eCode, OCResource::Ptr resource, int getId)
218 std::cout << "Got a response from get from the " << resourceName << std::endl;
219 std::cout << "Get ID is "<<getId<<" and resource URI is " << resource->uri() << std::endl;
220 std::cout << "Get eCode is "<< eCode << std::endl;
221 std::cout << "OCRepresentation uri is " << rep.getUri() << std::endl;
223 printHeaderOptions(headerOptions);
225 std::cout << "The Attribute Data is: "<<std::endl;
233 rep.getValue("device_name", name);
234 std::cout << "Name of device: "<< name << std::endl;
240 rep.getValue("on",isOn);
241 std::cout<<"The fridge light is "<< ((isOn)?"":"not ") <<"on"<<std::endl;
249 rep.getValue("open", isOpen);
250 rep.getValue("side", side);
251 std::cout << "Door is "<<isOpen<<" and is on the "<<side<<std::endl;
256 // Get on random resource called.
258 rep.getValue("device_name", name);
259 std::cout << "Name of fridge: "<< name << std::endl;
265 if(m_callbackCount == m_callsMade)
271 //Callback function to handle response for deleteResource call.
272 void deleteResponse(const std::string& resourceName, const HeaderOptions& headerOptions,
273 const int /*eCode*/, OCResource::Ptr resource, int deleteId)
275 std::cout << "Got a response from delete from the "<< resourceName << std::endl;
276 std::cout << "Delete ID is "<<deleteId<<" and resource URI is "<<resource->uri()<<std::endl;
277 printHeaderOptions(headerOptions);
281 if(m_callbackCount == m_callsMade)
287 //Function to print the headerOptions received from the server
288 void printHeaderOptions(const HeaderOptions& headerOptions)
290 for (auto it = headerOptions.begin(); it != headerOptions.end(); ++it)
292 if(it->getOptionID() == API_VERSION)
294 std::cout << "Server API version in GET response: " <<
295 it->getOptionData() << std::endl;
301 std::condition_variable m_cv;
302 std::atomic<int> m_callbackCount;
303 std::atomic<int> m_callsMade;
304 OCConnectivityType m_connectivityType;
307 int main(int argc, char* argv[])
309 OCConnectivityType connectivityType = CT_ADAPTER_IP;
314 std::size_t inputValLen;
315 int optionSelected = std::stoi(argv[1], &inputValLen);
317 if(inputValLen == strlen(argv[1]))
319 if(optionSelected == 0)
321 std::cout << "Using IP."<< std::endl;
322 connectivityType = CT_ADAPTER_IP;
326 std::cout << "Invalid connectivity type selected. Using default IP" << std::endl;
332 std::cout << "Invalid connectivity type selected. Using default IP" << std::endl;
335 catch(std::exception&)
337 std::cout << "Invalid input argument. Using IP as connectivity type" << std::endl;
343 std::cout << "Default input argument. Using IP as connectivity type" << std::endl;
352 QualityOfService::LowQos
355 OCPlatform::Configure(cfg);
356 ClientFridge cf(connectivityType);