Goby3 3.2.3
2025.05.13
Loading...
Searching...
No Matches
serial_interface.h
Go to the documentation of this file.
1// Copyright 2019-2023:
2// GobySoft, LLC (2013-)
3// Community contributors (see AUTHORS file)
4// File authors:
5// Toby Schneider <toby@gobysoft.org>
6//
7//
8// This file is part of the Goby Underwater Autonomy Project Libraries
9// ("The Goby Libraries").
10//
11// The Goby Libraries are free software: you can redistribute them and/or modify
12// them under the terms of the GNU Lesser General Public License as published by
13// the Free Software Foundation, either version 2.1 of the License, or
14// (at your option) any later version.
15//
16// The Goby Libraries are distributed in the hope that they will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19// GNU Lesser General Public License for more details.
20//
21// You should have received a copy of the GNU Lesser General Public License
22// along with Goby. If not, see <http://www.gnu.org/licenses/>.
23
24#ifndef GOBY_MIDDLEWARE_IO_DETAIL_SERIAL_INTERFACE_H
25#define GOBY_MIDDLEWARE_IO_DETAIL_SERIAL_INTERFACE_H
26
27#include <memory> // for shared_ptr
28#include <ostream> // for endl
29#include <string> // for operator+
30#include <sys/ioctl.h> // for ioctl, TIOCM...
31
32#include <boost/asio/serial_port.hpp> // for serial_port
33
34#include "goby/middleware/io/detail/io_interface.h" // for PubSubLayer
35#include "goby/middleware/protobuf/io.pb.h" // for SerialCommand
36#include "goby/middleware/protobuf/serial_config.pb.h" // for SerialConfig
37#include "goby/util/debug_logger/flex_ostream.h" // for glog, FlexOs...
39namespace goby
40{
41namespace middleware
42{
43class Group;
44}
45} // namespace goby
46
47namespace goby
48{
49namespace middleware
50{
51namespace io
52{
53namespace detail
54{
55template <const goby::middleware::Group& line_in_group,
56 const goby::middleware::Group& line_out_group, PubSubLayer publish_layer,
57 PubSubLayer subscribe_layer, template <class> class ThreadType,
58 bool use_indexed_groups = false>
59class SerialThread : public IOThread<line_in_group, line_out_group, publish_layer, subscribe_layer,
60 goby::middleware::protobuf::SerialConfig,
61 boost::asio::serial_port, ThreadType, use_indexed_groups>
62{
63 using Base = IOThread<line_in_group, line_out_group, publish_layer, subscribe_layer,
64 goby::middleware::protobuf::SerialConfig, boost::asio::serial_port,
65 ThreadType, use_indexed_groups>;
66
67 public:
72 : Base(config, index, std::string("serial: ") + config.port())
73 {
74 auto command_out_callback =
75 [this](std::shared_ptr<const goby::middleware::protobuf::SerialCommand> cmd) {
76 goby::glog.is_debug2() && goby::glog << group(this->glog_group()) << "< [Command] "
77 << cmd->ShortDebugString() << std::endl;
78 if (!cmd->has_index() || cmd->index() == this->index())
79 {
80 switch (cmd->command())
81 {
83 if (this->socket_is_open())
84 this->mutable_serial_port().send_break();
85 break;
86
87 // sets RTS high, needed for PHSEN and PCO2W comms
89 if (this->socket_is_open())
90 {
91 int fd = this->mutable_serial_port().native_handle();
92 int RTS_flag = TIOCM_RTS;
93 // TIOCMBIS - set bit
94 ioctl(fd, TIOCMBIS, &RTS_flag);
95 }
96 break;
97
99 if (this->socket_is_open())
100 {
101 int fd = this->mutable_serial_port().native_handle();
102 int RTS_flag = TIOCM_RTS;
103 // TIOCMBIC - clear bit
104 ioctl(fd, TIOCMBIC, &RTS_flag);
105 }
106 break;
108 if (this->socket_is_open())
109 {
110 int fd = this->mutable_serial_port().native_handle();
111 int DTR_flag = TIOCM_DTR;
112 ioctl(fd, TIOCMBIS, &DTR_flag);
113 }
114 break;
115
117 if (this->socket_is_open())
118 {
119 int fd = this->mutable_serial_port().native_handle();
120 int DTR_flag = TIOCM_DTR;
121 ioctl(fd, TIOCMBIC, &DTR_flag);
122 }
123 break;
124 }
125 publish_status();
126 }
127 };
128
129 this->template subscribe_out<goby::middleware::protobuf::SerialCommand>(
130 command_out_callback);
131
133 this->interthread().template publish<line_in_group>(ready);
134 }
135
136 virtual ~SerialThread() override
137 {
138 this->template unsubscribe_out<goby::middleware::protobuf::SerialCommand>();
139 }
140
141 protected:
143 boost::asio::serial_port& mutable_serial_port() { return this->mutable_socket(); }
144
145 private:
146 void async_write(std::shared_ptr<const goby::middleware::protobuf::IOData> io_msg) override
147 {
148 basic_async_write(this, io_msg);
149 }
150
151 void publish_status()
152 {
153 auto status_msg = std::make_shared<protobuf::SerialStatus>();
154 if (this->index() != -1)
155 status_msg->set_index(this->index());
156
157 if (this->socket_is_open())
158 {
159 int fd = this->mutable_serial_port().native_handle();
160 int status = 0;
161 // TIOCMGET - get the status of bits
162 ioctl(fd, TIOCMGET, &status);
163 status_msg->set_rts(status & TIOCM_RTS);
164 status_msg->set_dtr(status & TIOCM_DTR);
165 }
166
167 goby::glog.is_debug2() && goby::glog << group(this->glog_group()) << "< [Status] "
168 << status_msg->ShortDebugString() << std::endl;
169
170 this->publish_in(status_msg);
171 }
172
173 void open_socket() override;
174};
175} // namespace detail
176} // namespace io
177} // namespace middleware
178} // namespace goby
179
180template <const goby::middleware::Group& line_in_group,
181 const goby::middleware::Group& line_out_group,
183 goby::middleware::io::PubSubLayer subscribe_layer, template <class> class ThreadType,
184 bool use_indexed_groups>
185void goby::middleware::io::detail::SerialThread<line_in_group, line_out_group, publish_layer,
186 subscribe_layer, ThreadType,
187 use_indexed_groups>::open_socket()
188{
189 this->mutable_serial_port().open(this->cfg().port());
190 using boost::asio::serial_port_base;
191 this->mutable_serial_port().set_option(serial_port_base::baud_rate(this->cfg().baud()));
192
193 switch (this->cfg().flow_control())
194 {
196 this->mutable_serial_port().set_option(
197 serial_port_base::flow_control(serial_port_base::flow_control::none));
198 break;
200 this->mutable_serial_port().set_option(
201 serial_port_base::flow_control(serial_port_base::flow_control::software));
202 break;
204 this->mutable_serial_port().set_option(
205 serial_port_base::flow_control(serial_port_base::flow_control::hardware));
206 break;
207 }
208
209 // 8N1
210 this->mutable_serial_port().set_option(serial_port_base::character_size(8));
211 this->mutable_serial_port().set_option(
212 serial_port_base::parity(serial_port_base::parity::none));
213 this->mutable_serial_port().set_option(
214 serial_port_base::stop_bits(serial_port_base::stop_bits::one));
215
216 publish_status();
217}
218
219#endif
Class for grouping publications in the Goby middleware. Analogous to "topics" in ROS,...
Definition group.h:60
bool socket_is_open()
Does the socket exist and is it open?
SocketType & mutable_socket()
Access the (mutable) socket (or serial_port) object.
friend void basic_async_write(IOThreadImplementation *this_thread, std::shared_ptr< const goby::middleware::protobuf::IOData > io_msg)
SerialThread(const goby::middleware::protobuf::SerialConfig &config, int index=-1)
Constructs the thread.
boost::asio::serial_port & mutable_serial_port()
Access the (mutable) serial_port object.
static constexpr Command DTR_LOW
Definition io.pb.h:1033
static constexpr Command DTR_HIGH
Definition io.pb.h:1031
static constexpr Command RTS_HIGH
Definition io.pb.h:1027
static constexpr Command RTS_LOW
Definition io.pb.h:1029
static constexpr Command SEND_BREAK
Definition io.pb.h:1025
static constexpr FlowControl HARDWARE
static constexpr FlowControl SOFTWARE
goby::util::logger::GroupSetter group(std::string n)
detail namespace with internal helper functions
Definition json.hpp:247
The global namespace for the Goby project.
util::FlexOstream glog
Access the Goby logger through this object.
STL namespace.