Skip to content

Commit c40a953

Browse files
FW update added
1 parent f78c1d6 commit c40a953

9 files changed

+347
-3
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.save

UPS-2_G030.bak

64 KB
Binary file not shown.

UPS-2_G030.bin

17.9 KB
Binary file not shown.

stm32flash

117 KB
Binary file not shown.

testBoot.py

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import ups2_Interface as test
2+
import sys
3+
import os
4+
import time
5+
6+
7+
ser = test.ecInitSerial('/dev/serial0')
8+
ret = test.ecReqBootloader(ser)
9+
print(ret)
10+
time.sleep(2)
11+
12+
command = 'sudo pkill -f ups2_serial.py'
13+
os.system(str(command).encode())
14+
ser.close()
15+
16+
command = 'stm32flash -w UPS-2_G030.bin -v -g 0x0 /dev/serial0'
17+
os.system(str(command).encode())
18+
19+
command = 'python3 ups2_serial.py &'
20+
os.system(str(command).encode())
21+
22+

ups2_FirmwareUpd.py

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import PySimpleGUI as sg
2+
import ups2_update
3+
4+
def GetFileDialog():
5+
success = False
6+
sg.SetOptions(auto_size_buttons=True, font='Helvetica 11')
7+
8+
form_rows = [[sg.Text('Select Firmware Version')],
9+
[sg.Text('File', size=(15, 1)), sg.InputText(key='_file_'),
10+
sg.FileBrowse(button_text = '...' , initial_folder = './', file_types=(("UPS-2 Firmware", "*.bin"),))],
11+
[sg.Button('Update'), sg.Cancel()]]
12+
13+
window = sg.Window('Select UPS-2 Firmware Update')
14+
event, values = window.Layout(form_rows).Read()
15+
while True:
16+
if event in (None, 'Cancel'):
17+
window.close()
18+
return('')
19+
elif event == 'Update':
20+
success = ''
21+
newFile = values['_file_']
22+
if(newFile != ''):
23+
success = ups2_update.ecUpdateUPS(newFile, True)
24+
window.close()
25+
return newFile
26+
27+
if __name__ == "__main__":
28+
newFile = GetFileDialog()
29+
print(newFile)
30+
31+
32+
33+

ups2_GUI.py

+21-3
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,16 @@
1515
import PySimpleGUI as sg
1616
import os
1717
import ups2_Interface as ups
18+
import ups2_FirmwareUpd as FW_upd
1819

1920
GUI_Version = 'UPS GUI V0.8 '
2021

22+
# ------ Menu Definition ------ #
23+
menu_def = [['File ', ['Quit',]],
24+
['PowerControl ', ['Power OFF', 'Restart', 'Standby']],
25+
['About ', ['UPS-2 GUI', 'UPS-2 Firmware', 'PySimpleGUI']],
26+
['Firmware_Update', ['Browse...']]]
27+
2128

2229
print('PySimpleGUI Version', sg.version)
2330

@@ -48,12 +55,12 @@ def ecPopWin(count, title = 'ECOM UPS2'):
4855
'''
4956

5057
devider = count * 10
51-
layout2 = [[sg.Text('Pi shuddown in'),
58+
layout_shutDown = [[sg.Text('Pi shuddown in'),
5259
sg.Text('', key='barValue', size=(3,1), pad=(0,0)), sg.Text('seconds', pad=(0,0))],
5360
[sg.ProgressBar(devider, orientation='h', size=(20, 20), key='progressbar',
5461
bar_color=['lightgreen','grey'])],
5562
[sg.Button('Cancel'), sg.Button('Shutdown NOW', size=(12,1), focus=True)]]
56-
popWin = sg.Window(title , layout2)
63+
popWin = sg.Window(title , layout_shutDown)
5764

5865
while True:
5966
ev2, values2 = popWin.read(timeout=100)
@@ -164,7 +171,8 @@ def ecFormatDisplay(sysStatus, window):
164171
keypanel = [[sg.Button('Power OFF', tooltip='Disabled if USB powered'), sg.Button('Restart'), sg.Button('Standby'), sg.Button('Quit')]]
165172

166173
#frame layout around buttons
167-
layout = [[sg.Frame('Power Supply Overview', mainFrame)],
174+
layout = [[sg.Menu(menu_def)],
175+
[sg.Frame('Power Supply Overview', mainFrame)],
168176
[sg.Frame('', keypanel)]]
169177

170178

@@ -176,6 +184,7 @@ def ecFormatDisplay(sysStatus, window):
176184
print('UPS Status', ups2Values)
177185
analogStr = ups.ecFormatAnalog(ups2Values[1])
178186

187+
#titlebar = sg.Titlebar(title = 'hello')
179188
window = sg.Window(GUI_Version + " | " + ups2Version, layout)
180189

181190

@@ -196,8 +205,17 @@ def ecFormatDisplay(sysStatus, window):
196205
elif event == 'Standby':
197206
if ecPopWin(5, 'Standby') != 'cancel':
198207
os.system('sudo shutdown now\n')
208+
elif event == 'About':
209+
print('About event')
210+
elif event == 'Browse...':
211+
print ('FW update')
212+
window.hide()
213+
FW_upd.GetFileDialog()
214+
window.un_hide() #todo: close, if not cancelled
215+
199216
if divider < 100: #main processing tick = 1s
200217
divider +=1
218+
201219
else:
202220
divider = 0
203221
counter += 1

ups2_GUI_develop.py

+241
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Graphical interface for UPS-2 UART serial mode.
4+
5+
Usage:
6+
* For autostart: put this script in /etc/xdg/lxsession/LXDE-pi/autostart
7+
* This script needs PySimpleGUI.py found on https://github.com/PySimpleGUI/PySimpleGUI
8+
* Raspberry serial interface must be enabled (with raspi-config) i.e.
9+
* ups2_serial.py worker service must be started (instructions see docstring)
10+
"""
11+
#Todo: abs
12+
# calendar timed functions
13+
# email and/or other messaging functions
14+
15+
import PySimpleGUI as sg
16+
import os
17+
import ups2_Interface as ups
18+
import ups2_FirmwareUpd as FW_upd
19+
20+
GUI_Version = 'UPS GUI V0.8 '
21+
22+
# ------ Menu Definition ------ #
23+
menu_def = [['File ', ['Quit',]],
24+
['PowerControl ', ['Power OFF', 'Restart', 'Standby']],
25+
['About ', ['UPS-2 GUI', 'UPS-2 Firmware', 'PySimpleGUI']],
26+
['Firmware_Update', ['Browse...']]]
27+
28+
29+
print('PySimpleGUI Version', sg.version)
30+
31+
sg.theme('lightGreen')
32+
sg.SetOptions(button_element_size=(9,1), auto_size_buttons=False, font='Helvetica 11')
33+
ser = ups.ecInitSerial()
34+
fT = open("/sys/class/thermal/thermal_zone0/temp", "r") #Pi processor temperature
35+
36+
#globals
37+
bgOFF = 'lightgrey'
38+
bgOK = '#A2C477'
39+
bgLOW = 'lightblue'
40+
bgHIGH = 'orange'
41+
42+
keyMain = 'K_MAIN_V'
43+
keyBatt = 'K_BATT_V'
44+
keyUSB = 'K_USB'
45+
keyCPU = 'K_CPU_T'
46+
keyPiCPU = 'K_PI_T'
47+
48+
def ecPopWin(count, title = 'ECOM UPS2'):
49+
'''Opens a modal popup for count seconds and returns "shutdown" or "cancel"
50+
51+
Args:
52+
param count: countdown time in seconds
53+
param title: String to display in popup banner
54+
55+
'''
56+
57+
devider = count * 10
58+
layout_shutDown = [[sg.Text('Pi shuddown in'),
59+
sg.Text('', key='barValue', size=(3,1), pad=(0,0)), sg.Text('seconds', pad=(0,0))],
60+
[sg.ProgressBar(devider, orientation='h', size=(20, 20), key='progressbar',
61+
bar_color=['lightgreen','grey'])],
62+
[sg.Button('Cancel'), sg.Button('Shutdown NOW', size=(12,1), focus=True)]]
63+
popWin = sg.Window(title , layout_shutDown)
64+
65+
while True:
66+
ev2, values2 = popWin.read(timeout=100)
67+
devider -=1
68+
if devider:
69+
popWin['progressbar'].UpdateBar((devider))
70+
popWin['barValue'].update(devider/10)
71+
# popWin.set_title('123')
72+
if (ev2 == sg.WIN_CLOSED or ev2 == 'Cancel'):
73+
print('CANCELLED')
74+
action = 'cancel'
75+
popWin.close()
76+
return action
77+
elif ev2 == 'Shutdown NOW' or devider < 2:
78+
print('SHUTTING DOWN')
79+
action = 'shutdown'
80+
popWin.close()
81+
return action
82+
83+
84+
85+
def ecFormatDisplay(sysStatus, window):
86+
'''Set display attributes according to system state.
87+
88+
This function refreshes the display depending on the system state
89+
Must be periodically called by the main control loop
90+
91+
Args:
92+
sysStatus: string received from UPS-2 hardware
93+
window: initialized main window
94+
'''
95+
96+
s = int(sysStatus, 16) #sysStatus comes as string
97+
98+
#default values. In dictionary in order to easily update depending on status
99+
mainState = dict(key = keyMain, bgColor = bgOFF, borderW = 1, stat = 'OFF', selected = '')
100+
battState = dict(key = keyBatt, bgColor = bgOFF, borderW = 1, stat = 'OFF', selected = '')
101+
usbState = dict(key = keyUSB, text = '---', bgColor = bgOFF, borderW = 1, stat = 'OK', selected = '')
102+
# cpuState = dict(key = keyCPU, bgColor = bgOFF, borderW = 1, stat = 'OFF', selected = '')
103+
# piState = dict(key = keyPiCPU, bgColor = bgOFF, borderW = 1, stat = 'OFF', selected = '')
104+
105+
#decode status message from UPS
106+
if s & 0x0001: #main active
107+
mainState.update(selected = '@', bgColor = bgOK, borderW = 2)
108+
elif s & 0x0002: #batt active
109+
battState.update(selected = '@', bgColor = bgOK, borderW = 2)
110+
elif s & 0x0004: #usb active
111+
usbState.update(selected = '@', text = 'active', bgColor = bgOK, borderW = 2)
112+
if s & 0x0010: #main V present
113+
mainState.update(bgColor = bgOK, stat = 'OK')
114+
if s & 0x0020: #batt V present
115+
battState.update(bgColor = bgOK, stat = 'OK')
116+
if s & 0x0040: #usb V present
117+
usbState.update(bgColor = bgOK, text = 'active')
118+
if (s & 0x0110) == 0x0110: #main V LOW
119+
mainState.update(stat = 'LOW', bgColor = bgLOW)
120+
if s & 0x0200: #main V HIGH
121+
mainState.update(stat = 'HIGH', bgColor = bgHIGH)
122+
if (s & 0x0420) == 0x0420: #batt V LOW
123+
battState.update(stat = 'LOW', bgColor = bgLOW)
124+
if s & 0x0800: #batt V HIGH
125+
battState.update(stat = 'HIGH', bgColor = bgHIGH)
126+
if s & 0x1000: #CPU temp HIGH
127+
battState.update(stat = 'HIGH', bgColor = bgHIGH)
128+
129+
#adapt value displays
130+
window['K_MAIN_V'].update(background_color = mainState['bgColor'])
131+
window['K_MAIN_V'].Widget.configure(borderwidth = mainState['borderW']) #use underlying element
132+
window['K_MAIN_STATE'].update(mainState['stat'])
133+
window['K_BATT_V'].update(background_color = battState['bgColor'])
134+
window['K_BATT_V'].Widget.configure(borderwidth = battState['borderW']) #use underlying element
135+
window['K_BATT_STATE'].update(battState['stat'])
136+
window['K_USB'].update(background_color = usbState['bgColor'])
137+
window['K_USB'].update(usbState['text'])
138+
#adapt power button
139+
140+
if s & 0x0004:
141+
# window['Power OFF'].set_tooltip('Disabled, if USB 5V supplied')
142+
window['Power OFF'].update(disabled=True, disabled_button_color=('lightgrey', 'none'))
143+
144+
else:
145+
window['Power OFF'].update(disabled=False)
146+
# window['Power OFF'].SetTooltip('')
147+
148+
# Main window column layout
149+
col1 = [[sg.Text(text='Main supply', key="K_MAIN_LBL", size=(10,0), justification='right')],
150+
[sg.Text(text='Batt supply', key='K_BATT_LBL', size=(10,1), justification='right')],
151+
[sg.Text(text='Pi USB', key='K_USB_LBL', size=(10,1),justification='right')]]
152+
153+
col2 = [[sg.Text(text='12.2V', key="K_MAIN_V", relief=sg.RELIEF_SOLID, border_width=1, justification='right', background_color='#A2C477',size=(6,1))],
154+
[sg.Text(text='5.1V', key="K_BATT_V", relief=sg.RELIEF_SOLID, border_width=1, justification='right', background_color='#A2C477',size=(6,1))],
155+
[sg.Text(text=' ', key="K_USB", relief=sg.RELIEF_SOLID, justification='center', background_color='lightgrey', size=(6,1))]]
156+
157+
col3 = [[sg.Text('OK', key='K_MAIN_STATE', size=(6,1))],
158+
[sg.Text('LOW', key='K_BATT_STATE', size=(6,1))],
159+
[sg.Text('')]]
160+
161+
col4 = [[sg.Text('UPS CPU', size=(12,1), justification='right')],
162+
[sg.Text('Pi CPU', size=(12,1), justification='right')]]
163+
164+
col5 = [[sg.Text(text=' °C', key='K_CPU_T',relief=sg.RELIEF_SOLID, justification='right', background_color='#A2C477',size=(5,1))],
165+
[sg.Text(text=' °C', key='K_PI_T',relief=sg.RELIEF_SOLID, justification='right', background_color='#A2C477',size=(5,1))]]
166+
167+
#frame layout around readouts
168+
mainFrame = [[ sg.Column(col1), sg.Column(col2), sg.Column(col3), sg.Column(col4), sg.Column(col5)]]
169+
170+
#buttons to appear in frame below
171+
keypanel = [[sg.Button('Power OFF', tooltip='Disabled if USB powered'), sg.Button('Restart'), sg.Button('Standby'), sg.Button('Quit')]]
172+
173+
#frame layout around buttons
174+
layout = [[sg.Menu(menu_def)],
175+
[sg.Frame('Power Supply Overview', mainFrame)],
176+
[sg.Frame('', keypanel)]]
177+
178+
179+
180+
# Display, get values
181+
#window = sg.Window('ECOM UPS GUI V0.8', layout, location=(350,350))
182+
ups2Values = ups.ecGetUPSValues(ser)
183+
ups2Version = ups.ecGetUPSVersion(ser)
184+
print('UPS Status', ups2Values)
185+
analogStr = ups.ecFormatAnalog(ups2Values[1])
186+
187+
#titlebar = sg.Titlebar(title = 'hello')
188+
window = sg.Window(GUI_Version + " | " + ups2Version, layout)
189+
190+
191+
piTemp = '0'
192+
counter = 1
193+
divider = 0
194+
while 1:
195+
event, values = window.read(timeout=10) #time.sleep() may be used instead
196+
if event in (None, 'Quit'):
197+
break
198+
if event == 'Power OFF':
199+
if ecPopWin(5, 'POWER OFF') != 'cancel':
200+
ups.ecReqUPSPowerDown(ser)
201+
os.system('sudo shutdown -P now\n')
202+
elif event == 'Restart':
203+
if ecPopWin(5, 'Restart') != 'cancel':
204+
os.system('sudo shutdown -r now\n')
205+
elif event == 'Standby':
206+
if ecPopWin(5, 'Standby') != 'cancel':
207+
os.system('sudo shutdown now\n')
208+
elif event == 'About':
209+
print('About event')
210+
elif event == 'Browse...':
211+
print ('FW update')
212+
window.hide()
213+
FW_upd.GetFileDialog()
214+
window.un_hide() #todo: close, if not cancelled
215+
216+
if divider < 100: #main processing tick = 1s
217+
divider +=1
218+
219+
else:
220+
divider = 0
221+
counter += 1
222+
#real time value updates
223+
ups2Values = ups.ecGetUPSValues(ser)
224+
sysStatus = ups2Values[0]
225+
print (sysStatus)
226+
AnalogList = ups.ecFormatAnalog(ups2Values[1])
227+
piTemp = fT.readline()
228+
fT.seek(0) #reset to first line
229+
piTemp = piTemp[0:2] + '°C'
230+
#set display attributes
231+
ecFormatDisplay(sysStatus, window)
232+
#update values
233+
window['K_MAIN_V'].update(AnalogList[0])
234+
window['K_BATT_V'].update(AnalogList[1])
235+
window['K_CPU_T'].update(AnalogList[2])
236+
window['K_PI_T'].update(piTemp)
237+
238+
# time.sleep(.5)
239+
fT.close()
240+
ser.close()
241+
window.close()

ups2_update.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import ups2_Interface as test
2+
import sys
3+
import os
4+
import time
5+
6+
def ecUpdateUPS(newFile = 'UPS-2_G030.bin', backup = False):
7+
ser = test.ecInitSerial('/dev/serial0')
8+
ret = test.ecReqBootloader(ser) #send a request to UPS2
9+
print(ret)
10+
time.sleep(2) #todo ack from UPS2 instead of wait
11+
12+
#we have to free serial interface for flashing software
13+
command = 'sudo pkill -f ups2_serial.py'
14+
os.system(str(command).encode())
15+
ser.close()
16+
if backup == True:
17+
command = 'stm32flash -r UPS-2_G030.bak /dev/serial0'
18+
os.system(str(command).encode())
19+
command = 'stm32flash -w ' + newFile + ' -v -g 0x0 /dev/serial0'
20+
ret = os.system(str(command).encode())
21+
22+
#now restore serial interface
23+
command = 'python3 ups2_serial.py &'
24+
ret = os.system(str(command).encode())
25+
26+
return ret
27+
28+
if __name__ == "__main__":
29+
ecUpdateUPS()

0 commit comments

Comments
 (0)