Skip to content

Commit

Permalink
Merge pull request #4 from soylentOrange/rest-api
Browse files Browse the repository at this point in the history
Added Rest Api
  • Loading branch information
soylentOrange authored Oct 9, 2024
2 parents cd6ad20 + 3f67f33 commit b259f46
Show file tree
Hide file tree
Showing 9 changed files with 740 additions and 52 deletions.
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

0 comments on commit b259f46

Please sign in to comment.