iotivity 0.9.0
[platform/upstream/iotivity.git] / resource / examples / ocicuc / demo_client.hpp
1
2 /* Example client program (this is not a library header, don't include it in random programs): */
3
4 namespace Intel { namespace OCDemo { namespace client {
5
6 // Although not "done" here, this could be expanded into an interface to handle any sort of
7 // resource:
8 class resource_handle
9 {
10  friend class resource_handler;
11
12  private:
13  const std::string                     URI;
14  std::shared_ptr<OC::OCResource>       resource;
15
16  public:
17  resource_handle(const std::string& URI_, std::shared_ptr<OC::OCResource> resource_)
18   : URI(URI_),
19     resource(resource_)
20  {}
21
22  resource_handle(const std::string& URI_)
23   : URI(URI_)
24  {}
25
26  // Callbacks (note that the signature after binding will match exactly:
27  private:
28  void onFoundResource(std::shared_ptr<OC::OCResource> in_resource);
29  void onResourceGet(const OC::HeaderOptions& headerOptions,
30                 OC::OCRepresentation rep, const int error_code);
31  void onResourcePut(const OC::HeaderOptions& headerOptions, const OC::OCRepresentation rep,
32                 const int error_code);
33  void onObserve(const OC::HeaderOptions& headerOptions, const OC::OCRepresentation rep,
34                 const int error_code, const int& sequence_number);
35 };
36
37 class resource_handler
38 {
39
40  static std::vector<std::shared_ptr<resource_handle>> resources;    // URI -> Maybe resource
41
42  public:
43  resource_handler(const std::vector<std::string>& resource_URIs_);
44  resource_handler();
45
46  public:
47  bool has(const std::string& URI)
48  {
49     for(const auto& r : resources)
50      {
51       if(URI == r->URI)
52        return true;
53      }
54
55     return false;
56  }
57
58  void add(const std::string& URI)
59  {
60     if(!has(URI))
61      resources.emplace_back(std::make_shared<resource_handle>(URI));
62  }
63
64  void find_resources()
65  {
66         for(const auto& resource : resources)
67          {
68                 std::cout << "* Finding resources \"" << resource->URI << "\".\n";
69
70                 call_timer.mark("find_resources");
71
72                 OC::OCPlatform::findResource("", resource->URI,
73                                       std::bind(&resource_handle::onFoundResource, resource, std::placeholders::_1));
74          }
75  }
76 };
77
78 std::vector<std::shared_ptr<resource_handle>> resource_handler::resources;
79
80 resource_handler::resource_handler(const std::vector<std::string>& resource_URIs)
81 {
82  for(const auto& URI : resource_URIs)
83   add(URI);
84 }
85
86 void resource_handle::onFoundResource(std::shared_ptr<OC::OCResource> in_resource)
87 {
88  using std::cout;
89
90  cout << "* onFoundResource():\n";
91
92  try
93   {
94        if(nullptr == in_resource)
95         throw OC::OCException("invalid resource passed to client callback");
96
97        call_timer.report_and_reset("find_resources");
98
99        // Now, fixup our own representation ptr:
100        resource = in_resource;
101
102        /* Note: You can combine the host and URI to get a unique identifier, for
103        example to filter out events you aren't interested in. Here, we just report the
104        data: */
105        cout << "resource URI: " << resource->uri() << "; "
106             << "host address: " << resource->host() << '\n';
107
108        call_timer.mark("get_resource");
109
110        OC::QueryParamsMap qpm;
111
112        resource->get(qpm, std::bind(&resource_handle::onResourceGet, this,
113             std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
114   }
115  catch(OC::OCException& e)
116   {
117         std::cerr << "onFoundResource(): exception " << e.reason() << ": " << e.what() << '\n';
118   }
119  catch(std::exception& e)
120   {
121         std::cerr << "onFoundResource(): exception: " << e.what() << '\n';
122   }
123 }
124
125 void resource_handle::onResourceGet(const OC::HeaderOptions& headerOptions,
126                 const OC::OCRepresentation rep, const int error_code)
127 {
128  using std::cout;
129
130  cout << "onResourceGet():\n";
131
132  call_timer.report_and_reset("get_resource");
133
134  if(error_code)
135   {
136         std::cerr << "onResourceGet(): error: " << error_code << '\n';
137         return;
138   }
139
140  if(nullptr == resource)
141   {
142         std::cerr << "onResourceGet(): empty resource pointer.\n";
143         return;
144   }
145
146  std::cout << "input attributes:\n";
147  std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue<bool>("state")<<"; ";
148  std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue<int>("power")<<"; \n";
149
150  // Now, make a change to the light representation (replacing, rather than parsing):
151  bool state = true;
152  int power = 10;
153
154  std::cout << "output attributes:\n";
155  std::cout << "Attribute \"" << "state" << "\": "<< state<<"; ";
156  std::cout << "Attribute \"" << "power" << "\": "<< power<<"; \n";
157
158  call_timer.mark("put_resource");
159
160  OC::OCRepresentation out_rep;
161  out_rep.setValue("state", state);
162  out_rep.setValue("power", power);
163
164  resource->put(out_rep, OC::QueryParamsMap(),
165                std::bind(&resource_handle::onResourcePut, this, std::placeholders::_1,
166                std::placeholders::_2, std::placeholders::_3));
167 }
168
169 void resource_handle::onResourcePut(const OC::HeaderOptions& headerOptions,
170             const OC::OCRepresentation rep, const int error_code)
171 {
172  std::cout << "onResourcePut():\n";
173
174  call_timer.report_and_reset("put_resource");
175
176  if(0 != error_code)
177   {
178         std::ostringstream os;
179
180         os << "onResourcePut(): error code " << error_code << " from server response.";
181
182         throw OC::OCException(os.str());
183   }
184
185  std::cout << "input attributes:\n";
186  std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue<bool>("state")<<"; ";
187  std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue<int>("power")<<"; \n";
188
189  call_timer.mark("observe_resource");
190
191  // Start an observer:
192  resource->observe(OC::ObserveType::Observe, OC::QueryParamsMap(),
193                 std::bind(&resource_handle::onObserve, this,
194                 std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,
195                 std::placeholders::_4));
196 }
197
198 void resource_handle::onObserve(const OC::HeaderOptions& headerOptions,
199             const OC::OCRepresentation rep, const int error_code, const int& sequence_number)
200 {
201  if(0 != error_code)
202   {
203     std::ostringstream os;
204     os << "onObserve(): error " << error_code << " from callback.\n";
205     throw OC::OCException(os.str());
206   }
207
208  std::cout << "onObserve(): sequence number: " << sequence_number << ":\n";
209
210  call_timer.report_and_reset("observe_resource");
211
212  std::cout << "Attribute \"" << "state" << "\": "<< rep.getValue<bool>("state")<<"; ";
213  std::cout << "Attribute \"" << "power" << "\": "<< rep.getValue<int>("power")<<"; \n";
214
215  const auto oc = observe_count();
216
217  std::cout << "onObserve(): observation count is: " << oc << '\n';
218
219  // We don't want to be observed forever for purposes of this demo:
220  if(10 <= oc)
221   {
222     std::cout << "onObserve(): cancelling observation.\n";
223
224     const auto result = resource->cancelObserve();
225
226     std::cout << "onObserve(): result of cancellation: " << result << ".\n";
227
228     this_thread::sleep_for(chrono::seconds(10));
229   }
230 }
231
232 }}} // namespace Intel::OCDemo::client
233
234