Commit f93022a0 authored by Benjamin Mummery's avatar Benjamin Mummery 💻

update battery display for 2 batteries

At present raspberry-dataserver/BatteryLLI.py uses popen to run
upower as a shell command and parses the output. This should be
replaced by the upower python script (I would have done this, but I
can't compile upower on the Pi to test it)

raspberry-dataserver/CommsCommon.py is modified to add new parameters to
BatteryFormat (bat1_percent and bat2_percent, both ints). All other
parameters in BatteryFormat are unchanged.
parent 6abc4d31
...@@ -15,8 +15,9 @@ class BatteryHandler(PayloadHandler): ...@@ -15,8 +15,9 @@ class BatteryHandler(PayloadHandler):
self.__battery_status = { self.__battery_status = {
"on_mains_power":False, "on_mains_power":False,
"on_battery_power":False, "on_battery_power":False,
"battery_percent":0, "battery_percent_1":0,
"electrical_problem": "ERROR ELEC." "battery_percent_2":0,
"electrical_problem": "ERR"
} }
def active_payload(self, *args, **kwargs) -> int: def active_payload(self, *args, **kwargs) -> int:
...@@ -39,15 +40,20 @@ class BatteryHandler(PayloadHandler): ...@@ -39,15 +40,20 @@ class BatteryHandler(PayloadHandler):
logging.debug("Keyerror in battery payload: 'bat'") logging.debug("Keyerror in battery payload: 'bat'")
try: try:
new_status["battery_percent"] = self.compute_battery_percent(battery_data) new_status["battery_percent_1"] = int(battery_data["bat1_percent"])
except KeyError: except KeyError:
logging.debug("Keyerror in battery payload: 'bat85'") logging.debug("Keyerror in battery payload: 'bat1_percent'")
try:
new_status["battery_percent_2"] = int(battery_data["bat2_percent"])
except KeyError:
logging.debug("Keyerror in battery payload: 'bat2_percent'")
try: try:
if battery_data["prob_elec"] == 0: if battery_data["prob_elec"] == 0:
new_status["electrical_problem"] = None new_status["electrical_problem"] = None
else: else:
new_status["electrical_problem"] = "ERROR ELEC." new_status["electrical_problem"] = "ERR"
except KeyError: except KeyError:
logging.debug("Keyerror in battery payload: 'prob_elec'") logging.debug("Keyerror in battery payload: 'prob_elec'")
...@@ -56,7 +62,7 @@ class BatteryHandler(PayloadHandler): ...@@ -56,7 +62,7 @@ class BatteryHandler(PayloadHandler):
# If there is conflicting information w.r.t. power source, report a problem # If there is conflicting information w.r.t. power source, report a problem
new_status["on_mains_power"] = False new_status["on_mains_power"] = False
new_status["on_battery_power"] = False new_status["on_battery_power"] = False
new_status["electrical_problem"] = "ERROR ELEC." new_status["electrical_problem"] = "ERR"
self.__battery_status = new_status self.__battery_status = new_status
...@@ -67,22 +73,22 @@ class BatteryHandler(PayloadHandler): ...@@ -67,22 +73,22 @@ class BatteryHandler(PayloadHandler):
self.UpdateBatteryDisplay.emit(self.__battery_status) self.UpdateBatteryDisplay.emit(self.__battery_status)
return 0 return 0
def compute_battery_percent(self, battery_data: dict) -> float: # def compute_battery_percent(self, battery_data: dict) -> float:
""" # """
Determine the current battery percentage from the information in battery_data. # Determine the current battery percentage from the information in battery_data.
As of 17/03/21 battery payloads only contain enough information to # As of 17/03/21 battery payloads only contain enough information to
determine if the battery is above or below 85% battery life. # determine if the battery is above or below 85% battery life.
Unless provided with specific information to the contrary, assume that the # Unless provided with specific information to the contrary, assume that the
battery is on 0% so that we should never overestimate how much remains. # battery is on 0% so that we should never overestimate how much remains.
""" # """
if battery_data["bat85"] == 1: # if battery_data["bat85"] == 1:
return 85.0 # return 85.0
elif battery_data["bat85"] == 0: # elif battery_data["bat85"] == 0:
return 0.0 # return 0.0
else: # else:
raise TypeError( # raise TypeError(
"Battery Percentage (entry 'bat85' in the battery payload) is not 1 or 2." # "Battery Percentage (entry 'bat85' in the battery payload) is not 1 or 2."
) # )
...@@ -186,10 +186,10 @@ class Layout: ...@@ -186,10 +186,10 @@ class Layout:
# Define Sizes # Define Sizes
f_mode = 0.15 f_mode = 0.15
f_battery = 0.2 f_battery = 0.235
f_lock = 0.1 f_lock = 0.01
f_localisation = 0.1 f_localisation = 0.1
f_alarm = 0.2 f_alarm = 0.115
f_personal = 1 - (f_mode + f_battery + f_lock + f_localisation + f_alarm) f_personal = 1 - (f_mode + f_battery + f_lock + f_localisation + f_alarm)
mode_display_width = int(self.screen_width * f_mode) mode_display_width = int(self.screen_width * f_mode)
......
...@@ -58,6 +58,7 @@ class AlarmControlWidget(QtWidgets.QWidget): ...@@ -58,6 +58,7 @@ class AlarmControlWidget(QtWidgets.QWidget):
"background-color: " "background-color: "
+ NativeUI.colors["button_background_enabled"].name() + NativeUI.colors["button_background_enabled"].name()
+ "; border:none;" + "; border:none;"
+ "color:" + NativeUI.colors["page_foreground"].name() + ";"
) )
self.iconStack.addWidget(self.onSpeakers) self.iconStack.addWidget(self.onSpeakers)
self.offSpeakers = QtWidgets.QPushButton() self.offSpeakers = QtWidgets.QPushButton()
...@@ -66,6 +67,7 @@ class AlarmControlWidget(QtWidgets.QWidget): ...@@ -66,6 +67,7 @@ class AlarmControlWidget(QtWidgets.QWidget):
"background-color: " "background-color: "
+ NativeUI.colors["button_background_enabled"].name() + NativeUI.colors["button_background_enabled"].name()
+ "; border:none;" + "; border:none;"
+ "color:" + NativeUI.colors["page_foreground"].name() + ";"
) )
self.iconStack.addWidget(self.offSpeakers) self.iconStack.addWidget(self.offSpeakers)
hlayout.addWidget(self.iconStack) hlayout.addWidget(self.iconStack)
...@@ -83,19 +85,19 @@ class AlarmControlWidget(QtWidgets.QWidget): ...@@ -83,19 +85,19 @@ class AlarmControlWidget(QtWidgets.QWidget):
pixmap.setMask(mask) pixmap.setMask(mask)
self.onSpeakers.setIcon(QtGui.QIcon(pixmap)) self.onSpeakers.setIcon(QtGui.QIcon(pixmap))
self.__icon_path = os.path.join(NativeUI.iconpath, "bell-regular.png") # self.__icon_path = os.path.join(NativeUI.iconpath, "bell-regular.png")
pixmap = QtGui.QPixmap(self.__icon_path) # pixmap = QtGui.QPixmap(self.__icon_path)
mask = pixmap.mask() # mask = pixmap.mask()
pixmap.fill(NativeUI.colors["plot_flow"]) # pixmap.fill(NativeUI.colors["plot_flow"])
pixmap.setMask(mask) # pixmap.setMask(mask)
self.offSpeakers.setIcon(QtGui.QIcon(pixmap)) # self.offSpeakers.setIcon(QtGui.QIcon(pixmap))
self.timeLabel = QtWidgets.QLabel("") # self.timeLabel = QtWidgets.QLabel("")
self.timeLabel.setFont(NativeUI.value_font) self.offSpeakers.setFont(NativeUI.value_font)
self.timeLabel.setStyleSheet( # self.timeLabel.setStyleSheet(
"color:" + NativeUI.colors["page_foreground"].name() + ";" # "color:" + NativeUI.colors["page_foreground"].name() + ";"
) # )
hlayout.addWidget(self.timeLabel) # hlayout.addWidget(self.timeLabel)
self.setLayout(hlayout) self.setLayout(hlayout)
self.timer = QtCore.QTimer() self.timer = QtCore.QTimer()
...@@ -107,7 +109,7 @@ class AlarmControlWidget(QtWidgets.QWidget): ...@@ -107,7 +109,7 @@ class AlarmControlWidget(QtWidgets.QWidget):
def mute_timer(self): def mute_timer(self):
self.remaining_mute_time += -1 self.remaining_mute_time += -1
self.timeLabel.setText(str(self.remaining_mute_time)) self.offSpeakers.setText(str(self.remaining_mute_time))
if self.remaining_mute_time == 0: if self.remaining_mute_time == 0:
self.unmute_pressed() self.unmute_pressed()
...@@ -122,7 +124,7 @@ class AlarmControlWidget(QtWidgets.QWidget): ...@@ -122,7 +124,7 @@ class AlarmControlWidget(QtWidgets.QWidget):
def unmute_pressed(self): def unmute_pressed(self):
self.timer.stop() self.timer.stop()
self.remaining_mute_time = 120 self.remaining_mute_time = 120
self.timeLabel.setText("") self.offSpeakers.setText("120")
self.buttonPushed(self.volState) self.buttonPushed(self.volState)
self.iconStack.setCurrentWidget(self.onSpeakers) self.iconStack.setCurrentWidget(self.onSpeakers)
self.NativeUI.q_send_cmd("MUTE_ALARM", "FALSE") self.NativeUI.q_send_cmd("MUTE_ALARM", "FALSE")
...@@ -157,7 +159,11 @@ class AlarmControlWidget(QtWidgets.QWidget): ...@@ -157,7 +159,11 @@ class AlarmControlWidget(QtWidgets.QWidget):
logging.debug('didnt work') logging.debug('didnt work')
def set_size(self, x: int, y: int, spacing=10) -> int: def set_size(self, x: int, y: int, spacing=10) -> int:
if x < 2.2*y:
x = 2.2*y
self.setFixedSize(x, y) self.setFixedSize(x, y)
self.offSpeakers.setFixedSize(1.1*y,y)
self.onSpeakers.setFixedSize(1.1*y,y)
return 0 return 0
def localise_text(self, text: dict) -> int: def localise_text(self, text: dict) -> int:
......
...@@ -29,9 +29,11 @@ class BatteryDisplayWidget(QtWidgets.QWidget): ...@@ -29,9 +29,11 @@ class BatteryDisplayWidget(QtWidgets.QWidget):
self.NativeUI = NativeUI self.NativeUI = NativeUI
layout = QtWidgets.QHBoxLayout(self) layout = QtWidgets.QHBoxLayout(self)
self.icon_display = BatteryIcon(NativeUI) self.icon_display_1 = BatteryIcon(NativeUI, "battery_percent_1")
self.text_display = BatteryText(NativeUI) self.text_display_1 = BatteryText(NativeUI, "battery_percent_1")
self.widgets = [self.icon_display, self.text_display] self.icon_display_2 = BatteryIcon(NativeUI, "battery_percent_2")
self.text_display_2 = BatteryText(NativeUI, "battery_percent_2")
self.widgets = [self.icon_display_1, self.text_display_1, self.icon_display_2, self.text_display_2]
for widget in self.widgets: for widget in self.widgets:
layout.addWidget(widget, alignment=QtCore.Qt.AlignRight) layout.addWidget(widget, alignment=QtCore.Qt.AlignRight)
...@@ -80,9 +82,11 @@ class BatteryDisplayWidget(QtWidgets.QWidget): ...@@ -80,9 +82,11 @@ class BatteryDisplayWidget(QtWidgets.QWidget):
assert isinstance(x, int) assert isinstance(x, int)
assert isinstance(y, int) assert isinstance(y, int)
self.setFixedSize(x, y) self.setFixedSize(2*(int(x/2)-y), y)
self.icon_display.set_size(y, y) self.icon_display_1.set_size(y, y)
self.text_display.set_size(x - y, y) self.text_display_1.set_size(int(x/2) - y, y)
self.icon_display_2.set_size(y, y)
self.text_display_2.set_size(int(x/2) - y, y)
return 0 return 0
def setFont(self, font: QtGui.QFont) -> int: def setFont(self, font: QtGui.QFont) -> int:
...@@ -90,7 +94,8 @@ class BatteryDisplayWidget(QtWidgets.QWidget): ...@@ -90,7 +94,8 @@ class BatteryDisplayWidget(QtWidgets.QWidget):
Overrides the existing setFont method in order to propogate the change to Overrides the existing setFont method in order to propogate the change to
subwidgets. subwidgets.
""" """
self.text_display.setFont(font) self.text_display_1.setFont(font)
self.text_display_2.setFont(font)
return 0 return 0
def localise_text(self, text: dict) -> int: def localise_text(self, text: dict) -> int:
...@@ -103,10 +108,11 @@ class BatteryDisplayWidget(QtWidgets.QWidget): ...@@ -103,10 +108,11 @@ class BatteryDisplayWidget(QtWidgets.QWidget):
class BatteryText(QtWidgets.QLabel): class BatteryText(QtWidgets.QLabel):
"""""" """"""
def __init__(self, NativeUI, *args, **kwargs): def __init__(self, NativeUI, key, *args, **kwargs):
super().__init__("", *args, **kwargs) super().__init__("", *args, **kwargs)
self.__size = (0, 0) self.__size = (0, 0)
self.key = key
self.setStyleSheet( self.setStyleSheet(
"background-color:" + NativeUI.colors["page_background"].name() + ";" "background-color:" + NativeUI.colors["page_background"].name() + ";"
...@@ -125,7 +131,7 @@ class BatteryText(QtWidgets.QLabel): ...@@ -125,7 +131,7 @@ class BatteryText(QtWidgets.QLabel):
self.__apply_temp_size(0, self.__size[1]) self.__apply_temp_size(0, self.__size[1])
return 0 return 0
self.setText(str(status["battery_percent"]) + " %") self.setText(str(status[self.key]) + " %")
return 0 return 0
def set_size(self, x: int, y: int) -> int: def set_size(self, x: int, y: int) -> int:
...@@ -161,9 +167,9 @@ class BatteryIcon(QtWidgets.QPushButton): ...@@ -161,9 +167,9 @@ class BatteryIcon(QtWidgets.QPushButton):
Widget to display the current battery icon Widget to display the current battery icon
""" """
def __init__(self, NativeUI, *args, **kwargs): def __init__(self, NativeUI, key, *args, **kwargs):
super().__init__("", *args, **kwargs) super().__init__("", *args, **kwargs)
self.key = key
self.NativeUI = NativeUI self.NativeUI = NativeUI
self.__icon_list = self.__make_icon_list() self.__icon_list = self.__make_icon_list()
self.__mains_icon = os.path.join(self.NativeUI.iconpath, "plug-solid.png") self.__mains_icon = os.path.join(self.NativeUI.iconpath, "plug-solid.png")
...@@ -191,7 +197,7 @@ class BatteryIcon(QtWidgets.QPushButton): ...@@ -191,7 +197,7 @@ class BatteryIcon(QtWidgets.QPushButton):
self.setIcon( self.setIcon(
QtGui.QIcon( QtGui.QIcon(
self.__icon_list[self.__get_range_index(status["battery_percent"])] self.__icon_list[self.__get_range_index(status[self.key])]
) )
) )
return 0 return 0
...@@ -215,7 +221,7 @@ class BatteryIcon(QtWidgets.QPushButton): ...@@ -215,7 +221,7 @@ class BatteryIcon(QtWidgets.QPushButton):
""" """
if self.__icon_list is None: if self.__icon_list is None:
self.__icon_list = self.__make_icon_list() self.__icon_list = self.__make_icon_list()
n_icons = len(self.__icon_list) n_icons = len(self.__icon_list)-1
percent_per_icon = 100.0 / n_icons percent_per_icon = 100.0 / n_icons
if percent_per_icon < zero_point: if percent_per_icon < zero_point:
zero_point = percent_per_icon zero_point = percent_per_icon
...@@ -239,6 +245,7 @@ class BatteryIcon(QtWidgets.QPushButton): ...@@ -239,6 +245,7 @@ class BatteryIcon(QtWidgets.QPushButton):
"battery-quarter-solid.png", "battery-quarter-solid.png",
"battery-half-solid.png", "battery-half-solid.png",
"battery-three-quarters-solid.png", "battery-three-quarters-solid.png",
"battery-full-solid.png",
] ]
icon_list = [os.path.join(self.NativeUI.iconpath, icon) for icon in icon_list] icon_list = [os.path.join(self.NativeUI.iconpath, icon) for icon in icon_list]
return icon_list return icon_list
......
...@@ -71,6 +71,7 @@ class BatteryLLI: ...@@ -71,6 +71,7 @@ class BatteryLLI:
async def main(self) -> None: async def main(self) -> None:
while True: while True:
await asyncio.sleep(self._timeout) await asyncio.sleep(self._timeout)
print(1)
payload = BatteryFormat(dummy=self._dummy) payload = BatteryFormat(dummy=self._dummy)
try: try:
for pin in self._pins: for pin in self._pins:
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
import asyncio import asyncio
import logging import logging
import copy import copy
import os
from CommsCommon import BatteryFormat from CommsCommon import BatteryFormat
# Set up logging # Set up logging
logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s') logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s')
...@@ -72,9 +73,78 @@ class BatteryLLI: ...@@ -72,9 +73,78 @@ class BatteryLLI:
while True: while True:
await asyncio.sleep(self._timeout) await asyncio.sleep(self._timeout)
payload = BatteryFormat(dummy=self._dummy) payload = BatteryFormat(dummy=self._dummy)
# Get output from upower
# TODO: change this to use the upower python module
upower_out_list = os.popen("./../upower/upower22/src/upower_22").read().split('\n')
upower_out_dict = {}
for l in upower_out_list:
tmp = l.split("=")
if len(tmp) != 2:
logging.debug("Skipping upower output line: %s" % l)
continue
key = tmp[0].lstrip().rstrip()
value = tmp[1].lstrip().rstrip()
if key in upower_out_dict:
key += "_2"
upower_out_dict[key] = value
del upower_out_list
# set bat value
payload_dict = {}
try:
if upower_out_dict["AC Status"] == "No Plug":
payload_dict["ok"] = 1
payload_dict["bat"] = 0
else:
payload_dict["ok"] = 0
payload_dict["bat"] = 1
except KeyError:
logging.warning("No key 'AC Status' in upower output")
payload_dict["ok"] = 0
payload_dict["bat"] = 0
# set bat85 value
try:
payload_dict["bat1_percent"] = int(
upower_out_dict["RemainPercent"].rstrip("%")
)
except KeyError:
logging.warning("No key 'RemainPercent' in upower output")
payload_dict["bat1_percent"] = 0
try:
payload_dict["bat2_percent"] = int(
upower_out_dict["RemainPercent_2"].rstrip("%")
)
except KeyError:
logging.warning("No key 'RemainPercent_2' in upower output")
payload_dict["bat2_percent"] = 0
total_batt = payload_dict["bat1_percent"] + payload_dict["bat2_percent"]
if total_batt >= 85:
payload_dict["bat85"] = 1
else:
payload_dict["bat85"] = 0
# dummy_payload_dict = {
# "bat":1,
# "ok":0,
# "alarm":0,
# "rdy2buf":0,
# "bat85":1,
# "prob_elec":0,
# "dummy":True,
# "bat1_percent":13,
# "bat2_percent":93,
# }
# Construct payload
for key in payload_dict:
setattr(payload, key, payload_dict[key])
try: try:
for pin in self._pins:
setattr(payload, pin, gpio.input(self._pins[pin]))
self.queue.put_nowait(payload) self.queue.put_nowait(payload)
except asyncio.queues.QueueFull: except asyncio.queues.QueueFull:
try: try:
......
...@@ -873,7 +873,7 @@ class LogMsgFormat(PayloadFormat): ...@@ -873,7 +873,7 @@ class LogMsgFormat(PayloadFormat):
# BATTERY data payload # BATTERY data payload
# ======================================= # =======================================
@dataclass @dataclass
class BatteryFormat(PayloadFormat): class OldBatteryFormat(PayloadFormat):
_dataStruct = Struct("<BIBbbbbbbb") _dataStruct = Struct("<BIBbbbbbbb")
payload_type: PAYLOAD_TYPE = PAYLOAD_TYPE.BATTERY payload_type: PAYLOAD_TYPE = PAYLOAD_TYPE.BATTERY
...@@ -905,6 +905,43 @@ class BatteryFormat(PayloadFormat): ...@@ -905,6 +905,43 @@ class BatteryFormat(PayloadFormat):
self.payload_type = PAYLOAD_TYPE(tmp_payload_type) self.payload_type = PAYLOAD_TYPE(tmp_payload_type)
self._byteArray = byteArray self._byteArray = byteArray
@dataclass
class BatteryFormat(PayloadFormat):
_dataStruct = Struct("<BIBbbbbbbbbb")
payload_type: PAYLOAD_TYPE = PAYLOAD_TYPE.BATTERY
bat: int = 0
ok: int = 0
alarm: int = 0
rdy2buf: int = 0
bat85: int = 0
prob_elec: int = 0
dummy: int = 0
bat1_percent: int = 0
bat2_percent: int = 0
# fill the struct from a byteArray,
def fromByteArray(self, byteArray):
tmp_payload_type = 0
(
self.version,
self.timestamp,
tmp_payload_type,
self.bat,
self.ok,
self.alarm,
self.rdy2buf,
self.bat85,
self.prob_elec,
self.dummy,
self.bat1_percent,
self.bat2_percent,
) = self._dataStruct.unpack(byteArray)
self.checkVersion()
self.payload_type = PAYLOAD_TYPE(tmp_payload_type)
self._byteArray = byteArray
# ======================================= # =======================================
# cmd type payload # cmd type payload
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment