Skip to content

Commit 203f0e1

Browse files
authored
add huawei emma (#2643)
1 parent 17dfa98 commit 203f0e1

5 files changed

Lines changed: 280 additions & 0 deletions

File tree

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env python3
2+
from typing import TypedDict, Any
3+
4+
from modules.common.abstract_device import AbstractBat
5+
from modules.common.component_state import BatState
6+
from modules.common.component_type import ComponentDescriptor
7+
from modules.common.fault_state import ComponentInfo, FaultState
8+
from modules.common.modbus import ModbusDataType, ModbusTcpClient_
9+
from modules.common.simcount import SimCounter
10+
from modules.common.store import get_bat_value_store
11+
from modules.devices.huawei.huawei_emma.config import Huawei_EmmaBatSetup
12+
13+
14+
class KwargsDict(TypedDict):
15+
device_id: int
16+
modbus_id: int
17+
client: ModbusTcpClient_
18+
19+
20+
class Huawei_EmmaBat(AbstractBat):
21+
def __init__(self, component_config: Huawei_EmmaBatSetup, **kwargs: Any) -> None:
22+
self.component_config = component_config
23+
self.kwargs: KwargsDict = kwargs
24+
25+
def initialize(self) -> None:
26+
self.__device_id: int = self.kwargs['device_id']
27+
self.modbus_id: int = self.kwargs['modbus_id']
28+
self.client: ModbusTcpClient_ = self.kwargs['client']
29+
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="speicher")
30+
self.store = get_bat_value_store(self.component_config.id)
31+
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
32+
33+
def update(self) -> None:
34+
power = self.client.read_holding_registers(30360, ModbusDataType.INT_32, unit=self.modbus_id)
35+
soc = self.client.read_holding_registers(30368, ModbusDataType.UINT_16, unit=self.modbus_id) * 0.01
36+
37+
imported, exported = self.sim_counter.sim_count(power)
38+
bat_state = BatState(
39+
power=power,
40+
soc=soc,
41+
imported=imported,
42+
exported=exported
43+
)
44+
self.store.set(bat_state)
45+
46+
47+
component_descriptor = ComponentDescriptor(configuration_factory=Huawei_EmmaBatSetup)
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
from typing import Optional
2+
3+
from modules.common.component_setup import ComponentSetup
4+
from ..vendor import vendor_descriptor
5+
6+
7+
class Huawei_EmmaConfiguration:
8+
def __init__(self, modbus_id: int = 0,
9+
ip_address: Optional[str] = None,
10+
port: int = 502):
11+
self.modbus_id = modbus_id
12+
self.ip_address = ip_address
13+
self.port = port
14+
15+
16+
class Huawei_Emma:
17+
def __init__(self,
18+
name: str = "Huawei EMMA",
19+
type: str = "huawei_emma",
20+
id: int = 0,
21+
configuration: Huawei_EmmaConfiguration = None) -> None:
22+
self.name = name
23+
self.type = type
24+
self.vendor = vendor_descriptor.configuration_factory().type
25+
self.id = id
26+
self.configuration = configuration or Huawei_EmmaConfiguration()
27+
28+
29+
class Huawei_EmmaBatConfiguration:
30+
def __init__(self):
31+
pass
32+
33+
34+
class Huawei_EmmaBatSetup(ComponentSetup[Huawei_EmmaBatConfiguration]):
35+
def __init__(self,
36+
name: str = "Huawei EMMA Speicher",
37+
type: str = "bat",
38+
id: int = 0,
39+
configuration: Huawei_EmmaBatConfiguration = None) -> None:
40+
super().__init__(name, type, id, configuration or Huawei_EmmaBatConfiguration())
41+
42+
43+
class Huawei_EmmaCounterConfiguration:
44+
def __init__(self):
45+
pass
46+
47+
48+
class Huawei_EmmaCounterSetup(ComponentSetup[Huawei_EmmaCounterConfiguration]):
49+
def __init__(self,
50+
name: str = "Huawei EMMA Zähler",
51+
type: str = "counter",
52+
id: int = 0,
53+
configuration: Huawei_EmmaCounterConfiguration = None) -> None:
54+
super().__init__(name, type, id, configuration or Huawei_EmmaCounterConfiguration())
55+
56+
57+
class Huawei_EmmaInverterConfiguration:
58+
def __init__(self):
59+
pass
60+
61+
62+
class Huawei_EmmaInverterSetup(ComponentSetup[Huawei_EmmaInverterConfiguration]):
63+
def __init__(self,
64+
name: str = "Huawei EMMA Wechselrichter",
65+
type: str = "inverter",
66+
id: int = 0,
67+
configuration: Huawei_EmmaInverterConfiguration = None) -> None:
68+
super().__init__(name, type, id, configuration or Huawei_EmmaInverterConfiguration())
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env python3
2+
from typing import TypedDict, Any
3+
4+
from modules.common.abstract_device import AbstractCounter
5+
from modules.common.component_state import CounterState
6+
from modules.common.component_type import ComponentDescriptor
7+
from modules.common.fault_state import ComponentInfo, FaultState
8+
from modules.common.modbus import ModbusDataType, ModbusTcpClient_
9+
from modules.common.simcount import SimCounter
10+
from modules.common.store import get_counter_value_store
11+
from modules.devices.huawei.huawei_emma.config import Huawei_EmmaCounterSetup
12+
13+
14+
class KwargsDict(TypedDict):
15+
device_id: int
16+
modbus_id: int
17+
client: ModbusTcpClient_
18+
19+
20+
class Huawei_EmmaCounter(AbstractCounter):
21+
def __init__(self, component_config: Huawei_EmmaCounterSetup, **kwargs: Any) -> None:
22+
self.component_config = component_config
23+
self.kwargs: KwargsDict = kwargs
24+
25+
def initialize(self) -> None:
26+
self.__device_id: int = self.kwargs['device_id']
27+
self.modbus_id: int = self.kwargs['modbus_id']
28+
self.client: ModbusTcpClient_ = self.kwargs['client']
29+
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="bezug")
30+
self.store = get_counter_value_store(self.component_config.id)
31+
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
32+
33+
def update(self) -> None:
34+
currents = self.client.read_holding_registers(31651, [ModbusDataType.INT_32]*3, unit=self.modbus_id)
35+
currents = [val * 0.1 for val in currents]
36+
power = self.client.read_holding_registers(31657, ModbusDataType.INT_32, unit=self.modbus_id)
37+
38+
imported, exported = self.sim_counter.sim_count(power)
39+
40+
counter_state = CounterState(
41+
currents=currents,
42+
imported=imported,
43+
exported=exported,
44+
power=power
45+
)
46+
self.store.set(counter_state)
47+
48+
49+
component_descriptor = ComponentDescriptor(configuration_factory=Huawei_EmmaCounterSetup)
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/env python3
2+
import logging
3+
from pathlib import Path
4+
from typing import Iterable, Union
5+
6+
from helpermodules.utils.run_command import run_command
7+
from modules.common.abstract_device import DeviceDescriptor
8+
from modules.common.component_context import SingleComponentUpdateContext
9+
from modules.common.configurable_device import ComponentFactoryByType, ConfigurableDevice, MultiComponentUpdater
10+
from modules.common.modbus import ModbusTcpClient_
11+
from modules.devices.huawei.huawei_emma.bat import Huawei_EmmaBat
12+
from modules.devices.huawei.huawei_emma.config import Huawei_Emma, Huawei_EmmaBatSetup
13+
from modules.devices.huawei.huawei_emma.config import Huawei_EmmaCounterSetup, Huawei_EmmaInverterSetup
14+
from modules.devices.huawei.huawei_emma.counter import Huawei_EmmaCounter
15+
from modules.devices.huawei.huawei_emma.inverter import Huawei_EmmaInverter
16+
17+
log = logging.getLogger(__name__)
18+
19+
20+
def create_device(device_config: Huawei_Emma):
21+
client = None
22+
23+
def create_bat_component(component_config: Huawei_EmmaBatSetup):
24+
nonlocal client
25+
return Huawei_EmmaBat(component_config,
26+
device_id=device_config.id,
27+
modbus_id=device_config.configuration.modbus_id,
28+
client=client)
29+
30+
def create_counter_component(component_config: Huawei_EmmaCounterSetup):
31+
nonlocal client
32+
return Huawei_EmmaCounter(component_config,
33+
device_id=device_config.id,
34+
modbus_id=device_config.configuration.modbus_id,
35+
client=client)
36+
37+
def create_inverter_component(component_config: Huawei_EmmaInverterSetup):
38+
nonlocal client
39+
return Huawei_EmmaInverter(component_config,
40+
device_id=device_config.id,
41+
modbus_id=device_config.configuration.modbus_id,
42+
client=client)
43+
44+
def update_components(components: Iterable[Union[Huawei_EmmaBat, Huawei_EmmaCounter, Huawei_EmmaInverter]]):
45+
nonlocal client
46+
with client:
47+
for component in components:
48+
with SingleComponentUpdateContext(component.fault_state):
49+
component.update()
50+
51+
def initializer():
52+
nonlocal client
53+
client = ModbusTcpClient_(device_config.configuration.ip_address,
54+
device_config.configuration.port)
55+
56+
def error_handler():
57+
run_command(f"{Path(__file__).resolve().parents[4]}/modules/common/restart_protoss_admin")
58+
59+
return ConfigurableDevice(
60+
device_config=device_config,
61+
initializer=initializer,
62+
error_handler=error_handler,
63+
component_factory=ComponentFactoryByType(
64+
bat=create_bat_component,
65+
counter=create_counter_component,
66+
inverter=create_inverter_component,
67+
),
68+
component_updater=MultiComponentUpdater(update_components)
69+
)
70+
71+
72+
device_descriptor = DeviceDescriptor(configuration_factory=Huawei_Emma)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#!/usr/bin/env python3
2+
from typing import TypedDict, Any
3+
4+
from modules.common.abstract_device import AbstractInverter
5+
from modules.common.component_state import InverterState
6+
from modules.common.component_type import ComponentDescriptor
7+
from modules.common.fault_state import ComponentInfo, FaultState
8+
from modules.common.modbus import ModbusDataType, ModbusTcpClient_
9+
from modules.common.simcount import SimCounter
10+
from modules.common.store import get_inverter_value_store
11+
from modules.devices.huawei.huawei_emma.config import Huawei_EmmaInverterSetup
12+
13+
14+
class KwargsDict(TypedDict):
15+
device_id: int
16+
modbus_id: int
17+
client: ModbusTcpClient_
18+
19+
20+
class Huawei_EmmaInverter(AbstractInverter):
21+
def __init__(self, component_config: Huawei_EmmaInverterSetup, **kwargs: Any) -> None:
22+
self.component_config = component_config
23+
self.kwargs: KwargsDict = kwargs
24+
25+
def initialize(self) -> None:
26+
self.__device_id: int = self.kwargs['device_id']
27+
self.modbus_id: int = self.kwargs['modbus_id']
28+
self.client: ModbusTcpClient_ = self.kwargs['client']
29+
self.sim_counter = SimCounter(self.__device_id, self.component_config.id, prefix="pv")
30+
self.store = get_inverter_value_store(self.component_config.id)
31+
self.fault_state = FaultState(ComponentInfo.from_component_config(self.component_config))
32+
33+
def update(self) -> None:
34+
power = self.client.read_holding_registers(30354, ModbusDataType.INT_32, unit=self.modbus_id) * -1
35+
exported = self.client.read_holding_registers(30344, ModbusDataType.UINT_32, unit=self.modbus_id) * 0.01
36+
37+
inverter_state = InverterState(
38+
power=power,
39+
exported=exported
40+
)
41+
self.store.set(inverter_state)
42+
43+
44+
component_descriptor = ComponentDescriptor(configuration_factory=Huawei_EmmaInverterSetup)

0 commit comments

Comments
 (0)