23 #include <boost/system/system_error.hpp> 29 SerialPortHandler::SerialPortHandler(
const std::string &a_SerialPortName, std::shared_ptr<SerialPortHandlerCollection> a_SerialPortHandlerCollection, boost::asio::io_service &a_IOService): m_SerialPort(a_IOService), m_IOService(a_IOService) {
31 m_SerialPortName = a_SerialPortName;
32 m_SerialPortHandlerCollection = a_SerialPortHandlerCollection;
33 m_SendBufferOffset = 0;
34 ::memset(m_BufferTypeSubscribers, 0x00,
sizeof(m_BufferTypeSubscribers));
43 ++(m_BufferTypeSubscribers[a_HdlcdServerHandler->GetBufferType()]);
44 m_HdlcdServerHandlerList.push_back(a_HdlcdServerHandler);
45 if ((m_ProtocolState) && (m_ProtocolState->IsRunning())) {
52 if (m_Registered ==
false) {
58 m_ProtocolState->Stop();
59 m_SerialPort.cancel();
67 if (m_Registered ==
false) {
80 ForEachHdlcdServerHandler([
this](std::shared_ptr<HdlcdServerHandler> a_HdlcdServerHandler) {
81 a_HdlcdServerHandler->UpdateSerialPortState(m_ProtocolState->IsAlive(), m_SerialPortLock.
GetLockHolders());
86 m_ProtocolState->SendPayload(a_Payload, a_bReliable);
89 bool SerialPortHandler::RequiresBufferType(
E_BUFFER_TYPE a_eBufferType)
const {
91 return (m_BufferTypeSubscribers[a_eBufferType] != 0);
94 void SerialPortHandler::DeliverBufferToClients(
E_BUFFER_TYPE a_eBufferType,
const std::vector<unsigned char> &a_Payload,
bool a_bReliable,
bool a_bInvalid,
bool a_bWasSent) {
95 ForEachHdlcdServerHandler([a_eBufferType, &a_Payload, a_bReliable, a_bInvalid, a_bWasSent](std::shared_ptr<HdlcdServerHandler> a_HdlcdServerHandler) {
96 a_HdlcdServerHandler->DeliverBufferToClient(a_eBufferType, a_Payload, a_bReliable, a_bInvalid, a_bWasSent);
101 m_ProtocolState = std::make_shared<ProtocolState>(shared_from_this(), m_IOService);
102 return OpenSerialPort();
107 m_Registered =
false;
110 auto self(shared_from_this());
111 m_SerialPort.cancel();
112 m_SerialPort.close();
113 m_ProtocolState->Shutdown();
114 if (
auto l_SerialPortHandlerCollection = m_SerialPortHandlerCollection.lock()) {
115 l_SerialPortHandlerCollection->DeregisterSerialPortHandler(
self);
118 ForEachHdlcdServerHandler([](std::shared_ptr<HdlcdServerHandler> a_HdlcdServerHandler) {
119 a_HdlcdServerHandler->Stop();
124 bool SerialPortHandler::OpenSerialPort() {
125 bool l_bResult =
true;
128 m_SerialPort.open(m_SerialPortName);
129 m_SerialPort.set_option(boost::asio::serial_port::parity(boost::asio::serial_port::parity::none));
130 m_SerialPort.set_option(boost::asio::serial_port::character_size(boost::asio::serial_port::character_size(8)));
131 m_SerialPort.set_option(boost::asio::serial_port::stop_bits(boost::asio::serial_port::stop_bits::one));
132 m_SerialPort.set_option(boost::asio::serial_port::flow_control(boost::asio::serial_port::flow_control::none));
133 m_SerialPort.set_option(boost::asio::serial_port::baud_rate(m_BaudRate.
GetBaudRate()));
136 m_ProtocolState->Start();
141 }
catch (boost::system::system_error& error) {
142 std::cerr << error.what() << std::endl;
144 m_Registered =
false;
147 auto self(shared_from_this());
148 m_ProtocolState->Shutdown();
149 if (
auto l_SerialPortHandlerCollection = m_SerialPortHandlerCollection.lock()) {
150 l_SerialPortHandlerCollection->DeregisterSerialPortHandler(
self);
153 ForEachHdlcdServerHandler([](std::shared_ptr<HdlcdServerHandler> a_HdlcdServerHandler) {
154 a_HdlcdServerHandler->Stop();
161 void SerialPortHandler::ChangeBaudRate() {
164 m_SerialPort.set_option(boost::asio::serial_port::baud_rate(m_BaudRate.
GetBaudRate()));
168 void SerialPortHandler::TransmitHDLCFrame(
const std::vector<unsigned char> &a_Payload) {
170 assert(m_SendBufferOffset == 0);
172 m_SendBuffer = std::move(a_Payload);
178 void SerialPortHandler::QueryForPayload(
bool a_bQueryReliable,
bool a_bQueryUnreliable) {
179 ForEachHdlcdServerHandler([a_bQueryReliable, a_bQueryUnreliable](std::shared_ptr<HdlcdServerHandler> a_HdlcdServerHandler) {
180 a_HdlcdServerHandler->QueryForPayload(a_bQueryReliable, a_bQueryUnreliable);
184 void SerialPortHandler::DoRead() {
185 auto self(shared_from_this());
186 m_SerialPort.async_read_some(boost::asio::buffer(m_ReadBuffer, max_length),[
this,
self](boost::system::error_code a_ErrorCode, std::size_t a_BytesRead) {
188 m_ProtocolState->AddReceivedRawBytes(m_ReadBuffer, a_BytesRead);
194 std::cerr <<
"SERIAL READ ERROR:" << a_ErrorCode << std::endl;
201 void SerialPortHandler::DoWrite() {
202 auto self(shared_from_this());
203 m_SerialPort.async_write_some(boost::asio::buffer(&m_SendBuffer[m_SendBufferOffset], (m_SendBuffer.size() - m_SendBufferOffset)),[
this,
self](boost::system::error_code a_ErrorCode, std::size_t a_BytesSent) {
205 m_SendBufferOffset += a_BytesSent;
206 if (m_SendBufferOffset == m_SendBuffer.size()) {
208 m_SendBufferOffset = 0;
210 m_ProtocolState->TriggerNextHDLCFrame();
220 std::cerr <<
"SERIAL WRITE ERROR:" << a_ErrorCode << std::endl;
227 void SerialPortHandler::ForEachHdlcdServerHandler(std::function<
void(std::shared_ptr<HdlcdServerHandler>)> a_Function) {
229 bool l_RebuildSubscriptions =
false;
230 static bool s_bCyclicCallGuard =
false;
231 for (
auto cur = m_HdlcdServerHandlerList.begin(); cur != m_HdlcdServerHandlerList.end();) {
234 if (
auto l_ClientHandler = cur->lock()) {
236 bool l_bGuardLocked =
false;
237 if (!s_bCyclicCallGuard) {
238 s_bCyclicCallGuard =
true;
239 l_bGuardLocked =
true;
242 a_Function(l_ClientHandler);
243 if (l_bGuardLocked) {
244 s_bCyclicCallGuard =
false;
248 if (!s_bCyclicCallGuard) {
249 m_HdlcdServerHandlerList.erase(cur);
250 l_RebuildSubscriptions =
true;
257 if (l_RebuildSubscriptions) {
259 ::memset(m_BufferTypeSubscribers, 0x00,
sizeof(m_BufferTypeSubscribers));
260 ForEachHdlcdServerHandler([
this](std::shared_ptr<HdlcdServerHandler> a_HdlcdServerHandler) {
262 ++(m_BufferTypeSubscribers[a_HdlcdServerHandler->GetBufferType()]);
The HDLC Deamon implements the HDLC protocol to easily talk to devices connected via serial communica...
size_t GetLockHolders() const
SerialPortHandler(const std::string &a_SerialPortName, std::shared_ptr< SerialPortHandlerCollection > a_SerialPortHandlerCollection, boost::asio::io_service &a_IOService)
void DeliverPayloadToHDLC(const std::vector< unsigned char > &a_Payload, bool a_bReliable)
void ToggleBaudRate()
Iterate to another baud rate setting.
unsigned int GetBaudRate() const
Deliver the currently used baud rate setting.
bool GetSerialPortState() const
void AddHdlcdServerHandler(std::shared_ptr< HdlcdServerHandler > a_HdlcdServerHandler)
The HDLC Deamon implements the HDLC protocol to easily talk to devices connected via serial communica...
The HDLC Deamon implements the HDLC protocol to easily talk to devices connected via serial communica...
void PropagateSerialPortState()
Copyright (c) 2016, Florian Evers, florian-evers@gmx.de All rights reserved.