Skip to content

Commit

Permalink
Merge remote-tracking branch 'tbnobody/master' into development
Browse files Browse the repository at this point in the history
  • Loading branch information
schlimmchen committed Sep 21, 2024
2 parents f298fd9 + 98f4aed commit 38726b9
Show file tree
Hide file tree
Showing 27 changed files with 538 additions and 395 deletions.
4 changes: 2 additions & 2 deletions include/NetworkSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ class NetworkSettingsClass {
void setStaticIp();
void handleMDNS();
void setupMode();
void NetworkEvent(const WiFiEvent_t event);
void NetworkEvent(const WiFiEvent_t event, WiFiEventInfo_t info);

Task _loopTask;

Expand All @@ -86,4 +86,4 @@ class NetworkSettingsClass {
bool _spiEth = false;
};

extern NetworkSettingsClass NetworkSettings;
extern NetworkSettingsClass NetworkSettings;
4 changes: 4 additions & 0 deletions include/WebApi_firmware.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

class WebApiFirmwareClass {
public:
WebApiFirmwareClass();
void init(AsyncWebServer& server, Scheduler& scheduler);

private:
Expand All @@ -14,4 +15,7 @@ class WebApiFirmwareClass {
void onFirmwareUpdateFinish(AsyncWebServerRequest* request);
void onFirmwareUpdateUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final);
void onFirmwareStatus(AsyncWebServerRequest* request);

Task _rebootTask;
void rebootTaskCb();
};
3 changes: 3 additions & 0 deletions lib/Hoymiles/src/Hoymiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*/
#include "Hoymiles.h"
#include "Utils.h"
#include "inverters/HERF_1CH.h"
#include "inverters/HERF_2CH.h"
#include "inverters/HERF_4CH.h"
#include "inverters/HMS_1CH.h"
Expand Down Expand Up @@ -173,6 +174,8 @@ std::shared_ptr<InverterAbstract> HoymilesClass::addInverter(const char* name, c
i = std::make_shared<HM_2CH>(_radioNrf.get(), serial);
} else if (HM_1CH::isValidSerial(serial)) {
i = std::make_shared<HM_1CH>(_radioNrf.get(), serial);
} else if (HERF_1CH::isValidSerial(serial)) {
i = std::make_shared<HERF_1CH>(_radioNrf.get(), serial);
} else if (HERF_2CH::isValidSerial(serial)) {
i = std::make_shared<HERF_2CH>(_radioNrf.get(), serial);
} else if (HERF_4CH::isValidSerial(serial)) {
Expand Down
55 changes: 55 additions & 0 deletions lib/Hoymiles/src/inverters/HERF_1CH.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@

// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2022-2024 Thomas Basler and others
*/
#include "HERF_1CH.h"

static const byteAssign_t byteAssignment[] = {
{ TYPE_DC, CH0, FLD_UDC, UNIT_V, 2, 2, 10, false, 1 },
{ TYPE_DC, CH0, FLD_IDC, UNIT_A, 6, 2, 100, false, 2 },
{ TYPE_DC, CH0, FLD_PDC, UNIT_W, 10, 2, 10, false, 1 },
{ TYPE_DC, CH0, FLD_YD, UNIT_WH, 22, 2, 1, false, 0 },
{ TYPE_DC, CH0, FLD_YT, UNIT_KWH, 14, 4, 1000, false, 3 },
{ TYPE_DC, CH0, FLD_IRR, UNIT_PCT, CALC_CH_IRR, CH0, CMD_CALC, false, 3 },

{ TYPE_AC, CH0, FLD_UAC, UNIT_V, 26, 2, 10, false, 1 },
{ TYPE_AC, CH0, FLD_IAC, UNIT_A, 34, 2, 100, false, 2 },
{ TYPE_AC, CH0, FLD_PAC, UNIT_W, 30, 2, 10, false, 1 },
{ TYPE_AC, CH0, FLD_Q, UNIT_VAR, 40, 2, 10, false, 1 }, // to be verified
{ TYPE_AC, CH0, FLD_F, UNIT_HZ, 28, 2, 100, false, 2 },
{ TYPE_AC, CH0, FLD_PF, UNIT_NONE, 36, 2, 1000, false, 3 },

{ TYPE_INV, CH0, FLD_T, UNIT_C, 38, 2, 10, true, 1 }, // to be verified
{ TYPE_INV, CH0, FLD_EVT_LOG, UNIT_NONE, 40, 2, 1, false, 0 }, // to be verified

{ TYPE_INV, CH0, FLD_YD, UNIT_WH, CALC_TOTAL_YD, 0, CMD_CALC, false, 0 },
{ TYPE_INV, CH0, FLD_YT, UNIT_KWH, CALC_TOTAL_YT, 0, CMD_CALC, false, 3 },
{ TYPE_INV, CH0, FLD_PDC, UNIT_W, CALC_TOTAL_PDC, 0, CMD_CALC, false, 1 },
{ TYPE_INV, CH0, FLD_EFF, UNIT_PCT, CALC_TOTAL_EFF, 0, CMD_CALC, false, 3 }
};

HERF_1CH::HERF_1CH(HoymilesRadio* radio, const uint64_t serial)
: HM_Abstract(radio, serial) {};

bool HERF_1CH::isValidSerial(const uint64_t serial)
{
// serial >= 0x284100000000 && serial <= 0x2841ffffffff
uint16_t preSerial = (serial >> 32) & 0xffff;
return preSerial == 0x2841;
}

String HERF_1CH::typeName() const
{
return "HERF-300-1T";
}

const byteAssign_t* HERF_1CH::getByteAssignment() const
{
return byteAssignment;
}

uint8_t HERF_1CH::getByteAssignmentSize() const
{
return sizeof(byteAssignment) / sizeof(byteAssignment[0]);
}
13 changes: 13 additions & 0 deletions lib/Hoymiles/src/inverters/HERF_1CH.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#include "HM_Abstract.h"

class HERF_1CH : public HM_Abstract {
public:
explicit HERF_1CH(HoymilesRadio* radio, const uint64_t serial);
static bool isValidSerial(const uint64_t serial);
String typeName() const;
const byteAssign_t* getByteAssignment() const;
uint8_t getByteAssignmentSize() const;
};
2 changes: 1 addition & 1 deletion lib/Hoymiles/src/inverters/HMS_2CH.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ bool HMS_2CH::isValidSerial(const uint64_t serial)
{
// serial >= 0x114400000000 && serial <= 0x1144ffffffff
uint16_t preSerial = (serial >> 32) & 0xffff;
return preSerial == 0x1144 || preSerial == 0x1143;
return preSerial == 0x1144 || preSerial == 0x1143 || preSerial == 0x1410;
}

String HMS_2CH::typeName() const
Expand Down
27 changes: 14 additions & 13 deletions lib/Hoymiles/src/inverters/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# Class overview

| Class | Models | Serial range |
| --------------| --------------------------- | ------------ |
| HM_1CH | HM-300/350/400-1T | 1121 |
| HM_2CH | HM-600/700/800-2T | 1141 |
| HM_4CH | HM-1000/1200/1500-4T | 1161 |
| HMS_1CH | HMS-300/350/400/450/500-1T | 1124 |
| HMS_1CHv2 | HMS-500-1T v2 | 1125 |
| HMS_2CH | HMS-600/700/800/900/1000-2T | 1143, 1144 |
| HMS_4CH | HMS-1600/1800/2000-4T | 1164 |
| HMT_4CH | HMT-1600/1800/2000-4T | 1361 |
| HMT_6CH | HMT-1800/2250-6T | 1382 |
| HERF_2CH | HERF 800 | 2821 |
| HERF_4CH | HERF 1800 | 2801 |
| Class | Models | Serial range |
| --------------| --------------------------- | ------------- -- |
| HM_1CH | HM-300/350/400-1T | 1121 |
| HM_2CH | HM-600/700/800-2T | 1141 |
| HM_4CH | HM-1000/1200/1500-4T | 1161 |
| HMS_1CH | HMS-300/350/400/450/500-1T | 1124 |
| HMS_1CHv2 | HMS-500-1T v2 | 1125 |
| HMS_2CH | HMS-600/700/800/900/1000-2T | 1143, 1144, 1410 |
| HMS_4CH | HMS-1600/1800/2000-4T | 1164 |
| HMT_4CH | HMT-1600/1800/2000-4T | 1361 |
| HMT_6CH | HMT-1800/2250-6T | 1382 |
| HERF_1CH | HERF 300 | 2841 |
| HERF_2CH | HERF 800 | 2821 |
| HERF_4CH | HERF 1800 | 2801 |
8 changes: 4 additions & 4 deletions platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ build_unflags =
-std=gnu++11

lib_deps =
mathieucarbou/ESPAsyncWebServer @ 3.1.2
bblanchon/ArduinoJson @ 7.1.0
mathieucarbou/ESPAsyncWebServer @ 3.3.1
bblanchon/ArduinoJson @ 7.2.0
https://github.com/bertmelis/espMqttClient.git#v1.7.0
nrf24/RF24 @ 1.4.9
olikraus/U8g2 @ 2.35.19
olikraus/U8g2 @ 2.35.30
buelowp/sunset @ 1.1.7
https://github.com/arkhipenko/TaskScheduler#testing
arkhipenko/TaskScheduler @ 3.8.5
https://github.com/coryjfowler/MCP_CAN_lib
plerup/EspSoftwareSerial @ ^8.2.0

Expand Down
8 changes: 5 additions & 3 deletions src/NetworkSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ NetworkSettingsClass::NetworkSettingsClass()
void NetworkSettingsClass::init(Scheduler& scheduler)
{
using std::placeholders::_1;
using std::placeholders::_2;

WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN);
WiFi.setSortMethod(WIFI_CONNECT_AP_BY_SIGNAL);

WiFi.disconnect(true, true);

WiFi.onEvent(std::bind(&NetworkSettingsClass::NetworkEvent, this, _1));
WiFi.onEvent(std::bind(&NetworkSettingsClass::NetworkEvent, this, _1, _2));

if (PinMapping.isValidEthConfig()) {
PinMapping_t& pin = PinMapping.get();
Expand All @@ -54,7 +55,7 @@ void NetworkSettingsClass::init(Scheduler& scheduler)
_loopTask.enable();
}

void NetworkSettingsClass::NetworkEvent(const WiFiEvent_t event)
void NetworkSettingsClass::NetworkEvent(const WiFiEvent_t event, WiFiEventInfo_t info)
{
switch (event) {
case ARDUINO_EVENT_ETH_START:
Expand Down Expand Up @@ -94,7 +95,8 @@ void NetworkSettingsClass::NetworkEvent(const WiFiEvent_t event)
}
break;
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
MessageOutput.println("WiFi disconnected");
// Reason codes can be found here: https://github.com/espressif/esp-idf/blob/5454d37d496a8c58542eb450467471404c606501/components/esp_wifi/include/esp_wifi_types_generic.h#L79-L141
MessageOutput.printf("WiFi disconnected: %d\r\n", info.wifi_sta_disconnected.reason);
if (_networkMode == network_mode::WiFi) {
MessageOutput.println("Try reconnecting");
WiFi.disconnect(true, false);
Expand Down
2 changes: 1 addition & 1 deletion src/WebApi_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ void WebApiConfigClass::onConfigDelete(AsyncWebServerRequest* request)

auto& retMsg = response->getRoot();

if (!(root.containsKey("delete"))) {
if (!(root["delete"].is<bool>())) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
Expand Down
4 changes: 2 additions & 2 deletions src/WebApi_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ void WebApiDeviceClass::onDeviceAdminPost(AsyncWebServerRequest* request)

auto& retMsg = response->getRoot();

if (!(root.containsKey("curPin")
|| root.containsKey("display"))) {
if (!(root["curPin"].is<JsonObject>()
|| root["display"].is<JsonObject>())) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
Expand Down
14 changes: 7 additions & 7 deletions src/WebApi_dtu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,13 @@ void WebApiDtuClass::onDtuAdminPost(AsyncWebServerRequest* request)

auto& retMsg = response->getRoot();

if (!(root.containsKey("serial")
&& root.containsKey("pollinterval")
&& root.containsKey("verbose_logging")
&& root.containsKey("nrf_palevel")
&& root.containsKey("cmt_palevel")
&& root.containsKey("cmt_frequency")
&& root.containsKey("cmt_country"))) {
if (!(root["serial"].is<String>()
&& root["pollinterval"].is<uint32_t>()
&& root["verbose_logging"].is<bool>()
&& root["nrf_palevel"].is<uint8_t>()
&& root["cmt_palevel"].is<uint8_t>()
&& root["cmt_frequency"].is<uint32_t>()
&& root["cmt_country"].is<uint8_t>())) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
Expand Down
15 changes: 14 additions & 1 deletion src/WebApi_firmware.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@
#include <AsyncJson.h>
#include "esp_partition.h"

WebApiFirmwareClass::WebApiFirmwareClass()
: _rebootTask(TASK_IMMEDIATE, TASK_ONCE, std::bind(&WebApiFirmwareClass::rebootTaskCb, this))
{
}

void WebApiFirmwareClass::init(AsyncWebServer& server, Scheduler& scheduler)
{
using std::placeholders::_1;
Expand All @@ -25,6 +30,8 @@ void WebApiFirmwareClass::init(AsyncWebServer& server, Scheduler& scheduler)
std::bind(&WebApiFirmwareClass::onFirmwareUpdateUpload, this, _1, _2, _3, _4, _5, _6));

server.on("/api/firmware/status", HTTP_GET, std::bind(&WebApiFirmwareClass::onFirmwareStatus, this, _1));

scheduler.addTask(_rebootTask);
}

bool WebApiFirmwareClass::otaSupported() const
Expand All @@ -47,7 +54,8 @@ void WebApiFirmwareClass::onFirmwareUpdateFinish(AsyncWebServerRequest* request)
response->addHeader("Connection", "close");
response->addHeader("Access-Control-Allow-Origin", "*");
request->send(response);
Utils::restartDtu();
_rebootTask.enable();
_rebootTask.restart();
}

void WebApiFirmwareClass::onFirmwareUpdateUpload(AsyncWebServerRequest* request, String filename, size_t index, uint8_t* data, size_t len, bool final)
Expand Down Expand Up @@ -93,6 +101,11 @@ void WebApiFirmwareClass::onFirmwareUpdateUpload(AsyncWebServerRequest* request,
}
}

void WebApiFirmwareClass::rebootTaskCb()
{
Utils::restartDtu();
}

void WebApiFirmwareClass::onFirmwareStatus(AsyncWebServerRequest* request)
{
if (!WebApi.checkCredentialsReadonly(request)) {
Expand Down
13 changes: 8 additions & 5 deletions src/WebApi_inverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ void WebApiInverterClass::onInverterAdd(AsyncWebServerRequest* request)

auto& retMsg = response->getRoot();

if (!(root.containsKey("serial")
&& root.containsKey("name"))) {
if (!(root["serial"].is<String>()
&& root["name"].is<String>())) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
Expand Down Expand Up @@ -165,7 +165,10 @@ void WebApiInverterClass::onInverterEdit(AsyncWebServerRequest* request)

auto& retMsg = response->getRoot();

if (!(root.containsKey("id") && root.containsKey("serial") && root.containsKey("name") && root.containsKey("channel"))) {
if (!(root["id"].is<uint8_t>()
&& root["serial"].is<String>()
&& root["name"].is<String>()
&& root["channel"].is<JsonArray>())) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
Expand Down Expand Up @@ -281,7 +284,7 @@ void WebApiInverterClass::onInverterDelete(AsyncWebServerRequest* request)

auto& retMsg = response->getRoot();

if (!(root.containsKey("id"))) {
if (!(root["id"].is<uint8_t>())) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
Expand Down Expand Up @@ -323,7 +326,7 @@ void WebApiInverterClass::onInverterOrder(AsyncWebServerRequest* request)

auto& retMsg = response->getRoot();

if (!(root.containsKey("order"))) {
if (!(root["order"].is<JsonArray>())) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
Expand Down
6 changes: 3 additions & 3 deletions src/WebApi_limit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ void WebApiLimitClass::onLimitPost(AsyncWebServerRequest* request)

auto& retMsg = response->getRoot();

if (!(root.containsKey("serial")
&& root.containsKey("limit_value")
&& root.containsKey("limit_type"))) {
if (!(root["serial"].is<String>()
&& root["limit_value"].is<float>()
&& root["limit_type"].is<uint16_t>())) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
Expand Down
2 changes: 1 addition & 1 deletion src/WebApi_maintenance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ void WebApiMaintenanceClass::onRebootPost(AsyncWebServerRequest* request)

auto& retMsg = response->getRoot();

if (!(root.containsKey("reboot"))) {
if (!(root["reboot"].is<bool>())) {
retMsg["message"] = "Values are missing!";
retMsg["code"] = WebApiError::GenericValueMissing;
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
Expand Down
Loading

0 comments on commit 38726b9

Please sign in to comment.