25
25
26
26
MQTT_active = config .get ('MQTT' , 'MQTT_active' )
27
27
MQTT_broker = config .get ('MQTT' , 'MQTT_broker' )
28
+ MQTT_port = int (config .get ('MQTT' , 'MQTT_port' ))
29
+ MQTT_username = config .get ('MQTT' , 'MQTT_username' )
30
+ MQTT_password = config .get ('MQTT' , 'MQTT_password' )
28
31
29
32
start_time = time .time ()
30
33
up_time = time .time ()
33
36
errors_no = 0 # used to count no of errors and to calculate %
34
37
errors = 'false'
35
38
36
- print ('PytesSerial build: v0.2.3_20230114 ' )
39
+ print ('PytesSerial build: v0.3.0_20230123 ' )
37
40
38
41
# ------------------------functions area----------------------------
39
42
def log (str ) :
@@ -45,23 +48,32 @@ def log (str) :
45
48
return
46
49
except Exception as e :
47
50
print ("Errorhandling: double error in EventLog" , e )
48
-
51
+
49
52
def parsing_serial ():
50
- global errors
51
- if ser .is_open != True :
52
- ser .open ()
53
- time .sleep (0.2 )
54
- print ('...serial opened' )
55
- for power in range (1 , powers + 1 ): # do the loop for each battery
56
- try :
57
- # parsing pwr x commmand - reading power bank x
58
- line_str = "" # clear line_str
59
- line = "" # clear line
60
- power_bytes = bytes (str (power ), 'ascii' ) # convert to bytes
61
- ser .write (b'pwr ' + power_bytes + b'\n ' ) # write on serial port 'pwr x' command
53
+ global errors
54
+ volt_st = None # initiate non critical variable to ensure various firmaware combatibility
55
+ current_st = None
56
+ temp_st = None
57
+ coul_st = None
58
+ soh_st = None
59
+ heater_st = None
60
+ bat_events = None
61
+ power_events = None
62
+ sys_events = None
63
+
64
+ try :
65
+ if ser .is_open != True :
66
+ ser .open ()
67
+ print ('...serial opened' )
68
+
69
+ for power in range (1 , powers + 1 ): # do the loop for each battery
70
+ line_str = "" # clear line_str
71
+ line = "" # clear line
72
+ power_bytes = bytes (str (power ), 'ascii' ) # convert to bytes
73
+ ser .write (b'pwr ' + power_bytes + b'\n ' ) # write on serial port 'pwr x' command
62
74
ser .flush ()
63
75
64
- time .sleep (0.2 ) # calm down a bit ...
76
+ time .sleep (0.5 ) # calm down a bit ...
65
77
buffer = ser .in_waiting
66
78
print ('...writing complete ' , 'in buffer:' , buffer )
67
79
@@ -73,12 +85,12 @@ def parsing_serial():
73
85
print ('...suspicious data set, trying again' )
74
86
errors = 'true'
75
87
76
- log ('*' + str (errors_no )+ '*' + str (buffer )+ '**>' + str (line )) # [DPO] for debug purpose remark the line
88
+ log ('*' + str (errors_no )+ '*' + str (buffer )+ '**>' + str (line )) # [DPO] for debug purpose
77
89
78
90
if ser .is_open == True :
79
91
ser .close ()
80
92
print ('...serial closed' )
81
- return # do not move forward if no end of the parsing group detected
93
+ return # do not move forward if no end of the parsing group detected
82
94
83
95
if line_str [1 :18 ] == 'Voltage :' : voltage = int (line_str [19 :27 ])/ 1000
84
96
if line_str [1 :18 ] == 'Current :' : current = int (line_str [19 :27 ])/ 1000
@@ -93,7 +105,7 @@ def parsing_serial():
93
105
if line_str [1 :18 ] == 'Heater Status :' : heater_st = line_str [19 :27 ]
94
106
if line_str [1 :18 ] == 'Bat Events :' : bat_events = int (line_str [19 :27 ],16 )
95
107
if line_str [1 :18 ] == 'Power Events :' : power_events = int (line_str [19 :27 ],16 )
96
- if line_str [1 :18 ] == 'System Fault :' : sys_events = int (line_str [19 :27 ],16 )
108
+ if line_str [1 :18 ] == 'System Fault :' : sys_events = int (line_str [19 :27 ],16 )
97
109
if line_str [1 :18 ] == 'Command completed' :
98
110
break
99
111
@@ -132,28 +144,62 @@ def parsing_serial():
132
144
'sys_events' : sys_events }
133
145
134
146
pwr .append (pwr_array )
135
-
136
- except Exception as e :
137
- print ("...serial parsing error: " + str (e ))
138
- errors = 'true'
139
-
140
- log ('*' + str (errors_no )+ '*' + str (buffer )+ '**>' + str (line )) # [DPO] for debug purpose remark the line
141
147
142
- if ser .is_open == True :
143
- ser .close ()
144
- print ('...serial closed' )
145
- return
148
+ statistics ()
149
+
150
+ print ('...serial parsing: ok' )
151
+
152
+ except Exception as e :
153
+ print ("...serial parsing error: " + str (e ))
154
+ errors = 'true'
155
+ if ser .is_open == True :
156
+ ser .close ()
157
+ print ('...serial closed' )
158
+ return
159
+
160
+ log ('*' + str (errors_no )+ '*' + str (buffer )+ '**>' + str (line )) # [DPO] for debug purpose
146
161
147
- print ('...serial parsing: ok' )
162
+ def statistics ():
163
+ global sys_voltage
164
+ global sys_current
165
+ global sys_soc
166
+ global sys_temp
167
+ global sys_basic_st
168
+ sys_voltage = 0
169
+ sys_current = 0
170
+ sys_soc = 0
171
+ sys_temp = 0
172
+ sys_basic_st = ""
173
+
174
+ for power in range (1 , powers + 1 ):
175
+ sys_voltage = sys_voltage + pwr [power - 1 ]['voltage' ] # vontage will be the average of all batteries
176
+ sys_current = round ((sys_current + pwr [power - 1 ]['current' ]),3 ) # current will be sum of all banks
177
+ sys_soc = sys_soc + pwr [power - 1 ]['soc' ] # soc will be the average of all batteries
178
+ sys_temp = sys_temp + pwr [power - 1 ]['temperature' ] # temperature will be the average of all batteries
179
+
180
+ sys_voltage = round ((sys_voltage / powers ), 3 )
181
+ sys_soc = int (sys_soc / powers )
182
+ sys_basic_st = pwr [0 ]['basic_st' ] # status will be the master status
183
+ sys_temp = round ((sys_temp / powers ), 1 )
148
184
149
185
def json_serialize ():
150
186
global errors
151
187
global json_data
152
188
try :
153
- json_data = {'relay_local_time' :TimeStamp , 'serial_uptime' :uptime , 'pytes' :pwr }
189
+ json_data = {'relay_local_time' :TimeStamp ,
190
+ 'serial_uptime' :uptime ,
191
+ 'powers' : powers ,
192
+ 'voltage' : sys_voltage ,
193
+ 'current' : sys_current ,
194
+ 'temperature' : sys_temp ,
195
+ 'soc' : sys_soc ,
196
+ 'basic_st' : sys_basic_st ,
197
+ 'pytes' :pwr }
198
+
154
199
with open (output_path + 'pytes_status.json' , 'w' ) as outfile :
155
200
json .dump (json_data , outfile )
156
- print ('...json creation: ok' )
201
+ print ('...json creation: ok' )
202
+
157
203
except Exception as e :
158
204
print ('...json serailization error: ' + str (e ))
159
205
errors = 'true'
@@ -208,13 +254,39 @@ def maria_db():
208
254
209
255
def mqtt_discovery ():
210
256
try :
257
+ MQTT_auth = None
258
+ if len (MQTT_username ) > 0 :
259
+ MQTT_auth = { 'username' : MQTT_username , 'password' : MQTT_password }
211
260
msg = {}
212
261
config = 1
213
262
names = ["pytes_current" , "pytes_voltage" , "pytes_temperature" , "pytes_soc" , "pytes_status" ]
214
263
ids = ["current" , "voltage" , "temperature" , "soc" , "basic_st" ] #do not change the prefix "pytes_"
215
264
dev_cla = ["current" , "voltage" , "temperature" , "battery" ,"None" ]
216
265
unit_of_meas = ["A" ,"v" ,"°C" , "%" ,"" ]
217
266
267
+ # define system sensors
268
+ for n in range (5 ):
269
+ state_topic = "homeassistant/sensor/pytes/" + str (config )+ "/config"
270
+ msg ["name" ] = names [n ]
271
+ msg ["stat_t" ] = "homeassistant/sensor/pytes/state"
272
+ msg ["uniq_id" ] = "pytes_" + ids [n ]
273
+ if dev_cla [n ] != "None" :
274
+ msg ["dev_cla" ] = dev_cla [n ]
275
+ msg ["unit_of_meas" ] = unit_of_meas [n ]
276
+ msg ["val_tpl" ] = "{{ value_json." + ids [n ]+ "}}"
277
+ msg ["dev" ] = {"identifiers" : ["pytes" ],"manufacturer" : "PYTES" ,"model" : "E-Box48100R" ,"name" : "pytes_ebox" ,"sw_version" : "1.0" }
278
+
279
+ message = json .dumps (msg )
280
+ publish .single (state_topic , message , hostname = MQTT_broker , port = MQTT_port , auth = MQTT_auth , qos = 0 , retain = True )
281
+
282
+ b = "...mqtt auto discovery initialization :" + str (round (config / (5 * powers + 5 )* 100 )) + " %"
283
+ print (b , end = "\r " )
284
+
285
+ msg = {}
286
+ config = config + 1
287
+ time .sleep (2 )
288
+
289
+ # define individual batteries sensors
218
290
for power in range (1 , powers + 1 ):
219
291
for n in range (5 ):
220
292
state_topic = "homeassistant/sensor/pytes/" + str (config )+ "/config"
@@ -228,23 +300,28 @@ def mqtt_discovery():
228
300
msg ["dev" ] = {"identifiers" : ["pytes" ],"manufacturer" : "PYTES" ,"model" : "E-Box48100R" ,"name" : "pytes_ebox" ,"sw_version" : "1.0" }
229
301
230
302
message = json .dumps (msg )
231
- publish .single (state_topic , message , hostname = MQTT_broker , qos = 0 , retain = True )
303
+ publish .single (state_topic , message , hostname = MQTT_broker , port = MQTT_port , auth = MQTT_auth , qos = 0 , retain = True )
232
304
305
+ b = "...mqtt auto discovery initialization :" + str (round (config / (5 * powers + 5 )* 100 )) + " %"
306
+ print (b , end = "\r " )
307
+
233
308
msg = {}
234
309
config = config + 1
235
- b = "...mqtt auto discovery initialization" + "." * config
236
- print (b , end = "\r " )
237
310
time .sleep (2 )
311
+
238
312
print ("...mqtt auto discovery initialization completed" )
239
313
240
314
except Exception as e :
241
315
print ('...mqtt_discovery failed' + str (e ))
242
316
243
317
def mqtt_publish ():
244
318
try :
319
+ MQTT_auth = None
320
+ if len (MQTT_username ) > 0 :
321
+ MQTT_auth = { 'username' : MQTT_username , 'password' : MQTT_password }
245
322
state_topic = "homeassistant/sensor/pytes/state"
246
323
message = json .dumps (json_data )
247
- publish .single (state_topic , message , hostname = MQTT_broker )
324
+ publish .single (state_topic , message , hostname = MQTT_broker , port = MQTT_port , auth = MQTT_auth )
248
325
print ('...mqtt publish : ok' )
249
326
250
327
except Exception as e :
0 commit comments