2 * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include <sys/socket.h>
29 #include <libhomescreen.hpp>
30 #include "hmi-debug.h"
34 static bool has_verb(const string& verb);
35 static const char API[] = "homescreen";
36 static const char ApplicationId[] = "application_id";
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")
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"),
69 static void _on_hangup_static(void *closure, struct afb_wsj1 *wsj)
71 static_cast<LibHomeScreen*>(closure)->on_hangup(NULL,wsj);
74 static void _on_call_static(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg)
76 /* LibHomeScreen is not called from other process */
79 static void _on_event_static(void* closure, const char* event, struct afb_wsj1_msg *msg)
81 static_cast<LibHomeScreen*>(closure)->on_event(NULL,event,msg);
84 static void _on_reply_static(void *closure, struct afb_wsj1_msg *msg)
86 static_cast<LibHomeScreen*>(closure)->on_reply(NULL,msg);
93 LibHomeScreen::LibHomeScreen()
100 LibHomeScreen::~LibHomeScreen()
104 sd_event_unref(mploop);
106 if(sp_websock != NULL)
108 afb_wsj1_unref(sp_websock);
113 * This function is initializer
116 * - port [in] : This argument should be specified to the port number to be used for websocket
117 * - token [in] : This argument should be specified to the token to be used for websocket
123 * Use this constructor
126 int LibHomeScreen::init(const int port, const string& token)
129 if(port > 0 && token.size() > 0)
136 HMI_ERROR("libhomescreen","port and token should be > 0, Initial port and token uses.");
139 ret = initialize_websocket();
142 HMI_ERROR("libhomescreen","Failed to initialize websocket");
145 HMI_DEBUG("libhomescreen","Initialized");
152 * This function register callback function for reply/event message from home screen
155 * - event_cb [in] : This argument should be specified to the callback for subscribed event
156 * - reply_cb [in] : This argument should be specified to the reply callback for call function
162 * Event callback is invoked by home screen for event you subscribed.
163 * If you would like to get event, please call subscribe function before/after this function
165 void LibHomeScreen::registerCallback(
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))
172 onHangup = hangup_cb;
175 int LibHomeScreen::initialize_websocket()
180 int ret = sd_event_default(&mploop);
183 HMI_ERROR("libhomescreen","Failed to create event loop");
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)
195 HMI_ERROR("libhomescreen","Failed to create websocket connection");
199 /* creates the evsrc */
200 //ret = sd_event_add_io(mploop,&mevent_src, sp_websock->fd, EPOLLIN, event_callback, NULL);
206 sd_event_unref(mploop);
212 * Sending ShortCut Icon tapped event
214 * When HomeScreen shortcut area is tapped, sending a event
217 * - application_id [in] : Tapped application id (label)
220 * - Returns 0 on success or -1 in case of error.
222 int LibHomeScreen::tapShortcut(const char* application_id)
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);
228 return showWindow(application_id, obj);
232 * Sending onScreen message event
234 * Sending OnScreen message event to HomeScreen from applications
237 * - display_message [in] : message for display
240 * - Returns 0 on success or -1 in case of error.
242 int LibHomeScreen::onScreenMessage(const char* display_message)
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);
256 * Sending onScreen reply event
258 * Sending OnScreen reply event to applications from HomeScreen
261 * - reply_message [in] : message for reply
264 * - Returns 0 on success or -1 in case of error.
266 int LibHomeScreen::onScreenReply(const char* reply_message)
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);
280 * Setting Event Handler
282 * Setting event handler for Homescreen
285 * - et [in] : event name
286 * - f [in] : event handler
292 * Don't release json_object by json_object_put in handler_func.
293 * The resource is released by libafbwsc library.
295 void LibHomeScreen::set_event_handler(enum EventType et, handler_func f)
297 if (et >= 1 && et <= 7) {
299 case Event_ShowWindow:
300 this->subscribe(LibHomeScreen::event_list[0]);
302 case Event_OnScreenMessage:
303 this->subscribe(LibHomeScreen::event_list[1]);
305 case Event_OnScreenReply:
306 this->subscribe(LibHomeScreen::event_list[2]);
308 case Event_HideWindow:
309 this->subscribe(LibHomeScreen::event_list[3]);
311 case Event_ReplyShowWindow:
312 this->subscribe(LibHomeScreen::event_list[4]);
314 case Event_ShowNotification:
315 this->subscribe(LibHomeScreen::event_list[5]);
317 case Event_ShowInformation:
318 this->subscribe(LibHomeScreen::event_list[6]);
322 this->handlers[et] = std::move(f);
327 * This function calls the API of HomeScreen via WebSocket
330 * - verb [in] : This argument should be specified to the API name (e.g. "tap_shortcut")
331 * - arg [in] : This argument should be specified to the argument of API. And this argument expects JSON object
334 * - Returns 0 on success or -1 in case of error.
337 * To call HomeScreen's APIs, the application should set its function name, arguments to JSON format.
340 int LibHomeScreen::call(const string& verb, struct json_object* arg)
349 HMI_ERROR("libhomescreen","verb doesn't exit");
352 ret = afb_wsj1_call_j(sp_websock, API, verb.c_str(), arg, _on_reply_static, this);
354 HMI_ERROR("libhomescreen","Failed to call verb:%s",verb.c_str());
360 * This function calls the API of HomeScreen via WebSocket
361 * This function is overload function of "call"
364 * - verb [in] : This argument should be specified to the API name (e.g. "tap_shortcut")
365 * - arg [in] : This argument should be specified to the argument of API. And this argument expects JSON object
368 * - Returns 0 on success or -1 in case of error.
371 * To call HomeScreen's APIs, the application should set its function name, arguments to JSON format.
374 int LibHomeScreen::call(const char* verb, struct json_object* arg)
381 if (!has_verb(string(verb)))
383 HMI_ERROR("libhomescreen","verb doesn't exit");
386 ret = afb_wsj1_call_j(sp_websock, API, verb, arg, _on_reply_static, this);
388 HMI_ERROR("libhomescreen","Failed to call verb:%s",verb);
394 * Register callback function for each event
397 * - event_name [in] : This argument should be specified to the event name
400 * - Returns 0 on success or -1 in case of error.
403 * This function enables to get an event to your callback function.
406 int LibHomeScreen::subscribe(const string& event_name)
412 struct json_object* j_obj = json_object_new_object();
413 json_object_object_add(j_obj, "event", json_object_new_string(event_name.c_str()));
415 int ret = afb_wsj1_call_j(sp_websock, API, "subscribe", j_obj, _on_reply_static, this);
417 HMI_ERROR("libhomescreen","Failed to call verb");
423 * Unregister callback function for each event
426 * - event_name [in] : This argument should be specified to the event name
429 * - Returns 0 on success or -1 in case of error.
432 * This function disables to get an event to your callback function.
435 int LibHomeScreen::unsubscribe(const string& event_name)
441 struct json_object* j_obj = json_object_new_object();
442 json_object_object_add(j_obj, "event", json_object_new_string(event_name.c_str()));
444 int ret = afb_wsj1_call_j(sp_websock, API, "unsubscribe", j_obj, _on_reply_static, this);
446 HMI_ERROR("libhomescreen","Failed to call verb");
452 * Sending show window event
454 * Call HomeScreen Service's showWindow verb to request display id's screen.
457 * - application_id [in] : This argument should be specified to the application's id.
458 * - json [in] : This argument should be specified to the json parameters.
461 * - Returns 0 on success or -1 in case of error.
464 int LibHomeScreen::showWindow(const char* application_id, json_object* json)
471 struct json_object* j_obj = json_object_new_object();
472 struct json_object* val = json_object_new_string(application_id);
473 json_object_object_add(j_obj, ApplicationId, val);
475 if (json == nullptr) {
476 struct json_object* j_json = json_object_new_object();
477 struct json_object* value = json_object_new_string("normal");
478 json_object_object_add(j_json, "area", value);
479 json_object_object_add(j_obj, "parameter", j_json);
482 json_object_object_add(j_obj, "parameter", json);
485 return this->call("showWindow", j_obj);
489 * Sending hide window event
491 * Call HomeScreen Service's hideWindow verb to release id's screen.
494 * - application_id [in] : This argument should be specified to the application's id.
497 * - Returns 0 on success or -1 in case of error.
500 int LibHomeScreen::hideWindow(const char* application_id)
507 struct json_object* j_obj = json_object_new_object();
508 struct json_object* val = json_object_new_string(application_id);
509 json_object_object_add(j_obj, ApplicationId, val);
511 return this->call("hideWindow", j_obj);
515 * Sending reply onscreen message event
517 * Call HomeScreen Service's replyShowWindow verb to reply onscreen message.
520 * - application_id [in] : This argument should be specified to the onscreen reply to applilcation id.
521 * - json [in] : This argument should be specified to the json parameters.
524 * - Returns 0 on success or -1 in case of error.
527 int LibHomeScreen::replyShowWindow(const char* application_id, json_object* json)
534 if (json == nullptr) {
535 HMI_WARNING("libhomescreen", "replyShowWindow`s parameter is null");
539 struct json_object* j_obj = json_object_new_object();
540 struct json_object* val = json_object_new_string(application_id);
541 json_object_object_add(j_obj, ApplicationId, val);
542 json_object_object_add(j_obj, "parameter", json);
544 return this->call("replyShowWindow", j_obj);
548 * Sending show notification event
550 * Call HomeScreen Service's notification verb to show notification on Status Bar.
553 * - json [in] : This argument should be specified to the json parameters.
556 * - Returns 0 on success or -1 in case of error.
559 int LibHomeScreen::showNotification(json_object* json)
566 return this->call("showNotification", json);
570 * Sending show information event
572 * Call HomeScreen Service's information verb to show notification on Information Bar.
575 * - json [in] : This argument should be specified to the json parameters.
578 * - Returns 0 on success or -1 in case of error.
581 int LibHomeScreen::showInformation(json_object* json)
588 return this->call("showInformation", json);
592 /************* Callback Function *************/
594 void LibHomeScreen::on_hangup(void *closure, struct afb_wsj1 *wsj)
596 HMI_DEBUG("libhomescreen","called");
597 if(onHangup != nullptr)
603 void LibHomeScreen::on_call(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg)
608 * event is like "homescreen/hvac"
609 * msg is like {"event":"homescreen\/hvac","data":{"type":"tap_shortcut"},"jtype":"afb-event"}
611 event name : struct json_object obj = json_object_object_get(msg,"event")
613 void LibHomeScreen::on_event(void *closure, const char *event, struct afb_wsj1_msg *msg)
615 HMI_DEBUG("libhomescreen","event: (%s) msg: (%s).", event, afb_wsj1_msg_object_s(msg));
617 if (strstr(event, API) == NULL) {
621 struct json_object* ev_contents = afb_wsj1_msg_object_j(msg);
622 struct json_object *json_data;
623 if(!json_object_object_get_ex(ev_contents, "data", &json_data)) {
624 HMI_ERROR("libhomescreen", "got ev_contents error.");
628 if(onEvent != nullptr)
630 const string ev(event);
631 onEvent(ev, ev_contents);
634 const char* event_type = nullptr;
635 struct json_object *json_event_type;
636 if(json_object_object_get_ex(json_data, "type", &json_event_type)) {
637 event_type = json_object_get_string(json_event_type);
640 HMI_WARNING("libhomescreen","event_type is null.");
644 if (strcasecmp(event_type, LibHomeScreen::event_list[0].c_str()) == 0) {
645 auto i = this->handlers.find(Event_ShowWindow);
646 if ( i != this->handlers.end() ) {
647 i->second(json_data);
650 else if (strcasecmp(event_type, LibHomeScreen::event_list[1].c_str()) == 0) {
651 auto i = this->handlers.find(Event_OnScreenMessage);
652 if ( i != this->handlers.end() ) {
653 i->second(json_data);
656 else if (strcasecmp(event_type, LibHomeScreen::event_list[2].c_str()) == 0) {
657 auto i = this->handlers.find(Event_OnScreenReply);
658 if ( i != this->handlers.end() ) {
659 i->second(json_data);
662 else if (strcasecmp(event_type, LibHomeScreen::event_list[3].c_str()) == 0) {
663 auto i = this->handlers.find(Event_HideWindow);
664 if ( i != this->handlers.end() ) {
665 i->second(json_data);
668 else if (strcasecmp(event_type, LibHomeScreen::event_list[4].c_str()) == 0) {
669 auto i = this->handlers.find(Event_ReplyShowWindow);
670 if ( i != this->handlers.end() ) {
671 i->second(json_data);
674 else if (strcasecmp(event_type, LibHomeScreen::event_list[5].c_str()) == 0) {
675 auto i = this->handlers.find(Event_ShowNotification);
676 if ( i != this->handlers.end() ) {
677 i->second(json_data);
680 else if (strcasecmp(event_type, LibHomeScreen::event_list[6].c_str()) == 0) {
681 auto i = this->handlers.find(Event_ShowInformation);
682 if ( i != this->handlers.end() ) {
683 i->second(json_data);
689 * msg is like ({"response":{"verb":"subscribe","error":0},"jtype":"afb-reply","request":{"status":"success","info":"homescreen binder subscribe event name [on_screen_message]"}})
690 * msg is like ({"response":{"verb":"tap_shortcut","error":0},"jtype":"afb-reply","request":{"status":"success","info":"afb_event_push event [tap_shortcut]"}})
692 void LibHomeScreen::on_reply(void *closure, struct afb_wsj1_msg *msg)
694 HMI_DEBUG("libhomescreen","msg: (%s)", afb_wsj1_msg_object_s(msg));
695 if(onReply != nullptr)
697 struct json_object* reply = afb_wsj1_msg_object_j(msg);
702 static bool has_verb(const string& verb)
704 HMI_DEBUG("libhomescreen","verb is %s", verb.c_str());
705 if(find(LibHomeScreen::api_list.begin(), LibHomeScreen::api_list.end(), verb) != LibHomeScreen::api_list.end())