Add in Alexa Last used Sensor. #768

This commit is contained in:
ccostan 2020-06-07 14:29:26 -04:00
parent f9094e57d4
commit 93c5bb6837
34 changed files with 441 additions and 233 deletions

View File

@ -1,6 +1,7 @@
{ {
"common": { "common": {
"about": "Om", "about": "Om",
"add": "tilføj",
"appdaemon_apps": "AppDaemon-apps", "appdaemon_apps": "AppDaemon-apps",
"appdaemon_plural": "AppDaemon-apps", "appdaemon_plural": "AppDaemon-apps",
"background_task": "Baggrundsopgave kører. Denne side vil genindlæses automatisk.", "background_task": "Baggrundsopgave kører. Denne side vil genindlæses automatisk.",
@ -10,6 +11,7 @@
"documentation": "Dokumentation", "documentation": "Dokumentation",
"element": "element", "element": "element",
"hacs_is_disabled": "HACS er deaktiveret", "hacs_is_disabled": "HACS er deaktiveret",
"install": "Installer",
"installed": "installeret", "installed": "installeret",
"integration": "Integration", "integration": "Integration",
"integration_plural": "Integrationer", "integration_plural": "Integrationer",
@ -28,10 +30,12 @@
"python_script_plural": "Python-scripts", "python_script_plural": "Python-scripts",
"python_scripts": "Python-scripts", "python_scripts": "Python-scripts",
"repositories": "Repositories", "repositories": "Repositories",
"repository": "Repository",
"settings": "indstillinger", "settings": "indstillinger",
"theme": "Tema", "theme": "Tema",
"theme_plural": "Temaer", "theme_plural": "Temaer",
"themes": "Temaer", "themes": "Temaer",
"uninstall": "Afinstaller",
"version": "Version" "version": "Version"
}, },
"config": { "config": {
@ -77,6 +81,92 @@
"upgrade_all": "Dette vil opdatere alle repositories. Sørg for at du har læst udgivelsesnoterne for dem alle, inden du fortsætter.", "upgrade_all": "Dette vil opdatere alle repositories. Sørg for at du har læst udgivelsesnoterne for dem alle, inden du fortsætter.",
"yes": "Ja" "yes": "Ja"
}, },
"dialog_about": {
"frontend_version": "Frontend-version",
"installed_repositories": "Installerede repositories",
"integration_version": "Integrationsversion",
"useful_links": "Nyttige links"
},
"dialog_add_repo": {
"limit": "Kun de første 100 repositories vises. Brug søgningen til at filtrere, hvad du har brug for",
"no_match": "Der blev ikke fundet nogen repositories, der matcher dit filter",
"sort_by": "Sorter efter",
"title": "Tilføj repository"
},
"dialog_custom_repositories": {
"category": "Kategori",
"no_category": "Manglende kategori",
"no_repository": "Manglende repository",
"title": "Brugerdefinerede repositories",
"url_placeholder": "Tilføj brugerdefineret repository-webadresse"
},
"dialog_info": {
"author": "Udvikler",
"downloads": "Downloads",
"install": "Installer dette repository i HACS",
"loading": "Indlæser oplysninger...",
"no_info": "Udvikleren har ikke givet flere oplysninger om dette repository",
"open_repo": "Åbn repository",
"stars": "Stjerner",
"version_installed": "Installeret version"
},
"dialog_install": {
"restart": "Husk, at du skal genstarte Home Assistant, før ændringer af integrationer (custom_components) træder i kræft.",
"select_version": "Vælg version",
"show_beta": "Vis betaversioner",
"type": "Type",
"url": "Webadresse"
},
"dialog_update": {
"available_version": "Tilgængelig version",
"changelog": "Udgivelsesnoter",
"installed_version": "Installeret version",
"title": "Ventende opdatering"
},
"entry": {
"information": "Oplysninger",
"intro": "Opdateringer og vigtige meddelelser vises her, hvis der er nogen",
"messages": {
"disabled": {
"content": "Tjek din logfil for flere detaljer",
"title": "HACS er deaktiveret"
},
"has_pending_tasks": {
"content": "Nogle repositories vises muligvis ikke, før dette er fuldført",
"title": "Baggrundsopgaver venter"
},
"resources": {
"content": "Du har {number} Lovelace-elementer, der ikke er indlæst korrekt i Lovelace.",
"title": "Ikke indlæst i Lovelace"
},
"restart": {
"content": "Du har {number} integrationer, der kræver en genstart af Home Assistant. Du kan genstarte fra 'Serveradministration'-sektionen under Indstillinger i Home Assistant-brugerfladen.",
"title": "Afventer genstart"
},
"startup": {
"content": "HACS starter op. Der kan i dette tidsrum mangle nogle oplysninger, eller de kan være ukorekte.",
"title": "HACS starter op"
},
"wrong_frontend_installed": {
"content": "Du har version {running} af HACS-frontend installeret, men version {expected} var forventet, hvis dette ser du denne besked. Home Assistant kunne ikke installere den nye version. Prøv at genstarte Home Assistant.",
"title": "Uventet frontend-version"
},
"wrong_frontend_loaded": {
"content": "Du kører version {running} af HACS-frontend, men version {expected} var forventet. Du bør rydde din browser-cache.",
"title": "Uventet frontend-version"
}
},
"pending_updates": "Ventende opdateringer"
},
"menu": {
"about": "Om HACS",
"clear": "Ryd alle nye",
"custom_repositories": "Brugerdefinerede repositories",
"dismiss": "Afvis alle nye repositories",
"documentation": "Dokumentation",
"open_issue": "Opret issue",
"reload": "Genindlæs vindue"
},
"options": { "options": {
"step": { "step": {
"user": { "user": {
@ -104,6 +194,18 @@
"restart": "Du skal genstarte Home Assistant.", "restart": "Du skal genstarte Home Assistant.",
"restart_pending": "Afventer genstart" "restart_pending": "Afventer genstart"
}, },
"repository_card": {
"dismiss": "Afvis",
"hide": "Skjul",
"information": "Oplysninger",
"new_repository": "Nyt repository",
"not_loaded": "Ikke indlæst",
"open_issue": "Opret issue",
"pending_restart": "Afventer genstart",
"pending_update": "Ventende opdatering",
"reinstall": "Geninstaller",
"report": "Rapporter til fjernelse"
},
"repository": { "repository": {
"add_to_lovelace": "Tilføj til Lovelace", "add_to_lovelace": "Tilføj til Lovelace",
"authors": "Forfattere", "authors": "Forfattere",
@ -138,6 +240,9 @@
"update_information": "Opdater oplysninger", "update_information": "Opdater oplysninger",
"upgrade": "Opdater" "upgrade": "Opdater"
}, },
"search": {
"placeholder": "Søg efter repository"
},
"sections": { "sections": {
"about": { "about": {
"description": "Vis information om HACS", "description": "Vis information om HACS",
@ -188,7 +293,13 @@
"last_updated": "Sidst opdateret", "last_updated": "Sidst opdateret",
"name": "Navn", "name": "Navn",
"new_repositories": "Nye repositories", "new_repositories": "Nye repositories",
"pending_upgrades": "Afventende opdateringer", "new_repositories_note": "Du har over 10 nye repositories, der vises her, hvis du vil rydde dem alle, skal du klikke på de 3 prikker i øverste højre hjørne og afvise dem alle.",
"no_repositories": "Ingen repositories",
"no_repositories_desc1": "Det ser ud til, at du ikke har nogen repositories installeret i denne sektion endnu.",
"no_repositories_desc2": "Klik på + i nederste hjørne for at tilføje dit første!",
"no_repositories_found_desc1": "Der blev ikke fundet installerede repositories, der matcher \"{searchInput}\" i denne sektion.",
"no_repositories_found_desc2": "Prøv at søge efter noget andet!",
"pending_upgrades": "Ventende opdateringer",
"placeholder_search": "Indtast en søgeterm...", "placeholder_search": "Indtast en søgeterm...",
"sort": "sorter", "sort": "sorter",
"stars": "Stjerner", "stars": "Stjerner",

View File

@ -80,6 +80,32 @@
"upgrade_all": "Hierdurch werden all diese Repositories aktualisiert. Stelle sicher, dass du die Versionshinweise vorher gelesen hast.", "upgrade_all": "Hierdurch werden all diese Repositories aktualisiert. Stelle sicher, dass du die Versionshinweise vorher gelesen hast.",
"yes": "Ja" "yes": "Ja"
}, },
"dialog_add_repo": {
"sort_by": "Sortiere nach"
},
"dialog_install": {
"restart": "Denken Sie daran, dass Sie Home Assistant neu starten müssen, bevor Änderungen an Integrationen (custom_components) angewendet werden."
},
"entry": {
"messages": {
"resources": {
"content": "Sie haben {number} Lovelace-Elemente, die in Lovelace nicht richtig geladen sind.",
"title": "Nicht in Lovelace geladen"
},
"restart": {
"content": "Sie haben {number} -Integrationen, die einen Neustart von Home Assistant erfordern. Dies können Sie im Abschnitt 'Server Controls' im Konfigurationsteil der Home Assistant-Benutzeroberfläche tun.",
"title": "Ausstehender Neustart"
},
"wrong_frontend_installed": {
"content": "Sie haben {running} des HACS-Frontends installiert, aber Version {expected} wurde erwartet. Wenn diese Meldung angezeigt wird, dass Home Assistant die neue Version nicht installieren konnte, starten Sie Home Assistant neu.",
"title": "Unerwartete Frontend-Version"
},
"wrong_frontend_loaded": {
"content": "Sie führen die Version {running} des HACS-Frontends aus, aber es wurde die Version {expected} erwartet. Sie sollten Ihren Browser-Cache leeren.",
"title": "Unerwartete Frontend-Version"
}
}
},
"menu": { "menu": {
"dismiss": "Alle neuen Repositories ausblenden" "dismiss": "Alle neuen Repositories ausblenden"
}, },
@ -111,7 +137,11 @@
"restart_pending": "Neustart ausstehend" "restart_pending": "Neustart ausstehend"
}, },
"repository_card": { "repository_card": {
"dismiss": "Ausblenden" "dismiss": "Ausblenden",
"not_loaded": "Nicht geladen",
"open_source": "Quelldateien öffnen",
"pending_restart": "Ausstehender Neustart",
"report": "Melden zur Entfernung des Repositorys"
}, },
"repository": { "repository": {
"add_to_lovelace": "Zu Lovelace hinzufügen", "add_to_lovelace": "Zu Lovelace hinzufügen",

View File

@ -15,7 +15,7 @@
"manage": "διαχειρίζονται", "manage": "διαχειρίζονται",
"netdaemon": "NetDaemon", "netdaemon": "NetDaemon",
"netdaemon_apps": "NetDaemon Apps", "netdaemon_apps": "NetDaemon Apps",
"plugin": "Πρόσθετο", "plugin": "Lovelace",
"plugins": "Πρόσθετα", "plugins": "Πρόσθετα",
"python_script": "Πρόγραμμα Python", "python_script": "Πρόγραμμα Python",
"python_scripts": "Προγράμματα Python", "python_scripts": "Προγράμματα Python",

View File

@ -140,9 +140,25 @@
"content": "Some repositories might not show untill this is completed", "content": "Some repositories might not show untill this is completed",
"title": "Background tasks pending" "title": "Background tasks pending"
}, },
"resources": {
"content": "You have {number} Lovelace elements that are not loaded properly in Lovelace.",
"title": "Not loaded in Lovelace"
},
"restart": {
"content": "You have {number} integrations that requires a restart of Home Assistant, you can do that from the 'Server Controls' section under the configuration part of Home Assistant UI.",
"title": "Pending restart"
},
"startup": { "startup": {
"content": "HACS is starting up, during this time some information might be missing or incorrect", "content": "HACS is starting up, during this time some information might be missing or incorrect",
"title": "HACS is starting up" "title": "HACS is starting up"
},
"wrong_frontend_installed": {
"content": "You have {running} of the HACS frontend installed, but version {expected} was expected, if this you see this message Home Assistant was not able to install the new version, try restarting Home Assistant.",
"title": "Unexpected frontend version"
},
"wrong_frontend_loaded": {
"content": "You are running version {running} of the HACS frontend, but version {expected} was expected, you should clear your browser cache.",
"title": "Unexpected frontend version"
} }
}, },
"pending_updates": "Pending updates" "pending_updates": "Pending updates"
@ -188,8 +204,10 @@
"hide": "Hide", "hide": "Hide",
"information": "Information", "information": "Information",
"new_repository": "New repository", "new_repository": "New repository",
"not_loaded": "Not loaded",
"open_issue": "Open issue", "open_issue": "Open issue",
"open_source": "Open source", "open_source": "Open source",
"pending_restart": "Pending restart",
"pending_update": "Pending update", "pending_update": "Pending update",
"reinstall": "Reinstall", "reinstall": "Reinstall",
"report": "Report for removal", "report": "Report for removal",
@ -286,6 +304,8 @@
"no_repositories": "No repositories", "no_repositories": "No repositories",
"no_repositories_desc1": "It seems like you don't have any repositories installed in this section yet.", "no_repositories_desc1": "It seems like you don't have any repositories installed in this section yet.",
"no_repositories_desc2": "Click on the + in the bottom corner to add your first!", "no_repositories_desc2": "Click on the + in the bottom corner to add your first!",
"no_repositories_found_desc1": "No installed repositories matching \"{searchInput}\" found in this section.",
"no_repositories_found_desc2": "Try searching for something else!",
"pending_upgrades": "Pending upgrades", "pending_upgrades": "Pending upgrades",
"placeholder_search": "Please enter a search term...", "placeholder_search": "Please enter a search term...",
"sort": "sort", "sort": "sort",

View File

@ -15,8 +15,8 @@
"manage": "gérer", "manage": "gérer",
"netdaemon": "NetDaemon", "netdaemon": "NetDaemon",
"netdaemon_apps": "Applications NetDaemon", "netdaemon_apps": "Applications NetDaemon",
"plugin": "Plugin", "plugin": "Lovelace",
"plugins": "Plugins", "plugins": "Éléments Lovelace",
"python_script": "Script Python", "python_script": "Script Python",
"python_scripts": "Scripts Python", "python_scripts": "Scripts Python",
"repositories": "Dépôts", "repositories": "Dépôts",

View File

@ -76,7 +76,7 @@
"home_assistant_is_restarting": "Várj, a Home Assistant éppen újraindul.", "home_assistant_is_restarting": "Várj, a Home Assistant éppen újraindul.",
"home_assistant_version_not_correct": "A Home Assistant '{haversion}' verzióját használod, de ehhez a tárolóhoz legalább a(z) '{minversion}' verzióra van szükség.", "home_assistant_version_not_correct": "A Home Assistant '{haversion}' verzióját használod, de ehhez a tárolóhoz legalább a(z) '{minversion}' verzióra van szükség.",
"no": "Nem", "no": "Nem",
"no_upgrades": "Nincs függőben lévő frissítés", "no_upgrades": "Nincsenek elérhető frissítések",
"ok": "OK", "ok": "OK",
"overwrite": "Ezzel felül fogod írni.", "overwrite": "Ezzel felül fogod írni.",
"reload_data": "Ez újratölti a HACS által ismert összes tároló adatát, ami némi időbe telhet.", "reload_data": "Ez újratölti a HACS által ismert összes tároló adatát, ami némi időbe telhet.",
@ -93,7 +93,8 @@
}, },
"dialog_add_repo": { "dialog_add_repo": {
"limit": "Csak az első 100 tároló jelenik meg, használd a keresőt a találatok szűkítéséhez", "limit": "Csak az első 100 tároló jelenik meg, használd a keresőt a találatok szűkítéséhez",
"no_match": "Nincs a szűrőnek megfelelő tároló", "no_match": "Nincs a szűrésnek megfelelő tároló",
"sort_by": "Rendezés",
"title": "Tároló hozzáadása" "title": "Tároló hozzáadása"
}, },
"dialog_custom_repositories": { "dialog_custom_repositories": {
@ -109,11 +110,13 @@
"install": "Tároló telepítése HACS-ben", "install": "Tároló telepítése HACS-ben",
"loading": "Információ betöltése...", "loading": "Információ betöltése...",
"no_info": "A fejlesztő nem adott meg több információt ehhez a tárolóhoz", "no_info": "A fejlesztő nem adott meg több információt ehhez a tárolóhoz",
"open_issues": "Jelentett problémák",
"open_repo": "Tároló megnyitása", "open_repo": "Tároló megnyitása",
"stars": "Csillagok", "stars": "Csillagok",
"version_installed": "Telepített verzió" "version_installed": "Telepített verzió"
}, },
"dialog_install": { "dialog_install": {
"restart": "Ne feledd, hogy az egyéni integrációk (custom_components) módosításainak alkalmazásához újra kell indítanod a Home Assistant alkalmazást.",
"select_version": "Verzió kiválasztása", "select_version": "Verzió kiválasztása",
"show_beta": "Béta verziók megjelenítése", "show_beta": "Béta verziók megjelenítése",
"type": "Típus", "type": "Típus",
@ -123,29 +126,32 @@
"available_version": "Elérhető verzió", "available_version": "Elérhető verzió",
"changelog": "Változási napló", "changelog": "Változási napló",
"installed_version": "Telepített verzió", "installed_version": "Telepített verzió",
"title": "Frissítés függőben" "title": "Frissítés érhető el"
}, },
"entry": { "entry": {
"information": "Információ", "information": "Információ",
"intro": "A frissítések és a fontos üzenetek itt jelennek meg, ha vannak",
"messages": { "messages": {
"disabled": { "disabled": {
"content": "További részletek a naplófájlban", "content": "További részletek a naplófájlban",
"title": "A HACS le van tiltva" "title": "A HACS le van tiltva"
}, },
"has_pending_tasks": { "has_pending_tasks": {
"content": "Előfordulhat, hogy egyes tárolók nem jelennek meg, amíg ez be nem fejeződik",
"title": "Függőben lévő háttérfeladatok" "title": "Függőben lévő háttérfeladatok"
}, },
"startup": { "startup": {
"content": "A HACS éppen indul, ezidő alatt egyes információk hiányozhatnak vagy helytelenek lehetnek", "content": "A HACS éppen indul, ezidő alatt egyes információk hiányozhatnak vagy helytelenek lehetnek",
"title": "A HACS indul" "title": "A HACS éppen indul"
} }
}, },
"pending_updates": "Függő frissítések" "pending_updates": "Frissítések érhetők el"
}, },
"menu": { "menu": {
"about": "HACS névjegye", "about": "HACS névjegye",
"clear": "Új jelölések törlése", "clear": "Új jelölések törlése",
"custom_repositories": "Egyéni tárolók", "custom_repositories": "Egyéni tárolók",
"dismiss": "Minden új tároló elvetése",
"documentation": "Dokumentáció", "documentation": "Dokumentáció",
"open_issue": "Probléma jelentése", "open_issue": "Probléma jelentése",
"reload": "Ablak újratöltése" "reload": "Ablak újratöltése"
@ -178,15 +184,16 @@
"restart_pending": "Újraindítás függőben" "restart_pending": "Újraindítás függőben"
}, },
"repository_card": { "repository_card": {
"dismiss": "elvetés",
"hide": "Elrejtés", "hide": "Elrejtés",
"information": "Információ", "information": "Információ",
"new_repository": "Új tároló", "new_repository": "Új tároló",
"open_issue": "Probléma jelentése", "open_issue": "Probléma jelentése",
"open_source": "Forrás megnyitása", "open_source": "Forrás megnyitása",
"pending_update": "Függő frissítés", "pending_update": "Frissítés érhető el",
"reinstall": "Újratelepítés", "reinstall": "Újratelepítés",
"report": "Jelentés eltávolításra", "report": "Jelentés eltávolításra",
"update_information": "Frissítési információk" "update_information": "Frissítési információ"
}, },
"repository": { "repository": {
"add_to_lovelace": "Hozzáadás a Lovelace-hez", "add_to_lovelace": "Hozzáadás a Lovelace-hez",
@ -275,9 +282,11 @@
"last_updated": "Utolsó frissítés", "last_updated": "Utolsó frissítés",
"name": "Név", "name": "Név",
"new_repositories": "Új tárolók", "new_repositories": "Új tárolók",
"no_repositories": "Nincs tároló", "new_repositories_note": "Több mint 10 új tároló látható. Ha törölni szeretnéd őket, akkor kattints a jobb felső sarokban lévő 3 pontra, és válaszd ki a 'Minden új tároló elvetése' menüpontot.",
"no_repositories_desc1": "Úgy tűnik, még nincsenek telepítve tárolók ebben a részben.", "no_repositories": "Nincsenek tárolók",
"pending_upgrades": "Függőben lévő frissítések", "no_repositories_desc1": "Úgy tűnik, még nincsenek telepítve tárolók ebben a szekcióban.",
"no_repositories_desc2": "Kattints az alsó sarokban található + jelre az első hozzáadásához!",
"pending_upgrades": "Frissítések érhetők el",
"placeholder_search": "Kérlek adj meg egy keresési kifejezést...", "placeholder_search": "Kérlek adj meg egy keresési kifejezést...",
"sort": "rendezés", "sort": "rendezés",
"stars": "Csillag", "stars": "Csillag",

View File

@ -15,7 +15,7 @@
"manage": "gestione", "manage": "gestione",
"netdaemon": "NetDaemon", "netdaemon": "NetDaemon",
"netdaemon_apps": "Applicazioni NetDaemon", "netdaemon_apps": "Applicazioni NetDaemon",
"plugin": "Plugin", "plugin": "Lovelace",
"plugins": "Plugin", "plugins": "Plugin",
"python_script": "Script python", "python_script": "Script python",
"python_scripts": "Script python", "python_scripts": "Script python",

View File

@ -15,7 +15,7 @@
"manage": "beheer", "manage": "beheer",
"netdaemon": "NetDaemon", "netdaemon": "NetDaemon",
"netdaemon_apps": "NetDaemon Apps", "netdaemon_apps": "NetDaemon Apps",
"plugin": "Plugin", "plugin": "Lovelace",
"plugins": "Plugins", "plugins": "Plugins",
"python_script": "Python Script", "python_script": "Python Script",
"python_scripts": "Python Scripts", "python_scripts": "Python Scripts",

View File

@ -22,9 +22,9 @@
"netdaemon": "NetDaemon", "netdaemon": "NetDaemon",
"netdaemon_apps": "NetDeamon-appar", "netdaemon_apps": "NetDeamon-appar",
"netdaemon_plural": "NetDaemon-appar", "netdaemon_plural": "NetDaemon-appar",
"plugin": "Tillegg", "plugin": "Lovelace",
"plugin_plural": "Lovelace-element", "plugin_plural": "Lovelace-element",
"plugins": "Tillegg", "plugins": "Lovelace-element",
"python_script": "Pythonskript", "python_script": "Pythonskript",
"python_script_plural": "Pythonskript", "python_script_plural": "Pythonskript",
"python_scripts": "Pythonskript", "python_scripts": "Pythonskript",

View File

@ -21,9 +21,9 @@
"netdaemon": "NetDaemon", "netdaemon": "NetDaemon",
"netdaemon_apps": "Aplikacje NetDaemon", "netdaemon_apps": "Aplikacje NetDaemon",
"netdaemon_plural": "Aplikacje NetDaemon", "netdaemon_plural": "Aplikacje NetDaemon",
"plugin": "Wtyczka", "plugin": "Lovelace",
"plugin_plural": "Elementy Lovelace", "plugin_plural": "Elementy Lovelace",
"plugins": "Wtyczki", "plugins": "Elementy Lovelace",
"python_script": "Skrypt Python", "python_script": "Skrypt Python",
"python_script_plural": "Skrypty języka Python", "python_script_plural": "Skrypty języka Python",
"python_scripts": "Skrypty Python", "python_scripts": "Skrypty Python",
@ -131,7 +131,7 @@
"note_plugin": "musisz jeszcze dodać wtyczkę do konfiguracji interfejsu użytkownika (plik 'ui-lovelace.yaml' lub edytor interfejsu użytkownika)", "note_plugin": "musisz jeszcze dodać wtyczkę do konfiguracji interfejsu użytkownika (plik 'ui-lovelace.yaml' lub edytor interfejsu użytkownika)",
"note_plugin_post_107": "nadal musisz dodać go do konfiguracji Lovelace ('configuration.yaml' lub edytora zasobów '\/config\/lovelace\/resources')", "note_plugin_post_107": "nadal musisz dodać go do konfiguracji Lovelace ('configuration.yaml' lub edytora zasobów '\/config\/lovelace\/resources')",
"open_issue": "Powiadom o problemie", "open_issue": "Powiadom o problemie",
"open_plugin": "Otwórz dodatek", "open_plugin": "Otwórz element",
"reinstall": "Przeinstaluj", "reinstall": "Przeinstaluj",
"repository": "Repozytorium", "repository": "Repozytorium",
"restart_home_assistant": "Uruchom ponownie Home Assistant'a", "restart_home_assistant": "Uruchom ponownie Home Assistant'a",

View File

@ -15,7 +15,7 @@
"manage": "управлять", "manage": "управлять",
"netdaemon": "NetDaemon", "netdaemon": "NetDaemon",
"netdaemon_apps": "Приложения NetDaemon", "netdaemon_apps": "Приложения NetDaemon",
"plugin": "Плагин", "plugin": "Lovelace",
"plugins": "Плагины", "plugins": "Плагины",
"python_script": "Скрипт Python", "python_script": "Скрипт Python",
"python_scripts": "Скрипты Python", "python_scripts": "Скрипты Python",

View File

@ -15,7 +15,7 @@
"manage": "hantera", "manage": "hantera",
"netdaemon": "NetDaemon", "netdaemon": "NetDaemon",
"netdaemon_apps": "NetDaemon Applikationer", "netdaemon_apps": "NetDaemon Applikationer",
"plugin": "Plugin", "plugin": "Lovelace",
"plugins": "Plugins", "plugins": "Plugins",
"python_script": "Python skript", "python_script": "Python skript",
"python_scripts": "Python skript", "python_scripts": "Python skript",

View File

@ -15,13 +15,14 @@ from homeassistant.exceptions import ConfigEntryNotReady, ServiceNotFound
from homeassistant.helpers.aiohttp_client import async_create_clientsession from homeassistant.helpers.aiohttp_client import async_create_clientsession
from homeassistant.helpers.event import async_call_later from homeassistant.helpers.event import async_call_later
from custom_components.hacs.configuration_schema import hacs_config_combined from custom_components.hacs.configuration_schema import hacs_config_combined, FRONTEND_REPO, FRONTEND_REPO_URL
from custom_components.hacs.const import DOMAIN, ELEMENT_TYPES, STARTUP, VERSION from custom_components.hacs.const import DOMAIN, ELEMENT_TYPES, STARTUP, VERSION
from custom_components.hacs.constrains import check_constrains from custom_components.hacs.constrains import check_constrains
from custom_components.hacs.helpers.remaining_github_calls import get_fetch_updates_for from custom_components.hacs.helpers.remaining_github_calls import get_fetch_updates_for
from custom_components.hacs.hacsbase.configuration import Configuration from custom_components.hacs.hacsbase.configuration import Configuration
from custom_components.hacs.hacsbase.data import HacsData from custom_components.hacs.hacsbase.data import HacsData
from custom_components.hacs.setup import ( from custom_components.hacs.setup import (
clear_storage,
add_sensor, add_sensor,
load_hacs_repository, load_hacs_repository,
setup_frontend, setup_frontend,
@ -41,10 +42,18 @@ async def async_setup(hass, config):
return True return True
if hacs.configuration and hacs.configuration.config_type == "flow": if hacs.configuration and hacs.configuration.config_type == "flow":
return True return True
configuration = config[DOMAIN]
if configuration.get(FRONTEND_REPO) and configuration.get(FRONTEND_REPO_URL):
hacs.logger.critical("Could not setup HACS, set only one of ('frontend_repo', 'frontend_repo_url)")
return False
hass.data[DOMAIN] = config hass.data[DOMAIN] = config
hacs.hass = hass hacs.hass = hass
hacs.session = async_create_clientsession(hass) hacs.session = async_create_clientsession(hass)
hacs.configuration = Configuration.from_dict(config[DOMAIN]) hacs.configuration = Configuration.from_dict(configuration)
hacs.configuration.config = config hacs.configuration.config = config
hacs.configuration.config_type = "yaml" hacs.configuration.config_type = "yaml"
await startup_wrapper_for_yaml() await startup_wrapper_for_yaml()
@ -102,6 +111,7 @@ async def startup_wrapper_for_yaml():
async def hacs_startup(): async def hacs_startup():
"""HACS startup tasks.""" """HACS startup tasks."""
hacs = get_hacs() hacs = get_hacs()
if hacs.configuration.debug: if hacs.configuration.debug:
try: try:
await hacs.hass.services.async_call( await hacs.hass.services.async_call(
@ -125,6 +135,8 @@ async def hacs_startup():
hacs.system.config_path = hacs.hass.config.path() hacs.system.config_path = hacs.hass.config.path()
hacs.system.ha_version = HAVERSION hacs.system.ha_version = HAVERSION
await hacs.hass.async_add_executor_job(clear_storage)
hacs.system.lovelace_mode = lovelace_info.get("mode", "yaml") hacs.system.lovelace_mode = lovelace_info.get("mode", "yaml")
hacs.system.disabled = False hacs.system.disabled = False
hacs.github = GitHub( hacs.github = GitHub(

View File

@ -91,5 +91,7 @@ class HacsOptionsFlowHandler(config_entries.OptionsFlow):
schema = {vol.Optional("not_in_use", default=""): str} schema = {vol.Optional("not_in_use", default=""): str}
else: else:
schema = hacs_config_option_schema(self.config_entry.options) schema = hacs_config_option_schema(self.config_entry.options)
del schema["frontend_repo"]
del schema["frontend_repo_url"]
return self.async_show_form(step_id="user", data_schema=vol.Schema(schema)) return self.async_show_form(step_id="user", data_schema=vol.Schema(schema))

View File

@ -7,6 +7,8 @@ from .const import LOCALE
TOKEN = "token" TOKEN = "token"
SIDEPANEL_TITLE = "sidepanel_title" SIDEPANEL_TITLE = "sidepanel_title"
SIDEPANEL_ICON = "sidepanel_icon" SIDEPANEL_ICON = "sidepanel_icon"
FRONTEND_REPO = "frontend_repo"
FRONTEND_REPO_URL = "frontend_repo_url"
APPDAEMON = "appdaemon" APPDAEMON = "appdaemon"
NETDAEMON = "netdaemon" NETDAEMON = "netdaemon"
@ -40,6 +42,8 @@ def hacs_config_option_schema(options: dict = {}) -> dict:
RELEASE_LIMIT: 5, RELEASE_LIMIT: 5,
SIDEPANEL_ICON: "hacs:hacs", SIDEPANEL_ICON: "hacs:hacs",
SIDEPANEL_TITLE: "HACS", SIDEPANEL_TITLE: "HACS",
FRONTEND_REPO: "",
FRONTEND_REPO_URL: "",
} }
return { return {
vol.Optional(SIDEPANEL_TITLE, default=options.get(SIDEPANEL_TITLE)): str, vol.Optional(SIDEPANEL_TITLE, default=options.get(SIDEPANEL_TITLE)): str,
@ -50,6 +54,8 @@ def hacs_config_option_schema(options: dict = {}) -> dict:
vol.Optional(NETDAEMON, default=options.get(NETDAEMON)): bool, vol.Optional(NETDAEMON, default=options.get(NETDAEMON)): bool,
vol.Optional(DEBUG, default=options.get(DEBUG)): bool, vol.Optional(DEBUG, default=options.get(DEBUG)): bool,
vol.Optional(EXPERIMENTAL, default=options.get(EXPERIMENTAL)): bool, vol.Optional(EXPERIMENTAL, default=options.get(EXPERIMENTAL)): bool,
vol.Optional(FRONTEND_REPO, default=options.get(FRONTEND_REPO)): str,
vol.Optional(FRONTEND_REPO_URL, default=options.get(FRONTEND_REPO_URL)): str,
} }

View File

@ -1,7 +1,7 @@
"""Constants for HACS""" """Constants for HACS"""
NAME_LONG = "HACS (Home Assistant Community Store)" NAME_LONG = "HACS (Home Assistant Community Store)"
NAME_SHORT = "HACS" NAME_SHORT = "HACS"
VERSION = "1.0.3" VERSION = "1.1.0"
DOMAIN = "hacs" DOMAIN = "hacs"
PROJECT_URL = "https://github.com/hacs/integration/" PROJECT_URL = "https://github.com/hacs/integration/"
CUSTOM_UPDATER_LOCATIONS = [ CUSTOM_UPDATER_LOCATIONS = [

View File

@ -42,6 +42,7 @@ class HacsFrontend:
version_running = None version_running = None
version_available = None version_available = None
version_expected = None
update_pending = False update_pending = False

View File

@ -20,6 +20,8 @@ class Configuration:
dev: bool = False dev: bool = False
frontend_mode: str = "Grid" frontend_mode: str = "Grid"
frontend_compact: bool = False frontend_compact: bool = False
frontend_repo: str = ""
frontend_repo_url: str = ""
options: dict = {} options: dict = {}
onboarding_done: bool = False onboarding_done: bool = False
plugin_path: str = "www/community/" plugin_path: str = "www/community/"

View File

@ -1,6 +1,7 @@
"""Return repository information if any.""" """Return repository information if any."""
import json import json
from aiogithubapi import AIOGitHubAPIException, GitHub from aiogithubapi import AIOGitHubAPIException, GitHub
from custom_components.hacs.globals import get_hacs
from custom_components.hacs.handler.template import render_template from custom_components.hacs.handler.template import render_template
from custom_components.hacs.hacsbase.exceptions import HacsException from custom_components.hacs.hacsbase.exceptions import HacsException
@ -63,6 +64,28 @@ async def get_releases(repository, prerelease=False, returnlimit=5):
raise HacsException(exception) raise HacsException(exception)
def get_frontend_version():
"""get the frontend version from the manifest."""
manifest = read_hacs_manifest()
frontend = 0
for requirement in manifest.get("requirements", []):
if requirement.startswith("hacs_frontend"):
frontend = requirement.split("==")[1]
break
return frontend
def read_hacs_manifest():
"""Reads the HACS manifest file and returns the contents."""
hacs = get_hacs()
content = {}
with open(
f"{hacs.system.config_path}/custom_components/hacs/manifest.json"
) as manifest:
content = json.loads(manifest.read())
return content
async def get_integration_manifest(repository): async def get_integration_manifest(repository):
"""Return the integration manifest.""" """Return the integration manifest."""
if repository.data.content_in_root: if repository.data.content_in_root:

View File

@ -1,7 +1,6 @@
"""Install helper for repositories.""" """Install helper for repositories."""
import os import os
import tempfile import tempfile
from custom_components.hacs.globals import get_hacs
from custom_components.hacs.hacsbase.exceptions import HacsException from custom_components.hacs.hacsbase.exceptions import HacsException
from custom_components.hacs.hacsbase.backup import Backup, BackupNetDaemon from custom_components.hacs.hacsbase.backup import Backup, BackupNetDaemon
from custom_components.hacs.helpers.download import download_content from custom_components.hacs.helpers.download import download_content
@ -74,42 +73,6 @@ async def install_repository(repository):
else: else:
repository.data.installed_version = version repository.data.installed_version = version
await reload_after_install(repository)
installation_complete(repository)
async def reload_after_install(repository):
"""Reload action after installation success."""
if repository.data.category == "integration":
if repository.data.config_flow:
if repository.data.full_name != "hacs/integration":
await repository.reload_custom_components()
repository.pending_restart = True
elif repository.data.category == "theme":
try:
await repository.hacs.hass.services.async_call(
"frontend", "reload_themes", {}
)
except Exception: # pylint: disable=broad-except
pass
elif repository.data.category == "netdaemon":
try:
await repository.hacs.hass.services.async_call(
"hassio", "addon_restart", {"addon": "c6a2317c_netdaemon"}
)
except Exception: # pylint: disable=broad-except
pass
def installation_complete(repository):
"""Action to run when the installation is complete."""
hacs = get_hacs()
hacs.hass.bus.async_fire(
"hacs/repository",
{"id": 1337, "action": "install", "repository": repository.data.full_name},
)
def version_to_install(repository): def version_to_install(repository):
"""Determine which version to isntall.""" """Determine which version to isntall."""

View File

@ -5,7 +5,6 @@ from custom_components.hacs.hacsbase.exceptions import (
HacsException, HacsException,
HacsExpectedException, HacsExpectedException,
) )
from queueman import concurrent
# @concurrent(15, 5) # @concurrent(15, 5)
@ -27,7 +26,7 @@ async def register_repository(full_name, category, check=True, ref=None, action=
repository = RERPOSITORY_CLASSES[category](full_name) repository = RERPOSITORY_CLASSES[category](full_name)
if check: if check:
try: try:
await repository.registration(ref) await repository.async_registration(ref)
if hacs.system.status.new: if hacs.system.status.new:
repository.data.new = False repository.data.new = False
if repository.validate.errors: if repository.validate.errors:

View File

@ -7,6 +7,8 @@ from hacs_frontend import locate_gz, locate_debug_gz
from custom_components.hacs.globals import get_hacs from custom_components.hacs.globals import get_hacs
IGNORE = ["class-map.js.map"]
class HacsFrontend(HomeAssistantView): class HacsFrontend(HomeAssistantView):
"""Base View Class for HACS.""" """Base View Class for HACS."""
@ -24,15 +26,37 @@ async def get_file_response(requested_file):
"""Get file.""" """Get file."""
hacs = get_hacs() hacs = get_hacs()
if requested_file in IGNORE:
hacs.logger.debug(f"Ignoring request for {requested_file}")
return web.Response(status=200)
if requested_file.startswith("frontend-"): if requested_file.startswith("frontend-"):
if hacs.configuration.debug: if hacs.configuration.debug:
servefile = await hacs.hass.async_add_executor_job(locate_debug_gz) servefile = await hacs.hass.async_add_executor_job(locate_debug_gz)
hacs.logger.debug("Serving DEBUG frontend") hacs.logger.debug("Serving DEBUG frontend")
elif hacs.configuration.frontend_repo_url:
hacs.logger.debug("Serving REMOTE DEVELOPMENT frontend")
request = await hacs.session.get(f"{hacs.configuration.frontend_repo_url}/main.js")
if request.status == 200:
result = await request.read()
response = web.Response(body=result)
response.headers["Cache-Control"] = "no-store, max-age=0"
response.headers["Pragma"] = "no-store"
return response
elif hacs.configuration.frontend_repo:
hacs.logger.debug("Serving LOCAL DEVELOPMENT frontend")
servefile = f"{hacs.configuration.frontend_repo}/hacs_frontend/main.js"
else: else:
servefile = await hacs.hass.async_add_executor_job(locate_gz) servefile = await hacs.hass.async_add_executor_job(locate_gz)
if os.path.exists(servefile): if os.path.exists(servefile):
return web.FileResponse(servefile) response = web.FileResponse(servefile)
if hacs.configuration.frontend_repo:
response.headers["Cache-Control"] = "no-store, max-age=0"
response.headers["Pragma"] = "no-store"
return response
elif requested_file == "iconset.js": elif requested_file == "iconset.js":
return web.FileResponse( return web.FileResponse(
f"{hacs.system.config_path}/custom_components/hacs/iconset.js" f"{hacs.system.config_path}/custom_components/hacs/iconset.js"

View File

@ -8,13 +8,14 @@
"lovelace" "lovelace"
], ],
"documentation": "https://hacs.xyz/docs/configuration/start", "documentation": "https://hacs.xyz/docs/configuration/start",
"issue_tracker": "https://github.com/hacs/integration/issues",
"domain": "hacs", "domain": "hacs",
"name": "HACS", "name": "HACS",
"requirements": [ "requirements": [
"aiofiles==0.5.0", "aiofiles==0.5.0",
"aiogithubapi==1.0.4", "aiogithubapi==1.0.4",
"backoff==1.10.0", "backoff==1.10.0",
"hacs_frontend==202005242033", "hacs_frontend==202006071141",
"integrationhelper==0.2.2", "integrationhelper==0.2.2",
"semantic_version==2.8.5", "semantic_version==2.8.5",
"queueman==0.5" "queueman==0.5"

View File

@ -50,20 +50,6 @@ class HacsAppdaemon(HacsRepository):
self.logger.error(error) self.logger.error(error)
return self.validate.success return self.validate.success
async def registration(self, ref=None):
"""Registration."""
if ref is not None:
self.ref = ref
self.force_branch = True
if not await self.validate_repository():
return False
# Run common registration steps.
await self.common_registration()
# Set local path
self.content.path.local = self.localpath
async def update_repository(self, ignore_issues=False): async def update_repository(self, ignore_issues=False):
"""Update.""" """Update."""
await self.common_update(ignore_issues) await self.common_update(ignore_issues)

View File

@ -1,4 +1,5 @@
"""Class for integrations in HACS.""" """Class for integrations in HACS."""
# pylint: disable=attribute-defined-outside-init
from integrationhelper import Logger from integrationhelper import Logger
from homeassistant.loader import async_get_custom_components from homeassistant.loader import async_get_custom_components
@ -6,7 +7,6 @@ from homeassistant.loader import async_get_custom_components
from custom_components.hacs.hacsbase.exceptions import HacsException from custom_components.hacs.hacsbase.exceptions import HacsException
from custom_components.hacs.helpers.filters import get_first_directory_in_directory from custom_components.hacs.helpers.filters import get_first_directory_in_directory
from custom_components.hacs.helpers.information import get_integration_manifest from custom_components.hacs.helpers.information import get_integration_manifest
from custom_components.hacs.helpers.action import run_action_checks
from custom_components.hacs.repositories.repository import HacsRepository from custom_components.hacs.repositories.repository import HacsRepository
@ -27,6 +27,16 @@ class HacsIntegration(HacsRepository):
"""Return localpath.""" """Return localpath."""
return f"{self.hacs.system.config_path}/custom_components/{self.data.domain}" return f"{self.hacs.system.config_path}/custom_components/{self.data.domain}"
async def async_post_installation(self):
"""Run post installation steps."""
if self.data.config_flow:
if self.data.full_name != "hacs/integration":
await self.reload_custom_components()
if self.data.first_install:
self.pending_restart = False
return
self.pending_restart = True
async def validate_repository(self): async def validate_repository(self):
"""Validate.""" """Validate."""
await self.common_validate() await self.common_validate()
@ -50,9 +60,6 @@ class HacsIntegration(HacsRepository):
raise HacsException(exception) raise HacsException(exception)
self.logger.error(exception) self.logger.error(exception)
if self.hacs.action:
await run_action_checks(self)
# Handle potential errors # Handle potential errors
if self.validate.errors: if self.validate.errors:
for error in self.validate.errors: for error in self.validate.errors:
@ -60,20 +67,6 @@ class HacsIntegration(HacsRepository):
self.logger.error(error) self.logger.error(error)
return self.validate.success return self.validate.success
async def registration(self, ref=None):
"""Registration."""
if ref is not None:
self.ref = ref
self.force_branch = True
if not await self.validate_repository():
return False
# Run common registration steps.
await self.common_registration()
# Set local path
self.content.path.local = self.localpath
async def update_repository(self, ignore_issues=False): async def update_repository(self, ignore_issues=False):
"""Update.""" """Update."""
await self.common_update(ignore_issues) await self.common_update(ignore_issues)
@ -98,3 +91,4 @@ class HacsIntegration(HacsRepository):
self.logger.info("Reloading custom_component cache") self.logger.info("Reloading custom_component cache")
del self.hacs.hass.data["custom_components"] del self.hacs.hass.data["custom_components"]
await async_get_custom_components(self.hacs.hass) await async_get_custom_components(self.hacs.hass)
self.logger.info("Custom_component cache reloaded")

View File

@ -58,20 +58,6 @@ class HacsNetdaemon(HacsRepository):
self.logger.error(error) self.logger.error(error)
return self.validate.success return self.validate.success
async def registration(self, ref=None):
"""Registration."""
if ref is not None:
self.ref = ref
self.force_branch = True
if not await self.validate_repository():
return False
# Run common registration steps.
await self.common_registration()
# Set local path
self.content.path.local = self.localpath
async def update_repository(self, ignore_issues=False): async def update_repository(self, ignore_issues=False):
"""Update.""" """Update."""
await self.common_update(ignore_issues) await self.common_update(ignore_issues)
@ -89,3 +75,12 @@ class HacsNetdaemon(HacsRepository):
# Set local path # Set local path
self.content.path.local = self.localpath self.content.path.local = self.localpath
async def async_post_installation(self):
"""Run post installation steps."""
try:
await self.hacs.hass.services.async_call(
"hassio", "addon_restart", {"addon": "c6a2317c_netdaemon"}
)
except Exception: # pylint: disable=broad-except
pass

View File

@ -2,10 +2,9 @@
import json import json
from integrationhelper import Logger from integrationhelper import Logger
from .repository import HacsRepository from custom_components.hacs.hacsbase.exceptions import HacsException
from ..hacsbase.exceptions import HacsException
from custom_components.hacs.helpers.information import find_file_name from custom_components.hacs.helpers.information import find_file_name
from custom_components.hacs.repositories.repository import HacsRepository
class HacsPlugin(HacsRepository): class HacsPlugin(HacsRepository):
@ -18,11 +17,14 @@ class HacsPlugin(HacsRepository):
self.data.file_name = None self.data.file_name = None
self.data.category = "plugin" self.data.category = "plugin"
self.information.javascript_type = None self.information.javascript_type = None
self.content.path.local = ( self.content.path.local = self.localpath
f"{self.hacs.system.config_path}/www/community/{full_name.split('/')[-1]}"
)
self.logger = Logger(f"hacs.repository.{self.data.category}.{full_name}") self.logger = Logger(f"hacs.repository.{self.data.category}.{full_name}")
@property
def localpath(self):
"""Return localpath."""
return f"{self.hacs.system.config_path}/www/community/{self.data.full_name.split('/')[-1]}"
async def validate_repository(self): async def validate_repository(self):
"""Validate.""" """Validate."""
# Run common validation steps. # Run common validation steps.
@ -46,17 +48,6 @@ class HacsPlugin(HacsRepository):
self.logger.error(error) self.logger.error(error)
return self.validate.success return self.validate.success
async def registration(self, ref=None):
"""Registration."""
if ref is not None:
self.ref = ref
self.force_branch = True
if not await self.validate_repository():
return False
# Run common registration steps.
await self.common_registration()
async def update_repository(self, ignore_issues=False): async def update_repository(self, ignore_issues=False):
"""Update.""" """Update."""
await self.common_update(ignore_issues) await self.common_update(ignore_issues)
@ -65,7 +56,9 @@ class HacsPlugin(HacsRepository):
find_file_name(self) find_file_name(self)
if self.content.path.remote is None: if self.content.path.remote is None:
self.validate.errors.append("Repostitory structure not compliant") self.validate.errors.append(
f"Repostitory structure for {self.ref.replace('tags/','')} is not compliant"
)
if self.content.path.remote == "release": if self.content.path.remote == "release":
self.content.single = True self.content.single = True

View File

@ -17,10 +17,15 @@ class HacsPythonScript(HacsRepository):
self.data.full_name = full_name self.data.full_name = full_name
self.data.category = "python_script" self.data.category = "python_script"
self.content.path.remote = "python_scripts" self.content.path.remote = "python_scripts"
self.content.path.local = f"{self.hacs.system.config_path}/python_scripts" self.content.path.local = self.localpath
self.content.single = True self.content.single = True
self.logger = Logger(f"hacs.repository.{self.data.category}.{full_name}") self.logger = Logger(f"hacs.repository.{self.data.category}.{full_name}")
@property
def localpath(self):
"""Return localpath."""
return f"{self.hacs.system.config_path}/python_scripts"
async def validate_repository(self): async def validate_repository(self):
"""Validate.""" """Validate."""
# Run common validation steps. # Run common validation steps.
@ -49,17 +54,8 @@ class HacsPythonScript(HacsRepository):
self.logger.error(error) self.logger.error(error)
return self.validate.success return self.validate.success
async def registration(self, ref=None): async def async_post_registration(self):
"""Registration.""" """Registration."""
if ref is not None:
self.ref = ref
self.force_branch = True
if not await self.validate_repository():
return False
# Run common registration steps.
await self.common_registration()
# Set name # Set name
find_file_name(self) find_file_name(self)

View File

@ -15,3 +15,7 @@ class RemovedRepository:
for key in data: for key in data:
if key in self.__dict__: if key in self.__dict__:
setattr(self, key, data[key]) setattr(self, key, data[key])
def to_json(self):
"""Return a JSON representation of the data."""
return self.__dict__

View File

@ -9,9 +9,9 @@ from aiogithubapi import AIOGitHubAPIException
from .manifest import HacsManifest from .manifest import HacsManifest
from ..helpers.misc import get_repository_name from ..helpers.misc import get_repository_name
from ..handler.download import async_download_file, async_save_file from ..handler.download import async_download_file, async_save_file
from ..helpers.misc import version_left_higher_then_right from ..helpers.install import version_to_install
from ..helpers.install import install_repository, version_to_install
from custom_components.hacs.repositories.helpers import RepositoryHelpers
from custom_components.hacs.hacsbase.exceptions import HacsException from custom_components.hacs.hacsbase.exceptions import HacsException
from custom_components.hacs.store import async_remove_store from custom_components.hacs.store import async_remove_store
from custom_components.hacs.globals import get_hacs from custom_components.hacs.globals import get_hacs
@ -98,7 +98,7 @@ class RepositoryContent:
single = False single = False
class HacsRepository: class HacsRepository(RepositoryHelpers):
"""HacsRepository.""" """HacsRepository."""
def __init__(self): def __init__(self):
@ -122,49 +122,6 @@ class HacsRepository:
self.treefiles = [] self.treefiles = []
self.ref = None self.ref = None
@property
def pending_upgrade(self):
"""Return pending upgrade."""
if not self.can_install:
return False
if self.data.installed:
if self.data.selected_tag is not None:
if self.data.selected_tag == self.data.default_branch:
if self.data.installed_commit != self.data.last_commit:
return True
return False
if self.display_installed_version != self.display_available_version:
return True
return False
@property
def custom(self):
"""Return flag if the repository is custom."""
if self.data.full_name.split("/")[0] in ["custom-components", "custom-cards"]:
return False
if str(self.data.id) in [str(x) for x in self.hacs.common.default]:
return False
if self.data.full_name == "hacs/integration":
return False
return True
@property
def can_install(self):
"""Return bool if repository can be installed."""
target = None
if self.data.homeassistant is not None:
target = self.data.homeassistant
if self.data.homeassistant is not None:
target = self.data.homeassistant
if target is not None:
if self.data.releases:
if not version_left_higher_then_right(
self.hacs.system.ha_version, target
):
return False
return True
@property @property
def display_name(self): def display_name(self):
"""Return display name.""" """Return display name."""
@ -288,10 +245,6 @@ class HacsRepository:
# Update "info.md" # Update "info.md"
self.information.additional_info = await get_info_md_content(self) self.information.additional_info = await get_info_md_content(self)
async def install(self):
"""Common installation steps of the repository."""
await install_repository(self)
async def download_zip(self, validate): async def download_zip(self, validate):
"""Download ZIP archive from repository release.""" """Download ZIP archive from repository release."""
try: try:
@ -353,6 +306,8 @@ class HacsRepository:
json.loads(manifest.content) json.loads(manifest.content)
) )
self.data.update_data(json.loads(manifest.content)) self.data.update_data(json.loads(manifest.content))
if self.hacs.action:
self.logger.info(json.loads(manifest.content))
except (AIOGitHubAPIException, Exception) as exception: # Gotta Catch 'Em All except (AIOGitHubAPIException, Exception) as exception: # Gotta Catch 'Em All
if self.hacs.action: if self.hacs.action:
raise HacsException(f"hacs.json file is not valid ({exception}).") raise HacsException(f"hacs.json file is not valid ({exception}).")

View File

@ -14,10 +14,23 @@ class HacsTheme(HacsRepository):
self.data.full_name = full_name self.data.full_name = full_name
self.data.category = "theme" self.data.category = "theme"
self.content.path.remote = "themes" self.content.path.remote = "themes"
self.content.path.local = f"{self.hacs.system.config_path}/themes/" self.content.path.local = self.localpath
self.content.single = False self.content.single = False
self.logger = Logger(f"hacs.repository.{self.data.category}.{full_name}") self.logger = Logger(f"hacs.repository.{self.data.category}.{full_name}")
@property
def localpath(self):
"""Return localpath."""
return f"{self.hacs.system.config_path}/themes/{self.data.file_name.replace('.yaml', '')}"
async def async_post_installation(self):
"""Run post installation steps."""
try:
await self.hacs.hass.services.async_call("frontend", "reload_themes", {})
self.logger.info("Themes reloaded")
except Exception: # pylint: disable=broad-except
pass
async def validate_repository(self): async def validate_repository(self):
"""Validate.""" """Validate."""
# Run common validation steps. # Run common validation steps.
@ -44,20 +57,11 @@ class HacsTheme(HacsRepository):
self.logger.error(error) self.logger.error(error)
return self.validate.success return self.validate.success
async def registration(self, ref=None): async def async_post_registration(self):
"""Registration.""" """Registration."""
if ref is not None:
self.ref = ref
self.force_branch = True
if not await self.validate_repository():
return False
# Run common registration steps.
await self.common_registration()
# Set name # Set name
find_file_name(self) find_file_name(self)
self.content.path.local = f"{self.hacs.system.config_path}/themes/{self.data.file_name.replace('.yaml', '')}" self.content.path.local = self.localpath
async def update_repository(self, ignore_issues=False): async def update_repository(self, ignore_issues=False):
"""Update.""" """Update."""
@ -69,4 +73,4 @@ class HacsTheme(HacsRepository):
# Update name # Update name
find_file_name(self) find_file_name(self)
self.content.path.local = f"{self.hacs.system.config_path}/themes/{self.data.file_name.replace('.yaml', '')}" self.content.path.local = self.localpath

View File

@ -1,15 +1,30 @@
"""Setup functions for HACS.""" """Setup functions for HACS."""
# pylint: disable=bad-continuation # pylint: disable=bad-continuation
import os
from hacs_frontend.version import VERSION as FE_VERSION from hacs_frontend.version import VERSION as FE_VERSION
from homeassistant.helpers import discovery from homeassistant.helpers import discovery
from custom_components.hacs.hacsbase.exceptions import HacsException from custom_components.hacs.hacsbase.exceptions import HacsException
from custom_components.hacs.const import VERSION, DOMAIN from custom_components.hacs.const import VERSION, DOMAIN
from custom_components.hacs.globals import get_hacs from custom_components.hacs.globals import get_hacs
from custom_components.hacs.helpers.information import get_repository from custom_components.hacs.helpers.information import (
get_repository,
get_frontend_version,
)
from custom_components.hacs.helpers.register_repository import register_repository from custom_components.hacs.helpers.register_repository import register_repository
def clear_storage():
"""Clear old files from storage."""
hacs = get_hacs()
storagefiles = ["hacs"]
for s_f in storagefiles:
path = f"{hacs.system.config_path}/.storage/{s_f}"
if os.path.isfile(path):
hacs.logger.info(f"Cleaning up old storage file {path}")
os.remove(path)
async def load_hacs_repository(): async def load_hacs_repository():
"""Load HACS repositroy.""" """Load HACS repositroy."""
hacs = get_hacs() hacs = get_hacs()
@ -79,6 +94,9 @@ async def setup_frontend():
hacs.hass.http.register_view(HacsFrontend()) hacs.hass.http.register_view(HacsFrontend())
hacs.frontend.version_running = FE_VERSION hacs.frontend.version_running = FE_VERSION
hacs.frontend.version_expected = await hacs.hass.async_add_executor_job(
get_frontend_version
)
# Add to sidepanel # Add to sidepanel
custom_panel_config = { custom_panel_config = {

View File

@ -9,7 +9,7 @@ import homeassistant.helpers.config_validation as cv
from .hacsbase.exceptions import HacsException from .hacsbase.exceptions import HacsException
from .store import async_load_from_store, async_save_to_store from .store import async_load_from_store, async_save_to_store
from custom_components.hacs.globals import get_hacs from custom_components.hacs.globals import get_hacs, removed_repositories
from custom_components.hacs.helpers.register_repository import register_repository from custom_components.hacs.helpers.register_repository import register_repository
@ -22,6 +22,7 @@ async def setup_ws_api(hass):
websocket_api.async_register_command(hass, hacs_repository_data) websocket_api.async_register_command(hass, hacs_repository_data)
websocket_api.async_register_command(hass, check_local_path) websocket_api.async_register_command(hass, check_local_path)
websocket_api.async_register_command(hass, hacs_status) websocket_api.async_register_command(hass, hacs_status)
websocket_api.async_register_command(hass, hacs_removed)
websocket_api.async_register_command(hass, acknowledge_critical_repository) websocket_api.async_register_command(hass, acknowledge_critical_repository)
websocket_api.async_register_command(hass, get_critical_repositories) websocket_api.async_register_command(hass, get_critical_repositories)
@ -31,7 +32,7 @@ async def setup_ws_api(hass):
{ {
vol.Required("type"): "hacs/settings", vol.Required("type"): "hacs/settings",
vol.Optional("action"): cv.string, vol.Optional("action"): cv.string,
vol.Optional("category"): cv.string, vol.Optional("categories"): cv.ensure_list,
} }
) )
async def hacs_settings(hass, connection, msg): async def hacs_settings(hass, connection, msg):
@ -70,7 +71,7 @@ async def hacs_settings(hass, connection, msg):
elif action == "clear_new": elif action == "clear_new":
for repo in hacs.repositories: for repo in hacs.repositories:
if repo.data.new: if repo.data.new and repo.data.category in msg.get("categories", []):
hacs.logger.debug(f"Clearing new flag from '{repo.data.full_name}'") hacs.logger.debug(f"Clearing new flag from '{repo.data.full_name}'")
repo.data.new = False repo.data.new = False
else: else:
@ -92,6 +93,8 @@ async def hacs_config(hass, connection, msg):
content["frontend_compact"] = config.frontend_compact content["frontend_compact"] = config.frontend_compact
content["onboarding_done"] = config.onboarding_done content["onboarding_done"] = config.onboarding_done
content["version"] = hacs.version content["version"] = hacs.version
content["frontend_expected"] = hacs.frontend.version_expected
content["frontend_running"] = hacs.frontend.version_running
content["dev"] = config.dev content["dev"] = config.dev
content["debug"] = config.debug content["debug"] = config.debug
content["country"] = config.country content["country"] = config.country
@ -118,6 +121,16 @@ async def hacs_status(hass, connection, msg):
connection.send_message(websocket_api.result_message(msg["id"], content)) connection.send_message(websocket_api.result_message(msg["id"], content))
@websocket_api.async_response
@websocket_api.websocket_command({vol.Required("type"): "hacs/removed"})
async def hacs_removed(hass, connection, msg):
"""Get information about removed repositories."""
content = []
for repo in removed_repositories:
content.append(repo.to_json())
connection.send_message(websocket_api.result_message(msg["id"], content))
@websocket_api.async_response @websocket_api.async_response
@websocket_api.websocket_command({vol.Required("type"): "hacs/repositories"}) @websocket_api.websocket_command({vol.Required("type"): "hacs/repositories"})
async def hacs_repositories(hass, connection, msg): async def hacs_repositories(hass, connection, msg):
@ -201,6 +214,7 @@ async def hacs_repository(hass, connection, msg):
repository.status.updated_info = True repository.status.updated_info = True
elif action == "install": elif action == "install":
repository.data.new = False
was_installed = repository.data.installed was_installed = repository.data.installed
await repository.install() await repository.install()
if not was_installed: if not was_installed:
@ -210,6 +224,7 @@ async def hacs_repository(hass, connection, msg):
repository.data.new = False repository.data.new = False
elif action == "uninstall": elif action == "uninstall":
repository.data.new = False
await repository.uninstall() await repository.uninstall()
elif action == "hide": elif action == "hide":
@ -249,16 +264,15 @@ async def hacs_repository(hass, connection, msg):
await hacs.data.async_write() await hacs.data.async_write()
message = None message = None
except AIOGitHubAPIException as exception: except AIOGitHubAPIException as exception:
message = str(exception) message = exception
hass.bus.async_fire("hacs/error", {"message": str(exception)})
except AttributeError as exception: except AttributeError as exception:
message = f"Could not use repository with ID {repo_id} ({exception})" message = f"Could not use repository with ID {repo_id} ({exception})"
except Exception as exception: # pylint: disable=broad-except except Exception as exception: # pylint: disable=broad-except
message = str(exception) message = exception
if message is not None: if message is not None:
hacs.logger.error(message) hacs.logger.error(message)
hass.bus.async_fire("hacs/error", {"message": message}) hass.bus.async_fire("hacs/error", {"message": str(exception)})
repository.state = None repository.state = None
connection.send_message(websocket_api.result_message(msg["id"], {})) connection.send_message(websocket_api.result_message(msg["id"], {}))
@ -322,30 +336,43 @@ async def hacs_repository_data(hass, connection, msg):
return return
hacs.logger.debug(f"Running {action} for {repository.data.full_name}") hacs.logger.debug(f"Running {action} for {repository.data.full_name}")
try:
if action == "set_state":
repository.state = data
if action == "set_state": elif action == "set_version":
repository.state = data repository.data.selected_tag = data
await repository.update_repository()
elif action == "set_version": repository.state = None
repository.data.selected_tag = data
await repository.update_repository()
repository.state = None
elif action == "install": elif action == "install":
was_installed = repository.data.installed was_installed = repository.data.installed
repository.data.selected_tag = data repository.data.selected_tag = data
await repository.update_repository() await repository.update_repository()
await repository.install() await repository.install()
repository.state = None repository.state = None
if not was_installed: if not was_installed:
hass.bus.async_fire("hacs/reload", {"force": True}) hass.bus.async_fire("hacs/reload", {"force": True})
elif action == "add": elif action == "add":
repository.state = None repository.state = None
else: else:
repository.state = None repository.state = None
hacs.logger.error(f"WS action '{action}' is not valid") hacs.logger.error(f"WS action '{action}' is not valid")
message = None
except AIOGitHubAPIException as exception:
message = exception
except AttributeError as exception:
message = f"Could not use repository with ID {repo_id} ({exception})"
except Exception as exception: # pylint: disable=broad-except
message = exception
if message is not None:
hacs.logger.error(message)
hass.bus.async_fire("hacs/error", {"message": str(exception)})
await hacs.data.async_write() await hacs.data.async_write()
connection.send_message(websocket_api.result_message(msg["id"], {})) connection.send_message(websocket_api.result_message(msg["id"], {}))

View File

@ -0,0 +1,33 @@
#-------------------------------------------
# @CCOSTAN
# Original Repo : https://github.com/CCOSTAN/Home-AssistantConfig
# Alexa Media Sensor Support - Relies on Custom Component
#-------------------------------------------
sensor:
- platform: template
sensors:
last_alexa:
entity_id:
- media_player.bedroom
- media_player.carlos_2nd_echo
- media_player.front_room_flex
- media_player.justin_room
- media_player.kitchen
- media_player.living_room
- media_player.master_bathroom
- media_player.master_bedroom
- media_player.office
- media_player.paige_room
- media_player.tap
- media_player.upstairs
value_template: >
{{ states.media_player | selectattr('attributes.last_called','eq',True) | map(attribute='entity_id') | first }}
#-------------------------------------------
##############################################################################
### Automations - Detect when things are not right. Like any Good Watchdog.
##############################################################################
#automation:
#Tweets pushed out to twitter.