feat: Add Home Assistant auto-documentation to wiki
Security Audit / Docker Image Scan (docker.io/apache/tika:latest) (push) Failing after 4s
Security Audit / Infrastructure Scan (IaC) (push) Failing after 6s
Security Audit / Docker Image Scan (docker.io/gotenberg/gotenberg:8) (push) Failing after 5s
Security Audit / Docker Image Scan (docker.io/library/postgres:15) (push) Failing after 5s
Security Audit / Docker Image Scan (docker.io/library/redis:7) (push) Failing after 4s
Security Audit / Docker Image Scan (ghcr.io/paperless-ngx/paperless-ngx:latest) (push) Failing after 4s
Security Audit / Docker Image Scan (shenxn/protonmail-bridge:latest) (push) Failing after 4s
Security Audit / Docker Image Scan (ghcr.io/icereed/paperless-gpt:latest) (push) Failing after 17s

- Add generate-ha-docs.py script to query HA API
- Generate docs for entities, automations, scripts, scenes, devices, integrations
- Auto-regenerate HA docs every 15 minutes via cron
- Add HA token to vault
- Update mkdocs.yml navigation with HA Auto section

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-03-01 19:23:26 +01:00
co-authored by Claude
parent d398611425
commit 03bb3ce298
6 changed files with 593 additions and 113 deletions
+125 -113
View File
@@ -1,114 +1,126 @@
$ANSIBLE_VAULT;1.1;AES256
64393064366366386132356561333032366634326633643835373737336266353430373066383036
3633626338613238303162303433333831326462613935360a326664336165373630356536346331
35613966613236326633393733323666393862346564663262386461646263663262633866396339
3362373962643034620a366464333661376630346533396161393333646363636463653764383837
38343863626566386138303038613039333533346238343661616330633364323764316633326465
37633163383865343562623463666132643730633938343461376263363364386435336366363638
35663938633565353134316466373063343133303463356666666634623139643838336139363131
64353434646632656438663963353366626465646431333536376239616163653365653537386536
61383339626333383965316566373830383164613333343233336239613865336263393832323034
63653538356632373563623532656638633762323761623561333366616632643938653039383731
62343263643365613062393233336263363437323431346665383632373561666336383563663934
31396133363430333965643564346637306465666337363034613631326331653864633832336539
62666136363439356530366333373839636635613166316439366632613065346433346331303633
66623262633533373966656263323265343631653132343231396230316637666134316364366137
35323533376130613233663937373131306337383131653831356165643861666338623033346666
35363431313664316438383936373036313731396132323638396264326234636135396639313533
35643732303564303464643234376265356262663439633765393561663638623264666133393534
34376233363231646332313935373230356131663063333161323136366161396236646635636264
34633135623337366138316463396531323265666166323363376335356236613165666334616330
62393163653164333864666466613735373337333566313866376466613932356132363765653733
33386434653762306531303763366636313934656535373262326361613434316465623636393230
31306637383031653538386438666531313364323835666365306436633766666265663835376131
39323833356632353862306461636636663164656464323436336538316531393531643233353039
37393366323166626561353639333966343335663866643133653062373636623463643566313866
33336261383834306137383434613163386465343161653631633336623430623430393939643232
65316331393331383263343931343133343631653434643337633038303263636363303062343961
61323462376264646565623730323130626331663335326235366463343531373666643435383134
32333266646462323565343066363935376530666531396139363665376134653763303033373430
37626532363732616233646639343763346165633838613965303534656634626334393730366536
35626637363462633139333130613763313865613939393630366639313535623031653135373730
62393162313363636530383833376337316631373235396137323638626263333339346237666635
35633764383639636139366337383762626133323634356138656365303666333633623632303864
66363634333963346139613334363262303162356664313031653634643939303264386363326531
31646534616665343038396436323239313035663463366535643631356665323131636565623562
38346537646330343764343335316137373038346661383461613932656666333938303464313338
33323366346663333136623931383137326332643263623563356531306263303236303962323365
39363830643334333032303333313232626564333864633235646164393538663033633665336366
65373837353265356536356436653136346334623037343765383065393831386666653435346661
31346466343039663639333933323833623637313339383835616339373161663939333661363632
39336337373038326265646434326262396530626462633833643864653035656338633136613965
66323963313064653534376130386632356161623766643033613838323361306366366436373662
35393365383962643839346336303165666538633366396635303263633531306636383232396634
64623934336563616161623961306631333031626530336631333963343962336663353964623739
65346639396134616363623730636135636361653864363235343262656337386131623537653032
62653861353835373332393039633361643830613334623737323964353137323934376438323339
30653262323038656566646663306432623531623064616662306366363439333236663236623464
36353738653766313766333965636434376563633937626338616330383534396232663439353837
30636337653063376134623561383133323666303035656339303564613562646439396662346465
37333036353339313466393532653934303736353430373135343565383564393335346133383734
63313862313737373665386534326666326531313331363431636535646630353939626663383438
66343165343737363839303635653332616534363737343363636630373865303037653562386638
63373438633930613939323830333934373833363834656430626166636637376464363636366236
33393232393234343165656366346664366461343735363563383633363661613663393832373032
39666436376138353035343336633962643464336265636664623731343632663039386361306631
35383362363138343830376437333538636562306537376532616532363065396138636464346335
61643066376435616430653133303535653531393634393165333961633937653833323265366232
66666565626131623538363662393166393964343064623031303465333534343732656564303539
62376532306435326438646630363031343165376163393565356263306433326565313033343064
36336561666266353535633231363666336239353136656538313265363036366466303338633832
62383363653261323038376139303463306436333764313530333437623962656438323138386636
35643035396262303536376631373261383765313062643761343062663439613338663962313134
39373565363637646163346435616665663064383239643235636461396636666336376531646332
62626137616238383336653536353165626237613466613930656165633530363935613336643464
63313038663566623833666332653961306130646232626234656333653438646137383739393336
64636165636565396462373532373161633661386562643662383139633766646337343130383866
66363232356233313030326632656134363337643265633061666434333838323831343639393038
38643030396566383034346330373939346434396633393134643531363334383639316339646335
35623533316463353134626530656438373865333431326536643865383939383030643862636436
38653532393537646465633463363732343030626637666237393339373963623462613266343465
30393637656138663863623238333961396663656235383332646665383134623033363535623632
32346439386431336563653863636333333164366464363663356664623561636430616331323639
66323830383962666437333264396262303935613334333131316238386562633539613830633130
66343466363435343630356363616331333030626261336534326666663065326339386437373335
31333862346264613438623230626435666465666261373166616462363865363562323064643164
33633334623535356233626663636161623337643462653263313130373463393761353138643338
36303034326437336666393664343636633766336462623464363536373939326236336464643432
65373965626439396461353837663130353661656430643435343762336263356638653431643235
64366261356566393231636561656366613163656431656130373230373862306137326161303664
66646337373433386162626636303032613363663931353937343464333134353632386566636162
34303766313131343765316162326239363933363331306130356633663739613636666661363438
35366661653738636230326134303964623262663731623762643539616265316661636563303132
31346163653538656566613630366465393065336466343136393838326562346362633431366137
61313162393935386239373062663939303731663062666662353861363739616230633630636364
30323237303366316636396266386165626566343335363432323833353163333165653633646530
32313138343437626633653665623737613430373631336132353162346134376334373530626636
65303664663030653763386363316334643236316435643861363161353137376438373233363730
35363765653137386233366562613036653832663331633665656631613066616336626535633365
36306264623463313734333038316365623231613866666363306431663834643434633564393333
64366135616564316164353666313130653162336265373831633762666533633837646333663235
30353737356630623465363762363237616263356336343738333735626662663033623061393566
66303638386336313532306461363437313761393033393332646539653533653434363532383866
30346630323336333033653938316435346633313466653463313934383433613036386137326537
64373332363534363066353932396531663138326131393838346232303361623539363530663436
65363461313361376532356336643666656238373161393862316438306435383830386630633039
33353632323361653731636535303565353830396630643337626136376132383937343639616335
39316136396363313939303134373761393264653139363135653165363138316161633736373264
39623833653862316637626461386466323964646264313461613465656563303532376362346461
38663763666538643530613665623130633563313266656133633663333032616335356661306435
34633261323037373536633130613861643533616264363832336632613431343239326439356235
63396636663031653438333238633562646538333763363232376462383339633264306533373033
37636430333037363363356234646163346134656362393163383466316462613865366633396465
33353366356464303036653237326336323566353534626362303235643430303362666664373831
36633838366664373661626637623161373764303535653736333639356638353039363765353634
31633038656330623235313066353437393066333161383635653961333439663465653336346537
61313232336333326637636638326535613965653332316530343533343136353034323235363461
66313165393236383332373731316666333937393036303738663337336439333064616534366338
31396530333639353063616366313131663831393331643538643332383137313930306463333230
39346563366530626338313133343664316664323638336661366366393632303061333130613337
33616134613130633437323634636264653361613831613335383066616133313762383938666634
39306134623664636435333934363662643934623134626334623035653866316264376231313465
32366137343037656462633561376264313565643735356638653533343730333332326132396336
38383064363235313163353263343537373939396565623630623665646565633631613165616234
38396232336133646536366462376665336162323362643732643131393361396237
62356632343663393235653063393766376332613431303034346631616235313562626265643134
3639333031643831323334376230393765666336613135640a323832386462313366306461633632
34343164623965343866626133626338316663666234356439346637366630313033623734303737
6364313133666637350a646339373261313835346463333362323965386433373862303639653061
39663364346330633466303335626362653366306661646339323535373537333339303264653239
66346230643835616336303363346665383765303565666266643830653834313064326639343636
36643831643866653566616634346631653136656237346564363733623331656235393263636661
38353835643966623062303761616431653238323536393330623761643738356639613430623961
31396335316630346136643531656435323365353038383864313262653337643335623434626165
34633465656463643933313830323362323066383133353639326137613830663339396139643738
36313332643735303232353966306338653136336639373061323232363036643338363061656662
38383863373665343563653566626631346639646164633537396336303637316664313336643564
66366530356461656230333234393935646237383932626431366539313831303964396166643462
64333266353737363236336163373633663736386632323663613435363864303530323330396436
36613861373734386135643564386361393732383839663061316663373066303236396230373339
36613236353035306165393636663534316562653138326533376461316661636130663135333665
32383937373433383633393936376430393337616664666536613331636364666263353562373535
63646135623362663763356536656662626436663834383461386131363064326432386161646437
65643230366364363032333061616138613964336335636565323237373366346438666464303438
31623366396331326139666531393037666264386532303832343138383565393037346633343434
61353933333965643631343063373764396238316333336465663964636137323263396139306263
33633364343234353363363565303162653463623565326664316566396232393035303361343137
66373637333335363338633739643036383766393233653038373039633738323366333866613638
34313332343532306637613730653962333763663434383465336436393863353436626539323332
65316237333032646662306637313234303762626337633464323465306334653730386338313665
63386434313433336264623831653334646531306539346365633235383032316338386566343432
64393365663436353964373735313235613338346234373633396466356339316563343365353862
61643463616133386131633536616334616131623362666335353732623962346261623265313664
62353832326361306639343238313362323336653938666164373731343434343364386534323332
64313137366461323934346136313438313134386265303065343832643530613261356564396437
62646263323039396238393366653165643131663861393530633361343534623561396161333162
64373264303532393631306336306139373137333965633738353438363933386436303830666234
36386634353832636335366565353836633862623664313834386634373964663439353430376165
65646265373839393330393831373731306262356431323261646230306465666331616163303564
37336563366338653339303038613837376438376462666431626362613261663839653939343536
63303432356261386262393637323766336264376261636231646166373962666364393639636462
63623234666339356636643062653737396330386463323963656334636162386430333434643063
38613934376233323539616135666536646165383066396130396463343733613564303436366265
65636238313561313634396539343930333330393363343735353861303738643963336534326436
63333033303130353865383263373239373438326530383565303438663666643138386536646465
34393365656438663136386435356537393535343864666566313864313538646239353831303835
62363737613965346234653438306232353061303637653061373464313031616439383231343339
64643531323634366530333661323535323839323737303733333433616330313665303633633333
63363836613239616230656634646664656539363162343730353533316134336163663964616238
64633365616337363264643763336539343464343334333030393736346536353664666531343130
65643737343930343839393761373531663337386237303766303436616164313331373534323163
36616365303238633862636238343364313535333331646534383330623135313532346336313564
31333366313836376333633238336263633535333962383839323562623433366561336166336535
31363139646338393762363465613961366566663038356137336564316264353433363633363130
33393131373234343731323865636665376262386161326133616664613633303331656537383663
32333262383461383835303466363631373161653938343061353263383064336666396539346237
33316564326339383137653735663462383266356133333564323761633939666664383762333565
37613339663331616435363834316463366238316463303233653635643766343563383434653934
38303335363632323636623938656266613264336163306234653739393334616136303431366366
36326136306565633430626637636134646431336332633638323231396662393431633836613831
30306263633462616465616337366435306239313366646462656361663061633539343036386330
62666662373839613136383861653064643631383763393764613339333231666536633865656262
61386333663665666262386339353164346135393434646634336337336661306630366364616262
62343035653432383837343263313634316534366334303936363536356365373334323266383365
35636262336166653432366162383533326261653239643365363938306530396565646662643733
61633266393337313931393032646436653737616264613335326436623635386338353461303131
64386432373736376238363265663838393239636337313161383364626239613665346466643430
63313237313966303135636362363034376233663937353932383432346239313838663337633562
38313237303031326336346665396133353132396539663036353938653464643930626165623161
65376633373938366663323834373063346666343933333233306261653361343635336233303264
64363161653935623237356532633434333965663538666135343433653035643764343133393639
33363537636233326162393030643334353765643863633463643932353630376430663161373633
39636563653134366165646235386664383965376632323439666332366330363463353839653631
64303266353663323061376463336339363238613635636462333163643266333133343634623562
37633936613832333462633131636338626433353161666239313664633937653537356437366134
35383936316565646534323763373532323439643639333637356261316630383331303461653936
61666261303862326435326562306162323938353239353130633530616562373139316438643237
36363663393839656637663561336362366239616636373864626364353831353261383065653336
62386430623961313839383063626661316133343139336631653361336339303631613931303736
36626534376461653037323339653061326534636139626261663135646166343061353531373232
30333164333635386332316163656334346337633139333039623266643963323430333161363435
64613534316433353831633236356261333464393166303336623935633132643664316533373734
32373138376363626466356430306464336566336264313339366666376236653639633665346466
31616638646636636562363034353862613937616461303637633330643964353364653736393830
66376132653732326430666432666463613830366139333062626532656639333433333562303863
33613236346334383039633466363637323762373937326635333062383238383561386663376235
62313765313137333165373333336564646432653138393266313839333131623633393830656263
63613432343732646264626533363564386135656563366663323763636532303862656231336633
39363536616365376135653734663537356432393565343036633338323934316138623437326135
62306236613161643934306163376332303633363434613565613433633631626135363633663938
64643631306536343862323538616665636362633361373931326565656434356235373033646432
62666138353937303934653734653739356235653431376661383865613338353661363663316165
64373836613062633839313632303431326365363233326461333535363832323131643136633965
35623536336165623330646133373835323634356461643039386331623962633066366262303561
39393864376661663531626531653933363039316161633166383661363438616131366366303161
63333237333531386330623464656439393838316538373933373639633762313238643636313064
36376134343665353635616464373837313134653763366231336335633139393732343136386265
62613432373034643262376562383832356137616637313031396430316565386261653562643635
64363265353565666464303764626262396631396332373638663537353761626339346563383365
35653339346566393962353838613565326463346135383036636231383536396632303361376436
39393562363863343439333137616264313838366631623165343865623762333264386661636663
64656130626163633961353930373664633735313764663161323631663462646565653864366538
32643565373136373166333333633736653035353539326131323363316366376230316632333264
34623433353462633861353462633533343532386334656536356565323832343138373539623631
31346561663230396135633037396632373636393264336635396134643362316538323738346439
35363031346263386466313864373838363766366462666130396432643564343238343461323433
32613236633237646462396131666265356237366336613034643239646537613865643364616230
35346139663137626164356235366134616531623235623434613233613561373565393334333538
61633736653439323730333736303939393435363464383763366662396633333333303634333863
31346636343539346461356633393362633766343964303831636430666634373533303030666665
63363066323235633261636134323535626236333963613065356431613163306539653564366264
66313662383038323132346466616135373437343136353463316530373631366232356633653139
33396535323136393337366662376666353038613930326631633936336161373731393565643361
35343538353866323263386438313130373439343432636664633332613536323539626639303130
31323036663364383362663932643464373532376366363864373462626535373532356136343133
35376630333964373865336537653464613564356239633938663031636637336263643662356663
66383737663366643539353737663430633235633235313137343266376565336133373733613031
38323032353234323431663162393661306332336263323933393965656438366166633135663434
63643438363034373439393035656239623565363230626539656361656664306439653239313762
39353332356661353338643864386439663361393333353939333038643133656466646333326634
37373732646232303664396566633564366264633732613438633434646439353663346231306432
38393634363266623238653238383934396531373837303539666663343562633832663264666635
34313630333430316366636239626633313239386637336631666366376162353233383637653333
35383961383434363331366437323034666362373062616232333033343437333239306130613330
64653764383332333165323866346135356635363539633238303561326239303730363534613632
36633565313531303131343331646135663838653038383061643435393731313730383364623937
34346130643337353166383234666564323765393239303632616534333233633863343563323361
33323766373261656666316233313861383236353030393262396137363363666633373361326465
33333034656332386531666462653363356161383334383238336534323331383431646363636566
3566
@@ -0,0 +1,7 @@
---
# Wiki server configuration
# Home Assistant documentation generation
homeassistant_docs_enabled: true
homeassistant_url: "http://10.2.30.11:8123"
homeassistant_token: "{{ vault_homeassistant_token }}"
@@ -24,3 +24,9 @@ mkdocs_strict_mode: false
# Sync schedule (cron)
mkdocs_sync_enabled: true
mkdocs_sync_schedule: "*/15 * * * *" # Every 15 minutes
# Home Assistant documentation generation
homeassistant_docs_enabled: true
homeassistant_url: "http://10.2.30.11:8123"
# homeassistant_token: set in vault as vault_homeassistant_token
homeassistant_docs_dir: "{{ mkdocs_install_dir }}/docs/Services/Home Assistant Auto"
@@ -0,0 +1,413 @@
#!/usr/bin/env python3
"""
Home Assistant Documentation Generator
Queries the Home Assistant API and generates Markdown documentation
for entities, automations, integrations, and blueprints.
Usage:
python generate-ha-docs.py --url https://home.renner.uno --token <token> --output /path/to/docs
"""
import argparse
import json
import os
import sys
from datetime import datetime
from collections import defaultdict
try:
import requests
except ImportError:
print("Error: requests library required. Install with: pip install requests")
sys.exit(1)
class HomeAssistantDocs:
def __init__(self, url: str, token: str):
self.url = url.rstrip('/')
self.headers = {
'Authorization': f'Bearer {token}',
'Content-Type': 'application/json',
}
def _get(self, endpoint: str) -> dict:
"""Make GET request to HA API."""
resp = requests.get(f"{self.url}/api/{endpoint}", headers=self.headers, timeout=30)
resp.raise_for_status()
return resp.json()
def get_states(self) -> list:
"""Get all entity states."""
return self._get("states")
def get_config(self) -> dict:
"""Get HA configuration."""
return self._get("config")
def get_services(self) -> dict:
"""Get available services."""
return self._get("services")
def get_entities(self) -> dict:
"""Get entity registry via websocket-like endpoint."""
# This requires a different approach - we'll parse from states
return {}
def generate_entities_doc(self, states: list) -> str:
"""Generate entities documentation grouped by domain."""
domains = defaultdict(list)
for state in states:
entity_id = state.get('entity_id', '')
domain = entity_id.split('.')[0] if '.' in entity_id else 'unknown'
domains[domain].append(state)
lines = [
"# Home Assistant Entities",
"",
f"Last Updated: {datetime.now().strftime('%Y-%m-%d %H:%M')}",
"",
f"Total Entities: {len(states)}",
"",
"## Summary by Domain",
"",
"| Domain | Count |",
"|--------|-------|",
]
for domain in sorted(domains.keys()):
lines.append(f"| {domain} | {len(domains[domain])} |")
lines.extend(["", "## Entities by Domain", ""])
for domain in sorted(domains.keys()):
entities = domains[domain]
lines.extend([
f"### {domain.replace('_', ' ').title()} ({len(entities)})",
"",
"| Entity ID | Name | State |",
"|-----------|------|-------|",
])
for entity in sorted(entities, key=lambda x: x.get('entity_id', '')):
entity_id = entity.get('entity_id', '')
name = entity.get('attributes', {}).get('friendly_name', entity_id)
state = entity.get('state', 'unknown')
# Truncate long states
if len(state) > 30:
state = state[:27] + "..."
# Escape pipe characters
name = name.replace('|', '\\|')
state = state.replace('|', '\\|')
lines.append(f"| `{entity_id}` | {name} | {state} |")
lines.append("")
return '\n'.join(lines)
def generate_automations_doc(self, states: list) -> str:
"""Generate automations documentation."""
automations = [s for s in states if s.get('entity_id', '').startswith('automation.')]
lines = [
"# Home Assistant Automations",
"",
f"Last Updated: {datetime.now().strftime('%Y-%m-%d %H:%M')}",
"",
f"Total Automations: {len(automations)}",
"",
"## Automations List",
"",
"| Name | State | Last Triggered |",
"|------|-------|----------------|",
]
for auto in sorted(automations, key=lambda x: x.get('attributes', {}).get('friendly_name', '')):
attrs = auto.get('attributes', {})
name = attrs.get('friendly_name', auto.get('entity_id', ''))
state = auto.get('state', 'unknown')
last_triggered = attrs.get('last_triggered', 'Never')
if last_triggered and last_triggered != 'Never':
# Parse and format datetime
try:
dt = datetime.fromisoformat(last_triggered.replace('Z', '+00:00'))
last_triggered = dt.strftime('%Y-%m-%d %H:%M')
except:
pass
name = name.replace('|', '\\|')
lines.append(f"| {name} | {state} | {last_triggered} |")
lines.extend([
"",
"## Automation Details",
"",
])
for auto in sorted(automations, key=lambda x: x.get('attributes', {}).get('friendly_name', '')):
attrs = auto.get('attributes', {})
entity_id = auto.get('entity_id', '')
name = attrs.get('friendly_name', entity_id)
state = auto.get('state', 'unknown')
mode = attrs.get('mode', 'single')
current = attrs.get('current', 0)
last_triggered = attrs.get('last_triggered', 'Never')
lines.extend([
f"### {name}",
"",
f"- **Entity ID**: `{entity_id}`",
f"- **State**: {state}",
f"- **Mode**: {mode}",
f"- **Current runs**: {current}",
f"- **Last triggered**: {last_triggered}",
"",
])
return '\n'.join(lines)
def generate_integrations_doc(self, config: dict, services: dict) -> str:
"""Generate integrations documentation from config and services."""
lines = [
"# Home Assistant Integrations",
"",
f"Last Updated: {datetime.now().strftime('%Y-%m-%d %H:%M')}",
"",
]
# Config info
lines.extend([
"## Configuration",
"",
f"- **Version**: {config.get('version', 'unknown')}",
f"- **Location**: {config.get('location_name', 'unknown')}",
f"- **Unit System**: {config.get('unit_system', {}).get('temperature', 'unknown')}",
f"- **Time Zone**: {config.get('time_zone', 'unknown')}",
"",
"## Components",
"",
"Active components/integrations:",
"",
])
components = config.get('components', [])
for comp in sorted(components):
lines.append(f"- {comp}")
lines.extend([
"",
"## Available Services",
"",
"| Domain | Services |",
"|--------|----------|",
])
for service in sorted(services, key=lambda x: x.get('domain', '')):
domain = service.get('domain', '')
svc_list = list(service.get('services', {}).keys())
svc_count = len(svc_list)
lines.append(f"| {domain} | {svc_count} services |")
return '\n'.join(lines)
def generate_devices_doc(self, states: list) -> str:
"""Generate devices documentation by area/room."""
# Group entities by area if available, otherwise by domain
areas = defaultdict(list)
for state in states:
attrs = state.get('attributes', {})
# Try to get area from entity, fall back to domain grouping
entity_id = state.get('entity_id', '')
domain = entity_id.split('.')[0] if '.' in entity_id else 'unknown'
# Skip internal/system entities
if domain in ['automation', 'script', 'scene', 'group', 'persistent_notification']:
continue
# Use device_class or domain as category
device_class = attrs.get('device_class', domain)
areas[device_class].append(state)
lines = [
"# Home Assistant Devices",
"",
f"Last Updated: {datetime.now().strftime('%Y-%m-%d %H:%M')}",
"",
"## Devices by Type",
"",
]
for area in sorted(areas.keys()):
entities = areas[area]
if not entities:
continue
lines.extend([
f"### {area.replace('_', ' ').title()} ({len(entities)})",
"",
"| Entity | Name | State | Unit |",
"|--------|------|-------|------|",
])
for entity in sorted(entities, key=lambda x: x.get('attributes', {}).get('friendly_name', x.get('entity_id', ''))):
entity_id = entity.get('entity_id', '')
attrs = entity.get('attributes', {})
name = attrs.get('friendly_name', entity_id)
state = entity.get('state', '')
unit = attrs.get('unit_of_measurement', '')
# Truncate
if len(state) > 20:
state = state[:17] + "..."
name = name.replace('|', '\\|')
lines.append(f"| `{entity_id}` | {name} | {state} | {unit} |")
lines.append("")
return '\n'.join(lines)
def generate_scripts_doc(self, states: list) -> str:
"""Generate scripts documentation."""
scripts = [s for s in states if s.get('entity_id', '').startswith('script.')]
lines = [
"# Home Assistant Scripts",
"",
f"Last Updated: {datetime.now().strftime('%Y-%m-%d %H:%M')}",
"",
f"Total Scripts: {len(scripts)}",
"",
"| Name | State | Mode | Last Triggered |",
"|------|-------|------|----------------|",
]
for script in sorted(scripts, key=lambda x: x.get('attributes', {}).get('friendly_name', '')):
attrs = script.get('attributes', {})
name = attrs.get('friendly_name', script.get('entity_id', ''))
state = script.get('state', 'unknown')
mode = attrs.get('mode', 'single')
last_triggered = attrs.get('last_triggered', 'Never')
if last_triggered and last_triggered != 'Never':
try:
dt = datetime.fromisoformat(last_triggered.replace('Z', '+00:00'))
last_triggered = dt.strftime('%Y-%m-%d %H:%M')
except:
pass
name = name.replace('|', '\\|')
lines.append(f"| {name} | {state} | {mode} | {last_triggered} |")
return '\n'.join(lines)
def generate_scenes_doc(self, states: list) -> str:
"""Generate scenes documentation."""
scenes = [s for s in states if s.get('entity_id', '').startswith('scene.')]
lines = [
"# Home Assistant Scenes",
"",
f"Last Updated: {datetime.now().strftime('%Y-%m-%d %H:%M')}",
"",
f"Total Scenes: {len(scenes)}",
"",
"| Name | Entity ID |",
"|------|-----------|",
]
for scene in sorted(scenes, key=lambda x: x.get('attributes', {}).get('friendly_name', '')):
attrs = scene.get('attributes', {})
name = attrs.get('friendly_name', scene.get('entity_id', ''))
entity_id = scene.get('entity_id', '')
name = name.replace('|', '\\|')
lines.append(f"| {name} | `{entity_id}` |")
return '\n'.join(lines)
def main():
parser = argparse.ArgumentParser(description='Generate Home Assistant documentation')
parser.add_argument('--url', required=True, help='Home Assistant URL')
parser.add_argument('--token', required=True, help='Long-lived access token')
parser.add_argument('--output', required=True, help='Output directory for markdown files')
args = parser.parse_args()
# Create output directory
os.makedirs(args.output, exist_ok=True)
print(f"Connecting to Home Assistant at {args.url}...")
ha = HomeAssistantDocs(args.url, args.token)
try:
# Fetch data
print("Fetching states...")
states = ha.get_states()
print(f" Found {len(states)} entities")
print("Fetching config...")
config = ha.get_config()
print("Fetching services...")
services = ha.get_services()
print(f" Found {len(services)} service domains")
# Generate documentation
docs = [
("HA Entities.md", ha.generate_entities_doc(states)),
("HA Automations.md", ha.generate_automations_doc(states)),
("HA Integrations.md", ha.generate_integrations_doc(config, services)),
("HA Devices.md", ha.generate_devices_doc(states)),
("HA Scripts.md", ha.generate_scripts_doc(states)),
("HA Scenes.md", ha.generate_scenes_doc(states)),
]
for filename, content in docs:
filepath = os.path.join(args.output, filename)
with open(filepath, 'w') as f:
f.write(content)
print(f"Generated {filepath}")
# Generate index
index_content = f"""# Home Assistant Documentation
Last Updated: {datetime.now().strftime('%Y-%m-%d %H:%M')}
Auto-generated documentation from Home Assistant API.
## Contents
- [[HA Entities]] - All entities grouped by domain ({len(states)} total)
- [[HA Automations]] - Automation rules
- [[HA Scripts]] - Reusable scripts
- [[HA Scenes]] - Scene definitions
- [[HA Devices]] - Devices by type
- [[HA Integrations]] - Active integrations and services
## Home Assistant Info
- **Version**: {config.get('version', 'unknown')}
- **Location**: {config.get('location_name', 'unknown')}
- **URL**: {args.url}
"""
index_path = os.path.join(args.output, "Home Assistant Auto.md")
with open(index_path, 'w') as f:
f.write(index_content)
print(f"Generated {index_path}")
print("\nDone! Generated Home Assistant documentation.")
except requests.exceptions.RequestException as e:
print(f"Error connecting to Home Assistant: {e}")
sys.exit(1)
except Exception as e:
print(f"Error: {e}")
sys.exit(1)
if __name__ == '__main__':
main()
+33
View File
@@ -77,9 +77,42 @@
- mkdocs-material
- mkdocs-roamlinks-plugin
- mkdocs-static-i18n
- requests
virtualenv: "{{ mkdocs_venv_dir }}"
state: latest
# Home Assistant documentation generation
- name: Create HA docs directory
ansible.builtin.file:
path: "{{ homeassistant_docs_dir }}"
state: directory
owner: "{{ mkdocs_user }}"
group: "{{ mkdocs_group }}"
mode: "0755"
when: homeassistant_docs_enabled | default(false)
- name: Copy HA docs generator script
ansible.builtin.copy:
src: generate-ha-docs.py
dest: "{{ mkdocs_install_dir }}/generate-ha-docs.py"
owner: "{{ mkdocs_user }}"
group: "{{ mkdocs_group }}"
mode: "0755"
when: homeassistant_docs_enabled | default(false)
- name: Generate Home Assistant documentation
ansible.builtin.command:
cmd: >
{{ mkdocs_venv_dir }}/bin/python {{ mkdocs_install_dir }}/generate-ha-docs.py
--url "{{ homeassistant_url }}"
--token "{{ homeassistant_token }}"
--output "{{ homeassistant_docs_dir }}"
when:
- homeassistant_docs_enabled | default(false)
- homeassistant_token is defined
changed_when: true
ignore_errors: true
- name: Build MkDocs site
ansible.builtin.command:
cmd: "{{ mkdocs_venv_dir }}/bin/mkdocs build --site-dir {{ mkdocs_build_dir }}"
@@ -22,6 +22,15 @@ echo "[$(date)] Starting wiki sync..."
# rsync -avz --delete --exclude='.obsidian' --exclude='.git' \
# "${SOURCE_HOST}:${SOURCE_DIR}/" "${INSTALL_DIR}/docs/"
{% if homeassistant_docs_enabled | default(false) and homeassistant_token is defined %}
# Generate Home Assistant documentation
echo "[$(date)] Generating Home Assistant documentation..."
"${VENV_DIR}/bin/python" "${INSTALL_DIR}/generate-ha-docs.py" \
--url "{{ homeassistant_url }}" \
--token "{{ homeassistant_token }}" \
--output "{{ homeassistant_docs_dir }}" || echo "Warning: HA docs generation failed"
{% endif %}
# Rebuild site
cd "${INSTALL_DIR}"
"${VENV_DIR}/bin/mkdocs" build --site-dir "${BUILD_DIR}" --quiet