espwifiutils improvements for mac_t and ip_address_t

This commit is contained in:
2021-10-27 20:47:47 +02:00
parent 34792268a8
commit 0f54574b33
2 changed files with 49 additions and 17 deletions

View File

@@ -1,5 +1,8 @@
#include "espwifiutils.h" #include "espwifiutils.h"
// system includes
#include <cstdio>
// esp-idf includes // esp-idf includes
#include <esp_log.h> #include <esp_log.h>
@@ -116,13 +119,28 @@ std::string toString(esp_netif_dhcp_status_t status)
} }
} }
std::string toString(const mac_t &mac) template<> tl::expected<mac_t, std::string> fromString<mac_t>(std::string_view str)
{ {
return fmt::format("{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}", mac_t result;
mac.at(0), mac.at(1), mac.at(2), mac.at(3), mac.at(4), mac.at(5)); if (std::sscanf(str.data(), "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
&result[0], &result[1], &result[2], &result[3], &result[4], &result[5]) == 6)
return result;
return tl::make_unexpected(fmt::format("invalid format ({})", str));
} }
/*static*/ tl::expected<ip_address_t, std::string> ip_address_t::parseFromString(std::string_view address) std::string toString(const mac_t &val)
{
return fmt::format("{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
val.at(0), val.at(1), val.at(2), val.at(3), val.at(4), val.at(5));
}
std::string toString(const std::optional<mac_t> &val)
{
return val ? toString(*val) : "nullopt";
}
template<> tl::expected<ip_address_t, std::string> fromString<ip_address_t>(std::string_view str)
{ {
// TODO: add support for "a", "a.b", "a.b.c" formats // TODO: add support for "a", "a.b", "a.b.c" formats
// TODO: replace with scanf for better performance // TODO: replace with scanf for better performance
@@ -132,7 +150,7 @@ std::string toString(const mac_t &mac)
uint16_t acc = 0; // Accumulator uint16_t acc = 0; // Accumulator
uint8_t dots = 0; uint8_t dots = 0;
for (char c : address) for (char c : str)
{ {
if (c >= '0' && c <= '9') if (c >= '0' && c <= '9')
{ {
@@ -145,7 +163,7 @@ std::string toString(const mac_t &mac)
if (dots == 3) if (dots == 3)
return tl::make_unexpected("Too many dots (there must be 3 dots)"); return tl::make_unexpected("Too many dots (there must be 3 dots)");
result._bytes[dots++] = acc; result[dots++] = acc;
acc = 0; acc = 0;
} }
else else
@@ -155,14 +173,19 @@ std::string toString(const mac_t &mac)
if (dots != 3) if (dots != 3)
return tl::make_unexpected("Too few dots (there must be 3 dots)"); return tl::make_unexpected("Too few dots (there must be 3 dots)");
result._bytes[3] = acc; result[3] = acc;
return result; return result;
} }
std::string toString(const ip_address_t &address) std::string toString(ip_address_t val)
{ {
return fmt::format("{}.{}.{}.{}", address[0], address[1], address[2], address[3]); return fmt::format("{}.{}.{}.{}", val[0], val[1], val[2], val[3]);
}
std::string toString(const std::optional<ip_address_t> &val)
{
return val ? toString(*val) : "nullopt";
} }
ip_address_t wifi_calculate_network_id(ip_address_t ip, ip_address_t subnet) ip_address_t wifi_calculate_network_id(ip_address_t ip, ip_address_t subnet)

View File

@@ -5,6 +5,7 @@
#include <string> #include <string>
#include <string_view> #include <string_view>
#include <array> #include <array>
#include <optional>
// esp-idf includes // esp-idf includes
#include <esp_wifi_types.h> #include <esp_wifi_types.h>
@@ -24,12 +25,17 @@ std::string toString(wifi_cipher_type_t cipherType);
std::string toString(esp_interface_t interface); std::string toString(esp_interface_t interface);
std::string toString(esp_netif_dhcp_status_t status); std::string toString(esp_netif_dhcp_status_t status);
template<typename T> tl::expected<T, std::string> fromString(std::string_view str) = delete;
// A class to make it easier to handle and pass around mac addresses / bssids // A class to make it easier to handle and pass around mac addresses / bssids
class mac_t : public std::array<uint8_t, 6> class mac_t : public std::array<uint8_t, 6>
{ {
public: public:
static constexpr const size_t static_size = 6;
using std::array<uint8_t, 6>::array; using std::array<uint8_t, 6>::array;
using std::array<uint8_t, 6>::operator=;
constexpr explicit mac_t(const uint8_t (&arr)[6]) noexcept constexpr explicit mac_t(const uint8_t (&arr)[6]) noexcept
{ {
@@ -42,7 +48,9 @@ public:
} }
}; };
std::string toString(const mac_t &mac); template<> tl::expected<mac_t, std::string> fromString<mac_t>(std::string_view str);
std::string toString(const mac_t &val);
std::string toString(const std::optional<mac_t> &val);
// A class to make it easier to handle and pass around IP addresses // A class to make it easier to handle and pass around IP addresses
// Implementation taken from arduino-esp32 // Implementation taken from arduino-esp32
@@ -68,23 +76,22 @@ public:
constexpr explicit ip_address_t(esp_ip4_addr_t address) noexcept : _value{address.addr} {} constexpr explicit ip_address_t(esp_ip4_addr_t address) noexcept : _value{address.addr} {}
constexpr ip_address_t(std::array<uint8_t, 4> bytes) noexcept : _bytes{bytes} {} constexpr ip_address_t(std::array<uint8_t, 4> bytes) noexcept : _bytes{bytes} {}
static tl::expected<ip_address_t, std::string> parseFromString(std::string_view address);
// Access the raw byte array containing the address. Because this returns a pointer // Access the raw byte array containing the address. Because this returns a pointer
// to the internal structure rather than a copy of the address this function should only // to the internal structure rather than a copy of the address this function should only
// be used when you know that the usage of the returned uint8_t* will be transient and not // be used when you know that the usage of the returned uint8_t* will be transient and not
// stored. // stored.
constexpr std::array<uint8_t, 4> &bytes() noexcept { return _bytes; } constexpr std::array<uint8_t, 4> &bytes() noexcept { return _bytes; }
constexpr std::array<uint8_t, 4> bytes() const noexcept { return _bytes; } constexpr const std::array<uint8_t, 4> &bytes() const noexcept { return _bytes; }
constexpr value_t value() const noexcept { return _value; } constexpr value_t &value() noexcept { return _value; }
constexpr const value_t &value() const noexcept { return _value; }
friend constexpr bool operator==(const ip_address_t &left, const ip_address_t &right) noexcept { return left._value == right._value; } friend constexpr bool operator==(const ip_address_t &left, const ip_address_t &right) noexcept { return left._value == right._value; }
friend constexpr bool operator!=(const ip_address_t &left, const ip_address_t &right) noexcept { return !(left == right); } friend constexpr bool operator!=(const ip_address_t &left, const ip_address_t &right) noexcept { return !(left == right); }
// Overloaded index operator to allow getting and setting individual octets of the address // Overloaded index operator to allow getting and setting individual octets of the address
constexpr uint8_t& operator[](int index) noexcept { return _bytes[index]; } constexpr uint8_t &operator[](int index) noexcept { return _bytes[index]; }
constexpr uint8_t operator[](int index) const noexcept { return _bytes[index]; } constexpr const uint8_t &operator[](int index) const noexcept { return _bytes[index]; }
// Overloaded copy operators to allow initialisation of ip_address_t objects from other types // Overloaded copy operators to allow initialisation of ip_address_t objects from other types
constexpr ip_address_t& operator=(const ip_address_t &other) noexcept { _value = other._value; return *this; } constexpr ip_address_t& operator=(const ip_address_t &other) noexcept { _value = other._value; return *this; }
@@ -92,7 +99,9 @@ public:
constexpr ip_address_t& operator=(value_t value) noexcept { _value = value; return *this; } constexpr ip_address_t& operator=(value_t value) noexcept { _value = value; return *this; }
}; };
std::string toString(const ip_address_t &val); template<> tl::expected<ip_address_t, std::string> fromString<ip_address_t>(std::string_view str);
std::string toString(ip_address_t val);
std::string toString(const std::optional<ip_address_t> &val);
ip_address_t wifi_calculate_network_id(ip_address_t ip, ip_address_t subnet); ip_address_t wifi_calculate_network_id(ip_address_t ip, ip_address_t subnet);
ip_address_t wifi_calculate_broadcast(ip_address_t ip, ip_address_t subnet); ip_address_t wifi_calculate_broadcast(ip_address_t ip, ip_address_t subnet);