/* * BufferedCommunicationLink.cpp * * Created on: 23 апр. 2020 г. * Author: LeonidTitov */ #include "BufferedCommunicationLink.hh" #include communication::service::BufferedCommunicationLink::BufferedCommunicationLink( driver::ISlipCommunication & isc, std::pmr::memory_resource * memory, systemic::time_t timeout ) : communication(isc), free_counter(0), series(isc), subscribers( std::less(), memory ), timeout_after_send(timeout) { series_timeout.start(timeout_after_send); } bool communication::service::BufferedCommunicationLink::registerMessageHandler( IMessageHandler * handler, std::size_t packet_id ) { Subscribers::iterator subscriber = subscribers.find( packet_id ); if( subscriber == subscribers.end() ) { subscribers.insert( subscriber, std::pair( packet_id, handler ) ); return true; } return false; } void communication::service::BufferedCommunicationLink::process() { std::pair packet_info = communication.isPacketAvailable(); if( packet_info.first ) { free_counter++; PacketId packet_id = packet_info.second; Subscribers::iterator subscriber = subscribers.find( packet_id ); if( subscriber != subscribers.end() ) { MessageLink packet_handler( packet_id, communication, series ); subscriber->second->handler( &packet_handler ); } communication.recieveReset(); } if( communication.isPacketSent() and series_timeout.delayFinished() ) { series.update(); series_timeout.start(timeout_after_send); } } communication::IMessageSeriesLink::ostream & communication::service::BufferedCommunicationLink::Series::sendData( std::size_t size ) { data_sent = communication.sendHead( message_id | 0x8000u, size * ( CHAR_BIT / 8 ) ); return communication; } bool communication::service::BufferedCommunicationLink::Series::charge( PacketId id, std::size_t num_messages, IMessageSeriesHandler * handler ) { if( not message_remain ) { message_id = id; series_handler = handler; message_remain = num_messages; return true; } return false; } void communication::service::BufferedCommunicationLink::Series::update() { if( series_handler and message_remain ) { series_handler->handler( this ); if( data_sent ) { communication.sendEnd(); --message_remain; data_sent = false; } } } driver::IRxLink & communication::service::BufferedCommunicationLink::MessageLink::getData() { return communication; } driver::ITxLink & communication::service::BufferedCommunicationLink::MessageLink::createMessage( std::size_t size ) { //todo: x2??? message_answered = communication.sendHead( message_id | 0x8000u, size * ( CHAR_BIT / 8 ) ); return communication; } std::size_t communication::service::BufferedCommunicationLink::MessageLink::transmitBuffCapacity() const { return communication.transmitBuffCapacity(); } std::size_t communication::service::BufferedCommunicationLink::MessageLink::receiveBuffCapacity() const { return communication.receiveBuffCapacity(); } bool communication::service::BufferedCommunicationLink::MessageLink::createMessageSeries( std::size_t num_messages, IMessageSeriesHandler * handler ) { return series.charge(message_id, num_messages, handler); } communication::service::BufferedCommunicationLink::MessageLink::MessageLink( PacketId id, driver::ISlipCommunication & com, Series & ser ) : message_id(id), communication(com), series(ser), message_answered(false) {} communication::service::BufferedCommunicationLink::MessageLink::~MessageLink() noexcept { if( not message_answered ) communication.sendHead( message_id | 0x8000u, 0 ); communication.sendEnd(); } float communication::service::BufferedCommunicationLink::getPacketCounter() const { return free_counter; } communication::service::BufferedCommunicationLink::Series::Series( driver::ISlipCommunication & com ) : communication(com), data_sent(false), message_id(), message_remain(0), series_handler(nullptr) {}