system_utils.hpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
5 #pragma once
6 
7 #include <array>
8 #include <cassert>
9 #include <cctype>
10 #include <fstream>
11 #include <string>
12 #include <vector>
13 #include <cstdint>
14 #include <algorithm>
15 #include <utility>
17 #include <uavcan/data_type.hpp>
18 
19 namespace uavcan_linux
20 {
33 {
34 public:
35  static constexpr int MachineIDSize = 16;
36 
37  typedef std::array<std::uint8_t, MachineIDSize> MachineID;
38 
39  static std::vector<std::string> getDefaultSearchLocations()
40  {
41  return
42  {
43  "/etc/machine-id",
44  "/var/lib/dbus/machine-id",
45  "/sys/class/dmi/id/product_uuid"
46  };
47  }
48 
49 private:
50  const std::vector<std::string> search_locations_;
51 
52  static std::vector<std::string> mergeLists(const std::vector<std::string>& a, const std::vector<std::string>& b)
53  {
54  std::vector<std::string> ab;
55  ab.reserve(a.size() + b.size());
56  ab.insert(ab.end(), a.begin(), a.end());
57  ab.insert(ab.end(), b.begin(), b.end());
58  return ab;
59  }
60 
61  bool tryRead(const std::string& location, MachineID& out_id) const
62  {
63  /*
64  * Reading the file
65  */
66  std::string token;
67  try
68  {
69  std::ifstream infile(location);
70  infile >> token;
71  }
72  catch (std::exception&)
73  {
74  return false;
75  }
76 
77  /*
78  * Preprocessing the input string - convert to lowercase, remove all non-hex characters, limit to 32 chars
79  */
80  std::transform(token.begin(), token.end(), token.begin(), [](char x) { return std::tolower(x); });
81  token.erase(std::remove_if(token.begin(), token.end(),
82  [](char x){ return (x < 'a' || x > 'f') && !std::isdigit(x); }),
83  token.end());
84 
85  if (token.length() < (MachineIDSize * 2))
86  {
87  return false;
88  }
89  token.resize(MachineIDSize * 2); // Truncating
90 
91  /*
92  * Parsing the string as hex bytes
93  */
94  auto sym = std::begin(token);
95  for (auto& byte : out_id)
96  {
97  assert(sym != std::end(token));
98  byte = std::stoi(std::string{*sym++, *sym++}, nullptr, 16);
99  }
100 
101  return true;
102  }
103 
104 public:
108  MachineIDReader(const std::vector<std::string>& extra_search_locations = {})
109  : search_locations_(mergeLists(extra_search_locations, getDefaultSearchLocations()))
110  { }
111 
115  MachineID read() const { return readAndGetLocation().first; }
116 
122  std::pair<MachineID, std::string> readAndGetLocation() const
123  {
124  for (auto x : search_locations_)
125  {
126  auto out = MachineID();
127  if (tryRead(x, out))
128  {
129  return {out, x};
130  }
131  }
132  throw Exception("Failed to read machine ID");
133  }
134 };
135 
143 inline std::array<std::uint8_t, 16> makeApplicationID(const MachineIDReader::MachineID& machine_id,
144  const std::string& node_name,
145  const std::uint8_t instance_id = 0)
146 {
147  union HalfID
148  {
149  std::uint64_t num;
150  std::uint8_t bytes[8];
151 
152  HalfID(std::uint64_t arg_num) : num(arg_num) { }
153  };
154 
155  std::array<std::uint8_t, 16> out;
156 
157  // First 8 bytes of the application ID are CRC64 of the machine ID in native byte order
158  {
160  crc.add(machine_id.data(), static_cast<unsigned>(machine_id.size()));
161  HalfID half(crc.get());
162  std::copy_n(half.bytes, 8, out.begin());
163  }
164 
165  // Last 8 bytes of the application ID are CRC64 of the node name and optionally node ID
166  {
168  crc.add(reinterpret_cast<const std::uint8_t*>(node_name.c_str()), static_cast<unsigned>(node_name.length()));
169  crc.add(instance_id);
170  HalfID half(crc.get());
171  std::copy_n(half.bytes, 8, out.begin() + 8);
172  }
173 
174  return out;
175 }
176 
177 }
data_type.hpp
uavcan_linux::MachineIDReader::search_locations_
const std::vector< std::string > search_locations_
Definition: system_utils.hpp:50
uavcan::uint64_t
std::uint64_t uint64_t
Definition: std.hpp:27
uavcan_linux::MachineIDReader::mergeLists
static std::vector< std::string > mergeLists(const std::vector< std::string > &a, const std::vector< std::string > &b)
Definition: system_utils.hpp:52
uavcan_linux::MachineIDReader::MachineIDSize
static constexpr int MachineIDSize
Definition: system_utils.hpp:35
uavcan_linux::MachineIDReader::MachineID
std::array< std::uint8_t, MachineIDSize > MachineID
Definition: system_utils.hpp:37
uavcan_linux::MachineIDReader::tryRead
bool tryRead(const std::string &location, MachineID &out_id) const
Definition: system_utils.hpp:61
uavcan::DataTypeSignatureCRC::get
uint64_t get() const
Definition: data_type.hpp:103
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
uavcan_linux::Exception
Definition: exception.hpp:16
uavcan_linux::MachineIDReader::MachineIDReader
MachineIDReader(const std::vector< std::string > &extra_search_locations={})
Definition: system_utils.hpp:108
uavcan_linux::makeApplicationID
std::array< std::uint8_t, 16 > makeApplicationID(const MachineIDReader::MachineID &machine_id, const std::string &node_name, const std::uint8_t instance_id=0)
Definition: system_utils.hpp:143
uavcan::DataTypeSignatureCRC
Definition: data_type.hpp:90
uavcan_linux::MachineIDReader::getDefaultSearchLocations
static std::vector< std::string > getDefaultSearchLocations()
Definition: system_utils.hpp:39
uavcan_linux::MachineIDReader::readAndGetLocation
std::pair< MachineID, std::string > readAndGetLocation() const
Definition: system_utils.hpp:122
uavcan::DataTypeSignatureCRC::add
void add(uint8_t byte)
Definition: uc_data_type.cpp:46
uavcan_linux
Definition: platform_specific_components/linux/libuavcan/include/uavcan_linux/clock.hpp:18
exception.hpp
uavcan_linux::MachineIDReader
Definition: system_utils.hpp:32
uavcan_linux::MachineIDReader::read
MachineID read() const
Definition: system_utils.hpp:115
pyuavcan_v0.driver.timestamp_estimator.x
x
Definition: timestamp_estimator.py:221


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:03