/** * @brief Telemetry API initialization function. * * See scssdk_telemetry.h */ SCSAPI_RESULT scs_telemetry_init(const scs_u32_t version, const scs_telemetry_init_params_t *const params) { // We currently support only one version. if (version != SCS_TELEMETRY_VERSION_1_00) { return SCS_RESULT_unsupported; } const scs_telemetry_init_params_v100_t *const version_params = static_cast<const scs_telemetry_init_params_v100_t *>(params); if (! init_log()) { version_params->common.log(SCS_LOG_TYPE_error, "Unable to initialize the log file"); return SCS_RESULT_generic_error; } // Check application version. Note that this example uses fairly basic channels which are likely to be supported // by any future SCS trucking game however more advanced application might want to at least warn the user if there // is game or version they do not support. //log_line("Game '%s' %u.%u", version_params->common.game_id, SCS_GET_MAJOR_VERSION(version_params->common.game_version), SCS_GET_MINOR_VERSION(version_params->common.game_version)); if (strcmp(version_params->common.game_id, SCS_GAME_ID_EUT2) != 0) { log_line("WARNING: Unsupported game, some features or values might behave incorrectly"); } else { // Bellow the minimum version there might be some missing features (only minor change) or // incompatible values (major change). const scs_u32_t MINIMAL_VERSION = SCS_TELEMETRY_EUT2_GAME_VERSION_1_00; if (version_params->common.game_version < MINIMAL_VERSION) { log_line("WARNING: Too old version of the game, some features might behave incorrectly"); } // Future versions are fine as long the major version is not changed. const scs_u32_t IMPLEMENTED_VERSION = SCS_TELEMETRY_EUT2_GAME_VERSION_CURRENT; if (SCS_GET_MAJOR_VERSION(version_params->common.game_version) > SCS_GET_MAJOR_VERSION(IMPLEMENTED_VERSION)) { log_line("WARNING: Too new major version of the game, some features might behave incorrectly"); } } // Register for events. Note that failure to register those basic events // likely indicates invalid usage of the api or some critical problem. As the // example requires all of them, we can not continue if the registration fails. const bool events_registered = (version_params->register_for_event(SCS_TELEMETRY_EVENT_frame_start, telemetry_frame_start, NULL) == SCS_RESULT_ok) && (version_params->register_for_event(SCS_TELEMETRY_EVENT_frame_end, telemetry_frame_end, NULL) == SCS_RESULT_ok) && (version_params->register_for_event(SCS_TELEMETRY_EVENT_paused, telemetry_pause, NULL) == SCS_RESULT_ok) && (version_params->register_for_event(SCS_TELEMETRY_EVENT_started, telemetry_pause, NULL) == SCS_RESULT_ok) ; if (! events_registered) { // Registrations created by unsuccessfull initialization are // cleared automatically so we can simply exit. version_params->common.log(SCS_LOG_TYPE_error, "WARNING: Unable to register event callbacks"); return SCS_RESULT_generic_error; } // Register for the configuration info. As this example only prints the retrieved // data, it can operate even if that fails. version_params->register_for_event(SCS_TELEMETRY_EVENT_configuration, telemetry_configuration, NULL); // Register for channels. The channel might be missing if the game does not support // it (SCS_RESULT_not_found) or if does not support the requested type // (SCS_RESULT_unsupported_type). For purpose of this example we ignore the failues // so the unsupported channels will remain at theirs default value. version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_world_placement, SCS_U32_NIL, SCS_VALUE_TYPE_euler, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_orientation, &data); version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_speed, SCS_U32_NIL, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_none, telemetry_store_float, &data.speed); version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_engine_rpm, SCS_U32_NIL, SCS_VALUE_TYPE_float, SCS_TELEMETRY_CHANNEL_FLAG_none, telemetry_store_float, &data.rpm); version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_engine_gear, SCS_U32_NIL, SCS_VALUE_TYPE_s32, SCS_TELEMETRY_CHANNEL_FLAG_none, telemetry_store_s32, &data.gear); // Remember the function we will use for logging. game_log = version_params->common.log; game_log(SCS_LOG_TYPE_message, "Initializing ETS2Viewer"); // Set the structure with defaults. memset(&data, 0, sizeof(data)); print_header = true; last_timestamp = static_cast<scs_timestamp_t>(-1); // Initially the game is paused. output_paused = true; return SCS_RESULT_ok; }
SCSAPI_RESULT scs_telemetry_init(const scs_u32_t version, const scs_telemetry_init_params_t *const params) { // We currently support only one version. if (version != SCS_TELEMETRY_VERSION_1_00) { return SCS_RESULT_unsupported; } const scs_telemetry_init_params_v100_t *const version_params = static_cast<const scs_telemetry_init_params_v100_t *>(params); if (version_params == NULL) { return SCS_RESULT_generic_error; } /*** ACQUIRE SHARED MEMORY BUFFER ***/ telemMem = new SharedMemory(ets2MmfName, ETS2_PLUGIN_MMF_SIZE); if (telemMem == NULL) { return SCS_RESULT_generic_error; } if (telemMem->Hooked() == false) { return SCS_RESULT_generic_error; } #ifdef SDK_ENABLE_LOGGING log_file = fopen("telemetry.log", "wt"); #endif telemPtr = (ets2TelemetryMap_t*) (telemMem->GetBuffer()); if (telemPtr == NULL) { return SCS_RESULT_generic_error; } memset(telemPtr, 0, ETS2_PLUGIN_MMF_SIZE); /*** INITIALIZE TELEMETRY MAP TO DEFAULT ***/ telemPtr->paused = 1; telemPtr->time = 0; telemPtr->tel_revId.ets2_telemetry_plugin_revision = ETS2_PLUGIN_REVID; telemPtr->tel_revId.ets2_version_major = SCS_GET_MAJOR_VERSION(version_params->common.game_version); telemPtr->tel_revId.ets2_version_minor = SCS_GET_MINOR_VERSION(version_params->common.game_version); // Model & trailer type are stored in configuration event. // TODO: Invent a better way of sharing strings between plug-in and client application. telemPtr->tel_rev1.modelType[0] = TRUCK_STRING_OFFSET; telemPtr->tel_rev1.trailerType[0] = TRAILER_STRING_OFFSET; telemPtr->tel_rev1.modelType[1] = 0; telemPtr->tel_rev1.trailerType[1] = 0; /*** REGISTER GAME EVENTS (Pause/Unpause/Start/Time) ***/ const bool events_registered = (version_params->register_for_event(SCS_TELEMETRY_EVENT_frame_start, telemetry_frame_start, NULL) == SCS_RESULT_ok) && (version_params->register_for_event(SCS_TELEMETRY_EVENT_paused, telemetry_pause, NULL) == SCS_RESULT_ok) && (version_params->register_for_event(SCS_TELEMETRY_EVENT_started, telemetry_pause, NULL) == SCS_RESULT_ok); // Register configuration event, because it sends data like truck make, etc. version_params->register_for_event(SCS_TELEMETRY_EVENT_configuration, telemetry_configuration, NULL); if (!events_registered) { return SCS_RESULT_generic_error; } /*** REGISTER ALL TELEMETRY CHANNELS TO OUR SHARED MEMORY MAP ***/ registerChannel(TRUCK_CHANNEL_electric_enabled, bool, telemPtr->tel_rev1.engine_enabled); registerChannel(CHANNEL_game_time, u32, telemPtr->tel_rev2.time_abs); registerChannel(TRAILER_CHANNEL_connected, bool, telemPtr->tel_rev1.trailer_attached); registerChannel(TRUCK_CHANNEL_speed, float, telemPtr->tel_rev1.speed); registerChannel(TRUCK_CHANNEL_local_linear_acceleration, fvector, telemPtr->tel_rev1.accelerationX); registerChannel(TRUCK_CHANNEL_world_placement, dplacement, telemPtr->tel_rev1.coordinateX); registerChannel(TRUCK_CHANNEL_engine_gear, s32, telemPtr->tel_rev1.gear); registerChannel(TRUCK_CHANNEL_displayed_gear, s32, telemPtr->tel_rev4.gearDashboard); registerChannel(TRUCK_CHANNEL_engine_rpm, float, telemPtr->tel_rev1.engineRpm); registerChannel(TRUCK_CHANNEL_fuel, float, telemPtr->tel_rev1.fuel); // TODO: Calculate fuel rate registerChannel(TRUCK_CHANNEL_fuel_average_consumption, float, telemPtr->tel_rev1.fuelAvgConsumption); registerChannel(TRUCK_CHANNEL_input_steering, float, telemPtr->tel_rev1.userSteer); registerChannel(TRUCK_CHANNEL_input_throttle, float, telemPtr->tel_rev1.userThrottle); registerChannel(TRUCK_CHANNEL_input_brake, float, telemPtr->tel_rev1.userBrake); registerChannel(TRUCK_CHANNEL_input_clutch, float, telemPtr->tel_rev1.userClutch); registerChannel(TRUCK_CHANNEL_effective_steering, float, telemPtr->tel_rev1.gameSteer); registerChannel(TRUCK_CHANNEL_effective_throttle, float, telemPtr->tel_rev1.gameThrottle); registerChannel(TRUCK_CHANNEL_effective_brake, float, telemPtr->tel_rev1.gameBrake); registerChannel(TRUCK_CHANNEL_effective_clutch, float, telemPtr->tel_rev1.gameClutch); // Auxilliary stuff: registerChannel(TRUCK_CHANNEL_retarder_level, u32, telemPtr->tel_rev3.retarderBrake); registerChannel(TRUCK_CHANNEL_hshifter_slot, u32, telemPtr->tel_rev3.shifterSlot); registerChannel(TRUCK_CHANNEL_hshifter_selector, bool, telemPtr->tel_rev3.shifterToggle); // Booleans registerChannel(TRUCK_CHANNEL_wipers, bool, telemPtr->tel_rev3.wipers); registerChannel(TRUCK_CHANNEL_parking_brake, bool, telemPtr->tel_rev3.parkBrake); registerChannel(TRUCK_CHANNEL_motor_brake, bool, telemPtr->tel_rev3.motorBrake); registerChannel(TRUCK_CHANNEL_electric_enabled, bool, telemPtr->tel_rev3.electricEnabled); registerChannel(TRUCK_CHANNEL_engine_enabled, bool, telemPtr->tel_rev3.engineEnabled); registerChannel(TRUCK_CHANNEL_lblinker, bool, telemPtr->tel_rev3.blinkerLeftActive); registerChannel(TRUCK_CHANNEL_rblinker, bool, telemPtr->tel_rev3.blinkerRightActive); registerChannel(TRUCK_CHANNEL_light_lblinker, bool, telemPtr->tel_rev3.blinkerLeftOn); registerChannel(TRUCK_CHANNEL_light_rblinker, bool, telemPtr->tel_rev3.blinkerRightOn); registerChannel(TRUCK_CHANNEL_light_parking, bool, telemPtr->tel_rev3.lightsParking); registerChannel(TRUCK_CHANNEL_light_low_beam, bool, telemPtr->tel_rev3.lightsBeamLow); registerChannel(TRUCK_CHANNEL_light_high_beam, bool, telemPtr->tel_rev3.lightsBeamHigh); registerChannel(TRUCK_CHANNEL_light_aux_front, bool, telemPtr->tel_rev3.lightsAuxFront); registerChannel(TRUCK_CHANNEL_light_aux_roof, bool, telemPtr->tel_rev3.lightsAuxRoof); registerChannel(TRUCK_CHANNEL_light_beacon, bool, telemPtr->tel_rev3.lightsBeacon); registerChannel(TRUCK_CHANNEL_light_brake, bool, telemPtr->tel_rev3.lightsBrake); registerChannel(TRUCK_CHANNEL_light_reverse, bool, telemPtr->tel_rev3.lightsReverse); registerChannel(TRUCK_CHANNEL_battery_voltage_warning, bool, telemPtr->tel_rev3.batteryVoltageWarning); registerChannel(TRUCK_CHANNEL_brake_air_pressure_warning, bool, telemPtr->tel_rev3.airPressureWarning); registerChannel(TRUCK_CHANNEL_brake_air_pressure_emergency, bool, telemPtr->tel_rev3.airPressureEmergency); registerChannel(TRUCK_CHANNEL_adblue_warning, bool, telemPtr->tel_rev3.adblueWarning); registerChannel(TRUCK_CHANNEL_oil_pressure_warning, bool, telemPtr->tel_rev3.oilPressureWarning); registerChannel(TRUCK_CHANNEL_water_temperature_warning, bool, telemPtr->tel_rev3.waterTemperatureWarning); // Floats registerChannel(TRUCK_CHANNEL_brake_air_pressure, float, telemPtr->tel_rev3.airPressure); registerChannel(TRUCK_CHANNEL_brake_temperature, float, telemPtr->tel_rev3.brakeTemperature); registerChannel(TRUCK_CHANNEL_fuel_warning, bool, telemPtr->tel_rev3.fuelWarning); registerChannel(TRUCK_CHANNEL_adblue, float, telemPtr->tel_rev3.adblue); registerChannel(TRUCK_CHANNEL_adblue_average_consumption, float, telemPtr->tel_rev3.adblueConsumption); registerChannel(TRUCK_CHANNEL_oil_pressure, float, telemPtr->tel_rev3.oilPressure); registerChannel(TRUCK_CHANNEL_oil_temperature, float, telemPtr->tel_rev3.oilTemperature); registerChannel(TRUCK_CHANNEL_water_temperature, float, telemPtr->tel_rev3.waterTemperature); registerChannel(TRUCK_CHANNEL_battery_voltage, float, telemPtr->tel_rev3.batteryVoltage); registerChannel(TRUCK_CHANNEL_dashboard_backlight, float, telemPtr->tel_rev3.lightsDashboard); registerChannel(TRUCK_CHANNEL_wear_engine, float, telemPtr->tel_rev3.wearEngine); registerChannel(TRUCK_CHANNEL_wear_transmission, float, telemPtr->tel_rev3.wearTransmission); registerChannel(TRUCK_CHANNEL_wear_cabin, float, telemPtr->tel_rev3.wearCabin); registerChannel(TRUCK_CHANNEL_wear_chassis, float, telemPtr->tel_rev3.wearChassis); registerChannel(TRUCK_CHANNEL_wear_wheels, float, telemPtr->tel_rev3.wearWheels); registerChannel(TRAILER_CHANNEL_wear_chassis, float, telemPtr->tel_rev3.wearTrailer); registerChannel(TRUCK_CHANNEL_odometer, float, telemPtr->tel_rev3.truckOdometer); registerChannel(TRUCK_CHANNEL_cruise_control, float, telemPtr->tel_rev3.cruiseControlSpeed); registerChannel(TRUCK_CHANNEL_navigation_speed_limit, float, telemPtr->tel_rev4.speedLimit); registerChannel(TRUCK_CHANNEL_navigation_distance, float, telemPtr->tel_rev4.routeDistance); registerChannel(TRUCK_CHANNEL_navigation_time, float, telemPtr->tel_rev4.routeTime); registerChannel(TRUCK_CHANNEL_fuel_range, float, telemPtr->tel_rev4.fuelRange); // Set the structure with defaults. timestamp = static_cast<scs_timestamp_t>(0); last_timestamp = static_cast<scs_timestamp_t>(-1); return SCS_RESULT_ok; }