Skip to content

Commit 2f67ee8

Browse files
committed
Add Modbus TCP
OpenDTU is extended by a Modbus server. The Modbus server serves TCP at port 502. At Modbus ID 1 the server mimicks the Modbus registers in the original DTUPro. At Modbus ID 125 the server serves a SunSpec compatible pseudo inverter that provides the OpenDTU aggregated data from all registered inverters. The OpenDTU Modbus sources were imspired by : https://github.com/ArekKubacki/OpenDTU. See tbnobody#582 for the orignal pull request. The Modbus library used for Modbus communication is: https://github.com/eModbus/eModbus. Documentation for the library is here: https://emodbus.github.io/. The library was choosen to achieve a lower memory footprint. fixes tbnobody#582 Signed-off-by: Bobby Noelte <[email protected]>
1 parent d098193 commit 2f67ee8

File tree

13 files changed

+988
-0
lines changed

13 files changed

+988
-0
lines changed

include/Configuration.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ struct CONFIG_T {
8282
double Latitude;
8383
uint8_t SunsetType;
8484
} Ntp;
85+
struct {
86+
bool TCPEnabled;
87+
uint32_t Port;
88+
uint32_t IDDTUPro;
89+
uint32_t IDTotal;
90+
} Modbus;
8591

8692
struct {
8793
bool Enabled;

include/ModbusDtu.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
#pragma once
3+
4+
#include <TaskSchedulerDeclarations.h>
5+
6+
// eModbus
7+
#include "ModbusServerTCPasync.h"
8+
9+
class ModbusDtuClass {
10+
public:
11+
ModbusDtuClass();
12+
void init(Scheduler& scheduler);
13+
14+
private:
15+
void loop();
16+
17+
Task _loopTask;
18+
};
19+
20+
ModbusMessage OpenDTUTotal(ModbusMessage request);
21+
ModbusMessage DTUPro(ModbusMessage request);
22+
23+
extern ModbusDtuClass ModbusDtu;
24+
extern ModbusServerTCPasync ModbusTCPServer;

include/ModbusSettings.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
#pragma once
3+
4+
class ModbusSettingsClass {
5+
public:
6+
ModbusSettingsClass();
7+
void init();
8+
9+
void performConfig();
10+
11+
private:
12+
void startTCP();
13+
14+
void stopTCP();
15+
};
16+
17+
extern ModbusSettingsClass ModbusSettings;

include/WebApi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "WebApi_inverter.h"
1313
#include "WebApi_limit.h"
1414
#include "WebApi_maintenance.h"
15+
#include "WebApi_modbus.h"
1516
#include "WebApi_mqtt.h"
1617
#include "WebApi_network.h"
1718
#include "WebApi_ntp.h"
@@ -55,6 +56,7 @@ class WebApiClass {
5556
WebApiInverterClass _webApiInverter;
5657
WebApiLimitClass _webApiLimit;
5758
WebApiMaintenanceClass _webApiMaintenance;
59+
WebApiModbusClass _webApiModbus;
5860
WebApiMqttClass _webApiMqtt;
5961
WebApiNetworkClass _webApiNetwork;
6062
WebApiNtpClass _webApiNtp;

include/WebApi_modbus.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
#pragma once
3+
4+
#include <ESPAsyncWebServer.h>
5+
#include <TaskSchedulerDeclarations.h>
6+
7+
class WebApiModbusClass {
8+
public:
9+
void init(AsyncWebServer& server, Scheduler& scheduler);
10+
11+
private:
12+
void onModbusStatus(AsyncWebServerRequest* request);
13+
void onModbusAdminGet(AsyncWebServerRequest* request);
14+
void onModbusAdminPost(AsyncWebServerRequest* request);
15+
};

include/defaults.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@
3030
#define NTP_LATITUDE 51.1657f
3131
#define NTP_SUNSETTYPE 1U
3232

33+
#define MODBUS_TCP_ENABLED false
34+
#define MODBUS_PORT 502
35+
#define MODBUS_ID_DTUPRO 1
36+
#define MODBUS_ID_TOTAL 125
37+
3338
#define MQTT_ENABLED false
3439
#define MQTT_HOST ""
3540
#define MQTT_PORT 1883U

platformio.ini

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,17 @@ build_flags =
3636
build_unflags =
3737
-std=gnu++11
3838

39+
; Ignore dependencies of eModbus as they are fulfilled by other library variants
40+
lib_ignore =
41+
AsyncTCP
42+
ESPAsyncTCP
43+
custom-Ethernet
44+
3945
lib_deps =
4046
mathieucarbou/ESP Async WebServer @ 2.9.0
4147
bblanchon/ArduinoJson @ ^7.0.4
4248
https://github.com/bertmelis/espMqttClient.git#v1.6.0
49+
https://github.com/eModbus/eModbus.git
4350
nrf24/RF24 @ ^1.4.8
4451
olikraus/U8g2 @ ^2.35.15
4552
buelowp/sunset @ ^1.1.7

src/Configuration.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ bool ConfigurationClass::write()
5454
ntp["longitude"] = config.Ntp.Longitude;
5555
ntp["sunsettype"] = config.Ntp.SunsetType;
5656

57+
JsonObject modbus = doc["modbus"].to<JsonObject>();
58+
modbus["tcp_enabled"] = config.Modbus.TCPEnabled;
59+
modbus["port"] = config.Modbus.Port;
60+
modbus["id_dtupro"] = config.Modbus.IDDTUPro;
61+
modbus["id_total"] = config.Modbus.IDTotal;
62+
5763
JsonObject mqtt = doc["mqtt"].to<JsonObject>();
5864
mqtt["enabled"] = config.Mqtt.Enabled;
5965
mqtt["hostname"] = config.Mqtt.Hostname;
@@ -227,6 +233,12 @@ bool ConfigurationClass::read()
227233
config.Ntp.Longitude = ntp["longitude"] | NTP_LONGITUDE;
228234
config.Ntp.SunsetType = ntp["sunsettype"] | NTP_SUNSETTYPE;
229235

236+
JsonObject modbus = doc["modbus"];
237+
config.Modbus.TCPEnabled = modbus["tcp_enabled"] | MODBUS_TCP_ENABLED;
238+
config.Modbus.Port = modbus["port"] | MODBUS_PORT;
239+
config.Modbus.IDDTUPro = modbus["id_dtupro"] | MODBUS_ID_DTUPRO;
240+
config.Modbus.IDTotal = modbus["id_total"] | MODBUS_ID_TOTAL;
241+
230242
JsonObject mqtt = doc["mqtt"];
231243
config.Mqtt.Enabled = mqtt["enabled"] | MQTT_ENABLED;
232244
strlcpy(config.Mqtt.Hostname, mqtt["hostname"] | MQTT_HOST, sizeof(config.Mqtt.Hostname));

0 commit comments

Comments
 (0)