Skip to content

Commit

Permalink
Add basic DC/DC converter support
Browse files Browse the repository at this point in the history
  • Loading branch information
keshavdv committed Mar 5, 2023
1 parent de31f61 commit 88bc24c
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 1 deletion.
19 changes: 19 additions & 0 deletions tests/test_dcdc_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from victron_ble.devices.dcdc_converter import DcDcConverter
from victron_ble.devices.base import OperationMode, OffReason, ChargerError


class TestDcDcConverter:
def test_parse_data(self) -> None:
data = "1000c0a304121d64ca8d442b90bbdf6a8cba"
actual = DcDcConverter("64ba49f1a8562e45197a8e1fe50d7658").parse(
bytes.fromhex(data)
)

assert actual.get_charge_state() == OperationMode.OFF
assert actual.get_charger_error() == ChargerError.NO_ERROR
assert actual.get_input_voltage() == 13.15
# assert actual.get_output_voltage() == 0
assert actual.get_off_reason() == OffReason.ENGINE_SHUTDOWN
assert (
actual.get_model_name() == "Orion Smart 12V|12V-18A Isolated DC-DC Charger"
)
3 changes: 2 additions & 1 deletion victron_ble/devices/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from victron_ble.devices.battery_monitor import AuxMode, BatteryMonitor
from victron_ble.devices.battery_sense import BatterySense
from victron_ble.devices.dc_energy_meter import DcEnergyMeter
from victron_ble.devices.dcdc_converter import DcDcConverter
from victron_ble.devices.solar_charger import SolarCharger

__all__ = [
Expand Down Expand Up @@ -42,7 +43,7 @@ def detect_device_type(data: bytes) -> Optional[Type[Device]]:
elif mode == 0x8: # AcCharger
pass
elif mode == 0x4: # DcDcConverter
pass
return DcDcConverter
elif mode == 0x3: # Inverter
pass
elif mode == 0x6: # InverterRS
Expand Down
77 changes: 77 additions & 0 deletions victron_ble/devices/dcdc_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
from construct import GreedyBytes, Int8ul, Int16sl, Int16ul, Int32ul, Struct

from victron_ble.devices.base import (
ChargerError,
Device,
DeviceData,
OffReason,
OperationMode,
)


class DcDcConverterData(DeviceData):
def get_charge_state(self) -> OperationMode:
"""
Return an enum indicating the current charging state
"""
return self._data["device_state"]

def get_charger_error(self) -> ChargerError:
"""
Return an enum indicating the error code
"""
return self._data["charger_error"]

def get_input_voltage(self) -> float:
"""
Return the input voltage in volts
"""
return self._data["input_voltage"]

def get_output_voltage(self) -> float:
"""
Return the output voltage in volts
"""
reading = self._data["output_voltage"]
if reading == 0x7FFF:
return 0
return reading

def get_off_reason(self) -> OffReason:
"""
Return an error code stating the reason for the output to be off
"""
return self._data["off_reason"]


class DcDcConverter(Device):
PACKET = Struct(
# Charge State: 0 - Off
# 3 - Bulk
# 4 - Absorption
# 5 - Float
"device_state" / Int8ul,
# Charger Error Code
"charger_error" / Int8ul,
# Input voltage reading in 0.01V increments
"input_voltage" / Int16ul,
# Output voltage in 0.01V
"output_voltage" / Int16sl,
# Reason for Charger Off
"off_reason" / Int32ul,
GreedyBytes,
)

def parse(self, data: bytes) -> DcDcConverterData:
decrypted = self.decrypt(data)
pkt = self.PACKET.parse(decrypted)

parsed = {
"device_state": OperationMode(pkt.device_state),
"charger_error": ChargerError(pkt.charger_error),
"input_voltage": pkt.input_voltage / 100,
"output_voltage": pkt.output_voltage / 100,
"off_reason": OffReason(pkt.off_reason),
}

return DcDcConverterData(self.get_model_id(data), parsed)

0 comments on commit 88bc24c

Please sign in to comment.