From f55addb41f64bf29160105f7d65ea3fb156b1e3d Mon Sep 17 00:00:00 2001 From: LKuemmel Date: Wed, 4 Mar 2026 09:00:04 +0100 Subject: [PATCH 1/2] fix shelly phase iteration --- packages/modules/devices/shelly/shelly/bat.py | 27 ++++++------ .../devices/shelly/shelly/constants.py | 1 + .../modules/devices/shelly/shelly/counter.py | 41 ++++++++----------- .../modules/devices/shelly/shelly/inverter.py | 23 +++++------ 4 files changed, 39 insertions(+), 53 deletions(-) create mode 100644 packages/modules/devices/shelly/shelly/constants.py diff --git a/packages/modules/devices/shelly/shelly/bat.py b/packages/modules/devices/shelly/shelly/bat.py index 510c88b641..e80938f35d 100644 --- a/packages/modules/devices/shelly/shelly/bat.py +++ b/packages/modules/devices/shelly/shelly/bat.py @@ -9,6 +9,7 @@ from modules.common.store import get_bat_value_store from modules.common.simcount._simcounter import SimCounter from modules.devices.shelly.shelly.config import ShellyBatSetup +from modules.devices.shelly.shelly.constants import ALPHABETICAL_INDEX log = logging.getLogger(__name__) @@ -37,7 +38,6 @@ def initialize(self) -> None: self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config)) def update(self) -> None: - power = 0 if self.generation == 1: status_url = "http://" + self.address + "/status" else: @@ -45,32 +45,29 @@ def update(self) -> None: status = req.get_http_session().get(status_url, timeout=3).json() try: - alphabetical_index = ['a', 'b', 'c'] + power = 0 currents = [0.0, 0.0, 0.0] # GEN 1 if "meters" in status: meters = status['meters'] # einphasiger shelly? - for i in range(len(meters)): - currents[(i+self.phase-1) % 3] = ((float(meters[i]['power']) * self.factor) / 230 - if meters[i].get('power') else 0) - power = power + (float(meters[i]['power'] * self.factor)) + for i in range(0, min(3, len(meters))): + currents[(i+self.phase-1) % 3] = (float(meters[i].get('power', 0)) * self.factor) / 230 + power = power + (float(meters[i].get('power', 0)) * self.factor) elif "emeters" in status: meters = status['emeters'] # shellyEM & shelly3EM # shellyEM has one meter, shelly3EM has three meters - for i in range(len(meters)): - currents[(i+self.phase-1) % 3] = (float(meters[i]['current']) * self.factor - if meters[i].get('current') else 0) - power = power + (float(meters[i]['power'] * self.factor)) + for i in range(0, min(3, len(meters))): + currents[(i+self.phase-1) % 3] = float(meters[i].get('current', 0)) * self.factor + power = power + float(meters[i].get('power', 0)) * self.factor # GEN 2+ # shelly Pro3EM elif "em:0" in status: meters = status['em:0'] - for i in range(0, 3): - if meters.get(f'{alphabetical_index[i]}_current') is None: + for i, alphabetical_index in enumerate(ALPHABETICAL_INDEX): + if meters.get(f'{alphabetical_index}_current') is None: continue - currents[(i+self.phase-1) % 3] = (float(meters[f'{alphabetical_index[i]}_current']) * self.factor - if meters.get(f'{alphabetical_index[i]}_current') else 0) - power = float(meters['total_act_power']) * self.factor + currents[(i+self.phase-1) % 3] = float(meters.get(f'{alphabetical_index}_current', 0)) * self.factor + power = float(meters.get('total_act_power', 0)) * self.factor # Shelly MiniPM G3 elif "pm1:0" in status: log.debug("single phase shelly") diff --git a/packages/modules/devices/shelly/shelly/constants.py b/packages/modules/devices/shelly/shelly/constants.py new file mode 100644 index 0000000000..4af0561042 --- /dev/null +++ b/packages/modules/devices/shelly/shelly/constants.py @@ -0,0 +1 @@ +ALPHABETICAL_INDEX = ['a', 'b', 'c'] diff --git a/packages/modules/devices/shelly/shelly/counter.py b/packages/modules/devices/shelly/shelly/counter.py index a9f10fcfce..cb4ec9d8d4 100644 --- a/packages/modules/devices/shelly/shelly/counter.py +++ b/packages/modules/devices/shelly/shelly/counter.py @@ -9,6 +9,7 @@ from modules.common.store import get_counter_value_store from modules.common.simcount._simcounter import SimCounter from modules.devices.shelly.shelly.config import ShellyCounterSetup +from modules.devices.shelly.shelly.constants import ALPHABETICAL_INDEX log = logging.getLogger(__name__) @@ -45,14 +46,12 @@ def update(self) -> None: status = req.get_http_session().get(status_url, timeout=3).json() try: # GEN 1 - alphabetical_index = ['a', 'b', 'c'] if "meters" in status: powers = [0.0, 0.0, 0.0] voltages = [0.0, 0.0, 0.0] meters = status['meters'] # einphasiger shelly? - for i in range(len(meters)): - powers[(i+self.phase-1) % 3] = (float(meters[i]['power']) * self.factor - if meters[i].get('power') else 0) + for i in range(0, min(3, len(meters))): + powers[(i+self.phase-1) % 3] = float(meters[i].get('power', 0)) * self.factor voltages[(i+self.phase-1) % 3] = 230 power = sum(powers) elif "emeters" in status: @@ -62,15 +61,11 @@ def update(self) -> None: power_factors = [0.0, 0.0, 0.0] meters = status['emeters'] # shellyEM & shelly3EM # shellyEM has one meter, shelly3EM has three meters - for i in range(len(meters)): - powers[(i+self.phase-1) % 3] = (float(meters[i]['power']) * self.factor - if meters[i].get('power') else 0) - currents[(i+self.phase-1) % 3] = (float(meters[i]['current']) * self.factor - if meters[i].get('current') else 0) - voltages[(i+self.phase-1) % 3] = (float(meters[i]['voltage']) - if meters[i].get('voltage') else 0) - power_factors[(i+self.phase-1) % 3] = (float(meters[i]['pf']) - if meters[i].get('pf') else 0) + for i in range(0, min(3, len(meters))): + powers[(i+self.phase-1) % 3] = float(meters[i].get('power', 0)) * self.factor + currents[(i+self.phase-1) % 3] = float(meters[i].get('current', 0)) * self.factor + voltages[(i+self.phase-1) % 3] = float(meters[i].get('voltage', 0)) + power_factors[(i+self.phase-1) % 3] = float(meters[i].get('pf', 0)) power = sum(powers) # GEN 2+ @@ -81,18 +76,14 @@ def update(self) -> None: voltages = [0.0, 0.0, 0.0] power_factors = [0.0, 0.0, 0.0] meters = status['em:0'] - for i in range(0, 3): - if meters.get(f'{alphabetical_index[i]}_act_power') is None: + for i, alphabetical_index in enumerate(ALPHABETICAL_INDEX): + if meters.get(f'{alphabetical_index}_act_power') is None: continue - powers[(i+self.phase-1) % 3] = (float(meters[f'{alphabetical_index[i]}_act_power']) * self.factor - if meters.get(f'{alphabetical_index[i]}_act_power') else 0) - voltages[(i+self.phase-1) % 3] = (float(meters[f'{alphabetical_index[i]}_voltage']) - if meters.get(f'{alphabetical_index[i]}_voltage') else 0) - currents[(i+self.phase-1) % 3] = (float(meters[f'{alphabetical_index[i]}_current']) * self.factor - if meters.get(f'{alphabetical_index[i]}_current') else 0) - power_factors[(i+self.phase-1) % 3] = (float(meters[f'{alphabetical_index[i]}_pf']) - if meters.get(f'{alphabetical_index[i]}_pf') else 0) - power = float(meters['total_act_power']) * self.factor + powers[(i+self.phase-1) % 3] = float(meters.get(f'{alphabetical_index}_act_power', 0)) * self.factor + voltages[(i+self.phase-1) % 3] = float(meters.get(f'{alphabetical_index}_voltage', 0)) + currents[(i+self.phase-1) % 3] = float(meters.get(f'{alphabetical_index}_current', 0)) * self.factor + power_factors[(i+self.phase-1) % 3] = float(meters.get(f'{alphabetical_index}_pf', 0)) + power = float(meters.get('total_act_power', 0)) * self.factor # Shelly MiniPM G3 elif "pm1:0" in status: log.debug("single phase shelly") @@ -104,7 +95,7 @@ def update(self) -> None: powers[self.phase-1] = meters['apower'] * self.factor voltages[self.phase-1] = meters['voltage'] currents[self.phase-1] = meters['current'] * self.factor - power_factors[self.phase-1] = meters['pf'] if meters.get('pf') else 0 + power_factors[self.phase-1] = meters.get('pf', 0) power = meters['apower'] * self.factor frequency = meters['freq'] elif 'switch:0' in status and 'apower' in status['switch:0']: diff --git a/packages/modules/devices/shelly/shelly/inverter.py b/packages/modules/devices/shelly/shelly/inverter.py index dead37eb31..dc8f439412 100644 --- a/packages/modules/devices/shelly/shelly/inverter.py +++ b/packages/modules/devices/shelly/shelly/inverter.py @@ -9,6 +9,7 @@ from modules.common.store import get_inverter_value_store from modules.common.simcount._simcounter import SimCounter from modules.devices.shelly.shelly.config import ShellyInverterSetup +from modules.devices.shelly.shelly.constants import ALPHABETICAL_INDEX log = logging.getLogger(__name__) @@ -44,31 +45,27 @@ def update(self) -> None: status_url = "http://" + self.address + "/rpc/Shelly.GetStatus" status = req.get_http_session().get(status_url, timeout=3).json() try: - alphabetical_index = ['a', 'b', 'c'] currents = [0.0, 0.0, 0.0] # GEN 1 if "meters" in status: meters = status['meters'] # einphasiger shelly? - for i in range(len(meters)): - currents[(i+self.phase-1) % 3] += ((float(meters[i]['power']) * self.factor) / 230 - if meters[i].get('power') else 0) - power = power + (float(meters[i]['power'] * self.factor)) + for i in range(0, min(3, len(meters))): + currents[(i+self.phase-1) % 3] += (float(meters[i].get('power', 0)) * self.factor) / 230 + power = power + float(meters[i].get('power', 0)) * self.factor elif "emeters" in status: meters = status['emeters'] # shellyEM & shelly3EM # shellyEM has one meter, shelly3EM has three meters - for i in range(len(meters)): - currents[(i+self.phase-1) % 3] = (float(meters[i]['current']) * self.factor - if meters[i].get('current') else 0) - power = power + (float(meters[i]['power'] * self.factor)) + for i in range(0, min(3, len(meters))): + currents[(i+self.phase-1) % 3] = float(meters[i].get('current', 0)) * self.factor + power = power + float(meters[i].get('power', 0)) * self.factor # GEN 2+ # shelly Pro3EM elif "em:0" in status: meters = status['em:0'] - for i in range(len(meters)): - if meters.get(f'{alphabetical_index[i]}_current') is None: + for i, alphabetical_index in enumerate(ALPHABETICAL_INDEX): + if meters.get(f'{alphabetical_index}_current') is None: continue - currents[(i+self.phase-1) % 3] = (float(meters[f'{alphabetical_index[i]}_current']) * self.factor - if meters.get(f'{alphabetical_index[i]}_current') else 0) + currents[(i+self.phase-1) % 3] = float(meters.get(f'{alphabetical_index}_current', 0)) * self.factor power = float(meters['total_act_power']) * self.factor # Shelly MiniPM G3 elif "pm1:0" in status: From d432110fd63324d656087301bab1a482cb70684f Mon Sep 17 00:00:00 2001 From: LKuemmel <76958050+LKuemmel@users.noreply.github.com> Date: Wed, 4 Mar 2026 09:34:42 +0100 Subject: [PATCH 2/2] Update packages/modules/devices/shelly/shelly/inverter.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- packages/modules/devices/shelly/shelly/inverter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/modules/devices/shelly/shelly/inverter.py b/packages/modules/devices/shelly/shelly/inverter.py index dc8f439412..893f3263a0 100644 --- a/packages/modules/devices/shelly/shelly/inverter.py +++ b/packages/modules/devices/shelly/shelly/inverter.py @@ -66,7 +66,7 @@ def update(self) -> None: if meters.get(f'{alphabetical_index}_current') is None: continue currents[(i+self.phase-1) % 3] = float(meters.get(f'{alphabetical_index}_current', 0)) * self.factor - power = float(meters['total_act_power']) * self.factor + power = float(meters.get('total_act_power', 0)) * self.factor # Shelly MiniPM G3 elif "pm1:0" in status: log.debug("single phase shelly")