diff --git a/ebclfsa/MODULE.bazel b/ebclfsa/MODULE.bazel index 4fdc46c3f5..5616cd5ec4 100644 --- a/ebclfsa/MODULE.bazel +++ b/ebclfsa/MODULE.bazel @@ -74,6 +74,8 @@ single_version_override( version = "0.1.1", ) +bazel_dep(name = "score_scrample", version = "0.1.0") + # git_override are not forwarded by bazel_dep, so we need to redefine it here git_override( module_name = "trlc", diff --git a/ebclfsa/example/ipc_bridge/BUILD b/ebclfsa/example/ipc_bridge/BUILD deleted file mode 100644 index 79b84cc3bc..0000000000 --- a/ebclfsa/example/ipc_bridge/BUILD +++ /dev/null @@ -1,65 +0,0 @@ -# ******************************************************************************* -# Copyright (c) 2025 Contributors to the Eclipse Foundation -# -# See the NOTICE file(s) distributed with this work for additional -# information regarding copyright ownership. -# -# This program and the accompanying materials are made available under the -# terms of the Apache License Version 2.0 which is available at -# https://www.apache.org/licenses/LICENSE-2.0 -# -# SPDX-License-Identifier: Apache-2.0 -# ******************************************************************************* -load("@score_baselibs//score/language/safecpp:toolchain_features.bzl", "COMPILER_WARNING_FEATURES") - -cc_binary( - name = "ipc_bridge_cpp", - srcs = [ - "assert_handler.cpp", - "assert_handler.h", - "main.cpp", - ], - data = ["etc/mw_com_config.json"], - features = COMPILER_WARNING_FEATURES, - deps = [ - ":sample_sender_receiver", - "@score_communication//score/mw/com", - "@score_baselibs//score/mw/log", - "@score_baselibs//score/language/futurecpp", - "@boost.program_options", - ], - visibility = [ - "//visibility:public", # platform_only - ], -) - -cc_library( - name = "sample_sender_receiver", - srcs = [ - "sample_sender_receiver.cpp", - ], - hdrs = [ - "sample_sender_receiver.h", - ], - features = COMPILER_WARNING_FEATURES, - deps = [ - ":datatype", - "@score_communication//score/mw/com", - "@score_baselibs//score/mw/log", - ], -) - -cc_library( - name = "datatype", - srcs = [ - "datatype.cpp", - ], - hdrs = [ - "datatype.h", - ], - features = COMPILER_WARNING_FEATURES, - deps = [ - "@score_communication//score/mw/com", - "@score_baselibs//score/language/futurecpp", - ], -) diff --git a/ebclfsa/example/ipc_bridge/assert_handler.cpp b/ebclfsa/example/ipc_bridge/assert_handler.cpp deleted file mode 100644 index 9a46bdae1f..0000000000 --- a/ebclfsa/example/ipc_bridge/assert_handler.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#include "assert_handler.h" - -#include "score/mw/log/logging.h" - -#include -#include -#include -#include -#include - -namespace score::mw::com -{ - -namespace -{ - -void assert_handler(const score::cpp::handler_parameters& params) -{ - std::cerr << "Assertion \"" << params.condition << "\" failed"; - if (params.message != nullptr) - { - std::cerr << ": " << params.message; - } - std::cerr << " (" << params.file << ':' << params.line << ")" << std::endl; - std::cerr.flush(); - - score::mw::log::LogFatal("AsHa") << params.condition << params.message << params.file << params.line; - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - - const char* const no_abort = std::getenv("ASSERT_NO_CORE"); - if (no_abort != nullptr) - { - std::cerr << "Would not coredump on \"" << no_abort << "\"" << std::endl; - if (std::strcmp(no_abort, params.condition) == 0) - { - std::cerr << "... matched." << std::endl; - std::cerr.flush(); - std::quick_exit(1); - } - std::cerr << "... not matched." << std::endl; - } - std::cerr.flush(); -} - -} // namespace - -void SetupAssertHandler() -{ - score::cpp::set_assertion_handler(assert_handler); - // in addition, delay the calls to std::terminate() till the datarouter is able to read the logs - std::set_terminate([]() { - std::this_thread::sleep_for(std::chrono::milliseconds(500)); - std::abort(); - }); -} - -} // namespace score::mw::com diff --git a/ebclfsa/example/ipc_bridge/assert_handler.h b/ebclfsa/example/ipc_bridge/assert_handler.h deleted file mode 100644 index b163843cd2..0000000000 --- a/ebclfsa/example/ipc_bridge/assert_handler.h +++ /dev/null @@ -1,23 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#ifndef SCORE_MW_IPC_BRIDGE_ASSERTHANDLER_H -#define SCORE_MW_IPC_BRIDGE_ASSERTHANDLER_H - -namespace score::mw::com -{ - -void SetupAssertHandler(); - -} // namespace score::mw::com - -#endif // SCORE_MW_IPC_BRIDGE_ASSERTHANDLER_H diff --git a/ebclfsa/example/ipc_bridge/datatype.cpp b/ebclfsa/example/ipc_bridge/datatype.cpp deleted file mode 100644 index 83dcd7d427..0000000000 --- a/ebclfsa/example/ipc_bridge/datatype.cpp +++ /dev/null @@ -1,13 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#include "datatype.h" diff --git a/ebclfsa/example/ipc_bridge/datatype.h b/ebclfsa/example/ipc_bridge/datatype.h deleted file mode 100644 index 8f2b6c321d..0000000000 --- a/ebclfsa/example/ipc_bridge/datatype.h +++ /dev/null @@ -1,305 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#ifndef SCORE_IPC_BRIDGE_DATATYPE_H -#define SCORE_IPC_BRIDGE_DATATYPE_H - -#include "score/mw/com/types.h" - -namespace score::mw::com -{ - -constexpr std::size_t MAX_SUCCESSORS = 16U; -constexpr std::size_t MAX_LANES = 16U; - -enum class StdTimestampSyncState : std::uint32_t -{ - /// @brief Timestamp is in sync with the global master, MAX_DIFF property is guaranteed. - kStdTimestampSyncState_InSync = 0U, - /// @brief Timestamp is not in sync with the global master, no property guarantees can be given, use at your own - /// risk. - kStdTimestampSyncState_NotInSync = 1U, - /// @brief No timestamp is available due to infrastructure reasons (e.g. initial value, or no StbM integrated, or - /// prediction target timestamp cannot be calculated, ...). - kStdTimestampSyncState_Invalid = 255U -}; - -struct StdTimestamp -{ - /// @brief The sub-seconds part of the timestamp - /// - //// unit: [ns] - std::uint32_t fractional_seconds; - /// @brief The seconds part of the timestamp. - /// - /// unit: [s] - std::uint32_t seconds; - /// @brief Status whether the timestamp is in sync with the global master or not. - StdTimestampSyncState sync_status; -}; - -enum class EventDataQualifier : std::uint32_t -{ - /// @brief Event data available, normal operation. - /// - /// The event is valid and all data elements in the scope of the qualifier should be evaluated. Parts of the service - /// may still be in degradation (i.e.contained qualifiers or quality of service attributes (e.g. standard deviation) - /// must be evaluated). - kEventDataQualifier_EventDataAvailable = 0U, - /// @brief Event data available, but a degradation condition applies (e.g. calibration). The reason of the - /// degradation is stored in the parameter extendedQualifier. - /// - /// Parts of the data may still be in degradation. Therefore, the receiver must decide (based on contained - /// qualifiers or quality of service attributes) whether the data can be still used. - kEventDataQualifier_EventDataAvailableReduced = 1U, - /// @brief Data for this event is currently not available. The extendedQualifier (if present) contains information - /// on the reason for non-availability. - /// - /// The remaining information in the scope of the event (except extendedQualifier) must not be evaluated. - kEventDataQualifier_EventDataNotAvailable = 2U, - /// @brief Data for this event is currently unknown. - /// - /// The remaining information in the scope of the event (except extendedQualifier) must not be evaluated. - // kEventDataQualifier_EventDataUnknown = 14U, - /// @brief There is no event data available, due to the event data being invalid (e.g. CRC error) or due to a - /// timeout. - /// - /// The remaining information in the scope of the event (except extendedQualifier) must not be evaluated. - kEventDataQualifier_EventDataInvalid = 255U -}; - -struct MapApiLaneBoundaryData -{ -}; - -using LaneIdType = std::size_t; -using LaneWidth = std::size_t; -using LaneBoundaryId = std::size_t; - -namespace map_api -{ - -using LinkId = std::size_t; -using LengthM = std::double_t; - -struct LaneConnectionInfo -{ -}; - -using LaneConnectionInfoList = std::array; - -struct LaneRestrictionInfo -{ -}; - -using LaneRestrictionInfoList = std::array; - -struct ShoulderLaneInfo -{ -}; - -using ShoulderLaneInfoList = std::array; - -struct LaneToLinkAssociation -{ -}; - -using LaneUsedInBothDirections = bool; - -} // namespace map_api - -namespace adp -{ - -struct MapApiPointData -{ -}; - -enum class LaneType : std::size_t -{ - UNKNOWN, -}; - -enum class LaneTypeNew : std::size_t -{ - Unknown, -}; - -struct TurnDirection -{ -}; - -namespace map_api -{ - -using SpeedLimit = std::size_t; -using LaneFollowsMpp = bool; - -} // namespace map_api - -} // namespace adp - -struct MapApiLaneData -{ - MapApiLaneData() = default; - - MapApiLaneData(MapApiLaneData&&) = default; - - MapApiLaneData(const MapApiLaneData&) = default; - - MapApiLaneData& operator=(MapApiLaneData&&) = default; - - MapApiLaneData& operator=(const MapApiLaneData&) = default; - - /// @brief range: [1, n]. Unique ID of the lane - LaneIdType lane_id{0U}; - - /// @brief range: [1, n]. The IDs of all links that this lane belongs to - std::array link_ids; - - /// @brief The IDs of all lane from which this lane can be reached in longitudinal direction - std::array predecessor_lanes; - - /// @brief The IDs of all lane that can be reached from this lane in longitudinal direction - std::array successor_lanes; - - /// @brief The center line of this lane - std::array center_line; - - /// @brief The innermost left boundary at the beginning of this lane - LaneBoundaryId left_boundary_id{0U}; - - /// @brief The innermost right boundary at the beginning of this lane - LaneBoundaryId right_boundary_id{0U}; - - /// @brief The ID of the lane to the left - /// @note 0 indicates that there is no lane to the left - LaneIdType left_lane_id{0U}; - - /// @brief The id of the lane ro the right - /// @note 0 indicates that there is no lane to the right - LaneIdType right_lane_id{0U}; - - /// @brief The type of the lane - adp::LaneType lane_type{adp::LaneType::UNKNOWN}; - - /// @brief The type of the lane - adp::LaneTypeNew lane_type_new{adp::LaneTypeNew::Unknown}; - - /// @brief Describes Lane Connection Type and the range on the lane for which it applies - map_api::LaneConnectionInfoList lane_connection_info; - - /// @brief Describes Lane Restriction Type and the range on the lane for which it applies - map_api::LaneRestrictionInfoList lane_restriction_info; - - /// @brief Describes Shoulder Lane Type and the range on the lane for which it applies - /// @note not provided by MapDAL as of 6.08.2021r - map_api::ShoulderLaneInfoList shoulder_lane_info; - - /// @brief The turn direction associated with the lane - adp::TurnDirection turn_direction; - /// @brief unit: [cm]. The width of the current lane - /// @details This is the smallest width over the whole lane. When the lane is splitting or - /// merging, the width can be 0. - /// The width is also set to 0 when no width is available. - LaneWidth width_in_cm{0U}; - - /// @brief unit: [m]. The length of the current lane - map_api::LengthM length_in_m{0.0}; - - /// @brief The speed limits on the current lane - std::array speed_limits; - - /// @brief struct describing whether the lane is part of calculated Most Probable Path, or if yes within a range - adp::map_api::LaneFollowsMpp lane_follows_mpp; - - /// @brief Boolean flag describing whether lane is fully attributed - bool is_fully_attributed{false}; - - /// @brief array containing the IDs of all left lane boundaries ordered from curb to middle - std::array left_lane_boundaries_ids; - - /// @brief array containing the IDs of all right lane boundaries ordered from curb to middle - std::array right_lane_boundaries_ids; - - /// @brief links associated with current lane - std::array link_associations; - - /// @brief array of lane ranges where lane can be used in both directions. - std::array used_in_both_directions; -}; - -struct LaneGroupData -{ -}; - -struct MapApiLanesStamped -{ - MapApiLanesStamped() = default; - - MapApiLanesStamped(MapApiLanesStamped&&) = default; - - MapApiLanesStamped(const MapApiLanesStamped&) = default; - - MapApiLanesStamped& operator=(MapApiLanesStamped&&) = default; - - MapApiLanesStamped& operator=(const MapApiLanesStamped&) = default; - - StdTimestamp time_stamp{0, 0, StdTimestampSyncState::kStdTimestampSyncState_Invalid}; - - /// @brief A name of the coordinate frame, used while fetching data. - /// - /// Depending on the driving scenario, different coordinate frames can be used. - /// Case "map_debug" : for Highway scenario it is an NTM planar coordinate system. - /// Case: "local_map_frame": for Urban scenario it is a vehicle's local coordinate system. - std::array frame_id; - - /// @brief Current projection id. - /// - /// In case of NTM geodetic reference system, a zone can be of an arbitrary size, thus doesn't have a fixed - /// descriptor. This variable provides an index of the zone, in which the vehicle is currently located. - /// - /// range: [0, n] - std::uint32_t projection_id{}; - - /// @brief Describes the different kinds of quality levels of interface data. (placeholder for future concrete - /// implementation, for now we just initialize by not available) - EventDataQualifier event_data_qualifier{EventDataQualifier::kEventDataQualifier_EventDataNotAvailable}; - - /// @brief An array, containing lane boundaries, which refer to lanes from the given parent data structure. Lane - /// boundary indicates edge of the lane. - std::array lane_boundaries; - - /// @brief All lanes from HD map for a relevant piece of road. - std::array lanes; - - std::array lane_groups; - - std::uint32_t x; - std::size_t hash_value; -}; - -template -class IpcBridgeInterface : public Trait::Base -{ - public: - using Trait::Base::Base; - - typename Trait::template Event map_api_lanes_stamped_{*this, "map_api_lanes_stamped"}; -}; - -using IpcBridgeProxy = AsProxy; -using IpcBridgeSkeleton = AsSkeleton; - -} // namespace score::mw::com - -#endif // SCORE_IPC_BRIDGE_DATATYPE_H diff --git a/ebclfsa/example/ipc_bridge/etc/logging.json b/ebclfsa/example/ipc_bridge/etc/logging.json deleted file mode 100644 index ac6589ca35..0000000000 --- a/ebclfsa/example/ipc_bridge/etc/logging.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "appId": "IPBR", - "appDesc": "ipc_bridge", - "logLevel": "kDebug", - "logLevelThresholdConsole": "kDebug", - "logMode": "kRemote|kConsole", - "dynamicDatarouterIdentifiers" : true -} diff --git a/ebclfsa/example/ipc_bridge/etc/mw_com_config.json b/ebclfsa/example/ipc_bridge/etc/mw_com_config.json deleted file mode 100644 index f9a7701535..0000000000 --- a/ebclfsa/example/ipc_bridge/etc/mw_com_config.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "serviceTypes": [ - { - "serviceTypeName": "/bmw/adp/MapApiLanesStamped", - "version": { - "major": 1, - "minor": 0 - }, - "bindings": [ - { - "binding": "SHM", - "serviceId": 6432, - "events": [ - { - "eventName": "map_api_lanes_stamped", - "eventId": 1 - }, - { - "eventName": "dummy_data_stamped", - "eventId": 2 - } - ] - } - ] - } - ], - "serviceInstances": [ - { - "instanceSpecifier": "xpad/cp60/MapApiLanesStamped", - "serviceTypeName": "/bmw/adp/MapApiLanesStamped", - "version": { - "major": 1, - "minor": 0 - }, - "instances": [ - { - "instanceId": 1, - "allowedConsumer": { - "QM": [ - 4002, - 0 - ] - }, - "allowedProvider": { - "QM": [ - 4001, - 0 - ] - }, - "asil-level": "QM", - "binding": "SHM", - "events": [ - { - "eventName": "map_api_lanes_stamped", - "numberOfSampleSlots": 10, - "maxSubscribers": 3 - } - ] - } - ] - } - ] -} diff --git a/ebclfsa/example/ipc_bridge/main.cpp b/ebclfsa/example/ipc_bridge/main.cpp deleted file mode 100644 index ca3ea37d16..0000000000 --- a/ebclfsa/example/ipc_bridge/main.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#include "assert_handler.h" -#include "sample_sender_receiver.h" - -#include - -#include -#include - -#include "score/mw/com/types.h" -#include "score/mw/com/runtime.h" - -using namespace std::chrono_literals; - -struct Params -{ - score::cpp::optional mode; - score::cpp::optional instance_manifest; - score::cpp::optional cycle_time; - score::cpp::optional cycle_num; - bool check_sample_hash; -}; - -template -score::cpp::optional GetValueIfProvided(const boost::program_options::variables_map& args, std::string arg_string) -{ - return (args.count(arg_string) > 0U) ? static_cast(args[arg_string].as()) - : score::cpp::optional(); -} - -Params ParseCommandLineArguments(const int argc, const char** argv) -{ - namespace po = boost::program_options; - - po::options_description options; - - options.add_options()("help,h", "Display the help message"); - options.add_options()( - "num-cycles,n", - po::value()->default_value(0U), - "Number of cycles that are executed before determining success or failure. 0 indicates no limit."); - options.add_options()("mode,m", - po::value(), - "Set to either send/skeleton or recv/proxy to determine the role of the process"); - options.add_options()("cycle-time,t", po::value(), "Cycle time in milliseconds for sending/polling"); - options.add_options()( - "service_instance_manifest,s", po::value(), "Path to the com configuration file"); - options.add_options()( - "disable-hash-check,d", - po::bool_switch(), - "Do not check the sample hash value in the receiver. If true, the sample hash is not checked."); - - po::variables_map args; - const auto parsed_args = - po::command_line_parser{argc, argv} - .options(options) - .style(po::command_line_style::unix_style | po::command_line_style::allow_long_disguise) - .run(); - po::store(parsed_args, args); - - if (args.count("help") > 0U) - { - std::cerr << options << std::endl; - throw std::runtime_error("Could not parse command line arguments"); - } - - return {GetValueIfProvided(args, "mode"), - GetValueIfProvided(args, "service_instance_manifest"), - GetValueIfProvided(args, "cycle-time"), - GetValueIfProvided(args, "num-cycles"), - args.count("disable-hash-check") == 0U}; -} - -int main(const int argc, const char** argv) -{ - score::mw::com::SetupAssertHandler(); - Params params = ParseCommandLineArguments(argc, argv); - - if (!params.mode.has_value() || !params.cycle_num.has_value() || !params.cycle_time.has_value()) - { - std::cerr << "Mode, number of cycles and cycle time should be specified" << std::endl; - return EXIT_FAILURE; - } - - if (params.instance_manifest.has_value()) - { - const std::string& manifest_path = params.instance_manifest.value(); - score::StringLiteral runtime_args[2u] = {"-service_instance_manifest", manifest_path.c_str()}; - score::mw::com::runtime::InitializeRuntime(2, runtime_args); - } - - const auto mode = params.mode.value(); - const auto cycles = params.cycle_num.value(); - const auto cycle_time = params.cycle_time.value(); - const auto check_sample_hash = params.check_sample_hash; - - score::mw::com::EventSenderReceiver event_sender_receiver{}; - - const auto instance_specifier_result = score::mw::com::InstanceSpecifier::Create("xpad/cp60/MapApiLanesStamped"); - if (!instance_specifier_result.has_value()) - { - std::cerr << "Invalid instance specifier, terminating." << std::endl; - return EXIT_FAILURE; - } - const auto& instance_specifier = instance_specifier_result.value(); - - if (mode == "send" || mode == "skeleton") - { - return event_sender_receiver.RunAsSkeleton(instance_specifier, cycle_time, cycles); - } - else if (mode == "recv" || mode == "proxy") - { - return event_sender_receiver.RunAsProxy(instance_specifier, cycle_time, cycles, false, check_sample_hash); - } - else - { - std::cerr << "Unknown mode " << mode << ", terminating." << std::endl; - return EXIT_FAILURE; - } -} diff --git a/ebclfsa/example/ipc_bridge/sample_sender_receiver.cpp b/ebclfsa/example/ipc_bridge/sample_sender_receiver.cpp deleted file mode 100644 index db24972df2..0000000000 --- a/ebclfsa/example/ipc_bridge/sample_sender_receiver.cpp +++ /dev/null @@ -1,463 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#include "sample_sender_receiver.h" -#include "score/mw/com/impl/generic_proxy.h" -#include "score/mw/com/impl/generic_proxy_event.h" -#include "score/mw/com/impl/handle_type.h" - -#include "score/concurrency/notification.h" - -#include "score/mw/com/impl/proxy_event.h" -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace std::chrono_literals; - -namespace score::mw::com -{ - -namespace -{ - -constexpr std::size_t START_HASH = 64738U; - -std::ostream& operator<<(std::ostream& stream, const InstanceSpecifier& instance_specifier) -{ - stream << instance_specifier.ToString(); - return stream; -} - -template -void ToStringImpl(std::ostream& o, T t) -{ - o << t; -} - -template -void ToStringImpl(std::ostream& o, T t, Args... args) -{ - ToStringImpl(o, t); - ToStringImpl(o, args...); -} - -template -std::string ToString(Args... args) -{ - std::ostringstream oss; - ToStringImpl(oss, args...); - return oss.str(); -} - -void HashArray(const std::array& array, std::size_t& seed) -{ - const std::ptrdiff_t buffer_size = - reinterpret_cast(&*array.cend()) - reinterpret_cast(&*array.cbegin()); - SCORE_LANGUAGE_FUTURECPP_ASSERT_PRD(buffer_size > 0); - seed = score::cpp::hash_bytes_fnv1a(static_cast(array.data()), static_cast(buffer_size), seed); -} - -class SampleReceiver -{ - public: - explicit SampleReceiver(const InstanceSpecifier& instance_specifier, bool check_sample_hash = true) - : instance_specifier_{instance_specifier}, - last_received_{}, - received_{0U}, - check_sample_hash_{check_sample_hash} - { - } - - void ReceiveSample(const MapApiLanesStamped& map) noexcept - { - std::cout << ToString(instance_specifier_, ": Received sample: ", map.x, "\n"); - - if (CheckReceivedSample(map)) - { - received_ += 1U; - } - last_received_ = map.x; - } - - std::size_t GetReceivedSampleCount() const noexcept - { - return received_; - } - - private: - bool CheckReceivedSample(const MapApiLanesStamped& map) const noexcept - { - if (last_received_.has_value()) - { - if (map.x <= last_received_.value()) - { - std::cerr << ToString(instance_specifier_, - ": The received sample is out of order. Expected that ", - map.x, - " > ", - last_received_.value(), - "\n"); - return false; - } - } - - if (check_sample_hash_) - { - std::size_t hash_value = START_HASH; - for (const MapApiLaneData& lane : map.lanes) - { - HashArray(lane.successor_lanes, hash_value); - } - - if (hash_value != map.hash_value) - { - std::cerr << ToString(instance_specifier_, - ": Unexpected data received, hash comparison failed: ", - hash_value, - ", expected ", - map.hash_value, - "\n"); - return false; - } - } - - return true; - } - - const score::mw::com::InstanceSpecifier& instance_specifier_; - score::cpp::optional last_received_; - std::size_t received_; - bool check_sample_hash_; -}; - -score::cpp::optional>> GetMapApiLanesStampedProxyEvent( - IpcBridgeProxy& proxy) -{ - return proxy.map_api_lanes_stamped_; -} - -score::cpp::optional> GetMapApiLanesStampedProxyEvent( - GenericProxy& generic_proxy) -{ - const std::string event_name{"map_api_lanes_stamped"}; - auto event_it = generic_proxy.GetEvents().find(event_name); - if (event_it == generic_proxy.GetEvents().cend()) - { - std::cerr << "Could not find event " << event_name << " in generic proxy event map\n"; - return {}; - } - return event_it->second; -} - -/// \brief Function that returns the value pointed to by a pointer -const MapApiLanesStamped& GetSamplePtrValue(const MapApiLanesStamped* const sample_ptr) -{ - return *sample_ptr; -} - -/// \brief Function that casts and returns the value pointed to by a void pointer -/// -/// Assumes that the object in memory being pointed to is of type MapApiLanesStamped. -const MapApiLanesStamped& GetSamplePtrValue(const void* const void_ptr) -{ - auto* const typed_ptr = static_cast(void_ptr); - return *typed_ptr; -} - -/// \brief Function that extracts the underlying pointer to const from a SamplePtr and casts away the const. Only used -/// in death test to check that we can't modify the SamplePtr! -template -SampleType* ExtractNonConstPointer(const SamplePtr& sample) noexcept -{ - const SampleType* sample_const_ptr = sample.get(); - - // The underlying shared memory in which the SamplePtr is stored (i.e. the data section) is opened read-only by the - // operating system when we open and mmap the memory into our consumer process. However, the SampleType itself is - // not a const object (although the SamplePtr holds a pointer to const). The standard states that "Modifying a const - // object through a non-const access path and referring to a volatile object through a non-volatile glvalue results - // in undefined behavior." (https://en.cppreference.com/w/cpp/language/const_cast). We are _not_ modifying a const - // object. We are modifying a non-const object that is pointer to by a pointer to const. Therefore, modifying the - // underlying object after using const cast is not undefined behaviour. We expect that the failure should occur - // since the memory in which the object is allocated is in read-only memory. - auto* sample_non_const_ptr = const_cast(sample_const_ptr); - return sample_non_const_ptr; -} - -void ModifySampleValue(const SamplePtr& sample) -{ - auto* const sample_non_const_ptr = ExtractNonConstPointer(sample); - sample_non_const_ptr->x += 1; -} - -void ModifySampleValue(const SamplePtr& sample) -{ - auto* const sample_non_const_ptr = ExtractNonConstPointer(sample); - - auto* const typed_ptr = static_cast(sample_non_const_ptr); - typed_ptr->x += 1; -} - -template -score::Result GetHandleFromSpecifier(const InstanceSpecifier& instance_specifier) -{ - std::cout << ToString(instance_specifier, ": Running as proxy, looking for services\n"); - ServiceHandleContainer handles{}; - do - { - auto handles_result = ProxyType::FindService(instance_specifier); - if (!handles_result.has_value()) - { - return MakeUnexpected(std::move(handles_result.error())); - } - handles = std::move(handles_result).value(); - if (handles.size() == 0) - { - std::this_thread::sleep_for(500ms); - } - } while (handles.size() == 0); - - std::cout << ToString(instance_specifier, ": Found service, instantiating proxy\n"); - return handles.front(); -} - -Result> PrepareMapLaneSample(IpcBridgeSkeleton& skeleton, - const std::size_t cycle) -{ - const std::default_random_engine::result_type seed{static_cast( - std::chrono::steady_clock::now().time_since_epoch().count())}; - std::default_random_engine rng{seed}; - - auto sample_result = skeleton.map_api_lanes_stamped_.Allocate(); - if (!sample_result.has_value()) - { - return sample_result; - } - auto sample = std::move(sample_result).value(); - sample->hash_value = START_HASH; - sample->x = static_cast(cycle); - - std::cout << ToString("Sending sample: ", sample->x, "\n"); - for (MapApiLaneData& lane : sample->lanes) - { - for (LaneIdType& successor : lane.successor_lanes) - { - successor = std::uniform_int_distribution()(rng); - } - - HashArray(lane.successor_lanes, sample->hash_value); - } - return sample; -} - -} // namespace - -template -int EventSenderReceiver::RunAsProxy(const score::mw::com::InstanceSpecifier& instance_specifier, - const score::cpp::optional cycle_time, - const std::size_t num_cycles, - bool try_writing_to_data_segment, - bool check_sample_hash) -{ - // For a GenericProxy, the SampleType will be void. For a regular proxy, it will by MapApiLanesStamped. - using SampleType = - typename std::conditional::value, void, MapApiLanesStamped>::type; - constexpr std::size_t SAMPLES_PER_CYCLE = 2U; - - auto handle_result = GetHandleFromSpecifier(instance_specifier); - if (!handle_result.has_value()) - { - std::cerr << "Unable to find service: " << instance_specifier - << ". Failed with error: " << handle_result.error() << ", bailing!\n"; - return EXIT_FAILURE; - } - auto handle = handle_result.value(); - - auto proxy_result = ProxyType::Create(std::move(handle)); - if (!proxy_result.has_value()) - { - std::cerr << "Unable to construct proxy: " << proxy_result.error() << ", bailing!\n"; - return EXIT_FAILURE; - } - auto& proxy = proxy_result.value(); - - auto map_api_lanes_stamped_event_optional = GetMapApiLanesStampedProxyEvent(proxy); - if (!map_api_lanes_stamped_event_optional.has_value()) - { - std::cerr << "Could not get MapApiLanesStamped proxy event\n"; - return EXIT_FAILURE; - } - auto& map_api_lanes_stamped_event = map_api_lanes_stamped_event_optional.value().get(); - - concurrency::Notification event_received; - if (!cycle_time.has_value()) - { - map_api_lanes_stamped_event.SetReceiveHandler([&event_received, &instance_specifier]() { - std::cout << ToString(instance_specifier, ": Callback called\n"); - event_received.notify(); - }); - } - - std::cout << ToString(instance_specifier, ": Subscribing to service\n"); - map_api_lanes_stamped_event.Subscribe(SAMPLES_PER_CYCLE); - - score::cpp::optional last_received{}; - SampleReceiver receiver{instance_specifier, check_sample_hash}; - for (std::size_t cycle = 0U; cycle < num_cycles;) - { - const auto cycle_start_time = std::chrono::steady_clock::now(); - if (cycle_time.has_value()) - { - std::this_thread::sleep_for(*cycle_time); - } - - const auto received_before = receiver.GetReceivedSampleCount(); - Result num_samples_received = map_api_lanes_stamped_event.GetNewSamples( - [&receiver, try_writing_to_data_segment](SamplePtr sample) noexcept { - if (try_writing_to_data_segment) - { - // Try writing to the data segment (in which the sample data is stored). Used in a death test to - // ensure that this is not possible. - ModifySampleValue(sample); - } - - // For the GenericProxy case, the void pointer managed by the SamplePtr will be cast to - // MapApiLanesStamped. - const MapApiLanesStamped& sample_value = GetSamplePtrValue(sample.get()); - receiver.ReceiveSample(sample_value); - }, - SAMPLES_PER_CYCLE); - const auto received = receiver.GetReceivedSampleCount() - received_before; - - const bool get_new_samples_api_error = !num_samples_received.has_value(); - const bool mismatch_api_returned_receive_count_vs_sample_callbacks = *num_samples_received != received; - const bool receive_handler_called_without_new_samples = *num_samples_received == 0 && !cycle_time.has_value(); - - if (get_new_samples_api_error || mismatch_api_returned_receive_count_vs_sample_callbacks || - receive_handler_called_without_new_samples) - { - std::stringstream ss; - ss << instance_specifier << ": Error in cycle " << cycle << " during sample reception: "; - if (!get_new_samples_api_error) - { - if (mismatch_api_returned_receive_count_vs_sample_callbacks) - { - ss << "number of received samples doesn't match to what IPC claims: " << *num_samples_received - << " vs " << received; - } - else - { - ss << "expected at least one new sample, since event-notifier has been called, but " - "GetNewSamples() didn't provide one! "; - } - } - else - { - ss << std::move(num_samples_received).error(); - } - ss << ", terminating.\n"; - std::cerr << ss.str(); - - map_api_lanes_stamped_event.Unsubscribe(); - return EXIT_FAILURE; - } - - if (*num_samples_received >= 1U) - { - std::cout << ToString(instance_specifier, ": Proxy received valid data\n"); - cycle += *num_samples_received; - } - - const auto cycle_duration = std::chrono::steady_clock::now() - cycle_start_time; - - std::cout << ToString(instance_specifier, - ": Cycle duration ", - std::chrono::duration_cast(cycle_duration).count(), - "ms\n"); - - event_received.reset(); - } - - std::cout << ToString(instance_specifier, ": Unsubscribing...\n"); - map_api_lanes_stamped_event.Unsubscribe(); - std::cout << ToString(instance_specifier, ": and terminating, bye bye\n"); - return EXIT_SUCCESS; -} - -int EventSenderReceiver::RunAsSkeleton(const score::mw::com::InstanceSpecifier& instance_specifier, - const std::chrono::milliseconds cycle_time, - const std::size_t num_cycles) -{ - auto create_result = IpcBridgeSkeleton::Create(instance_specifier); - if (!create_result.has_value()) - { - std::cerr << "Unable to construct skeleton: " << create_result.error() << ", bailing!\n"; - return EXIT_FAILURE; - } - auto& skeleton = create_result.value(); - - const auto offer_result = skeleton.OfferService(); - if (!offer_result.has_value()) - { - std::cerr << "Unable to offer service for skeleton: " << offer_result.error() << ", bailing!\n"; - return EXIT_FAILURE; - } - std::cout << "Starting to send data\n"; - - for (std::size_t cycle = 0U; cycle < num_cycles || num_cycles == 0U; ++cycle) - { - auto sample_result = PrepareMapLaneSample(skeleton, cycle); - if (!sample_result.has_value()) - { - std::cerr << "No sample received. Exiting.\n"; - return EXIT_FAILURE; - } - auto sample = std::move(sample_result).value(); - - { - std::lock_guard lock{event_sending_mutex_}; - skeleton.map_api_lanes_stamped_.Send(std::move(sample)); - event_published_ = true; - } - std::this_thread::sleep_for(cycle_time); - } - - std::cout << "Stop offering service..."; - skeleton.StopOfferService(); - std::cout << "and terminating, bye bye\n"; - - return EXIT_SUCCESS; -} - -template int EventSenderReceiver::RunAsProxy>( - const score::mw::com::InstanceSpecifier&, - const score::cpp::optional, - const std::size_t, - bool, - bool); -template int EventSenderReceiver::RunAsProxy( - const score::mw::com::InstanceSpecifier&, - const score::cpp::optional, - const std::size_t, - bool, - bool); - -} // namespace score::mw::com diff --git a/ebclfsa/example/ipc_bridge/sample_sender_receiver.h b/ebclfsa/example/ipc_bridge/sample_sender_receiver.h deleted file mode 100644 index 541ad6decb..0000000000 --- a/ebclfsa/example/ipc_bridge/sample_sender_receiver.h +++ /dev/null @@ -1,54 +0,0 @@ -/******************************************************************************** - * Copyright (c) 2025 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0 - * - * SPDX-License-Identifier: Apache-2.0 - ********************************************************************************/ -#ifndef SCORE_MW_COM_IPC_BRIDGE_SAMPLE_SENDER_RECEIVER_H -#define SCORE_MW_COM_IPC_BRIDGE_SAMPLE_SENDER_RECEIVER_H - -#include "datatype.h" - -#include - -#include -#include -#include -#include -#include - -namespace score::mw::com -{ - -class EventSenderReceiver -{ - public: - int RunAsSkeleton(const score::mw::com::InstanceSpecifier& instance_specifier, - const std::chrono::milliseconds cycle_time, - const std::size_t num_cycles); - - template > - int RunAsProxy(const score::mw::com::InstanceSpecifier& instance_specifier, - const score::cpp::optional cycle_time, - const std::size_t num_cycles, - bool try_writing_to_data_segment = false, - bool check_sample_hash = true); - - private: - std::mutex event_sending_mutex_{}; - std::atomic event_published_{false}; - - std::mutex map_lanes_mutex_{}; - std::vector> map_lanes_list_{}; -}; - -} // namespace score::mw::com - -#endif // SCORE_MW_COM_IPC_BRIDGE_SAMPLE_SENDER_RECEIVER_H diff --git a/ebclfsa/example/ipc_bridge_hi_wrapper/BUILD b/ebclfsa/example/ipc_bridge_hi_wrapper/BUILD index 7248b4a8f7..5d28b5dbf7 100644 --- a/ebclfsa/example/ipc_bridge_hi_wrapper/BUILD +++ b/ebclfsa/example/ipc_bridge_hi_wrapper/BUILD @@ -14,7 +14,7 @@ load("@score_baselibs//score/language/safecpp:toolchain_features.bzl", "COMPILER genrule( name = "ipc_bridge_cpp_sil", - srcs = ["//example/ipc_bridge:ipc_bridge_cpp"], + srcs = ["@score_scrample//src:scrample"], outs = ["ipc_bridge_cpp_sil"], cmd = "cp $(SRCS) $@ && \ chmod ugo+w $@ && \ @@ -44,7 +44,7 @@ cc_binary( ], features = COMPILER_WARNING_FEATURES, deps = [ - "//example/ipc_bridge:ipc_bridge_cpp", + "@score_scrample//src:scrample", ], ) @@ -69,7 +69,7 @@ genrule( name = "upload", srcs = [ ":ipc_bridge_cpp_sil", - "//example/ipc_bridge:ipc_bridge_cpp", + "@score_scrample//src:scrample", ":hi_app", ":fastdev-image", "mw_com_config.json", @@ -82,7 +82,7 @@ genrule( $(location run_qemu.sh) $(RULEDIR)/deb-qemuarm64-modified -pidfile $(RULEDIR)/qemu.pid > $(RULEDIR)/qemu_upload.log &\ sleep 30 ; \ sshpass -p linux scp -o StrictHostKeyChecking=no -P 2222 $(location :ipc_bridge_cpp_sil) root@localhost:/usr/bin &&\ - sshpass -p linux scp -o StrictHostKeyChecking=no -P 2222 $(location //example/ipc_bridge:ipc_bridge_cpp) root@localhost:/usr/bin &&\ + sshpass -p linux scp -o StrictHostKeyChecking=no -P 2222 $(location @score_scrample//src:scrample) root@localhost:/usr/bin &&\ sshpass -p linux scp -o StrictHostKeyChecking=no -P 2222 $(location :hi_app) root@localhost:/usr/bin &&\ sshpass -p linux scp -o StrictHostKeyChecking=no -P 2222 $(location mw_com_config.json) root@localhost:/etc/ &&\ sshpass -p linux scp -o StrictHostKeyChecking=no -P 2222 $(location logging.json) root@localhost:/etc/ &&\ @@ -107,7 +107,7 @@ genrule( cmd = " \ $(location run_qemu.sh) $(RULEDIR)/deb-qemuarm64-modified -pidfile $(RULEDIR)/qemu.pid > $(RULEDIR)/qemu_run.log &\ sleep 10 ; \ - sshpass -p linux ssh -o StrictHostKeyChecking=no -p 2222 root@localhost ipc_bridge_cpp -n 10 -m send -t 200 -s /etc/mw_com_config.json > $(RULEDIR)/ssh_run.log && \ + sshpass -p linux ssh -o StrictHostKeyChecking=no -p 2222 root@localhost scrample -n 10 -m send -t 200 -s /etc/mw_com_config.json > $(RULEDIR)/ssh_run.log && \ sshpass -p linux ssh -o StrictHostKeyChecking=no -p 2222 root@localhost crinit-ctl poweroff || true \ sleep 5 \ ", diff --git a/ebclfsa/example/ipc_bridge_hi_wrapper/logging.json b/ebclfsa/example/ipc_bridge_hi_wrapper/logging.json index 54646e1055..8b3d1eacc8 100644 --- a/ebclfsa/example/ipc_bridge_hi_wrapper/logging.json +++ b/ebclfsa/example/ipc_bridge_hi_wrapper/logging.json @@ -1,8 +1,8 @@ { "appId": "IPBR", "appDesc": "ipc_bridge", - "logLevel": "kInfo", + "logLevel": "kDebug", "logLevelThresholdConsole": "kInfo", - "logMode": "kRemote|kConsole", + "logMode": "kConsole", "dynamicDatarouterIdentifiers" : true } diff --git a/ebclfsa/example/ipc_bridge_hi_wrapper/mw_com_config.json b/ebclfsa/example/ipc_bridge_hi_wrapper/mw_com_config.json index f9a7701535..1e104bd484 100644 --- a/ebclfsa/example/ipc_bridge_hi_wrapper/mw_com_config.json +++ b/ebclfsa/example/ipc_bridge_hi_wrapper/mw_com_config.json @@ -1,7 +1,7 @@ { "serviceTypes": [ { - "serviceTypeName": "/bmw/adp/MapApiLanesStamped", + "serviceTypeName": "/score/MapApiLanesStamped", "version": { "major": 1, "minor": 0 @@ -26,8 +26,8 @@ ], "serviceInstances": [ { - "instanceSpecifier": "xpad/cp60/MapApiLanesStamped", - "serviceTypeName": "/bmw/adp/MapApiLanesStamped", + "instanceSpecifier": "score/MapApiLanesStamped", + "serviceTypeName": "/score/MapApiLanesStamped", "version": { "major": 1, "minor": 0