HomeScreenBinding
libhomescreen.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdarg.h>
18 #include <sys/socket.h>
19 #include <iostream>
20 #include <algorithm>
21 #include <errno.h>
22 #include <cassert>
23 #include <cctype>
24 #include <cerrno>
25 #include <cstdio>
26 #include <cstdlib>
27 #include <cstring>
28 
29 #include <libhomescreen.hpp>
30 #include "hmi-debug.h"
31 
32 using namespace std;
33 
34 static bool has_verb(const string& verb);
35 static const char API[] = "homescreen";
36 static const char ApplicationId[] = "application_id";
37 
38 const std::vector<std::string> LibHomeScreen::api_list {
39  std::string("ping"), // debug do not use
40  std::string("tap_shortcut"), // HomeScreen Application only
41  std::string("on_screen_message"),
42  std::string("on_screen_reply"),
43  std::string("subscribe"),
44  std::string("unsubscribe"),
45  std::string("showWindow"),
46  std::string("hideWindow"),
47  std::string("replyShowWindow"),
48  std::string("showNotification"),
49  std::string("showInformation")
50 };
51 
52 const std::vector<std::string> LibHomeScreen::event_list {
53 // std::string("tap_shortcut"),
54  std::string("showWindow"),
55  std::string("on_screen_message"),
56  std::string("on_screen_reply"),
57  std::string("hideWindow"),
58  std::string("replyShowWindow"),
59  std::string("showNotification"),
60  std::string("showInformation"),
61  std::string("none")
62 };
63 
64 
69 static void _on_hangup_static(void *closure, struct afb_wsj1 *wsj)
70 {
71  static_cast<LibHomeScreen*>(closure)->on_hangup(NULL,wsj);
72 }
73 
74 static void _on_call_static(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg)
75 {
76  /* LibHomeScreen is not called from other process */
77 }
78 
79 static void _on_event_static(void* closure, const char* event, struct afb_wsj1_msg *msg)
80 {
81  static_cast<LibHomeScreen*>(closure)->on_event(NULL,event,msg);
82 }
83 
84 static void _on_reply_static(void *closure, struct afb_wsj1_msg *msg)
85 {
86  static_cast<LibHomeScreen*>(closure)->on_reply(NULL,msg);
87 }
88 
89 
94 {
95 }
96 
101 {
102  if(mploop)
103  {
104  sd_event_unref(mploop);
105  }
106  if(sp_websock != NULL)
107  {
108  afb_wsj1_unref(sp_websock);
109  }
110 }
111 
126 int LibHomeScreen::init(const int port, const string& token)
127 {
128  int ret = 0;
129  if(port > 0 && token.size() > 0)
130  {
131  mport = port;
132  mtoken = token;
133  }
134  else
135  {
136  HMI_ERROR("libhomescreen","port and token should be > 0, Initial port and token uses.");
137  }
138 
139  ret = initialize_websocket();
140  if(ret != 0 )
141  {
142  HMI_ERROR("libhomescreen","Failed to initialize websocket");
143  }
144  else{
145  HMI_DEBUG("libhomescreen","Initialized");
146  }
147 
148  return ret;
149 }
150 
166  void (*event_cb)(const std::string& event, struct json_object* event_contents),
167  void (*reply_cb)(struct json_object* reply_contents),
168  void (*hangup_cb)(void))
169 {
170  onEvent = event_cb;
171  onReply = reply_cb;
172  onHangup = hangup_cb;
173 }
174 
175 int LibHomeScreen::initialize_websocket()
176 {
177  mploop = NULL;
178  onEvent = nullptr;
179  onReply = nullptr;
180  int ret = sd_event_default(&mploop);
181  if(ret < 0)
182  {
183  HMI_ERROR("libhomescreen","Failed to create event loop");
184  goto END;
185  }
186 
187  /* Initialize interface from websocket */
188  minterface.on_hangup = _on_hangup_static;
189  minterface.on_call = _on_call_static;
190  minterface.on_event = _on_event_static;
191  muri += "ws://localhost:" + to_string(mport) + "/api?token=" + mtoken; /*To be modified*/
192  sp_websock = afb_ws_client_connect_wsj1(mploop, muri.c_str(), &minterface, this);
193  if(sp_websock == NULL)
194  {
195  HMI_ERROR("libhomescreen","Failed to create websocket connection");
196  goto END;
197  }
198 
199  /* creates the evsrc */
200  //ret = sd_event_add_io(mploop,&mevent_src, sp_websock->fd, EPOLLIN, event_callback, NULL);
201 
202  return 0;
203 END:
204  if(mploop)
205  {
206  sd_event_unref(mploop);
207  }
208  return -1;
209 }
210 
222 int LibHomeScreen::tapShortcut(const char* application_id)
223 {
224  struct json_object* obj = json_object_new_object();
225  struct json_object* val = json_object_new_string("normal");
226  json_object_object_add(obj, "area", val);
227 
228  return showWindow(application_id, obj);
229 }
230 
242 int LibHomeScreen::onScreenMessage(const char* display_message)
243 {
244  if(!sp_websock)
245  {
246  return -1;
247  }
248 
249  struct json_object* j_obj = json_object_new_object();
250  struct json_object* val = json_object_new_string(display_message);
251  json_object_object_add(j_obj, "display_message", val);
252  return this->call("on_screen_message", j_obj);
253 }
254 
266 int LibHomeScreen::onScreenReply(const char* reply_message)
267 {
268  if(!sp_websock)
269  {
270  return -1;
271  }
272 
273  struct json_object* j_obj = json_object_new_object();
274  struct json_object* val = json_object_new_string(reply_message);
275  json_object_object_add(j_obj, "reply_message", val);
276  return this->call("on_screen_reply", j_obj);
277 }
278 
296 {
297  if (et >= 1 && et <= 7) {
298  switch (et) {
299 /* case Event_TapShortcut:
300  this->subscribe(LibHomeScreen::event_list[0]);
301  break;*/
302  case Event_ShowWindow:
304  break;
305  case Event_OnScreenMessage:
307  break;
308  case Event_OnScreenReply:
310  break;
311  case Event_HideWindow:
313  break;
314  case Event_ReplyShowWindow:
316  break;
317  case Event_ShowNotification:
319  break;
320  case Event_ShowInformation:
322  break;
323  }
324 
325  this->handlers[et] = std::move(f);
326  }
327 }
328 
343 int LibHomeScreen::call(const string& verb, struct json_object* arg)
344 {
345  int ret;
346  if(!sp_websock)
347  {
348  return -1;
349  }
350  if (!has_verb(verb))
351  {
352  HMI_ERROR("libhomescreen","verb doesn't exit");
353  return -1;
354  }
355  ret = afb_wsj1_call_j(sp_websock, API, verb.c_str(), arg, _on_reply_static, this);
356  if (ret < 0) {
357  HMI_ERROR("libhomescreen","Failed to call verb:%s",verb.c_str());
358  }
359  return ret;
360 }
361 
377 int LibHomeScreen::call(const char* verb, struct json_object* arg)
378 {
379  int ret;
380  if(!sp_websock)
381  {
382  return -1;
383  }
384  if (!has_verb(string(verb)))
385  {
386  HMI_ERROR("libhomescreen","verb doesn't exit");
387  return -1;
388  }
389  ret = afb_wsj1_call_j(sp_websock, API, verb, arg, _on_reply_static, this);
390  if (ret < 0) {
391  HMI_ERROR("libhomescreen","Failed to call verb:%s",verb);
392  }
393  return ret;
394 }
395 
409 int LibHomeScreen::subscribe(const string& event_name)
410 {
411  if(!sp_websock)
412  {
413  return -1;
414  }
415  struct json_object* j_obj = json_object_new_object();
416  json_object_object_add(j_obj, "event", json_object_new_string(event_name.c_str()));
417 
418  int ret = afb_wsj1_call_j(sp_websock, API, "subscribe", j_obj, _on_reply_static, this);
419  if (ret < 0) {
420  HMI_ERROR("libhomescreen","Failed to call verb");
421  }
422  return ret;
423 }
424 
438 int LibHomeScreen::unsubscribe(const string& event_name)
439 {
440  if(!sp_websock)
441  {
442  return -1;
443  }
444  struct json_object* j_obj = json_object_new_object();
445  json_object_object_add(j_obj, "event", json_object_new_string(event_name.c_str()));
446 
447  int ret = afb_wsj1_call_j(sp_websock, API, "unsubscribe", j_obj, _on_reply_static, this);
448  if (ret < 0) {
449  HMI_ERROR("libhomescreen","Failed to call verb");
450  }
451  return ret;
452 }
453 
467 int LibHomeScreen::showWindow(const char* application_id, json_object* json)
468 {
469  if(!sp_websock)
470  {
471  return -1;
472  }
473 
474  struct json_object* j_obj = json_object_new_object();
475  struct json_object* val = json_object_new_string(application_id);
476  json_object_object_add(j_obj, ApplicationId, val);
477 
478  if (json == nullptr) {
479  struct json_object* j_json = json_object_new_object();
480  struct json_object* value = json_object_new_string("normal");
481  json_object_object_add(j_json, "area", value);
482  json_object_object_add(j_obj, "parameter", j_json);
483  }
484  else {
485  json_object_object_add(j_obj, "parameter", json);
486  }
487 
488  return this->call("showWindow", j_obj);
489 }
490 
503 int LibHomeScreen::hideWindow(const char* application_id)
504 {
505  if(!sp_websock)
506  {
507  return -1;
508  }
509 
510  struct json_object* j_obj = json_object_new_object();
511  struct json_object* val = json_object_new_string(application_id);
512  json_object_object_add(j_obj, ApplicationId, val);
513 
514  return this->call("hideWindow", j_obj);
515 }
516 
530 int LibHomeScreen::replyShowWindow(const char* application_id, json_object* json)
531 {
532  if(!sp_websock)
533  {
534  return -1;
535  }
536 
537  if (json == nullptr) {
538  HMI_WARNING("libhomescreen", "replyShowWindow`s parameter is null");
539  return -1;
540  }
541 
542  struct json_object* j_obj = json_object_new_object();
543  struct json_object* val = json_object_new_string(application_id);
544  json_object_object_add(j_obj, ApplicationId, val);
545  json_object_object_add(j_obj, "parameter", json);
546 
547  return this->call("replyShowWindow", j_obj);
548 }
549 
562 int LibHomeScreen::showNotification(json_object* json)
563 {
564  if(!sp_websock)
565  {
566  return -1;
567  }
568 
569  return this->call("showNotification", json);
570 }
571 
584 int LibHomeScreen::showInformation(json_object* json)
585 {
586  if(!sp_websock)
587  {
588  return -1;
589  }
590 
591  return this->call("showInformation", json);
592 }
593 
594 
595 /************* Callback Function *************/
596 
597 void LibHomeScreen::on_hangup(void *closure, struct afb_wsj1 *wsj)
598 {
599  HMI_DEBUG("libhomescreen","called");
600  if(onHangup != nullptr)
601  {
602  onHangup();
603  }
604 }
605 
606 void LibHomeScreen::on_call(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg)
607 {
608 }
609 
610 /*
611 * event is like "homescreen/hvac"
612 * msg is like {"event":"homescreen\/hvac","data":{"type":"tap_shortcut"},"jtype":"afb-event"}
613 * so you can get
614  event name : struct json_object obj = json_object_object_get(msg,"event")
615 */
616 void LibHomeScreen::on_event(void *closure, const char *event, struct afb_wsj1_msg *msg)
617 {
618  HMI_DEBUG("libhomescreen","event: (%s) msg: (%s).", event, afb_wsj1_msg_object_s(msg));
619 
620  if (strstr(event, API) == NULL) {
621  return;
622  }
623 
624  struct json_object* ev_contents = afb_wsj1_msg_object_j(msg);
625  struct json_object *json_data;
626  if(!json_object_object_get_ex(ev_contents, "data", &json_data)) {
627  HMI_ERROR("libhomescreen", "got ev_contents error.");
628  return;
629  }
630 
631  if(onEvent != nullptr)
632  {
633  const string ev(event);
634  onEvent(ev, ev_contents);
635  }
636 
637  const char* event_type = nullptr;
638  struct json_object *json_event_type;
639  if(json_object_object_get_ex(json_data, "type", &json_event_type)) {
640  event_type = json_object_get_string(json_event_type);
641  }
642  else {
643  HMI_WARNING("libhomescreen","event_type is null.");
644  return;
645  }
646 
647  if (strcasecmp(event_type, LibHomeScreen::event_list[0].c_str()) == 0) {
648  auto i = this->handlers.find(Event_ShowWindow);
649  if ( i != this->handlers.end() ) {
650  i->second(json_data);
651  }
652  }
653  else if (strcasecmp(event_type, LibHomeScreen::event_list[1].c_str()) == 0) {
654  auto i = this->handlers.find(Event_OnScreenMessage);
655  if ( i != this->handlers.end() ) {
656  i->second(json_data);
657  }
658  }
659  else if (strcasecmp(event_type, LibHomeScreen::event_list[2].c_str()) == 0) {
660  auto i = this->handlers.find(Event_OnScreenReply);
661  if ( i != this->handlers.end() ) {
662  i->second(json_data);
663  }
664  }
665  else if (strcasecmp(event_type, LibHomeScreen::event_list[3].c_str()) == 0) {
666  auto i = this->handlers.find(Event_HideWindow);
667  if ( i != this->handlers.end() ) {
668  i->second(json_data);
669  }
670  }
671  else if (strcasecmp(event_type, LibHomeScreen::event_list[4].c_str()) == 0) {
672  auto i = this->handlers.find(Event_ReplyShowWindow);
673  if ( i != this->handlers.end() ) {
674  i->second(json_data);
675  }
676  }
677  else if (strcasecmp(event_type, LibHomeScreen::event_list[5].c_str()) == 0) {
678  auto i = this->handlers.find(Event_ShowNotification);
679  if ( i != this->handlers.end() ) {
680  i->second(json_data);
681  }
682  }
683  else if (strcasecmp(event_type, LibHomeScreen::event_list[6].c_str()) == 0) {
684  auto i = this->handlers.find(Event_ShowInformation);
685  if ( i != this->handlers.end() ) {
686  i->second(json_data);
687  }
688  }
689 }
690 
695 void LibHomeScreen::on_reply(void *closure, struct afb_wsj1_msg *msg)
696 {
697  HMI_DEBUG("libhomescreen","msg: (%s)", afb_wsj1_msg_object_s(msg));
698  if(onReply != nullptr)
699  {
700  struct json_object* reply = afb_wsj1_msg_object_j(msg);
701  onReply(reply);
702  }
703 }
704 
705 static bool has_verb(const string& verb)
706 {
707  HMI_DEBUG("libhomescreen","verb is %s", verb.c_str());
708  if(find(LibHomeScreen::api_list.begin(), LibHomeScreen::api_list.end(), verb) != LibHomeScreen::api_list.end())
709  return true;
710  else
711  return false;
712 }
void on_event(void *closure, const char *event, struct afb_wsj1_msg *msg)
static void _on_hangup_static(void *closure, struct afb_wsj1 *wsj)
void on_reply(void *closure, struct afb_wsj1_msg *msg)
static void showWindow(afb_req_t request)
Definition: homescreen.cpp:194
int onScreenReply(const char *reply_message)
std::function< void(json_object *)> handler_func
void on_call(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg)
static void subscribe(afb_req_t request)
Definition: homescreen.cpp:140
int tapShortcut(const char *application_id)
static void _on_call_static(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg)
static const char API[]
int hideWindow(const char *application_id)
int showWindow(const char *application_id, json_object *json)
static const char ApplicationId[]
int replyShowWindow(const char *application_id, json_object *json)
string token
Definition: simple-egl.cpp:61
int call(const std::string &verb, struct json_object *arg)
int showInformation(json_object *json)
void on_hangup(void *closure, struct afb_wsj1 *wsj)
int subscribe(const std::string &event_name)
#define HMI_WARNING(prefix, args,...)
Definition: hmi-debug.h:39
long port
Definition: simple-egl.cpp:60
static const std::vector< std::string > event_list
int init(const int port, const std::string &token)
static bool has_verb(const string &verb)
static void _on_event_static(void *closure, const char *event, struct afb_wsj1_msg *msg)
#define HMI_ERROR(prefix, args,...)
Definition: hmi-debug.h:38
#define HMI_DEBUG(prefix, args,...)
Definition: hmi-debug.h:42
int onScreenMessage(const char *display_message)
static const std::vector< std::string > api_list
int unsubscribe(const std::string &event_name)
void set_event_handler(enum EventType et, handler_func f)
void registerCallback(void(*event_cb)(const std::string &event, struct json_object *event_contents), void(*reply_cb)(struct json_object *reply_contents), void(*hangup_cb)(void)=nullptr)
int showNotification(json_object *json)
static void _on_reply_static(void *closure, struct afb_wsj1_msg *msg)