Hi,
I too see it as an experimental thing. For me to be able to support it properly I’d have to have clear and full instructions for everyone to follow, even those with low skill and knowledge and I’m not sure that I want to do that. However, it sounds like you should be OK with the info I’ve already given and the source code below but if you do have any questions then let me know here.
You’ll notice that I have set 38400 baud for the Powerlink UART connection and 9600 baud for the Panel UART. I got better results doing this but feel free to experiment.
As I said previously, I got best results when I “Force Standard” in the HA Integration settings, this way only the real Powerlink is communicating with the Panel using the Powerlink protocol messages. Again though, try experimenting and let me know the results that you get.
Here’s the code I have, I didn’t do any tidying up… so best of luck
As it says in the code the “receiver” variable is very important, it determines from where to receive data for a period of time.
Please update these 2 variables to your Wifi settings
const char *ssid = “MyWifiSSID”;
const char *password = “MyWifiPassword”;
#include <WiFi.h>
#include <HardwareSerial.h>
#define FALSE 0
#define TRUE !FALSE
#define DEBUG
#define ANY_INPUT -1
#define PL_INPUT -2
#define CLIENT_MAX 4
const char *ssid = "MyWifiSSID";
const char *password = "MyWifiPassword";
#ifdef DEBUG
#define DEBUG_PRINT_VAR(...) \
Serial.print(F(#__VA_ARGS__ " = ")); \
Serial.print(__VA_ARGS__); \
Serial.print(F(" "))
#define DEBUG_PRINTLN_VAR(...) \
DEBUG_PRINT(__VA_ARGS__); \
Serial.println()
#define DEBUG_PRINT(...) Serial.print(__VA_ARGS__)
#define DEBUG_PRINTLN(...) Serial.println(__VA_ARGS__)
#define DEBUG_PRINTF(...) Serial.printf(__VA_ARGS__)
void printHEX(byte b) {
char A[17] = "0123456789ABCDEF";
byte v = b / 16;
byte w = b % 16;
Serial.print(A[v]);
Serial.print(A[w]);
Serial.flush();
}
#else
#define DEBUG_PRINT_VAR(x)
#define DEBUG_PRINTLN_VAR(x)
#define DEBUG_PRINT(...)
#define DEBUG_PRINTLN(...)
void printHEX(byte b) {
}
#endif
WiFiServer server(30000, CLIENT_MAX);
//WiFiServer monitor(30001);
HardwareSerial SerialPortPanel(1); // use UART1
HardwareSerial SerialPortPowerlink(2); // use UART2
// receiver is very important, when:
// - ANY_INPUT then look at panel first end then the Powerlink and wifi clients
// - PL_INPUT then look at Powerlink in preference
// - Greater or equal to 0 --> then look at wifi client receiver in preference
int receiver;
int no_data_count;
uint8_t bluelight;
WiFiClient client[CLIENT_MAX];
bool clientInUse[CLIENT_MAX];
uint8_t dataBuffer[256];
void setup() {
#ifdef DEBUG
Serial.begin(115200);
#endif
pinMode(LED_BUILTIN, OUTPUT);
SerialPortPanel.begin(9600, SERIAL_8N1, 16, 17); // RX2 and TX2
SerialPortPowerlink.begin(38400, SERIAL_8N1, 15, 4); //12,13
receiver = ANY_INPUT;
no_data_count = 0;
bluelight = 0;
for (int i = 0; i < CLIENT_MAX; i++) {
clientInUse[i] = FALSE;
}
}
int getEmptyClientSlot() {
for (int i = 0; i < CLIENT_MAX; i++) {
if (!clientInUse[i]) {
return i;
}
}
return -1;
}
void updateState() {
if (WiFi.status() != WL_CONNECTED) {
for (int i = 0; i < CLIENT_MAX; i++) {
if (clientInUse[i]) {
client[i].stop();
}
clientInUse[i] = FALSE;
}
// We start by connecting to a WiFi network
WiFi.begin(ssid, password);
delay(5000);
if (WiFi.status() == WL_CONNECTED) {
server.begin();
DEBUG_PRINT("Connected to wifi. My address:");
IPAddress myAddress = WiFi.localIP();
DEBUG_PRINTLN(myAddress);
}
}
if (WiFi.status() == WL_CONNECTED) {
WiFiClient temp_client = server.available(); // listen for incoming clients
if (temp_client) {
// Add new clients
int s = getEmptyClientSlot();
if (s >= 0) {
client[s] = temp_client;
clientInUse[s] = TRUE;
DEBUG_PRINTF("Client %d Connected\n", s);
} else {
DEBUG_PRINTLN("Exceeded the maximum number of Clients");
temp_client.stop();
}
}
for (int i = 0; i < CLIENT_MAX; i++) {
if (clientInUse[i] && !client[i].connected()) {
// Remove disconnected Clients
DEBUG_PRINTF("Client %d Disconnected\n", i);
clientInUse[i] = FALSE;
}
}
}
}
void dumpBuffer(int count) {
Serial.printf(" %3d ", count);
//DEBUG_PRINT_VAR(count);
DEBUG_PRINT(" Data = ");
for (int i = 0; i < count; i++) {
printHEX(dataBuffer[i]);
DEBUG_PRINT(" ");
}
DEBUG_PRINTLN();
}
void loop() {
updateState();
if (receiver == ANY_INPUT) {
digitalWrite(LED_BUILTIN, bluelight / 16);
bluelight = (bluelight == 31 ? 0 : bluelight + 1); // Flash the blue led slowly
if (SerialPortPanel.available()) {
DEBUG_PRINT("Panel");
size_t count = SerialPortPanel.read((uint8_t *)&dataBuffer, (size_t)255);
// send to powerlink
SerialPortPowerlink.write((uint8_t *)&dataBuffer, count);
// send to wifi
for (int i = 0; i < CLIENT_MAX; i++) {
if (WiFi.status() == WL_CONNECTED && clientInUse[i] && client[i]) { // if you get a client,
client[i].write((const char *)&dataBuffer, count); // write a s bytes
}
}
dumpBuffer(count);
} else if (SerialPortPowerlink.available()) {
receiver = PL_INPUT;
bluelight = 0;
} else {
for (int i = 0; i < CLIENT_MAX && receiver == ANY_INPUT ; i++) {
if (clientInUse[i] && client[i].available()) {
receiver = i;
bluelight = 0;
}
}
}
}
if (receiver == PL_INPUT) {
digitalWrite(LED_BUILTIN, bluelight / 4);
bluelight = (bluelight == 7 ? 0 : bluelight + 1); // Flash the blue led slowly
int count = SerialPortPowerlink.read((uint8_t *)&dataBuffer, 255);
if (count > 0) {
SerialPortPanel.write((uint8_t *)&dataBuffer, count);
if (no_data_count > 0) {
DEBUG_PRINT(" ");
} else {
DEBUG_PRINT("PLink");
}
dumpBuffer(count);
no_data_count = 0; // zero the no data count as we have data
}
}
if (receiver >= 0 && receiver < CLIENT_MAX) {
digitalWrite(LED_BUILTIN, bluelight / 4);
bluelight = (bluelight == 7 ? 0 : bluelight + 1); // Flash the blue led slowly
int count = 0;
if (WiFi.status() == WL_CONNECTED && clientInUse[receiver] && client[receiver]) { // if you get a client,
count = client[receiver].read((uint8_t *)&dataBuffer, 255); // read into buffer, return no of characters in buffer
}
if (count > 0) {
SerialPortPanel.write((uint8_t *)&dataBuffer, count);
if (no_data_count > 0) {
DEBUG_PRINTF(" ");
} else {
DEBUG_PRINTF("Wifi%d", receiver);
}
dumpBuffer(count);
no_data_count = 0; // zero the no data count as we have data
delay(10);
}
}
if (receiver == PL_INPUT || (receiver >= 0 && receiver < CLIENT_MAX)) {
// if no data has been transferred in X loops then reset it back to allow either source
no_data_count = no_data_count + 1;
if (no_data_count >= 2) { // 2 at 20 mSec = 40 mSec
//DEBUG_PRINTLN();
//DEBUG_PRINTLN("Receive from any input");
receiver = ANY_INPUT;
no_data_count = 0;
}
}
delay(20); // delay 20mSec so approx 50Hz and it doesn't need to be accurate
}
I used the Arduino IDE, and I just updated to the latest version so I assume it will still work:
Version: 2.0.3
Date: 2022-12-05T09:30:25.331Z
CLI Version: 0.29.0 [76251df9]
Copyright © 2023 Arduino SA
The Board Type I use is “DOIT ESP32 DEVKIT V1”
You will need to install the esp32 board types from Espressif Systems in the Board Manager
You should be able to use the debug “Serial” monitor in the Arduino IDE to see the print debug messages.
Best of luck and let me know how you get on