handler.cpp
Go to the documentation of this file.
2 
3 namespace industrial_modbus_tcp
4 {
5 
6 Handler::Handler(const std::shared_ptr<ros::NodeHandle> nh,
7  const std::string name,
8  const std::shared_ptr<ros::Publisher> error_publisher,
9  const std::string server_ip,
10  const modbus_error_recovery_mode recovery,
11  const unsigned server_port):
12  nh_(nh),
13  error_publisher_(error_publisher),
14  run_(false),
15  name_(name),
16  ctx_(modbus_new_tcp(server_ip.c_str(), server_port))
17 {
18  if (ctx_ == nullptr)
19  throw std::runtime_error("Unable to allocate libmodbus context:\n" + std::string(modbus_strerror(errno)));
20 
21  if (modbus_connect(ctx_) == -1)
22  {
23  // mobus_free is called in the destructor
24  throw std::runtime_error("Modbus connection failed:\n" + std::string(modbus_strerror(errno)));
25  }
26 
27  // Automatically reconnect in case of closed connection
28  // No warning will be printed in case of auto-reconnect
29  // The thread may hang while reconnecting!
30  if (modbus_set_error_recovery(ctx_, recovery) != 0)
31  {
32  // modbus_close and mobus_free are called in the destructor
33  throw std::runtime_error("Unable to set error recovery mode:\n" + std::string(modbus_strerror(errno)));
34  }
35 }
36 
38 {
39  stop();
40  modbus_close(ctx_);
41  modbus_free(ctx_);
42 }
43 
45 {
46  run_ = false;
47  if (!threads_.empty())
48  {
49  for (std::unique_ptr<std::thread> &thread : threads_)
50  thread->join(); // Stop thread after it's last execution
51  for (std::unique_ptr<std::thread> &thread : threads_)
52  thread.reset();
53  }
54 }
55 
57 {
58  if (run_)
59  stop();
60 
61  data_.clear();
62 }
63 
64 void Handler::setData(const std::vector<std::shared_ptr<DataType>> &data)
65 {
66  if (run_)
67  stop();
68  data_ = data;
69 
70  run_ = true;
71  threads_.resize(data_.size());
72  for (std::size_t i(0); i < threads_.size(); ++i)
73  threads_[i].reset(new std::thread([this, i]
74  { readData(i);}));
75 }
76 
77 const std::vector<std::shared_ptr<DataType>> Handler::getData()
78 {
79  return data_;
80 }
81 
82 void Handler::readData(const std::size_t index)
83 {
84  using std::chrono::system_clock;
85  system_clock::time_point next_start_time(system_clock::now());
86 
87  while (nh_->ok() && run_)
88  {
89  next_start_time += data_.at(index)->poll_rate_;
90  std::this_thread::sleep_until(next_start_time);
91 
92  uint16_t reg_values[data_.at(index)->number_of_registers_];
93 
94  int rc;
95  // Lock mutex because a modbus context is NOT thread safe as advertised
96  {
97  std::lock_guard<std::mutex> lock(modbus_mutex_);
98  rc = modbus_read_registers(
99  ctx_,
100  data_.at(index)->start_register_address_,
101  data_.at(index)->number_of_registers_,
102  reg_values);
103  }
104  if (rc == -1 || (std::size_t)rc != data_.at(index)->number_of_registers_)
105  {
106  std_msgs::String error;
107  error.data = data_.at(index)->topic_name_ + ": " + modbus_strerror(errno);
108  error_publisher_->publish(error);
109  ROS_ERROR_STREAM(name_ << ": " << error.data);
110  continue;
111  }
112 
113  std::vector<uint16_t> regs;
114  for (std::size_t i(0); i < data_.at(index)->number_of_registers_; ++i)
115  regs.emplace_back(reg_values[i]);
116 
117  data_.at(index)->convertAndPublishData(regs);
118  }
119 }
120 
121 }
std::shared_ptr< ros::NodeHandle > nh_
Definition: handler.hpp:58
Handler(const std::shared_ptr< ros::NodeHandle > nh, const std::string name, const std::shared_ptr< ros::Publisher > error_pub, const std::string server_ip, const modbus_error_recovery_mode recovery=MODBUS_ERROR_RECOVERY_NONE, const unsigned server_port=MODBUS_TCP_DEFAULT_PORT)
Definition: handler.cpp:6
std::shared_ptr< ros::Publisher > error_publisher_
Definition: handler.hpp:63
std::vector< std::unique_ptr< std::thread > > threads_
Definition: handler.hpp:102
void setData(const std::vector< std::shared_ptr< DataType >> &data)
Definition: handler.cpp:64
const std::vector< std::shared_ptr< DataType > > getData()
Definition: handler.cpp:77
std::atomic< bool > run_
Definition: handler.hpp:74
std::shared_ptr< ros::NodeHandle > nh
Definition: node.cpp:7
void readData(const std::size_t index)
Definition: handler.cpp:82
std::vector< std::shared_ptr< DataType > > data_
Definition: handler.hpp:91
#define ROS_ERROR_STREAM(args)


industrial_modbus_tcp
Author(s): Victor Lamoine - Institut Maupertuis
autogenerated on Mon Feb 28 2022 22:33:12