Skip to content

Commit

Permalink
Adding enable/disable option and pin to control a switch/relais to po…
Browse files Browse the repository at this point in the history
…wer the Huawei PSU
  • Loading branch information
MalteSchm committed Mar 26, 2023
1 parent db7ad52 commit 0b5c47c
Show file tree
Hide file tree
Showing 10 changed files with 150 additions and 30 deletions.
1 change: 1 addition & 0 deletions include/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
7 changes: 5 additions & 2 deletions include/Huawei_can.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -62,6 +64,7 @@ class HuaweiCanClass {
SPIClass *hspi;
MCP_CAN *CAN;
uint8_t _huawei_irq;
uint8_t _huawei_power;

};

Expand Down
1 change: 1 addition & 0 deletions include/PinMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 5 additions & 2 deletions include/WebApi_Huawei.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
2 changes: 2 additions & 0 deletions include/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,5 @@
#define POWERLIMITER_VOLTAGE_LOAD_CORRECTION_FACTOR 0.001

#define BATTERY_ENABLED false

#define HUAWEI_ENABLED false
6 changes: 6 additions & 0 deletions src/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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;
}
Expand Down
18 changes: 14 additions & 4 deletions src/Huawei_can.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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()
Expand Down Expand Up @@ -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);
}


5 changes: 4 additions & 1 deletion src/PinMapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
129 changes: 108 additions & 21 deletions src/WebApi_Huawei.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -16,46 +17,52 @@ 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));
}

void WebApiHuaweiClass::loop()
{
}

void WebApiHuaweiClass::onStatus(AsyncWebServerRequest* request)
{
if (!WebApi.checkCredentialsReadonly(request)) {
return;
}

AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject root = response->getRoot();

const RectifierParameters_t& rp = HuaweiCan.get();
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")]["v"] = rp->input_voltage;
root[F("input_voltage")]["u"] = "V";
root[F("input_current")]["v"] = rp.input_current;
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")]["v"] = rp->input_power;
root[F("input_power")]["u"] = "W";
root[F("output_voltage")]["v"] = rp.output_voltage;
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")]["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")]["v"] = rp->max_output_current;
root[F("max_output_current")]["u"] = "A";
root[F("output_power")]["v"] = rp.output_power;
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")]["v"] = rp->input_temp;
root[F("input_temp")]["u"] = "°C";
root[F("output_temp")]["v"] = rp.output_temp;
root[F("output_temp")]["v"] = rp->output_temp;
root[F("output_temp")]["u"] = "°C";
root[F("efficiency")]["v"] = rp.efficiency;
root[F("efficiency")]["v"] = rp->efficiency;
root[F("efficiency")]["u"] = "%";

}

void WebApiHuaweiClass::onStatus(AsyncWebServerRequest* request)
{
if (!WebApi.checkCredentialsReadonly(request)) {
return;
}

AsyncJsonResponse* response = new AsyncJsonResponse();
JsonObject root = response->getRoot();
getJsonData(root);

response->setLength();
request->send(response);
}
Expand Down Expand Up @@ -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);
}
4 changes: 4 additions & 0 deletions src/WebApi_ws_live.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 0b5c47c

Please sign in to comment.