websockets

This commit is contained in:
James 2024-04-27 19:37:14 +01:00
parent 39cc68c4d9
commit b1be320655
3 changed files with 109 additions and 119 deletions

View File

@ -1,20 +1,20 @@
#include "BLEDevice.h"
#include <ETH.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include "ca_cert.h"
#include "config.h"
#include "WebSocketManager.h"
// NTP Client setup
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
WebSocketManager wsManager("wss://hq.ecomotus.co.uk", 443, "/");
static BLEUUID serviceUUID("0000ff00-0000-1000-8000-00805f9b34fb"); //xiaoxiang bms service
static BLEUUID charUUID_rx("0000ff01-0000-1000-8000-00805f9b34fb"); //xiaoxiang bms rx id
static BLEUUID charUUID_tx("0000ff02-0000-1000-8000-00805f9b34fb"); //xiaoxiang bms tx id
#define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN // ETH_CLOCK_GPIO17_OUT
#define ETH_POWER_PIN 16
#define ETH_TYPE ETH_PHY_LAN8720
#define ETH_ADDR 1
#define ETH_MDC_PIN 23
#define ETH_MDIO_PIN 18
typedef struct
{
byte start;
@ -28,31 +28,15 @@ bool gotBasicInfo;
bool gotCellInfo;
static bool eth_ready = false;
WiFiClientSecure client;
HTTPClient https;
void setup() {
Serial.begin(115200);
eth_begin();
timeClient.begin();
client.setCACert(ca_cert);
client.setHandshakeTimeout(5);
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
BLEDevice::init(""); // Initialize BLE device
}
bool client_connect(){
//https.setTimeout(preferences.getInt("http_timeout"));
//https.setConnectTimeout(preferences.getInt("http_timeout"));
//https.addHeader("Content-Type","application/x-www-form-urlencoded");
String url="URL";
https.end();
if(!https.begin(client, url)) { // HTTPS
Serial.println("connect fail");
return false;
}
Serial.println("connect ok");
return true;
Serial.begin(115200);
ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE);
WiFi.onEvent(WiFiEvent);
BLEDevice::init("");
wsManager.begin();
wsManager.sendText("hello");
wsManager.sendText("Up: %lu ms", millis());
}
void loop() {
@ -66,14 +50,6 @@ void loop() {
Serial.println("Devices found: " + String(foundDevices.getCount()));
while(!eth_ready){
Serial.println("Wait for eth...");
delay(250);
}
timeClient.update();
//testClient("www.google.com", 80);
client_connect();
for (int i = 0; i < foundDevices.getCount(); i++) {
delay(1000);
Serial.printf("\r\n\r\n===============================\r\n\r\n");
@ -81,8 +57,6 @@ void loop() {
BLEAdvertisedDevice advertisedDevice = foundDevices.getDevice(i);
Serial.println("\nFound Device: " + String(advertisedDevice.toString().c_str()));
client_connect();
std::string targetAddress = "d0:65:de:e5:89:76";
if (advertisedDevice.getAddress().toString() == targetAddress) {
Serial.println("Victron device found!");
@ -360,14 +334,14 @@ bool processBasicInfo(byte *data, unsigned int dataLen){
uint16_t BalanceCodeHigh = (two_ints_into16(data[14], data[15]));
uint8_t MosfetStatus = ((byte)data[20]);
eth_send("test.RC.%s.Voltage %f",currentName, (float)Volts / 1000);
eth_send("test.RC.%s.Amps %f",currentName, (float)Amps / 1000);
eth_send("test.RC.%s.Watts %f",currentName, (float)Watts);
eth_send("test.RC.%s.Capacity_Remain_Ah %f",currentName, (float)CapacityRemainAh / 1000);
eth_send("test.RC.%s.Capacity_Remain_Wh %f",currentName, ((float)(CapacityRemainAh) / 1000) * ((float)(Volts) / 1000));
eth_send("test.RC.%s.Capacity_Remain_Percent %d",currentName, CapacityRemainPercent);
eth_send("test.RC.%s.Temp1 %f",currentName, (float)Temp1 / 10);
eth_send("test.RC.%s.Temp2 %f",currentName, (float)Temp2 / 10);
wsManager.sendText("test.RC.%s.Voltage %f",currentName, (float)Volts / 1000);
wsManager.sendText("test.RC.%s.Amps %f",currentName, (float)Amps / 1000);
wsManager.sendText("test.RC.%s.Watts %f",currentName, (float)Watts);
wsManager.sendText("test.RC.%s.Capacity_Remain_Ah %f",currentName, (float)CapacityRemainAh / 1000);
wsManager.sendText("test.RC.%s.Capacity_Remain_Wh %f",currentName, ((float)(CapacityRemainAh) / 1000) * ((float)(Volts) / 1000));
wsManager.sendText("test.RC.%s.Capacity_Remain_Percent %d",currentName, CapacityRemainPercent);
wsManager.sendText("test.RC.%s.Temp1 %f",currentName, (float)Temp1 / 10);
wsManager.sendText("test.RC.%s.Temp2 %f",currentName, (float)Temp2 / 10);
/*
Serial.printf("%s Balance Code Low: 0x%x\r\n",currentName, BalanceCodeLow);
Serial.printf("%s Balance Code High: 0x%x\r\n",currentName, BalanceCodeHigh);
@ -401,13 +375,13 @@ bool processCellInfo(byte *data, unsigned int dataLen)
_cellMin = CellVolt;
}
eth_send("test.RC.%s.Cell.%d.Voltage %f",currentName, i+1,(float)CellVolt/1000);
wsManager.sendText("test.RC.%s.Cell.%d.Voltage %f",currentName, i+1,(float)CellVolt/1000);
}
eth_send("test.RC.%s.Max_Cell_Voltage %f",currentName, (float)_cellMax / 1000);
eth_send("test.RC.%s.Min_Cell_Voltage %f",currentName, (float)_cellMin / 1000);
eth_send("test.RC.%s.Difference_Cell_Voltage %f",currentName, (float)(_cellMax - _cellMin) / 1000);
eth_send("test.RC.%s.Average_Cell_Voltage %f",currentName, (float)(_cellSum / NumOfCells) / 1000);
wsManager.sendText("test.RC.%s.Max_Cell_Voltage %f",currentName, (float)_cellMax / 1000);
wsManager.sendText("test.RC.%s.Min_Cell_Voltage %f",currentName, (float)_cellMin / 1000);
wsManager.sendText("test.RC.%s.Difference_Cell_Voltage %f",currentName, (float)(_cellMax - _cellMin) / 1000);
wsManager.sendText("test.RC.%s.Average_Cell_Voltage %f",currentName, (float)(_cellSum / NumOfCells) / 1000);
gotCellInfo=true;
@ -456,30 +430,6 @@ int16_t two_ints_into16(int highbyte, int lowbyte) // turns two bytes into a sin
return result;
}
/////
/*
* ETH_CLOCK_GPIO0_IN - default: external clock from crystal oscillator
* ETH_CLOCK_GPIO0_OUT - 50MHz clock from internal APLL output on GPIO0 - possibly an inverter is needed for LAN8720
* ETH_CLOCK_GPIO16_OUT - 50MHz clock from internal APLL output on GPIO16 - possibly an inverter is needed for LAN8720
* ETH_CLOCK_GPIO17_OUT - 50MHz clock from internal APLL inverted output on GPIO17 - tested with LAN8720
*/
#define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN // ETH_CLOCK_GPIO17_OUT
// Pin# of the enable signal for the external crystal oscillator (-1 to disable for internal APLL source)
#define ETH_POWER_PIN 16
// Type of the Ethernet PHY (LAN8720 or TLK110)
#define ETH_TYPE ETH_PHY_LAN8720
// I²C-address of Ethernet PHY (0 or 1 for LAN8720, 31 for TLK110)
#define ETH_ADDR 1
// Pin# of the I²C clock signal for the Ethernet PHY
#define ETH_MDC_PIN 23
// Pin# of the I²C IO signal for the Ethernet PHY
#define ETH_MDIO_PIN 18
void WiFiEvent(WiFiEvent_t event) {
Serial.print("E:");
@ -518,36 +468,3 @@ void WiFiEvent(WiFiEvent_t event) {
break;
}
}
// Overloaded template function for formatted sending
template<typename... Args>
void eth_send(const char* format, Args... args) {
constexpr std::size_t bufferSize = 1024; // Define a reasonable default buffer size
std::array<char, bufferSize> buffer;
snprintf(buffer.data(), buffer.size(), format, args...);
eth_send(buffer.data()); // Call the original eth_send function
}
void eth_send(const char *data) {
if(!https.connected()){
https.end();
client_connect();
}
Serial.print("http connecting...\r\n");
Serial.printf("ETH Send: %s\r\n", data);
int httpCode=https.POST(data);
if(httpCode==200){
Serial.println("post ok");
while (client.available()) {
Serial.write(client.read());
}
}else{
Serial.print("post fail:");
Serial.println(httpCode);
}
}
void eth_begin() {
WiFi.onEvent(WiFiEvent);
ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE);
}

73
WebSocketManager.h Normal file
View File

@ -0,0 +1,73 @@
#ifndef WEBSOCKETMANAGER_H
#define WEBSOCKETMANAGER_H
#include <WebSocketsClient.h>
#include <WiFiClientSecure.h>
#include "ca_cert.h" // Include the CA certificate
class WebSocketManager {
public:
WebSocketManager(const char* server, uint16_t port, const char* url) {
serverUrl = server;
serverPort = port;
serverPath = url;
}
void begin() {
xTaskCreate(&WebSocketManager::webSocketTask, "WebSocketTask", 8192, nullptr, 1, nullptr);
}
template<typename... Args>
void sendText(const char* format, Args... args) {
if (webSocket.isConnected()) {
char buffer[512]; // Define a buffer to hold the constructed message
snprintf(buffer, sizeof(buffer), format, args...); // Use snprintf to format the string
webSocket.sendTXT(buffer);
}
}
private:
static void webSocketTask(void *param) {
WiFiClientSecure client;
client.setCACert(ca_cert);
webSocket.beginSSL(serverUrl.c_str(), serverPort, serverPath.c_str(), ca_cert);
webSocket.onEvent(webSocketEvent);
webSocket.setReconnectInterval(5000);
for (;;) {
webSocket.loop();
vTaskDelay(1 / portTICK_PERIOD_MS);
}
}
static void webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
switch (type) {
case WStype_DISCONNECTED:
Serial.println("[WebSocket] Disconnected");
break;
case WStype_CONNECTED:
Serial.println("[WebSocket] Connected");
break;
case WStype_TEXT:
Serial.print("[WebSocket] Received: ");
Serial.println((char*)payload);
break;
case WStype_BIN:
Serial.println("[WebSocket] Received binary data");
break;
}
}
static WebSocketsClient webSocket;
static String serverUrl;
static uint16_t serverPort;
static String serverPath;
};
// Define static members
WebSocketsClient WebSocketManager::webSocket;
String WebSocketManager::serverUrl = "";
uint16_t WebSocketManager::serverPort = 0;
String WebSocketManager::serverPath = "";
#endif // WEBSOCKETMANAGER_H

View File

@ -185,12 +185,12 @@ void decodeVictron(BLEAdvertisedDevice advertisedDevice) {
return;
}
eth_send("test.RC.MPPT.1.Battery_Volts %f",batteryVoltage);
eth_send("test.RC.MPPT.1.Battery_Amps %f",batteryCurrent);
eth_send("test.RC.MPPT.1.Battery_Watts %f",batteryVoltage*batteryCurrent);
eth_send("test.RC.MPPT.1.Solar_Watts %f",inputPower);
eth_send("test.RC.MPPT.1.Output_Current %f",outputCurrent);
eth_send("test.RC.MPPT.1.Yield %f",todayYield);
eth_send("test.RC.MPPT.1.State %d",deviceState);
wsManager.sendText("test.RC.MPPT.1.Battery_Volts %f",batteryVoltage);
wsManager.sendText("test.RC.MPPT.1.Battery_Amps %f",batteryCurrent);
wsManager.sendText("test.RC.MPPT.1.Battery_Watts %f",batteryVoltage*batteryCurrent);
wsManager.sendText("test.RC.MPPT.1.Solar_Watts %f",inputPower);
wsManager.sendText("test.RC.MPPT.1.Output_Current %f",outputCurrent);
wsManager.sendText("test.RC.MPPT.1.Yield %f",todayYield);
wsManager.sendText("test.RC.MPPT.1.State %d",deviceState);
}
}