Adding enable/disable option and pin to control a switch/relais to power the Huawei PSU
This commit is contained in:
parent
db7ad52a4d
commit
0b5c47cd2e
@ -119,6 +119,7 @@ struct CONFIG_T {
|
||||
float PowerLimiter_VoltageLoadCorrectionFactor;
|
||||
|
||||
bool Battery_Enabled;
|
||||
bool Huawei_Enabled;
|
||||
|
||||
char Security_Password[WIFI_MAX_PASSWORD_STRLEN + 1];
|
||||
bool Security_AllowReadonly;
|
||||
|
||||
@ -45,10 +45,12 @@ struct RectifierParameters_t {
|
||||
|
||||
class HuaweiCanClass {
|
||||
public:
|
||||
void init(uint8_t huawei_miso, uint8_t huawei_mosi, uint8_t huawei_clk, uint8_t huawei_irq, uint8_t huawei_cs);
|
||||
void init(uint8_t huawei_miso, uint8_t huawei_mosi, uint8_t huawei_clk, uint8_t huawei_irq, uint8_t huawei_cs, uint8_t huawei_power);
|
||||
void loop();
|
||||
void setValue(float in, uint8_t parameterType);
|
||||
RectifierParameters_t& get();
|
||||
void setPower(bool power);
|
||||
|
||||
RectifierParameters_t * get();
|
||||
unsigned long getLastUpdate();
|
||||
|
||||
private:
|
||||
@ -62,6 +64,7 @@ private:
|
||||
SPIClass *hspi;
|
||||
MCP_CAN *CAN;
|
||||
uint8_t _huawei_irq;
|
||||
uint8_t _huawei_power;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -38,6 +38,7 @@ struct PinMapping_t {
|
||||
uint8_t huawei_clk;
|
||||
uint8_t huawei_irq;
|
||||
uint8_t huawei_cs;
|
||||
uint8_t huawei_power;
|
||||
};
|
||||
|
||||
class PinMappingClass {
|
||||
|
||||
@ -2,15 +2,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <ESPAsyncWebServer.h>
|
||||
#include <AsyncJson.h>
|
||||
|
||||
class WebApiHuaweiClass {
|
||||
public:
|
||||
void init(AsyncWebServer* server);
|
||||
void loop();
|
||||
|
||||
void getJsonData(JsonObject& root);
|
||||
private:
|
||||
void onStatus(AsyncWebServerRequest* request);
|
||||
void onAdminGet(AsyncWebServerRequest* request);
|
||||
void onAdminPost(AsyncWebServerRequest* request);
|
||||
void onPost(AsyncWebServerRequest* request);
|
||||
|
||||
|
||||
AsyncWebServer* _server;
|
||||
};
|
||||
@ -109,3 +109,5 @@
|
||||
#define POWERLIMITER_VOLTAGE_LOAD_CORRECTION_FACTOR 0.001
|
||||
|
||||
#define BATTERY_ENABLED false
|
||||
|
||||
#define HUAWEI_ENABLED false
|
||||
|
||||
@ -138,6 +138,9 @@ bool ConfigurationClass::write()
|
||||
JsonObject battery = doc.createNestedObject("battery");
|
||||
battery["enabled"] = config.Battery_Enabled;
|
||||
|
||||
JsonObject huawei = doc.createNestedObject("huawei");
|
||||
huawei["enabled"] = config.Huawei_Enabled;
|
||||
|
||||
// Serialize JSON to file
|
||||
if (serializeJson(doc, f) == 0) {
|
||||
MessageOutput.println("Failed to write file");
|
||||
@ -303,6 +306,9 @@ bool ConfigurationClass::read()
|
||||
JsonObject battery = doc["battery"];
|
||||
config.Battery_Enabled = battery["enabled"] | BATTERY_ENABLED;
|
||||
|
||||
JsonObject huawei = doc["huawei"];
|
||||
config.Huawei_Enabled = huawei["enabled"] | HUAWEI_ENABLED;
|
||||
|
||||
f.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
|
||||
HuaweiCanClass HuaweiCan;
|
||||
|
||||
void HuaweiCanClass::init(uint8_t huawei_miso, uint8_t huawei_mosi, uint8_t huawei_clk, uint8_t huawei_irq, uint8_t huawei_cs)
|
||||
void HuaweiCanClass::init(uint8_t huawei_miso, uint8_t huawei_mosi, uint8_t huawei_clk, uint8_t huawei_irq, uint8_t huawei_cs, uint8_t huawei_power)
|
||||
{
|
||||
|
||||
hspi = new SPIClass(VSPI);
|
||||
@ -32,11 +32,15 @@ void HuaweiCanClass::init(uint8_t huawei_miso, uint8_t huawei_mosi, uint8_t huaw
|
||||
|
||||
CAN->setMode(MCP_NORMAL); // Change to normal mode to allow messages to be transmitted
|
||||
|
||||
pinMode(huawei_power, OUTPUT);
|
||||
digitalWrite(huawei_power,HIGH);
|
||||
_huawei_power = huawei_power;
|
||||
|
||||
}
|
||||
|
||||
RectifierParameters_t& HuaweiCanClass::get()
|
||||
RectifierParameters_t * HuaweiCanClass::get()
|
||||
{
|
||||
return _rp;
|
||||
return &_rp;
|
||||
}
|
||||
|
||||
unsigned long HuaweiCanClass::getLastUpdate()
|
||||
@ -178,4 +182,10 @@ void HuaweiCanClass::setValue(float in, uint8_t parameterType)
|
||||
} else {
|
||||
MessageOutput.println("Error Sending Message...");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HuaweiCanClass::setPower(bool power) {
|
||||
digitalWrite(_huawei_power, power);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -72,6 +72,7 @@ PinMappingClass::PinMappingClass()
|
||||
_pinMapping.huawei_clk = HUAWEI_PIN_SCLK;
|
||||
_pinMapping.huawei_cs = HUAWEI_PIN_CS;
|
||||
_pinMapping.huawei_irq = HUAWEI_PIN_IRQ;
|
||||
_pinMapping.huawei_power = HUAWEI_PIN_POWER;
|
||||
}
|
||||
|
||||
PinMapping_t& PinMappingClass::get()
|
||||
@ -135,6 +136,7 @@ bool PinMappingClass::init(const String& deviceMapping)
|
||||
_pinMapping.huawei_clk = doc[i]["huawei"]["clk"] | HUAWEI_PIN_SCLK;
|
||||
_pinMapping.huawei_irq = doc[i]["huawei"]["irq"] | HUAWEI_PIN_IRQ;
|
||||
_pinMapping.huawei_cs = doc[i]["huawei"]["cs"] | HUAWEI_PIN_CS;
|
||||
_pinMapping.huawei_power = doc[i]["huawei"]["power"] | HUAWEI_PIN_POWER;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -176,5 +178,6 @@ bool PinMappingClass::isValidHuaweiConfig()
|
||||
&& _pinMapping.huawei_mosi > 0
|
||||
&& _pinMapping.huawei_clk > 0
|
||||
&& _pinMapping.huawei_irq > 0
|
||||
&& _pinMapping.huawei_cs > 0;
|
||||
&& _pinMapping.huawei_cs > 0
|
||||
&& _pinMapping.huawei_power > 0;
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
*/
|
||||
#include "WebApi_Huawei.h"
|
||||
#include "Huawei_can.h"
|
||||
#include "Configuration.h"
|
||||
#include "WebApi.h"
|
||||
#include "WebApi_errors.h"
|
||||
#include <AsyncJson.h>
|
||||
@ -16,6 +17,8 @@ void WebApiHuaweiClass::init(AsyncWebServer* server)
|
||||
_server = server;
|
||||
|
||||
_server->on("/api/huawei/status", HTTP_GET, std::bind(&WebApiHuaweiClass::onStatus, this, _1));
|
||||
_server->on("/api/huawei/config", HTTP_GET, std::bind(&WebApiHuaweiClass::onAdminGet, this, _1));
|
||||
_server->on("/api/huawei/config", HTTP_POST, std::bind(&WebApiHuaweiClass::onAdminPost, this, _1));
|
||||
_server->on("/api/huawei/limit/config", HTTP_POST, std::bind(&WebApiHuaweiClass::onPost, this, _1));
|
||||
}
|
||||
|
||||
@ -23,6 +26,33 @@ void WebApiHuaweiClass::loop()
|
||||
{
|
||||
}
|
||||
|
||||
void WebApiHuaweiClass::getJsonData(JsonObject& root) {
|
||||
const RectifierParameters_t * rp = HuaweiCan.get();
|
||||
|
||||
root["data_age"] = (millis() - HuaweiCan.getLastUpdate()) / 1000;
|
||||
root[F("input_voltage")]["v"] = rp->input_voltage;
|
||||
root[F("input_voltage")]["u"] = "V";
|
||||
root[F("input_current")]["v"] = rp->input_current;
|
||||
root[F("input_current")]["u"] = "A";
|
||||
root[F("input_power")]["v"] = rp->input_power;
|
||||
root[F("input_power")]["u"] = "W";
|
||||
root[F("output_voltage")]["v"] = rp->output_voltage;
|
||||
root[F("output_voltage")]["u"] = "V";
|
||||
root[F("output_current")]["v"] = rp->output_current;
|
||||
root[F("output_current")]["u"] = "A";
|
||||
root[F("max_output_current")]["v"] = rp->max_output_current;
|
||||
root[F("max_output_current")]["u"] = "A";
|
||||
root[F("output_power")]["v"] = rp->output_power;
|
||||
root[F("output_power")]["u"] = "W";
|
||||
root[F("input_temp")]["v"] = rp->input_temp;
|
||||
root[F("input_temp")]["u"] = "°C";
|
||||
root[F("output_temp")]["v"] = rp->output_temp;
|
||||
root[F("output_temp")]["u"] = "°C";
|
||||
root[F("efficiency")]["v"] = rp->efficiency;
|
||||
root[F("efficiency")]["u"] = "%";
|
||||
|
||||
}
|
||||
|
||||
void WebApiHuaweiClass::onStatus(AsyncWebServerRequest* request)
|
||||
{
|
||||
if (!WebApi.checkCredentialsReadonly(request)) {
|
||||
@ -31,30 +61,7 @@ void WebApiHuaweiClass::onStatus(AsyncWebServerRequest* request)
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
const RectifierParameters_t& rp = HuaweiCan.get();
|
||||
|
||||
root["data_age"] = (millis() - HuaweiCan.getLastUpdate()) / 1000;
|
||||
root[F("input_voltage")]["v"] = rp.input_voltage;
|
||||
root[F("input_voltage")]["u"] = "V";
|
||||
root[F("input_current")]["v"] = rp.input_current;
|
||||
root[F("input_current")]["u"] = "A";
|
||||
root[F("input_power")]["v"] = rp.input_power;
|
||||
root[F("input_power")]["u"] = "W";
|
||||
root[F("output_voltage")]["v"] = rp.output_voltage;
|
||||
root[F("output_voltage")]["u"] = "V";
|
||||
root[F("output_current")]["v"] = rp.output_current;
|
||||
root[F("output_current")]["u"] = "A";
|
||||
root[F("max_output_current")]["v"] = rp.max_output_current;
|
||||
root[F("max_output_current")]["u"] = "A";
|
||||
root[F("output_power")]["v"] = rp.output_power;
|
||||
root[F("output_power")]["u"] = "W";
|
||||
root[F("input_temp")]["v"] = rp.input_temp;
|
||||
root[F("input_temp")]["u"] = "°C";
|
||||
root[F("output_temp")]["v"] = rp.output_temp;
|
||||
root[F("output_temp")]["u"] = "°C";
|
||||
root[F("efficiency")]["v"] = rp.efficiency;
|
||||
root[F("efficiency")]["u"] = "%";
|
||||
getJsonData(root);
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
@ -165,4 +172,84 @@ void WebApiHuaweiClass::onPost(AsyncWebServerRequest* request)
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void WebApiHuaweiClass::onAdminGet(AsyncWebServerRequest* request)
|
||||
{
|
||||
if (!WebApi.checkCredentialsReadonly(request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
const CONFIG_T& config = Configuration.get();
|
||||
|
||||
root[F("enabled")] = config.Huawei_Enabled;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
void WebApiHuaweiClass::onAdminPost(AsyncWebServerRequest* request)
|
||||
{
|
||||
if (!WebApi.checkCredentials(request)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject retMsg = response->getRoot();
|
||||
retMsg[F("type")] = F("warning");
|
||||
|
||||
if (!request->hasParam("data", true)) {
|
||||
retMsg[F("message")] = F("No values found!");
|
||||
retMsg[F("code")] = WebApiError::GenericNoValueFound;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
String json = request->getParam("data", true)->value();
|
||||
|
||||
if (json.length() > 1024) {
|
||||
retMsg[F("message")] = F("Data too large!");
|
||||
retMsg[F("code")] = WebApiError::GenericDataTooLarge;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
DynamicJsonDocument root(1024);
|
||||
DeserializationError error = deserializeJson(root, json);
|
||||
|
||||
if (error) {
|
||||
retMsg[F("message")] = F("Failed to parse data!");
|
||||
retMsg[F("code")] = WebApiError::GenericParseError;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(root.containsKey("enabled"))) {
|
||||
retMsg[F("message")] = F("Values are missing!");
|
||||
retMsg[F("code")] = WebApiError::GenericValueMissing;
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
return;
|
||||
}
|
||||
|
||||
CONFIG_T& config = Configuration.get();
|
||||
config.Huawei_Enabled = root[F("enabled")].as<bool>();
|
||||
Configuration.write();
|
||||
|
||||
retMsg[F("type")] = F("success");
|
||||
retMsg[F("message")] = F("Settings saved!");
|
||||
retMsg[F("code")] = WebApiError::GenericSuccess;
|
||||
|
||||
response->setLength();
|
||||
request->send(response);
|
||||
|
||||
HuaweiCan.setPower(config.Huawei_Enabled);
|
||||
}
|
||||
|
||||
@ -183,6 +183,10 @@ void WebApiWsLiveClass::generateJsonResponse(JsonVariant& root)
|
||||
|
||||
JsonObject vedirectObj = root.createNestedObject("vedirect");
|
||||
vedirectObj[F("enabled")] = Configuration.get().Vedirect_Enabled;
|
||||
|
||||
JsonObject huaweiObj = root.createNestedObject("huawei");
|
||||
huaweiObj[F("enabled")] = Configuration.get().Huawei_Enabled;
|
||||
|
||||
}
|
||||
|
||||
void WebApiWsLiveClass::addField(JsonObject& root, uint8_t idx, std::shared_ptr<InverterAbstract> inv, ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId, String topic)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user