/* Copyright (C) 2020 - 2024, Thornwave Labs Inc
* Written by Razvan Turiac <razvan.turiac@thornwave.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
* documentation files (the “Software”), to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
* Attribution shall be given to Thornwave Labs Inc. and shall be made visible to the final user.
*
* THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _POWERMON_H
#define _POWERMON_H
#include <stdint.h>
#include <string.h>
#include <string>
#include <vector>
#include <functional>
#include <powermon_config.h>
#include <powermon_schedule.h>
#include <powermon_log.h>
#define MAX_WIFI_SSID_SIZE 32
#define MAX_WIFI_PASSWORD_SIZE 64
#define CHANNEL_ID_SIZE 16
#define ENCRYPTION_KEY_SIZE 32
#define MAX_BLE_NAME_LENGTH 8
#define MAX_WIFI_NAME_LENGTH 32
#define MAX_TIMER_NAME_LENGTH 16
#define MAX_TIMER_COUNT 16
#define FG_SOC_DISABLED 0xFF
#define FG_SOC_UNKNOWN 0xFE
#define FG_RUNTIME_DISABLED 0xFFFF
#define FG_RUNTIME_UNKNOWN 0xFFFE
#define FG_RUNTIME_MAX 0xFFF0
/**
* \brief Powermon is a class representing one PowerMon device (BLE or WiFi) and offers a set of functions for accessing all features of PowerMon battery monitors.
*/
class Powermon
{
public:
/**
* \brief HardwareRevision definitions (2 digit BCD format)
*/
enum HardwareRevision: uint8_t
{
FAMILY_MASK = 0xF0, ///<Mask for the family part of the revision number
POWERMON = 0x20, ///<Original PowerMon (BLE)
POWERMON_5S = 0x30, ///<PowerMon-5S (BLE)
POWERMON_W = 0x40 ///<PowerMon-W (WiFi)
};
/**
* \brief State represents the PowerMon connection state
*/
enum State: uint8_t
{
Disconnected = 0, ///<Device is not connected
Connecting, ///<Device is in the process of connecting
Connected ///<Device is connected
};
/**
* \brief DisconnectReason is an enumeration of all reasons a connection can be terminated
*/
enum DisconnectReason: uint8_t
{
CLOSED = 0,
NO_ROUTE,
FAILED,
UNEXPECTED_ERROR,
UNEXPECTED_RESPONSE,
WRITE_ERROR,
READ_ERROR,
};
/**
* \brief ResponseCodes is an enumeration of all possible response codes for requests to a PowerMon device
*/
enum ResponseCode: uint16_t
{
RSP_SUCCESS = 0x0000,
RSP_SUCCESS_MORE = 0x0100,
RSP_INVALID_REQ = 0x0001,
RSP_INVALID_PARAM = 0x0002,
RSP_ERROR = 0x0003,
RSP_LOCKED_USER = 0x0004,
RSP_LOCKED_MASTER = 0x0005,
RSP_CANNOT_UNLOCK = 0x0006,
RSP_NOT_FOUND = 0x0007,
RSP_TIMEOUT = 0x0008,
RSP_INVALID = 0x0009,
RSP_CANCELLED = 0x000A,
};
/**
* \brief PowerStatus is an enumeration of all possible power states
*/
enum PowerStatus: uint8_t
{
PS_OFF = 0, ///<Power status is Off
PS_ON = 1, ///<Power status is On
PS_LVD = 2, ///<Power status is Low Voltage Disconnect
PS_OCD = 3, ///<Power status is Over-Current Disconnect
PS_HVD = 4, ///<Power status is High Voltage Disconnect
PS_FGD = 5, ///<Power status is Fuel Gauge Disconnect
PS_NCH = 6, ///<Power status is Not CHarging (for LiFePO4 charge manager only)
PS_LTD = 7, ///<Power status is Low Temperature Disconnect
PS_HTD = 8, ///<Power status is High Temperature Disconnect
};
/**
* \brief AuthKey is a structure representing an authentication key used to unlock a locked PowerMon device
*/
struct AuthKey
{
uint8_t data[32];
};
/**
* \brief WifiAccessKey is a structure representing the access keys used to connect to a WiFi PowerMon remotely (via the cloud)
*/
struct WifiAccessKey
{
uint8_t channel_id[CHANNEL_ID_SIZE];
uint8_t encryption_key[ENCRYPTION_KEY_SIZE];
};
/**
* \brief WifiNetwork represents all information required by PowerMon to connect to an access point
*/
struct WifiNetwork
{
enum SecurityMode: uint8_t
{
OPEN = 0x0, ///< No security
WEP = 0x1, ///< Use WEP
WPA2_WPA1_PSK = 0x2, ///< Use WPA1 or WPA2
WPA2_PSK = 0x4, ///< Use only WPA2
WPA3_SAE = 0x6 ///< Use WPA3 (STA mode only)
};
uint8_t ssid_length;
uint8_t ssid[MAX_WIFI_SSID_SIZE];
uint8_t pass_length;
uint8_t pass[MAX_WIFI_PASSWORD_SIZE];
SecurityMode security;
};
/**
* \brief WifiScanResult represents a WiFi network detected by PowerMon during WiFi scanning
*/
struct WifiScanResult
{
uint8_t ssid_length;
uint8_t ssid[MAX_WIFI_SSID_SIZE];
uint8_t channel;
struct
{
uint8_t wep : 1; ///< Network supports WEP
uint8_t wpa : 1; ///< Network supports WPA. If both WPA bits are set the network supports mixed mode.
uint8_t wpa2 : 1; ///< Network supports WPA2. If both WPA bits are set the network supports mixed mode.
uint8_t wpa3 : 1; ///< Network supports WPA3. If multiple WPA bits are set the network supports mixed mode.
uint8_t pmf : 1; ///< Networks requires use of Protected Management Frames
uint8_t unused : 1; ///< Reserved, set to zero
uint8_t psk : 1; ///< Network supports Personal authentication
uint8_t eap : 1; ///< Network supports Enterprise authentication
}security;
int8_t rssi;
bool operator==(const WifiScanResult &rhs) const;
};
/**
* \brief DeviceInfo is the information structure returned by PowerMon as response to the GetInfo request
*/
struct DeviceInfo
{
std::string name;
uint16_t firmware_version_bcd;
uint8_t hardware_revision_bcd;
uint64_t address;
uint64_t serial;
uint8_t ssid_length;
uint8_t ssid[MAX_WIFI_SSID_SIZE];
uint8_t flags;
bool isUserPasswordSet(void) const;
bool isMasterPasswordSet(void) const;
bool isUserLocked(void) const;
bool isMasterLocked(void) const;
bool isWifiConnecting(void) const;
bool isWifiConnected(void) const;
bool isWifiFailed(void) const;
};
/**
* \brief DeviceIdentifier is a structure containing all information used to identify a PowerMon device (either BLE or WiFi)
*/
struct DeviceIdentifier
{
std::string name; ///<Device name
uint64_t serial; ///<Device serial number
uint8_t hardware_revision_bcd; ///<Identifies if it's a WiFi or BLE device
uint64_t address; ///<contains the BLE MAC address for a BLE device of the IP address of a local WiFi device.
WifiAccessKey access_key; ///<Contains the access keys for a remote WiFi device. In this case address is zero.
DeviceIdentifier();
bool operator==(const DeviceIdentifier &rhs);
/**
* \brief Initializes the current object from a device link.
* \param url C string containing a valid PowerMon-W access link
* \return True if the link was correctly decoded, false otherwise.
*/
bool fromURL(const char* url);
/**
* \brief Saves the current PowerMon-W access structure to a link. Only remote access WiFi device identifiers can be saved.
* \return String containing the link or a zero length string if the structure is not a valid remote PowerMon-W identifier
*/
std::string toURL(void);
};
/**
* \brief MonitorData is a structure containing the real-time PowerMon data
*/
struct MonitorData
{
uint16_t firmware_version_bcd; ///<current firmware version in BCD format xx.yy
uint8_t hardware_revision_bcd; ///<current hardware revision in BCD format x.y
uint32_t time; ///<UNIX time in localtime (not UTC)
uint32_t flags; ///<various flags - do not use directly
float voltage1; ///<Voltage 1 in Volts
float voltage2; ///<Voltage 2 in Volts
float current; ///<Current in Amperes
float power; ///<Power in Watts. Depending on the configuration, either V1 or V2 are used to compute this value.
float temperature; ///<Temperature in Celsius
int64_t coulomb_meter; ///<Coulomb meter in mAh
int64_t energy_meter; ///<Energy meter in mWh
PowerStatus power_status; ///<Device power status
uint8_t fg_soc; ///<Fuelgauge SoC (State of Charge) in percentage. 0xFF means the FG is not enabled. 0xFE means the SoC is unknown
uint16_t fg_runtime; ///<Fuelgauge runtime in minutes. 0xFFFF means the FG is not enabled. The maximum valid value is 0xFFF0.
int16_t rssi = INT16_MIN; ///<RSSI as seen by the device in dBm
/**
* \brief Returns true if the temperature is read from an external sensor.
*/
bool isTemperatureExternal(void) const;
};
/**
* \brief MonitorStatistics is a structure containing power meter statistics
*/
struct MonitorStatistics
{
uint32_t seconds_since_on; ///<number of seconds since PowerMon was powered up
float voltage1_min;
float voltage1_max;
float voltage2_min;
float voltage2_max;
float peak_charge_current;
float peak_discharge_current;
float temperature_min; ///<in Celsius
float temperature_max; ///<in Celsius
};
/**
* \brief FuelgaugeStatistics is a structure containing battery statistics
*/
struct FuelgaugeStatistics
{
uint32_t time_since_last_full_charge; //in seconds
float full_charge_capacity; //current total capacity in Ah
uint64_t total_discharge; //in mAh
uint64_t total_discharge_energy; //in mWh
uint64_t total_charge; //in mAh
uint64_t total_charge_energy; //in mWh
float min_voltage;
float max_voltage;
float max_discharge_current;
float max_charge_current;
float deepest_discharge; //in Ah
float last_discharge; //in Ah
float soc; //in percentage
uint32_t RESERVED;
};
/**
* \brief LogFileDescriptor represents a PowerMon log file
*/
struct LogFileDescriptor
{
uint32_t id; ///<ID of the file (timestamp in UNIX time of the first sample in the file)
uint32_t size; ///<Size in bytes
};
/**
* \brief Creates an instance of the Powermon class
* \return Pointer to the newly created Powermon object. Must be freed using delete().
*/
static Powermon* createInstance(void);
virtual ~Powermon();
/**
* \brief Connects to a remote WiFi PowerMon
* \param key The access key used to connect
*/
virtual void connectWifi(const WifiAccessKey &key) = 0;
/**
* \brief Connects to a local WiFi PowerMon
* \param ipaddr The IPv4 address of the local WiFi PowerMon device
*/
virtual void connectWifi(uint32_t ipaddr) = 0;
/**
* \brief Connects to a local BLE PowerMon
* \param ble_address The Bluetooth address of the PowerMon device
*/
virtual void connectBle(uint64_t ble_address) = 0;
/**
* \brief Disconnects from a connected device
*/
virtual void disconnect(void) = 0;
/**
* \brief Returns true if the current connection is local: BLE or WiFi
*/
virtual bool isLocalConnection(void) const = 0;
/**
* \brief Sets the callback to be called by the driver when a connection to the PowerMon device is fully established
* \param cb Lambda of type `void(void)`
*/
virtual void setOnConnectCallback(const std::function<void(void)> &cb) = 0;
/**
* \brief Sets the callback to be called by the driver when a connection to the PowerMon device is disconnected
* \param cb Lambda of type `void(Powermmon::DisconnectReason)`
*/
virtual void setOnDisconnectCallback(const std::function<void(DisconnectReason)> &cb) = 0;
/**
* \brief Sets the callback to be called by the driver when new monitor data is received. This applies to the BLE devices only.
* For the WiFi devices, use the request to retrieve the monitor data.
* \param cb Lambda of type `void(Powermon::MonitorData&)`
*/
virtual void setOnMonitorDataCallback(const std::function<void(const MonitorData&)> &cb) = 0;
/**
* \brief Sets the callback to be called by the driver when a new WiFi scan result is received from the PowerMon. This applies to the WiFi devices only.
* WiFi scanning can be initiated using requestStartWifiScan().
* \param cb Lambda of type `void(Powermon::WifiScanResult*)`
* \param result Pointer to a WiFiScanResult structure describing a WiFi network. The pointer is only valid inside the scope of the callback closure.
* Do not store this pointer. Result can be nullptr to signal the WiFi scan ending.
*/
virtual void setOnWifiScanReportCallback(const std::function<void(const WifiScanResult*)> &cb) = 0;
/**
* \brief Returns the last DeviceInfo retrieved from the PowerMon
* \return Reference to internal DeviceInfo structure. This is not valid before the first requestGetInfo() that returns success.
*/
virtual const DeviceInfo& getLastDeviceInfo(void) const = 0;
/**
* \brief Requests the device information
* \param cb Lambda of type void(ResponseCode, const DeviceInfo&) that will be called to signal the result of the request
*/
virtual void requestGetInfo(const std::function<void(ResponseCode, const DeviceInfo&)> &cb) = 0;
/**
* \brief Requests the device monitor data. It only applies to the WiFi devices.
* \param cb Lambda of type void(ResponseCode, const MonitorData&) that will be called to signal the result of the request
*/
virtual void requestGetMonitorData(const std::function<void(ResponseCode, const MonitorData&)> &cb) = 0;
/**
* \brief Requests the device power monitor statistics data
* \param cb Lambda of type void(ResponseCode, const MonitorStatistics&) that will be called to signal the result of the request
*/
virtual void requestGetStatistics(const std::function<void(ResponseCode, const MonitorStatistics&)> &cb) = 0;
/**
* \brief Requests the device battery statistics data
* \param cb Lambda of type void(ResponseCode, const FuelgaugeStatistics&) that will be called to signal the result of the request
*/
virtual void requestGetFgStatistics(const std::function<void(ResponseCode, const FuelgaugeStatistics&)> &cb) = 0;
/**
* \brief Requests unlocking a password protected device
* \param key 32 bytes AuthKey type used to unlock the device. This is typically the SHA256 hash of a password.
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestUnlock(const AuthKey &key, std::function<void(ResponseCode)> cb) = 0;
/**
* \brief Requests setting a user password lock
* \param key 32 bytes AuthKey type used to unlock the device. This is typically the SHA256 hash of a password.
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestSetUserPasswordLock(const AuthKey &key, std::function<void(ResponseCode)> cb) = 0;
/**
* \brief Requests setting a master password lock on
* \param key 32 bytes AuthKey type used to unlock the device. This is typically the SHA256 hash of a password.
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestSetMasterPasswordLock(const AuthKey &key, std::function<void(ResponseCode)> cb) = 0;
/**
* \brief Requests clearing of the user password lock
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestClearUserPasswordLock(std::function<void(ResponseCode)> cb) = 0;
/**
* \brief Requests clearing of the master password lock
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestClearMasterPasswordLock(std::function<void(ResponseCode)> cb) = 0;
/**
* \brief Requests the authentication key from the device. This key can be used to unlock a locked device. It acts the same way as the user password lock.
* \param cb Lambda of type void(ResponseCode, const AuthKey&) that will be called to signal the result of the request
*/
virtual void requestGetAuthKey(std::function<void(ResponseCode, const AuthKey&)> cb) = 0;
/**
* \brief Requests the reset of the device authentication key
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestResetAuthKey(std::function<void(ResponseCode)> cb) = 0;
/**
* \brief Requests the reset of the energy meter
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestResetEnergyMeter(const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests the reset of the coulomb meter
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestResetCoulombMeter(const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests the reset of the power meter statistics
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestResetStatistics(const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests changing the power state
* \param state New power state (ON / OFF)
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestSetPowerState(bool state, const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Retrieves the device configuration structure
* \param cb Lambda of type void(ResponseCode, const PowermonConfig&) that will be called to signal the result of the request
*/
virtual void requestGetConfig(const std::function<void(ResponseCode, const PowermonConfig&)> &cb) = 0;
/**
* \brief Sends new configuration to the device
* \param config New configuration structure
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestSetConfig(const PowermonConfig &config, const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Resets the PowerMon configuration to factory settings
* This will also clear the data log, reset the name, authentication keys and access keys (for WiFi devices).
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request.
*/
virtual void requestResetConfig(const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests renaming the PowerMon device
* \param name New name. For Bluetooth PowerMons the name is limited to 8 characters. For WiFi PowerMons the name can be up to 32 characters in length.
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestRename(const char* name, const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests setting the internal clock of the PowerMon device
* \param time New clock in UNIX format (number of seconds since Jan 1st, 1970) in localtime (not UTC)
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestSetTime(uint32_t time, const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests forcing the SoC to 100% (SoC synchronize)
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestFgSynchronize(const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests starting the WiFi scan (only applies to the WiFi PowerMons). WiFi scanning will stop automatically after a max of 5 seconds.
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestStartWifiScan(const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Sends new WiFi network credentials to the PowerMon device.
* The new credentials will be saved by the device whether PowerMon can or cannot connect to that specified network.
* \param network WiFi network credentials
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestWifiConfigure(const WifiNetwork &network, const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests the WiFi access keys (only applies to the WiFi PowerMons). The access keys are used to remotely access the device.
* \param cb Lambda of type void(ResponseCode, const WifiAccessKey&) that will be called to signal the result of the request
*/
virtual void requestGetAccessKeys(const std::function<void(ResponseCode, const WifiAccessKey&)> &cb) = 0;
/**
* \brief Requests resetting of the WiFi access keys (only applies to the WiFi PowerMons). This effectively severs the connection to all the paired clients.
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestResetAccessKeys(const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests zeroing of the current reading offset
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestZeroCurrentOffset(const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests calibration of the current reading
* \param value The actual current flowing through the shunt. An accurate multimeter is required to measure the current.
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestCalibrateCurrent(float value, const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests the list of all schedules stored in the device
* \param cb Lambda of type void(ResponseCode, const std::vector<PowermonSchedule>&) that will be called to signal the result of the request
*/
virtual void requestGetSchedules(const std::function<void(ResponseCode, const std::vector<PowermonSchedule>&)> &cb) = 0;
/**
* \brief Requests adding new schedules
* \param schedules A list of schedules to add
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestAddSchedules(const std::vector<PowermonSchedule> &schedules, const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests updating an existing schedule
* \param old_schedule_descriptor The descriptor of the schedule to update
* \param new_schedule The new schedule
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestUpdateSchedule(uint64_t old_schedule_descriptor, const PowermonSchedule &new_schedule, const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests deleting an existing schedule
* \param schedule_descriptor The descriptor of the schedule to delete
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestDeleteSchedule(uint64_t schedule_descriptor, const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests clearing of all schedule
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestClearSchedules(const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests committing the schedules to non-volatile memory
* \param cb Lambda of type void(ResponseCode) that will be called to signal the result of the request
*/
virtual void requestCommitSchedules(const std::function<void(ResponseCode)> &cb) = 0;
/**
* \brief Requests the list of log files
* \param cb Lambda of type void(ResponseCode, const std::vector<LogFileDescriptor>&) that will be called to signal the result of the request
*/
virtual void requestGetFileList(const std::function<void(ResponseCode, const std::vector<LogFileDescriptor>&)> &cb) = 0;
/**
* \brief Requests reading of a log file
* \param file_id ID of the file to read (obtained from the LogFileDescriptor)
* \param offset Offset to read from
* \param read_size Read size in bytes
* \param cb Lambda of type void(ResponseCode, const uint8_t*, size_t) that will be called to signal the result of the request
*/
virtual void requestReadFile(uint32_t file_id, uint32_t offset, uint32_t read_size, const std::function<void(ResponseCode, const uint8_t*, size_t)> &cb) = 0;
/**
* \brief Requests firmware update
* \param firmware_image The firmware update image
* \param size Size of the firmware update image
* \param progress_cb Lambda of type bool(uint32_t progress, uint32_t total) that will be called regularly with updates about the progress.
* Returning false fronm the lambda will abort the update operation.
* \param done_cb Lambda of type void(ResponseCode) that will be called to signal the result of the request upon completion of the firmware update
*/
virtual void requestUpdateFirmware(const uint8_t* firmware_image, uint32_t size, const std::function<bool(uint32_t, uint32_t)> &progress_cb,
const std::function<void(ResponseCode)> &done_cb) = 0;
/**
* \brief Returns the IP address as string
*/
static std::string getIpAddressString(uint32_t ip);
/**
* \brief Returns the Bluetooth MAC address as string
*/
static std::string getMacAddressString(uint64_t mac);
/**
* \brief Parses a MAC address string
*/
static uint64_t parseMacAddress(const char* address);
/**
* \brief Returns the hardware name based on the hardware revision in BCD format
*/
static std::string getHardwareString(uint8_t bcd);
/**
* \brief Returns the power status string representation
*/
static std::string getPowerStatusString(PowerStatus ps);
/**
* \brief Returns true if the PowerMon described by the BCD hardware revision has V2
*/
static bool hasVoltage2(uint8_t bcd);
/**
* \brief Returns true if the PowerMon described by the BCD hardware revision supports configurable shunts
*/
static bool hasConfigurableShunt(uint8_t bcd);
/**
* \brief Returns true if the PowerMon described by the BCD hardware revision has WiFi
*/
static bool hasWifi(uint8_t bcd);
/**
* \brief Returns true if the parameter is a valid BCD number
*/
static inline bool checkBCD(uint16_t bcd)
{
for(uint32_t i = 0; i < 4; i++)
{
if ((bcd & 0xF) > 0x9)
return false;
bcd >>= 4;
}
return true;
}
/**
* \brief Generates the SHA256 hash of a password
* \param password C string containing the password
* \return Authentication key that can be used for the lock / unlock functions
*/
static AuthKey getAuthKeyFromPassword(const char* password);
/**
* \brief Returns the update firmware image URL based on the hardware revision and firmware version.
*/
static std::string getUpdateFirmwareImageUrl(uint8_t hardware_revision_bcd, uint16_t firmware_revision_bcd);
/**
* \brief Checks the validity of the firmware update image.
*/
static uint16_t checkFirmwareImage(const uint8_t* image, size_t size, uint8_t hardware_revision_bcd);
};
#include <powermon_scanner.h>
#endif