Skip to content

sdm compatibility mode - #3212

Merged
LKuemmel merged 1 commit into
openWB:masterfrom
LKuemmel:fix-sdm
Mar 17, 2026
Merged

LKuemmel merged 1 commit into
openWB:masterfrom
LKuemmel:fix-sdm

Conversation

@LKuemmel

Copy link
Copy Markdown
Contributor

Ticket #66001671

@LKuemmel
LKuemmel requested a review from Copilot March 17, 2026 09:21
@LKuemmel
LKuemmel merged commit be1671d into openWB:master Mar 17, 2026
5 checks passed
@LKuemmel
LKuemmel deleted the fix-sdm branch March 17, 2026 09:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an SDM “compatibility mode” to improve Modbus read reliability for SDM meters that can’t handle larger bulk register reads.

Changes:

  • Add logger and a fast_mode flag to control bulk-read vs. compatibility/slow-read behavior.
  • Update Sdm630_72.get_counter_state() to attempt bulk reads first and fall back to smaller reads on failure.
  • Reduce bulk-read sizes (e.g., bulk_2 from 8 to 6 registers) to better match actual mapped registers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines 17 to 23
class Sdm(AbstractCounter):
def __init__(self, modbus_id: int, client: modbus.ModbusTcpClient_) -> None:
self.client = client
self.id = modbus_id
self.fast_mode = True
with client:
self.serial_number = str(self.client.read_holding_registers(0xFC00, ModbusDataType.UINT_32, unit=self.id))
Comment on lines 70 to +76
# entgegen der Doku können nicht bei allen SDM72 80 Register auf einmal gelesen werden,
# manche können auch nur 20
time.sleep(0.1)
bulk_1 = self.client.read_input_registers_bulk(
SdmRegister.VOLTAGE_L1, 20, mapping=self.REG_MAPPING_BULK_1, unit=self.id)
time.sleep(0.1)
power_factors = self.client.read_input_registers(0x1E, [ModbusDataType.FLOAT_32]*3, unit=self.id)
time.sleep(0.1)
bulk_2 = self.client.read_input_registers_bulk(
SdmRegister.FREQUENCY, 8, mapping=self.REG_MAPPING_BULK_2, unit=self.id)
resp = {**bulk_1, **bulk_2}
# manche können auch nur 10
if self.fast_mode:
try:
time.sleep(0.1)
bulk_1 = self.client.read_input_registers_bulk(
SdmRegister.VOLTAGE_L1, 18, mapping=self.REG_MAPPING_BULK_1, unit=self.id)
Comment on lines 69 to +112
def get_counter_state(self) -> CounterState:
# entgegen der Doku können nicht bei allen SDM72 80 Register auf einmal gelesen werden,
# manche können auch nur 20
time.sleep(0.1)
bulk_1 = self.client.read_input_registers_bulk(
SdmRegister.VOLTAGE_L1, 20, mapping=self.REG_MAPPING_BULK_1, unit=self.id)
time.sleep(0.1)
power_factors = self.client.read_input_registers(0x1E, [ModbusDataType.FLOAT_32]*3, unit=self.id)
time.sleep(0.1)
bulk_2 = self.client.read_input_registers_bulk(
SdmRegister.FREQUENCY, 8, mapping=self.REG_MAPPING_BULK_2, unit=self.id)
resp = {**bulk_1, **bulk_2}
# manche können auch nur 10
if self.fast_mode:
try:
time.sleep(0.1)
bulk_1 = self.client.read_input_registers_bulk(
SdmRegister.VOLTAGE_L1, 18, mapping=self.REG_MAPPING_BULK_1, unit=self.id)
time.sleep(0.1)
power_factors = self.client.read_input_registers(
SdmRegister.POWER_FACTOR_L1, [ModbusDataType.FLOAT_32]*3, unit=self.id)
time.sleep(0.1)
bulk_2 = self.client.read_input_registers_bulk(
SdmRegister.FREQUENCY, 6, mapping=self.REG_MAPPING_BULK_2, unit=self.id)
resp = {**bulk_1, **bulk_2}
except Exception:
log.exception("Fehler beim Auslesen des Zählers")
self.client.read_input_registers(
SdmRegister.VOLTAGE_L1, [ModbusDataType.FLOAT_32]*3, unit=self.id)
self.fast_mode = False
if self.fast_mode is False:
# im gleichen Durchlauf noch im slow mode versuchen, sonst schlägt der Hardware-Check fehl
log.debug("Auslesung des Zählers im Kompatibilitäts-Modus")
resp = {}
time.sleep(0.1)
resp[SdmRegister.VOLTAGE_L1] = self.client.read_input_registers(
SdmRegister.VOLTAGE_L1, [ModbusDataType.FLOAT_32]*3, unit=self.id)
time.sleep(0.1)
resp[SdmRegister.CURRENT_L1] = self.client.read_input_registers(
SdmRegister.CURRENT_L1, [ModbusDataType.FLOAT_32]*3, unit=self.id)
time.sleep(0.1)
resp[SdmRegister.POWER_L1] = self.client.read_input_registers(
SdmRegister.POWER_L1, [ModbusDataType.FLOAT_32]*3, unit=self.id)
time.sleep(0.1)
power_factors = self.client.read_input_registers(
SdmRegister.POWER_FACTOR_L1, [ModbusDataType.FLOAT_32]*3, unit=self.id)
time.sleep(0.1)
# frequency noch mit auslesen klappt nicht
resp[SdmRegister.IMPORTED], resp[SdmRegister.EXPORTED] = self.client.read_input_registers(
SdmRegister.IMPORTED, [ModbusDataType.FLOAT_32]*2, unit=self.id)
time.sleep(0.1)
resp[SdmRegister.FREQUENCY] = self.client.read_input_registers(
SdmRegister.FREQUENCY, ModbusDataType.FLOAT_32, unit=self.id)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants