From 68e8e3fc8573a18f4e0cd8720bf37126c073eee3 Mon Sep 17 00:00:00 2001 From: Paul G Date: Fri, 20 Mar 2026 13:27:02 +0000 Subject: [PATCH] New Features and fixes --- .gitignore | 1 + dbus-generator-ramp/dbus-generator-ramp.py | 32 +++- mfd-custom-app/package.sh | 9 ++ venus-html5-app/src/app/Marine2/App.tsx | 4 + .../Marine2/components/ui/Footer/Footer.tsx | 11 +- .../ui/SettingsMenu/SettingsMenu.tsx | 18 ++- .../views/custom/CompactForecastCard.tsx | 25 +-- .../views/custom/CompactPowerEnergyCard.tsx | 121 ++++++++------- .../views/custom/CompactTideCard.tsx | 31 +--- .../views/custom/CompactWeatherCard.tsx | 2 +- .../views/custom/TideAnalysisView.tsx | 27 +--- .../components/views/custom/TideView.tsx | 27 +--- .../components/views/custom/WindCompass.tsx | 144 +++++++++--------- .../modules/AppViews/AppViews.store.ts | 2 +- .../Marine2/utils/hooks/use-custom-mqtt.ts | 4 + .../utils/hooks/use-sunrise-sunset-mode.ts | 94 ++++++++++++ .../utils/hooks/use-sunset-mode-store.ts | 39 +++++ .../src/app/Marine2/utils/sun-utils.ts | 33 ++++ 18 files changed, 388 insertions(+), 236 deletions(-) create mode 100644 venus-html5-app/src/app/Marine2/utils/hooks/use-sunrise-sunset-mode.ts create mode 100644 venus-html5-app/src/app/Marine2/utils/hooks/use-sunset-mode-store.ts create mode 100644 venus-html5-app/src/app/Marine2/utils/sun-utils.ts diff --git a/.gitignore b/.gitignore index 884b1e8..90cfba9 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,4 @@ dbus-windy-station/station_config.json # Design reference assets (kept locally, not in repo) inspiration assets/ +venus-data.zip diff --git a/dbus-generator-ramp/dbus-generator-ramp.py b/dbus-generator-ramp/dbus-generator-ramp.py index b9e7a4e..be39a9d 100755 --- a/dbus-generator-ramp/dbus-generator-ramp.py +++ b/dbus-generator-ramp/dbus-generator-ramp.py @@ -55,7 +55,7 @@ from ramp_controller import RampController # Version -VERSION = '1.1.1' +VERSION = '1.2.0' # D-Bus service name for our addon SERVICE_NAME = 'com.victronenergy.generatorramp' @@ -113,6 +113,11 @@ class GeneratorRampController: # Enabled flag self.enabled = True + + # Energy accumulation (Wh -> kWh) + self._run_energy_wh = 0.0 + self._last_run_energy_wh = 0.0 + self._energy_last_time = None # D-Bus connection self.bus = dbus.SystemBus() @@ -236,6 +241,12 @@ class GeneratorRampController: self.dbus_service.add_path('/Ramp/TimeRemaining', 0, gettextcallback=lambda p, v: f"{v//60}m {v%60}s" if v > 0 else "0s") + # Energy accumulation (kWh) + self.dbus_service.add_path('/Energy/CurrentRun', 0.0, + gettextcallback=lambda p, v: f"{v:.1f} kWh") + self.dbus_service.add_path('/Energy/LastRun', 0.0, + gettextcallback=lambda p, v: f"{v:.1f} kWh") + # Fast recovery status self.dbus_service.add_path('/Recovery/InFastRamp', 0) self.dbus_service.add_path('/Recovery/FastRampTarget', 0.0, @@ -735,9 +746,28 @@ class GeneratorRampController: self._read_output_power() self._read_current_limit() + # Accumulate energy while generator is providing AC power + if self.ac_connected and self.generator_state in [ + GENERATOR_STATE['RUNNING'], GENERATOR_STATE['WARMUP'], GENERATOR_STATE['COOLDOWN'] + ]: + total_power = self.current_l1_power + self.current_l2_power + if self._energy_last_time is not None and total_power > 0: + dt_hours = (now - self._energy_last_time) / 3600.0 + self._run_energy_wh += total_power * dt_hours + self.dbus_service['/Energy/CurrentRun'] = round(self._run_energy_wh / 1000.0, 2) + self._energy_last_time = now + else: + self._energy_last_time = None + # Check for generator stop if self.generator_state == GENERATOR_STATE['STOPPED']: if self.state != self.STATE_IDLE: + if self._run_energy_wh > 0: + self._last_run_energy_wh = self._run_energy_wh + self.dbus_service['/Energy/LastRun'] = round(self._last_run_energy_wh / 1000.0, 2) + self.logger.info(f"Run energy: {self._last_run_energy_wh / 1000.0:.2f} kWh") + self._run_energy_wh = 0.0 + self.dbus_service['/Energy/CurrentRun'] = 0.0 self.logger.info("Generator stopped") self._transition_to(self.STATE_IDLE) return True diff --git a/mfd-custom-app/package.sh b/mfd-custom-app/package.sh index fdb7a98..b81f6dc 100755 --- a/mfd-custom-app/package.sh +++ b/mfd-custom-app/package.sh @@ -82,3 +82,12 @@ echo "" echo "Deploy via USB:" echo " Copy venus-data.zip to a USB stick, insert into Cerbo, reboot." echo "" + +read -p "Copy tarball to remote cerbo host? [y/N] " answer +if [[ "$answer" =~ ^[Yy]$ ]]; then + echo "Copying to cerbo..." + scp "$OUTPUT_DIR/${DIST_NAME}.tar.gz" cerbo:/data/ + echo "Done." +else + echo "Skipping remote copy." +fi diff --git a/venus-html5-app/src/app/Marine2/App.tsx b/venus-html5-app/src/app/Marine2/App.tsx index 1ee876d..51b1791 100644 --- a/venus-html5-app/src/app/Marine2/App.tsx +++ b/venus-html5-app/src/app/Marine2/App.tsx @@ -7,6 +7,8 @@ import { useVisibleWidgetsStore } from "./modules" import { Marine2 } from "./Marine2" import Connecting from "./components/ui/Connecting" import { appErrorBoundaryProps } from "./components/ui/Error/appErrorBoundary" +import { useSunsetModeStore } from "./utils/hooks/use-sunset-mode-store" +import { useSunriseSunsetMode } from "./utils/hooks/use-sunrise-sunset-mode" import "./css/global.css" export type AppProps = { @@ -23,8 +25,10 @@ const App = (props: AppProps) => { const locale = getLocale() const visibleWidgetsStore = useVisibleWidgetsStore() const { themeStore } = useTheme() + const sunsetStore = useSunsetModeStore() useVebus() + useSunriseSunsetMode(sunsetStore.enabled) useEffect(() => { if (!appStore.remote) { diff --git a/venus-html5-app/src/app/Marine2/components/ui/Footer/Footer.tsx b/venus-html5-app/src/app/Marine2/components/ui/Footer/Footer.tsx index 8f9fdbb..dcad4a3 100644 --- a/venus-html5-app/src/app/Marine2/components/ui/Footer/Footer.tsx +++ b/venus-html5-app/src/app/Marine2/components/ui/Footer/Footer.tsx @@ -6,18 +6,18 @@ import BackIcon from "../../../images/icons/back.svg" import DockViewIcon from "../../../images/icons/dock-view.svg" import WavesIcon from "../../../images/icons/waves.svg" import { AppViews, useAppViewsStore } from "../../../modules/AppViews" -import SwitchingPane from "../../views/SwitchingPane" - const Footer = ({ pageSelectorProps }: Props) => { const appViewsStore = useAppViewsStore() - const [isShowingBackButton, setIsShowingBackButton] = useState(appViewsStore.currentView !== AppViews.ROOT) + const [isShowingBackButton, setIsShowingBackButton] = useState( + appViewsStore.currentView !== AppViews.CUSTOM_MOORING_VIEW, + ) const handleBackClick = () => { - appViewsStore.setView(AppViews.ROOT) + appViewsStore.setView(AppViews.CUSTOM_MOORING_VIEW) } useEffect(() => { - setIsShowingBackButton(appViewsStore.currentView !== AppViews.ROOT) + setIsShowingBackButton(appViewsStore.currentView !== AppViews.CUSTOM_MOORING_VIEW) }, [appViewsStore.currentView]) return ( @@ -49,7 +49,6 @@ const Footer = ({ pageSelectorProps }: Props) => { > - ) diff --git a/venus-html5-app/src/app/Marine2/components/ui/SettingsMenu/SettingsMenu.tsx b/venus-html5-app/src/app/Marine2/components/ui/SettingsMenu/SettingsMenu.tsx index 9d1e7fa..22cf8d1 100644 --- a/venus-html5-app/src/app/Marine2/components/ui/SettingsMenu/SettingsMenu.tsx +++ b/venus-html5-app/src/app/Marine2/components/ui/SettingsMenu/SettingsMenu.tsx @@ -8,6 +8,7 @@ import CloseIcon from "../../../images/icons/close.svg" import ToggleSwitch from "../ToggleSwitch" import RadioButton from "../RadioButton" import { AppViews, useAppViewsStore } from "../../../modules/AppViews" +import { useSunsetModeStore } from "../../../utils/hooks/use-sunset-mode-store" import Button from "../Button" import classNames from "classnames" @@ -15,6 +16,7 @@ const SettingsMenu = () => { const { locked, toggleLocked } = useAppStore() const { themeStore } = useTheme() const appViewsStore = useAppViewsStore() + const sunsetStore = useSunsetModeStore() const [isModalOpen, setIsModalOpen] = useState(false) const [isHorizontal, setIsHorizontal] = useState(false) @@ -119,10 +121,24 @@ const SettingsMenu = () => { themeStore.setAutoMode(e.target.checked)} + onChange={(e) => { + themeStore.setAutoMode(e.target.checked) + if (e.target.checked) sunsetStore.setEnabled(false) + }} selected={themeStore.autoMode} /> +