MotorControlModuleSDFM_TMS3.../Projects/EFC_Communication/UMLibrary/communication/service/BufferedCommunicationLink.cpp

153 lines
4.2 KiB
C++
Raw Permalink Normal View History

2024-06-07 11:12:56 +03:00
/*
* BufferedCommunicationLink.cpp
*
* Created on: 23 апр. 2020 г.
* Author: LeonidTitov
*/
#include "BufferedCommunicationLink.hh"
#include <climits>
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<PacketId>(), 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<const PacketId, IMessageHandler *>( packet_id, handler ) );
return true;
}
return false;
}
void communication::service::BufferedCommunicationLink::process() {
std::pair<bool, unsigned short> 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) {}