Add ESP32 alarms system status and debug commands
This commit is contained in:
@@ -0,0 +1,13 @@
|
|||||||
|
#include "alarms.h"
|
||||||
|
#include "bms.h"
|
||||||
|
|
||||||
|
AlarmState alarms;
|
||||||
|
|
||||||
|
void updateAlarms() {
|
||||||
|
alarms.lowSoc = bmsData.valid && bmsData.soc < 20;
|
||||||
|
alarms.criticalSoc = bmsData.valid && bmsData.soc < 10;
|
||||||
|
alarms.lowVoltage = bmsData.valid && bmsData.voltage < 12.0;
|
||||||
|
alarms.highBatteryTemp = bmsData.valid && bmsData.temperatureF > 120.0;
|
||||||
|
alarms.cellImbalance = bmsData.cellsValid && bmsData.cellDeltaMv > 20;
|
||||||
|
alarms.bmsDisconnected = !bmsData.connected;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct AlarmState {
|
||||||
|
bool lowSoc = false;
|
||||||
|
bool criticalSoc = false;
|
||||||
|
bool lowVoltage = false;
|
||||||
|
bool highBatteryTemp = false;
|
||||||
|
bool cellImbalance = false;
|
||||||
|
bool bmsDisconnected = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern AlarmState alarms;
|
||||||
|
|
||||||
|
void updateAlarms();
|
||||||
@@ -64,9 +64,19 @@ static void handleNotify(
|
|||||||
|
|
||||||
static bool connectBms() {
|
static bool connectBms() {
|
||||||
if (client && client->isConnected()) {
|
if (client && client->isConnected()) {
|
||||||
|
bmsData.connected = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (client && !client->isConnected()) {
|
||||||
|
Serial.println("BMS: Disconnected, resetting client");
|
||||||
|
NimBLEDevice::deleteClient(client);
|
||||||
|
client = nullptr;
|
||||||
|
notifyChar = nullptr;
|
||||||
|
writeChar = nullptr;
|
||||||
|
bmsData.connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
Serial.println("BMS: Connecting...");
|
Serial.println("BMS: Connecting...");
|
||||||
|
|
||||||
NimBLEAddress address(std::string(BMS_ADDRESS), BLE_ADDR_PUBLIC);
|
NimBLEAddress address(std::string(BMS_ADDRESS), BLE_ADDR_PUBLIC);
|
||||||
@@ -76,6 +86,8 @@ static bool connectBms() {
|
|||||||
if (!client->connect(address)) {
|
if (!client->connect(address)) {
|
||||||
Serial.println("BMS: Connect failed");
|
Serial.println("BMS: Connect failed");
|
||||||
bmsData.connected = false;
|
bmsData.connected = false;
|
||||||
|
NimBLEDevice::deleteClient(client);
|
||||||
|
client = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +128,9 @@ static bool requestPacket(uint8_t* command, size_t commandLength) {
|
|||||||
if (!ok) {
|
if (!ok) {
|
||||||
Serial.println("BMS: Write failed");
|
Serial.println("BMS: Write failed");
|
||||||
bmsData.connected = false;
|
bmsData.connected = false;
|
||||||
|
if (client) {
|
||||||
|
client->disconnect();
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define FIRMWARE_VERSION "0.3.0"
|
||||||
|
#define FIRMWARE_NAME "xterra-controller"
|
||||||
@@ -7,6 +7,8 @@
|
|||||||
#include "relays.h"
|
#include "relays.h"
|
||||||
#include "sensors.h"
|
#include "sensors.h"
|
||||||
#include "bms.h"
|
#include "bms.h"
|
||||||
|
#include "alarms.h"
|
||||||
|
#include "system_status.h"
|
||||||
|
|
||||||
WebServer server(80);
|
WebServer server(80);
|
||||||
HardwareSerial DashboardSerial(2);
|
HardwareSerial DashboardSerial(2);
|
||||||
@@ -56,6 +58,7 @@ void buildStatusDocument(JsonDocument& doc) {
|
|||||||
battery["cell_min_voltage"] = bmsData.cellMinVoltage;
|
battery["cell_min_voltage"] = bmsData.cellMinVoltage;
|
||||||
battery["cell_max_voltage"] = bmsData.cellMaxVoltage;
|
battery["cell_max_voltage"] = bmsData.cellMaxVoltage;
|
||||||
battery["cell_delta_mv"] = bmsData.cellDeltaMv;
|
battery["cell_delta_mv"] = bmsData.cellDeltaMv;
|
||||||
|
battery["cells_valid"] = bmsData.cellsValid;
|
||||||
} else {
|
} else {
|
||||||
battery["source"] = "placeholder";
|
battery["source"] = "placeholder";
|
||||||
battery["connected"] = false;
|
battery["connected"] = false;
|
||||||
@@ -113,6 +116,21 @@ void buildStatusDocument(JsonDocument& doc) {
|
|||||||
JsonObject network = doc.createNestedObject("network");
|
JsonObject network = doc.createNestedObject("network");
|
||||||
network["wifi_enabled"] = true;
|
network["wifi_enabled"] = true;
|
||||||
network["uart_connected"] = true;
|
network["uart_connected"] = true;
|
||||||
|
|
||||||
|
JsonObject alarmObj = doc.createNestedObject("alarms");
|
||||||
|
alarmObj["low_soc"] = alarms.lowSoc;
|
||||||
|
alarmObj["critical_soc"] = alarms.criticalSoc;
|
||||||
|
alarmObj["low_voltage"] = alarms.lowVoltage;
|
||||||
|
alarmObj["high_battery_temp"] = alarms.highBatteryTemp;
|
||||||
|
alarmObj["cell_imbalance"] = alarms.cellImbalance;
|
||||||
|
alarmObj["bms_disconnected"] = alarms.bmsDisconnected;
|
||||||
|
|
||||||
|
JsonObject system = doc.createNestedObject("system");
|
||||||
|
system["firmware_name"] = FIRMWARE_NAME;
|
||||||
|
system["firmware_version"] = FIRMWARE_VERSION;
|
||||||
|
system["build_date"] = __DATE__;
|
||||||
|
system["build_time"] = __TIME__;
|
||||||
|
system["uptime_seconds"] = millis() / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendStatus(Stream& output, bool pretty = false) {
|
void sendStatus(Stream& output, bool pretty = false) {
|
||||||
@@ -214,6 +232,51 @@ void pollDashboardUart() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleDebugSerial() {
|
||||||
|
if (!Serial.available()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String command = Serial.readStringUntil('\n');
|
||||||
|
command.trim();
|
||||||
|
|
||||||
|
if (command == "status") {
|
||||||
|
sendStatus(Serial, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command == "relay starlink on") {
|
||||||
|
setRelayByName("starlink", true);
|
||||||
|
Serial.println("OK starlink on");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command == "relay starlink off") {
|
||||||
|
setRelayByName("starlink", false);
|
||||||
|
Serial.println("OK starlink off");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command == "relay fridge on") {
|
||||||
|
setRelayByName("fridge", true);
|
||||||
|
Serial.println("OK fridge on");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command == "relay fridge off") {
|
||||||
|
setRelayByName("fridge", false);
|
||||||
|
Serial.println("OK fridge off");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command.length() > 0) {
|
||||||
|
Serial.print("Unknown command: ");
|
||||||
|
Serial.println(command);
|
||||||
|
Serial.println("Commands: status, relay starlink on/off, relay fridge on/off");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handleStatus() {
|
void handleStatus() {
|
||||||
DynamicJsonDocument doc(2048);
|
DynamicJsonDocument doc(2048);
|
||||||
buildStatusDocument(doc);
|
buildStatusDocument(doc);
|
||||||
@@ -305,7 +368,9 @@ void setup() {
|
|||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
server.handleClient();
|
server.handleClient();
|
||||||
|
handleDebugSerial();
|
||||||
updateBms();
|
updateBms();
|
||||||
|
updateAlarms();
|
||||||
pollDashboardUart();
|
pollDashboardUart();
|
||||||
|
|
||||||
static unsigned long lastSensorUpdate = 0;
|
static unsigned long lastSensorUpdate = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user