Add AmperageBudgetManager, InfluxDB, ModbusMirror; expose version
This commit is contained in:
parent
2d9815b199
commit
02faa08df1
1303
src/components/AmperageBudgetManager.cpp
Normal file
1303
src/components/AmperageBudgetManager.cpp
Normal file
File diff suppressed because it is too large
Load Diff
202
src/components/AmperageBudgetManager.h
Normal file
202
src/components/AmperageBudgetManager.h
Normal file
@ -0,0 +1,202 @@
|
||||
#ifndef AMPERAGE_BUDGET_MANAGER_H
|
||||
#define AMPERAGE_BUDGET_MANAGER_H
|
||||
|
||||
#include <Component.h>
|
||||
#include <ArduinoLog.h>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <enums.h>
|
||||
|
||||
#include "components/OmronE5.h"
|
||||
#include "modbus/NetworkComponent.h"
|
||||
#include "NetworkValue.h"
|
||||
#include <ArduinoJson.h>
|
||||
#include <LittleFS.h>
|
||||
|
||||
#include "config-modbus.h"
|
||||
#include "config.h"
|
||||
|
||||
// Forward declaration
|
||||
class OmronE5;
|
||||
|
||||
// Default values
|
||||
#define MIN_HEATING_DURATION_S 3 // 3 seconds
|
||||
#define MAX_HEATING_DURATION_S 5 // 5 seconds
|
||||
#define DEFAULT_MAX_SIMULTANEOUS_HEATING 2 // Default number of devices that can heat simultaneously
|
||||
#define DEFAULT_WINDOW_OFFSET 1 // Default window offset
|
||||
#define DEFAULT_START_INDEX 0 // Default start index for cycling
|
||||
#define DEFAULT_END_INDEX (MAX_MANAGED_DEVICES - 1) // Default end index for cycling
|
||||
#define DEFAULT_MAX_HEATING_OSCILLATING_S 15 // 60 seconds
|
||||
#define STOP_ALL_DEVICES_WAIT_MS 50 // Wait time after stopping all devices
|
||||
|
||||
// Modbus write boundaries
|
||||
#define MB_MAX_TIME_MIN_S 1 // Minimum max time: 1s
|
||||
#define MB_MAX_TIME_MAX_S (120 * 60) // Maximum max time: 2 hours
|
||||
|
||||
#define MB_MIN_TIME_MIN_S 1 // Minimum min time: 1s
|
||||
#define MB_MIN_TIME_MAX_S 60 // Maximum min time: 60s
|
||||
|
||||
#define AMP_BUDGET_MB_COUNT 12 // m_enabled + 11 custom values
|
||||
|
||||
enum E_AMPERAGE_MODE
|
||||
{
|
||||
E_AM_CYCLE_ALL, // Cycle through all devices
|
||||
E_AM_CYCLE_SP, // Cycle through partitions (REG_OFFSET_MAX_SIM), advance when SP - DEADBAND is reached
|
||||
E_AM_CYCLE_SP_ANY, // Heat any N devices that require it
|
||||
E_AM_CYCLE_SP_MOST_URGENT // Heat most urgent N devices, within window
|
||||
};
|
||||
|
||||
enum E_OP_FLAGS : uint16_t
|
||||
{
|
||||
E_SQ_NONE = 0,
|
||||
E_SQ_RUNNING_PROFILES_ONLY = 1 << 0,
|
||||
E_SQ_VERBOSE = 1 << 1,
|
||||
E_SQ_USER = 1 << 2,
|
||||
};
|
||||
|
||||
class AmperageBudgetManager : public NetworkComponent<AMP_BUDGET_MB_COUNT>
|
||||
{
|
||||
public:
|
||||
typedef bool (*CanUsePIDCallback)(Component *owner, OmronE5 *device);
|
||||
typedef void (*OnWarmupCompleteCallback)(Component *owner);
|
||||
|
||||
enum E_MB_OFFSETS
|
||||
{
|
||||
REG_OFFSET_INFO = E_NVC_USER,
|
||||
REG_OFFSET_MIN_TIME,
|
||||
REG_OFFSET_MAX_TIME,
|
||||
REG_OFFSET_MAX_SIM,
|
||||
REG_OFFSET_OFFSET,
|
||||
REG_OFFSET_START_INDEX,
|
||||
REG_OFFSET_END_INDEX,
|
||||
REG_OFFSET_MODE,
|
||||
REG_OFFSET_MAX_TIME_OSCILLATING,
|
||||
REG_OFFSET_POST_HEATUP_MODE,
|
||||
REG_OFFSET_OP_FLAGS
|
||||
};
|
||||
|
||||
AmperageBudgetManager(Component *owner, uint16_t baseAddress = MB_ADDR_AMPERAGE_BUDGET_BASE);
|
||||
virtual ~AmperageBudgetManager() = default;
|
||||
|
||||
void setCanUseCallback(CanUsePIDCallback cb)
|
||||
{
|
||||
_canUseCallback = cb;
|
||||
}
|
||||
|
||||
void setOnWarmupCompleteCallback(OnWarmupCompleteCallback cb)
|
||||
{
|
||||
_onWarmupCompleteCallback = cb;
|
||||
}
|
||||
|
||||
bool addManagedDevice(OmronE5 *device);
|
||||
virtual short setup() override;
|
||||
virtual short loop() override;
|
||||
virtual short info(short val0, short val1) override;
|
||||
virtual short reset() override;
|
||||
|
||||
virtual void onCycleStart(const std::vector<OmronE5 *> &activeDevices);
|
||||
virtual void onCycleEnd(const std::vector<OmronE5 *> &activeDevices);
|
||||
virtual void onHeatupComplete();
|
||||
|
||||
// Max simultaneous heating control
|
||||
uint8_t getMaxSimultaneousHeating() const { return m_maxSimultaneousHeating.getValue(); }
|
||||
void setMaxSimultaneousHeating(uint8_t value)
|
||||
{
|
||||
if (value > 0 && value <= MAX_MANAGED_DEVICES)
|
||||
{
|
||||
m_maxSimultaneousHeating.update(value);
|
||||
}
|
||||
}
|
||||
|
||||
// Modbus interface
|
||||
virtual short mb_tcp_write(MB_Registers *reg, short value) override;
|
||||
virtual short mb_tcp_read(MB_Registers *reg) override;
|
||||
virtual short serial_register(Bridge *bridge) override;
|
||||
|
||||
// Persistence methods
|
||||
void toJson(JsonDocument &doc) const;
|
||||
bool fromJson(const JsonObject &json);
|
||||
bool load(const char *path);
|
||||
bool save(const char *path) const;
|
||||
void print() const;
|
||||
|
||||
protected:
|
||||
virtual void notifyStateChange() override; // Override to handle device stopping
|
||||
|
||||
private:
|
||||
CanUsePIDCallback _canUseCallback;
|
||||
OnWarmupCompleteCallback _onWarmupCompleteCallback;
|
||||
static const uint8_t MAX_MANAGED_DEVICES = NUM_OMRON_DEVICES;
|
||||
OmronE5 *_devices[MAX_MANAGED_DEVICES];
|
||||
uint8_t _numDevices;
|
||||
uint8_t _currentIndex; // Current device index in the round-robin
|
||||
|
||||
// Configurable parameters
|
||||
NetworkValue<uint16_t> m_minHeatingDurationS;
|
||||
NetworkValue<uint16_t> m_maxHeatingDurationS;
|
||||
NetworkValue<uint16_t> m_maxHeatingDurationOscillatingS;
|
||||
NetworkValue<uint8_t> m_maxSimultaneousHeating;
|
||||
NetworkValue<uint8_t> m_windowOffset;
|
||||
NetworkValue<E_AMPERAGE_MODE> m_mode;
|
||||
NetworkValue<E_AMPERAGE_MODE> m_postHeatupMode;
|
||||
NetworkValue<uint8_t> m_startIndex;
|
||||
NetworkValue<uint8_t> m_endIndex;
|
||||
NetworkValue<uint16_t> m_opFlags;
|
||||
|
||||
E_AMPERAGE_MODE _initialMode;
|
||||
|
||||
uint32_t _deviceStartTimes[MAX_MANAGED_DEVICES];
|
||||
bool _deviceHeating[MAX_MANAGED_DEVICES];
|
||||
bool _deviceInHeatup[MAX_MANAGED_DEVICES];
|
||||
bool _heatupPhaseComplete;
|
||||
String _name;
|
||||
|
||||
millis_t _lastLoopTime;
|
||||
millis_t _lastDebugLogTime;
|
||||
uint32_t _lastStopTimeLog[MAX_MANAGED_DEVICES];
|
||||
std::vector<OmronE5 *> _activeDevices;
|
||||
|
||||
bool _checkHeatup(OmronE5 *device);
|
||||
void _stopAllDevices();
|
||||
int16_t _stoppingIndex;
|
||||
uint32_t _lastStopTimestamp;
|
||||
void _stopDevice(uint8_t deviceIndex, const char *reason);
|
||||
void _checkAllDevicesForHeatupCompletion();
|
||||
|
||||
void _loopCycleAll();
|
||||
void _loopCycleSp();
|
||||
void _loopCycleSpAny();
|
||||
void _loopCycleSpMostUrgent();
|
||||
|
||||
// Validation methods
|
||||
bool _validateMaxTime(short value) const
|
||||
{
|
||||
return value >= MB_MAX_TIME_MIN_S && value <= MB_MAX_TIME_MAX_S;
|
||||
}
|
||||
bool _validateMinTime(short value) const
|
||||
{
|
||||
return value >= MB_MIN_TIME_MIN_S && value <= MB_MIN_TIME_MAX_S;
|
||||
}
|
||||
bool _validateMaxTimeOscillating(short value) const
|
||||
{
|
||||
return value >= 1 && value <= 3600; // 1s to 1hr
|
||||
}
|
||||
bool _validateMaxSim(short value) const
|
||||
{
|
||||
return value >= 1 && value <= MAX_MANAGED_DEVICES;
|
||||
}
|
||||
bool _validateOffset(short value) const
|
||||
{
|
||||
return value >= 1 && value <= MAX_MANAGED_DEVICES;
|
||||
}
|
||||
bool _validateStartIndex(short value) const
|
||||
{
|
||||
return value >= 0 && value < MAX_MANAGED_DEVICES && value <= m_endIndex.getValue();
|
||||
}
|
||||
bool _validateEndIndex(short value) const
|
||||
{
|
||||
return value >= 0 && value < MAX_MANAGED_DEVICES && value >= m_startIndex.getValue();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
90
src/components/InfluxDB.cpp
Normal file
90
src/components/InfluxDB.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
#include "InfluxDB.h"
|
||||
#include "config-extensions.h"
|
||||
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
|
||||
InfluxDB::InfluxDB(Component *owner, short _id)
|
||||
: Component("InfluxDB", _id, Component::COMPONENT_DEFAULT, owner)
|
||||
{
|
||||
setFlag(OBJECT_RUN_FLAGS::E_OF_BROKER);
|
||||
}
|
||||
|
||||
void InfluxDB::_connect()
|
||||
{
|
||||
_lastConnectionAttempt = millis();
|
||||
Log.infoln("InfluxDB: connecting...");
|
||||
if (_client.validateConnection())
|
||||
{
|
||||
Log.infoln("InfluxDB: connected!");
|
||||
_isConnected = true;
|
||||
_reconnectInterval = 1000;
|
||||
Log.infoln("InfluxDB: connected to %s", INFLUXDB_URL);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.warningln("InfluxDB: connection failed: %s", _client.getLastErrorMessage().c_str());
|
||||
_isConnected = false;
|
||||
// Exponential backoff
|
||||
_reconnectInterval *= 2;
|
||||
if (_reconnectInterval > _maxReconnectInterval)
|
||||
{
|
||||
_reconnectInterval = _maxReconnectInterval;
|
||||
}
|
||||
Log.warningln("InfluxDB: next reconnect attempt in %lu ms", _reconnectInterval);
|
||||
}
|
||||
}
|
||||
|
||||
short InfluxDB::setup()
|
||||
{
|
||||
Component::setup();
|
||||
Log.verboseln(F("InfluxDB::setup - ID %d"), id);
|
||||
_client.setConnectionParams(INFLUXDB_URL, INFLUXDB_ORG, INFLUXDB_BUCKET, INFLUXDB_TOKEN);
|
||||
_client.setInsecure(true);
|
||||
_connect();
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
short InfluxDB::loop()
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
if (millis() - _lastConnectionAttempt > _reconnectInterval)
|
||||
{
|
||||
_connect();
|
||||
}
|
||||
}
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
short InfluxDB::info(short flags, short val)
|
||||
{
|
||||
Log.verboseln("InfluxDB::info - ID: %d, Connected: %s", id, _isConnected ? "true" : "false");
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
short InfluxDB::debug()
|
||||
{
|
||||
return info(0, 0);
|
||||
}
|
||||
|
||||
short InfluxDB::write(Point &influxDbPoint)
|
||||
{
|
||||
if (!_isConnected)
|
||||
{
|
||||
Log.warningln(F("InfluxDB: not connected, cannot write point."));
|
||||
return 1; // Not connected error
|
||||
}
|
||||
|
||||
if (!_client.writePoint(influxDbPoint))
|
||||
{
|
||||
Log.warningln(F("InfluxDB: failed to write point: %s"), _client.getLastErrorMessage().c_str());
|
||||
if (_client.isBufferFull())
|
||||
{
|
||||
Log.warningln(F("InfluxDB: buffer is full. Flushing..."));
|
||||
_client.flushBuffer();
|
||||
}
|
||||
return 2; // Write error
|
||||
}
|
||||
return E_OK;
|
||||
}
|
||||
#endif
|
||||
31
src/components/InfluxDB.h
Normal file
31
src/components/InfluxDB.h
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef INFLUXDB_H
|
||||
#define INFLUXDB_H
|
||||
|
||||
#include "config.h"
|
||||
#include <Component.h>
|
||||
#include <ArduinoLog.h>
|
||||
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
#include <InfluxDbClient.h>
|
||||
class InfluxDB : public Component
|
||||
{
|
||||
private:
|
||||
InfluxDBClient _client;
|
||||
bool _isConnected = false;
|
||||
unsigned long _lastConnectionAttempt = 0;
|
||||
unsigned long _reconnectInterval = 1000; // Initial interval 1s
|
||||
static const unsigned long _maxReconnectInterval = 25000; // Max 25s
|
||||
|
||||
void _connect();
|
||||
|
||||
public:
|
||||
InfluxDB(Component *owner, short _id);
|
||||
|
||||
short setup() override;
|
||||
short info(short flags = 0, short val = 0) override;
|
||||
short debug() override;
|
||||
short loop() override;
|
||||
short write(Point &influxDbPoint);
|
||||
};
|
||||
#endif
|
||||
#endif // ENABLE_INFLUXDB
|
||||
160
src/components/ModbusMirror.cpp
Normal file
160
src/components/ModbusMirror.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
#include "components/ModbusMirror.h"
|
||||
#include "PHApp.h"
|
||||
#include <ArduinoLog.h>
|
||||
#include <modbus/ModbusTypes.h>
|
||||
|
||||
#ifdef ENABLE_MODBUS_MIRROR
|
||||
|
||||
static ModbusMirror* instance = nullptr;
|
||||
|
||||
void ModbusMirror::onData(ModbusMessage response, uint32_t token) {
|
||||
if (instance && !instance->_isConnected) {
|
||||
instance->_isConnected = true;
|
||||
instance->m_status.update(MBM_STATUS_CONNECTED);
|
||||
LS_INFO("ModbusMirror: Connected to server %s:%d.", instance->_serverIP.toString().c_str(), instance->_serverPort);
|
||||
}
|
||||
}
|
||||
|
||||
void ModbusMirror::onError(Error error, uint32_t token) {
|
||||
ModbusError me(error);
|
||||
LS_ERROR("ModbusMirror::onError: %02X - %s, token: %08X", (int)me, (const char *)me, token);
|
||||
if (instance) {
|
||||
instance->_isConnected = false;
|
||||
if (me.operator int() == (int)MB_Error::Timeout) {
|
||||
instance->m_status.update(MBM_STATUS_TIMEOUT);
|
||||
} else {
|
||||
instance->m_status.update(MBM_STATUS_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ModbusMirror::ModbusMirror(PHApp* owner, uint16_t id) :
|
||||
NetworkComponent(MB_ADDR_MB_MIRROR_START, "ModbusMirror", id, Component::COMPONENT_DEFAULT, owner),
|
||||
_serverIP(),
|
||||
_serverPort(MODBUS_MIRROR_SERVER_PORT),
|
||||
_mbClient(nullptr),
|
||||
_isConnected(false),
|
||||
_lastConnectionAttempt(0),
|
||||
_initialConnectionAttempt(0),
|
||||
m_command(this, 0, "Command"),
|
||||
m_server_id(this, 1, "ServerID"),
|
||||
m_status(this, 2, "Status")
|
||||
{
|
||||
instance = this;
|
||||
|
||||
setNetCapability(OBJECT_NET_CAPS::E_NCAPS_MODBUS);
|
||||
|
||||
IPAddress ip(MODBUS_MIRROR_SERVER_IP);
|
||||
_serverIP = ip;
|
||||
|
||||
_mbClient = new ModbusClientTCPasync(_serverIP, _serverPort);
|
||||
|
||||
_mbClient->onDataHandler(&ModbusMirror::onData);
|
||||
_mbClient->onErrorHandler(&ModbusMirror::onError);
|
||||
_mbClient->setTimeout(10000);
|
||||
_mbClient->setIdleTimeout(60000);
|
||||
m_server_id.update(1);
|
||||
m_status.update(MBM_STATUS_DISCONNECTED);
|
||||
}
|
||||
|
||||
ModbusMirror::~ModbusMirror() {
|
||||
delete _mbClient;
|
||||
instance = nullptr;
|
||||
}
|
||||
|
||||
short ModbusMirror::setup() {
|
||||
NetworkComponent::setup();
|
||||
_initialConnectionAttempt = 0;
|
||||
const uint16_t baseAddr = mb_tcp_base_address();
|
||||
m_command.initModbus(baseAddr + MB_OFS_COMMAND, 1, this->id, this->slaveId, FN_WRITE_HOLD_REGISTER, m_command.name.c_str(), this->name.c_str());
|
||||
m_server_id.initModbus(baseAddr + MB_OFS_SERVER_ID, 1, this->id, this->slaveId, FN_WRITE_HOLD_REGISTER, m_server_id.name.c_str(), this->name.c_str());
|
||||
m_status.initModbus(baseAddr + MB_OFS_STATUS, 1, this->id, this->slaveId, FN_READ_HOLD_REGISTER, m_status.name.c_str(), this->name.c_str());
|
||||
registerBlock(m_command.getRegisterInfo());
|
||||
registerBlock(m_server_id.getRegisterInfo());
|
||||
registerBlock(m_status.getRegisterInfo());
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
short ModbusMirror::loop() {
|
||||
Component::loop();
|
||||
if (!_isConnected) {
|
||||
unsigned long now = millis();
|
||||
if (_initialConnectionAttempt == 0) {
|
||||
_initialConnectionAttempt = now;
|
||||
}
|
||||
|
||||
if (now - _initialConnectionAttempt > MODBUS_MIRROR_MAX_RECONNECT_TIME_MS) {
|
||||
L_ERROR("ModbusMirror: Max reconnect time exceeded. Giving up.");
|
||||
m_status.update(MBM_STATUS_TIMEOUT);
|
||||
disable();
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
if (now - _lastConnectionAttempt > MODBUS_MIRROR_RECONNECT_INTERVAL_MS) {
|
||||
_lastConnectionAttempt = now;
|
||||
L_INFO("ModbusMirror: Attempting to connect to %s:%d...", _serverIP.toString().c_str(), _serverPort);
|
||||
m_status.update(MBM_STATUS_CONNECTING);
|
||||
|
||||
uint32_t token = millis();
|
||||
Error err = _mbClient->addRequest(token, m_server_id.getValue(), READ_HOLD_REGISTER, 0, 1);
|
||||
if (err != SUCCESS) {
|
||||
ModbusError e(err);
|
||||
L_ERROR("ModbusMirror: Error creating request: %02X - %s", (int)e, (const char *)e);
|
||||
m_status.update(MBM_STATUS_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
}
|
||||
return E_OK;
|
||||
}
|
||||
|
||||
ModbusClientTCPasync* ModbusMirror::getClient() {
|
||||
return _mbClient;
|
||||
}
|
||||
|
||||
short ModbusMirror::mb_tcp_write(MB_Registers *reg, short networkValue)
|
||||
{
|
||||
short result = NetworkComponent::mb_tcp_write(reg, networkValue);
|
||||
if (result != E_NOT_IMPLEMENTED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t address = reg->startAddress;
|
||||
if (address == (_baseAddress + MB_OFS_COMMAND))
|
||||
{
|
||||
m_command.update(networkValue);
|
||||
// Handle command
|
||||
return E_OK;
|
||||
}
|
||||
if (address == (_baseAddress + MB_OFS_SERVER_ID))
|
||||
{
|
||||
m_server_id.update(networkValue);
|
||||
return E_OK;
|
||||
}
|
||||
return E_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
short ModbusMirror::mb_tcp_read(MB_Registers *reg)
|
||||
{
|
||||
short result = NetworkComponent::mb_tcp_read(reg);
|
||||
if (result != E_NOT_IMPLEMENTED) {
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t address = reg->startAddress;
|
||||
if (address == (_baseAddress + MB_OFS_COMMAND))
|
||||
{
|
||||
return m_command.getValue();
|
||||
}
|
||||
if (address == (_baseAddress + MB_OFS_SERVER_ID))
|
||||
{
|
||||
return m_server_id.getValue();
|
||||
}
|
||||
if (address == (_baseAddress + MB_OFS_STATUS))
|
||||
{
|
||||
return m_status.getValue();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif // ENABLE_MODBUS_MIRROR
|
||||
68
src/components/ModbusMirror.h
Normal file
68
src/components/ModbusMirror.h
Normal file
@ -0,0 +1,68 @@
|
||||
#ifndef MODBUS_MIRROR_H
|
||||
#define MODBUS_MIRROR_H
|
||||
|
||||
#include "config.h"
|
||||
#ifdef ENABLE_MODBUS_MIRROR
|
||||
|
||||
#include "modbus/NetworkComponent.h"
|
||||
#include <ModbusClientTCPasync.h>
|
||||
#include "config-modbus.h"
|
||||
#include "NetworkValue.h"
|
||||
|
||||
#define MODBUS_MIRROR_MB_COUNT 4 // command, server_id, status
|
||||
|
||||
class PHApp;
|
||||
|
||||
class ModbusMirror : public NetworkComponent<MODBUS_MIRROR_MB_COUNT> {
|
||||
public:
|
||||
enum E_MBM_CMD {
|
||||
E_MBM_INFO, // (stub)
|
||||
E_MBM_SYNC
|
||||
};
|
||||
|
||||
enum E_MBM_Status {
|
||||
MBM_STATUS_DISCONNECTED,
|
||||
MBM_STATUS_CONNECTING,
|
||||
MBM_STATUS_CONNECTED,
|
||||
MBM_STATUS_TIMEOUT
|
||||
};
|
||||
|
||||
enum E_MB_Offset {
|
||||
MB_OFS_COMMAND = E_NVC_USER + 0,
|
||||
MB_OFS_SERVER_ID = E_NVC_USER + 1,
|
||||
MB_OFS_STATUS = E_NVC_USER + 2
|
||||
};
|
||||
|
||||
ModbusMirror(PHApp* owner, uint16_t id);
|
||||
~ModbusMirror() override;
|
||||
|
||||
short setup() override;
|
||||
short loop() override;
|
||||
|
||||
short mb_tcp_write(MB_Registers *reg, short networkValue) override;
|
||||
short mb_tcp_read(MB_Registers *reg) override;
|
||||
|
||||
ModbusClientTCPasync* getClient();
|
||||
|
||||
private:
|
||||
friend void onData(ModbusMessage response, uint32_t token);
|
||||
friend void onError(Error error, uint32_t token);
|
||||
|
||||
static void onData(ModbusMessage response, uint32_t token);
|
||||
static void onError(Error error, uint32_t token);
|
||||
|
||||
IPAddress _serverIP;
|
||||
uint16_t _serverPort;
|
||||
ModbusClientTCPasync* _mbClient;
|
||||
|
||||
bool _isConnected;
|
||||
unsigned long _lastConnectionAttempt;
|
||||
unsigned long _initialConnectionAttempt;
|
||||
|
||||
NetworkValue<uint16_t> m_command;
|
||||
NetworkValue<uint16_t> m_server_id;
|
||||
NetworkValue<uint16_t> m_status;
|
||||
};
|
||||
|
||||
#endif // ENABLE_MODBUS_MIRROR
|
||||
#endif // MODBUS_MIRROR_H
|
||||
@ -1,4 +1,5 @@
|
||||
#include "config.h" // Application configuration
|
||||
#include "version.h"
|
||||
|
||||
// #define WS_MAX_QUEUED_MESSAGES 512
|
||||
|
||||
@ -684,7 +685,16 @@ void RESTServer::getSystemInfoHandler(AsyncWebServerRequest *request)
|
||||
{
|
||||
AsyncResponseStream *response = request->beginResponseStream("application/json");
|
||||
JsonDocument doc;
|
||||
doc["version"] = "3ce112f";
|
||||
#ifdef VERSION
|
||||
doc["version"] = VERSION;
|
||||
#else
|
||||
doc["version"] = "unknown";
|
||||
#endif
|
||||
#ifdef PACKAGE_URL
|
||||
doc["url"] = PACKAGE_URL;
|
||||
#else
|
||||
doc["url"] = "unknown";
|
||||
#endif
|
||||
doc["board"] = BOARD_NAME;
|
||||
doc["uptime"] = millis() / 1000;
|
||||
doc["timestamp"] = millis();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user