From 5c804bd2809b15a6941d45395558c6949186703e Mon Sep 17 00:00:00 2001 From: dougiteixeira <31328123+dougiteixeira@users.noreply.github.com> Date: Sat, 25 Mar 2023 20:25:33 -0300 Subject: [PATCH 1/6] Add entity name translations --- custom_components/proxmoxve/binary_sensor.py | 3 + custom_components/proxmoxve/button.py | 11 +++ custom_components/proxmoxve/sensor.py | 23 +++++ custom_components/proxmoxve/strings.json | 92 +++++++++++++++++++- custom_components/proxmoxve/switch.py | 2 + 5 files changed, 130 insertions(+), 1 deletion(-) diff --git a/custom_components/proxmoxve/binary_sensor.py b/custom_components/proxmoxve/binary_sensor.py index 54004ec..b49dea3 100644 --- a/custom_components/proxmoxve/binary_sensor.py +++ b/custom_components/proxmoxve/binary_sensor.py @@ -36,6 +36,7 @@ class ProxmoxBinarySensorEntityDescription( name="Status", device_class=BinarySensorDeviceClass.RUNNING, on_value="online", + translation_key="status", ), ) @@ -45,6 +46,7 @@ class ProxmoxBinarySensorEntityDescription( name="Status", device_class=BinarySensorDeviceClass.RUNNING, on_value="running", + translation_key="status", ), ProxmoxBinarySensorEntityDescription( key=ProxmoxKeyAPIParse.HEALTH, @@ -53,6 +55,7 @@ class ProxmoxBinarySensorEntityDescription( on_value="running", inverted=True, api_category=ProxmoxType.QEMU, + translation_key="health", ), ) diff --git a/custom_components/proxmoxve/button.py b/custom_components/proxmoxve/button.py index e51e18f..1d15945 100644 --- a/custom_components/proxmoxve/button.py +++ b/custom_components/proxmoxve/button.py @@ -43,24 +43,28 @@ class ProxmoxButtonEntityDescription(ProxmoxEntityDescription, ButtonEntityDescr key=ProxmoxCommand.START_ALL, icon="mdi:play", name="Start All", + translation_key="start_all", entity_registry_enabled_default=False, ), ProxmoxButtonEntityDescription( key=ProxmoxCommand.STOP_ALL, icon="mdi:stop", name="Stop All", + translation_key="stop_all", entity_registry_enabled_default=False, ), ProxmoxButtonEntityDescription( key=ProxmoxCommand.SHUTDOWN, icon="mdi:server-off", name="Shutdown", + translation_key="shutdown", entity_registry_enabled_default=False, ), ProxmoxButtonEntityDescription( key=ProxmoxCommand.REBOOT, icon="mdi:restart", name="Reboot", + translation_key="reboot", entity_registry_enabled_default=False, ), ) @@ -70,42 +74,49 @@ class ProxmoxButtonEntityDescription(ProxmoxEntityDescription, ButtonEntityDescr key=ProxmoxCommand.REBOOT, icon="mdi:restart", name="Reboot", + translation_key="reboot", entity_registry_enabled_default=False, ), ProxmoxButtonEntityDescription( key=ProxmoxCommand.START, icon="mdi:server", name="Start", + translation_key="start", entity_registry_enabled_default=False, ), ProxmoxButtonEntityDescription( key=ProxmoxCommand.SHUTDOWN, icon="mdi:server-off", name="Shutdown", + translation_key="shutdown", entity_registry_enabled_default=False, ), ProxmoxButtonEntityDescription( key=ProxmoxCommand.STOP, icon="mdi:stop", name="Stop", + translation_key="stop", entity_registry_enabled_default=False, ), ProxmoxButtonEntityDescription( key=ProxmoxCommand.RESUME, icon="mdi:play", name="Resume", + translation_key="resume", entity_registry_enabled_default=False, ), ProxmoxButtonEntityDescription( key=ProxmoxCommand.SUSPEND, icon="mdi:pause", name="Suspend", + translation_key="suspend", entity_registry_enabled_default=False, ), ProxmoxButtonEntityDescription( key=ProxmoxCommand.RESET, icon="mdi:restart-alert", name="Reset", + translation_key="reset", entity_registry_enabled_default=False, ), ) diff --git a/custom_components/proxmoxve/sensor.py b/custom_components/proxmoxve/sensor.py index 76a6033..f57c2ba 100644 --- a/custom_components/proxmoxve/sensor.py +++ b/custom_components/proxmoxve/sensor.py @@ -53,6 +53,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr dt_util.utcnow() - timedelta(seconds=x) if x > 0 else None ), device_class=SensorDeviceClass.TIMESTAMP, + translation_key="uptime", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.CPU, @@ -62,6 +63,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr conversion_fn=lambda x: (x * 100) if x > 0 else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=1, + translation_key="cpu_used", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.MEMORY_USED, @@ -71,6 +73,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr conversion_fn=lambda x: (x / 1073741824), state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, + translation_key="memory_used", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.MEMORY_FREE, @@ -80,6 +83,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr conversion_fn=lambda x: (x / 1073741824), state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, + translation_key="memory_free", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.MEMORY_TOTAL, @@ -90,6 +94,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, entity_registry_enabled_default=False, + translation_key="memory_total", ), ProxmoxSensorEntityDescription( key="memory_free_perc", @@ -103,6 +108,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, + translation_key="memory_free_perc", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.SWAP_TOTAL, @@ -113,6 +119,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, entity_registry_enabled_default=False, + translation_key="swap_total", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.SWAP_FREE, @@ -123,6 +130,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, entity_registry_enabled_default=False, + translation_key="swap_free", ), ProxmoxSensorEntityDescription( key="swap_free_perc", @@ -136,6 +144,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, + translation_key="swap_free_perc", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.DISK_TOTAL, @@ -146,6 +155,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, entity_registry_enabled_default=False, + translation_key="disk_total", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.DISK_USED, @@ -156,6 +166,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, entity_registry_enabled_default=False, + translation_key="disk_used", ), ProxmoxSensorEntityDescription( key="disk_free_perc", @@ -169,6 +180,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=1, + translation_key="disk_free_perc", ), ) @@ -182,6 +194,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr dt_util.utcnow() - timedelta(seconds=x) if x > 0 else None ), device_class=SensorDeviceClass.TIMESTAMP, + translation_key="uptime", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.DISK_USED, @@ -192,6 +205,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, entity_registry_enabled_default=False, + translation_key="disk_used", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.DISK_TOTAL, @@ -202,6 +216,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, entity_registry_enabled_default=False, + translation_key="disk_total", ), ProxmoxSensorEntityDescription( key="disk_free_perc", @@ -215,6 +230,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=1, + translation_key="disk_free_perc", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.CPU, @@ -224,6 +240,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr conversion_fn=lambda x: (x * 100) if x > 0 else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=1, + translation_key="cpu_used", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.MEMORY_USED, @@ -233,6 +250,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr conversion_fn=lambda x: (x / 1073741824), state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, + translation_key="memory_used", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.MEMORY_FREE, @@ -242,6 +260,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr conversion_fn=lambda x: (x / 1073741824), state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, + translation_key="memory_free", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.MEMORY_TOTAL, @@ -252,6 +271,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, entity_registry_enabled_default=False, + translation_key="memory_total", ), ProxmoxSensorEntityDescription( key="memory_free_perc", @@ -265,6 +285,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=1, + translation_key="memory_free_perc", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.NETWORK_IN, @@ -275,6 +296,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, entity_registry_enabled_default=False, + translation_key="network_in", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.NETWORK_OUT, @@ -285,6 +307,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, entity_registry_enabled_default=False, + translation_key="network_out", ), ) diff --git a/custom_components/proxmoxve/strings.json b/custom_components/proxmoxve/strings.json index fa39187..6a4b8ae 100644 --- a/custom_components/proxmoxve/strings.json +++ b/custom_components/proxmoxve/strings.json @@ -133,5 +133,95 @@ "no_vms": "There are no virtual machines or containers for this node, the configuration entry will be created for the node.", "changes_successful": "Changes saved successfully." } - } + }, + "entity": { + "binary_sensor":{ + "status": { + "name": "Status" + }, + "health": { + "name": "Health" + } + }, + "button": { + "start_all": { + "name": "Start All" + }, + "stop_all": { + "name": "Stop All" + }, + "shutdown": { + "name": "Shutdown" + }, + "reboot": { + "name": "Reboot" + }, + "start": { + "name": "Start" + }, + "stop": { + "name": "Stop" + }, + "resume": { + "name": "Resume" + }, + "suspend": { + "name": "Suspend" + }, + "reset": { + "name": "Reset" + } + }, + "sensor": { + "uptime": { + "name": "Uptime" + }, + "cpu_used": { + "name": "CPU used" + }, + "memory_used": { + "name": "Memory used" + }, + "memory_free": { + "name": "Memory free" + }, + "memory_total": { + "name": "Memory total" + }, + "memory_free_perc": { + "name": "Memory free percentage" + }, + "swap_total": { + "name": "Swap total" + }, + "swap_free": { + "name": "Swap free" + }, + "swap_free_perc": { + "name": "Swap free percentage" + }, + "disk_total": { + "name": "Disk total" + }, + "disk_used": { + "name": "Disk used" + }, + "disk_free_perc": { + "name": "Disk free percentage" + }, + "network_in": { + "name": "Network in" + }, + "network_out": { + "name": "Network out" + } + }, + "switch": { + "start": { + "name": "Start" + }, + "stop": { + "name": "Stop" + } + } } diff --git a/custom_components/proxmoxve/switch.py b/custom_components/proxmoxve/switch.py index adfa07c..b65f961 100644 --- a/custom_components/proxmoxve/switch.py +++ b/custom_components/proxmoxve/switch.py @@ -47,6 +47,7 @@ class ProxmoxSwitchDescription(SwitchEntityDescription): name="Start", start_command=COMMAND_START, stop_command=COMMAND_SHUTDOWN, + translation_key="start", ), ProxmoxSwitchDescription( key="Switch_Stop", @@ -54,6 +55,7 @@ class ProxmoxSwitchDescription(SwitchEntityDescription): icon="mdi:server", start_command=COMMAND_START, stop_command=COMMAND_STOP, + translation_key="stop", ), ) From c7c7ecc27281d780a80e022988e7d0a160a4626e Mon Sep 17 00:00:00 2001 From: dougiteixeira <31328123+dougiteixeira@users.noreply.github.com> Date: Sat, 25 Mar 2023 20:49:02 -0300 Subject: [PATCH 2/6] Update strings.json --- custom_components/proxmoxve/strings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/custom_components/proxmoxve/strings.json b/custom_components/proxmoxve/strings.json index 6a4b8ae..1e7e83c 100644 --- a/custom_components/proxmoxve/strings.json +++ b/custom_components/proxmoxve/strings.json @@ -224,4 +224,5 @@ "name": "Stop" } } + } } From 43a27ba40f7c477e4123499e7f1f8cb863fc81f0 Mon Sep 17 00:00:00 2001 From: dougiteixeira <31328123+dougiteixeira@users.noreply.github.com> Date: Sat, 25 Mar 2023 20:54:25 -0300 Subject: [PATCH 3/6] Fixes --- custom_components/proxmoxve/button.py | 4 +- custom_components/proxmoxve/strings.json | 5 +- .../proxmoxve/translations/en.json | 99 ++++++++++++++++++- 3 files changed, 100 insertions(+), 8 deletions(-) diff --git a/custom_components/proxmoxve/button.py b/custom_components/proxmoxve/button.py index 1d15945..7e51039 100644 --- a/custom_components/proxmoxve/button.py +++ b/custom_components/proxmoxve/button.py @@ -42,14 +42,14 @@ class ProxmoxButtonEntityDescription(ProxmoxEntityDescription, ButtonEntityDescr ProxmoxButtonEntityDescription( key=ProxmoxCommand.START_ALL, icon="mdi:play", - name="Start All", + name="Start all", translation_key="start_all", entity_registry_enabled_default=False, ), ProxmoxButtonEntityDescription( key=ProxmoxCommand.STOP_ALL, icon="mdi:stop", - name="Stop All", + name="Stop all", translation_key="stop_all", entity_registry_enabled_default=False, ), diff --git a/custom_components/proxmoxve/strings.json b/custom_components/proxmoxve/strings.json index 6a4b8ae..07623df 100644 --- a/custom_components/proxmoxve/strings.json +++ b/custom_components/proxmoxve/strings.json @@ -145,10 +145,10 @@ }, "button": { "start_all": { - "name": "Start All" + "name": "Start all" }, "stop_all": { - "name": "Stop All" + "name": "Stop all" }, "shutdown": { "name": "Shutdown" @@ -224,4 +224,5 @@ "name": "Stop" } } + } } diff --git a/custom_components/proxmoxve/translations/en.json b/custom_components/proxmoxve/translations/en.json index bf26af5..c53f1d2 100644 --- a/custom_components/proxmoxve/translations/en.json +++ b/custom_components/proxmoxve/translations/en.json @@ -119,10 +119,10 @@ }, "interval_update": { "data": { - "interval_update_host": "Host (segundos)", - "interval_update_lxc": "Linux Containers (LXC) (segundos)", - "interval_update_node": "Node (segundos)", - "interval_update_qemu": "Virtual Machines (QEMU) (segundos)" + "interval_update_host": "Host (seconds)", + "interval_update_lxc": "Linux Containers (LXC) (seconds)", + "interval_update_node": "Node (seconds)", + "interval_update_qemu": "Virtual Machines (QEMU) (seconds)" }, "description": "Change the time (in seconds) for the information and sensors to update for each Proxmox resource:", "title": "Information update interval setting:" @@ -137,5 +137,96 @@ "title": "Selection of Virtual Machines (QEMU) and Containers (LXC):" } } + }, + "entity": { + "binary_sensor":{ + "status": { + "name": "Status" + }, + "health": { + "name": "Health" + } + }, + "button": { + "start_all": { + "name": "Start all" + }, + "stop_all": { + "name": "Stop all" + }, + "shutdown": { + "name": "Shutdown" + }, + "reboot": { + "name": "Reboot" + }, + "start": { + "name": "Start" + }, + "stop": { + "name": "Stop" + }, + "resume": { + "name": "Resume" + }, + "suspend": { + "name": "Suspend" + }, + "reset": { + "name": "Reset" + } + }, + "sensor": { + "uptime": { + "name": "Uptime" + }, + "cpu_used": { + "name": "CPU used" + }, + "memory_used": { + "name": "Memory used" + }, + "memory_free": { + "name": "Memory free" + }, + "memory_total": { + "name": "Memory total" + }, + "memory_free_perc": { + "name": "Memory free percentage" + }, + "swap_total": { + "name": "Swap total" + }, + "swap_free": { + "name": "Swap free" + }, + "swap_free_perc": { + "name": "Swap free percentage" + }, + "disk_total": { + "name": "Disk total" + }, + "disk_used": { + "name": "Disk used" + }, + "disk_free_perc": { + "name": "Disk free percentage" + }, + "network_in": { + "name": "Network in" + }, + "network_out": { + "name": "Network out" + } + }, + "switch": { + "start": { + "name": "Start" + }, + "stop": { + "name": "Stop" + } + } } } \ No newline at end of file From 3924b8f364db217cba8a796cde9e1346b2975d9e Mon Sep 17 00:00:00 2001 From: dougiteixeira <31328123+dougiteixeira@users.noreply.github.com> Date: Sun, 26 Mar 2023 19:53:35 -0300 Subject: [PATCH 4/6] Adds translation for new sensors and sorts strings --- custom_components/proxmoxve/sensor.py | 4 + custom_components/proxmoxve/strings.json | 52 +- .../proxmoxve/translations/en.json | 446 +++++++++--------- 3 files changed, 263 insertions(+), 239 deletions(-) diff --git a/custom_components/proxmoxve/sensor.py b/custom_components/proxmoxve/sensor.py index c0f7964..dcbd41b 100644 --- a/custom_components/proxmoxve/sensor.py +++ b/custom_components/proxmoxve/sensor.py @@ -67,6 +67,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=1, + translation_key="disk_free_perc", entity_registry_enabled_default=False, ), ProxmoxSensorEntityDescription( @@ -105,6 +106,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=1, + translation_key="disk_used_perc", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.MEMORY_FREE, @@ -285,6 +287,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=1, + translation_key="disk_used_perc", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.CPU, @@ -357,6 +360,7 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=1, + translation_key="memory_used_perc", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.NETWORK_IN, diff --git a/custom_components/proxmoxve/strings.json b/custom_components/proxmoxve/strings.json index 07623df..48e8b10 100644 --- a/custom_components/proxmoxve/strings.json +++ b/custom_components/proxmoxve/strings.json @@ -173,26 +173,41 @@ } }, "sensor": { - "uptime": { - "name": "Uptime" - }, "cpu_used": { "name": "CPU used" }, - "memory_used": { - "name": "Memory used" + "disk_free_perc": { + "name": "Disk free percentage" + }, + "disk_total": { + "name": "Disk total" + }, + "disk_used": { + "name": "Disk used" + }, + "disk_used_perc": { + "name": "Disk used percentage" }, "memory_free": { "name": "Memory free" }, + "memory_free_perc": { + "name": "Memory free percentage" + }, "memory_total": { "name": "Memory total" }, - "memory_free_perc": { - "name": "Memory free percentage" + "memory_used": { + "name": "Memory used" }, - "swap_total": { - "name": "Swap total" + "memory_used_perc": { + "name": "Memory used percentage" + }, + "network_in": { + "name": "Network in" + }, + "network_out": { + "name": "Network out" }, "swap_free": { "name": "Swap free" @@ -200,20 +215,17 @@ "swap_free_perc": { "name": "Swap free percentage" }, - "disk_total": { - "name": "Disk total" - }, - "disk_used": { - "name": "Disk used" + "swap_total": { + "name": "Swap total" }, - "disk_free_perc": { - "name": "Disk free percentage" + "swap_used": { + "name": "Swap used" }, - "network_in": { - "name": "Network in" + "swap_used_perc": { + "name": "Swap used percentage" }, - "network_out": { - "name": "Network out" + "uptime": { + "name": "Uptime" } }, "switch": { diff --git a/custom_components/proxmoxve/translations/en.json b/custom_components/proxmoxve/translations/en.json index c53f1d2..48e8b10 100644 --- a/custom_components/proxmoxve/translations/en.json +++ b/custom_components/proxmoxve/translations/en.json @@ -1,232 +1,240 @@ { - "config": { - "abort": { - "already_configured": "Device is already configured", - "no_nodes": "No nodes were returned for the host.", - "reauth_successful": "Re-authentication was successful" - }, - "error": { - "auth_error": "Invalid authentication", - "cant_connect": "Failed to connect", - "general_error": "Unexpected error", - "invalid_port": "Invalid port number", - "ssl_rejection": "Could not verify the SSL certificate" - }, - "step": { - "host": { - "data": { - "host": "Host", - "password": "Password", - "port": "Port", - "realm": "Realm", - "username": "Username", - "verify_ssl": "Verify SSL certificate" - }, - "description": "Please fill out the form and then press submit when you're ready", - "title": "Proxmox host information" - }, - "node": { - "data": { - "node": "Node:" - }, - "description": "Select the Proxmox instance nodes you want to expose:", - "title": "Proxmox node selection" - }, - "reauth_confirm": { - "data": { - "password": "Password", - "username": "Username" - }, - "description": "The username or password is invalid.", - "title": "Reauthenticate Integration" - }, - "selection_qemu_lxc": { - "data": { - "lxc": "Linux Containers (LXC)", - "node": "Node", - "qemu": "Virtual Machines (QEMU)" - }, - "description": "Select the virtual machines and containers to expose:", - "title": "Selection of Virtual Machines (QEMU) and Containers (LXC):" - } + "config": { + "step": { + "host": { + "title": "Proxmox host information", + "description": "Please fill out the form and then press submit when you're ready", + "data": { + "host": "[%key:common::config_flow::data::host%]", + "port": "[%key:common::config_flow::data::port%]", + "username": "[%key:common::config_flow::data::username%]", + "password": "[%key:common::config_flow::data::password%]", + "realm": "Realm", + "verify_ssl": "[%key:common::config_flow::data::verify_ssl%]" } - }, - "issues": { - "import_already_configured": { - "description": "The YAML configuration of the {node} of {host}:{port} instance of {integration} (`{platform}`) already exists in the UI and was ignored on import.\n\nYou must remove this configuration from your `configuration.yaml` file and restart Home Assistant.", - "title": "The node {node} of {host}:{port} already exists in the UI, can be removed" - }, - "import_auth_error": { - "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to authentication error.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually.", - "title": "Error in importing YAML configuration from {host}:{port}" - }, - "import_cant_connect": { - "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to connection failed.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually.", - "title": "Error in importing YAML configuration from {host}:{port}" - }, - "import_general_error": { - "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to unknown error.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually.", - "title": "Error in importing YAML configuration from {host}:{port}" - }, - "import_invalid_port": { - "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to invalid port.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually.", - "title": "Error in importing YAML configuration from {host}:{port}" - }, - "import_node_not_exist": { - "description": "The {node} of the {host}:{port} instance of {integration} (`{platform}`) present in the YAML configuration does not exist in this instance and was ignored in the import.\n\nYou must remove this configuration from your `configuration.yaml` file and restart Home Assistant.", - "title": "Node {node} does not exist in {host}:{port}" - }, - "import_ssl_rejection": { - "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to SSL rejection.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually.", - "title": "Error in importing YAML configuration from {host}:{port}" - }, - "import_success": { - "description": "The YAML configuration of node {node} of {host}:{port} instance of {integration} (`{platform}`) has been imported into the UI automatically.\n\nCan be safely removed from your `configuration.yaml` file.", - "title": "Node {node} of {host}:{port} was imported from YAML configuration" - }, - "yaml_deprecated": { - "description": "Configuration of the {integration} (`{platform}`) in YAML is deprecated and should be removed in 2022.12. Resolve the import issues and remove the YAML configuration from your `configuration.yaml` file.", - "title": "Configuration of the {integration} in YAML is deprecated" - }, - "vm_id_nonexistent": { - "description": "VM/container {vm_id} does not exist on node {node} ({host}:{port}), remove it in integration options.", - "title": "VM/container {vm_id} does not exist" + }, + "node": { + "title": "Proxmox node selection", + "description": "Select the Proxmox instance nodes you want to expose:", + "data": { + "node": "Node:" } - }, - "options": { - "abort": { - "changes_successful": "Changes saved successfully.", - "no_nodes": "No nodes were returned for the host.", - "no_vms": "There are no virtual machines or containers for this node, the configuration entry will be created for the node." - }, - "error": { - "auth_error": "Invalid authentication", - "cant_connect": "Failed to connect", - "general_error": "Unexpected error", - "invalid_port": "Invalid port number", - "ssl_rejection": "Could not verify the SSL certificate" - }, - "step": { - "host": { - "data": { - "password": "Password", - "realm": "Realm", - "username": "Username", - "verify_ssl": "Verify SSL certificate" - }, - "description": "Please fill out the form and then press submit when you're ready", - "title": "Proxmox VE host information" - }, - "interval_update": { - "data": { - "interval_update_host": "Host (seconds)", - "interval_update_lxc": "Linux Containers (LXC) (seconds)", - "interval_update_node": "Node (seconds)", - "interval_update_qemu": "Virtual Machines (QEMU) (seconds)" - }, - "description": "Change the time (in seconds) for the information and sensors to update for each Proxmox resource:", - "title": "Information update interval setting:" - }, - "selection_qemu_lxc": { - "data": { - "lxc": "Linux Containers (LXC)", - "node": "Node", - "qemu": "Virtual Machines (QEMU)" - }, - "description": "Select the virtual machines (QEMU) and containers (LXC) to expose:", - "title": "Selection of Virtual Machines (QEMU) and Containers (LXC):" - } + }, + "selection_qemu_lxc": { + "title": "Selection of Virtual Machines (QEMU) and Containers (LXC):", + "description": "Select the virtual machines and containers to expose:", + "data": { + "node": "Node", + "qemu": "Virtual Machines (QEMU)", + "lxc": "Linux Containers (LXC)" } + }, + "reauth_confirm": { + "description": "The username or password is invalid.", + "title": "[%key:common::config_flow::title::reauth%]", + "data": { + "username": "[%key:common::config_flow::data::username%]", + "password": "[%key:common::config_flow::data::password%]" + } + } + }, + "error": { + "auth_error": "[%key:common::config_flow::error::invalid_auth%]", + "ssl_rejection": "Could not verify the SSL certificate", + "cant_connect": "[%key:common::config_flow::error::cannot_connect%]", + "general_error": "[%key:common::config_flow::error::unknown%]", + "invalid_port": "Invalid port number" + }, + "abort": { + "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", + "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]", + "no_nodes": "No nodes were returned for the host." + } + }, + "issues": { + "import_success": { + "title": "Node {node} of {host}:{port} was imported from YAML configuration", + "description": "The YAML configuration of node {node} of {host}:{port} instance of {integration} (`{platform}`) has been imported into the UI automatically.\n\nCan be safely removed from your `configuration.yaml` file." + }, + "import_invalid_port": { + "title": "Error in importing YAML configuration from {host}:{port}", + "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to invalid port.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually." + }, + "import_auth_error": { + "title": "Error in importing YAML configuration from {host}:{port}", + "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to authentication error.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually." + }, + "import_ssl_rejection": { + "title": "Error in importing YAML configuration from {host}:{port}", + "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to SSL rejection.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually." + }, + "import_cant_connect": { + "title": "Error in importing YAML configuration from {host}:{port}", + "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to connection failed.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually." }, - "entity": { - "binary_sensor":{ - "status": { - "name": "Status" - }, - "health": { - "name": "Health" + "import_general_error": { + "title": "Error in importing YAML configuration from {host}:{port}", + "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to unknown error.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually." + }, + "import_already_configured": { + "title": "The node {node} of {host}:{port} already exists in the UI, can be removed", + "description": "The YAML configuration of the {node} of {host}:{port} instance of {integration} (`{platform}`) already exists in the UI and was ignored on import.\n\nYou must remove this configuration from your `configuration.yaml` file and restart Home Assistant." + }, + "import_node_not_exist": { + "title": "Node {node} does not exist in {host}:{port}", + "description": "The {node} of the {host}:{port} instance of {integration} (`{platform}`) present in the YAML configuration does not exist in this instance and was ignored in the import.\n\nYou must remove this configuration from your `configuration.yaml` file and restart Home Assistant." + }, + "yaml_deprecated": { + "title": "Configuration of the {integration} in YAML is deprecated", + "description": "Configuration of the {integration} (`{platform}`) in YAML is deprecated and should be removed in 2022.12. Resolve the import issues and remove the YAML configuration from your `configuration.yaml` file." + } + }, + "options": { + "step": { + "host": { + "title": "Proxmox VE host information", + "description": "[%key:component::proxmoxve::config::step::host::description%]", + "data": { + "username": "[%key:component::proxmoxve::config::step::host::data::username%]", + "password": "[%key:component::proxmoxve::config::step::host::data::password%]", + "realm": "[%key:component::proxmoxve::config::step::host::data::realm%]", + "verify_ssl": "[%key:component::proxmoxve::config::step::host::data::verify_ssl%]" } }, - "button": { - "start_all": { - "name": "Start all" - }, - "stop_all": { - "name": "Stop all" - }, - "shutdown": { - "name": "Shutdown" - }, - "reboot": { - "name": "Reboot" - }, - "start": { - "name": "Start" - }, - "stop": { - "name": "Stop" - }, - "resume": { - "name": "Resume" - }, - "suspend": { - "name": "Suspend" - }, - "reset": { - "name": "Reset" + "selection_qemu_lxc": { + "title": "Selection of Virtual Machines (QEMU) and Containers (LXC):", + "description": "Select the virtual machines (QEMU) and containers (LXC) to expose:", + "data": { + "node": "Node", + "qemu": "Virtual Machines (QEMU)", + "lxc": "Linux Containers (LXC)" } }, - "sensor": { - "uptime": { - "name": "Uptime" - }, - "cpu_used": { - "name": "CPU used" - }, - "memory_used": { - "name": "Memory used" - }, - "memory_free": { - "name": "Memory free" - }, - "memory_total": { - "name": "Memory total" - }, - "memory_free_perc": { - "name": "Memory free percentage" - }, - "swap_total": { - "name": "Swap total" - }, - "swap_free": { - "name": "Swap free" - }, - "swap_free_perc": { - "name": "Swap free percentage" - }, - "disk_total": { - "name": "Disk total" - }, - "disk_used": { - "name": "Disk used" - }, - "disk_free_perc": { - "name": "Disk free percentage" - }, - "network_in": { - "name": "Network in" - }, - "network_out": { - "name": "Network out" + "interval_update": { + "title": "Information update interval setting:", + "description": "Change the time (in seconds) for the information and sensors to update for each Proxmox resource:", + "data": { + "interval_update_host": "Host (segundos)", + "interval_update_node": "Node (segundos)", + "interval_update_qemu": "Virtual Machines (QEMU) (segundos)", + "interval_update_lxc": "Linux Containers (LXC) (segundos)" } + } + }, + "error": { + "auth_error": "[%key:component::proxmoxve::config::error::auth_error%]", + "ssl_rejection": "[%key:component::proxmoxve::config::error::ssl_rejection%]", + "cant_connect": "[%key:component::proxmoxve::config::error::cant_connect%]", + "general_error": "[%key:component::proxmoxve::config::error::general_error%]", + "invalid_port": "[%key:component::proxmoxve::config::error::invalid_port%]" + }, + "abort": { + "no_nodes": "No nodes were returned for the host.", + "no_vms": "There are no virtual machines or containers for this node, the configuration entry will be created for the node.", + "changes_successful": "Changes saved successfully." + } + }, + "entity": { + "binary_sensor":{ + "status": { + "name": "Status" }, - "switch": { - "start": { - "name": "Start" - }, - "stop": { - "name": "Stop" - } + "health": { + "name": "Health" + } + }, + "button": { + "start_all": { + "name": "Start all" + }, + "stop_all": { + "name": "Stop all" + }, + "shutdown": { + "name": "Shutdown" + }, + "reboot": { + "name": "Reboot" + }, + "start": { + "name": "Start" + }, + "stop": { + "name": "Stop" + }, + "resume": { + "name": "Resume" + }, + "suspend": { + "name": "Suspend" + }, + "reset": { + "name": "Reset" + } + }, + "sensor": { + "cpu_used": { + "name": "CPU used" + }, + "disk_free_perc": { + "name": "Disk free percentage" + }, + "disk_total": { + "name": "Disk total" + }, + "disk_used": { + "name": "Disk used" + }, + "disk_used_perc": { + "name": "Disk used percentage" + }, + "memory_free": { + "name": "Memory free" + }, + "memory_free_perc": { + "name": "Memory free percentage" + }, + "memory_total": { + "name": "Memory total" + }, + "memory_used": { + "name": "Memory used" + }, + "memory_used_perc": { + "name": "Memory used percentage" + }, + "network_in": { + "name": "Network in" + }, + "network_out": { + "name": "Network out" + }, + "swap_free": { + "name": "Swap free" + }, + "swap_free_perc": { + "name": "Swap free percentage" + }, + "swap_total": { + "name": "Swap total" + }, + "swap_used": { + "name": "Swap used" + }, + "swap_used_perc": { + "name": "Swap used percentage" + }, + "uptime": { + "name": "Uptime" + } + }, + "switch": { + "start": { + "name": "Start" + }, + "stop": { + "name": "Stop" } } -} \ No newline at end of file + } +} From aa708744d85c49e12180e780f147ed5ac4e23d20 Mon Sep 17 00:00:00 2001 From: dougiteixeira <31328123+dougiteixeira@users.noreply.github.com> Date: Thu, 20 Jul 2023 00:44:15 -0300 Subject: [PATCH 5/6] Fix translation_key --- custom_components/proxmoxve/button.py | 4 + custom_components/proxmoxve/sensor.py | 264 ++++++++--------------- custom_components/proxmoxve/strings.json | 14 +- custom_components/proxmoxve/switch.py | 247 --------------------- 4 files changed, 102 insertions(+), 427 deletions(-) delete mode 100644 custom_components/proxmoxve/switch.py diff --git a/custom_components/proxmoxve/button.py b/custom_components/proxmoxve/button.py index e52587e..6a87f5c 100644 --- a/custom_components/proxmoxve/button.py +++ b/custom_components/proxmoxve/button.py @@ -45,6 +45,7 @@ class ProxmoxButtonEntityDescription(ProxmoxEntityDescription, ButtonEntityDescr name="Start all", translation_key="start_all", entity_registry_enabled_default=False, + translation_key="start_all", ), ProxmoxButtonEntityDescription( key=ProxmoxCommand.STOP_ALL, @@ -52,6 +53,7 @@ class ProxmoxButtonEntityDescription(ProxmoxEntityDescription, ButtonEntityDescr name="Stop all", translation_key="stop_all", entity_registry_enabled_default=False, + translation_key="stop_all", ), ProxmoxButtonEntityDescription( key=ProxmoxCommand.SHUTDOWN, @@ -59,6 +61,7 @@ class ProxmoxButtonEntityDescription(ProxmoxEntityDescription, ButtonEntityDescr name="Shutdown", translation_key="shutdown", entity_registry_enabled_default=False, + translation_key="shutdown", ), ProxmoxButtonEntityDescription( key=ProxmoxCommand.REBOOT, @@ -66,6 +69,7 @@ class ProxmoxButtonEntityDescription(ProxmoxEntityDescription, ButtonEntityDescr name="Reboot", translation_key="reboot", entity_registry_enabled_default=False, + translation_key="reboot", ), ) diff --git a/custom_components/proxmoxve/sensor.py b/custom_components/proxmoxve/sensor.py index dcbd41b..7bc4c13 100644 --- a/custom_components/proxmoxve/sensor.py +++ b/custom_components/proxmoxve/sensor.py @@ -44,16 +44,19 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr api_category: ProxmoxType | None = None # Set when the sensor applies to only QEMU or LXC, if None applies to both. -PROXMOX_SENSOR_NODES: Final[tuple[ProxmoxSensorEntityDescription, ...]] = ( +PROXMOX_SENSOR_DISK: Final[tuple[ProxmoxSensorEntityDescription, ...]] = ( ProxmoxSensorEntityDescription( - key=ProxmoxKeyAPIParse.CPU, - name="CPU used", - icon="mdi:cpu-64-bit", - native_unit_of_measurement=PERCENTAGE, - conversion_fn=lambda x: (x * 100) if x > 0 else 0, + key="disk_free", + name="Disk free", + icon="mdi:harddisk", + native_unit_of_measurement=UnitOfInformation.BYTES, + value_fn=lambda x: (x.disk_total - x.disk_used), + device_class=SensorDeviceClass.DATA_SIZE, state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=1, - translation_key="cpu_used", + suggested_display_precision=2, + suggested_unit_of_measurement=UnitOfInformation.GIGABYTES, + entity_registry_enabled_default=False, + translation_key="disk_free", ), ProxmoxSensorEntityDescription( key="disk_free_perc", @@ -61,14 +64,11 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr icon="mdi:harddisk", native_unit_of_measurement=PERCENTAGE, conversion_fn=lambda x: (x * 100) if x > 0 else 0, - value_fn=lambda x: 1 - - x[ProxmoxKeyAPIParse.DISK_USED] / x[ProxmoxKeyAPIParse.DISK_TOTAL] - if x[ProxmoxKeyAPIParse.DISK_TOTAL] > 0 - else 0, + value_fn=lambda x: 1 - (x.disk_used / x.disk_total) if x.disk_total > 0 else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=1, - translation_key="disk_free_perc", entity_registry_enabled_default=False, + translation_key="disk_free_perc", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.DISK_TOTAL, @@ -79,8 +79,8 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, suggested_unit_of_measurement=UnitOfInformation.GIGABYTES, - translation_key="disk_total", entity_registry_enabled_default=False, + translation_key="disk_total", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.DISK_USED, @@ -91,8 +91,8 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, suggested_unit_of_measurement=UnitOfInformation.GIGABYTES, - translation_key="disk_used", entity_registry_enabled_default=False, + translation_key="disk_used", ), ProxmoxSensorEntityDescription( key="disk_used_perc", @@ -100,14 +100,13 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr icon="mdi:harddisk", native_unit_of_measurement=PERCENTAGE, conversion_fn=lambda x: (x * 100) if x > 0 else 0, - value_fn=lambda x: x[ProxmoxKeyAPIParse.DISK_USED] - / x[ProxmoxKeyAPIParse.DISK_TOTAL] - if x[ProxmoxKeyAPIParse.DISK_TOTAL] > 0 - else 0, + value_fn=lambda x: (x.disk_used / x.disk_total) if x.disk_total > 0 else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=1, translation_key="disk_used_perc", ), +) +PROXMOX_SENSOR_MEMORY: Final[tuple[ProxmoxSensorEntityDescription, ...]] = ( ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.MEMORY_FREE, name="Memory free", @@ -125,14 +124,13 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr icon="mdi:memory", native_unit_of_measurement=PERCENTAGE, conversion_fn=lambda x: (x * 100) if x > 0 else 0, - value_fn=lambda x: x[ProxmoxKeyAPIParse.MEMORY_FREE] - / x[ProxmoxKeyAPIParse.MEMORY_TOTAL] - if x[ProxmoxKeyAPIParse.MEMORY_TOTAL] > 0 + value_fn=lambda x: (x.memory_free / x.memory_total) + if x.memory_total > 0 else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, - translation_key="memory_free_perc", entity_registry_enabled_default=False, + translation_key="memory_free_perc", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.MEMORY_TOTAL, @@ -163,14 +161,15 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr icon="mdi:memory", native_unit_of_measurement=PERCENTAGE, conversion_fn=lambda x: (x * 100) if x > 0 else 0, - value_fn=lambda x: x[ProxmoxKeyAPIParse.MEMORY_USED] - / x[ProxmoxKeyAPIParse.MEMORY_TOTAL] - if x[ProxmoxKeyAPIParse.MEMORY_TOTAL] > 0 + value_fn=lambda x: (x.memory_used / x.memory_total) + if x.memory_total > 0 else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, translation_key="memory_used_perc", ), +) +PROXMOX_SENSOR_SWAP: Final[tuple[ProxmoxSensorEntityDescription, ...]] = ( ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.SWAP_FREE, name="Swap free", @@ -179,7 +178,8 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr device_class=SensorDeviceClass.DATA_SIZE, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, - suggested_unit_of_measurement=UnitOfInformation.GIGABYTES, + suggested_unit_of_measurement=UnitOfInformation.MEGABYTES, + entity_registry_enabled_default=False, translation_key="swap_free", ), ProxmoxSensorEntityDescription( @@ -188,14 +188,11 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr icon="mdi:memory", native_unit_of_measurement=PERCENTAGE, conversion_fn=lambda x: (x * 100) if x > 0 else 0, - value_fn=lambda x: x[ProxmoxKeyAPIParse.SWAP_FREE] - / x[ProxmoxKeyAPIParse.SWAP_TOTAL] - if x[ProxmoxKeyAPIParse.SWAP_TOTAL] > 0 - else 0, + value_fn=lambda x: (x.swap_free / x.swap_total) if x.swap_total > 0 else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, - translation_key="swap_free_perc", entity_registry_enabled_default=False, + translation_key="swap_free_perc", ), ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.SWAP_TOTAL, @@ -205,24 +202,36 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr device_class=SensorDeviceClass.DATA_SIZE, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, - suggested_unit_of_measurement=UnitOfInformation.GIGABYTES, + suggested_unit_of_measurement=UnitOfInformation.MEGABYTES, entity_registry_enabled_default=False, translation_key="swap_total", ), + ProxmoxSensorEntityDescription( + key=ProxmoxKeyAPIParse.SWAP_USED, + name="Swap used", + icon="mdi:memory", + native_unit_of_measurement=UnitOfInformation.BYTES, + device_class=SensorDeviceClass.DATA_SIZE, + state_class=SensorStateClass.MEASUREMENT, + suggested_display_precision=2, + suggested_unit_of_measurement=UnitOfInformation.MEGABYTES, + entity_registry_enabled_default=False, + translation_key="swap_used", + ), ProxmoxSensorEntityDescription( key="swap_used_perc", name="Swap used percentage", icon="mdi:memory", native_unit_of_measurement=PERCENTAGE, conversion_fn=lambda x: (x * 100) if x > 0 else 0, - value_fn=lambda x: 1 - - (x[ProxmoxKeyAPIParse.SWAP_FREE] / x[ProxmoxKeyAPIParse.SWAP_TOTAL]) - if x[ProxmoxKeyAPIParse.SWAP_TOTAL] > 0 - else 0, + value_fn=lambda x: (x.swap_used / x.swap_total) if x.swap_total > 0 else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, + entity_registry_enabled_default=False, translation_key="swap_used_perc", ), +) +PROXMOX_SENSOR_UPTIME: Final[tuple[ProxmoxSensorEntityDescription, ...]] = ( ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.UPTIME, name="Uptime", @@ -234,168 +243,79 @@ class ProxmoxSensorEntityDescription(ProxmoxEntityDescription, SensorEntityDescr translation_key="uptime", ), ) - - -PROXMOX_SENSOR_VM: Final[tuple[ProxmoxSensorEntityDescription, ...]] = ( - ProxmoxSensorEntityDescription( - key="disk_free_perc", - name="Disk free percentage", - icon="mdi:harddisk", - native_unit_of_measurement=PERCENTAGE, - conversion_fn=lambda x: (x * 100) if x > 0 else 0, - value_fn=lambda x: 1 - - x[ProxmoxKeyAPIParse.DISK_USED] / x[ProxmoxKeyAPIParse.DISK_TOTAL] - if x[ProxmoxKeyAPIParse.DISK_TOTAL] > 0 - else 0, - state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=1, - translation_key="disk_free_perc", - ), +PROXMOX_SENSOR_NETWORK: Final[tuple[ProxmoxSensorEntityDescription, ...]] = ( ProxmoxSensorEntityDescription( - key=ProxmoxKeyAPIParse.DISK_TOTAL, - name="Disk total", - icon="mdi:harddisk-plus", + key=ProxmoxKeyAPIParse.NETWORK_IN, + name="Network in", + icon="mdi:download-network-outline", native_unit_of_measurement=UnitOfInformation.BYTES, device_class=SensorDeviceClass.DATA_SIZE, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, - suggested_unit_of_measurement=UnitOfInformation.GIGABYTES, + suggested_unit_of_measurement=UnitOfInformation.MEGABYTES, entity_registry_enabled_default=False, - translation_key="disk_total", + translation_key="network_in", ), ProxmoxSensorEntityDescription( - key=ProxmoxKeyAPIParse.DISK_USED, - name="Disk used", - icon="mdi:harddisk", + key=ProxmoxKeyAPIParse.NETWORK_OUT, + name="Network out", + icon="mdi:upload-network-outline", native_unit_of_measurement=UnitOfInformation.BYTES, device_class=SensorDeviceClass.DATA_SIZE, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=2, - suggested_unit_of_measurement=UnitOfInformation.GIGABYTES, - translation_key="disk_used", + suggested_unit_of_measurement=UnitOfInformation.MEGABYTES, entity_registry_enabled_default=False, + translation_key="network_out", ), - ProxmoxSensorEntityDescription( - key="disk_used_perc", - name="Disk used percentage", - icon="mdi:harddisk", - native_unit_of_measurement=PERCENTAGE, - conversion_fn=lambda x: (x * 100) if x > 0 else 0, - value_fn=lambda x: x[ProxmoxKeyAPIParse.DISK_USED] - / x[ProxmoxKeyAPIParse.DISK_TOTAL] - if x[ProxmoxKeyAPIParse.DISK_TOTAL] > 0 - else 0, - state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=1, - translation_key="disk_used_perc", - ), +) +PROXMOX_SENSOR_CPU: Final[tuple[ProxmoxSensorEntityDescription, ...]] = ( ProxmoxSensorEntityDescription( key=ProxmoxKeyAPIParse.CPU, name="CPU used", icon="mdi:cpu-64-bit", native_unit_of_measurement=PERCENTAGE, - conversion_fn=lambda x: (x * 100) if x > 0 else 0, + conversion_fn=lambda x: (x * 100) if x >= 0 else 0, state_class=SensorStateClass.MEASUREMENT, suggested_display_precision=1, translation_key="cpu_used", ), +) + +PROXMOX_SENSOR_NODES: Final[tuple[ProxmoxSensorEntityDescription, ...]] = ( + *PROXMOX_SENSOR_CPU, + *PROXMOX_SENSOR_DISK, + *PROXMOX_SENSOR_MEMORY, + *PROXMOX_SENSOR_SWAP, + *PROXMOX_SENSOR_UPTIME, +) + +PROXMOX_SENSOR_QEMU: Final[tuple[ProxmoxSensorEntityDescription, ...]] = ( ProxmoxSensorEntityDescription( - key=ProxmoxKeyAPIParse.MEMORY_FREE, - name="Memory free", - icon="mdi:memory", - native_unit_of_measurement=UnitOfInformation.BYTES, - device_class=SensorDeviceClass.DATA_SIZE, - state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=2, - suggested_unit_of_measurement=UnitOfInformation.GIGABYTES, - translation_key="memory_free", - ), - ProxmoxSensorEntityDescription( - key="memory_free_perc", - name="Memory free percentage", - icon="mdi:memory", - native_unit_of_measurement=PERCENTAGE, - conversion_fn=lambda x: (x * 100) if x > 0 else 0, - value_fn=lambda x: x[ProxmoxKeyAPIParse.MEMORY_FREE] - / x[ProxmoxKeyAPIParse.MEMORY_TOTAL] - if x[ProxmoxKeyAPIParse.MEMORY_TOTAL] > 0 - else 0, - state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=1, - translation_key="memory_free_perc", - entity_registry_enabled_default=False, - ), - ProxmoxSensorEntityDescription( - key=ProxmoxKeyAPIParse.MEMORY_TOTAL, - name="Memory total", - icon="mdi:memory", - native_unit_of_measurement=UnitOfInformation.BYTES, - device_class=SensorDeviceClass.DATA_SIZE, - state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=2, - suggested_unit_of_measurement=UnitOfInformation.GIGABYTES, - entity_registry_enabled_default=False, - translation_key="memory_total", - ), - ProxmoxSensorEntityDescription( - key=ProxmoxKeyAPIParse.MEMORY_USED, - name="Memory used", - icon="mdi:memory", - native_unit_of_measurement=UnitOfInformation.BYTES, - device_class=SensorDeviceClass.DATA_SIZE, - state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=2, - suggested_unit_of_measurement=UnitOfInformation.GIGABYTES, - translation_key="memory_used", - ), - ProxmoxSensorEntityDescription( - key="memory_used_perc", - name="Memory used percentage", - icon="mdi:memory", - native_unit_of_measurement=PERCENTAGE, - conversion_fn=lambda x: (x * 100) if x > 0 else 0, - value_fn=lambda x: x[ProxmoxKeyAPIParse.MEMORY_USED] - / x[ProxmoxKeyAPIParse.MEMORY_TOTAL] - if x[ProxmoxKeyAPIParse.MEMORY_TOTAL] > 0 - else 0, - state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=1, - translation_key="memory_used_perc", - ), - ProxmoxSensorEntityDescription( - key=ProxmoxKeyAPIParse.NETWORK_IN, - name="Network in", - icon="mdi:download-network-outline", - native_unit_of_measurement=UnitOfInformation.BYTES, - device_class=SensorDeviceClass.DATA_SIZE, - state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=2, - suggested_unit_of_measurement=UnitOfInformation.MEGABYTES, - entity_registry_enabled_default=False, - translation_key="network_in", - ), - ProxmoxSensorEntityDescription( - key=ProxmoxKeyAPIParse.NETWORK_OUT, - name="Network out", - icon="mdi:upload-network-outline", - native_unit_of_measurement=UnitOfInformation.BYTES, - device_class=SensorDeviceClass.DATA_SIZE, - state_class=SensorStateClass.MEASUREMENT, - suggested_display_precision=2, - suggested_unit_of_measurement=UnitOfInformation.MEGABYTES, - entity_registry_enabled_default=False, - translation_key="network_out", + key="node", + name="Node", + icon="mdi:server", + translation_key="node", ), + *PROXMOX_SENSOR_CPU, + *PROXMOX_SENSOR_DISK, + *PROXMOX_SENSOR_MEMORY, + *PROXMOX_SENSOR_NETWORK, + *PROXMOX_SENSOR_UPTIME, +) + +PROXMOX_SENSOR_LXC: Final[tuple[ProxmoxSensorEntityDescription, ...]] = ( ProxmoxSensorEntityDescription( - key=ProxmoxKeyAPIParse.UPTIME, - name="Uptime", - icon="mdi:database-clock-outline", - conversion_fn=lambda x: ( - dt_util.utcnow() - timedelta(seconds=x) if x > 0 else None - ), - device_class=SensorDeviceClass.TIMESTAMP, - translation_key="uptime", + key="node", + name="Node", + icon="mdi:server", ), + *PROXMOX_SENSOR_CPU, + *PROXMOX_SENSOR_DISK, + *PROXMOX_SENSOR_MEMORY, + *PROXMOX_SENSOR_NETWORK, + *PROXMOX_SENSOR_SWAP, + *PROXMOX_SENSOR_UPTIME, ) diff --git a/custom_components/proxmoxve/strings.json b/custom_components/proxmoxve/strings.json index 48e8b10..70e31d1 100644 --- a/custom_components/proxmoxve/strings.json +++ b/custom_components/proxmoxve/strings.json @@ -176,6 +176,9 @@ "cpu_used": { "name": "CPU used" }, + "disk_free": { + "name": "Disk free" + }, "disk_free_perc": { "name": "Disk free percentage" }, @@ -209,6 +212,9 @@ "network_out": { "name": "Network out" }, + "node": { + "name": "Node" + }, "swap_free": { "name": "Swap free" }, @@ -227,14 +233,6 @@ "uptime": { "name": "Uptime" } - }, - "switch": { - "start": { - "name": "Start" - }, - "stop": { - "name": "Stop" - } } } } diff --git a/custom_components/proxmoxve/switch.py b/custom_components/proxmoxve/switch.py deleted file mode 100644 index b65f961..0000000 --- a/custom_components/proxmoxve/switch.py +++ /dev/null @@ -1,247 +0,0 @@ -"""Switch to set Proxmox VE data.""" -from __future__ import annotations - -from dataclasses import dataclass - -from typing import Any, Final - -from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription -from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_HOST, CONF_PORT -from homeassistant.core import HomeAssistant -from homeassistant.helpers.entity import DeviceInfo -from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator - - -from . import ProxmoxClient, ProxmoxEntity, call_api_post_status, device_info -from .const import ( - COMMAND_SHUTDOWN, - COMMAND_START, - COMMAND_STOP, - CONF_LXC, - CONF_NODE, - CONF_QEMU, - COORDINATORS, - DOMAIN, - PROXMOX_CLIENT, - LOGGER, - ProxmoxType, -) - - -@dataclass -class ProxmoxSwitchDescription(SwitchEntityDescription): - """Class describing Proxmox switch entities.""" - - unit_metric: str | None = None - unit_imperial: str | None = None - start_command: str | None = None - stop_command: str | None = None - - -PROXMOX_SWITCH_TYPES: Final[tuple[ProxmoxSwitchDescription, ...]] = ( - ProxmoxSwitchDescription( - key="Switch", - icon="mdi:server", - name="Start", - start_command=COMMAND_START, - stop_command=COMMAND_SHUTDOWN, - translation_key="start", - ), - ProxmoxSwitchDescription( - key="Switch_Stop", - name="Stop", - icon="mdi:server", - start_command=COMMAND_START, - stop_command=COMMAND_STOP, - translation_key="stop", - ), -) - - -async def async_setup_entry( - hass: HomeAssistant, - config_entry: ConfigEntry, - async_add_entities: AddEntitiesCallback, -) -> None: - """Set up sensor.""" - - switches = [] - - coordinators = hass.data[DOMAIN][config_entry.entry_id][COORDINATORS] - proxmox_client = hass.data[DOMAIN][config_entry.entry_id][PROXMOX_CLIENT] - - for vm_id in config_entry.data[CONF_QEMU]: - coordinator = coordinators[vm_id] - - # unfound vm case - if coordinator.data is None: - continue - - for description in PROXMOX_SWITCH_TYPES: - switches.append( - create_switch( - coordinator=coordinator, - info_device=device_info( - hass=hass, - config_entry=config_entry, - api_category=ProxmoxType.QEMU, - vm_id=vm_id, - ), - description=description, - vm_id=vm_id, - proxmox_client=proxmox_client, - machine_type=ProxmoxType.QEMU, - config_entry=config_entry, - ) - ) - - for ct_id in config_entry.data[CONF_LXC]: - coordinator = coordinators[ct_id] - - # unfound container case - if coordinator.data is None: - continue - - for description in PROXMOX_SWITCH_TYPES: - switches.append( - create_switch( - coordinator=coordinator, - info_device=device_info( - hass=hass, - config_entry=config_entry, - api_category=ProxmoxType.LXC, - vm_id=ct_id, - ), - description=description, - vm_id=ct_id, - proxmox_client=proxmox_client, - machine_type=ProxmoxType.LXC, - config_entry=config_entry, - ) - ) - - async_add_entities(switches) - - -def create_switch( - coordinator: DataUpdateCoordinator, - info_device: DeviceInfo, - description: ProxmoxSwitchDescription, - vm_id: str, - proxmox_client: ProxmoxClient, - machine_type: ProxmoxType, - config_entry, -): - """Create a switch based on the given data.""" - return ProxmoxBinarySwitch( - description=description, - proxmox_client=proxmox_client, - machine_type=machine_type, - coordinator=coordinator, - unique_id=f"proxmox_{config_entry.data[CONF_HOST]}_{config_entry.data[CONF_PORT]}_{config_entry.data[CONF_NODE]}_{vm_id}_{description.key}", - vm_id=vm_id, - info_device=info_device, - config_entry=config_entry, - name=description.name, - icon=description.icon, - ) - - -class ProxmoxBinarySwitch(ProxmoxEntity, SwitchEntity): - """A switch for reading/writing Proxmox VE status.""" - - _attr_has_entity_name = True - - def __init__( - self, - coordinator: DataUpdateCoordinator, - info_device: DeviceInfo, - description: ProxmoxSwitchDescription, - name: str, - unique_id: str, - proxmox_client: ProxmoxClient, - vm_id: str, - machine_type: ProxmoxType, - icon, - config_entry, - ) -> None: - """Create the switch for vms or containers.""" - super().__init__(coordinator, unique_id, name, icon, vm_id) - - self._attr_device_info = info_device - self.entity_description = description - self.entity_description = description - - def _turn_on_funct(): - """Post start command & tell HA state is on.""" - result = call_api_post_status( - proxmox_client.get_api_client(), - config_entry.data[CONF_NODE], - vm_id, - machine_type, - description.start_command, - ) - if result is not None and COMMAND_START in result: - # received success acknoledgement from API, set state optimistically to on - self._attr_is_on = True - self.async_write_ha_state() - # TODO - QOL improvement - depending on polling overlap, there is still a possibility for the switch - # to bounce if the server isn't fully on before the next polling cycle. Ideally need - # to skip the next polling cycle if there is one scheduled in the next ~10 seconds - LOGGER.debug( - "Swtich on: %s - %s - %s - %s", - config_entry.data[CONF_NODE], - vm_id, - machine_type, - description.start_command, - ) - - def _turn_off_funct(): - """Post shutdown command & tell HA state is off.""" - result = call_api_post_status( - proxmox_client.get_api_client(), - config_entry.data[CONF_NODE], - vm_id, - machine_type, - description.stop_command, - ) - if result is not None and COMMAND_SHUTDOWN in result: - # received success acknoledgement from API, set state optimistically to off - self._attr_is_on = False - self.async_write_ha_state() - # TODO - QOL improvement - depending on polling overlap, there is still a possibility for the switch - # to bounce if the server isn't fully off before the next polling cycle. Ideally need - # to skip the next polling cycle if there is one scheduled in the next ~10 seconds - LOGGER.debug( - "Swtich on: %s - %s - %s - %s", - config_entry.data[CONF_NODE], - vm_id, - machine_type, - description.stop_command, - ) - - self._turn_on_funct = _turn_on_funct - self._turn_off_funct = _turn_off_funct - - @property - def is_on(self): - """Return the switch.""" - if (data := self.coordinator.data) is None: - return None - - return data["status"] == "running" - - @property - def available(self): - """Return sensor availability.""" - return super().available and self.coordinator.data is not None - - def turn_on(self, **kwargs: Any) -> None: - """Turn the entity on.""" - self._turn_on_funct() - - def turn_off(self, **kwargs: Any) -> None: - """Turn the entity off.""" - self._turn_off_funct() From bd15fabc05c7299e35ce63b270220a44365341f6 Mon Sep 17 00:00:00 2001 From: dougiteixeira <31328123+dougiteixeira@users.noreply.github.com> Date: Thu, 20 Jul 2023 01:05:06 -0300 Subject: [PATCH 6/6] Fixes --- custom_components/proxmoxve/__init__.py | 12 +- custom_components/proxmoxve/button.py | 5 - custom_components/proxmoxve/config_flow.py | 2 +- custom_components/proxmoxve/coordinator.py | 4 +- custom_components/proxmoxve/entity.py | 2 + custom_components/proxmoxve/manifest.json | 2 +- custom_components/proxmoxve/model.py | 2 +- custom_components/proxmoxve/sensor.py | 8 +- custom_components/proxmoxve/strings.json | 12 +- .../proxmoxve/translations/en.json | 465 +++++++++--------- 10 files changed, 248 insertions(+), 266 deletions(-) diff --git a/custom_components/proxmoxve/__init__.py b/custom_components/proxmoxve/__init__.py index dc14781..1852c67 100644 --- a/custom_components/proxmoxve/__init__.py +++ b/custom_components/proxmoxve/__init__.py @@ -1,6 +1,8 @@ """Support for Proxmox VE.""" from __future__ import annotations + from typing import Any +import warnings from proxmoxer import AuthenticationError, ProxmoxAPI from proxmoxer.core import ResourceException @@ -10,10 +12,9 @@ RetryError, SSLError, ) +from urllib3.exceptions import InsecureRequestWarning import voluptuous as vol -import warnings - from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry from homeassistant.const import ( CONF_HOST, @@ -35,9 +36,6 @@ ) from homeassistant.helpers.typing import ConfigType - -from urllib3.exceptions import InsecureRequestWarning - from .const import ( CONF_CONTAINERS, CONF_LXC, @@ -176,11 +174,11 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry): device_identifiers.append( f"{config_entry.data[CONF_HOST]}_{config_entry.data[CONF_PORT]}_{config_entry.data.get(CONF_NODE)}" ) - for resource in config_entry.data.get(CONF_QEMU): + for resource in config_entry.data[CONF_QEMU]: device_identifiers.append( f"{config_entry.data[CONF_HOST]}_{config_entry.data[CONF_PORT]}_{config_entry.data.get(CONF_NODE)}_{resource}" ) - for resource in config_entry.data.get(CONF_LXC): + for resource in config_entry.data[CONF_LXC]: device_identifiers.append( f"{config_entry.data[CONF_HOST]}_{config_entry.data[CONF_PORT]}_{config_entry.data.get(CONF_NODE)}_{resource}" ) diff --git a/custom_components/proxmoxve/button.py b/custom_components/proxmoxve/button.py index 9dcb3d2..8fc9023 100644 --- a/custom_components/proxmoxve/button.py +++ b/custom_components/proxmoxve/button.py @@ -18,7 +18,6 @@ ) from .const import ( CONF_LXC, - CONF_NODE, CONF_NODES, CONF_QEMU, COORDINATORS, @@ -44,7 +43,6 @@ class ProxmoxButtonEntityDescription(ProxmoxEntityDescription, ButtonEntityDescr key=ProxmoxCommand.START_ALL, icon="mdi:play", name="Start all", - translation_key="start_all", entity_registry_enabled_default=False, translation_key="start_all", ), @@ -52,7 +50,6 @@ class ProxmoxButtonEntityDescription(ProxmoxEntityDescription, ButtonEntityDescr key=ProxmoxCommand.STOP_ALL, icon="mdi:stop", name="Stop all", - translation_key="stop_all", entity_registry_enabled_default=False, translation_key="stop_all", ), @@ -60,7 +57,6 @@ class ProxmoxButtonEntityDescription(ProxmoxEntityDescription, ButtonEntityDescr key=ProxmoxCommand.SHUTDOWN, icon="mdi:server-off", name="Shutdown", - translation_key="shutdown", entity_registry_enabled_default=False, translation_key="shutdown", ), @@ -68,7 +64,6 @@ class ProxmoxButtonEntityDescription(ProxmoxEntityDescription, ButtonEntityDescr key=ProxmoxCommand.REBOOT, icon="mdi:restart", name="Reboot", - translation_key="reboot", entity_registry_enabled_default=False, translation_key="reboot", ), diff --git a/custom_components/proxmoxve/config_flow.py b/custom_components/proxmoxve/config_flow.py index 322664e..2941722 100644 --- a/custom_components/proxmoxve/config_flow.py +++ b/custom_components/proxmoxve/config_flow.py @@ -774,7 +774,7 @@ async def async_step_expose( self._config[CONF_LXC].append(lxc_selection) return self.async_create_entry( - title=(f"{self._config[CONF_HOST]}:" f"{self._config[CONF_PORT]}"), + title=(f"{self._config[CONF_HOST]}:{self._config[CONF_PORT]}"), data=self._config, ) diff --git a/custom_components/proxmoxve/coordinator.py b/custom_components/proxmoxve/coordinator.py index 51d51a3..88fb451 100644 --- a/custom_components/proxmoxve/coordinator.py +++ b/custom_components/proxmoxve/coordinator.py @@ -9,7 +9,7 @@ from requests.exceptions import ConnectTimeout, SSLError from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_HOST, CONF_PORT, CONF_USERNAME +from homeassistant.const import CONF_HOST, CONF_USERNAME from homeassistant.core import HomeAssistant from homeassistant.helpers import device_registry as dr from homeassistant.helpers.issue_registry import ( @@ -21,7 +21,7 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import CONF_NODE, DOMAIN, LOGGER, UPDATE_INTERVAL, ProxmoxType -from .models import ProxmoxNodeData, ProxmoxVMData, ProxmoxLXCData +from .models import ProxmoxLXCData, ProxmoxNodeData, ProxmoxVMData class ProxmoxCoordinator( diff --git a/custom_components/proxmoxve/entity.py b/custom_components/proxmoxve/entity.py index 22f7a97..a6083fc 100644 --- a/custom_components/proxmoxve/entity.py +++ b/custom_components/proxmoxve/entity.py @@ -4,8 +4,10 @@ CoordinatorEntity, DataUpdateCoordinator, ) + from .models import ProxmoxEntityDescription + class ProxmoxEntity(CoordinatorEntity): """Represents any entity created for the Proxmox VE platform.""" diff --git a/custom_components/proxmoxve/manifest.json b/custom_components/proxmoxve/manifest.json index defbbfb..6f97aaf 100644 --- a/custom_components/proxmoxve/manifest.json +++ b/custom_components/proxmoxve/manifest.json @@ -8,5 +8,5 @@ "issue_tracker": "https://github.com/dougiteixeira/proxmoxve/issues", "loggers": ["proxmoxer"], "requirements": ["proxmoxer==2.0.1"], - "version": "2.0.0" + "version": "2.0.3" } diff --git a/custom_components/proxmoxve/model.py b/custom_components/proxmoxve/model.py index 1be1514..4b14dad 100644 --- a/custom_components/proxmoxve/model.py +++ b/custom_components/proxmoxve/model.py @@ -44,4 +44,4 @@ class ProxmoxButtonDescription(ButtonEntityDescription): unit_metric: str | None = None unit_imperial: str | None = None - button_command: str | None = None \ No newline at end of file + button_command: str | None = None diff --git a/custom_components/proxmoxve/sensor.py b/custom_components/proxmoxve/sensor.py index c5949d3..2704a77 100644 --- a/custom_components/proxmoxve/sensor.py +++ b/custom_components/proxmoxve/sensor.py @@ -28,7 +28,6 @@ CONF_QEMU, COORDINATORS, DOMAIN, - LOGGER, ProxmoxKeyAPIParse, ProxmoxType, ) @@ -441,11 +440,10 @@ def native_value(self) -> StateType: if not getattr(data, self.entity_description.key, False): if value := self.entity_description.value_fn: native_value = value(data) + elif self.entity_description.key is ProxmoxKeyAPIParse.CPU: + return 0 else: - if self.entity_description.key is ProxmoxKeyAPIParse.CPU: - return 0 - else: - return None + return None else: native_value = getattr(data, self.entity_description.key) diff --git a/custom_components/proxmoxve/strings.json b/custom_components/proxmoxve/strings.json index c9b984a..6220306 100644 --- a/custom_components/proxmoxve/strings.json +++ b/custom_components/proxmoxve/strings.json @@ -2,8 +2,7 @@ "config": { "step": { "host": { - "title": "Proxmox host information", - "description": "Please fill out the form and then press submit when you're ready", + "description": "Proxmox host information", "data": { "host": "[%key:common::config_flow::data::host%]", "port": "[%key:common::config_flow::data::port%]", @@ -14,8 +13,7 @@ } }, "expose": { - "title": "Select the Proxmox instance nodes ans Virtual Machines (QEMU) and Containers (LXC) you want to expose.", - "description": "Select the virtual machines and containers to expose:", + "description": "Select the Proxmox instance nodes ans Virtual Machines (QEMU) and Containers (LXC) you want to expose", "data": { "nodes": "Nodes", "qemu": "Virtual Machines (QEMU)", @@ -103,7 +101,6 @@ } }, "host_auth": { - "title": "[%key:component::proxmoxve::config::step::host::title%]", "description": "[%key:component::proxmoxve::config::step::host::description%]", "data": { "username": "[%key:component::proxmoxve::config::step::host::data::username%]", @@ -113,10 +110,9 @@ } }, "change_expose": { - "title": "[%key:component::proxmoxve::config::step::expose::title%]", "description": "[%key:component::proxmoxve::config::step::expose::description%]", "data": { - "nodes": "[%key:component::proxmoxve::config::step::expose::data::node%]", + "nodes": "[%key:component::proxmoxve::config::step::expose::data::nodes%]", "qemu": "[%key:component::proxmoxve::config::step::expose::data::qemu%]", "lxc": "[%key:component::proxmoxve::config::step::expose::data::lxc%]" } @@ -138,7 +134,7 @@ } }, "entity": { - "binary_sensor":{ + "binary_sensor": { "status": { "name": "Status" }, diff --git a/custom_components/proxmoxve/translations/en.json b/custom_components/proxmoxve/translations/en.json index a01865e..d2bf918 100644 --- a/custom_components/proxmoxve/translations/en.json +++ b/custom_components/proxmoxve/translations/en.json @@ -1,244 +1,237 @@ { - "config": { - "step": { - "host": { - "title": "Proxmox host information", - "description": "Please fill out the form and then press submit when you're ready", - "data": { - "host": "[%key:common::config_flow::data::host%]", - "port": "[%key:common::config_flow::data::port%]", - "username": "[%key:common::config_flow::data::username%]", - "password": "[%key:common::config_flow::data::password%]", - "realm": "Realm", - "verify_ssl": "[%key:common::config_flow::data::verify_ssl%]" + "config": { + "abort": { + "already_configured": "Device is already configured", + "no_resources": "No resources were returned for this instance.", + "reauth_successful": "Re-authentication was successful" + }, + "error": { + "auth_error": "Invalid authentication", + "cant_connect": "Failed to connect", + "general_error": "Unexpected error", + "invalid_port": "Invalid port number", + "ssl_rejection": "Could not verify the SSL certificate" + }, + "step": { + "expose": { + "data": { + "lxc": "Linux Containers (LXC)", + "nodes": "Nodes", + "qemu": "Virtual Machines (QEMU)" + }, + "description": "Select the Proxmox instance nodes ans Virtual Machines (QEMU) and Containers (LXC) you want to expose" + }, + "host": { + "data": { + "host": "Host", + "password": "Password", + "port": "Port", + "realm": "Realm", + "username": "Username", + "verify_ssl": "Verify SSL certificate" + }, + "description": "Proxmox host information" + }, + "reauth_confirm": { + "data": { + "password": "Password", + "username": "Username" + }, + "description": "The username or password is invalid.", + "title": "Reauthenticate Integration" + } } - }, - "expose": { - "title": "Select the Proxmox instance nodes ans Virtual Machines (QEMU) and Containers (LXC) you want to expose.", - "description": "Select the virtual machines and containers to expose:", - "data": { - "nodes": "Nodes", - "qemu": "Virtual Machines (QEMU)", - "lxc": "Linux Containers (LXC)" - } - }, - "reauth_confirm": { - "description": "The username or password is invalid.", - "title": "[%key:common::config_flow::title::reauth%]", - "data": { - "username": "[%key:common::config_flow::data::username%]", - "password": "[%key:common::config_flow::data::password%]" - } - } - }, - "error": { - "auth_error": "[%key:common::config_flow::error::invalid_auth%]", - "ssl_rejection": "Could not verify the SSL certificate", - "cant_connect": "[%key:common::config_flow::error::cannot_connect%]", - "general_error": "[%key:common::config_flow::error::unknown%]", - "invalid_port": "Invalid port number" - }, - "abort": { - "already_configured": "[%key:common::config_flow::abort::already_configured_device%]", - "reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]", - "no_resources": "No resources were returned for this instance." - } - }, - "issues": { - "import_success": { - "title": "{host}:{port} was imported from YAML configuration", - "description": "The YAML configuration of {host}:{port} instance of {integration} (`{platform}`) has been imported into the UI automatically.\n\nCan be safely removed from your `configuration.yaml` file." - }, - "import_invalid_port": { - "title": "Error in importing YAML configuration from {host}:{port}", - "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to invalid port.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually." - }, - "import_auth_error": { - "title": "Error in importing YAML configuration from {host}:{port}", - "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to authentication error.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually." - }, - "import_ssl_rejection": { - "title": "Error in importing YAML configuration from {host}:{port}", - "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to SSL rejection.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually." - }, - "import_cant_connect": { - "title": "Error in importing YAML configuration from {host}:{port}", - "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to connection failed.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually." - }, - "import_general_error": { - "title": "Error in importing YAML configuration from {host}:{port}", - "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to unknown error.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually." - }, - "import_already_configured": { - "title": "The instance {host}:{port} already exists in the UI, can be removed", - "description": "The YAML configuration of instace {host}:{port} of {integration} (`{platform}`) already exists in the UI and was ignored on import.\n\nYou must remove this configuration from your `configuration.yaml` file and restart Home Assistant." - }, - "import_node_not_exist": { - "title": "Node {node} does not exist in {host}:{port}", - "description": "The {node} of the {host}:{port} instance of {integration} (`{platform}`) present in the YAML configuration does not exist in this instance and was ignored in the import.\n\nYou must remove this configuration from your `configuration.yaml` file and restart Home Assistant." }, - "yaml_deprecated": { - "title": "Configuration of the {integration} in YAML is deprecated", - "description": "Configuration of the {integration} (`{platform}`) in YAML is deprecated and should be removed in {version}.\n\nResolve the import issues and remove the YAML configuration from your `configuration.yaml` file." - }, - "resource_nonexistent": { - "description": "{resource_type} {resource} does not exist on ({host}:{port}), remove it in integration options.\n\nThis can also be caused if the user doesn't have enough permission to access the resource.", - "title": "{resource_type} {resource} does not exist" - }, - "no_permissions": { - "description": "The user `{user}` does not have the required permissions for all features.\n\nThe following features are not accessible by the user:\n`{errors}`\n\nCheck the user permissions as described in the documentation.", - "title": "User `{user}` does not have the required permissions" - }, - "resource_exception_forbiden": { - "description": "User {user} does not have sufficient permissions to access resource {resource}.\n\nPlease check documentation and user permissions.", - "title": "Permissions error for `{resource}`" - } - }, - "options": { - "step": { - "menu": { - "menu_options": { - "host_auth": "Change host authentication information", - "change_expose": "Add or remove Nodes, VMs or Containers" - } - }, - "host_auth": { - "title": "[%key:component::proxmoxve::config::step::host::title%]", - "description": "[%key:component::proxmoxve::config::step::host::description%]", - "data": { - "username": "[%key:component::proxmoxve::config::step::host::data::username%]", - "password": "[%key:component::proxmoxve::config::step::host::data::password%]", - "realm": "[%key:component::proxmoxve::config::step::host::data::realm%]", - "verify_ssl": "[%key:component::proxmoxve::config::step::host::data::verify_ssl%]" - } - }, - "change_expose": { - "title": "[%key:component::proxmoxve::config::step::expose::title%]", - "description": "[%key:component::proxmoxve::config::step::expose::description%]", - "data": { - "nodes": "[%key:component::proxmoxve::config::step::expose::data::node%]", - "qemu": "[%key:component::proxmoxve::config::step::expose::data::qemu%]", - "lxc": "[%key:component::proxmoxve::config::step::expose::data::lxc%]" + "entity": { + "binary_sensor": { + "health": { + "name": "Health" + }, + "status": { + "name": "Status" + } + }, + "button": { + "reboot": { + "name": "Reboot" + }, + "reset": { + "name": "Reset" + }, + "resume": { + "name": "Resume" + }, + "shutdown": { + "name": "Shutdown" + }, + "start": { + "name": "Start" + }, + "start_all": { + "name": "Start all" + }, + "stop": { + "name": "Stop" + }, + "stop_all": { + "name": "Stop all" + }, + "suspend": { + "name": "Suspend" + } + }, + "sensor": { + "cpu_used": { + "name": "CPU used" + }, + "disk_free": { + "name": "Disk free" + }, + "disk_free_perc": { + "name": "Disk free percentage" + }, + "disk_total": { + "name": "Disk total" + }, + "disk_used": { + "name": "Disk used" + }, + "disk_used_perc": { + "name": "Disk used percentage" + }, + "memory_free": { + "name": "Memory free" + }, + "memory_free_perc": { + "name": "Memory free percentage" + }, + "memory_total": { + "name": "Memory total" + }, + "memory_used": { + "name": "Memory used" + }, + "memory_used_perc": { + "name": "Memory used percentage" + }, + "network_in": { + "name": "Network in" + }, + "network_out": { + "name": "Network out" + }, + "node": { + "name": "Node" + }, + "swap_free": { + "name": "Swap free" + }, + "swap_free_perc": { + "name": "Swap free percentage" + }, + "swap_total": { + "name": "Swap total" + }, + "swap_used": { + "name": "Swap used" + }, + "swap_used_perc": { + "name": "Swap used percentage" + }, + "uptime": { + "name": "Uptime" + } } - } }, - "error": { - "auth_error": "[%key:component::proxmoxve::config::error::auth_error%]", - "ssl_rejection": "[%key:component::proxmoxve::config::error::ssl_rejection%]", - "cant_connect": "[%key:component::proxmoxve::config::error::cant_connect%]", - "general_error": "[%key:component::proxmoxve::config::error::general_error%]", - "invalid_port": "[%key:component::proxmoxve::config::error::invalid_port%]" - }, - "abort": { - "no_nodes": "No nodes were returned for the host.", - "no_vms": "There are no virtual machines or containers for this node, the configuration entry will be created for the node.", - "changes_successful": "Changes saved successfully.", - "no_nodes_to_add": "No nodes to add.", - "node_already_exists": "The selected node already exists." - } - } - "entity": { - "binary_sensor":{ - "status": { - "name": "Status" - }, - "health": { - "name": "Health" - } - }, - "button": { - "start_all": { - "name": "Start all" - }, - "stop_all": { - "name": "Stop all" - }, - "shutdown": { - "name": "Shutdown" - }, - "reboot": { - "name": "Reboot" - }, - "start": { - "name": "Start" - }, - "stop": { - "name": "Stop" - }, - "resume": { - "name": "Resume" - }, - "suspend": { - "name": "Suspend" - }, - "reset": { - "name": "Reset" - } - }, - "sensor": { - "cpu_used": { - "name": "CPU used" - }, - "disk_free_perc": { - "name": "Disk free percentage" - }, - "disk_total": { - "name": "Disk total" - }, - "disk_used": { - "name": "Disk used" - }, - "disk_used_perc": { - "name": "Disk used percentage" - }, - "memory_free": { - "name": "Memory free" - }, - "memory_free_perc": { - "name": "Memory free percentage" - }, - "memory_total": { - "name": "Memory total" - }, - "memory_used": { - "name": "Memory used" - }, - "memory_used_perc": { - "name": "Memory used percentage" - }, - "network_in": { - "name": "Network in" - }, - "network_out": { - "name": "Network out" - }, - "swap_free": { - "name": "Swap free" - }, - "swap_free_perc": { - "name": "Swap free percentage" - }, - "swap_total": { - "name": "Swap total" - }, - "swap_used": { - "name": "Swap used" - }, - "swap_used_perc": { - "name": "Swap used percentage" - }, - "uptime": { - "name": "Uptime" - } + "issues": { + "import_already_configured": { + "description": "The YAML configuration of instace {host}:{port} of {integration} (`{platform}`) already exists in the UI and was ignored on import.\n\nYou must remove this configuration from your `configuration.yaml` file and restart Home Assistant.", + "title": "The instance {host}:{port} already exists in the UI, can be removed" + }, + "import_auth_error": { + "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to authentication error.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually.", + "title": "Error in importing YAML configuration from {host}:{port}" + }, + "import_cant_connect": { + "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to connection failed.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually.", + "title": "Error in importing YAML configuration from {host}:{port}" + }, + "import_general_error": { + "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to unknown error.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually.", + "title": "Error in importing YAML configuration from {host}:{port}" + }, + "import_invalid_port": { + "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to invalid port.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually.", + "title": "Error in importing YAML configuration from {host}:{port}" + }, + "import_node_not_exist": { + "description": "The {node} of the {host}:{port} instance of {integration} (`{platform}`) present in the YAML configuration does not exist in this instance and was ignored in the import.\n\nYou must remove this configuration from your `configuration.yaml` file and restart Home Assistant.", + "title": "Node {node} does not exist in {host}:{port}" + }, + "import_ssl_rejection": { + "description": "Importing YAML configuration from {host}:{port} instance of {integration} (`{platform}`) failed due to SSL rejection.\n\nYou must remove this configuration from your `configuration.yaml` file, restart Home Assistant and configure it manually.", + "title": "Error in importing YAML configuration from {host}:{port}" + }, + "import_success": { + "description": "The YAML configuration of {host}:{port} instance of {integration} (`{platform}`) has been imported into the UI automatically.\n\nCan be safely removed from your `configuration.yaml` file.", + "title": "{host}:{port} was imported from YAML configuration" + }, + "no_permissions": { + "description": "The user `{user}` does not have the required permissions for all features.\n\nThe following features are not accessible by the user:\n`{errors}`\n\nCheck the user permissions as described in the documentation.", + "title": "User `{user}` does not have the required permissions" + }, + "resource_exception_forbiden": { + "description": "User {user} does not have sufficient permissions to access resource {resource}.\n\nPlease check documentation and user permissions.", + "title": "Permissions error for `{resource}`" + }, + "resource_nonexistent": { + "description": "{resource_type} {resource} does not exist on ({host}:{port}), remove it in integration options.\n\nThis can also be caused if the user doesn't have enough permission to access the resource.", + "title": "{resource_type} {resource} does not exist" + }, + "yaml_deprecated": { + "description": "Configuration of the {integration} (`{platform}`) in YAML is deprecated and should be removed in {version}.\n\nResolve the import issues and remove the YAML configuration from your `configuration.yaml` file.", + "title": "Configuration of the {integration} in YAML is deprecated" + } }, - "switch": { - "start": { - "name": "Start" - }, - "stop": { - "name": "Stop" - } + "options": { + "abort": { + "changes_successful": "Changes saved successfully.", + "no_nodes": "No nodes were returned for the host.", + "no_nodes_to_add": "No nodes to add.", + "no_vms": "There are no virtual machines or containers for this node, the configuration entry will be created for the node.", + "node_already_exists": "The selected node already exists." + }, + "error": { + "auth_error": "Invalid authentication", + "cant_connect": "Failed to connect", + "general_error": "Unexpected error", + "invalid_port": "Invalid port number", + "ssl_rejection": "Could not verify the SSL certificate" + }, + "step": { + "change_expose": { + "data": { + "lxc": "Linux Containers (LXC)", + "nodes": "Nodes", + "qemu": "Virtual Machines (QEMU)" + }, + "description": "Select the Proxmox instance nodes ans Virtual Machines (QEMU) and Containers (LXC) you want to expose" + }, + "host_auth": { + "data": { + "password": "Password", + "realm": "Realm", + "username": "Username", + "verify_ssl": "Verify SSL certificate" + }, + "description": "Proxmox host information" + }, + "menu": { + "menu_options": { + "change_expose": "Add or remove Nodes, VMs or Containers", + "host_auth": "Change host authentication information" + } + } + } } - } -} } \ No newline at end of file