C

Qt Quick Ultralite Automotive Cluster Demo

// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial
#include "simulationcontroller.h"
#include "Automotive/MainModel.h"
#include "Automotive/TellTalesModel.h"
#include "statemachine.h"
#include "simulation/smfwd.h"
#include "simulation/states.h"
#include "simulation/drivestates.h"
#include "hmi_input.h"

#include <limits>

using namespace Simulation;
using namespace Automotive;

void introFinished(Machine &sm);

namespace {
// State Machine instance
Machine sm(State_Idle);

// State Instances
IntroState introState(introFinished);
DriveModeMenuState driveModeMenuState;
CarStatusMenuState carStatusMenuState;
LastTripMenuState lastTripMenuState;
NormalDriveState normalDriveState;
MediaPlayerState mediaPlayerState(State_Navi);
NaviState naviState(State_Phone);
PhoneState phoneState(State_DriveModeMenu);
SportDriveState sportDriveState;
InteractiveModeState interactiveModeState;
EndState endState(State_Intro);
} // namespace

SimulationController::SimulationController()
{
    sm.registerState(State_Intro, &introState);
    sm.registerState(State_NormalDrive, &normalDriveState);
    sm.registerState(State_MediaPlayer, &mediaPlayerState);
    sm.registerState(State_Navi, &naviState);
    sm.registerState(State_Phone, &phoneState);
    sm.registerState(State_DriveModeMenu, &driveModeMenuState);
    sm.registerState(State_CarStatus, &carStatusMenuState);
    sm.registerState(State_LastTrip, &lastTripMenuState);
    sm.registerState(State_SportDrive, &sportDriveState);
    sm.registerState(State_InteractiveMode, &interactiveModeState);
    sm.registerState(State_End, &endState);
}

void SimulationController::start()
{
    sm.changeState(State_Intro, Layer_Gauges);
    sm.changeState(State_MediaPlayer, Layer_Menu, 5000);
}

void SimulationController::startInteractiveMode()
{
    if (sm.getCurrentStateId(Layer_Menu) != State_InteractiveMode) {
        sm.dismissUpdate(Layer_Menu);
        sm.dismissScheduledStateChanges(Layer_Menu);
        sm.changeState(State_InteractiveMode, Layer_Menu);
    }
}
void SimulationController::stopInteractiveMode()
{
    sm.requestUpdate(0, false, Layer_Menu);
}

void SimulationController::switchToNormalMode()
{
    sm.changeState(State_NormalDrive, Layer_Gauges);
}

void SimulationController::switchToSportMode()
{
    sm.changeState(State_SportDrive, Layer_Gauges);
}

void introFinished(Machine &sm)
{
    sm.changeState(State_NormalDrive, Layer_Gauges);
    sm.changeState(State_MediaPlayer, Layer_Menu);

    if (MainModel::instance().forceInteractiveMode.value()) {
        sm.dismissUpdate(Layer_Menu);
        sm.dismissScheduledStateChanges(Layer_Menu);
        sm.changeState(State_InteractiveMode, Layer_Menu);
    }
}

extern "C" {
void qul_application_force_interactive_mode(bool force_interactive_mode)
{
    MainModel::instance().forceInteractiveMode.setValue(force_interactive_mode);
}

static bool firstOdoUpdate = true;

void qul_application_show_simulated_drive_data(bool simulated_drive_data)
{
    static float initialOdo = 0.0f;
    static bool restoreInitialOdo = false;

    if (simulated_drive_data != MainModel::instance().showSimulatedDriveData.value()) {
        // Restore initial ODO value when switching back to simulated drive data
        if (simulated_drive_data) {
            if (restoreInitialOdo) {
                MainModel::instance().initialOdo.setValue(initialOdo);
                restoreInitialOdo = false;
            }
        } else {
            initialOdo = MainModel::instance().initialOdo.value();
            firstOdoUpdate = true;
            restoreInitialOdo = true;
        }

        MainModel::instance().showSimulatedDriveData.setValue(simulated_drive_data);
    }
}

void qul_application_set_speed(float speed)
{
    if (!MainModel::instance().showSimulatedDriveData.value()) {
        MainModel::instance().speed.setValue(speed);
    }
}

void qul_application_set_rpm(float rpm)
{
    if (!MainModel::instance().showSimulatedDriveData.value()) {
        MainModel::instance().rpm.setValue(rpm);
    }
}

void qul_application_set_gear(int gear)
{
    if (!MainModel::instance().showSimulatedDriveData.value()) {
        //   0 = parking gear
        // 1-6 = drive gear
        MainModel::instance().gear.setValue(gear);
    }
}

void qul_application_set_odo(float odo)
{
    if (!MainModel::instance().showSimulatedDriveData.value()) {
        if (firstOdoUpdate) {
            MainModel::instance().initialOdo.setValue(odo);
            firstOdoUpdate = false;
        }

        MainModel::instance().odo.setValue(odo);
    }
}

void qul_application_set_range(int range)
{
    if (!MainModel::instance().showSimulatedDriveData.value()) {
        MainModel::instance().range.setValue(range);
    }
}

void qul_application_set_battery_level(float battery_level)
{
    if (!MainModel::instance().showSimulatedDriveData.value()) {
        MainModel::instance().batteryLevel.setValue(battery_level);
    }
}

void qul_application_set_fuel_level(float fuel_level)
{
    if (!MainModel::instance().showSimulatedDriveData.value()) {
        MainModel::instance().fuelLevel.setValue(fuel_level);
    }
}

void qul_application_set_coolant_temp(float coolant_temp)
{
    if (!MainModel::instance().showSimulatedDriveData.value()) {
        MainModel::instance().temp.setValue(coolant_temp);
    }
}

void qul_application_set_lane_assistant_enabled(bool enabled)
{
    MainModel::instance().laneAssistEnabled.setValue(enabled);
}

void qul_application_show_simulated_light_indicators(bool simulated_light_indicators)
{
    TellTalesModel::instance().showSimulatedLightIndicators.setValue(simulated_light_indicators);
}
void qul_application_set_left_blinker_on(bool left_blinker_on)
{
    if (!TellTalesModel::instance().showSimulatedLightIndicators.value()) {
        TellTalesModel::instance().turnLeftBlinking.setValue(left_blinker_on);
    }
}

void qul_application_set_right_blinker_on(bool right_blinker_on)
{
    if (!TellTalesModel::instance().showSimulatedLightIndicators.value()) {
        TellTalesModel::instance().turnRightBlinking.setValue(right_blinker_on);
    }
}

void qul_application_set_parking_lights_on(bool parking_lights_on)
{
    if (!TellTalesModel::instance().showSimulatedLightIndicators.value()) {
        TellTalesModel::instance().parkingLightsActive.setValue(parking_lights_on);
    }
}

void qul_application_set_low_beam_headlights_on(bool low_beam_headlights_on)
{
    if (!TellTalesModel::instance().showSimulatedLightIndicators.value()) {
        TellTalesModel::instance().lowBeamHeadlightsActive.setValue(low_beam_headlights_on);
    }
}

void qul_application_control_navigate_up(bool pressed)
{
    const HMIInputEvent event = HMIInputEvent(HMIInputEvent::HMI_BTN_UP,
                                              pressed ? HMIInputEvent::KeyPress : HMIInputEvent::KeyRelease);
    HMIInput::instance().onEvent(event);
}

void qul_application_control_navigate_down(bool pressed)
{
    const HMIInputEvent event = HMIInputEvent(HMIInputEvent::HMI_BTN_DOWN,
                                              pressed ? HMIInputEvent::KeyPress : HMIInputEvent::KeyRelease);
    HMIInput::instance().onEvent(event);
}

void qul_application_control_navigate_left(bool pressed)
{
    const HMIInputEvent event = HMIInputEvent(HMIInputEvent::HMI_BTN_LEFT,
                                              pressed ? HMIInputEvent::KeyPress : HMIInputEvent::KeyRelease);
    HMIInput::instance().onEvent(event);
}

void qul_application_control_navigate_right(bool pressed)
{
    const HMIInputEvent event = HMIInputEvent(HMIInputEvent::HMI_BTN_RIGHT,
                                              pressed ? HMIInputEvent::KeyPress : HMIInputEvent::KeyRelease);
    HMIInput::instance().onEvent(event);
}

void qul_application_control_previous_page(bool pressed)
{
    const HMIInputEvent event = HMIInputEvent(HMIInputEvent::HMI_KNOB_TURN_LEFT,
                                              pressed ? HMIInputEvent::KeyPress : HMIInputEvent::KeyRelease);
    HMIInput::instance().onEvent(event);
}

void qul_application_control_next_page(bool pressed)
{
    const HMIInputEvent event = HMIInputEvent(HMIInputEvent::HMI_KNOB_TURN_RIGHT,
                                              pressed ? HMIInputEvent::KeyPress : HMIInputEvent::KeyRelease);
    HMIInput::instance().onEvent(event);
}

void qul_application_control_validate(bool pressed)
{
    const HMIInputEvent event = HMIInputEvent(HMIInputEvent::HMI_KNOB_CENTER,
                                              pressed ? HMIInputEvent::KeyPress : HMIInputEvent::KeyRelease);
    HMIInput::instance().onEvent(event);
}
}