Compare commits
No commits in common. "eth_websockets" and "master" have entirely different histories.
eth_websoc
...
master
104
ESPBMS.ino
104
ESPBMS.ino
@ -1,20 +1,9 @@
|
||||
#include "BLEDevice.h"
|
||||
#include <ETH.h>
|
||||
#include "WebSocketManager.h"
|
||||
|
||||
WebSocketManager wsManager("ws://chodbox.home.arpa", 8765, "/");
|
||||
|
||||
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;
|
||||
@ -23,19 +12,15 @@ typedef struct
|
||||
byte dataLen;
|
||||
} bmsPacketHeaderStruct;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
BLEDevice::init(""); // Initialize BLE device
|
||||
}
|
||||
|
||||
char currentName[128];
|
||||
bool gotBasicInfo;
|
||||
bool gotCellInfo;
|
||||
static bool eth_ready = false;
|
||||
|
||||
void setup() {
|
||||
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||
Serial.begin(115200);
|
||||
WiFi.onEvent(WiFiEvent);
|
||||
ETH.begin(ETH_ADDR, ETH_POWER_PIN, ETH_MDC_PIN, ETH_MDIO_PIN, ETH_TYPE, ETH_CLK_MODE);
|
||||
BLEDevice::init("");
|
||||
wsManager.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
Serial.printf("\r\n\r\n===============================\r\n\r\n");
|
||||
@ -48,16 +33,6 @@ void loop() {
|
||||
|
||||
Serial.println("Devices found: " + String(foundDevices.getCount()));
|
||||
|
||||
while(!eth_ready){
|
||||
Serial.println("Wait for eth...");
|
||||
delay(250);
|
||||
}
|
||||
|
||||
while(!wsManager.isConnected()){
|
||||
Serial.println("Wait for socket...");
|
||||
delay(250);
|
||||
}
|
||||
|
||||
for (int i = 0; i < foundDevices.getCount(); i++) {
|
||||
delay(1000);
|
||||
Serial.printf("\r\n\r\n===============================\r\n\r\n");
|
||||
@ -329,8 +304,8 @@ bool processBasicInfo(byte *data, unsigned int dataLen){
|
||||
|
||||
int32_t Watts = Volts * Amps / 1000000; // W
|
||||
|
||||
//Serial.printf("Remaining Capacity: %4.2fAh\n", ((float)(data[4] * 256 + data[5]))/100);
|
||||
//Serial.printf("Nominal Capacity: %4.2fAh\n", ((float)(data[6] * 256 + data[7]))/100);
|
||||
//Serial.printf("Remaining Capacity: %4.2fAhr\n", ((float)(data[4] * 256 + data[5]))/100);
|
||||
//Serial.printf("Nominal Capacity: %4.2fAhr\n", ((float)(data[6] * 256 + data[7]))/100);
|
||||
|
||||
uint32_t CapacityRemainAh = ((uint16_t)two_ints_into16(data[4], data[5])) * 10;
|
||||
uint8_t CapacityRemainPercent = ((uint8_t)data[19]);
|
||||
@ -342,14 +317,14 @@ bool processBasicInfo(byte *data, unsigned int dataLen){
|
||||
uint16_t BalanceCodeHigh = (two_ints_into16(data[14], data[15]));
|
||||
uint8_t MosfetStatus = ((byte)data[20]);
|
||||
|
||||
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(">>>RC.%s.Voltage %f\r\n",currentName, (float)Volts / 1000);
|
||||
Serial.printf(">>>RC.%s.Amps %f\r\n",currentName, (float)Amps / 1000);
|
||||
Serial.printf(">>>RC.%s.Watts %f\r\n",currentName, (float)Watts);
|
||||
Serial.printf(">>>RC.%s.Capacity_Remain_Ah %f\r\n",currentName, (float)CapacityRemainAh / 1000);
|
||||
Serial.printf(">>>RC.%s.Capacity_Remain_Wh %f\r\n",currentName, ((float)(CapacityRemainAh) / 1000) * ((float)(Volts) / 1000));
|
||||
Serial.printf(">>>RC.%s.Capacity_Remain_Percent %d\r\n",currentName, CapacityRemainPercent);
|
||||
Serial.printf(">>>RC.%s.Temp1 %f\r\n",currentName, (float)Temp1 / 10);
|
||||
Serial.printf(">>>RC.%s.Temp2 %f\r\n",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);
|
||||
@ -383,13 +358,13 @@ bool processCellInfo(byte *data, unsigned int dataLen)
|
||||
_cellMin = CellVolt;
|
||||
}
|
||||
|
||||
wsManager.sendText("test.RC.%s.Cell.%d.Voltage %f",currentName, i+1,(float)CellVolt/1000);
|
||||
Serial.printf(">>>RC.%s.Cell.%d.Voltage %f\r\n",currentName, i+1,(float)CellVolt/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);
|
||||
Serial.printf(">>>RC.%s.Max_Cell_Voltage %f\r\n",currentName, (float)_cellMax / 1000);
|
||||
Serial.printf(">>>RC.%s.Min_Cell_Voltage %f\r\n",currentName, (float)_cellMin / 1000);
|
||||
Serial.printf(">>>RC.%s.Difference_Cell_Voltage %f\r\n",currentName, (float)(_cellMax - _cellMin) / 1000);
|
||||
Serial.printf(">>>RC.%s.Average_Cell_Voltage %f\r\n",currentName, (float)(_cellSum / NumOfCells) / 1000);
|
||||
|
||||
gotCellInfo=true;
|
||||
|
||||
@ -437,42 +412,3 @@ int16_t two_ints_into16(int highbyte, int lowbyte) // turns two bytes into a sin
|
||||
result = (result | lowbyte); //OR operation, merge the two
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void WiFiEvent(WiFiEvent_t event) {
|
||||
Serial.print("E:");
|
||||
Serial.println(event);
|
||||
switch (event) {
|
||||
case ARDUINO_EVENT_ETH_START:
|
||||
Serial.println("ETH Started");
|
||||
//set eth hostname here
|
||||
ETH.setHostname("esp32-ethernet");
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||
Serial.println("ETH Connected");
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||
Serial.print("ETH MAC: ");
|
||||
Serial.print(ETH.macAddress());
|
||||
Serial.print(", IPv4: ");
|
||||
Serial.print(ETH.localIP());
|
||||
if (ETH.fullDuplex()) {
|
||||
Serial.print(", FULL_DUPLEX");
|
||||
}
|
||||
Serial.print(", ");
|
||||
Serial.print(ETH.linkSpeed());
|
||||
Serial.println("Mbps");
|
||||
eth_ready = true;
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||
Serial.println("ETH Disconnected");
|
||||
eth_ready = false;
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_STOP:
|
||||
Serial.println("ETH Stopped");
|
||||
eth_ready = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1,83 +0,0 @@
|
||||
#ifndef WEBSOCKETMANAGER_H
|
||||
#define WEBSOCKETMANAGER_H
|
||||
|
||||
#include <WebSocketsClient.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
#include <WiFiClient.h>
|
||||
#include "ca_cert.h"
|
||||
|
||||
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() && 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);
|
||||
}
|
||||
}
|
||||
|
||||
static bool isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
private:
|
||||
static void webSocketTask(void *param) {
|
||||
WiFiClient client;
|
||||
//client.setCACert(ca_cert);
|
||||
//webSocket.beginSSL(serverUrl.c_str(), serverPort, serverPath.c_str(), ca_cert);
|
||||
webSocket.begin(serverUrl.c_str(), serverPort, serverPath.c_str());
|
||||
webSocket.onEvent(webSocketEvent);
|
||||
webSocket.setReconnectInterval(1000);
|
||||
|
||||
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:
|
||||
connected = false;
|
||||
Serial.println("[WebSocket] Disconnected");
|
||||
break;
|
||||
case WStype_CONNECTED:
|
||||
connected = true;
|
||||
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;
|
||||
static bool connected;
|
||||
};
|
||||
|
||||
// Define static members
|
||||
WebSocketsClient WebSocketManager::webSocket;
|
||||
String WebSocketManager::serverUrl = "";
|
||||
uint16_t WebSocketManager::serverPort = 0;
|
||||
String WebSocketManager::serverPath = "";
|
||||
bool WebSocketManager::connected = false;
|
||||
|
||||
#endif // WEBSOCKETMANAGER_H
|
57
bin/2graphite.py
Normal file
57
bin/2graphite.py
Normal file
@ -0,0 +1,57 @@
|
||||
import asyncio
|
||||
import aiohttp
|
||||
import sys
|
||||
import serial_asyncio # Ensure this package is installed
|
||||
|
||||
def parse_to_graphite(data):
|
||||
results = []
|
||||
|
||||
lines = data.strip().split('\n')
|
||||
for line in lines:
|
||||
if line.startswith('>>>'):
|
||||
metric_path = line[3:].strip() # Remove the ">>>" prefix and any leading/trailing whitespace
|
||||
results.append(metric_path)
|
||||
return results
|
||||
|
||||
async def send_to_graphite(data, session, api_url):
|
||||
for message in data:
|
||||
#print(f"Sending data to API: {message}") # Debug message for sending data
|
||||
try:
|
||||
# Sending raw metric path directly as plain text
|
||||
headers = {'Content-Type': 'text/plain'}
|
||||
async with session.post(api_url, data=message, headers=headers) as response:
|
||||
if response.status != 200:
|
||||
print(f"Failed to send data: {response.status}", await response.text())
|
||||
except Exception as e:
|
||||
print(f"Error sending data: {e}")
|
||||
|
||||
async def handle_serial(reader, api_url):
|
||||
session = aiohttp.ClientSession()
|
||||
try:
|
||||
while True:
|
||||
line = await reader.readline()
|
||||
if not line:
|
||||
break
|
||||
line = line.decode('utf-8')
|
||||
print(line.strip()) # echo output for received line
|
||||
graphite_data = parse_to_graphite(line)
|
||||
if graphite_data:
|
||||
await send_to_graphite(graphite_data, session, api_url)
|
||||
finally:
|
||||
await session.close()
|
||||
|
||||
async def main():
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: python script.py <serial_device> <api_url>")
|
||||
sys.exit(1)
|
||||
|
||||
serial_device = sys.argv[1]
|
||||
api_url = sys.argv[2]
|
||||
baud_rate = 115200 # You can modify this as needed
|
||||
|
||||
# Creating the connection to the serial port
|
||||
reader, _ = await serial_asyncio.open_serial_connection(url=serial_device, baudrate=baud_rate)
|
||||
await handle_serial(reader, api_url)
|
||||
|
||||
if __name__ == '__main__':
|
||||
asyncio.run(main())
|
23
ca_cert.h
23
ca_cert.h
@ -1,23 +0,0 @@
|
||||
#ifndef CA_CERT_H
|
||||
#define CA_CERT_H
|
||||
const char* ca_cert = \
|
||||
"-----BEGIN CERTIFICATE-----\n" \
|
||||
"MIIDHTCCAgWgAwIBAgIUWLAb5lCXs4G6QxCaV78EtsRQgkEwDQYJKoZIhvcNAQEL\n" \
|
||||
"BQAwHTEbMBkGA1UEAwwSYXBpLmVjb21vdHVzLmNvLnVrMCAXDTIyMTAxOTE1Mjgx\n" \
|
||||
"N1oYDzIxMjIwOTI1MTUyODE3WjAdMRswGQYDVQQDDBJhcGkuZWNvbW90dXMuY28u\n" \
|
||||
"dWswggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwXfttIwX1y1tSeaiZ\n" \
|
||||
"0LtnQ3q9xosglFsXyoLcctJmOf+zgdHbNNxMH8CRbm4Z3ZQ4ghBoL/1RHaERl5aA\n" \
|
||||
"U7oVxr4MPHn6fWsYrLlaXLIcmL6ZS91woTKLejhf6D991sH2Jt0xVDhqerimnF4p\n" \
|
||||
"Ut1U6rY6Lw7aUAUUldChhzRUAkAcMHApWwzxElAM+KFFleLq63AESkT21xYOO+WG\n" \
|
||||
"2hLTQB+hDcBvN9IQ4Ud1V7AQ/MDKzVvJsn/z+KnslbH246l1w6haJk230UbPizau\n" \
|
||||
"fAWl63O2/xIxPJzWBXJeUuvi+lTqCf+ZVPBU6chpyL4xX+I7vCTBoKmpaI+qAF9F\n" \
|
||||
"2C4HAgMBAAGjUzBRMB0GA1UdDgQWBBTtxYrL2Cg9PVp4wx6MllB/cKXXYjAfBgNV\n" \
|
||||
"HSMEGDAWgBTtxYrL2Cg9PVp4wx6MllB/cKXXYjAPBgNVHRMBAf8EBTADAQH/MA0G\n" \
|
||||
"CSqGSIb3DQEBCwUAA4IBAQBAai8ewCT3Q2CgBMxvDLKQx7YRBNlv1gbUtYq88rvK\n" \
|
||||
"iz6yzGmbPP1Ax5LCv0oRtRdnrz0h2F80tBibS2mJ2tqsLd3277yMN81mHB0qVIrR\n" \
|
||||
"tq9aTzjGHUXgXmcezEgkTLTfISebvCB8jdR7cjvFUaTUKH3MLR3jNAAqU6WLVY6Q\n" \
|
||||
"wCYLKRhTU+aYkDeObOu2fsoph8FwR9gB9D4K0/W78UTiOQxLFJmCqubooNtGLrph\n" \
|
||||
"dz1hmIkYSKH3pdhE3kZwNilYVjyfxq3UFkh2/2J0Fz7vB7eaJE6PptcPJ2KgxTMO\n" \
|
||||
"i7QEQ+jNru8B20F4DrbvEa0IY5wv9mywugBsXg5rcfjs\n" \
|
||||
"-----END CERTIFICATE-----\n";
|
||||
#endif
|
14
victron.ino
14
victron.ino
@ -185,12 +185,12 @@ void decodeVictron(BLEAdvertisedDevice advertisedDevice) {
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
Serial.printf(">>>RC.MPPT.1.Battery_Volts %f\r\n",batteryVoltage);
|
||||
Serial.printf(">>>RC.MPPT.1.Battery_Amps %f\r\n",batteryCurrent);
|
||||
Serial.printf(">>>RC.MPPT.1.Battery_Watts %f\r\n",batteryVoltage*batteryCurrent);
|
||||
Serial.printf(">>>RC.MPPT.1.Solar_Watts %f\r\n",inputPower);
|
||||
Serial.printf(">>>RC.MPPT.1.Output_Current %f\r\n",outputCurrent);
|
||||
Serial.printf(">>>RC.MPPT.1.Yield %f\r\n",todayYield);
|
||||
Serial.printf(">>>RC.MPPT.1.State %d\r\n",deviceState);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user