Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Rest Api #4

Merged
merged 1 commit into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion include/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@
class Config{
private:
Preferences *_prefs;
int16_t _tcpPort;
uint16_t _tcpPort;
uint32_t _tcpTimeout;
uint32_t _modbusTimeout;
unsigned long _modbusBaudRate;
uint32_t _modbusConfig;
int8_t _modbusRtsPin;
unsigned long _serialBaudRate;
uint32_t _serialConfig;
int8_t _WiFiTXPower;
uint8_t _localMbEnable;
uint8_t _localMbAddress;
String _hostname;
public:
Config();
Expand All @@ -25,6 +28,8 @@
void setTcpPort(uint16_t value);
uint32_t getTcpTimeout();
void setTcpTimeout(uint32_t value);
uint32_t getModbusTimeout();
void setModbusTimeout(uint32_t value);
uint32_t getModbusConfig();
unsigned long getModbusBaudRate();
void setModbusBaudRate(unsigned long value);
Expand All @@ -47,6 +52,10 @@
void setSerialStopBits(uint8_t value);
int8_t getWiFiTXPower();
void setWiFiTXPower(int8_t value);
uint8_t getLocalModbusEnable();
void setLocalModbusEnable(uint8_t value);
uint8_t getLocalModbusAddress();
void setLocalModbusAddress(uint8_t value);
String getHostname();
void setHostname(String value);
};
Expand Down
15 changes: 15 additions & 0 deletions include/localmodbus.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef LOCALMODBUS_H
#define LOCALMODBUS_H

#include <WiFiManager.h>
#include <ModbusBridgeWiFi.h>
#include <Update.h>
#include "config.h"

enum SubFunctionCode : uint16_t {
RETURN_QUERY_DATA = 0x00,
RESTART_COMMUNICATION_OPTION = 0x01,
};

void setupLocalModbus(uint8_t serverID, ModbusBridgeWiFi *bridge, Config *config, WiFiManager *wm);
#endif /* LOCALMODBUS_H */
13 changes: 13 additions & 0 deletions include/restapi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef RESTAPI_H
#define RESTAPI_H

#include <WiFiManager.h>
#include <ESPAsyncWebServer.h>
#include <ModbusBridgeWiFi.h>
#include <ModbusClientRTU.h>
#include <Update.h>
#include "config.h"
#include "debug.h"

void setupRestApi(AsyncWebServer* server, ModbusClientRTU *rtu, ModbusBridgeWiFi *bridge, Config *config, WiFiManager *wm);
#endif /* RESTAPI_H */
1 change: 1 addition & 0 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
https://github.com/tzapu/WiFiManager.git
https://github.com/me-no-dev/ESPAsyncWebServer.git
https://github.com/eModbus/eModbus.git
https://github.com/bblanchon/ArduinoJson.git
build_flags = -Wall -DLOG_LEVEL=LOG_LEVEL_DEBUG
monitor_speed = 115200
lib_ldf_mode = deep+
Expand Down
36 changes: 36 additions & 0 deletions src/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@ Config::Config()
:_prefs(NULL)
,_tcpPort(502)
,_tcpTimeout(10000)
,_modbusTimeout(1000)
,_modbusBaudRate(9600)
,_modbusConfig(SERIAL_8N1)
,_modbusRtsPin(-1)
,_serialBaudRate(115200)
,_serialConfig(SERIAL_8N1)
,_WiFiTXPower(60)
,_localMbEnable(0)
,_localMbAddress(247)
,_hostname("na")
{}

Expand All @@ -18,12 +21,15 @@ void Config::begin(Preferences *prefs)
_prefs = prefs;
_tcpPort = _prefs->getUShort("tcpPort", _tcpPort);
_tcpTimeout = _prefs->getULong("tcpTimeout", _tcpTimeout);
_modbusTimeout = _prefs->getULong("modbusTimeout", _modbusTimeout);
_modbusBaudRate = _prefs->getULong("modbusBaudRate", _modbusBaudRate);
_modbusConfig = _prefs->getULong("modbusConfig", _modbusConfig);
_modbusRtsPin = _prefs->getChar("modbusRtsPin", _modbusRtsPin);
_serialBaudRate = _prefs->getULong("serialBaudRate", _serialBaudRate);
_serialConfig = _prefs->getULong("serialConfig", _serialConfig);
_WiFiTXPower = _prefs->getChar("txPower", _WiFiTXPower);
_localMbEnable = _prefs->getUChar("localMbEn", _localMbEnable);
_localMbAddress = _prefs->getUChar("localMbAdd", _localMbAddress);
_hostname = _prefs->getString("hostname", _hostname);
}

Expand All @@ -47,6 +53,16 @@ void Config::setTcpTimeout(uint32_t value){
_prefs->putULong("tcpTimeout", _tcpTimeout);
}

uint32_t Config::getModbusTimeout(){
return _modbusTimeout;
}

void Config::setModbusTimeout(uint32_t value){
if (_modbusTimeout == value) return;
_modbusTimeout = value;
_prefs->putULong("modbusTimeout", _modbusTimeout);
}

uint32_t Config::getModbusConfig(){
return _modbusConfig;
}
Expand Down Expand Up @@ -176,4 +192,24 @@ void Config::setWiFiTXPower(int8_t value){
if (_WiFiTXPower == value) return;
_WiFiTXPower = value;
_prefs->putChar("txPower", _WiFiTXPower);
}

uint8_t Config::getLocalModbusAddress(){
return _localMbAddress;
}

void Config::setLocalModbusAddress(uint8_t value){
if (_localMbAddress == value) return;
_localMbAddress = value;
_prefs->putUChar("localMbAdd", _localMbAddress);
}

uint8_t Config::getLocalModbusEnable(){
return _localMbEnable;
}

void Config::setLocalModbusEnable(uint8_t value){
if (_localMbEnable == value) return;
_localMbEnable = value;
_prefs->putUChar("localMbEn", _localMbEnable);
}
64 changes: 64 additions & 0 deletions src/localmodbus.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "localmodbus.h"
#define ETAG "\"" __DATE__ "" __TIME__ "\""

// FC03: worker do serve Modbus function code 0x03 (READ_HOLD_REGISTER)
ModbusMessage FC03(ModbusMessage request) {
uint16_t address; // requested register address
uint16_t words; // requested number of registers
ModbusMessage response; // response message to be sent back

LOG_D("WORKER CALLED FC03");

// get request values
request.get(2, address);
request.get(4, words);

// Address and words valid? We assume 10 registers here for demo
if (address && words && (address + words) <= 10) {
// Looks okay. Set up message with serverID, FC and length of data
response.add(request.getServerID(), request.getFunctionCode(), (uint8_t)(words * 2));
// Fill response with requested data
for (uint16_t i = address; i < address + words; ++i) {
response.add(i);
}
} else {
// No, either address or words are outside the limits. Set up error response.
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_DATA_ADDRESS);
}
return response;
}

// FC08: worker do serve Modbus function code 0x08 (DIAGNOSTICS_SERIAL)
ModbusMessage FC08(ModbusMessage request) {
uint16_t subFunctionCode; // Sub-function code
ModbusMessage response; // response message to be sent back

LOG_D("WORKER CALLED FC08");

// get request values
request.get(2, subFunctionCode);

switch(subFunctionCode) {
case RETURN_QUERY_DATA:
LOG_D("Return Query Data");
response = request;
break;
case RESTART_COMMUNICATION_OPTION:
LOG_D("Restart Communications Option");
response = request;
break;
default:
LOG_D("default: ILLEGAL_FUNCTION");
response.setError(request.getServerID(), request.getFunctionCode(), ILLEGAL_FUNCTION);
}

return response;
}

void setupLocalModbus(uint8_t serverID, ModbusBridgeWiFi *bridge, Config *config, WiFiManager *wm) {
String EfuseMac = String(ESP.getEfuseMac(), 16);
dbgln(EfuseMac);
bridge->registerWorker(serverID, READ_HOLD_REGISTER, &FC03);
bridge->registerWorker(serverID, DIAGNOSTICS_SERIAL, &FC08);
//bridge->registerWorker(serverID, REPORT_SERVER_ID_SERIAL, &FC08);
}
122 changes: 77 additions & 45 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,50 +9,31 @@
#include <ModbusClientRTU.h>
#include "config.h"
#include "pages.h"
#include "restapi.h"
#include "localmodbus.h"

AsyncWebServer webServer(80);
Config config;
Preferences prefs;
ModbusClientRTU *MBclient;
ModbusBridgeWiFi MBbridge;
WiFiManager wm;
static volatile uint32_t ip_addr(INADDR_NONE);
boolean isConnected(false);

// Callback for setting up mdns
void WiFiGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
uint32_t new_ip_addr = IPAddress(info.got_ip.ip_info.ip.addr);
dbg("new IP-Address: "); dbgln(IPAddress(new_ip_addr));
if(new_ip_addr != ip_addr) {
ip_addr = new_ip_addr;
dbgln("re-start mDNS");
MDNS.begin(WiFi.getHostname());
MDNS.addService("http", "tcp", 80);
}
}

// Callback for stopping mdns
void WiFiLostIP(WiFiEvent_t event, WiFiEventInfo_t info) {
dbgln("Lost IP-Address");
ip_addr = INADDR_NONE;
MDNS.end();
}
// Start mDNS for webserver and modbus
void startMDNS(uint16_t webPort = 80, uint16_t modbusPort = 502) {
// start mDNS
MDNS.begin(WiFi.getHostname());
MDNS.addService("http", "tcp", webPort);
MDNS.addService("modbus", "tcp", modbusPort);
};

void setup() {
// Set up debug serial port
debugSerial.begin(115200);
dbgln();
dbgln("[config] load");
prefs.begin("modbusRtuGw");
config.begin(&prefs);
debugSerial.end();
debugSerial.begin(config.getSerialBaudRate(), config.getSerialConfig());
dbgln("[wifi] start");
// Connect to Wifi
boolean WiFiConnect() {
// Set Hostname
if(config.getHostname().length() > 2) {
WiFi.setHostname(config.getHostname().c_str());
}
// Enable auto-reconnect
wm.setWiFiAutoReconnect(true);
// Set WiFi to station mode
WiFi.mode(WIFI_STA);
// Set (reduced) WiFi TX Power
Expand All @@ -61,11 +42,52 @@ void setup() {
wm.setClass("invert");
auto reboot = false;
wm.setAPCallback([&reboot](WiFiManager *wifiManager){reboot = true;});
wm.autoConnect();
isConnected = wm.autoConnect();
if (reboot){
ESP.restart();
}
dbgln("[wifi] finished");
if(WiFi.getMode() == WIFI_MODE_STA) {
dbgln("[WiFi] connected in WIFI_MODE_STA");
wm.setWiFiAutoReconnect(false);
return true;
} else {
dbgln("[WiFi] NOT connected in WIFI_MODE_STA");
return false;
}
};

// Callback for reconnecting
void WiFiLostIP(WiFiEvent_t event, WiFiEventInfo_t info) {
dbgln("[WiFi] (possibly) disconnected");

if(WiFi.status() != WL_CONNECTED) {
dbgln("[WiFi] trying to reconnect");
MDNS.end();

isConnected = false;
isConnected = WiFiConnect();

// Start mDNS
if(isConnected) {
startMDNS(80, config.getTcpPort());
}
} else {
dbgln("[WiFi] actually is connected");
}
}

void setup() {
// Set up debug serial port
debugSerial.begin(115200);
dbgln();
dbgln("[config] load");
prefs.begin("modbusRtuGw");
config.begin(&prefs);
debugSerial.end();
debugSerial.begin(config.getSerialBaudRate(), config.getSerialConfig());
dbgln();
dbgln("[wifi] start");
isConnected = WiFiConnect();
dbgln("[modbus] start");

MBUlogLvl = LOG_LEVEL_WARNING;
Expand All @@ -80,24 +102,34 @@ void setup() {
#endif

MBclient = new ModbusClientRTU(config.getModbusRtsPin());
MBclient->setTimeout(1000);
MBclient->setTimeout(config.getModbusTimeout());
MBclient->begin(modbusSerial, 1);
for (uint8_t i = 1; i < 248; i++)
{
MBbridge.attachServer(i, i, ANY_FUNCTION_CODE, MBclient);
uint8_t skipAddress = (config.getLocalModbusEnable() && config.getLocalModbusAddress() > 0 && config.getLocalModbusAddress() < 248) ? config.getLocalModbusAddress() : 0;
for (uint8_t i = 1; i < 248; i++) {
if(i != skipAddress) {
MBbridge.attachServer(i, i, ANY_FUNCTION_CODE, MBclient);
}
}

// register worker for local Modbus function
if(skipAddress) {
setupLocalModbus(config.getLocalModbusAddress(), &MBbridge, &config, &wm);
}

// Start Modbus Bridge
MBbridge.start(config.getTcpPort(), 10, config.getTcpTimeout());
dbgln("[modbus] finished");
dbgln("[server] start");

// Setup the pages for Webserver and Rest api (v1)
setupPages(&webServer, MBclient, &MBbridge, &config, &wm);
setupRestApi(&webServer, MBclient, &MBbridge, &config, &wm);
webServer.begin();
ip_addr = WiFi.localIP();
MDNS.begin(WiFi.getHostname());
MDNS.addService("http", "tcp", 80);
dbgln("[server] finished");
// Register Callbacks for re-starting mDNs after reconnect
WiFi.onEvent(WiFiLostIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_LOST_IP);
WiFi.onEvent(WiFiGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_GOT_IP);

// Start mDNS
startMDNS(80, config.getTcpPort());

// Register Callbacks for re-starting mDNs after disconnect
WiFi.onEvent(WiFiLostIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_STA_DISCONNECTED);
dbgln("[setup] finished");
}

Expand Down
Loading
Loading