Compare commits

...

26 Commits
v1.2 ... v1.3

Author SHA1 Message Date
6b8892aee8 Update README.md
Added release notes for version 1.3.
2023-11-16 09:19:36 +00:00
fce353dc38 Apply automatic changes 2023-11-15 07:51:24 +00:00
647f92e9c6 2023-11-15 07:49:33 +00:00
c2bd0dfa40 Apply automatic changes 2023-11-14 23:18:35 +00:00
22f9fa6901 Rename resources-deu/corrections.xml to resources-deu/strings/corrections.xml 2023-11-14 23:09:59 +00:00
cf7be0bcd9 Create corrections.xml 2023-11-14 23:09:15 +00:00
6a2a70ba0b Merge pull request #8 from Someone0nEarth/correcting_german_translation 2023-11-14 23:05:59 +00:00
f58fe2d26d Apply automatic changes 2023-11-14 23:00:33 +00:00
812b601f86 Update translate.yml 2023-11-14 22:48:02 +00:00
b726b8b6ac Update translate.yml 2023-11-14 22:31:52 +00:00
abfddd22e2 Update translate.yml 2023-11-14 22:29:39 +00:00
5794d67058 Update translate.yml 2023-11-14 22:27:58 +00:00
a6b7c27bf8 Update translate.yml 2023-11-14 22:24:52 +00:00
c57d6c18cf Added French corrections to corrections.xml 2023-11-14 22:23:31 +00:00
ae346da3f2 Merge pull request #3 from Patrick44fr/patch-1 2023-11-14 22:16:08 +00:00
ff47e2c76c Merge branch 'main' into patch-1 2023-11-14 22:14:53 +00:00
f9efb7b9b8 Update translate.yml 2023-11-14 22:10:15 +00:00
f5e68da346 Merge pull request #6 from house-of-abbey/5-dont-overwrite-corrections-for-strings-xml 2023-11-14 22:09:14 +00:00
e05799bbbc Change to a seperate corrections file 2023-11-14 22:07:02 +00:00
34bead8b67 Merge pull request #7 from house-of-abbey/2-tap-or-toggle-dont-work-on-venu-2
Changes required for 2-tap-or-toggle-dont-work-on-venu-2
2023-11-14 21:32:30 +00:00
33bc12d779 Update HomeAssistantMenuItem.mc
Review comments. Vibrate on tap, visual confirmation on receipt of response.
2023-11-14 21:14:32 +00:00
28a2616021 Correct German translation 2023-11-14 19:14:22 +01:00
2ccd2bfbff Changes required for 2-tap-or-toggle-dont-work-on-venu-2
Made the 'service' field for taps mandatory.
This makes scripts work for both the emulator and real devices.
Provide a response for automations started with a tap, and now they can be used for both tap and toggle.
2023-11-14 08:35:38 +00:00
c57324f7ad Create translate.yml 2023-11-13 23:00:57 +00:00
3c7d9e8b41 Updated translate script to use corrected attr 2023-11-13 22:46:10 +00:00
ba8812a6ab Update strings.xml 2023-11-11 19:43:21 +01:00
15 changed files with 159 additions and 49 deletions

35
.github/workflows/translate.yml vendored Normal file
View File

@ -0,0 +1,35 @@
name: Translate
on:
workflow_dispatch:
push:
paths:
- "resources/strings/strings.xml"
- "translate.py"
- "resources-*/strings/corrections.xml"
jobs:
translate:
runs-on: ubuntu-latest
permissions:
# Give the default GITHUB_TOKEN write permission to commit and push the
# added or changed files to the repository.
contents: write
steps:
- uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v4.7.1
- run: |
pip install beautifulsoup4
pip install deep-translator
pip install lxml
- run: python translate.py
# Commit all changed files back to the repository
- uses: stefanzweifel/git-auto-commit-action@v5
with:
push_options: '--force'

View File

@ -2,10 +2,6 @@
"folders": [
{
"path": "."
},
{
"name": "abc",
"path": "../blah/abc"
}
],
"settings": {}

View File

@ -34,7 +34,8 @@ Example schema as shown in the images:
{
"entity": "script.food_on_table",
"name": "Food is Ready!",
"type": "tap"
"type": "tap",
"service" : "script.turn_on"
},
{
"entity": "light.bedside_light_switch",
@ -79,6 +80,12 @@ Example schema as shown in the images:
"name": "Garage Door Check",
"type": "toggle"
},
{
"entity": "automation.turn_off_usb_chargers",
"name": "Turn off USBs",
"type": "tap",
"service" : "automation.trigger"
},
{
"entity": "scene.tv_light",
"name": "TV Lights Scene",
@ -99,6 +106,18 @@ The example above illustrates how to configure:
* Service invocation, e.g. Scene setting, (tap)
* A sub-menu to open (tap)
The example JSON shows an example usage of each of these Home Assistance entity types. Presently, an automation is the only one that can be either a 'tap' or a 'toggle'.
| HA Type | Tap | Toggle |
|------------|:---:|:------:|
| Switch | N | Y |
| Light | N | Y |
| Automation | Y | Y |
| Script | Y | N |
| Scene | Y | N |
NB. All 'tap' items must specify a 'service' tag.
Possible future extensions might include specifying the alternative texts to use instead of "On" and "Off", e.g. "Locked" and "Unlocked" (but wouldn't having locks operated from your watch be a security concern ;-))
The [schema](https://raw.githubusercontent.com/house-of-abbey/GarminHomeAssistant/main/config.schema.json) is checked by using a URL directly back to this GitHub source repository, so you do not need to install that file. You can just copy & paste your entity names from the YAML configuration files used to configure Home Assistant. With a submenu, there's a difference between "title" and "name". The "name" goes on the menu item, and the "title" at the head of the submenu. If your dashboard definition fails to meet the schema, the application will simply drop items with the wrong field names without warning.
@ -150,3 +169,4 @@ When you change the JSON file defining your dashboard, you must exit the applica
| 1.0 | Initial release for 26 devices. |
| 1.1 | Updated for 54 more devices, 80 in total. Scene support. Added vibrate acknowledgement for tap-based menu items. Falls back to a custom visual confirmation in the absence of 'toast' and vibrate support. Bug fix for large menus needing status updates. |
| 1.2 | Do not crash on zero items to update. Report unreachable URLs. Verify API URL does not have a trailing slash '/'. Increased HTTP response diagnosis. Reduced minimum API Level required from 3.3.0 to 3.1.0 to allow more device "part numbers" to be satisfied. |
| 1.3 | Tap for scripts was working in emulation but not on some phones. Decision is to make the 'service' field in the JSON compulsory for 'tap' menu items. This is a breaking change, but for many might be a fix for something not working correctly. Improve language support, we can now accept language corrections and prevent the automated translation of strings from clobbering manually refined entries. Thank you to two new contributors. |

View File

@ -26,7 +26,7 @@
"type": { "const": "tap" },
"service": { "$ref": "#/$defs/entity" }
},
"required": ["entity", "name", "type"],
"required": ["entity", "name", "type", "service"],
"additionalProperties": false
},
"menu": {

View File

@ -25,7 +25,7 @@
<string id="MenuItemTap">Tryk på</string>
<string id="MenuItemMenu">Menu</string>
<string id="NoInternet">Ingen internetforbindelse</string>
<string id="NoMenu">Menuhentningsfejl</string>
<string id="NoMenu">Fejl ved menuhentning</string>
<string id="NoAPIKey">Ingen API-nøgle i applikationsindstillingerne</string>
<string id="NoApiUrl">Ingen API-URL i applikationsindstillingerne</string>
<string id="NoConfigUrl">Ingen konfigurations-URL i applikationsindstillingerne</string>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Distributed under MIT Licence
See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE.
GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely
tested on a Venu 2 device. The source code is provided at:
https://github.com/house-of-abbey/GarminHomeAssistant.
P A Abbey & J D Abbey, 14 November 2023
-->
<!--
Corrections for the German language
Korrekturen für die deutsche Sprache
-->
<strings>
<string id="MenuItemTap">Antippen</string>
<string id="MenuItemMenu">Menü</string>
<string id="UnhandledHttpErr">Die HTTP-Anfrage gab folgenden Fehlercode zurück = </string>
</strings>

View File

@ -22,8 +22,8 @@
<string id="AppName">HomeAssistant</string>
<string id="MenuItemOn">An</string>
<string id="MenuItemOff">Aus</string>
<string id="MenuItemTap">Klopfen</string>
<string id="MenuItemMenu">Speisekarte</string>
<string id="MenuItemTap">Antippen</string>
<string id="MenuItemMenu">Menü</string>
<string id="NoInternet">Keine Internetverbindung</string>
<string id="NoMenu">Fehler beim Abrufen des Menüs</string>
<string id="NoAPIKey">Kein API-Schlüssel in den Anwendungseinstellungen</string>
@ -32,6 +32,6 @@
<string id="ApiFlood">API-Aufrufe zu schnell. Bitte verlangsamen Sie Ihre Anfragen.</string>
<string id="ApiUrlNotFound">URL nicht gefunden. Möglicher API-URL-Fehler in den Einstellungen.</string>
<string id="ConfigUrlNotFound">URL nicht gefunden. Möglicher Konfigurations-URL-Fehler in den Einstellungen.</string>
<string id="UnhandledHttpErr">Die HTTP-Anfrage hat den Fehlercode = zurückgegeben</string>
<string id="UnhandledHttpErr">Die HTTP-Anfrage gab folgenden Fehlercode zurück = </string>
<string id="TrailingSlashErr">Die API-URL darf keinen abschließenden Schrägstrich „/“ enthalten.</string>
</strings>

View File

@ -15,7 +15,7 @@
<!--
Generated by Google Translate: English to Estonian
Loodud Google'i tõlke abil inglise keelest
Inglise keelest loodud Google'i tõlke abil
-->
<strings>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Distributed under MIT Licence
See https://github.com/house-of-abbey/GarminHomeAssistant/blob/main/LICENSE.
GarminHomeAssistant is a Garmin IQ application written in Monkey C and routinely
tested on a Venu 2 device. The source code is provided at:
https://github.com/house-of-abbey/GarminHomeAssistant.
P A Abbey & J D Abbey, 14 November 2023
-->
<!--
Corrections for the French language
Corrections pour la langue française
-->
<strings>
<string id="MenuItemOn">Activé</string>
<string id="MenuItemTap">Clic</string>
<string id="ApiFlood">Appels API trop rapide. Veuillez signaler cette erreur avec les détails de l'appareil.</string>
</strings>

View File

@ -20,16 +20,16 @@
<strings>
<string id="AppName">HomeAssistant</string>
<string id="MenuItemOn">Sur</string>
<string id="MenuItemOn">Activé</string>
<string id="MenuItemOff">Désactivé</string>
<string id="MenuItemTap">Robinet</string>
<string id="MenuItemTap">Clic</string>
<string id="MenuItemMenu">Menu</string>
<string id="NoInternet">Pas de connexion Internet</string>
<string id="NoMenu">Erreur de récupération du menu</string>
<string id="NoAPIKey">Pas de clé API dans les paramètres de l'application</string>
<string id="NoApiUrl">Aucune URL API dans les paramètres de l'application</string>
<string id="NoConfigUrl">Aucune URL de configuration dans les paramètres de l'application</string>
<string id="ApiFlood">Appels API trop rapides. Veuillez ralentir vos demandes.</string>
<string id="ApiFlood">Appels API trop rapide. Veuillez signaler cette erreur avec les détails de l'appareil.</string>
<string id="ApiUrlNotFound">URL introuvable. Erreur potentielle d'URL d'API dans les paramètres.</string>
<string id="ConfigUrlNotFound">URL introuvable. Erreur potentielle d'URL de configuration dans les paramètres.</string>
<string id="UnhandledHttpErr">La requête HTTP a renvoyé un code d'erreur =</string>

View File

@ -33,5 +33,5 @@
<string id="ApiUrlNotFound">URL을 찾을 수 없습니다. 설정에 잠재적인 API URL 오류가 있습니다.</string>
<string id="ConfigUrlNotFound">URL을 찾을 수 없습니다. 설정에 잠재적인 구성 URL 오류가 있습니다.</string>
<string id="UnhandledHttpErr">HTTP 요청이 오류 코드를 반환했습니다 =</string>
<string id="TrailingSlashErr">API URL에는 후행 슬래시 '/'가 있어서는 안 됩니다.</string>
<string id="TrailingSlashErr">API URL에는 후행 슬래시 '/'가 없어야 합니다.</string>
</strings>

View File

@ -33,5 +33,5 @@
<string id="ApiUrlNotFound">URL bulunamadı. Ayarlarda olası API URL hatası.</string>
<string id="ConfigUrlNotFound">URL bulunamadı. Ayarlarda Olası Yapılandırma URL'si hatası.</string>
<string id="UnhandledHttpErr">HTTP isteği hata kodunu döndürdü =</string>
<string id="TrailingSlashErr">API URL'sinin sonunda '/' eğik çizgi olmamalıdır</string>
<string id="TrailingSlashErr">API URL'sinin sonunda eğik çizgi '/' olmamalıdır</string>
</strings>

View File

@ -15,7 +15,7 @@
<!--
Generated by Google Translate: English to Ukrainian
Створено Google Translate з англійської
Згенеровано Google Translate з англійської
-->
<strings>

View File

@ -77,36 +77,27 @@ class HomeAssistantMenuItem extends WatchUi.MenuItem {
}
WatchUi.pushView(new ErrorView(strApiUrlNotFound), new ErrorDelegate(), WatchUi.SLIDE_UP);
} else if (responseCode == 200) {
var d = data as Lang.Array;
if (Globals.scDebug) {
System.println("HomeAssistantMenuItem onReturnExecScript(): Service executed.");
}
var d = data as Lang.Array;
var toast = "Executed";
for(var i = 0; i < d.size(); i++) {
if ((d[i].get("entity_id") as Lang.String).equals(mIdentifier)) {
if (Globals.scDebug) {
System.println("HomeAssistantMenuItem onReturnExecScript(): Correct script executed.");
}
if (WatchUi has :showToast) {
WatchUi.showToast(
(d[i].get("attributes") as Lang.Dictionary).get("friendly_name") as Lang.String,
null
);
}
if (Attention has :vibrate) {
Attention.vibrate([
new Attention.VibeProfile(50, 100), // On for 100ms
new Attention.VibeProfile( 0, 100), // Off for 100ms
new Attention.VibeProfile(50, 100) // On for 100ms
]);
}
if (!(WatchUi has :showToast) && !(Attention has :vibrate)) {
new Alert({
:timeout => Globals.scAlertTimeout,
:font => Graphics.FONT_MEDIUM,
:text => (d[i].get("attributes") as Lang.Dictionary).get("friendly_name") as Lang.String,
:fgcolor => Graphics.COLOR_WHITE,
:bgcolor => Graphics.COLOR_BLACK
}).pushView(WatchUi.SLIDE_IMMEDIATE);
}
toast = (d[i].get("attributes") as Lang.Dictionary).get("friendly_name") as Lang.String;
}
}
if (WatchUi has :showToast) {
WatchUi.showToast(toast, null);
} else {
new Alert({
:timeout => Globals.scAlertTimeout,
:font => Graphics.FONT_MEDIUM,
:text => toast,
:fgcolor => Graphics.COLOR_WHITE,
:bgcolor => Graphics.COLOR_BLACK
}).pushView(WatchUi.SLIDE_IMMEDIATE);
}
} else {
if (Globals.scDebug) {
System.println("HomeAssistantMenuItem onReturnExecScript(): Unhandled HTTP response code = " + responseCode);
@ -129,7 +120,7 @@ class HomeAssistantMenuItem extends WatchUi.MenuItem {
// ERROR: venu: Cannot find symbol ':substring' on type 'PolyType<Null or $.Toybox.Lang.Object>'.
var id = mIdentifier as Lang.String;
if (mService == null) {
var url = (Properties.getValue("api_url") as Lang.String) + "/services/" + id.substring(0, id.find(".")) + "/" + id.substring(id.find(".")+1, id.length());
var url = (Properties.getValue("api_url") as Lang.String) + "/services/" + id.substring(0, id.find(".")) + "/" + id.substring(id.find(".")+1, null);
if (Globals.scDebug) {
System.println("HomeAssistantMenuItem execScript() URL=" + url);
System.println("HomeAssistantMenuItem execScript() mIdentifier=" + mIdentifier);
@ -144,7 +135,7 @@ class HomeAssistantMenuItem extends WatchUi.MenuItem {
var url = (Properties.getValue("api_url") as Lang.String) + "/services/" + mService.substring(0, mService.find(".")) + "/" + mService.substring(mService.find(".")+1, null);
if (Globals.scDebug) {
System.println("HomeAssistantMenuItem execScript() URL=" + url);
System.println("HomeAssistantMenuItem execScript() mIdentifier=" + mIdentifier);
System.println("HomeAssistantMenuItem execScript() mService=" + mService);
}
Communications.makeWebRequest(
url,
@ -155,6 +146,13 @@ class HomeAssistantMenuItem extends WatchUi.MenuItem {
method(:onReturnExecScript)
);
}
if (Attention has :vibrate) {
Attention.vibrate([
new Attention.VibeProfile(50, 100), // On for 100ms
new Attention.VibeProfile( 0, 100), // Off for 100ms
new Attention.VibeProfile(50, 100) // On for 100ms
]);
}
} else {
if (Globals.scDebug) {
System.println("HomeAssistantMenuItem execScript(): No Internet connection, skipping API call.");

View File

@ -18,7 +18,7 @@
# language using Google Translate.
#
# Python installation:
# pip install BeautifulSoup
# pip install beautifulsoup4
# pip install deep-translator
# NB. For XML formatting:
# pip install lxml
@ -84,9 +84,15 @@ exceptionIds: list[str] = ["AppName", "AppVersionTitle"]
titleIds: list[str] = ["setMode", "tapIcon"]
i = 1
with open("./resources/strings/strings.xml") as f:
with open("./resources/strings/strings.xml", "r") as f:
c = f.read().replace('\r', '')
for l in languages:
os.makedirs(f"./resources-{l[0]}/strings/", exist_ok=True)
try:
with open(f"./resources-{l[0]}/strings/corrections.xml", "r") as r:
curr = BeautifulSoup(r.read().replace('\r', ''), features="xml")
except FileNotFoundError:
curr = BeautifulSoup("", features=["xml"])
print(f"{i} of {langLength}: Translating English to {l[2]}")
soup = BeautifulSoup(c, features="xml")
soup.find(name="strings").insert_before("\n\n")
@ -99,7 +105,12 @@ with open("./resources/strings/strings.xml") as f:
for s in soup.find(name="strings").findAll(name="string"):
s.insert_before(" ")
if s["id"] not in exceptionIds:
if s["id"] in exceptionIds: continue
s_curr = curr.find(name="string", attrs={ "id": s["id"] })
if s_curr:
s.string = s_curr.string
else:
a = GoogleTranslator(source='en', target=l[1]).translate(s.string)
if s["id"] in titleIds:
s.string = a.title()
@ -108,8 +119,8 @@ with open("./resources/strings/strings.xml") as f:
for s in soup.find(name="strings").findAll(text=lambda text:isinstance(text, Comment)):
s.insert_before(" ")
s.replace_with(Comment(" " + GoogleTranslator(source='en', target=l[1]).translate(s) + " "))
#print(str(soup))
os.makedirs(f"./resources-{l[0]}/strings/", exist_ok=True)
with open(f"./resources-{l[0]}/strings/strings.xml", "wb") as w:
w.write(soup.encode("utf-8"))
i += 1