mavtables  0.2.1
MAVLink router and firewall.
MAVAddress.cpp
Go to the documentation of this file.
1 // MAVLink router and firewall.
2 // Copyright (C) 2017-2018 Michael R. Shannon <mrshannon.aerospace@gmail.com>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 
18 #include <algorithm>
19 #include <cctype>
20 #include <sstream>
21 #include <stdexcept>
22 #include <string>
23 #include <vector>
24 
25 #include "MAVAddress.hpp"
26 #include "utility.hpp"
27 
28 
29 /** Construct a MAVLink address from an address in numeric representation.
30  *
31  * The numeric representation of a MAVLink address is two bytes, the MSB
32  * contains the system ID and the LSB contains the component ID.
33  *
34  * \param address Address (0 - 65535) with system ID encoded in MSB and
35  * component ID encoded in LSB.
36  * \throws std::out_of_range if the address is not between 0 and 65535.
37  */
38 MAVAddress::MAVAddress(unsigned int address)
39 {
40  if (address > 65535)
41  {
42  throw std::out_of_range(
43  "Address (" + std::to_string(address) +
44  ") is outside of the allowed range (0 - 65535).");
45  }
46 
47  address_ = address;
48 }
49 
50 
51 /** Construct a MAVLink address from system and component ID's.
52  *
53  * \param system System ID (0 - 255).
54  * \param component Component ID (0 - 255).
55  * \throws std::out_of_range if either the \p system ID or the \p component ID
56  * is out of range.
57  */
58 void MAVAddress::construct_(unsigned int system, unsigned int component)
59 {
60  if (system > 255)
61  {
62  throw std::out_of_range(
63  "System ID (" + std::to_string(system) +
64  ") is outside of the allowed range (0 - 255).");
65  }
66 
67  if (component > 255)
68  {
69  throw std::out_of_range(
70  "Component ID (" + std::to_string(component) +
71  ") is outside of the allowed range (0 - 255).");
72  }
73 
74  address_ = ((system << 8) & 0xFF00) | (component & 0x00FF);
75 }
76 
77 
78 /** Construct a MAVLink address from the system ID and component ID.
79  *
80  * \note component=0 and system=0 is the broadcast address.
81  *
82  * \param system System ID (0 - 255).
83  * \param component Component ID (0 - 255).
84  * \throws std::out_of_range if either the \p system ID or the \p component ID
85  * is out of range.
86  */
87 MAVAddress::MAVAddress(unsigned int system, unsigned int component)
88 {
89  construct_(system, component);
90 }
91 
92 
93 /** Construct MAVLink address from a string.
94  *
95  * Parse a string of the form "<System ID>.<Component ID>".
96  *
97  * Some examples are:
98  * - "0.0"
99  * - "16.8"
100  * - "128.4"
101  *
102  * \param address String representing the MAVLink address.
103  * \throws std::invalid_argument if the address string does not represent a
104  * valid MAVLink address.
105  * \throws std::out_of_range if either the \p system ID or the \p component ID
106  * is out of range.
107  */
108 MAVAddress::MAVAddress(std::string address)
109 {
110  // Check validity of address string.
111  if (address.size() < 3 || !(isdigit(address.front()))
112  || !isdigit(address.back()))
113  {
114  throw std::invalid_argument("Invalid MAVLink address string.");
115  }
116 
117  for (auto c : address)
118  {
119  if (!(c == '.' || isdigit(c)))
120  {
121  throw std::invalid_argument("Invalid MAVLink address string.");
122  }
123  }
124 
125  // Read address string.
126  std::replace(address.begin(), address.end(), '.', ' ');
127  std::vector<unsigned int> octets;
128  std::istringstream ss(address);
129  unsigned int i;
130 
131  while (ss >> i)
132  {
133  octets.push_back(i);
134  }
135 
136  // Check for correct number of octets.
137  if (octets.size() != 2 || !ss.eof())
138  {
139  throw std::invalid_argument("Invalid MAVLink address string.");
140  }
141 
142  construct_(octets[0], octets[1]);
143 }
144 
145 
146 /** Return the MAVLink address in numeric form.
147  *
148  * \returns The MAVLink address as a two byte number with the system ID encoded
149  * in the MSB and the component ID in the LSB.
150  */
151 unsigned int MAVAddress::address() const
152 {
153  return address_;
154 }
155 
156 
157 /** Return the System ID.
158  *
159  * \returns The system ID (0 - 255).
160  */
161 unsigned int MAVAddress::system() const
162 {
163  return (address_ >> 8) & 0x00FF;
164 }
165 
166 
167 /** Return the Component ID.
168  *
169  * \returns The component ID (0 - 255).
170  */
171 unsigned int MAVAddress::component() const
172 {
173  return address_ & 0x00FF;
174 }
175 
176 
177 /** Equality comparison.
178  *
179  * \relates MAVAddress
180  * \param lhs The left hand side MAVLink address.
181  * \param rhs The right hand side MAVLink address.
182  * \retval true if \p lhs and \p rhs have the same system and component ID's.
183  * \retval false if \p lhs and \p rhs do not have the same system and component
184  * ID's.
185  */
186 bool operator==(const MAVAddress &lhs, const MAVAddress &rhs)
187 {
188  return lhs.address() == rhs.address();
189 }
190 
191 
192 /** Inequality comparison.
193  *
194  * \relates MAVAddress
195  * \param lhs The left hand side MAVLink address.
196  * \param rhs The right hand side MAVLink address.
197  * \retval true if \p lhs and \p rhs do not have the same system and component
198  * ID's
199  * \retval false if \p lhs and \p rhs have the same system and component ID's.
200  */
201 bool operator!=(const MAVAddress &lhs, const MAVAddress &rhs)
202 {
203  return lhs.address() != rhs.address();
204 }
205 
206 
207 /** Less than comparison.
208  *
209  * \note The System ID is considered first followed by the Component ID.
210  *
211  * \relates MAVAddress
212  * \param lhs The left hand side MAVLink address.
213  * \param rhs The right hand side MAVLink address.
214  * \retval true if \p lhs is less than \p rhs.
215  * \retval false if \p lhs is not less than \p rhs.
216  */
217 bool operator<(const MAVAddress &lhs, const MAVAddress &rhs)
218 {
219  return lhs.address() < rhs.address();
220 }
221 
222 
223 /** Greater than comparison.
224  *
225  * \note The System ID is considered first followed by the Component ID.
226  *
227  * \relates MAVAddress
228  * \param lhs The left hand side MAVLink address.
229  * \param rhs The right hand side IP address.
230  * \retval true if \p lhs is greater than \p rhs.
231  * \retval false if \p lhs is not greater than \p rhs.
232  */
233 bool operator>(const MAVAddress &lhs, const MAVAddress &rhs)
234 {
235  return lhs.address() > rhs.address();
236 }
237 
238 
239 /** Less than or equal comparison.
240  *
241  * \note The System ID is considered first followed by the Component ID.
242  *
243  * \relates MAVAddress
244  * \param lhs The left hand side IP address.
245  * \param rhs The right hand side IP address.
246  * \retval true if \p lhs is less than or eqaul to \p rhs.
247  * \retval false if \p lhs is greater than \p rhs.
248  */
249 bool operator<=(const MAVAddress &lhs, const MAVAddress &rhs)
250 {
251  return lhs.address() <= rhs.address();
252 }
253 
254 
255 /** Greater than comparison.
256  *
257  * \note The System ID is considered first followed by the Component ID.
258  *
259  * \relates MAVAddress
260  * \param lhs The left hand side IP address.
261  * \param rhs The right hand side IP address.
262  * \retval true if \p lhs is greater than or equal to \p rhs.
263  * \retval false if \p lhs is less than \p rhs.
264  */
265 bool operator>=(const MAVAddress &lhs, const MAVAddress &rhs)
266 {
267  return lhs.address() >= rhs.address();
268 }
269 
270 
271 /** Print the MAVLink address to the given output stream.
272  *
273  * The format is "<System ID>.<Component ID>".
274  *
275  * Some examples are:
276  * - `0.0`
277  * - `16.8`
278  * - `128.4`
279  *
280  * \note The string constructor \ref MAVAddress(std::string) and the output
281  * stream operator are inverses and thus:
282  * ```
283  * std::string addr = "192.168"
284  * str(MAVAddress(addr)) == addr
285  * ```
286  *
287  * \relates MAVAddress
288  * \param os The output stream to print to.
289  * \param mavaddress The MAVLink address to print.
290  * \returns The output stream.
291  */
292 std::ostream &operator<<(std::ostream &os, const MAVAddress &mavaddress)
293 {
294  os << mavaddress.system() << "." << mavaddress.component();
295  return os;
296 }
unsigned int component() const
Definition: MAVAddress.cpp:171
bool operator!=(const MAVAddress &lhs, const MAVAddress &rhs)
Definition: MAVAddress.cpp:201
unsigned int system() const
Definition: MAVAddress.cpp:161
bool operator>(const MAVAddress &lhs, const MAVAddress &rhs)
Definition: MAVAddress.cpp:233
bool operator>=(const MAVAddress &lhs, const MAVAddress &rhs)
Definition: MAVAddress.cpp:265
bool operator<=(const MAVAddress &lhs, const MAVAddress &rhs)
Definition: MAVAddress.cpp:249
unsigned int address() const
Definition: MAVAddress.cpp:151
MAVAddress(const MAVAddress &other)=default
bool operator==(const MAVAddress &lhs, const MAVAddress &rhs)
Definition: MAVAddress.cpp:186
bool operator<(const MAVAddress &lhs, const MAVAddress &rhs)
Definition: MAVAddress.cpp:217
std::ostream & operator<<(std::ostream &os, const MAVAddress &mavaddress)
Definition: MAVAddress.cpp:292