#include "cam_application.hpp" #include #include #include #include #include #include #include #include // This is a very simple CA application sending CAMs at a fixed rate. using namespace vanetza; using namespace vanetza::facilities; using namespace std::chrono; CamApplication::CamApplication(PositionProvider& positioning, Runtime& rt) : positioning_(positioning), runtime_(rt), cam_interval_(seconds(1)) { schedule_timer(); } void CamApplication::set_interval(Clock::duration interval) { cam_interval_ = interval; runtime_.cancel(this); schedule_timer(); } void CamApplication::set_station_id(std::uint32_t station_id) { station_id_ = station_id; } void CamApplication::print_generated_message(bool flag) { print_tx_msg_ = flag; } void CamApplication::print_received_message(bool flag) { print_rx_msg_ = flag; } CamApplication::PortType CamApplication::port() { return btp::ports::CAM; } void CamApplication::indicate(const DataIndication&, UpPacketPtr packet) { asn1::PacketVisitor visitor; std::shared_ptr cam = boost::apply_visitor(visitor, *packet); std::cout << "CAM application received a packet with " << (cam ? "decodable" : "broken") << " content" << std::endl; if (cam && print_rx_msg_) { std::cout << "Received CAM contains\n"; print_indented(std::cout, *cam, " ", 1); } } void CamApplication::schedule_timer() { runtime_.schedule(cam_interval_, std::bind(&CamApplication::on_timer, this, std::placeholders::_1), this); } void CamApplication::on_timer(Clock::time_point) { schedule_timer(); vanetza::asn1::Cam message; ItsPduHeader_t& header = message->header; header.protocolVersion = 2; header.messageID = ItsPduHeader__messageID_cam; header.stationID = station_id_; const auto time_now = duration_cast(runtime_.now().time_since_epoch()); uint16_t gen_delta_time = time_now.count(); CoopAwareness_t& cam = message->cam; cam.generationDeltaTime = gen_delta_time * GenerationDeltaTime_oneMilliSec; auto position = positioning_.position_fix(); if (!has_horizontal_position(position)) { std::cerr << "Skip CAM generation without position fix" << std::endl; return; } BasicContainer_t& basic = cam.camParameters.basicContainer; basic.stationType = StationType_passengerCar; copy(position, basic.referencePosition); cam.camParameters.highFrequencyContainer.present = HighFrequencyContainer_PR_basicVehicleContainerHighFrequency; BasicVehicleContainerHighFrequency& bvc = cam.camParameters.highFrequencyContainer.choice.basicVehicleContainerHighFrequency; bvc.heading.headingValue = 0; bvc.heading.headingConfidence = HeadingConfidence_equalOrWithinOneDegree; bvc.speed.speedValue = 0; bvc.speed.speedConfidence = SpeedConfidence_equalOrWithinOneCentimeterPerSec; bvc.driveDirection = DriveDirection_forward; bvc.longitudinalAcceleration.longitudinalAccelerationValue = LongitudinalAccelerationValue_unavailable; bvc.vehicleLength.vehicleLengthValue = VehicleLengthValue_unavailable; bvc.vehicleLength.vehicleLengthConfidenceIndication = VehicleLengthConfidenceIndication_noTrailerPresent; bvc.vehicleWidth = VehicleWidth_unavailable; bvc.curvature.curvatureValue = 0; bvc.curvature.curvatureConfidence = CurvatureConfidence_unavailable; bvc.curvatureCalculationMode = CurvatureCalculationMode_yawRateUsed; bvc.yawRate.yawRateValue = YawRateValue_unavailable; std::string error; if (!message.validate(error)) { throw std::runtime_error("Invalid high frequency CAM: %s" + error); } if (print_tx_msg_) { std::cout << "Generated CAM contains\n"; print_indented(std::cout, message, " ", 1); } DownPacketPtr packet { new DownPacket() }; packet->layer(OsiLayer::Application) = std::move(message); DataRequest request; request.its_aid = aid::CA; request.transport_type = geonet::TransportType::SHB; request.communication_profile = geonet::CommunicationProfile::ITS_G5; auto confirm = Application::request(request, std::move(packet)); if (!confirm.accepted()) { throw std::runtime_error("CAM application data request failed"); } }