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>
30 #include <libhomescreen.hpp>
31 #include "hmi-debug.h"
35 static bool has_verb(const string& verb);
36 static const char API[] = "homescreen";
37 static const char ApplicationId[] = "application_id";
39 const std::vector<std::string> LibHomeScreen::api_list {
40 std::string("ping"), // debug do not use
41 std::string("tap_shortcut"), // HomeScreen Application only
42 std::string("on_screen_message"),
43 std::string("on_screen_reply"),
44 std::string("subscribe"),
45 std::string("unsubscribe"),
46 std::string("showWindow"),
47 std::string("hideWindow"),
48 std::string("replyShowWindow"),
49 std::string("showNotification"),
50 std::string("showInformation")
53 const std::vector<std::string> LibHomeScreen::event_list {
54 // std::string("tap_shortcut"),
55 std::string("showWindow"),
56 std::string("on_screen_message"),
57 std::string("on_screen_reply"),
58 std::string("hideWindow"),
59 std::string("replyShowWindow"),
60 std::string("showNotification"),
61 std::string("showInformation"),
70 static void _on_hangup_static(void *closure, struct afb_wsj1 *wsj)
72 static_cast<LibHomeScreen*>(closure)->on_hangup(NULL,wsj);
75 static void _on_call_static(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg)
77 /* LibHomeScreen is not called from other process */
80 static void _on_event_static(void* closure, const char* event, struct afb_wsj1_msg *msg)
82 static_cast<LibHomeScreen*>(closure)->on_event(NULL,event,msg);
85 static void _on_reply_static(void *closure, struct afb_wsj1_msg *msg)
87 static_cast<LibHomeScreen*>(closure)->on_reply(NULL,msg);
91 static void event_loop_run(struct sd_event* loop){
100 LibHomeScreen::LibHomeScreen()
107 LibHomeScreen::~LibHomeScreen()
109 if(sp_websock != NULL)
111 afb_wsj1_unref(sp_websock);
115 sd_event_exit(mploop, 0);
120 * This function is initializer
123 * - port [in] : This argument should be specified to the port number to be used for websocket
124 * - token [in] : This argument should be specified to the token to be used for websocket
130 * Use this constructor
133 int LibHomeScreen::init(const int port, const string& token)
136 if(port > 0 && token.size() > 0)
143 HMI_ERROR("libhomescreen","port and token should be > 0, Initial port and token uses.");
146 ret = initialize_websocket();
149 HMI_ERROR("libhomescreen","Failed to initialize websocket");
152 HMI_DEBUG("libhomescreen","Initialized");
159 * This function register callback function for reply/event message from home screen
162 * - event_cb [in] : This argument should be specified to the callback for subscribed event
163 * - reply_cb [in] : This argument should be specified to the reply callback for call function
169 * Event callback is invoked by home screen for event you subscribed.
170 * If you would like to get event, please call subscribe function before/after this function
172 void LibHomeScreen::registerCallback(
173 void (*event_cb)(const std::string& event, struct json_object* event_contents),
174 void (*reply_cb)(struct json_object* reply_contents),
175 void (*hangup_cb)(void))
179 onHangup = hangup_cb;
182 int LibHomeScreen::initialize_websocket()
187 int ret = sd_event_new(&mploop);
190 HMI_ERROR("libhomescreen","Failed to create event loop");
195 // enforce context to avoid initialization/goto error
196 std::thread th(event_loop_run, mploop);
200 /* Initialize interface from websocket */
201 minterface.on_hangup = _on_hangup_static;
202 minterface.on_call = _on_call_static;
203 minterface.on_event = _on_event_static;
204 muri += "ws://localhost:" + to_string(mport) + "/api?token=" + mtoken; /*To be modified*/
205 sp_websock = afb_ws_client_connect_wsj1(mploop, muri.c_str(), &minterface, this);
206 if(sp_websock == NULL)
208 HMI_ERROR("libhomescreen","Failed to create websocket connection");
212 /* creates the evsrc */
213 //ret = sd_event_add_io(mploop,&mevent_src, sp_websock->fd, EPOLLIN, event_callback, NULL);
221 * Sending ShortCut Icon tapped event
223 * When HomeScreen shortcut area is tapped, sending a event
226 * - application_id [in] : Tapped application id (label)
229 * - Returns 0 on success or -1 in case of error.
231 int LibHomeScreen::tapShortcut(const char* application_id)
233 struct json_object* obj = json_object_new_object();
234 struct json_object* val = json_object_new_string("normal");
235 json_object_object_add(obj, "area", val);
237 return showWindow(application_id, obj);
241 * Sending onScreen message event
243 * Sending OnScreen message event to HomeScreen from applications
246 * - display_message [in] : message for display
249 * - Returns 0 on success or -1 in case of error.
251 int LibHomeScreen::onScreenMessage(const char* display_message)
258 struct json_object* j_obj = json_object_new_object();
259 struct json_object* val = json_object_new_string(display_message);
260 json_object_object_add(j_obj, "display_message", val);
261 return this->call("on_screen_message", j_obj);
265 * Sending onScreen reply event
267 * Sending OnScreen reply event to applications from HomeScreen
270 * - reply_message [in] : message for reply
273 * - Returns 0 on success or -1 in case of error.
275 int LibHomeScreen::onScreenReply(const char* reply_message)
282 struct json_object* j_obj = json_object_new_object();
283 struct json_object* val = json_object_new_string(reply_message);
284 json_object_object_add(j_obj, "reply_message", val);
285 return this->call("on_screen_reply", j_obj);
289 * Setting Event Handler
291 * Setting event handler for Homescreen
294 * - et [in] : event name
295 * - f [in] : event handler
301 * Don't release json_object by json_object_put in handler_func.
302 * The resource is released by libafbwsc library.
304 void LibHomeScreen::set_event_handler(enum EventType et, handler_func f)
306 if (et >= 1 && et <= 7) {
308 case Event_ShowWindow:
309 this->subscribe(LibHomeScreen::event_list[0]);
311 case Event_OnScreenMessage:
312 this->subscribe(LibHomeScreen::event_list[1]);
314 case Event_OnScreenReply:
315 this->subscribe(LibHomeScreen::event_list[2]);
317 case Event_HideWindow:
318 this->subscribe(LibHomeScreen::event_list[3]);
320 case Event_ReplyShowWindow:
321 this->subscribe(LibHomeScreen::event_list[4]);
323 case Event_ShowNotification:
324 this->subscribe(LibHomeScreen::event_list[5]);
326 case Event_ShowInformation:
327 this->subscribe(LibHomeScreen::event_list[6]);
331 this->handlers[et] = std::move(f);
336 * This function calls the API of HomeScreen via WebSocket
339 * - verb [in] : This argument should be specified to the API name (e.g. "tap_shortcut")
340 * - arg [in] : This argument should be specified to the argument of API. And this argument expects JSON object
343 * - Returns 0 on success or -1 in case of error.
346 * To call HomeScreen's APIs, the application should set its function name, arguments to JSON format.
349 int LibHomeScreen::call(const string& verb, struct json_object* arg)
358 HMI_ERROR("libhomescreen","verb doesn't exit");
361 ret = afb_wsj1_call_j(sp_websock, API, verb.c_str(), arg, _on_reply_static, this);
363 HMI_ERROR("libhomescreen","Failed to call verb:%s",verb.c_str());
369 * This function calls the API of HomeScreen via WebSocket
370 * This function is overload function of "call"
373 * - verb [in] : This argument should be specified to the API name (e.g. "tap_shortcut")
374 * - arg [in] : This argument should be specified to the argument of API. And this argument expects JSON object
377 * - Returns 0 on success or -1 in case of error.
380 * To call HomeScreen's APIs, the application should set its function name, arguments to JSON format.
383 int LibHomeScreen::call(const char* verb, struct json_object* arg)
390 if (!has_verb(string(verb)))
392 HMI_ERROR("libhomescreen","verb doesn't exit");
395 ret = afb_wsj1_call_j(sp_websock, API, verb, arg, _on_reply_static, this);
397 HMI_ERROR("libhomescreen","Failed to call verb:%s",verb);
403 * Register callback function for each event
406 * - event_name [in] : This argument should be specified to the event name
409 * - Returns 0 on success or -1 in case of error.
412 * This function enables to get an event to your callback function.
415 int LibHomeScreen::subscribe(const string& event_name)
421 struct json_object* j_obj = json_object_new_object();
422 json_object_object_add(j_obj, "event", json_object_new_string(event_name.c_str()));
424 int ret = afb_wsj1_call_j(sp_websock, API, "subscribe", j_obj, _on_reply_static, this);
426 HMI_ERROR("libhomescreen","Failed to call verb");
432 * Unregister callback function for each event
435 * - event_name [in] : This argument should be specified to the event name
438 * - Returns 0 on success or -1 in case of error.
441 * This function disables to get an event to your callback function.
444 int LibHomeScreen::unsubscribe(const string& event_name)
450 struct json_object* j_obj = json_object_new_object();
451 json_object_object_add(j_obj, "event", json_object_new_string(event_name.c_str()));
453 int ret = afb_wsj1_call_j(sp_websock, API, "unsubscribe", j_obj, _on_reply_static, this);
455 HMI_ERROR("libhomescreen","Failed to call verb");
461 * Sending show window event
463 * Call HomeScreen Service's showWindow verb to request display id's screen.
466 * - application_id [in] : This argument should be specified to the application's id.
467 * - json [in] : This argument should be specified to the json parameters.
470 * - Returns 0 on success or -1 in case of error.
473 int LibHomeScreen::showWindow(const char* application_id, json_object* json)
480 struct json_object* j_obj = json_object_new_object();
481 struct json_object* val = json_object_new_string(application_id);
482 json_object_object_add(j_obj, ApplicationId, val);
484 if (json == nullptr) {
485 struct json_object* j_json = json_object_new_object();
486 struct json_object* value = json_object_new_string("normal");
487 json_object_object_add(j_json, "area", value);
488 json_object_object_add(j_obj, "parameter", j_json);
491 json_object_object_add(j_obj, "parameter", json);
494 return this->call("showWindow", j_obj);
498 * Sending hide window event
500 * Call HomeScreen Service's hideWindow verb to release id's screen.
503 * - application_id [in] : This argument should be specified to the application's id.
506 * - Returns 0 on success or -1 in case of error.
509 int LibHomeScreen::hideWindow(const char* application_id)
516 struct json_object* j_obj = json_object_new_object();
517 struct json_object* val = json_object_new_string(application_id);
518 json_object_object_add(j_obj, ApplicationId, val);
520 return this->call("hideWindow", j_obj);
524 * Sending reply onscreen message event
526 * Call HomeScreen Service's replyShowWindow verb to reply onscreen message.
529 * - application_id [in] : This argument should be specified to the onscreen reply to applilcation id.
530 * - json [in] : This argument should be specified to the json parameters.
533 * - Returns 0 on success or -1 in case of error.
536 int LibHomeScreen::replyShowWindow(const char* application_id, json_object* json)
543 if (json == nullptr) {
544 HMI_WARNING("libhomescreen", "replyShowWindow`s parameter is null");
548 struct json_object* j_obj = json_object_new_object();
549 struct json_object* val = json_object_new_string(application_id);
550 json_object_object_add(j_obj, ApplicationId, val);
551 json_object_object_add(j_obj, "parameter", json);
553 return this->call("replyShowWindow", j_obj);
557 * Sending show notification event
559 * Call HomeScreen Service's notification verb to show notification on Status Bar.
562 * - json [in] : This argument should be specified to the json parameters.
565 * - Returns 0 on success or -1 in case of error.
568 int LibHomeScreen::showNotification(json_object* json)
575 return this->call("showNotification", json);
579 * Sending show information event
581 * Call HomeScreen Service's information verb to show notification on Information Bar.
584 * - json [in] : This argument should be specified to the json parameters.
587 * - Returns 0 on success or -1 in case of error.
590 int LibHomeScreen::showInformation(json_object* json)
597 return this->call("showInformation", json);
601 /************* Callback Function *************/
603 void LibHomeScreen::on_hangup(void *closure, struct afb_wsj1 *wsj)
605 HMI_DEBUG("libhomescreen","called");
606 if(onHangup != nullptr)
612 void LibHomeScreen::on_call(void *closure, const char *api, const char *verb, struct afb_wsj1_msg *msg)
617 * event is like "homescreen/hvac"
618 * msg is like {"event":"homescreen\/hvac","data":{"type":"tap_shortcut"},"jtype":"afb-event"}
620 event name : struct json_object obj = json_object_object_get(msg,"event")
622 void LibHomeScreen::on_event(void *closure, const char *event, struct afb_wsj1_msg *msg)
624 HMI_DEBUG("libhomescreen","event: (%s) msg: (%s).", event, afb_wsj1_msg_object_s(msg));
626 if (strstr(event, API) == NULL) {
630 struct json_object* ev_contents = afb_wsj1_msg_object_j(msg);
631 struct json_object *json_data;
632 if(!json_object_object_get_ex(ev_contents, "data", &json_data)) {
633 HMI_ERROR("libhomescreen", "got ev_contents error.");
637 if(onEvent != nullptr)
639 const string ev(event);
640 onEvent(ev, ev_contents);
643 const char* event_type = nullptr;
644 struct json_object *json_event_type;
645 if(json_object_object_get_ex(json_data, "type", &json_event_type)) {
646 event_type = json_object_get_string(json_event_type);
649 HMI_WARNING("libhomescreen","event_type is null.");
653 if (strcasecmp(event_type, LibHomeScreen::event_list[0].c_str()) == 0) {
654 auto i = this->handlers.find(Event_ShowWindow);
655 if ( i != this->handlers.end() ) {
656 i->second(json_data);
659 else if (strcasecmp(event_type, LibHomeScreen::event_list[1].c_str()) == 0) {
660 auto i = this->handlers.find(Event_OnScreenMessage);
661 if ( i != this->handlers.end() ) {
662 i->second(json_data);
665 else if (strcasecmp(event_type, LibHomeScreen::event_list[2].c_str()) == 0) {
666 auto i = this->handlers.find(Event_OnScreenReply);
667 if ( i != this->handlers.end() ) {
668 i->second(json_data);
671 else if (strcasecmp(event_type, LibHomeScreen::event_list[3].c_str()) == 0) {
672 auto i = this->handlers.find(Event_HideWindow);
673 if ( i != this->handlers.end() ) {
674 i->second(json_data);
677 else if (strcasecmp(event_type, LibHomeScreen::event_list[4].c_str()) == 0) {
678 auto i = this->handlers.find(Event_ReplyShowWindow);
679 if ( i != this->handlers.end() ) {
680 i->second(json_data);
683 else if (strcasecmp(event_type, LibHomeScreen::event_list[5].c_str()) == 0) {
684 auto i = this->handlers.find(Event_ShowNotification);
685 if ( i != this->handlers.end() ) {
686 i->second(json_data);
689 else if (strcasecmp(event_type, LibHomeScreen::event_list[6].c_str()) == 0) {
690 auto i = this->handlers.find(Event_ShowInformation);
691 if ( i != this->handlers.end() ) {
692 i->second(json_data);
698 * msg is like ({"response":{"verb":"subscribe","error":0},"jtype":"afb-reply","request":{"status":"success","info":"homescreen binder subscribe event name [on_screen_message]"}})
699 * msg is like ({"response":{"verb":"tap_shortcut","error":0},"jtype":"afb-reply","request":{"status":"success","info":"afb_event_push event [tap_shortcut]"}})
701 void LibHomeScreen::on_reply(void *closure, struct afb_wsj1_msg *msg)
703 HMI_DEBUG("libhomescreen","msg: (%s)", afb_wsj1_msg_object_s(msg));
704 if(onReply != nullptr)
706 struct json_object* reply = afb_wsj1_msg_object_j(msg);
711 static bool has_verb(const string& verb)
713 HMI_DEBUG("libhomescreen","verb is %s", verb.c_str());
714 if(find(LibHomeScreen::api_list.begin(), LibHomeScreen::api_list.end(), verb) != LibHomeScreen::api_list.end())