Goby3  3.1.5a
2024.05.23
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...
39 namespace goby
40 {
41 namespace middleware
42 {
43 class Group;
44 }
45 } // namespace goby
46 
47 namespace goby
48 {
49 namespace middleware
50 {
51 namespace io
52 {
53 namespace detail
54 {
55 template <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>
59 class 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 
180 template <const goby::middleware::Group& line_in_group,
181  const goby::middleware::Group& line_out_group,
182  goby::middleware::io::PubSubLayer publish_layer,
183  goby::middleware::io::PubSubLayer subscribe_layer, template <class> class ThreadType,
184  bool use_indexed_groups>
185 void 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
goby::middleware::protobuf::SerialCommand::DTR_HIGH
static const Command DTR_HIGH
Definition: io.pb.h:804
io.pb.h
goby::middleware::io::detail::IOThread< line_in_group, line_out_group, publish_layer, subscribe_layer, goby::middleware::protobuf::SerialConfig, boost::asio::serial_port, ThreadType, false >::mutable_socket
boost::asio::serial_port & mutable_socket()
Access the (mutable) socket (or serial_port) object.
Definition: io_interface.h:212
goby
The global namespace for the Goby project.
Definition: acomms_constants.h:33
goby::acomms::abc::protobuf::config
extern ::google::protobuf::internal::ExtensionIdentifier< ::goby::acomms::protobuf::DriverConfig, ::google::protobuf::internal::MessageTypeTraits< ::goby::acomms::abc::protobuf::Config >, 11, false > config
Definition: abc_driver.pb.h:203
goby::middleware::io::detail::SerialThread::~SerialThread
virtual ~SerialThread() override
Definition: serial_interface.h:136
goby::middleware::protobuf::SerialConfig::HARDWARE
static const FlowControl HARDWARE
Definition: serial_config.pb.h:194
detail
detail namespace with internal helper functions
Definition: json.hpp:246
group
goby::util::logger::GroupSetter group(std::string n)
Definition: logger_manipulators.h:134
serial_config.pb.h
goby::util::logger_lock::none
@ none
Definition: flex_ostreambuf.h:61
goby::middleware::protobuf::SerialCommand::DTR_LOW
static const Command DTR_LOW
Definition: io.pb.h:806
goby::util::FlexOstream::is_debug2
bool is_debug2()
Definition: flex_ostream.h:85
goby::middleware::acomms::groups::status
constexpr Group status
Definition: groups.h:43
goby::middleware::io::detail::SerialThread::SerialThread
SerialThread(const goby::middleware::protobuf::SerialConfig &config, int index=-1)
Constructs the thread.
Definition: serial_interface.h:71
goby::middleware::protobuf::SerialCommand::RTS_LOW
static const Command RTS_LOW
Definition: io.pb.h:802
goby::middleware::io::PubSubLayer
PubSubLayer
Definition: io_transporters.h:38
goby::middleware::io::detail::SerialThread::mutable_serial_port
boost::asio::serial_port & mutable_serial_port()
Access the (mutable) serial_port object.
Definition: serial_interface.h:143
goby::middleware::io::detail::IOThread< line_in_group, line_out_group, publish_layer, subscribe_layer, goby::middleware::protobuf::SerialConfig, boost::asio::serial_port, ThreadType, false >::socket_is_open
bool socket_is_open()
Does the socket exist and is it open?
Definition: io_interface.h:223
flex_ostream.h
goby::middleware::io::detail::IOThread< line_in_group, line_out_group, publish_layer, subscribe_layer, goby::middleware::protobuf::SerialConfig, boost::asio::serial_port, ThreadType, false >::glog_group
const std::string & glog_group()
Definition: io_interface.h:234
goby::middleware::io::detail::IOThread< line_in_group, line_out_group, publish_layer, subscribe_layer, goby::middleware::protobuf::SerialConfig, boost::asio::serial_port, ThreadType, false >::basic_async_write
friend void basic_async_write(IOThreadImplementation *this_thread, std::shared_ptr< const goby::middleware::protobuf::IOData > io_msg)
Definition: io_interface.h:261
goby::middleware::Group
Class for grouping publications in the Goby middleware. Analogous to "topics" in ROS,...
Definition: group.h:59
logger_manipulators.h
goby::middleware::io::detail::SerialThread
Definition: serial_interface.h:59
goby::middleware::protobuf::SerialConfig::NONE
static const FlowControl NONE
Definition: serial_config.pb.h:190
io_interface.h
goby::middleware::io::detail::IOThread
Definition: io_interface.h:79
goby::middleware::io::ThreadState::SUBSCRIPTIONS_COMPLETE
@ SUBSCRIPTIONS_COMPLETE
goby::glog
util::FlexOstream glog
Access the Goby logger through this object.
goby::middleware::protobuf::SerialCommand::SEND_BREAK
static const Command SEND_BREAK
Definition: io.pb.h:798
goby::middleware::protobuf::SerialConfig
Definition: serial_config.pb.h:97
goby::middleware::protobuf::SerialConfig::SOFTWARE
static const FlowControl SOFTWARE
Definition: serial_config.pb.h:192
goby::middleware::protobuf::SerialCommand::RTS_HIGH
static const Command RTS_HIGH
Definition: io.pb.h:800