/* * Copyright (c) 2018 TOYOTA MOTOR CORPORATION * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "pm_wrapper.hpp" #include "json_helper.hpp" #include "util.hpp" namespace wm { static PMWrapper *g_context; namespace { static void onStateTransitioned(json_object *json_out) { g_context->updateStates(json_out); } static void onError(json_object *json_out) { HMI_DEBUG("error message from PolicyManager:%s", json_object_get_string(json_out)); g_context->processError(); } } // namespace PMWrapper::PMWrapper() {} int PMWrapper::initialize(std::string ecu_name) { int ret = 0; ret = this->pm.initialize(ecu_name); if (0 > ret) { HMI_ERROR("wm:pmw", "Faild to initialize PolicyManager"); } g_context = this; return ret; } void PMWrapper::registerCallback(StateTransitionHandler on_state_transitioned, ErrorHandler on_error) { this->on_state_transitioned = on_state_transitioned; this->on_error = on_error; PolicyManager::CallbackTable my_callback; my_callback.onStateTransitioned = onStateTransitioned; my_callback.onError = onError; this->pm.registerCallback(my_callback); } int PMWrapper::setInputEventData(Task task, std::string role, std::string area) { const char* event; if (Task::TASK_ALLOCATE == task) { event = "activate"; } else if (Task::TASK_RELEASE == task) { event = "deactivate"; } else if (Task::TASK_PARKING_BRAKE_OFF == task) { event = "parking_brake_off"; } else if (Task::TASK_PARKING_BRAKE_ON == task) { event = "parking_brake_on"; } else if (Task::TASK_ACCEL_PEDAL_OFF == task) { event = "accel_pedal_off"; } else if (Task::TASK_ACCEL_PEDAL_ON == task) { event = "accel_pedal_on"; } else if (Task::TASK_HEDLAMP_OFF == task) { event = "headlamp_off"; } else if (Task::TASK_HEDLAMP_ON == task) { event = "headlamp_on"; } else if (Task::TASK_LIGHTSTATUS_BRAKE_OFF == task) { event = "lightstatus_brake_off"; } else if (Task::TASK_LIGHTSTATUS_BRAKE_ON == task) { event = "lightstatus_brake_on"; } else { event = ""; } json_object *json_in = json_object_new_object(); json_object_object_add(json_in, "event", json_object_new_string(event)); json_object_object_add(json_in, "role", json_object_new_string(role.c_str())); json_object_object_add(json_in, "area", json_object_new_string(area.c_str())); int ret; ret = this->pm.setInputEventData(json_in); if (0 > ret) { HMI_ERROR("wm:pmw", "Faild to set input event data to PolicyManager"); } json_object_put(json_in); return ret; } int PMWrapper::executeStateTransition() { int ret; ret = this->pm.executeStateTransition(); if (0 > ret) { HMI_ERROR("wm:pmw", "Failed to execute state transition for PolicyManager"); } return ret; } void PMWrapper::undoState() { this->pm.undoState(); this->crrlayer2rolestate = this->prvlayer2rolestate; } void PMWrapper::updateStates(json_object *json_out) { std::vector actions; HMI_DEBUG("json_out dump:%s", json_object_get_string(json_out)); this->createCarStateChangeAction(json_out, actions); this->createLayoutChangeAction(json_out, actions); this->on_state_transitioned(actions); } void PMWrapper::createCarStateChangeAction(json_object *json_out, std::vector &actions) { json_object *json_car_ele; if (!json_object_object_get_ex(json_out, "car_elements", &json_car_ele)) { HMI_DEBUG("Not found key \"car_elements\""); return; } int len = json_object_array_length(json_car_ele); HMI_DEBUG("json_car_ele len:%d", len); for (int i = 0; i < len; i++) { json_object *json_tmp = json_object_array_get_idx(json_car_ele, i); std::string car_ele_name = jh::getStringFromJson(json_tmp, "name"); std::string state = jh::getStringFromJson(json_tmp, "state"); json_bool changed = jh::getBoolFromJson(json_tmp, "changed"); HMI_DEBUG("car_element:%s changed:%d", car_ele_name.c_str(), changed); if (changed) { TaskCarState task = TaskCarState::NO_TASK; if ("parking_brake" == car_ele_name) { if ("off" == state) { task = TaskCarState::PARKING_BRAKE_OFF; } else if ("on" == state) { task = TaskCarState::PARKING_BRAKE_ON; } else { HMI_DEBUG("Unknown parking brake state: %s", state.c_str()); } } else if ("accel_pedal" == car_ele_name) { if ("off" == state) { task = TaskCarState::ACCEL_PEDAL_OFF; } else if ("on" == state) { task = TaskCarState::ACCEL_PEDAL_ON; } else { HMI_DEBUG("Unknown accel pedal state: %s", state.c_str()); } } else if ("lamp" == car_ele_name) { if ("off" == state) { task = TaskCarState::HEDLAMP_OFF; } else if ("on" == state) { task = TaskCarState::HEDLAMP_ON; } else { HMI_DEBUG("Unknown lamp state: %s", state.c_str()); } } else if ("lightstatus_brake" == car_ele_name) { if ("off" == state) { task = TaskCarState::LIGHTSTATUS_BRAKE_OFF; } else if ("on" == state) { task = TaskCarState::LIGHTSTATUS_BRAKE_ON; } else { HMI_DEBUG("Unknown lightstatus brake state: %s", state.c_str()); } } else if ("running" == car_ele_name) { if ("stop" == state) { task = TaskCarState::CAR_STOP; } else if ("run" == state) { task = TaskCarState::CAR_RUN; } else { HMI_DEBUG("Unknown car state: %s", state.c_str()); } } else if ("restriction_mode" == car_ele_name) { if ("off" == state) { task = TaskCarState::RESTRICTION_MODE_OFF; } else if ("on" == state) { task = TaskCarState::RESTRICTION_MODE_ON; } else { HMI_DEBUG("Unknown car state: %s", state.c_str()); } } else { HMI_DEBUG("Unknown car element: %s", car_ele_name.c_str()); } // Set action if (TaskCarState::NO_TASK != task) { bool end_draw_finished = true; WMAction act { 0, nullptr, "", "", TaskVisible::NO_CHANGE, end_draw_finished, task }; actions.push_back(act); } } } } void PMWrapper::createLayoutChangeAction(json_object *json_out, std::vector &actions) { // Get displayed roles from previous layout json_object *json_layers; if (!json_object_object_get_ex(json_out, "layers", &json_layers)) { HMI_DEBUG("Not found key \"layers\""); return; } int len = json_object_array_length(json_layers); HMI_DEBUG("json_layers len:%d", len); for (int i = 0; i < len; i++) { json_object *json_tmp = json_object_array_get_idx(json_layers, i); std::string layer_name = jh::getStringFromJson(json_tmp, "name"); json_bool changed = jh::getBoolFromJson(json_tmp, "changed"); HMI_DEBUG("layer:%s changed:%d", layer_name.c_str(), changed); if (changed) { json_object *json_areas; if (!json_object_object_get_ex(json_tmp, "areas", &json_areas)) { HMI_DEBUG("Not found key \"areas\""); return; } int len = json_object_array_length(json_areas); HMI_DEBUG("json_layers len:%d", len); // Store previous role state in this layer this->prvlayer2rolestate[layer_name] = this->crrlayer2rolestate[layer_name]; RoleState crr_roles; RoleState prv_roles = this->prvlayer2rolestate[layer_name]; for (int j = 0; j < len; j++) { json_object *json_tmp2 = json_object_array_get_idx(json_areas, j); std::string area_name = jh::getStringFromJson(json_tmp2, "name"); std::string role_name = jh::getStringFromJson(json_tmp2, "role"); crr_roles[role_name] = area_name; auto i_prv = prv_roles.find(role_name); HMI_DEBUG("current role:%s area:%s", role_name.c_str(), area_name.c_str()); // If current role does not exist in previous if (prv_roles.end() == i_prv) { HMI_DEBUG("current role does not exist in previous"); // Set activate action bool end_draw_finished = false; WMAction act { 0, nullptr, role_name, area_name, TaskVisible::VISIBLE, end_draw_finished, TaskCarState::NO_TASK }; actions.push_back(act); } else { HMI_DEBUG("previous role:%s area:%s", i_prv->first.c_str(), i_prv->second.c_str()); // If current role exists in previous and area is different with previous if (area_name != i_prv->second) { HMI_DEBUG("current role exists in previous and area is different with previous"); // Set activate action bool end_draw_finished = false; WMAction act { 0, nullptr, role_name, area_name, TaskVisible::VISIBLE, end_draw_finished, TaskCarState::NO_TASK }; actions.push_back(act); } // Remove role which exist in current list from previous list prv_roles.erase(i_prv); } } // Deactivate roles which remains in previous list // because these are not displayed in current layout for (auto i_prv : prv_roles) { HMI_DEBUG("Deactivate role:%s", i_prv.first.c_str()); // Set deactivate action bool end_draw_finished = true; WMAction act { 0, nullptr, i_prv.first, "", TaskVisible::INVISIBLE, end_draw_finished, TaskCarState::NO_TASK }; actions.push_back(act); } // Update previous role list this->crrlayer2rolestate[layer_name] = crr_roles; } } } void PMWrapper::processError() { this->on_error(); } } // namespace wm