316 lines
9.9 KiB
C++
316 lines
9.9 KiB
C++
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
*
|
|
* Copyright (C) 2013 - 2024, nymea GmbH
|
|
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
|
|
*
|
|
* This file is part of nymea-plugins.
|
|
*
|
|
* nymea-plugins is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* nymea-plugins is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with nymea-plugins. If not, see <https://www.gnu.org/licenses/>.
|
|
*
|
|
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
|
|
|
#include "kebaproductinfo.h"
|
|
#include "extern-plugininfo.h"
|
|
|
|
KebaProductInfo::KebaProductInfo(const QString &productString) :
|
|
m_productString(productString)
|
|
{
|
|
// Examples
|
|
|
|
// BMW-10-EC240522-E1R
|
|
// KC-P30-EC240122-E0R
|
|
// KC-P30-EC220112-000-DE
|
|
// KC-P30-EC2404B2-M0A-GE
|
|
// KC-P30-EC2204U2-E00-PV
|
|
// KC-P30-ESS400U2-E00-PV (PV-Edition, Shutter T2, 32A, triphasé, marché FR)
|
|
|
|
qCDebug(dcKeba()) << "Parsing product information from" << productString.count() << productString;
|
|
if (m_productString.count() < 19) {
|
|
qCWarning(dcKeba()) << "Invalid product information string size for" << productString << ". Cannot parse.";
|
|
m_isValid = false;
|
|
return;
|
|
}
|
|
|
|
QStringList subStrings = productString.split('-');
|
|
if (subStrings.count() < 4) {
|
|
qCWarning(dcKeba()) << "Invalid product information format" << subStrings << ". Cannot parse" << productString;
|
|
m_isValid = false;
|
|
return;
|
|
}
|
|
|
|
// 1. Manufacturer
|
|
// 2. Model
|
|
// 3. Desciptor
|
|
// 4. Meter infos
|
|
|
|
// Parse the product string according to Keba Product code definitions
|
|
m_manufacturer = subStrings.at(0);
|
|
if (m_manufacturer == "KC") {
|
|
m_manufacturer = "KeConnect";
|
|
}
|
|
qCDebug(dcKeba()) << "Manufacturer:" << m_manufacturer;
|
|
m_model = subStrings.at(1);
|
|
qCDebug(dcKeba()) << "Model:" << m_model;
|
|
|
|
QString descriptor = subStrings.at(2); // EC240522
|
|
m_countryCode = descriptor.at(0); // E
|
|
qCDebug(dcKeba()) << "Country:" << m_countryCode;
|
|
|
|
QChar connectorValue = descriptor.at(1);
|
|
if (connectorValue.toLower() == QChar('s')) {
|
|
m_connector = ConnectorSocket;
|
|
qCDebug(dcKeba()) << "Connector: Socket";
|
|
} else if (connectorValue.toLower() == QChar('c')) {
|
|
m_connector = ConnectorCable;
|
|
qCDebug(dcKeba()) << "Connector: Cable";
|
|
} else {
|
|
m_isValid = false;
|
|
return;
|
|
}
|
|
|
|
QChar connectorTypeValue = descriptor.at(2);
|
|
if (connectorTypeValue.isDigit() && connectorTypeValue == QChar('1')) {
|
|
m_connectorType = Type1;
|
|
} else if (connectorTypeValue.isDigit() && connectorTypeValue == QChar('2')) {
|
|
m_connectorType = Type2;
|
|
} else if (connectorTypeValue.toLower() == QChar('s')) {
|
|
m_connectorType = Shutter;
|
|
} else {
|
|
m_isValid = false;
|
|
return;
|
|
}
|
|
|
|
qCDebug(dcKeba()) << "Connector type:" << m_connectorType;
|
|
|
|
QChar connectorCurrentValue = descriptor.at(3);
|
|
if (m_connectorType == Shutter) {
|
|
// Shutter: le courant est encodé directement en position 3
|
|
// (indépendant de connectorTypeValue qui vaut 'S')
|
|
if (connectorCurrentValue == QChar('4')) {
|
|
m_current = Current32A;
|
|
qCDebug(dcKeba()) << "Current (Shutter): 32A";
|
|
} else if (connectorCurrentValue == QChar('3')) {
|
|
m_current = Current20A;
|
|
qCDebug(dcKeba()) << "Current (Shutter): 20A";
|
|
} else if (connectorCurrentValue == QChar('2')) {
|
|
m_current = Current16A;
|
|
qCDebug(dcKeba()) << "Current (Shutter): 16A";
|
|
} else if (connectorCurrentValue == QChar('1')) {
|
|
m_current = Current13A;
|
|
qCDebug(dcKeba()) << "Current (Shutter): 13A";
|
|
} else {
|
|
qCWarning(dcKeba()) << "Current (Shutter): valeur inconnue" << connectorCurrentValue;
|
|
m_isValid = false;
|
|
return;
|
|
}
|
|
} else if (connectorCurrentValue.isDigit() && connectorTypeValue == QChar('1')) {
|
|
m_current = Current13A;
|
|
} else if (connectorCurrentValue.isDigit() && connectorTypeValue == QChar('2')) {
|
|
m_current = Current16A;
|
|
} else if (connectorCurrentValue.isDigit() && connectorTypeValue == QChar('3')) {
|
|
m_current = Current20A;
|
|
} else if (connectorCurrentValue.isDigit() && connectorTypeValue == QChar('4')) {
|
|
m_current = Current32A;
|
|
} else {
|
|
m_isValid = false;
|
|
return;
|
|
}
|
|
|
|
qCDebug(dcKeba()) << "Current:" << m_current;
|
|
|
|
// KC-P30-EC24 01 22-E0R
|
|
QString cableValue = descriptor.mid(4, 2);
|
|
if (cableValue == "00") {
|
|
m_cable = NoCable;
|
|
qCDebug(dcKeba()) << "Cable: No cable";
|
|
} else if (cableValue == "01") {
|
|
m_cable = Cable4m;
|
|
qCDebug(dcKeba()) << "Cable: 4 meter";
|
|
} else if (cableValue == "05") {
|
|
m_cable = Cable5m;
|
|
qCDebug(dcKeba()) << "Cable: 5 meter";
|
|
} else if (cableValue == "04") {
|
|
m_cable = Cable6m;
|
|
qCDebug(dcKeba()) << "Cable: 6 meter";
|
|
} else if (cableValue == "07") {
|
|
m_cable = Cable5p5m;
|
|
qCDebug(dcKeba()) << "Cable: 5.5 meter";
|
|
} else {
|
|
m_isValid = false;
|
|
return;
|
|
}
|
|
|
|
// KC-P30-EC2401 2 2-E0R
|
|
QChar seriesValue = descriptor.at(6);
|
|
if (seriesValue == QChar('0')) {
|
|
m_series = SeriesE;
|
|
qCDebug(dcKeba()) << "Series: E";
|
|
} else if (seriesValue == QChar('1')) {
|
|
m_series = SeriesB;
|
|
qCDebug(dcKeba()) << "Series: B";
|
|
} else if (seriesValue == QChar('2')) {
|
|
m_series = SeriesC;
|
|
qCDebug(dcKeba()) << "Series: C";
|
|
} else if (seriesValue == QChar('3')) {
|
|
m_series = SeriesA;
|
|
qCDebug(dcKeba()) << "Series: A";
|
|
} else if (seriesValue.toLower() == QChar('b')) {
|
|
m_series = SeriesXWlan;
|
|
qCDebug(dcKeba()) << "Series: X (Wlan)";
|
|
} else if (seriesValue.toLower() == QChar('c')) {
|
|
m_series = SeriesXWlan3G;
|
|
qCDebug(dcKeba()) << "Series: X (Wlan + 3G)";
|
|
} else if (seriesValue.toLower() == QChar('e')) {
|
|
m_series = SeriesXWlan4G;
|
|
qCDebug(dcKeba()) << "Series: X (Wlan + 4G)";
|
|
} else if (seriesValue.toLower() == QChar('g')) {
|
|
m_series = SeriesX3G;
|
|
qCDebug(dcKeba()) << "Series: X (3G)";
|
|
} else if (seriesValue.toLower() == QChar('h')) {
|
|
m_series = SeriesX4G;
|
|
qCDebug(dcKeba()) << "Series: X (4G)";
|
|
} else if (seriesValue.toLower() == QChar('u')) {
|
|
m_series = SeriesSpecial;
|
|
qCDebug(dcKeba()) << "Series: Special" + m_productString.right(2);
|
|
} else {
|
|
qCWarning(dcKeba()) << "Series: Unknown" << productString << "value:" << seriesValue;
|
|
m_isValid = false;
|
|
return;
|
|
}
|
|
|
|
// KC-P30-EC24012 2 -E0R
|
|
QChar phaseCountValue = descriptor.at(7);
|
|
if (phaseCountValue == QChar('1')) {
|
|
m_phaseCount = 1;
|
|
} else if (phaseCountValue == QChar('2')) {
|
|
m_phaseCount = 3;
|
|
} else {
|
|
m_isValid = false;
|
|
return;
|
|
}
|
|
|
|
qCDebug(dcKeba()) << "Phases:" << m_phaseCount;
|
|
|
|
// Meter infos
|
|
QString meterInfos = subStrings.at(3);
|
|
|
|
QChar meterValue = meterInfos.at(0);
|
|
if (meterValue == QChar('0')) {
|
|
m_meter = NoMeter;
|
|
qCDebug(dcKeba()) << "Meter: No meter";
|
|
} else if (meterValue.toLower() == QChar('e')) {
|
|
m_meter = MeterNotCalibrated;
|
|
qCDebug(dcKeba()) << "Meter: Not calibrated meter";
|
|
} else if (meterValue.toLower() == QChar('m')) {
|
|
m_meter = MeterCalibrated;
|
|
qCDebug(dcKeba()) << "Meter: Calibrated meter";
|
|
} else if (meterValue.toLower() == QChar('l')) {
|
|
m_meter = MeterCalibratedNationalCertified;
|
|
qCDebug(dcKeba()) << "Meter: Calibrated meter (national certified)";
|
|
} else {
|
|
m_isValid = false;
|
|
return;
|
|
}
|
|
|
|
QChar authValue = meterInfos.at(2);
|
|
if (authValue == QChar('0')) {
|
|
m_authorization = NoAuthorization;
|
|
qCDebug(dcKeba()) << "Authorization: No authorization";
|
|
} else if (authValue.toLower() == QChar('r')) {
|
|
m_authorization = Rfid;
|
|
qCDebug(dcKeba()) << "Authorization: RFID";
|
|
} else if (authValue.toLower() == QChar('k')) {
|
|
m_authorization = Key;
|
|
qCDebug(dcKeba()) << "Authorization: Key";
|
|
} else {
|
|
// Note: we don't require this info, so we don't mark it as invalid.
|
|
qCDebug(dcKeba()) << "Authorization: Unknown" << authValue;
|
|
}
|
|
|
|
m_germanEdition = m_productString.toUpper().endsWith("DE");
|
|
qCDebug(dcKeba()) << "German Edition:" << m_germanEdition;
|
|
}
|
|
|
|
bool KebaProductInfo::isValid() const
|
|
{
|
|
return m_isValid;
|
|
}
|
|
|
|
QString KebaProductInfo::productString() const
|
|
{
|
|
return m_productString;
|
|
}
|
|
|
|
QString KebaProductInfo::manufacturer() const
|
|
{
|
|
return m_manufacturer;
|
|
}
|
|
|
|
QString KebaProductInfo::model() const
|
|
{
|
|
return m_model;
|
|
}
|
|
|
|
QString KebaProductInfo::countryCode() const
|
|
{
|
|
return m_countryCode;
|
|
}
|
|
|
|
KebaProductInfo::Connector KebaProductInfo::connector() const
|
|
{
|
|
return m_connector;
|
|
}
|
|
|
|
KebaProductInfo::ConnectorType KebaProductInfo::connectorType() const
|
|
{
|
|
return m_connectorType;
|
|
}
|
|
|
|
KebaProductInfo::ConnectorCurrent KebaProductInfo::current() const
|
|
{
|
|
return m_current;
|
|
}
|
|
|
|
KebaProductInfo::Cable KebaProductInfo::cable() const
|
|
{
|
|
return m_cable;
|
|
}
|
|
|
|
KebaProductInfo::Series KebaProductInfo::series() const
|
|
{
|
|
return m_series;
|
|
}
|
|
|
|
int KebaProductInfo::phaseCount() const
|
|
{
|
|
return m_phaseCount;
|
|
}
|
|
|
|
KebaProductInfo::Meter KebaProductInfo::meter() const
|
|
{
|
|
return m_meter;
|
|
}
|
|
|
|
KebaProductInfo::Authorization KebaProductInfo::authorization() const
|
|
{
|
|
return m_authorization;
|
|
}
|
|
|
|
bool KebaProductInfo::germanEdition() const
|
|
{
|
|
return m_germanEdition;
|
|
}
|