First valid working config with drawing

This commit is contained in:
2026-05-15 21:44:10 +02:00
parent dbda5a8daa
commit fac18c17ac
6 changed files with 372 additions and 120 deletions
+1 -2
View File
@@ -16,11 +16,10 @@ The configuration (handmade) on which this generator is based, can be found in t
- Notification service: until dismissed, or with timeout - Notification service: until dismissed, or with timeout
- LED effects: flash, breathe - LED effects: flash, breathe
- Top level config only for drawing, everything else hidden - Top level config only for drawing, everything else hidden
- back to using packages or includes probably
- Allow adding of font and icons easily - Allow adding of font and icons easily
## Missing config ## Missing config
- Scripts for updating displays (see scripts.yaml)
- Draw routines (see config.yaml)
- Event generation (triggers and stuff, see events.yaml) - Event generation (triggers and stuff, see events.yaml)
- configurable timing and button events - configurable timing and button events
- Always set display to left and right page - Always set display to left and right page
+23 -1
View File
@@ -1,5 +1,8 @@
## GPIO Pins ## GPIO Pins
from enum import StrEnum
GPIO_NEOPIXELS = "GPIO4" #Neopixel LED's GPIO_NEOPIXELS = "GPIO4" #Neopixel LED's
GPIO_SPI_MOSI = "GPIO5" #SPI MOSI GPIO_SPI_MOSI = "GPIO5" #SPI MOSI
GPIO_SPI_CLK = "GPIO6" #SPI SCK GPIO_SPI_CLK = "GPIO6" #SPI SCK
@@ -9,4 +12,23 @@ GPIO_BACKLIGHT_MINI = "GPIO46" #Backlight mini displays
GPIO_I2C_BUTTONS_SDA = "GPIO1" #I2C SDA > Buttons GPIO_I2C_BUTTONS_SDA = "GPIO1" #I2C SDA > Buttons
GPIO_I2C_BUTTONS_SCL = "GPIO2" #I2C SCL > Buttons GPIO_I2C_BUTTONS_SCL = "GPIO2" #I2C SCL > Buttons
GPIO_I2C_SENSORS_SDA = "GPIO47" #I2C SDA > Temperature & Ambient Sensor GPIO_I2C_SENSORS_SDA = "GPIO47" #I2C SDA > Temperature & Ambient Sensor
GPIO_I2C_SENSORS_SCL = "GPIO48" #I2S SCL > Temperature & Ambient Sensor GPIO_I2C_SENSORS_SCL = "GPIO48" #I2S SCL > Temperature & Ambient Sensor
class BarSide(StrEnum):
LEFT = "left"
RIGHT = "right"
class ClickTypes(StrEnum):
SINGLE = "single"
DOUBLE = "double"
TRIPLE = "triple"
HOLD = "hold"
class YAMLExtend:
def __init__(self, value): self.value = value
class YAMLLambda:
def __init__(self, value): self.value = value
class YAMLSecret:
def __init__(self, value): self.value = value
+35 -11
View File
@@ -10,26 +10,29 @@ from typing import Any, Dict, List
import yaml import yaml
from buttonplus_generator.constants import YAMLExtend, YAMLLambda, YAMLSecret
from buttonplus_generator.snippets.common import config_common from buttonplus_generator.snippets.common import config_common
from buttonplus_generator.snippets.display import config_display
from buttonplus_generator.merger import deep_merge
from buttonplus_generator.snippets.bars import config_bars from buttonplus_generator.snippets.bars import config_bars
from buttonplus_generator.snippets.display import config_display
#from buttonplus_generator.snippets.events import config_events
from buttonplus_generator.merger import deep_merge
def compose_config(device_name: str, version: int, num_bars: int, pages: List[str]) -> Dict[str, Any]: def compose_config(device_name: str, version: int, num_bars: int, pages: List[str], click_types: List[str]) -> Dict[str, Any]:
config = config_common(device_name=device_name, version=version, page_names=pages, num_bars=num_bars) config = config_common(device_name=device_name, version=version, page_names=pages, num_bars=num_bars)
if(num_bars < 4): # Always assume display if less than 4 bars if(num_bars < 4): # Always assume display if less than 4 bars
config = deep_merge(config, config_display(version=version, num_bars=num_bars)) config = deep_merge(config, config_display(version=version, num_bars=num_bars, page_names=pages))
config = deep_merge(config, config_bars(version=version, num_bars=num_bars)) config = deep_merge(config, config_bars(version=version, num_bars=num_bars, page_names=pages))
#config = deep_merge(config, config_events(version=version, num_bars=num_bars, page_names=pages, click_types=click_types))
return config return config
def yaml_dumper(config: Dict[str, Any], fh) -> str: def yaml_dumper(config: Dict[str, Any], fh) -> str:
## Handle multiline strings ## Handle multiline strings
def str_presenter(dumper, data): def represent_multistr(dumper, data):
"""configures yaml for dumping multiline strings """configures yaml for dumping multiline strings
Ref: https://stackoverflow.com/questions/8640959/how-can-i-control-what-scalar-form-pyyaml-uses-for-my-data Ref: https://stackoverflow.com/questions/8640959/how-can-i-control-what-scalar-form-pyyaml-uses-for-my-data
""" """
@@ -37,7 +40,20 @@ def yaml_dumper(config: Dict[str, Any], fh) -> str:
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|') return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
return dumper.represent_scalar('tag:yaml.org,2002:str', data) return dumper.represent_scalar('tag:yaml.org,2002:str', data)
yaml.add_representer(str, str_presenter) def represent_extend(dumper, data):
return dumper.represent_scalar('!extend', data.value)
def represent_lambda(dumper, data):
return dumper.represent_scalar('!lambda', data.value, style='"')
def represent_secret(dumper, data):
return dumper.represent_scalar('!secret', data.value, style="'")
yaml.add_representer(str, represent_multistr)
yaml.add_representer(YAMLExtend, represent_extend)
yaml.add_representer(YAMLLambda, represent_lambda)
yaml.add_representer(YAMLSecret, represent_secret)
yaml.dump(config, fh, sort_keys=False, encoding="utf-8", default_flow_style=False) yaml.dump(config, fh, sort_keys=False, encoding="utf-8", default_flow_style=False)
def main(argv=None) -> int: def main(argv=None) -> int:
@@ -47,8 +63,7 @@ def main(argv=None) -> int:
) )
parser.add_argument( parser.add_argument(
"--device-name", "--device-name",
"--name", "-d",
"-n",
default="buttonplus", default="buttonplus",
help="ESPHome device name", help="ESPHome device name",
) )
@@ -59,7 +74,7 @@ def main(argv=None) -> int:
choices=[1,2], choices=[1,2],
required=True, required=True,
help="The version of the display and bars. Only V2 PCB is supported.", help="The version of the display and bars. Only V2 PCB is supported.",
metavar="VER" metavar="[1|2]"
) )
parser.add_argument( parser.add_argument(
"--bars", "--bars",
@@ -77,6 +92,14 @@ def main(argv=None) -> int:
help="List of page names", help="List of page names",
metavar="NAME" metavar="NAME"
) )
parser.add_argument(
"--click-types",
"-c",
nargs="+",
default=["single", "double", "triple", "hold"],
help="List click types buttons, choices are [single|double|triple|hold].",
metavar="TYPE"
)
parser.add_argument( parser.add_argument(
"--output", "-o", default="buttonplus.yaml", help="Output file path" "--output", "-o", default="buttonplus.yaml", help="Output file path"
) )
@@ -86,9 +109,10 @@ def main(argv=None) -> int:
version: int = args.version version: int = args.version
num_bars: int = args.bars num_bars: int = args.bars
pages: List[str] = args.pages pages: List[str] = args.pages
click_types: List[str] = args.click_types
output: str = args.output output: str = args.output
config = compose_config(device_name, version, num_bars, pages) config = compose_config(device_name, version, num_bars, pages, click_types)
with open(output, "w", encoding="utf-8") as fh: with open(output, "w", encoding="utf-8") as fh:
fh.writelines( fh.writelines(
[ [
+220 -78
View File
@@ -2,18 +2,27 @@ from typing import Dict, Any, List
from buttonplus_generator.constants import * from buttonplus_generator.constants import *
from buttonplus_generator.merger import deep_merge from buttonplus_generator.merger import deep_merge
def config_bars(
version: int, num_bars: int def config_bars(version: int, num_bars: int, page_names: List[str]) -> Dict[str, Any]:
) -> Dict[str, Any]:
config = bars_backlight() config = bars_backlight()
config = deep_merge(config, bars_setup(num_bars=num_bars)) config = deep_merge(config, bars_setup(num_bars=num_bars))
config = deep_merge(config, bars_buttons(num_bars=num_bars)) config = deep_merge(config, bars_buttons(num_bars=num_bars))
config = deep_merge(config, bars_lights(num_bars=num_bars, display_has_leds=(version == 2 and num_bars < 4))) config = deep_merge(
config,
bars_lights(
num_bars=num_bars, display_has_leds=(version == 2 and num_bars < 4)
),
)
config = deep_merge(config, bars_display_output(num_bars=num_bars)) config = deep_merge(config, bars_display_output(num_bars=num_bars))
config = deep_merge(config, bars_display()) config = deep_merge(config, bars_display())
config = deep_merge(config, bars_scripts(num_bars=num_bars))
config = deep_merge(
config, bars_draw_scripts(num_bars=num_bars, page_names=page_names)
)
return config return config
def bars_backlight() -> Dict[str, Any]: def bars_backlight() -> Dict[str, Any]:
return { return {
"output": [ "output": [
@@ -55,8 +64,10 @@ def bars_setup(num_bars: int = 3) -> Dict[str, Any]:
) )
scripts.extend( scripts.extend(
[{"script.execute": "update_bar1_left"}, [
{"script.execute": "update_bar1_right"}] {"script.execute": "update_bar1_left"},
{"script.execute": "update_bar1_right"},
]
) )
# At least two bars, in bottom two slots # At least two bars, in bottom two slots
@@ -66,8 +77,10 @@ def bars_setup(num_bars: int = 3) -> Dict[str, Any]:
) )
scripts.extend( scripts.extend(
[{"script.execute": "update_bar2_left"}, [
{"script.execute": "update_bar2_right"}] {"script.execute": "update_bar2_left"},
{"script.execute": "update_bar2_right"},
]
) )
# At least three bars, in bottom three slots # At least three bars, in bottom three slots
@@ -77,8 +90,10 @@ def bars_setup(num_bars: int = 3) -> Dict[str, Any]:
) )
scripts.extend( scripts.extend(
[{"script.execute": "update_bar3_left"}, [
{"script.execute": "update_bar3_right"}] {"script.execute": "update_bar3_left"},
{"script.execute": "update_bar3_right"},
]
) )
# No display, only bars, also in top slot # No display, only bars, also in top slot
@@ -88,8 +103,10 @@ def bars_setup(num_bars: int = 3) -> Dict[str, Any]:
) )
scripts.extend( scripts.extend(
[{"script.execute": "update_bar4_left"}, [
{"script.execute": "update_bar4_right"}] {"script.execute": "update_bar4_left"},
{"script.execute": "update_bar4_right"},
]
) )
bar_dict["esphome"] = {"on_boot": {"then": scripts}} bar_dict["esphome"] = {"on_boot": {"then": scripts}}
@@ -169,62 +186,40 @@ def bars_lights(num_bars: int, display_has_leds: bool = True) -> Dict[str, Any]:
bar_dict["light"].extend(_bar_lights_entry(3, 8 + display_offset)) bar_dict["light"].extend(_bar_lights_entry(3, 8 + display_offset))
if num_bars > 3: if num_bars > 3:
bar_dict["light"].extend(_bar_lights_entry(4, 12)) # no display bar_dict["light"].extend(_bar_lights_entry(4, 12)) # no display
return bar_dict return bar_dict
def _bar_lights_entry(bar_nr: int, offset: int) -> List[Dict[str, Any]]: def _bar_lights_entry(bar_nr: int, offset: int) -> List[Dict[str, Any]]:
return [ return [
{ {
"platform": "partition", "platform": "partition",
"name": f"BAR {bar_nr} Left RGB Front", "name": f"BAR {bar_nr} Left RGB Front",
"id": f"bar{bar_nr}_left_rgb_front", "id": f"bar{bar_nr}_left_rgb_front",
"segments": [ "segments": [{"id": "neopixels", "from": offset + 0, "to": offset + 0}],
{ },
"id": "neopixels", {
"from": offset + 0, "platform": "partition",
"to": offset + 0 "name": f"BAR {bar_nr} Left RGB Back",
} "id": f"bar{bar_nr}_left_rgb_back",
] "segments": [{"id": "neopixels", "from": offset + 1, "to": offset + 1}],
}, },
{ {
"platform": "partition", "platform": "partition",
"name": f"BAR {bar_nr} Left RGB Back", "name": f"BAR {bar_nr} Right RGB Front",
"id": f"bar{bar_nr}_left_rgb_back", "id": f"bar{bar_nr}_right_rgb_front",
"segments": [ "segments": [{"id": "neopixels", "from": offset + 2, "to": offset + 2}],
{ },
"id": "neopixels", {
"from": offset + 1, "platform": "partition",
"to": offset + 1 "name": f"BAR {bar_nr} Right RGB Back",
} "id": f"bar{bar_nr}_right_rgb_back",
] "segments": [{"id": "neopixels", "from": offset + 3, "to": offset + 3}],
}, },
{
"platform": "partition",
"name": f"BAR {bar_nr} Right RGB Front",
"id": f"bar{bar_nr}_right_rgb_front",
"segments": [
{
"id": "neopixels",
"from": offset + 2,
"to": offset + 2
}
]
},
{
"platform": "partition",
"name": f"BAR {bar_nr} Right RGB Back",
"id": f"bar{bar_nr}_right_rgb_back",
"segments": [
{
"id": "neopixels",
"from": offset + 3,
"to": offset + 3
}
]
},
] ]
def bars_display_output(num_bars: int = 3) -> Dict[str, Any]: def bars_display_output(num_bars: int = 3) -> Dict[str, Any]:
bar_dict = {"output": []} bar_dict = {"output": []}
@@ -260,9 +255,7 @@ def _bar_display_output_entry(bar_nr: int, base_id: str) -> List[Dict[str, Any]]
"pin": { "pin": {
"mcp23xxx": base_id, "mcp23xxx": base_id,
"number": 5, "number": 5,
"mode": { "mode": {"output": True},
"output": True
},
"inverted": True, "inverted": True,
}, },
}, },
@@ -272,14 +265,13 @@ def _bar_display_output_entry(bar_nr: int, base_id: str) -> List[Dict[str, Any]]
"pin": { "pin": {
"mcp23xxx": base_id, "mcp23xxx": base_id,
"number": 1, "number": 1,
"mode": { "mode": {"output": True},
"output": True
},
"inverted": True, "inverted": True,
}, },
}, },
] ]
def bars_display() -> Dict[str, Any]: def bars_display() -> Dict[str, Any]:
return { return {
"display": [ "display": [
@@ -289,18 +281,168 @@ def bars_display() -> Dict[str, Any]:
"model": "ST7735", "model": "ST7735",
"color_order": "bgr", "color_order": "bgr",
"update_interval": "never", "update_interval": "never",
"dc_pin": { "dc_pin": {"number": GPIO_SPI_REG, "allow_other_uses": True},
"number": GPIO_SPI_REG,
"allow_other_uses": True
},
"invert_colors": False, "invert_colors": False,
"show_test_card": False, "show_test_card": False,
"auto_clear_enabled": False, "auto_clear_enabled": False,
"dimensions": { "dimensions": {"height": 160, "width": 80, "offset_width": 24},
"height": 160,
"width": 80,
"offset_width": 24
}
} }
], ],
} }
def bars_scripts(num_bars: int) -> Dict[str, Any]:
bar_dict = {"script": []}
if num_bars < 1:
raise ValueError("At least one bar must be connected!")
setup_cpp = ""
if num_bars > 0:
bar_dict["script"].append(_bars_script_update_entry(1, BarSide.LEFT, num_bars))
bar_dict["script"].append(_bars_script_update_entry(1, BarSide.RIGHT, num_bars))
setup_cpp += _bars_script_setup_entry(1, BarSide.LEFT)
setup_cpp += _bars_script_setup_entry(1, BarSide.RIGHT)
if num_bars > 1:
bar_dict["script"].append(_bars_script_update_entry(2, BarSide.LEFT, num_bars))
bar_dict["script"].append(_bars_script_update_entry(2, BarSide.RIGHT, num_bars))
setup_cpp += _bars_script_setup_entry(2, BarSide.LEFT)
setup_cpp += _bars_script_setup_entry(2, BarSide.RIGHT)
if num_bars > 2:
bar_dict["script"].append(_bars_script_update_entry(3, BarSide.LEFT, num_bars))
bar_dict["script"].append(_bars_script_update_entry(3, BarSide.RIGHT, num_bars))
setup_cpp += _bars_script_setup_entry(3, BarSide.LEFT)
setup_cpp += _bars_script_setup_entry(3, BarSide.RIGHT)
if num_bars > 3:
bar_dict["script"].append(_bars_script_update_entry(4, BarSide.LEFT, num_bars))
bar_dict["script"].append(_bars_script_update_entry(4, BarSide.RIGHT, num_bars))
setup_cpp += _bars_script_setup_entry(4, BarSide.LEFT)
setup_cpp += _bars_script_setup_entry(4, BarSide.RIGHT)
bar_dict["script"].append(
{"id": "setup_bar_displays", "then": [{"lambda": setup_cpp}]}
)
return bar_dict
def _bars_script_update_entry(
bar_nr: int, bar_side: BarSide, num_bars: int
) -> Dict[str, Any]:
# Generate all possible bars
bars_ids = [
f"cs_pin_bar{nr}_{side}"
for nr in range(1, num_bars + 1)
for side in [BarSide.LEFT, BarSide.RIGHT]
]
bars_state = [
"on" if (nr is bar_nr and side is bar_side) else "off"
for nr in range(1, num_bars + 1)
for side in [BarSide.LEFT, BarSide.RIGHT]
]
generated_cpp = ""
for bar, state in zip(bars_ids, bars_state):
generated_cpp += f"id({bar}).turn_{state}();\n"
rotation = "90" if bar_side is BarSide.RIGHT else "270"
generated_cpp += (
"id(bar_display).clear();\n"
f"id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_{rotation}_DEGREES);\n"
f"id(bar{bar_nr}_{bar_side}_draw).execute();\n"
"id(bar_display).update();\n"
"delay(1);\n"
f"id(cs_pin_bar{bar_nr}_{bar_side}).turn_off();"
)
return {"id": f"update_bar{bar_nr}_{bar_side}", "then": [{"lambda": generated_cpp}]}
def _bars_script_setup_entry(bar_nr: int, bar_side: BarSide) -> str:
return (
f"id(cs_pin_bar{bar_nr}_{bar_side}).turn_on();\n"
"id(bar_display).setup();\n"
"delay(5);\n"
f"id(cs_pin_bar{bar_nr}_{bar_side}).turn_off();\n"
)
def bars_draw_scripts(num_bars: int, page_names: List[str]) -> Dict[str, Any]:
bar_dict = {"script": []}
if num_bars < 1:
raise ValueError("At least one bar must be connected!")
update_list = []
if num_bars > 0:
bar_dict["script"].append(_bars_script_draw_entry(1, BarSide.LEFT, page_names))
bar_dict["script"].append(_bars_script_draw_entry(1, BarSide.RIGHT, page_names))
update_list.extend(_bars_script_execute_entry(1, BarSide.LEFT))
update_list.extend(_bars_script_execute_entry(1, BarSide.RIGHT))
if num_bars > 1:
bar_dict["script"].append(_bars_script_draw_entry(2, BarSide.LEFT, page_names))
bar_dict["script"].append(_bars_script_draw_entry(2, BarSide.RIGHT, page_names))
update_list.extend(_bars_script_execute_entry(2, BarSide.LEFT))
update_list.extend(_bars_script_execute_entry(2, BarSide.RIGHT))
if num_bars > 2:
bar_dict["script"].append(_bars_script_draw_entry(3, BarSide.LEFT, page_names))
bar_dict["script"].append(_bars_script_draw_entry(3, BarSide.RIGHT, page_names))
update_list.extend(_bars_script_execute_entry(3, BarSide.LEFT))
update_list.extend(_bars_script_execute_entry(3, BarSide.RIGHT))
if num_bars > 3:
bar_dict["script"].append(_bars_script_draw_entry(4, BarSide.LEFT, page_names))
bar_dict["script"].append(_bars_script_draw_entry(4, BarSide.RIGHT, page_names))
update_list.extend(_bars_script_execute_entry(3, BarSide.LEFT))
update_list.extend(_bars_script_execute_entry(3, BarSide.RIGHT))
bar_dict["script"].append({"id": "update_bars", "then": update_list[:-1]})
return bar_dict
def _bars_script_draw_entry(
bar_nr: int, bar_side: BarSide, page_names: List[str]
) -> Dict[str, Any]:
generated_cpp = "switch (id(active_page_nr)){\n"
for page_num in range(0, len(page_names)):
generated_cpp += (
f" // Page {page_num} - {page_names[page_num]}\n"
f" case {page_num}:\n"
f' id(bar_display).printf(80, 0, id(font_arial20), id(accent), TextAlign::TOP_CENTER , "Bar {bar_nr} {bar_side}");\n'
f' id(bar_display).printf(80, 80, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER , "Page {page_num}");\n'
f" break;\n"
)
generated_cpp += "}\n"
return {"id": f"bar{bar_nr}_{bar_side}_draw", "then": [{"lambda": generated_cpp}]}
def _bars_script_execute_entry(bar_nr: int, bar_side: BarSide) -> List[Dict[str, str]]:
return [
{
"script.execute": f"update_bar{bar_nr}_{bar_side}",
},
{"delay": "0.1s"},
]
+33 -10
View File
@@ -17,7 +17,7 @@ def config_common(
config = deep_merge(config, i2c()) config = deep_merge(config, i2c())
config = deep_merge(config, spi()) config = deep_merge(config, spi())
config = deep_merge( config = deep_merge(
config, sensors(ambient_gain="auto", extra_ambient_sensors=False) config, sensors(ambient_gain="96x", extra_ambient_sensors=False)
) )
num_leds = 0 num_leds = 0
@@ -32,6 +32,7 @@ def config_common(
num_leds = 17 #no display num_leds = 17 #no display
config = deep_merge(config, neopixels(num_leds=num_leds)) config = deep_merge(config, neopixels(num_leds=num_leds))
config = deep_merge(config, update_scripts(num_bars=num_bars))
return config return config
@@ -54,12 +55,12 @@ def base_config(device_name: str) -> Dict[str, Any]:
}, },
"psram": {"mode": "octal", "speed": "80MHz"}, "psram": {"mode": "octal", "speed": "80MHz"},
"wifi": { "wifi": {
"ssid": "!secret wifi_ssid", "ssid": YAMLSecret("wifi_ssid"),
"password": "!secret wifi_password", "password": YAMLSecret("wifi_password"),
}, },
"logger": {"level": "DEBUG"}, "logger": {"level": "DEBUG"},
"api": {"encryption": {"key": "!secret encryption_key"}}, "api": {"encryption": {"key": YAMLSecret("encryption_key")}},
"ota": [{"platform": "esphome", "password": "!secret ota_password"}], "ota": [{"platform": "esphome", "password": YAMLSecret("ota_password")}],
} }
@@ -101,7 +102,7 @@ def pages(nr_of_pages: int, page_names: List[str]) -> Dict[str, Any]:
{"id": "active_page_nr", "type": "int", "initial_value": "0"}, {"id": "active_page_nr", "type": "int", "initial_value": "0"},
{"id": "active_page_name", "type": "std::string", "initial_value": ""}, {"id": "active_page_name", "type": "std::string", "initial_value": ""},
], ],
"sensors": [ "sensor": [
{ {
"platform": "template", "platform": "template",
"name": "Active Page Number", "name": "Active Page Number",
@@ -170,14 +171,14 @@ def pages(nr_of_pages: int, page_names: List[str]) -> Dict[str, Any]:
}, },
{ {
"sensor.template.publish": { "sensor.template.publish": {
"id": "active_page_id_ha", "id": "active_page_nr_ha",
"state": "return id(active_page_nr);", "state": YAMLLambda("return id(active_page_nr);"),
} }
}, },
{ {
"text_sensor.template.publish": { "text_sensor.template.publish": {
"id": "active_page_name_ha", "id": "active_page_name_ha",
"state": "return id(active_page_name);", "state": YAMLLambda("return id(active_page_name);"),
} }
}, },
{"script.execute": "update_all"}, {"script.execute": "update_all"},
@@ -189,7 +190,7 @@ def pages(nr_of_pages: int, page_names: List[str]) -> Dict[str, Any]:
{ {
"number.set": { "number.set": {
"id": "pageselector", "id": "pageselector",
"value": "return id(active_page_nr);", "value": YAMLLambda("return id(active_page_nr);"),
} }
}, },
{"script.execute": "set_page"}, {"script.execute": "set_page"},
@@ -325,3 +326,25 @@ def sensors(ambient_gain: str, extra_ambient_sensors: bool) -> Dict[str, Any]:
} }
return sensors_dict return sensors_dict
def update_scripts(num_bars: int) -> Dict[str, Any]:
common_dict = {"script": []}
update_list = [
{
"script.execute": "update_bars",
},
{"delay": "0.1s"},
]
if num_bars < 4:
update_list.extend([
{
"script.execute": "update_main",
},
{"delay": "0.1s"},
])
common_dict["script"].append({"id": "update_all", "then": update_list[:-1]})
return common_dict
+60 -18
View File
@@ -1,15 +1,17 @@
from typing import Dict, Any from typing import Dict, Any, List
from buttonplus_generator.constants import * from buttonplus_generator.constants import *
from buttonplus_generator.utils import get_display_id, get_display_address from buttonplus_generator.utils import get_display_id, get_display_address
from buttonplus_generator.merger import deep_merge from buttonplus_generator.merger import deep_merge
def config_display(
version: int, num_bars: int def config_display(version: int, num_bars: int, page_names: List[str]) -> Dict[str, Any]:
) -> Dict[str, Any]:
config = display_backlight(num_bars=num_bars) config = display_backlight(num_bars=num_bars)
config = deep_merge(config, display_setup(num_bars=num_bars)) config = deep_merge(config, display_setup(num_bars=num_bars))
config = deep_merge(config, display_buttons(num_bars=num_bars)) config = deep_merge(config, display_buttons(num_bars=num_bars))
config = deep_merge(config, display_lights(num_bars=num_bars, display_has_leds=(version == 2))) config = deep_merge(
config, display_lights(num_bars=num_bars, display_has_leds=(version == 2))
)
config = deep_merge(config, update_scripts(page_names=page_names))
return config return config
@@ -44,24 +46,17 @@ def display_backlight(num_bars: int) -> Dict[str, Any]:
"invert_colors": False, "invert_colors": False,
"color_order": "rgb", "color_order": "rgb",
"update_interval": "30s", "update_interval": "30s",
"dc_pin": { "dc_pin": {"number": GPIO_SPI_REG, "allow_other_uses": True},
"number": GPIO_SPI_REG,
"allow_other_uses": True
},
"cs_pin": { "cs_pin": {
"mcp23xxx": get_display_id(num_bars), "mcp23xxx": get_display_id(num_bars),
"number": 5, "number": 5,
"mode": { "mode": {"output": True},
"output": True "inverted": False,
},
"inverted": False
}, },
"show_test_card": False, "show_test_card": False,
"dimensions": { "dimensions": {"height": 240, "width": 320},
"height": 240, "rotation": 180,
"width": 320 "lambda": "id(main_draw).execute();"
},
"rotation": 180
}, },
], ],
} }
@@ -150,3 +145,50 @@ def display_lights(num_bars: int, display_has_leds: bool = True) -> Dict[str, An
}, },
] ]
} }
def update_scripts(page_names: List[str]) -> Dict[str, Any]:
display_dict = {"script": []}
display_dict["script"].append(
{
"id": "update_main",
"then": [
{
"component.update": "main_display",
}
],
}
)
generated_cpp = (
"// All pages\n"
"id(main_display).image(0, 235, id(icon_prev_page), ImageAlign::BOTTOM_LEFT, id(grey));\n"
"id(main_display).image(320, 235, id(icon_next_page), ImageAlign::BOTTOM_RIGHT, id(grey));\n"
"\n"
"id(main_display).strftime(160, 5, id(font_arial20), TextAlign::TOP_CENTER, \"%H:%M\", id(datetime).now());\n"
"id(main_display).strftime(160, 80, id(font_arial20), TextAlign::TOP_CENTER, \"%d-%m-%Y\", id(datetime).now());\n"
"\n"
"switch (id(active_page_nr)){\n"
)
for page_num in range(0, len(page_names)):
generated_cpp += (
f" // Page {page_num} - {page_names[page_num]}\n"
f" case {page_num}:\n"
f" id(main_display).print(160, 235, id(font_arial20), id(white), TextAlign::BOTTOM_CENTER, id(active_page_name).c_str());\n"
f" break;\n"
)
generated_cpp += "}\n"
display_dict["script"].append(
{
"id": "main_draw",
"then": [
{"lambda": generated_cpp}
],
}
)
return display_dict