Add Home Assistant screen manager and runtime tile configuration
This commit is contained in:
@@ -7,7 +7,7 @@ import zipfile
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
FILES = ['.gitignore', 'README.md', 'AGENTS.md', 'requirements.txt', 'device.example.yaml',
|
||||
'calibration.example.yaml', 'secrets.yaml.example', 'cyd_ui.h', 'light_controls.h', 'LICENSE',
|
||||
'guition_diagnostics.h', 'guition-4848s040.yaml', 'guition-device.example.yaml', 'TILE_CONFIGURATION.md', 'CYD_STABILITY.md', 'TEST_RESULTS.md']
|
||||
'guition_diagnostics.h', 'guition-4848s040.yaml', 'guition-device.example.yaml', 'TILE_CONFIGURATION.md', 'CYD_STABILITY.md', 'TEST_RESULTS.md', 'repository.yaml']
|
||||
FOLDERS = ['docs', 'tools', 'tests', 'components', 'diagnostics', 'fonts']
|
||||
SUFFIXES = {'.py', '.cpp', '.h', '.md', '.ttf', '.txt'}
|
||||
|
||||
@@ -29,6 +29,11 @@ def export(root, output):
|
||||
for path in (root / folder).rglob('*'):
|
||||
if path.is_file() and '__pycache__' not in path.parts and (path.suffix in SUFFIXES or path.name == 'LICENSE'):
|
||||
paths.append(path)
|
||||
# Dedicated distribution directories only; never recursively include owner YAML.
|
||||
for folder in ['screen_manager', 'packages', 'installers']:
|
||||
for path in (root / folder).rglob('*'):
|
||||
if path.is_file() and '__pycache__' not in path.parts and (path.suffix in SUFFIXES | {'.yaml', '.html', '.js', '.css'} or path.name == 'Dockerfile'):
|
||||
paths.append(path)
|
||||
for path in paths:
|
||||
if path.is_symlink() or not path.resolve().is_relative_to(root):
|
||||
raise ValueError(f'Geen bestanden buiten de bronmap of symlinks toegestaan: {path}')
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
"""Generate self-contained remote packages from the maintained board profiles."""
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
REPO = 'https://github.com/MaxGramser/homeassistant_espscreen'
|
||||
REFS = {'cyd': 'main', 'guition': 'main'}
|
||||
|
||||
def generate(board):
|
||||
source = ROOT / ('home-like-2432s028.yaml' if board == 'cyd' else 'guition-4848s040.yaml')
|
||||
s = source.read_text()
|
||||
defaults = (ROOT / ('device.example.yaml' if board == 'cyd' else 'guition-device.example.yaml')).read_text()
|
||||
defaults += '\n' + (ROOT / 'calibration.example.yaml').read_text()
|
||||
replacements = dict(re.findall(r'^ (\w+): ("[^"\n]*")', defaults, re.M))
|
||||
replacements.update(DYNAMIC_TILES='"true"', DASHBOARD_INBOX_INTERNAL='"false"', DIRECT_ACTIONS='"true"',
|
||||
ROOM_NAME='"Kies tegels in HA"', TILE_COUNT='"1"')
|
||||
s = re.sub(r'^ (\w+): ("[^"\n]*")', lambda m: f' {m[1]}: {replacements.get(m[1],m[2])}', s, flags=re.M)
|
||||
# The owner's wizard YAML supplies wifi/API/OTA credentials. No shared keys.
|
||||
s = re.sub(r'^ encryption:\n key: !secret api_encryption_key\n', '', s, flags=re.M)
|
||||
s = re.sub(r'^ota:\n.*?(?=^\w)', '', s, flags=re.M | re.S)
|
||||
s = re.sub(r'^wifi:\n.*?(?=^\w)', '', s, flags=re.M | re.S)
|
||||
# Referenced files are fetched as an external component or over HTTPS.
|
||||
s = re.sub(r'^ - (cyd_ui.h|light_controls.h|guition_diagnostics.h)$', r' - <esphome/components/smart_display/\1>', s, flags=re.M)
|
||||
components = '[xpt2046, smart_display]' if board == 'cyd' else '[smart_display]'
|
||||
external = f'''external_components:
|
||||
- source:
|
||||
type: git
|
||||
url: {REPO}.git
|
||||
ref: {REFS[board]}
|
||||
path: components
|
||||
refresh: 0s
|
||||
components: {components}
|
||||
|
||||
'''
|
||||
s = re.sub(r'^external_components:\n.*?(?=^\w)', lambda m: external, s, flags=re.M | re.S)
|
||||
s = re.sub(r'file: ["\']fonts/([^"\']+)["\']', lambda m: 'file: "https://raw.githubusercontent.com/MaxGramser/homeassistant_espscreen/main/fonts/' + m[1] + '"', s)
|
||||
# Keep the established card bindings, but remove all fixed HA subscriptions.
|
||||
# Runtime values arrive through ESP Screen Manager, including after changing entities.
|
||||
for section in ['sensor', 'text_sensor']:
|
||||
match = re.search(r'^' + section + r':\n.*?(?=^[a-zA-Z_]+:|\Z)', s, re.M | re.S)
|
||||
if not match: continue
|
||||
block = match[0]
|
||||
def sensor(m):
|
||||
body = re.sub(r'^ (entity_id|attribute):.*\n', '', m[1], flags=re.M)
|
||||
return ' - platform: template\n update_interval: never\n' + body
|
||||
block = re.sub(r'^ - platform: homeassistant\n(.*?)(?=^ - platform:|\Z)', sensor, block, flags=re.M | re.S)
|
||||
s = s[:match.start()] + block + s[match.end():]
|
||||
if '!secret' in s: raise ValueError('Remote package still depends on local secrets')
|
||||
return '# GENERATED by tools/generate_packages.py; edit the source board profile.\n' + s
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--check', action='store_true')
|
||||
args = parser.parse_args()
|
||||
for board in REFS:
|
||||
source = ROOT / ('home-like-2432s028.yaml' if board == 'cyd' else 'guition-4848s040.yaml')
|
||||
if not source.exists(): continue
|
||||
path = ROOT / 'packages' / f'{board}.yaml'
|
||||
expected = generate(board)
|
||||
if args.check:
|
||||
if not path.exists() or path.read_text() != expected: raise SystemExit(f'Outdated: {path}')
|
||||
else:
|
||||
path.parent.mkdir(exist_ok=True)
|
||||
path.write_text(expected)
|
||||
print(f'{board}: package ' + ('verified' if args.check else 'generated'))
|
||||
|
||||
if __name__ == '__main__': main()
|
||||
Reference in New Issue
Block a user