/**
- * @brief Simple logger.
+ * @brief Shared memory telemetry plugin.
*
- * Writes the output into file inside the current directory.
+ * Makes telemetry data available to other processes via shared memory.
*/
// Windows stuff.
-
#ifdef _WIN32
# define WINVER 0x0500
# define _WIN32_WINNT 0x0500
# include <windows.h>
#endif
+// Linux
+#ifdef __linux__
+# include <unistd.h>
+# include <pthread.h>
+#endif
+
#include <stdio.h>
#include <stdlib.h>
-#include <assert.h>
#include <string.h>
-#include <pthread.h>
-
// SDK
-
#include "scssdk_telemetry.h"
#include "eurotrucks2/scssdk_eut2.h"
#include "eurotrucks2/scssdk_telemetry_eut2.h"
#include "amtrucks/scssdk_ats.h"
#include "amtrucks/scssdk_telemetry_ats.h"
-//LINUX
-
-#include <unistd.h>
-#include <signal.h>
-
#define UNUSED(x)
/**
}
}
#else
-#define log_open() 0
-#define log_close()
-#define log_print(...)
-#define log_named_value(...)
+# define log_open() 0
+# define log_close()
+# define log_print(...)
+# define log_named_value(...)
#endif // def LOGGING
// When we just initialized itself, assume that the time started
// just now.
-
if (last_timestamp == static_cast<scs_timestamp_t>(-1)) {
last_timestamp = info->paused_simulation_time;
}
// The timer might be sometimes restarted (e.g. after load) while
// we want to provide continuous time on our output.
-
if (info->flags & SCS_TELEMETRY_FRAME_START_FLAG_timer_restart) {
last_timestamp = 0;
}
}
}
-// Handling of individual channels.
+/**
+ * @brief Handling of individual channels.
+ */
SCSAPI_VOID telemetry_store_dplacement(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context)
{
- assert(value);
- assert(value->type == SCS_VALUE_TYPE_dplacement);
- assert(context);
telemetry_state_t *const tele = static_cast<telemetry_state_t *>(context);
// This callback was registered with the SCS_TELEMETRY_CHANNEL_FLAG_no_value flag
// so it is called even when the value is not available.
if ( !value || value->type != SCS_VALUE_TYPE_dplacement ) {
+ lock_shm();
tele->placement_isvalid = false;
+ unlock_shm();
return;
}
lock_shm();
SCSAPI_VOID telemetry_store_double(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context)
{
- // The SCS_TELEMETRY_CHANNEL_FLAG_no_value flag was not provided during registration
- // so this callback is only called when a valid value is available.
-
- assert(value);
- assert(value->type == SCS_VALUE_TYPE_double);
- assert(context);
lock_shm();
*static_cast<double *>(context) = value->value_double.value;
unlock_shm();
SCSAPI_VOID telemetry_store_double_nz(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context)
{
- // The SCS_TELEMETRY_CHANNEL_FLAG_no_value flag was not provided during registration
- // so this callback is only called when a valid value is available.
-
- assert(value);
- assert(value->type == SCS_VALUE_TYPE_double);
- assert(context);
if (value->value_double.value) {
lock_shm();
*static_cast<double *>(context) = value->value_double.value;
SCSAPI_VOID telemetry_store_s32(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context)
{
- // The SCS_TELEMETRY_CHANNEL_FLAG_no_value flag was not provided during registration
- // so this callback is only called when a valid value is available.
-
- assert(value);
- assert(value->type == SCS_VALUE_TYPE_s32);
- assert(context);
lock_shm();
*static_cast<int32_t *>(context) = value->value_s32.value;
unlock_shm();
SCSAPI_VOID telemetry_store_u32(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context)
{
- // The SCS_TELEMETRY_CHANNEL_FLAG_no_value flag was not provided during registration
- // so this callback is only called when a valid value is available.
-
- assert(value);
- assert(value->type == SCS_VALUE_TYPE_u32);
- assert(context);
lock_shm();
*static_cast<uint32_t *>(context) = value->value_u32.value;
unlock_shm();
SCSAPI_VOID telemetry_store_bool(const scs_string_t name, const scs_u32_t index, const scs_value_t *const value, const scs_context_t context)
{
- // The SCS_TELEMETRY_CHANNEL_FLAG_no_value flag was not provided during registration
- // so this callback is only called when a valid value is available.
-
- assert(value);
- assert(value->type == SCS_VALUE_TYPE_bool);
- assert(context);
lock_shm();
*static_cast<bool *>(context) = value->value_bool.value;
unlock_shm();
// Below 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_01;
if (version_params->common.game_version < MINIMAL_VERSION) {
log_print("WARNING: Too old version of the game, some features might behave incorrectly\n");
}
// 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_print("WARNING: Too new major version of the game, some features might behave incorrectly\n");
// 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_ATS_GAME_VERSION_1_01;
if (version_params->common.game_version < MINIMAL_VERSION) {
log_print("WARNING: Too old version of the game, some features might behave incorrectly\n");
}
// Future versions are fine as long the major version is not changed.
-
const scs_u32_t IMPLEMENTED_VERSION = SCS_TELEMETRY_ATS_GAME_VERSION_CURRENT;
if (SCS_GET_MAJOR_VERSION(version_params->common.game_version) > SCS_GET_MAJOR_VERSION(IMPLEMENTED_VERSION)) {
log_print("WARNING: Too new major version of the game, some features might behave incorrectly\n");
// 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.
-
const bool channels_registered =
(version_params->register_for_channel(SCS_TELEMETRY_CHANNEL_game_time, SCS_U32_NIL, SCS_VALUE_TYPE_u32, SCS_TELEMETRY_CHANNEL_FLAG_none, telemetry_store_u32, &telemetry->game_time) == SCS_RESULT_ok)
&& (version_params->register_for_channel(SCS_TELEMETRY_TRUCK_CHANNEL_world_placement, SCS_U32_NIL, SCS_VALUE_TYPE_dplacement, SCS_TELEMETRY_CHANNEL_FLAG_no_value, telemetry_store_dplacement, telemetry) == SCS_RESULT_ok)
{
// Any cleanup needed. The registrations will be removed automatically
// so there is no need to do that manually.
-
drop_shm();
log_close();
}