37 #include <arpa/inet.h> 38 #include <boost/algorithm/string/predicate.hpp> 39 #include <boost/foreach.hpp> 62 ROS_WARN_STREAM(
"Serial read buffer is " << available <<
", now flushing in an attempt to catch up.");
67 uint8_t header_bytes[5];
70 uint8_t type, address;
71 if (memcmp(header_bytes,
"snp", 3) == 0)
74 type = header_bytes[3];
75 address = header_bytes[4];
82 if (!boost::algorithm::ends_with(snp,
"snp"))
throw SerialTimeout();
86 "Discarded " << 5 + snp.length() - 3 <<
" junk byte(s) preceeding packet.");
94 uint16_t checksum_calculated =
's' +
'n' +
'p' + type + address;
98 uint8_t data_length = 1;
102 ROS_DEBUG(
"Received packet %02x with batched (%d) data.", address, data_length);
106 ROS_DEBUG(
"Received packet %02x with non-batched data.", address);
111 BOOST_FOREACH(uint8_t ch, data)
113 checksum_calculated += ch;
118 ROS_INFO(
"Received packet %02x without data.", address);
122 uint16_t checksum_transmitted;
123 if (
serial_->
read(reinterpret_cast<uint8_t*>(&checksum_transmitted), 2) != 2)
127 checksum_transmitted = ntohs(checksum_transmitted);
128 if (checksum_transmitted != checksum_calculated)
135 if ((data.length() > 0) && registers)
137 registers->write_raw(address, data);
145 ROS_WARN(
"Timed out waiting for packet from device.");
149 ROS_WARN(
"Discarding packet due to bad checksum.");
157 BOOST_FOREACH(uint8_t ch, s)
161 checksum = htons(checksum);
162 ROS_DEBUG(
"Computed checksum on string of length %zd as %04x.", s.length(),
checksum);
163 std::string out(2, 0);
164 memcpy(&out[0], &checksum, 2);
171 if (data.length() > 0)
175 if (data.length() > 4)
181 std::stringstream ss(std::stringstream::out | std::stringstream::binary);
182 ss <<
"snp" << type << address << data;
183 std::string output = ss.str();
187 ROS_DEBUG(
"Generated message %02x of overall length %zd.", address, output.length());
193 uint8_t address = r.
index;
194 std::string data(reinterpret_cast<char*>(r.
raw()), r.
length * 4);
200 const uint8_t tries = 5;
201 for (uint8_t t = 0; t < tries; t++)
204 const uint8_t listens = 20;
205 for (uint8_t i = 0; i < listens; i++)
208 if (received == r.
index)
210 ROS_DEBUG(
"Message %02x ack received.", received);
213 else if (received == -1)
215 ROS_DEBUG(
"Serial read timed out waiting for ack. Attempting to retransmit.");
size_t readline(std::string &buffer, size_t size=65536, std::string eol="\n")
Provides the Registers class, which initializes with a suite of accessors suitable for reading and wr...
bool sendWaitAck(const Accessor_ &a)
static const uint8_t PACKET_BATCH_LENGTH_MASK
void send(const Accessor_ &a) const
int16_t receive(Registers *r)
#define ROS_WARN_STREAM_COND(cond, args)
#define ROS_WARN_STREAM(args)
size_t read(uint8_t *buffer, size_t size)
Comms class definition. Does not manage the serial connection itself, but takes care of reading and w...
static const uint8_t PACKET_IS_BATCH
static std::string checksum(const std::string &s)
static const uint8_t PACKET_BATCH_LENGTH_OFFSET
static const uint8_t PACKET_HAS_DATA
static std::string message(uint8_t address, std::string data)
size_t write(const uint8_t *data, size_t size)