Skip to content

Commit

Permalink
first attempt to add icons for hassd_mqtt output
Browse files Browse the repository at this point in the history
  • Loading branch information
jblance committed Jan 10, 2023
1 parent a9e984f commit afe1a14
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 43 deletions.
7 changes: 6 additions & 1 deletion mppsolar/outputs/hassd_mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,16 @@ def build_msgs(self, *args, **kwargs):
for _key in _data:
value = _data[_key][0]
unit = _data[_key][1]
icon = None
if len(_data[_key]) > 2 and _data[_key][2] and "icon" in _data[_key][2]:
icon = _data[_key][2]["icon"]

#
# CONFIG / AUTODISCOVER
#
# <discovery_prefix>/<component>/[<node_id>/]<object_id>/config
# topic "homeassistant/binary_sensor/garden/config"
# msg '{"name": "garden", "device_class": "motion", "state_topic": "homeassistant/binary_sensor/garden/state", "unit_of_measurement": "°C"}'
# msg '{"name": "garden", "device_class": "motion", "state_topic": "homeassistant/binary_sensor/garden/state", "unit_of_measurement": "°C", "icon": "power-plug"}'

# For binary sensors
if unit == "bool":
Expand Down Expand Up @@ -129,6 +132,8 @@ def build_msgs(self, *args, **kwargs):
}
if unit == "W":
payload.update({"state_class": "measurement", "device_class": "power"})
if icon:
payload.update({"icon": icon})
# msg = {"topic": topic, "payload": payload, "retain": True}
payloads = js.dumps(payload)
# print(payloads)
Expand Down
6 changes: 5 additions & 1 deletion mppsolar/outputs/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,8 @@ def output(self, *args, **kwargs):
for key in displayData:
value = displayData[key][0]
unit = displayData[key][1]
print(f"{pad(key,maxP+1)}{value:<15}\t{unit:<4}")
if len(displayData[key]) > 2 and displayData[key][2]:
extra = displayData[key][2]
print(f"{pad(key,maxP+1)}{value:<15}\t{unit:<4}\t{extra}")
else:
print(f"{pad(key,maxP+1)}{value:<15}\t{unit:<4}")
35 changes: 19 additions & 16 deletions mppsolar/protocols/abstractprotocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ def process_response(
data_units=None,
raw_value=None,
frame_number=0,
extra_info=None,
):
template = None
# Check for a format modifying template
Expand All @@ -117,28 +118,28 @@ def process_response(
)
if data_type == "loop":
log.warning("loop not implemented...")
return [(data_name, None, data_units)]
return [(data_name, None, data_units, extra_info)]
if data_type == "exclude" or data_type == "discard" or raw_value == "extra":
# Just ignore these ones
log.debug(f"Discarding {data_name}:{raw_value}")
return [(None, raw_value, data_units)]
return [(None, raw_value, data_units, extra_info)]
if data_type == "option":
try:
key = int(raw_value)
r = data_units[key]
except ValueError:
r = f"Unable to process to int: {raw_value}"
return [(None, r, "")]
return [(None, r, "", None)]
except IndexError:
r = f"Invalid option: {key}"
return [(data_name, r, "")]
return [(data_name, r, "", extra_info)]
if data_type == "hex_option":
key = int(raw_value[0])
if key < len(data_units):
r = data_units[key]
else:
r = f"Invalid hex_option: {key}"
return [(data_name, r, "")]
return [(data_name, r, "", extra_info)]
if data_type == "flags":
log.debug("flags defn")
# [
Expand All @@ -152,7 +153,7 @@ def process_response(
# ],
return_value = []
for i, flag in enumerate(raw_value):
return_value.append((data_units[i], int(chr(flag)), "bool"))
return_value.append((data_units[i], int(chr(flag)), "bool", None))

# if flag != "" and flag != b'':
# msgs[resp_format[2][j]] = [int(flag), "bool"]
Expand All @@ -178,7 +179,7 @@ def process_response(
r = data_units[key]
else:
r = f"Invalid key: {key}"
return [(data_name, r, "")]
return [(data_name, r, "", None)]
if data_type == "str_keyed":
log.debug("str_keyed defn")
# [
Expand All @@ -201,25 +202,25 @@ def process_response(
r = data_units[key]
else:
r = f"Invalid key: {key}"
return [(data_name, r, "")]
return [(data_name, r, "", extra_info)]
format_string = f"{data_type}(raw_value)"
log.debug(f"Processing format string {format_string}")
try:
r = eval(format_string)
except ValueError as e:
log.info(f"Failed to eval format {format_string} (returning 0), error: {e}")
return [(data_name, 0, data_units)]
return [(data_name, 0, data_units, extra_info)]
except TypeError as e:
log.warning(f"Failed to eval format {format_string}, error: {e}")
return [(data_name, format_string, data_units)]
return [(data_name, format_string, data_units, extra_info)]
if template is not None:
# eg template=r/1000
r = eval(template)
if "{" in data_name:
# eg "f'Frame Number {f:02d}'"
f = frame_number # noqa: F841
data_name = eval(data_name)
return [(data_name, r, data_units)]
return [(data_name, r, data_units, extra_info)]

def decode(self, response, command) -> dict:
"""
Expand Down Expand Up @@ -404,6 +405,7 @@ def decode(self, response, command) -> dict:
for frame_number, frame in enumerate(frames):

for i, response in enumerate(frame):
extra_info = None
if response_type == "KEYED":
log.debug("Processing KEYED type responses")
# example defn ["V", "Main or channel 1 (battery) voltage", "V", "float:r/1000"]
Expand Down Expand Up @@ -464,7 +466,7 @@ def decode(self, response, command) -> dict:
data_name = get_value(response_defn, 1)
data_type = get_value(response_defn, 2)
data_units = get_value(response_defn, 3)
# extra_info = get_value(response_defn, 4)
extra_info = get_value(response_defn, 4)

# print(f"{data_type=}, {data_name=}, {raw_value=}")
elif response_type in ["POSITIONAL", "MULTIFRAME-POSITIONAL"]:
Expand Down Expand Up @@ -514,7 +516,7 @@ def decode(self, response, command) -> dict:
log.debug(f"looking up values for: {lookup}")
value, data_units = m[lookup]
if data_name is not None:
msgs[data_name] = [value, data_units]
msgs[data_name] = [value, data_units, extra_info]
elif data_type.startswith("info"):
log.debug("processing info...")
# print(
Expand All @@ -525,7 +527,7 @@ def decode(self, response, command) -> dict:
cv = self._command_value # noqa: F841
value = eval(template)
if data_name is not None:
msgs[data_name] = [value, data_units]
msgs[data_name] = [value, data_units, extra_info]
else:
# Process response
processed_responses = self.process_response(
Expand All @@ -534,6 +536,7 @@ def decode(self, response, command) -> dict:
data_units=data_units,
data_type=data_type,
frame_number=frame_number,
extra_info=extra_info,
)
# data_name, value, data_units = self.process_response(
# data_name=data_name,
Expand All @@ -544,9 +547,9 @@ def decode(self, response, command) -> dict:
# )
# print(data_type, data_name, raw_value, value)
for item in processed_responses:
data_name, value, data_units = item
data_name, value, data_units, extra_info = item
if data_name is not None:
msgs[data_name] = [value, data_units]
msgs[data_name] = [value, data_units, extra_info]
# print(f"{i=} {response=} {len(command_defn['response'])}")

return msgs
54 changes: 29 additions & 25 deletions mppsolar/protocols/pi30max.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,26 +164,28 @@
"name": "QPIGS",
"description": "General Status Parameters inquiry",
"type": "QUERY",
"response_type": "INDEXED",
"response": [
["float", "AC Input Voltage", "V"],
["float", "AC Input Frequency", "Hz"],
["float", "AC Output Voltage", "V"],
["float", "AC Output Frequency", "Hz"],
["int", "AC Output Apparent Power", "VA"],
["int", "AC Output Active Power", "W"],
["int", "AC Output Load", "%"],
["int", "BUS Voltage", "V"],
["float", "Battery Voltage", "V"],
["int", "Battery Charging Current", "A"],
["int", "Battery Capacity", "%"],
["int", "Inverter Heat Sink Temperature", "°C"],
["float", "PV1 Input Current", "A"],
["float", "PV1 Input Voltage", "V"],
["float", "Battery Voltage from SCC", "V"],
["int", "Battery Discharge Current", "A"],
[
"flags",
[1, "AC Input Voltage", "float", "V", {"icon": "power-plug"}],
[2, "AC Input Frequency", "float", "Hz", {"icon": "current-ac"}],
[3, "AC Output Voltage", "float", "V", {"icon": "power-plug"}],
[4, "AC Output Frequency", "float", "Hz", {"icon": "current-ac"}],
[5, "AC Output Apparent Power", "int", "VA", {"icon": "power-plug"}],
[6, "AC Output Active Power", "int", "W", {"icon": "power-plug"}],
[7, "AC Output Load", "int", "%", {"icon": "brightness-percent"}],
[8, "BUS Voltage", "int", "V", {"icon": "details"}],
[9, "Battery Voltage", "float", "V", {"icon": "battery-outline"}],
[10, "Battery Charging Current", "int", "A", {"icon": "current-dc"}],
[11, "Battery Capacity", "int", "%", {"icon": "battery-outline"}],
[12, "Inverter Heat Sink Temperature", "int", "°C", {"icon": "details"}],
[13, "PV1 Input Current", "float", "A", {"icon": "solar-power"}],
[14, "PV1 Input Voltage", "float", "V", {"icon": "solar-power"}],
[15, "Battery Voltage from SCC", "float", "V", {"icon": "battery-outline"}],
[16, "Battery Discharge Current", "int", "A", {"icon": "battery-negative"}],
[
17,
"Device Status",
"flags",
[
"Is SBU Priority Version Added",
"Is Configuration Changed",
Expand All @@ -195,25 +197,27 @@
"Is AC Charging On",
],
],
["int", "Battery Voltage Offset for Fans On", "10mV"],
["int", "EEPROM Version", ""],
["int", "PV1 Charging Power", "W"],
[18, "Battery Voltage Offset for Fans On", "int", "10mV"],
[19, "EEPROM Version", "int", ""],
[20, "PV1 Charging Power", "int", "W"],
[
"flags",
21,
"Device Status2",
"flags",
["Is Charging to Float", "Is Switched On", "Is Dustproof Installed"],
],
["option", "Solar Feed to Grid", ["Disabled", "Enabled"]],
[22, "Solar Feed to Grid", "option", ["Disabled", "Enabled"]],
[
"keyed",
23,
"Country",
"keyed",
{
"00": "India",
"01": "Germany",
"02": "South America",
},
],
["int", "Solar Feed to Grid Power", "W"],
[24, "Solar Feed to Grid Power", "int", "W"],
],
"test_responses": [
b"(227.2 50.0 230.3 50.0 0829 0751 010 447 54.50 020 083 0054 02.7 323.6 00.00 00000 00010110 00 00 00879 010\xf1\x8c\r",
Expand Down

0 comments on commit afe1a14

Please sign in to comment.