diff --git a/CMakeLists.txt b/CMakeLists.txt index d1ea3b574..9770fb25a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -694,6 +694,7 @@ list(APPEND VenusQMLModule_CPP_SOURCES src/cpuinfo.cpp src/frameratemodel.h src/frameratemodel.cpp + src/productinfo.h src/quantityinfo.h src/quantityinfo.cpp src/qrangemodel_p.h diff --git a/components/settings/ListAcInError.qml b/components/settings/ListAcInError.qml index 2f1d34505..50415831a 100644 --- a/components/settings/ListAcInError.qml +++ b/components/settings/ListAcInError.qml @@ -11,17 +11,12 @@ ListTextItem { property string bindPrefix - // froniusInverterProductId should always be equal to VE_PROD_ID_PV_INVERTER_FRONIUS - readonly property int froniusInverterProductId: 0xA142 - // carloGavazziEmProductId should always be equal to VE_PROD_ID_CARLO_GAVAZZI_EM - readonly property int carloGavazziEmProductId: 0xB002 - text: CommonWords.error_code dataItem.uid: root.bindPrefix + "/ErrorCode" secondaryText: { - if (productId.value === froniusInverterProductId) { + if (productId.value === ProductInfo.ProductId_PvInverter_Fronius) { return dataItem.value - } else if (productId.value === carloGavazziEmProductId) { + } else if (productId.value === ProductInfo.ProductId_EnergyMeter_CarloGavazzi) { if (dataItem.value === 1) { //: %1 = the error number //% "Front selector locked (%1)" @@ -34,8 +29,8 @@ ListTextItem { } return "" } - allowed: productId.value === froniusInverterProductId - || productId.value === carloGavazziEmProductId + allowed: productId.value === ProductInfo.ProductId_PvInverter_Fronius + || productId.value === ProductInfo.ProductId_EnergyMeter_CarloGavazzi VeQuickItem { diff --git a/data/common/Tank.qml b/data/common/Tank.qml index 6e5b71f67..7ae8d9fb5 100644 --- a/data/common/Tank.qml +++ b/data/common/Tank.qml @@ -87,7 +87,7 @@ Device { } } - name: productId === 0xA160 + name: productId === ProductInfo.ProductId_TankSensor_Generic // This must be a generic Victron tank sensor, where the product name is always "Tank // sensor" and there is no custom name, so use the tank type to provide a meaningful name. ? Gauges.tankProperties(type).name diff --git a/data/mock/AcInputsImpl.qml b/data/mock/AcInputsImpl.qml index 44bd193f8..518210eaa 100644 --- a/data/mock/AcInputsImpl.qml +++ b/data/mock/AcInputsImpl.qml @@ -27,7 +27,7 @@ QtObject { customName: "Genset AC input", connected: 1, phaseCount: 3, - productId: 0xB040, // fisher panda + productId: ProductInfo.ProductId_Genset_FischerPanda, } setInputs([ gridInput, generatorInput ]) } diff --git a/data/mock/DcInputsImpl.qml b/data/mock/DcInputsImpl.qml index e731c31dc..d679f7454 100644 --- a/data/mock/DcInputsImpl.qml +++ b/data/mock/DcInputsImpl.qml @@ -56,7 +56,7 @@ QtObject { } if (props.serviceType === "alternator" && props.productId === undefined) { // Set a generic product id so that PageAlternator can show a valid page. - input._productId.setValue(0xB091) + input._productId.setValue(ProductInfo.ProductId_Alternator_Generic) } _createdObjects.push(input) } @@ -92,7 +92,7 @@ QtObject { } onProductIdChanged: { - if (productId === 0xA3F0) { + if (productId === ProductInfo.ProductId_OrionXs_Min) { initOrionXSValues() } } diff --git a/data/mock/config/BriefAndOverviewPageConfig.qml b/data/mock/config/BriefAndOverviewPageConfig.qml index e87e641be..9be9a0e1d 100644 --- a/data/mock/config/BriefAndOverviewPageConfig.qml +++ b/data/mock/config/BriefAndOverviewPageConfig.qml @@ -179,7 +179,7 @@ QtObject { { name: "Multiple alternators (including Orion XS), no AC/DC inputs", acInputs: [emptyAcInput, emptyAcInput], - dcInputs: { types: [ { serviceType: "alternator", productId: 0xA3F0 }, { serviceType: "alternator" } ] }, + dcInputs: { types: [ { serviceType: "alternator", productId: ProductInfo.ProductId_OrionXs_Min }, { serviceType: "alternator" } ] }, }, { name: "Shore and Generator, Shore active", diff --git a/pages/settings/devicelist/ac-in/PageAcIn.qml b/pages/settings/devicelist/ac-in/PageAcIn.qml index feefd8091..eb8a0a0a5 100644 --- a/pages/settings/devicelist/ac-in/PageAcIn.qml +++ b/pages/settings/devicelist/ac-in/PageAcIn.qml @@ -11,20 +11,13 @@ Page { property string bindPrefix - // Genset productids - readonly property int fisherPandaProductId: 0xB040 - readonly property int comApProductId: 0xB044 - readonly property int dseProductId: 0xB046 - readonly property int creProductId: 0xB048 - readonly property int deifProductId: 0xB049 - VeQuickItem { id: productIdDataItem uid: root.bindPrefix + "/ProductId" onValueChanged: { if (value !== undefined && modelLoader.status === Loader.Null) { - if ([fisherPandaProductId, comApProductId, dseProductId, creProductId, deifProductId].indexOf(value) > -1) { + if (ProductInfo.isGensetProduct(value)) { modelLoader.sourceComponent = gensetModelComponent } else { modelLoader.sourceComponent = defaultModelComponent diff --git a/pages/settings/devicelist/ac-in/PageAcInModelDefault.qml b/pages/settings/devicelist/ac-in/PageAcInModelDefault.qml index 292909e69..c38610443 100644 --- a/pages/settings/devicelist/ac-in/PageAcInModelDefault.qml +++ b/pages/settings/devicelist/ac-in/PageAcInModelDefault.qml @@ -12,21 +12,16 @@ ObjectModel { property string bindPrefix property int productId - // froniusInverterProductId should always be equal to VE_PROD_ID_PV_INVERTER_FRONIUS - readonly property int froniusInverterProductId: 0xA142 - // carloGavazziEmProductId should always be equal to VE_PROD_ID_CARLO_GAVAZZI_EM - readonly property int carloGavazziEmProductId: 0xB002 - readonly property var nrOfPhases: VeQuickItem { uid: root.bindPrefix + "/NrOfPhases" } ListTextItem { text: CommonWords.status - dataItem.uid: root.productId === froniusInverterProductId + dataItem.uid: root.productId === ProductInfo.ProductId_PvInverter_Fronius ? root.bindPrefix + "/StatusCode" : "" - allowed: root.productId === froniusInverterProductId + allowed: root.productId === ProductInfo.ProductId_PvInverter_Fronius secondaryText: Global.pvInverters.statusCodeToText(dataItem.value) } diff --git a/pages/settings/devicelist/ac-in/PageAcInSetup.qml b/pages/settings/devicelist/ac-in/PageAcInSetup.qml index 2199a4cc4..4fc9907be 100644 --- a/pages/settings/devicelist/ac-in/PageAcInSetup.qml +++ b/pages/settings/devicelist/ac-in/PageAcInSetup.qml @@ -11,9 +11,6 @@ Page { property string bindPrefix - property int em24ProductId: 0xb017 - property int smappeeProductId: 0xb018 - /* * This is a bit weird, when changing the role in a cgwacs service, it will * directly disconnect, without a reply or signal that the value changed. So @@ -100,7 +97,7 @@ Page { ListRadioButtonGroup { //% "Phase configuration" text: qsTrId("ac-in-setup_phase_configuration") - allowed: productId.value == em24ProductId + allowed: productId.value == ProductInfo.ProductId_EnergyMeter_Em24 dataItem.uid: root.bindPrefix + "/PhaseConfig" enabled: !em24Locked() optionModel: [ @@ -116,14 +113,14 @@ Page { id: em24SwitchPos //% "Switch position" text: qsTrId("ac-in-setup_switch_position") - allowed: productId.value == em24ProductId + allowed: productId.value == ProductInfo.ProductId_EnergyMeter_Em24 dataItem.uid: root.bindPrefix + "/SwitchPos" secondaryText: dataItem.isValid ? em24SwitchText(dataItem.value) : "--" } ListLabel { text: qsTr("Set the switch in an unlocked position to modify the settings.") - allowed: productId.value == em24ProductId && em24Locked() + allowed: productId.value == ProductInfo.ProductId_EnergyMeter_Em24 && em24Locked() } /* Smappee settings */ @@ -131,7 +128,7 @@ Page { ListRadioButtonGroup { //% "Phase configuration" text: qsTrId("ac-in-setup_phase_configuration") - allowed: productId.value == smappeeProductId + allowed: productId.value == ProductInfo.ProductId_PowerBox_Smappee dataItem.uid: root.bindPrefix + "/PhaseConfig" optionModel: [ //% "Single phase" @@ -145,7 +142,7 @@ Page { ListNavigationItem { text: CommonWords.current_transformers - allowed: productId.value == smappeeProductId + allowed: productId.value == ProductInfo.ProductId_PowerBox_Smappee onClicked: { Global.pageManager.pushPage("/pages/settings/devicelist/ac-in/PageSmappeeCTList.qml", { "title": text, "bindPrefix": root.bindPrefix }) @@ -155,7 +152,7 @@ Page { ListNavigationItem { //% "Devices" text: qsTrId("ac-in-setup_devices") - allowed: productId.value == smappeeProductId + allowed: productId.value == ProductInfo.ProductId_PowerBox_Smappee onClicked: { Global.pageManager.pushPage("/pages/settings/devicelist/ac-in/PageSmappeeDeviceList.qml", { "bindPrefix": root.bindPrefix }) diff --git a/pages/settings/devicelist/battery/PageBattery.qml b/pages/settings/devicelist/battery/PageBattery.qml index c31f962e2..dbe6f1b1b 100644 --- a/pages/settings/devicelist/battery/PageBattery.qml +++ b/pages/settings/devicelist/battery/PageBattery.qml @@ -11,8 +11,8 @@ Page { property var battery - readonly property bool isFiamm48TL: productId.value === 0xB012 - readonly property bool isParallelBms: productId.value === 0xA3E3 + readonly property bool isFiamm48TL: productId.value === ProductInfo.ProductId_Battery_Fiamm48TL + readonly property bool isParallelBms: productId.value === ProductInfo.ProductId_Battery_ParallelBms title: battery.name diff --git a/pages/settings/devicelist/dc-in/PageAlternator.qml b/pages/settings/devicelist/dc-in/PageAlternator.qml index 4d3bbec4d..f62c5b293 100644 --- a/pages/settings/devicelist/dc-in/PageAlternator.qml +++ b/pages/settings/devicelist/dc-in/PageAlternator.qml @@ -11,31 +11,13 @@ Page { property string bindPrefix - // wakespeedProductId should always be equal to VE_PROD_ID_WAKESPEED_WS500 - readonly property int wakespeedProductId: 0xB080 - readonly property int arcoProductId: 0xB090 - readonly property int mgAfcProductId: 0xB0F0 - readonly property int genericProductId: 0xB091 - readonly property int integrelProductId: 0xB092 - readonly property int orionXsProductIdMin: 0xA3F0 - readonly property int orionXsProductIdMax: 0xA3FF - - function isRealAlternator(productId) { - const alternators = [arcoProductId, wakespeedProductId, mgAfcProductId, genericProductId, integrelProductId] - return alternators.indexOf(productId) > -1 - } - - function isOrionXsAlternator(productId) { - return productId >= orionXsProductIdMin && productId <= orionXsProductIdMax - } - VeQuickItem { id: productIdDataItem uid: root.bindPrefix + "/ProductId" onValueChanged: { if (value !== undefined && modelLoader.status === Loader.Null) { - if (isRealAlternator(value) || isOrionXsAlternator(value)) { + if (ProductInfo.isRealAlternatorProduct(value) || ProductInfo.isOrionXsProduct(value)) { modelLoader.sourceComponent = alternatorModelComponent } else { modelLoader.sourceComponent = dcMeterModelComponent diff --git a/src/productinfo.h b/src/productinfo.h new file mode 100644 index 000000000..8b3fc921f --- /dev/null +++ b/src/productinfo.h @@ -0,0 +1,94 @@ +/* +** Copyright (C) 2024 Victron Energy B.V. +** See LICENSE.txt for license information. +*/ + +#ifndef VICTRON_VENUSOS_GUI_V2_PRODUCTINFO_H +#define VICTRON_VENUSOS_GUI_V2_PRODUCTINFO_H + +#include +#include + +namespace Victron { +namespace VenusOS { + +class ProductInfo : public QObject +{ + Q_OBJECT + QML_ELEMENT + QML_SINGLETON + +public: + explicit ProductInfo(QObject * = nullptr) {} + ~ProductInfo() override {} + + enum ProductId_Alternator { + ProductId_Alternator_Wakespeed = 0xB080, // VE_PROD_ID_WAKESPEED_WS500 + ProductId_Alternator_Arco = 0xB090, + ProductId_Alternator_MgAfc = 0xB0F0, + ProductId_Alternator_Generic = 0xB091, + ProductId_Alternator_Integrel = 0xB092, + }; + Q_ENUM(ProductId_Alternator) + + enum ProductId_Battery { + ProductId_Battery_Fiamm48TL = 0xB012, + ProductId_Battery_ParallelBms = 0xA3E3, + }; + Q_ENUM(ProductId_Battery) + + enum ProductId_Genset { + ProductId_Genset_FischerPanda = 0xB040, + ProductId_Genset_ComAp = 0xB044, + ProductId_Genset_Dse = 0xB046, + ProductId_Genset_Cre = 0xB048, + ProductId_Genset_Deif = 0xB049, + }; + Q_ENUM(ProductId_Genset) + + enum ProductId_Misc { + ProductId_EnergyMeter_CarloGavazzi = 0xB002, // VE_PROD_ID_CARLO_GAVAZZI_EM + ProductId_EnergyMeter_Em24 = 0xB017, + ProductId_OrionXs_Min = 0xA3F0, + ProductId_OrionXs_Max = 0xA3FF, + ProductId_PowerBox_Smappee = 0xB018, + ProductId_PvInverter_Fronius = 0xA142, // VE_PROD_ID_PV_INVERTER_FRONIUS + ProductId_TankSensor_Generic = 0xA160, + }; + Q_ENUM(ProductId_Misc) + + Q_INVOKABLE bool isGensetProduct(int productId) { + switch (productId) { + case ProductId_Genset_FischerPanda: + case ProductId_Genset_ComAp: + case ProductId_Genset_Dse: + case ProductId_Genset_Cre: + case ProductId_Genset_Deif: + return true; + default: + return false; + }; + } + + Q_INVOKABLE bool isOrionXsProduct(int productId) { + return productId >= ProductId_OrionXs_Min && productId <= ProductId_OrionXs_Max; + } + + Q_INVOKABLE bool isRealAlternatorProduct(int productId) { + switch (productId) { + case ProductId_Alternator_Arco: + case ProductId_Alternator_Wakespeed: + case ProductId_Alternator_MgAfc: + case ProductId_Alternator_Generic: + case ProductId_Alternator_Integrel: + return true; + default: + return false; + }; + } +}; + +} +} + +#endif // VICTRON_VENUSOS_GUI_V2_PRODUCTINFO_H