2 * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
3 * Copyright (c) 2018,2019 TOYOTA MOTOR CORPORATION
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
19 #include <sys/socket.h>
31 #include <libhomescreen.hpp>
32 #include "hmi-debug.h"
36 static bool has_verb(const string& verb);
37 static const char API[] = "homescreen";
38 static const char ApplicationId[] = "application_id";
40 const std::vector<std::string> LibHomeScreen::api_list {
41 std::string("ping"), // debug do not use
42 std::string("tap_shortcut"), // HomeScreen Application only
43 std::string("on_screen_message"),
44 std::string("on_screen_reply"),
45 std::string("subscribe"),
46 std::string("unsubscribe"),
47 std::string("showWindow"),
48 std::string("hideWindow"),
49 std::string("replyShowWindow"),
50 std::string("showNotification"),
51 std::string("showInformation"),
52 std::string("getRunnables"),
53 std::string("registerShortcut"),
54 std::string("updateShortcut")
57 const std::vector<std::string> LibHomeScreen::event_list {
58 // std::string("tap_shortcut"),
59 std::string("showWindow"),
60 std::string("on_screen_message"),
61 std::string("on_screen_reply"),
62 std::string("hideWindow"),
63 std::string("replyShowWindow"),
64 std::string("showNotification"),
65 std::string("showInformation"),
66 std::string("application-list-changed"),
67 std::string("registerShortcut"),
68 std::string("updateShortcut"),
69 std::string("setDestination"),
70 std::string("cancelDestination"),
71 std::string("startNavigation"),
72 std::string("stopNavigation"),
81 static void _on_hangup_static(void *closure, struct afb_wsj1 *wsj)
83 static_cast<LibHomeScreen*>(closure)->on_hangup(NULL,wsj);
86 static void _on_call_static(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg)
88 /* LibHomeScreen is not called from other process */
91 static void _on_event_static(void* closure, const char* event, struct afb_wsj1_msg *msg)
93 static_cast<LibHomeScreen*>(closure)->on_event(NULL,event,msg);
96 static void _on_reply_static(void *closure, struct afb_wsj1_msg *msg)
98 static_cast<LibHomeScreen*>(closure)->on_reply(NULL,msg);
102 static void event_loop_run(struct sd_event* loop){
104 sd_event_unref(loop);
111 LibHomeScreen::LibHomeScreen()
118 LibHomeScreen::~LibHomeScreen()
120 if(sp_websock != NULL)
122 afb_wsj1_unref(sp_websock);
126 sd_event_exit(mploop, 0);
131 * This function is initializer
134 * - port [in] : This argument should be specified to the port number to be used for websocket
135 * - token [in] : This argument should be specified to the token to be used for websocket
141 * Use this constructor
144 int LibHomeScreen::init(const int port, const string& token)
147 if(port > 0 && token.size() > 0)
154 HMI_ERROR("libhomescreen","port and token should be > 0, Initial port and token uses.");
157 ret = initialize_websocket();
160 HMI_ERROR("libhomescreen","Failed to initialize websocket");
163 HMI_DEBUG("libhomescreen","Initialized");
170 * This function register callback function for reply/event message from home screen
173 * - event_cb [in] : This argument should be specified to the callback for subscribed event
174 * - reply_cb [in] : This argument should be specified to the reply callback for call function
180 * Event callback is invoked by home screen for event you subscribed.
181 * If you would like to get event, please call subscribe function before/after this function
183 void LibHomeScreen::registerCallback(
184 void (*event_cb)(const std::string& event, struct json_object* event_contents),
185 void (*reply_cb)(struct json_object* reply_contents),
186 void (*hangup_cb)(void))
190 onHangup = hangup_cb;
193 int LibHomeScreen::initialize_websocket()
198 int ret = sd_event_new(&mploop);
201 HMI_ERROR("libhomescreen","Failed to create event loop");
206 // enforce context to avoid initialization/goto error
207 std::thread th(event_loop_run, mploop);
211 /* Initialize interface from websocket */
212 minterface.on_hangup = _on_hangup_static;
213 minterface.on_call = _on_call_static;
214 minterface.on_event = _on_event_static;
215 muri += "ws://localhost:" + to_string(mport) + "/api?token=" + mtoken; /*To be modified*/
216 sp_websock = afb_ws_client_connect_wsj1(mploop, muri.c_str(), &minterface, this);
217 if(sp_websock == NULL)
219 HMI_ERROR("libhomescreen","Failed to create websocket connection");
223 /* creates the evsrc */
224 //ret = sd_event_add_io(mploop,&mevent_src, sp_websock->fd, EPOLLIN, event_callback, NULL);
232 * Sending ShortCut Icon tapped event
234 * When HomeScreen shortcut area is tapped, sending a event
237 * - application_id [in] : Tapped application id (label)
240 * - Returns 0 on success or -1 in case of error.
242 int LibHomeScreen::tapShortcut(const char* application_id)
244 struct json_object* obj = json_object_new_object();
245 struct json_object* val = json_object_new_string("normal");
246 json_object_object_add(obj, "area", val);
248 return showWindow(application_id, obj);
252 * Sending onScreen message event
254 * Sending OnScreen message event to HomeScreen from applications
257 * - display_message [in] : message for display
260 * - Returns 0 on success or -1 in case of error.
262 int LibHomeScreen::onScreenMessage(const char* display_message)
269 struct json_object* j_obj = json_object_new_object();
270 struct json_object* val = json_object_new_string(display_message);
271 json_object_object_add(j_obj, "display_message", val);
272 return this->call("on_screen_message", j_obj);
276 * Sending onScreen reply event
278 * Sending OnScreen reply event to applications from HomeScreen
281 * - reply_message [in] : message for reply
284 * - Returns 0 on success or -1 in case of error.
286 int LibHomeScreen::onScreenReply(const char* reply_message)
293 struct json_object* j_obj = json_object_new_object();
294 struct json_object* val = json_object_new_string(reply_message);
295 json_object_object_add(j_obj, "reply_message", val);
296 return this->call("on_screen_reply", j_obj);
300 * Setting Event Handler
302 * Setting event handler for Homescreen
305 * - et [in] : event name
306 * - f [in] : event handler
312 * Don't release json_object by json_object_put in handler_func.
313 * The resource is released by libafbwsc library.
315 void LibHomeScreen::set_event_handler(enum EventType et, handler_func f)
317 if (et > Event_Min && et < Event_Max) {
318 this->handlers[et] = std::move(f);
323 * This function subscribe HomeScreen event
332 * To call HomeScreen's subscribe APIs.
335 void LibHomeScreen::publishSubscription(void)
337 struct json_object* j_obj = json_object_new_array();
338 for(auto &it : handlers) {
339 json_object_array_add(j_obj, json_object_new_string(LibHomeScreen::event_list[it.first - 1].c_str()));
345 struct json_object* push_obj = json_object_new_object();
346 json_object_object_add(push_obj, "event", j_obj);
348 int ret = afb_wsj1_call_j(sp_websock, API, "subscribe", push_obj, _on_reply_static, this);
350 HMI_ERROR("libhomescreen","Failed to call subscribe.");
355 * This function calls the API of HomeScreen via WebSocket
358 * - verb [in] : This argument should be specified to the API name (e.g. "tap_shortcut")
359 * - arg [in] : This argument should be specified to the argument of API. And this argument expects JSON object
362 * - Returns 0 on success or -1 in case of error.
365 * To call HomeScreen's APIs, the application should set its function name, arguments to JSON format.
368 int LibHomeScreen::call(const string& verb, struct json_object* arg)
377 HMI_ERROR("libhomescreen","verb doesn't exit");
380 ret = afb_wsj1_call_j(sp_websock, API, verb.c_str(), arg, _on_reply_static, this);
382 HMI_ERROR("libhomescreen","Failed to call verb:%s",verb.c_str());
388 * This function calls the API of HomeScreen via WebSocket
389 * This function is overload function of "call"
392 * - verb [in] : This argument should be specified to the API name (e.g. "tap_shortcut")
393 * - arg [in] : This argument should be specified to the argument of API. And this argument expects JSON object
396 * - Returns 0 on success or -1 in case of error.
399 * To call HomeScreen's APIs, the application should set its function name, arguments to JSON format.
402 int LibHomeScreen::call(const char* verb, struct json_object* arg)
409 if (!has_verb(string(verb)))
411 HMI_ERROR("libhomescreen","verb doesn't exit");
414 ret = afb_wsj1_call_j(sp_websock, API, verb, arg, _on_reply_static, this);
416 HMI_ERROR("libhomescreen","Failed to call verb:%s",verb);
422 * Register callback function for each event
425 * - event_name [in] : This argument should be specified to the event name
428 * - Returns 0 on success or -1 in case of error.
431 * This function enables to get an event to your callback function.
434 int LibHomeScreen::subscribe(const string& event_name)
440 struct json_object* j_obj = json_object_new_object();
441 json_object_object_add(j_obj, "event", json_object_new_string(event_name.c_str()));
443 int ret = afb_wsj1_call_j(sp_websock, API, "subscribe", j_obj, _on_reply_static, this);
445 HMI_ERROR("libhomescreen","Failed to call verb");
451 * Unregister callback function for each event
454 * - event_name [in] : This argument should be specified to the event name
457 * - Returns 0 on success or -1 in case of error.
460 * This function disables to get an event to your callback function.
463 int LibHomeScreen::unsubscribe(const string& event_name)
469 struct json_object* j_obj = json_object_new_object();
470 json_object_object_add(j_obj, "event", json_object_new_string(event_name.c_str()));
472 int ret = afb_wsj1_call_j(sp_websock, API, "unsubscribe", j_obj, _on_reply_static, this);
474 HMI_ERROR("libhomescreen","Failed to call verb");
480 * Sending show window event
482 * Call HomeScreen Service's showWindow verb to request display id's screen.
485 * - application_id [in] : This argument should be specified to the application's id.
486 * - json [in] : This argument should be specified to the json parameters.
489 * - Returns 0 on success or -1 in case of error.
492 int LibHomeScreen::showWindow(const char* application_id, json_object* json)
499 struct json_object* j_obj = json_object_new_object();
500 struct json_object* val = json_object_new_string(application_id);
501 json_object_object_add(j_obj, ApplicationId, val);
503 if (json == nullptr) {
504 struct json_object* j_json = json_object_new_object();
505 struct json_object* value = json_object_new_string("normal");
506 json_object_object_add(j_json, "area", value);
507 json_object_object_add(j_obj, "parameter", j_json);
510 json_object_object_add(j_obj, "parameter", json);
513 return this->call("showWindow", j_obj);
517 * Sending hide window event
519 * Call HomeScreen Service's hideWindow verb to release id's screen.
522 * - application_id [in] : This argument should be specified to the application's id.
525 * - Returns 0 on success or -1 in case of error.
528 int LibHomeScreen::hideWindow(const char* application_id)
535 struct json_object* j_obj = json_object_new_object();
536 struct json_object* val = json_object_new_string(application_id);
537 json_object_object_add(j_obj, ApplicationId, val);
539 return this->call("hideWindow", j_obj);
543 * Sending reply onscreen message event
545 * Call HomeScreen Service's replyShowWindow verb to reply onscreen message.
548 * - application_id [in] : This argument should be specified to the onscreen reply to applilcation id.
549 * - json [in] : This argument should be specified to the json parameters.
552 * - Returns 0 on success or -1 in case of error.
555 int LibHomeScreen::replyShowWindow(const char* application_id, json_object* json)
562 if (json == nullptr) {
563 HMI_WARNING("libhomescreen", "replyShowWindow`s parameter is null");
567 struct json_object* j_obj = json_object_new_object();
568 struct json_object* val = json_object_new_string(application_id);
569 json_object_object_add(j_obj, ApplicationId, val);
570 json_object_object_add(j_obj, "parameter", json);
572 return this->call("replyShowWindow", j_obj);
576 * Sending show notification event
578 * Call HomeScreen Service's notification verb to show notification on Status Bar.
581 * - json [in] : This argument should be specified to the json parameters.
584 * - Returns 0 on success or -1 in case of error.
587 int LibHomeScreen::showNotification(json_object* json)
594 return this->call("showNotification", json);
598 * Sending show information event
600 * Call HomeScreen Service's information verb to show notification on Information Bar.
603 * - json [in] : This argument should be specified to the json parameters.
606 * - Returns 0 on success or -1 in case of error.
609 int LibHomeScreen::showInformation(json_object* json)
616 return this->call("showInformation", json);
622 * Call HomeScreen Service's getRunnables verb to get runnalbes list.
628 * - Returns 0 on success or -1 in case of error.
631 int LibHomeScreen::getRunnables(void)
633 return this->call("getRunnables", nullptr);
637 * register shortcut to homescreen
639 * Call HomeScreen Service's registerShortcut verb to regitster shortcut.
642 * - json [in] : This argument should be specified to the json parameters.
645 * - Returns 0 on success or -1 in case of error.
648 int LibHomeScreen::registerShortcut(const char* application_id, json_object* json)
655 struct json_object* j_obj = json_object_new_object();
656 struct json_object* val = json_object_new_string(application_id);
657 json_object_object_add(j_obj, ApplicationId, val);
658 json_object_object_add(j_obj, "parameter", json);
660 return this->call("registerShortcut", j_obj);
665 * update shortcut to launcher
667 * Call HomeScreen Service's updateShortcut verb to update shortcut.
670 * - json [in] : This argument should be specified to the json parameters.
673 * - Returns 0 on success or -1 in case of error.
676 int LibHomeScreen::updateShortcut(const char* application_id, json_object* json)
683 struct json_object* j_obj = json_object_new_object();
684 struct json_object* val = json_object_new_string(application_id);
685 json_object_object_add(j_obj, ApplicationId, val);
686 json_object_object_add(j_obj, "parameter", json);
688 return this->call("updateShortcut", j_obj);
692 /************* Callback Function *************/
694 void LibHomeScreen::on_hangup(void *closure, struct afb_wsj1 *wsj)
696 HMI_DEBUG("libhomescreen","called");
697 if(onHangup != nullptr)
703 void LibHomeScreen::on_call(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg)
708 * event is like "homescreen/hvac"
709 * msg is like {"event":"homescreen\/hvac","data":{"type":"tap_shortcut"},"jtype":"afb-event"}
711 event name : struct json_object obj = json_object_object_get(msg,"event")
713 void LibHomeScreen::on_event(void *closure, const char *event, struct afb_wsj1_msg *msg)
715 HMI_DEBUG("libhomescreen","event: (%s) msg: (%s).", event, afb_wsj1_msg_object_s(msg));
717 if (strstr(event, API) == NULL) {
721 struct json_object* ev_contents = afb_wsj1_msg_object_j(msg);
722 struct json_object *json_data;
723 if(!json_object_object_get_ex(ev_contents, "data", &json_data)) {
724 HMI_ERROR("libhomescreen", "got ev_contents error.");
728 if(onEvent != nullptr)
730 const string ev(event);
731 onEvent(ev, ev_contents);
734 const char* event_type = nullptr;
735 struct json_object *json_event_type;
736 if(json_object_object_get_ex(json_data, "type", &json_event_type)) {
737 event_type = json_object_get_string(json_event_type);
740 HMI_WARNING("libhomescreen","event_type is null.");
744 int e_type = getEventType(event_type);
745 if(e_type < Event_Max) {
746 auto it = this->handlers.find(EventType(e_type));
747 if ( it != this->handlers.end() ) {
748 it->second(json_data);
754 * msg is like ({"response":{"verb":"subscribe","error":0},"jtype":"afb-reply","request":{"status":"success","info":"homescreen binder subscribe event name [on_screen_message]"}})
755 * msg is like ({"response":{"verb":"tap_shortcut","error":0},"jtype":"afb-reply","request":{"status":"success","info":"afb_event_push event [tap_shortcut]"}})
757 void LibHomeScreen::on_reply(void *closure, struct afb_wsj1_msg *msg)
759 HMI_DEBUG("libhomescreen","msg: (%s)", afb_wsj1_msg_object_s(msg));
760 if(onReply != nullptr)
762 struct json_object* reply = afb_wsj1_msg_object_j(msg);
768 * convert event name to event type
770 int LibHomeScreen::getEventType(const char *event)
773 for(; i < LibHomeScreen::event_list.size(); ++i) {
774 if (strcasecmp(event, LibHomeScreen::event_list[i].c_str()) == 0) {
778 return (i + 1) < Event_Max ? (i + 1) : Event_Max;
781 static bool has_verb(const string& verb)
783 HMI_DEBUG("libhomescreen","verb is %s", verb.c_str());
784 if(find(LibHomeScreen::api_list.begin(), LibHomeScreen::api_list.end(), verb) != LibHomeScreen::api_list.end())