33from socketserver import TCPServer
44from collections import defaultdict
55import struct
6- from typing import Optional
6+ from typing import Optional , Union
77
88from helpermodules .utils .error_handling import ImportErrorContext
99with ImportErrorContext ():
3131 log .exception ("Fehler im Modbus-Server" )
3232
3333
34- def _form_int32 (value , startreg ):
35- secondreg = startreg + 1
34+ def _form_int32 (value : Union [int , float ], register : int ):
3635 try :
3736 binary32 = struct .pack ('>l' , int (value ))
3837 high_byte , low_byte = struct .unpack ('>hh' , binary32 )
39- data_store [startreg ] = high_byte
40- data_store [secondreg ] = low_byte
38+ data_store [register ] = high_byte
39+ data_store [register + 1 ] = low_byte
4140 except Exception :
4241 log .exception ("Fehler beim Füllen der Register" )
43- data_store [startreg ] = - 1
44- data_store [secondreg ] = - 1
42+ data_store [register ] = - 1
43+ data_store [register + 1 ] = - 1
4544
4645
47- def _form_int16 (value , startreg ):
46+ def _form_int16 (value : Union [ int , float , bool ], register : int ):
4847 try :
4948 value = int (value )
5049 if (value > 32767 or value < - 32768 ):
5150 raise Exception ("Number to big" )
52- data_store [startreg ] = value
51+ data_store [register ] = value
5352 except Exception :
5453 log .exception ("Fehler beim Füllen der Register" )
55- data_store [startreg ] = - 1
54+ data_store [register ] = - 1
5655
5756
58- def _form_str (value : Optional [str ], startreg ):
57+ def _form_str (value : Optional [str ], register : int ):
5958 if value is None or len (value ) == 0 :
60- data_store [startreg ] = 0
59+ data_store [register ] = 0
6160 else :
6261 bytes = value .encode ("utf-8" )
6362 length = len (bytes )
@@ -72,79 +71,97 @@ def _form_str(value: Optional[str], startreg):
7271 else :
7372 stream_two_bytes = struct .pack (">bb" , bytes [i ], 0 )
7473 stream_one_word = struct .unpack (">h" , stream_two_bytes )[0 ]
75- data_store [startreg + register_offset ] = stream_one_word
74+ data_store [register + register_offset ] = stream_one_word
7675 except Exception :
77- data_store [startreg + register_offset ] = - 1
76+ data_store [register + register_offset ] = - 1
7877 finally :
7978 register_offset += 1
8079
8180
82- def _get_pos (number , n ):
83- return number // 10 ** n % 10 - 1
81+ def _charge_point_index (address : int ):
82+ return int (str (address )[- 3 ]) - 1
83+
84+
85+ def _value_index (address : int ):
86+ return int (str (address )[- 2 :])
8487
8588
8689try :
8790 @app .route (slave_ids = [1 ], function_codes = [3 , 4 ], addresses = list (range (0 , 32000 )))
88- def read_data_store (slave_id , function_code , address ):
91+ def read_data_store (slave_id : int , function_code : int , address : int ):
8992 """" Return value of address. """
93+ # Mapping für einfache Zuordnung
94+ int32_map = {
95+ 0 : lambda cp : cp .get .power ,
96+ 2 : lambda cp : cp .get .imported ,
97+ 41 : lambda cp : cp .get .exported ,
98+ }
99+ int16_map = {
100+ 4 : lambda cp : cp .get .voltages [0 ] * 100 ,
101+ 5 : lambda cp : cp .get .voltages [1 ] * 100 ,
102+ 6 : lambda cp : cp .get .voltages [2 ] * 100 ,
103+ 7 : lambda cp : cp .get .currents [0 ] * 100 ,
104+ 8 : lambda cp : cp .get .currents [1 ] * 100 ,
105+ 9 : lambda cp : cp .get .currents [2 ] * 100 ,
106+ 14 : lambda cp : cp .get .plug_state ,
107+ 15 : lambda cp : cp .get .charge_state ,
108+ 16 : lambda cp : cp .get .evse_current ,
109+ 30 : lambda cp : cp .get .powers [0 ],
110+ 31 : lambda cp : cp .get .powers [1 ],
111+ 32 : lambda cp : cp .get .powers [2 ],
112+ 43 : lambda _ : 1 ,
113+ }
114+ str_map = {
115+ 50 : lambda _ : serial_number ,
116+ 60 : lambda cp : cp .get .rfid ,
117+ }
118+
90119 if address > 10099 :
91120 Pub ().pub ("openWB/set/internal_chargepoint/global_data" ,
92121 {"heartbeat" : timecheck .create_timestamp (), "parent_ip" : None })
93- chargepoint = SubData .internal_chargepoint_data [f"cp{ _get_pos (address , 2 )} " ]
94- askedvalue = int (str (address )[- 2 :])
95- if askedvalue == 00 :
96- _form_int32 (chargepoint .get .power , address )
97- elif askedvalue == 2 :
98- _form_int32 (chargepoint .get .imported , address )
99- elif 4 <= askedvalue <= 6 :
100- _form_int16 (chargepoint .get .voltages [askedvalue - 4 ]* 100 , address )
101- elif 7 <= askedvalue <= 9 :
102- _form_int16 (chargepoint .get .currents [askedvalue - 7 ]* 100 , address )
103- elif askedvalue == 14 :
104- _form_int16 (chargepoint .get .plug_state , address )
105- elif askedvalue == 15 :
106- _form_int16 (chargepoint .get .charge_state , address )
107- elif askedvalue == 16 :
108- _form_int16 (chargepoint .get .evse_current , address )
109- elif 30 <= askedvalue <= 32 :
110- _form_int16 (chargepoint .get .powers [askedvalue - 30 ], address )
111- elif askedvalue == 41 :
112- _form_int32 (chargepoint .get .exported , address )
113- elif askedvalue == 43 :
114- _form_int16 (1 , address )
115- elif askedvalue == 50 :
116- _form_str (serial_number , address )
117- elif askedvalue == 60 :
118- _form_str (chargepoint .get .rfid , address )
122+ charge_point = SubData .internal_chargepoint_data [f"cp{ _charge_point_index (address )} " ]
123+ requested_value = _value_index (address )
124+
125+ if requested_value in int32_map :
126+ _form_int32 (int32_map [requested_value ](charge_point ), address )
127+ elif requested_value in int16_map :
128+ _form_int16 (int16_map [requested_value ](charge_point ), address )
129+ elif requested_value in str_map :
130+ _form_str (str_map [requested_value ](charge_point ), address )
131+ else :
132+ log .warning (f"Unbekannte Adresse: { address } " )
119133
120134 return data_store [address ]
121135except Exception :
122136 log .exception ("Fehler im Modbus-Server" )
123137
124138try :
125139 @app .route (slave_ids = [1 ], function_codes = [6 , 16 ], addresses = list (range (0 , 32000 )))
126- def write_data_store (slave_id , function_code , address , value ):
140+ def write_data_store (slave_id : int , function_code : int , address : int , value ):
127141 """" Set value for address. """
128142 if 10170 < address :
129- cp_topic = f"openWB/set/internal_chargepoint/{ _get_pos (address , 2 )} /data/"
130- askedvalue = int (str (address )[- 2 :])
131- if askedvalue == 71 :
132- Pub ().pub (f"{ cp_topic } set_current" , value / 100 )
133- elif askedvalue == 80 :
134- Pub ().pub (f"{ cp_topic } phases_to_use" , value )
135- elif askedvalue == 81 :
136- Pub ().pub (f"{ cp_topic } trigger_phase_switch" , value )
137- elif askedvalue == 98 :
138- Pub ().pub (f"{ cp_topic } cp_interruption_duration" , value )
139- elif askedvalue == 99 :
140- Pub ().pub ("openWB/set/command/modbus_server/todo" , {"command" : "systemUpdate" , "data" : {}})
143+ cp_topic = f"openWB/set/internal_chargepoint/{ _charge_point_index (address )} /data/"
144+ requested_value = _value_index (address )
145+
146+ write_map = {
147+ 71 : lambda value : Pub ().pub (f"{ cp_topic } set_current" , value / 100 ),
148+ 80 : lambda value : Pub ().pub (f"{ cp_topic } phases_to_use" , value ),
149+ 81 : lambda value : Pub ().pub (f"{ cp_topic } trigger_phase_switch" , value ),
150+ 98 : lambda value : Pub ().pub (f"{ cp_topic } cp_interruption_duration" , value ),
151+ 99 : lambda _ : Pub ().pub ("openWB/set/command/modbus_server/todo" ,
152+ {"command" : "systemUpdate" , "data" : {}})
153+ }
154+ if requested_value in write_map :
155+ write_map [requested_value ](value )
156+ else :
157+ log .warning (f"Unbekannte Adresse beim Schreiben: { address } " )
141158except Exception :
142159 log .exception ("Fehler im Modbus-Server" )
143160
144161
145162def start_modbus_server (event_modbus_server ):
146163 try :
147- # Wenn start_modbus_server aus SubData aufegrufen wird, wenn das Topic gesetzt wird, führt das zu einem
164+ # Wenn start_modbus_server aus SubData aufgerufen wird, wenn das Topic gesetzt wird, führt das zu einem
148165 # circular Import.
149166 event_modbus_server .wait ()
150167 event_modbus_server .clear ()
0 commit comments