diff --git a/firmware/Venus_Release/VenusReleaseFiles/PageChargingStrategy.qml b/firmware/Venus_Release/VenusReleaseFiles/PageChargingStrategy.qml new file mode 100644 index 000000000..9a47adfc7 --- /dev/null +++ b/firmware/Venus_Release/VenusReleaseFiles/PageChargingStrategy.qml @@ -0,0 +1,321 @@ +import QtQuick 1.1 +import com.victron.velib 1.0 +import "utils.js" as Utils + + +MbPage { + property string cgwacsPath: "com.victronenergy.settings/Settings/CGwacs" + property string settingsPrefix: "com.victronenergy.settings" + property string batteryLifePath: cgwacsPath + "/BatteryLife" + // Hub4Mode + property int hub4PhaseCompensation: 1 + property int hub4PhaseSplit: 2 + property int hub4Disabled: 3 + + property bool initialized: false + + property VBusItem lastEoc: VBusItem { bind: "com.victronenergy.settings/Settings/Controller/LastEOC" } + property int previousEocValue: -1 + property bool isCalibrationActive: false + + title: qsTr("Charging Strategy") + + Component.onCompleted: { + initialized = true + } + + VBusItem { + id: controllerState + bind: "com.victronenergy.controller/State" + } + + VBusItem { + id: systemType + bind: "com.victronenergy.system/SystemType" + } + + VBusItem { + id: gridSetpoint + bind: "com.victronenergy.settings/Settings/CGwacs/AcPowerSetPoint" + } + + VBusItem { + id: maxChargePowerItem + bind: Utils.path(cgwacsPath, "/MaxChargePower") + } + + VBusItem { + id: maxDischargePowerItem + bind: Utils.path(cgwacsPath, "/MaxDischargePower") + } + + VBusItem { + id: socLimitItem + bind: Utils.path(batteryLifePath, "/SocLimit") + } + + VBusItem { + id: minSocLimitItem + bind: Utils.path(batteryLifePath, "/MinimumSocLimit") + } + + VBusItem { + id: stateItem + bind: Utils.path(batteryLifePath, "/State") + } + + + model: hub4Settings + + VisualItemModel { + id: hub4Settings + + MbItemOptions { + id: chargingState + description: qsTr("Charging state") + readonly: true + bind: "com.victronenergy.controller/State" + possibleValues:[ + MbOption { description: qsTr("Unknown"); value: 0 }, + MbOption { description: qsTr("Heating"); value: 1 }, + MbOption { description: qsTr("Optimize self-consumption"); value: 2 }, + MbOption { description: qsTr("Calibration charge"); value: 3 }, + MbOption { description: qsTr("Hold min SOC"); value: 4 }, + MbOption { description: qsTr("Charge to min SOC"); value: 5 }, + MbOption { description: qsTr("Bridge grid blackout"); value: 6 }, + MbOption { description: qsTr("Limit discharge power"); value: 7 }, + MbOption { description: qsTr("Scheduled charge"); value: 8 }, + MbOption { description: qsTr("Limit charge power"); value: 9 }, + MbOption { description: qsTr("No grid meter available"); value: 10 }, + MbOption { description: qsTr("No battery available"); value: 11 }, + MbOption { description: qsTr("No inverter available"); value: 12 } + ] + } + + MbItemOptionsKnown { + id: timeToEoc + description: qsTr("Time to calibration charge") + readonly: true + bind: "com.victronenergy.controller/TimeToCalibrationCharge" + possibleValues:[ + MbOption { description: qsTr("Now"); value: "now" } + ] + } + + MbEditBoxTime { + id: startTime + description: qsTr("Calibration charge start time (hh:mm)") + item.bind: "com.victronenergy.settings/Settings/Controller/CalibrationChargeStartTime" + writeAccessLevel: User.AccessUser + } + + MbOK { + id: eoctime + description: qsTr("Start calibration charge now?") + writeAccessLevel: User.AccessUser + value: isCalibrationActive ? qsTr("Calibration charge started") : qsTr("Press here") + show: true + onClicked: { + console.log("Button clicked. Current controllerState: " + controllerState.value); + + if (controllerState.value !== 3 && controllerState.value !== 11 && !isCalibrationActive) { + console.log("Starting calibration charge..."); + // Save current lastEoc value as previousEocValue + if (previousEocValue === -1) { + previousEocValue = lastEoc.value; + console.log("Previous EOC Value saved: " + previousEocValue); + } + lastEoc.setValue(0); // Set lastEoc to 0 to start the calibration charge + console.log("Set lastEoc to 0"); + isCalibrationActive = true; + } else if (controllerState.value === 3 && isCalibrationActive) { + console.log("Stopping calibration charge..."); + // Revert lastEoc to its previous value + if (previousEocValue !== -1) { + lastEoc.setValue(previousEocValue); + console.log("Reverted lastEoc to previous value: " + previousEocValue); + previousEocValue = -1; // Reset the previousEocValue + } else { + console.warn("No previous EOC value recorded."); + } + isCalibrationActive = false; + } else { + isCalibrationActive = false; + } + + // Update value + eoctime.value = isCalibrationActive ? qsTr("Calibration charge started") : qsTr("Press here"); + + } + } + + MbSpinBox { + description: qsTr("Grid setpoint") + //show: hub4Mode.value !== hub4Disabled && stateItem.value !== batteryKeepCharged #we don't depend on hub4Mode anymore + show: true + userHasWriteAccess: true + bind: "com.victronenergy.settings/Settings/CGwacs/AcPowerSetPoint" + numOfDecimals: 0 + unit: "W" + stepSize: 100 + } + + MbSpinBox { + id: minSocLimit + description: qsTr("Minimum SOC (unless grid fails)") + userHasWriteAccess: true + //show: hub4Mode.value !== hub4Disabled && stateItem.value !== batteryKeepCharged #we don't depend on hub4Mode anymore + show: true + bind: Utils.path(batteryLifePath, "/MinimumSocLimit") + numOfDecimals: 0 + unit: "%" + min: 0 + max: 100 + stepSize: 5 + } + + MbSwitch { + id: withoutGridMeter + name: qsTr("Grid meter installed") + userHasWriteAccess: true + enabled: true + bind: Utils.path(cgwacsPath, '/RunWithoutGridMeter') + //show: hub4Mode.value !== hub4Disabled #we don't depend on hub4Mode anymore + show: true + invertSense: true + } + + MbSwitch { + bind: Utils.path(settingsPrefix, "/Settings/SystemSetup/HasAcOutSystem") + name: qsTr("Inverter AC output in use") + show: withoutGridMeter.checked + userHasWriteAccess: true + enabled: true + } + +/* MbSwitch { //auskommentiert for possible future use + VBusItem { + id: vebusPath + bind: "com.victronenergy.system/VebusService" + } + VBusItem { + id: doNotFeedInvOvervoltage + bind: Utils.path(vebusPath.value, "/Hub4/DoNotFeedInOvervoltage") + } + name: qsTr("Feed-in excess solarcharger power") + bind: Utils.path(settingsPrefix, "/Settings/CGwacs/OvervoltageFeedIn") + show: hub4Mode.value !== hub4Disabled && doNotFeedInvOvervoltage.valid + userHasWriteAccess: true + enabled: true + }*/ + + MbSwitch { + id: maxChargePowerSwitch + name: qsTr("Limit the charge power") + checked: maxChargePowerItem.value >= 0 + userHasWriteAccess: true + enabled: true + //show: hub4Mode.value !== hub4Disabled && !(maxChargeCurrentControl.valid && maxChargeCurrentControl.value) #we don't depend on hub4Mode anymore + show: true + onCheckedChanged: { + if (checked && maxChargePowerItem.value < 0) + maxChargePowerItem.setValue(1000) + else if (!checked && maxChargePowerItem.value >= 0) + maxChargePowerItem.setValue(-1) + } + } + + MbSpinBox { + id: maxChargePower + description: qsTr("Maximum charge power") + userHasWriteAccess: true + show: maxChargePowerSwitch.show && maxChargePowerSwitch.checked + bind: Utils.path(cgwacsPath, "/MaxChargePower") + numOfDecimals: 0 + unit: "W" + min: 0 + max: 200000 + stepSize: 50 + } + + MbSwitch { + id: maxInverterPowerSwitch + name: qsTr("Limit the discharge power") + checked: maxDischargePowerItem.value >= 0 + userHasWriteAccess: true + enabled: true + //show: hub4Mode.value !== hub4Disabled && stateItem.value !== batteryKeepCharged #we don't depend on hub4Mode anymore + show: true + onCheckedChanged: { + if (checked && maxDischargePowerItem.value < 0) + maxDischargePowerItem.setValue(1000) + else if (!checked && maxDischargePowerItem.value >= 0) + maxDischargePowerItem.setValue(-1) + } + } + + MbSpinBox { + id: maxDischargePower + description: qsTr("Maximum discharge power") + userHasWriteAccess: true + show: maxInverterPowerSwitch.show && maxInverterPowerSwitch.checked + bind: Utils.path(cgwacsPath, "/MaxDischargePower") + numOfDecimals: 0 + unit: "W" + min: 0 + max: 300000 + stepSize: 50 + } + + MbSwitch { + name: qsTr("Fronius Zero feed-in") + bind: Utils.path(cgwacsPath, "/PreventFeedback") + //show: hub4Mode.value !== hub4Disabled #we don't depend on hub4Mode anymore + show: true + userHasWriteAccess: true + } + + MbItemValue { + VBusItem { + id: pvPowerLimiterActive + bind: "com.victronenergy.hub4/PvPowerLimiterActive" + } + description: qsTr("Fronius Zero feed-in active") + //show: hub4Mode.value !== hub4Disabled && pvPowerLimiterActive.valid #we don't depend on hub4Mode anymore + show: pvPowerLimiterActive.valid + item.value: pvPowerLimiterActive.value === 0 ? qsTr("No") : qsTr("Yes") + } + + // TODO, support scheduled charging + + MbSubMenu { + id: scheduleSettings + property string bindPrefix: "com.victronenergy.settings/Settings/CGwacs/BatteryLife/Schedule/Charge/" + description: qsTr("Scheduled charging") + //show: hub4Mode.value !== hub4Disabled #we don't depend on hub4Mode anymore + show: true + subpage: Component { + MbPage { + title: scheduleSettings.description + model: VisualItemModel { + ChargeScheduleItem { bindPrefix: scheduleSettings.bindPrefix; scheduleNumber: 0 } + ChargeScheduleItem { bindPrefix: scheduleSettings.bindPrefix; scheduleNumber: 1 } + ChargeScheduleItem { bindPrefix: scheduleSettings.bindPrefix; scheduleNumber: 2 } + ChargeScheduleItem { bindPrefix: scheduleSettings.bindPrefix; scheduleNumber: 3 } + ChargeScheduleItem { bindPrefix: scheduleSettings.bindPrefix; scheduleNumber: 4 } + } + } + } + } + + + MbSubMenu { + id: deviceItem + description: qsTr("Debug") + show: user.accessLevel >= User.AccessService + subpage: Component { + PageHub4Debug { } + } + } + } +} diff --git a/firmware/Venus_Release/VenusReleaseFiles/rc.local b/firmware/Venus_Release/VenusReleaseFiles/rc.local index 60179e120..a9e86d170 100644 --- a/firmware/Venus_Release/VenusReleaseFiles/rc.local +++ b/firmware/Venus_Release/VenusReleaseFiles/rc.local @@ -41,6 +41,9 @@ fi echo "Copying battery folder from /data to /opt/victronenergy/ ..." cp -r "$source_dir" "$destination_dir_upper" +# Set toggle calibration charge button +cp /data/PageChargingStrategy.qml /opt/victronenergy/gui/qml + # # Set VPN # echo "Running VPN service..." # find /opt/innovenergy/openvpn -type f -exec chmod 777 {} \; diff --git a/firmware/Venus_Release/update_Venus.py b/firmware/Venus_Release/update_Venus.py index b017e641f..b97e20641 100644 --- a/firmware/Venus_Release/update_Venus.py +++ b/firmware/Venus_Release/update_Venus.py @@ -42,6 +42,7 @@ async def upload_files(remote_host): file_location_mappings = { "rc.local": "/data/", "dbus-fzsonick-48tl": "/data/", + "PageChargingStrategy.qml": "/data/", "pika-0.13.1": "/data/innovenergy/" }