Merge branch 'development'

This commit is contained in:
helgeerbe 2023-09-19 13:06:46 +02:00
commit ae392329ea
13 changed files with 159 additions and 63 deletions

View File

@ -3,6 +3,7 @@
#include <stdint.h>
#include <Arduino.h>
#include <HTTPClient.h>
class HttpPowerMeterClass {
public:
@ -14,9 +15,12 @@ public:
float getFloatValueByJsonPath(const char* jsonString, const char* jsonPath, float &value);
private:
float power[POWERMETER_MAX_PHASES];
void extractUrlComponents(const String& url, String& protocol, String& hostname, String& uri);
void prepareRequest(uint32_t timeout, const char* httpHeader, const char* httpValue);
HTTPClient httpClient;
float power[POWERMETER_MAX_PHASES];
String sha256(const String& data);
};
extern HttpPowerMeterClass HttpPowerMeter;

View File

@ -9,7 +9,7 @@ public:
void loop();
private:
uint32_t _lastPublish;
uint32_t _lastPublish = 0;
};
extern MqttHandleDtuClass MqttHandleDtu;

View File

@ -17,8 +17,8 @@ private:
void publishField(std::shared_ptr<InverterAbstract> inv, ChannelType_t type, ChannelNum_t channel, FieldId_t fieldId);
void onMqttMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total);
uint32_t _lastPublishStats[INV_MAX_COUNT];
uint32_t _lastPublish;
uint32_t _lastPublishStats[INV_MAX_COUNT] = { 0 };
uint32_t _lastPublish = 0;
FieldId_t _publishFields[14] = {
FLD_UDC,

View File

@ -5,6 +5,7 @@
#include "Hoymiles.h"
#include "Utils.h"
#include "inverters/HMS_1CH.h"
#include "inverters/HMS_1CHv2.h"
#include "inverters/HMS_2CH.h"
#include "inverters/HMS_4CH.h"
#include "inverters/HMT_6CH.h"
@ -147,6 +148,8 @@ std::shared_ptr<InverterAbstract> HoymilesClass::addInverter(const char* name, u
i = std::make_shared<HMS_2CH>(_radioCmt.get(), serial);
} else if (HMS_1CH::isValidSerial(serial)) {
i = std::make_shared<HMS_1CH>(_radioCmt.get(), serial);
} else if (HMS_1CHv2::isValidSerial(serial)) {
i = std::make_shared<HMS_1CHv2>(_radioCmt.get(), serial);
} else if (HM_4CH::isValidSerial(serial)) {
i = std::make_shared<HM_4CH>(_radioNrf.get(), serial);
} else if (HM_2CH::isValidSerial(serial)) {

View File

@ -0,0 +1,54 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2023 Thomas Basler and others
*/
#include "HMS_1CHv2.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_IRR_CH, 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, 20, 2, 10, false, 1 },
{ 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 },
{ TYPE_INV, CH0, FLD_EVT_LOG, UNIT_NONE, 18, 2, 1, false, 0 },
{ TYPE_AC, CH0, FLD_YD, UNIT_WH, CALC_YD_CH0, 0, CMD_CALC, false, 0 },
{ TYPE_AC, CH0, FLD_YT, UNIT_KWH, CALC_YT_CH0, 0, CMD_CALC, false, 3 },
{ TYPE_AC, CH0, FLD_PDC, UNIT_W, CALC_PDC_CH0, 0, CMD_CALC, false, 1 },
{ TYPE_AC, CH0, FLD_EFF, UNIT_PCT, CALC_EFF_CH0, 0, CMD_CALC, false, 3 }
};
HMS_1CHv2::HMS_1CHv2(HoymilesRadio* radio, uint64_t serial)
: HMS_Abstract(radio, serial) {};
bool HMS_1CHv2::isValidSerial(uint64_t serial)
{
// serial >= 0x112500000000 && serial <= 0x112599999999
uint16_t preSerial = (serial >> 32) & 0xffff;
return preSerial == 0x1125;
}
String HMS_1CHv2::typeName()
{
return "HMS-500 v2";
}
const byteAssign_t* HMS_1CHv2::getByteAssignment()
{
return byteAssignment;
}
uint8_t HMS_1CHv2::getByteAssignmentSize()
{
return sizeof(byteAssignment) / sizeof(byteAssignment[0]);
}

View File

@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "HMS_Abstract.h"
#include <list>
class HMS_1CHv2 : public HMS_Abstract {
public:
explicit HMS_1CHv2(HoymilesRadio* radio, uint64_t serial);
static bool isValidSerial(uint64_t serial);
String typeName();
const byteAssign_t* getByteAssignment();
uint8_t getByteAssignmentSize();
};

View File

@ -32,6 +32,7 @@ const devInfo_t devInfo[] = {
{ { 0x10, 0x20, 0x41, ALL }, 400, "HMS-400" }, // 00
{ { 0x10, 0x10, 0x51, ALL }, 450, "HMS-450" }, // 01
{ { 0x10, 0x10, 0x71, ALL }, 500, "HMS-500" }, // 02
{ { 0x10, 0x20, 0x71, ALL }, 500, "HMS-500 v2" }, // 02
{ { 0x10, 0x21, 0x11, ALL }, 600, "HMS-600" }, // 01
{ { 0x10, 0x21, 0x41, ALL }, 800, "HMS-800" }, // 00
{ { 0x10, 0x11, 0x51, ALL }, 900, "HMS-900" }, // 01

View File

@ -3,7 +3,6 @@
#include "HttpPowerMeter.h"
#include "MessageOutput.h"
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <FirebaseJson.h>
#include <Crypto.h>
#include <SHA256.h>
@ -87,30 +86,19 @@ bool HttpPowerMeterClass::httpRequest(const char* url, Auth authType, const char
wifiClient = std::make_unique<WiFiClient>();
}
HTTPClient httpClient;
if (!httpClient.begin(*wifiClient, newUrl)) {
snprintf_P(error, errorSize, "httpClient.begin(%s) failed", newUrl.c_str());
return false;
}
httpClient.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
httpClient.setUserAgent("OpenDTU-OnBattery");
httpClient.setConnectTimeout(timeout);
httpClient.setTimeout(timeout);
httpClient.addHeader("Content-Type", "application/json");
httpClient.addHeader("Accept", "application/json");
if (strlen(httpHeader) > 0) {
httpClient.addHeader(httpHeader, httpValue);
}
prepareRequest(timeout, httpHeader, httpValue);
if (authType == Auth::digest) {
const char *headers[1] = {"WWW-Authenticate"};
httpClient.collectHeaders(headers, 1);
}
int httpCode = httpClient.GET();
if (httpCode == HTTP_CODE_UNAUTHORIZED && authType == Auth::digest) {
// Handle authentication challenge
char realm[256]; // Buffer to store the realm received from the server
@ -160,6 +148,12 @@ bool HttpPowerMeterClass::httpRequest(const char* url, Auth authType, const char
authorization += "\", nc=00000001, qop=auth, response=\"";
authorization += response;
authorization += "\", algorithm=SHA-256";
httpClient.end();
if (!httpClient.begin(*wifiClient, newUrl)) {
snprintf_P(error, errorSize, "httpClient.begin(%s) for digest auth failed", newUrl.c_str());
return false;
}
prepareRequest(timeout, httpHeader, httpValue);
httpClient.addHeader("Authorization", authorization);
httpCode = httpClient.GET();
}
@ -259,4 +253,17 @@ String HttpPowerMeterClass::sha256(const String& data) {
return hashStr;
}
void HttpPowerMeterClass::prepareRequest(uint32_t timeout, const char* httpHeader, const char* httpValue) {
httpClient.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
httpClient.setUserAgent("OpenDTU-OnBattery");
httpClient.setConnectTimeout(timeout);
httpClient.setTimeout(timeout);
httpClient.addHeader("Content-Type", "application/json");
httpClient.addHeader("Accept", "application/json");
if (strlen(httpHeader) > 0) {
httpClient.addHeader(httpHeader, httpValue);
}
}
HttpPowerMeterClass HttpPowerMeter;

View File

@ -143,7 +143,7 @@ void MqttHandleHassClass::publishField(std::shared_ptr<InverterAbstract> inv, Ch
root["stat_cla"] = stateCls;
}
char buffer[512];
String buffer;
serializeJson(root, buffer);
publish(configTopic, buffer);
} else {
@ -181,7 +181,7 @@ void MqttHandleHassClass::publishInverterButton(std::shared_ptr<InverterAbstract
JsonObject deviceObj = root.createNestedObject("dev");
createDeviceInfo(deviceObj, inv);
char buffer[512];
String buffer;
serializeJson(root, buffer);
publish(configTopic, buffer);
}
@ -220,7 +220,7 @@ void MqttHandleHassClass::publishInverterNumber(
JsonObject deviceObj = root.createNestedObject("dev");
createDeviceInfo(deviceObj, inv);
char buffer[512];
String buffer;
serializeJson(root, buffer);
publish(configTopic, buffer);
}
@ -249,7 +249,7 @@ void MqttHandleHassClass::publishInverterBinarySensor(std::shared_ptr<InverterAb
JsonObject deviceObj = root.createNestedObject("dev");
createDeviceInfo(deviceObj, inv);
char buffer[512];
String buffer;
serializeJson(root, buffer);
publish(configTopic, buffer);
}

View File

@ -12,21 +12,21 @@
},
"dependencies": {
"@popperjs/core": "^2.11.8",
"bootstrap": "^5.3.1",
"bootstrap": "^5.3.2",
"bootstrap-icons-vue": "^1.10.3",
"mitt": "^3.0.1",
"sortablejs": "^1.15.0",
"spark-md5": "^3.0.2",
"vue": "^3.3.4",
"vue-i18n": "^9.4.0",
"vue-i18n": "^9.4.1",
"vue-router": "^4.2.4"
},
"devDependencies": {
"@intlify/unplugin-vue-i18n": "^1.2.0",
"@rushstack/eslint-patch": "^1.3.3",
"@rushstack/eslint-patch": "^1.4.0",
"@tsconfig/node18": "^18.2.2",
"@types/bootstrap": "^5.2.6",
"@types/node": "^20.6.0",
"@types/bootstrap": "^5.2.7",
"@types/node": "^20.6.2",
"@types/sortablejs": "^1.15.2",
"@types/spark-md5": "^3.0.2",
"@vitejs/plugin-vue": "^4.3.4",
@ -35,7 +35,7 @@
"eslint": "^8.49.0",
"eslint-plugin-vue": "^9.17.0",
"npm-run-all": "^4.1.5",
"sass": "^1.66.1",
"sass": "^1.67.0",
"terser": "^5.19.4",
"typescript": "^5.2.2",
"vite": "^4.4.9",

View File

@ -176,7 +176,7 @@
"eventlog": {
"Start": "Begin",
"Stop": "Ende",
"Id": "Fehlernummer",
"Id": "ID",
"Message": "Meldung"
},
"devinfo": {

View File

@ -206,15 +206,23 @@
source-map-js "^1.0.1"
yaml-eslint-parser "^1.2.2"
"@intlify/core-base@9.4.0":
version "9.4.0"
resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-9.4.0.tgz#a99a89f1263ab0f4d2889b49629bfbbf4f238d85"
integrity sha512-bIvtuEjLES35l39R0OccYbmr/fatSr4VSRThhouvFc05mnoAZyJGgj3st1iLaHGlFTmvd507uww1427o56r36Q==
"@intlify/core-base@9.4.1":
version "9.4.1"
resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-9.4.1.tgz#5ab9b624a34af2299a9b45aa331b6516c169b8b5"
integrity sha512-WIwx+elsZbxSMxRG5+LC+utRohFvmZMoDevfKOfnYMLbpCjCSavqTfHJAtfsY6ruowzqXeKkeLhRHbYbjoJx5g==
dependencies:
"@intlify/message-compiler" "9.4.0"
"@intlify/shared" "9.4.0"
"@intlify/message-compiler" "9.4.1"
"@intlify/shared" "9.4.1"
"@intlify/message-compiler@9.4.0", "@intlify/message-compiler@^9.4.0":
"@intlify/message-compiler@9.4.1":
version "9.4.1"
resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-9.4.1.tgz#aa00629a455e23cece3464293834a02994b4fb04"
integrity sha512-aN2N+dUx320108QhH51Ycd2LEpZ+NKbzyQ2kjjhqMcxhHdxtOnkgdx+MDBhOy/CObwBmhC3Nygzc6hNlfKvPNw==
dependencies:
"@intlify/shared" "9.4.1"
source-map-js "^1.0.2"
"@intlify/message-compiler@^9.4.0":
version "9.4.0"
resolved "https://registry.yarnpkg.com/@intlify/message-compiler/-/message-compiler-9.4.0.tgz#c11fceb4cc07dfe6a4b3066ca6e9a9e44e897f23"
integrity sha512-EdjqOH3bQqEjZcUOwo90wuW4ZuFr41FDxVni6WNKS0V0myKgwz9EuvLDcnEbjJMIX8vKAWPjWfnSTt5fMwKHLA==
@ -227,6 +235,11 @@
resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-9.4.0.tgz#4a78d462fc82433db900981e12eb5b1aae3d6085"
integrity sha512-AFqymip2kToqA0B6KZPg5jSrdcVHoli9t/VhGKE2iiMq9utFuMoGdDC/JOCIZgwxo6aXAk86QyU2XtzEoMuZ6A==
"@intlify/shared@9.4.1":
version "9.4.1"
resolved "https://registry.yarnpkg.com/@intlify/shared/-/shared-9.4.1.tgz#bd0d221aaac476b6778a10ddcd0472f812c64e27"
integrity sha512-A51elBmZWf1FS80inf/32diO9DeXoqg9GR9aUDHFcfHoNDuT46Q+fpPOdj8jiJnSHSBh8E1E+6qWRhAZXdK3Ng==
"@intlify/unplugin-vue-i18n@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@intlify/unplugin-vue-i18n/-/unplugin-vue-i18n-1.2.0.tgz#ca4ac742140f1eaf4668c9530db5db23069eb604"
@ -325,20 +338,20 @@
estree-walker "^2.0.2"
picomatch "^2.3.1"
"@rushstack/eslint-patch@^1.3.3":
version "1.3.3"
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.3.3.tgz#16ab6c727d8c2020a5b6e4a176a243ecd88d8d69"
integrity sha512-0xd7qez0AQ+MbHatZTlI1gu5vkG8r7MYRUJAHPAHJBmGLs16zpkrpAVLvjQKQOqaXPDUBwOiJzNc00znHSCVBw==
"@rushstack/eslint-patch@^1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.4.0.tgz#77e948b9760bd22736a5d26e335a690f76fda37b"
integrity sha512-cEjvTPU32OM9lUFegJagO0mRnIn+rbqrG89vV8/xLnLFX0DoR0r1oy5IlTga71Q7uT3Qus7qm7wgeiMT/+Irlg==
"@tsconfig/node18@^18.2.2":
version "18.2.2"
resolved "https://registry.yarnpkg.com/@tsconfig/node18/-/node18-18.2.2.tgz#81fb16ecff0d400b1cbadbf76713b50f331029ce"
integrity sha512-d6McJeGsuoRlwWZmVIeE8CUA27lu6jLjvv1JzqmpsytOYYbVi1tHZEnwCNVOXnj4pyLvneZlFlpXUK+X9wBWyw==
"@types/bootstrap@^5.2.6":
version "5.2.6"
resolved "https://registry.yarnpkg.com/@types/bootstrap/-/bootstrap-5.2.6.tgz#e861b3aa1f4a1434da0bf50fbaa372b6f7e64d2f"
integrity sha512-BlAc3YATdasbHoxMoBWODrSF6qwQO/E9X8wVxCCSa6rWjnaZfpkr2N6pUMCY6jj2+wf0muUtLySbvU9etX6YqA==
"@types/bootstrap@^5.2.7":
version "5.2.7"
resolved "https://registry.yarnpkg.com/@types/bootstrap/-/bootstrap-5.2.7.tgz#a920df4ea82d8cc605751007f5c9744336842f30"
integrity sha512-vWs0HzobIB8Af2F0B1GXpaVLSVn1NWULDYgTIWp08Et/r2B3aAwwhFBeOs/rRFWJA38EZTXkWP3tepIjpQkpLg==
dependencies:
"@popperjs/core" "^2.9.2"
@ -352,10 +365,10 @@
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb"
integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==
"@types/node@^20.6.0":
version "20.6.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.0.tgz#9d7daa855d33d4efec8aea88cd66db1c2f0ebe16"
integrity sha512-najjVq5KN2vsH2U/xyh2opaSEz6cZMR2SetLIlxlj08nOcmPOemJmUK2o4kUzfLqfrWE0PIrNeE16XhYDd3nqg==
"@types/node@^20.6.2":
version "20.6.2"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.6.2.tgz#a065925409f59657022e9063275cd0b9bd7e1b12"
integrity sha512-Y+/1vGBHV/cYk6OI1Na/LHzwnlNCAfU3ZNGrc1LdRe/LAIbdDPTTv/HU3M7yXN448aTVDq3eKRm2cg7iKLb8gw==
"@types/semver@^7.5.0":
version "7.5.1"
@ -789,10 +802,10 @@ bootstrap-icons-vue@^1.10.3:
resolved "https://registry.yarnpkg.com/bootstrap-icons-vue/-/bootstrap-icons-vue-1.10.3.tgz#ae725513c9655ce86effa2a0b09e9e65b02c8f1a"
integrity sha512-BzqmLufgHjFvSReJ1GQqNkl780UFK0rWT4Y1IQC7lZClXyOSsM5Ipw04BnuVmmrqgtSxzak83jcBwLJgCK3scg==
bootstrap@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.1.tgz#8ca07040ad15d7f75891d1504cf14c5dedfb1cfe"
integrity sha512-jzwza3Yagduci2x0rr9MeFSORjcHpt0lRZukZPZQJT1Dth5qzV7XcgGqYzi39KGAVYR8QEDVoO0ubFKOxzMG+g==
bootstrap@^5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-5.3.2.tgz#97226583f27aae93b2b28ab23f4c114757ff16ae"
integrity sha512-D32nmNWiQHo94BKHLmOrdjlL05q1c8oxbtBphQFb9Z5to6eGRDCm0QgeaZ4zFBHzfg2++rqa2JkqCcxDy0sH0g==
brace-expansion@^1.1.7:
version "1.1.11"
@ -2132,10 +2145,10 @@ safe-regex-test@^1.0.0:
get-intrinsic "^1.1.3"
is-regex "^1.1.4"
sass@^1.66.1:
version "1.66.1"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.66.1.tgz#04b51c4671e4650aa393740e66a4e58b44d055b1"
integrity sha512-50c+zTsZOJVgFfTgwwEzkjA3/QACgdNsKueWPyAR0mRINIvLAStVQBbPg14iuqEQ74NPDbXzJARJ/O4SI1zftA==
sass@^1.67.0:
version "1.67.0"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.67.0.tgz#fed84d74b9cd708db603b1380d6dc1f71bb24f6f"
integrity sha512-SVrO9ZeX/QQyEGtuZYCVxoeAL5vGlYjJ9p4i4HFuekWl8y/LtJ7tJc10Z+ck1c8xOuoBm2MYzcLfTAffD0pl/A==
dependencies:
chokidar ">=3.0.0 <4.0.0"
immutable "^4.0.0"
@ -2471,13 +2484,13 @@ vue-eslint-parser@^9.3.1:
lodash "^4.17.21"
semver "^7.3.6"
vue-i18n@^9.4.0:
version "9.4.0"
resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-9.4.0.tgz#13dd07102fd00da3809c5886e250cb505f071ac1"
integrity sha512-701V7wv6m/Fesbu58rRJv9Rd3en/9F7Nxyn/NiwcR7bJkEfwflMJg5wVezkeHy1tIqjXME1e1zbHhK1dNaR8mg==
vue-i18n@^9.4.1:
version "9.4.1"
resolved "https://registry.yarnpkg.com/vue-i18n/-/vue-i18n-9.4.1.tgz#c7402662fe9b40b17798afffa9d8bfa4734dd7f5"
integrity sha512-vnQyYE9LBuNOqPpETIcCaGnAyLEqfeIvDcyZ9T+WBCWFTqWw1J8FuF1jfeDwpHBi5JKgAwgXyq1mt8jp/x/GPA==
dependencies:
"@intlify/core-base" "9.4.0"
"@intlify/shared" "9.4.0"
"@intlify/core-base" "9.4.1"
"@intlify/shared" "9.4.1"
"@vue/devtools-api" "^6.5.0"
vue-router@^4.2.4:

Binary file not shown.