From bbb53e450ce0a156e6476d87d66497f1193ebea2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Tue, 9 Jul 2024 12:54:23 +0200
Subject: [PATCH 01/20] Update README.md
---
README.md | 1 +
1 file changed, 1 insertion(+)
diff --git a/README.md b/README.md
index b0ad866..9980cb6 100644
--- a/README.md
+++ b/README.md
@@ -51,6 +51,7 @@ There are probably many issues to list...
- There are (almost) no unit tests :(
- Logging is pretty much non-existent, documentation is a bit lacking
- ankerctl can crash sometimes, hindering the integration from working until it's restarted
+- Not sure if multiple printers on one ankerctl instance will work, I doubt it.
## Testing
From 128211ad55ef5951a3dd8406ff199e6d34e6534d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Tue, 9 Jul 2024 21:31:24 +0200
Subject: [PATCH 02/20] Add API status (not present in main branch of ankerctl
yet)
---
README.md | 7 +-
custom_components/ankermake/__init__.py | 6 +-
custom_components/ankermake/ankerctl_util.py | 16 ++++
.../ankermake/ankermake_mqtt_adapter.py | 22 ++++-
custom_components/ankermake/binary_sensor.py | 14 +++-
custom_components/ankermake/sensor.py | 9 ++-
.../ankermake/sensor_manifest.py | 80 ++++++++++++++++++-
7 files changed, 142 insertions(+), 12 deletions(-)
diff --git a/README.md b/README.md
index 9980cb6..7ce3071 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,8 @@ Home Assistant UI by searching for "AnkerMake" or click the button below.
[![Open your Home Assistant instance and start setting up a new integration.](https://my.home-assistant.io/badges/config_flow_start.svg)](https://my.home-assistant.io/redirect/config_flow_start/?domain=ankermake)
-> Note: You can add as many instances as you'd like (but you will need an ankerctl instance running for each one).
+> Note: You can add as many instances as you'd like (but you will need an ankerctl instance configured for each
+> printer).
## Dependencies
@@ -37,6 +38,9 @@ For this component to work, you will need an instance of [ankerctl](https://gith
running and working. Please refer to the ankerctl documentation for installation instructions. (They do have a Home
Assistant add-on in their organization, but I have not tested it with this component).
+(The branch of ankerctl I'm
+using: https://github.com/sondregronas/ankermake-m5-protocol/tree/patch-exiles-1.1-auto-restart-on-failure)
+
## Known issues
There are probably many issues to list...
@@ -51,7 +55,6 @@ There are probably many issues to list...
- There are (almost) no unit tests :(
- Logging is pretty much non-existent, documentation is a bit lacking
- ankerctl can crash sometimes, hindering the integration from working until it's restarted
-- Not sure if multiple printers on one ankerctl instance will work, I doubt it.
## Testing
diff --git a/custom_components/ankermake/__init__.py b/custom_components/ankermake/__init__.py
index 67cc45b..74f736e 100644
--- a/custom_components/ankermake/__init__.py
+++ b/custom_components/ankermake/__init__.py
@@ -23,6 +23,7 @@
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, CoordinatorEntity
from .anker_models import AnkerException
+from .ankerctl_util import get_api_status
from .ankermake_mqtt_adapter import AnkerData
from .const import DOMAIN, STARTUP, UPDATE_FREQUENCY_SECONDS
@@ -101,10 +102,13 @@ def on_message(message):
await session.close()
async def _async_update_data(self):
+ try:
+ self.ankerdata._api_status = await get_api_status(self.config['host'])
+ except AnkerException as e:
+ _LOGGER.debug(f"[AnkerMake] Error updating API data: {e}")
# Ensure task is still running
if self._listen_to_ws_task.done():
self._listen_to_ws_task = asyncio.create_task(self._listen_to_ws())
- await asyncio.sleep(5) # If the task dies, wait 5 seconds before trying again
class AnkerMakeBaseEntity(CoordinatorEntity[AnkerMakeUpdateCoordinator]):
diff --git a/custom_components/ankermake/ankerctl_util.py b/custom_components/ankermake/ankerctl_util.py
index 064193b..c3e87eb 100644
--- a/custom_components/ankermake/ankerctl_util.py
+++ b/custom_components/ankermake/ankerctl_util.py
@@ -72,3 +72,19 @@ async def reload_ankerctl(host: str):
raise AnkerUtilException(f"Failed to reload ankerctl: {response.status}")
except Exception as e:
raise AnkerUtilException(f"Failed to reload ankerctl: {e}")
+
+
+async def get_api_status(host: str):
+ """Gets the status of the ankerctl api."""
+ url = host.replace("ws://", "http://").replace("wss://", "https://")
+ try:
+ async with aiohttp.ClientSession() as session:
+ async with session.get(f"{url}/api/ankerctl/status") as response:
+ # TODO: Temporary if on the main branch of ankerctl
+ if response.status == 404:
+ raise AnkerUtilException("Ankerctl API not found (not present in ankerctl yet)")
+ if response.status != 200:
+ raise AnkerUtilException(f"Failed to get api status: {response.status}")
+ return await response.json()
+ except Exception as e:
+ raise AnkerUtilException(f"Failed to get api status: {e}")
diff --git a/custom_components/ankermake/ankermake_mqtt_adapter.py b/custom_components/ankermake/ankermake_mqtt_adapter.py
index e2a4a3c..4f32d44 100644
--- a/custom_components/ankermake/ankermake_mqtt_adapter.py
+++ b/custom_components/ankermake/ankermake_mqtt_adapter.py
@@ -28,7 +28,9 @@
@dataclass
class AnkerData:
- _timezone: datetime.tzinfo = None
+ _timezone: datetime.tzinfo = None # Defined in __init__.py
+ _api_status: dict = None # Updated via __init__.py
+
_last_heartbeat: datetime = None
_status: AnkerStatus = AnkerStatus.OFFLINE
_old_status: AnkerStatus = None
@@ -208,6 +210,24 @@ def _remove_error(self):
self.error_message = ""
self.error_level = ""
+ @property
+ def api_status(self) -> str:
+ return self._api_status.get('status', 'Offline').capitalize()
+
+ @staticmethod
+ def api_status_possible_states() -> list:
+ return ['Ok', 'Error', 'Offline']
+
+ @property
+ def api_service_possible_states(self) -> list:
+ return list(self._api_status.get('possible_states', {}).keys()) + ['Unavailable']
+
+ def get_api_service_status(self, service: str) -> str:
+ return self._api_status.get('services', {}).get(service, {}).get('state', 'Unavailable')
+
+ def get_api_service_online(self, service: str) -> bool:
+ return self._api_status.get('services', {}).get(service, {}).get('online', False)
+
def update(self, websocket_message: dict):
"""Update the AnkerData object with a new message from the AnkerMake printer."""
command_type = websocket_message.get("commandType")
diff --git a/custom_components/ankermake/binary_sensor.py b/custom_components/ankermake/binary_sensor.py
index 872570a..b7e36d1 100644
--- a/custom_components/ankermake/binary_sensor.py
+++ b/custom_components/ankermake/binary_sensor.py
@@ -36,16 +36,22 @@ def __init__(self, coordinator, description, dev_info, attrs):
self.attrs = attrs.copy()
self._attr_extra_state_attributes = dict()
+ def _filter_handler(self, key: str):
+ if key.startswith('%SVC_ONLINE='):
+ return self.coordinator.ankerdata.get_api_service_online(key.split('=')[1])
+ elif key.startswith('%SVC_STATE='):
+ return self.coordinator.ankerdata.get_api_service_status(key.split('=')[1])
+
+ return getattr(self.coordinator.ankerdata, key)
+
@callback
def _update_from_anker(self) -> None:
try:
- state = getattr(self.coordinator.ankerdata, self.attrs['state'])
- self._attr_is_on = state
-
for attr, key in self.attrs.items():
if attr == 'state':
+ self._attr_is_on = self._filter_handler(key)
continue
- self._attr_extra_state_attributes[attr] = getattr(self.coordinator.ankerdata, key)
+ self._attr_extra_state_attributes[attr] = self._filter_handler(key)
if not self.coordinator.ankerdata.online:
self._attr_available = True
diff --git a/custom_components/ankermake/sensor.py b/custom_components/ankermake/sensor.py
index 5aa983b..8dd9f0d 100644
--- a/custom_components/ankermake/sensor.py
+++ b/custom_components/ankermake/sensor.py
@@ -45,18 +45,21 @@ def td_convert(seconds):
def _filter_handler(self, key: str):
if key.startswith('%%TD='):
- val = getattr(self.coordinator.ankerdata, key[5:])
+ val = getattr(self.coordinator.ankerdata, key.split('=')[1])
return self.td_convert(val)
elif key.startswith('='):
return key[1:]
+ elif key.startswith('%SVC_ONLINE='):
+ return self.coordinator.ankerdata.get_api_service_online(key.split('=')[1])
+ elif key.startswith('%SVC_STATE='):
+ return self.coordinator.ankerdata.get_api_service_status(key.split('=')[1])
return getattr(self.coordinator.ankerdata, key)
@callback
def _update_from_anker(self) -> None:
try:
- state = getattr(self.coordinator.ankerdata, self.attrs['state'])
- self._attr_native_value = state
+ self._attr_native_value = self._filter_handler(self.attrs['state'])
for attr, key in self.attrs.items():
if attr == 'state':
diff --git a/custom_components/ankermake/sensor_manifest.py b/custom_components/ankermake/sensor_manifest.py
index 08ebf8e..e070deb 100644
--- a/custom_components/ankermake/sensor_manifest.py
+++ b/custom_components/ankermake/sensor_manifest.py
@@ -2,7 +2,7 @@
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
from homeassistant.components.sensor import SensorEntityDescription, SensorDeviceClass
-from .ankermake_mqtt_adapter import AnkerStatus, FilamentType
+from .ankermake_mqtt_adapter import AnkerStatus, FilamentType, AnkerData
# Linter is complaining without this class, it is strictly unnecessary
@@ -39,6 +39,62 @@ def __init__(self, *args, **kwargs):
'data_collection': 'ai_data_collection',
}
],
+ # Filetransfer service
+ [Description(
+ key="filetransfer_service",
+ name="Filetransfer Service",
+ icon="mdi:console",
+ device_class=BinarySensorDeviceClass.CONNECTIVITY,
+ entity_registry_enabled_default=False, # TODO: Enable this when API is in master
+ ),
+ {
+ 'state': '%SVC_ONLINE=filetransfer',
+ 'status': '%SVC_STATE=filetransfer',
+ 'possible_states': 'api_service_possible_states',
+ }
+ ],
+ # PPPPservice
+ [Description(
+ key="pppp_service",
+ name="PPPP Service",
+ icon="mdi:console",
+ device_class=BinarySensorDeviceClass.CONNECTIVITY,
+ entity_registry_enabled_default=False, # TODO: Enable this when API is in master
+ ),
+ {
+ 'state': '%SVC_ONLINE=pppp',
+ 'status': '%SVC_STATE=pppp',
+ 'possible_states': 'api_service_possible_states',
+ }
+ ],
+ # Videoqueue
+ [Description(
+ key="videoqueue_service",
+ name="Videoqueue Service",
+ icon="mdi:console",
+ device_class=BinarySensorDeviceClass.CONNECTIVITY,
+ entity_registry_enabled_default=False, # TODO: Enable this when API is in master
+ ),
+ {
+ 'state': '%SVC_ONLINE=videoqueue',
+ 'status': '%SVC_STATE=videoqueue',
+ 'possible_states': 'api_service_possible_states',
+ }
+ ],
+ # mqtt
+ [Description(
+ key="mqtt_service",
+ name="MQTT Service",
+ icon="mdi:console",
+ device_class=BinarySensorDeviceClass.CONNECTIVITY,
+ entity_registry_enabled_default=False, # TODO: Enable this when API is in master
+ ),
+ {
+ 'state': '%SVC_ONLINE=mqtt',
+ 'status': '%SVC_STATE=mqtt',
+ 'possible_states': 'api_service_possible_states',
+ }
+ ],
]
# Key must match the attribute in the AnkerData class
@@ -247,4 +303,26 @@ def __init__(self, *args, **kwargs):
'error_level': 'error_level',
}
],
+ # Ankerctl
+ [Description(
+ key="ankerctl",
+ name="Ankerctl",
+ icon="mdi:console",
+ entity_registry_enabled_default=False, # TODO: Enable this when API is in master
+ device_class='enum',
+ options=AnkerData.api_status_possible_states(),
+ ),
+ {
+ 'state': 'api_status',
+ 'pppp_service': '%SVC_STATE=pppp',
+ 'pppp_online': '%SVC_ONLINE=pppp',
+ 'filetransfer_service': '%SVC_STATE=filetransfer',
+ 'filetransfer_online': '%SVC_ONLINE=filetransfer',
+ 'videoqueue_service': '%SVC_STATE=videoqueue',
+ 'videoqueue_online': '%SVC_ONLINE=videoqueue',
+ 'mqtt_service': '%SVC_STATE=mqtt',
+ 'mqtt_online': '%SVC_ONLINE=mqtt',
+ 'possible_states': 'api_service_possible_states',
+ }
+ ],
]
From 661b28d7e14c12153ca3f60ac82a145945610ea5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Tue, 9 Jul 2024 22:27:16 +0200
Subject: [PATCH 03/20] Add camera instructions (WIP)
---
README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/README.md b/README.md
index 7ce3071..a62dc28 100644
--- a/README.md
+++ b/README.md
@@ -32,6 +32,55 @@ Home Assistant UI by searching for "AnkerMake" or click the button below.
> Note: You can add as many instances as you'd like (but you will need an ankerctl instance configured for each
> printer).
+## Adding a camera (WIP)
+
+
+
+Click to expand!
+
+> NOTE: This might not work for you YET! Also it isn't the most reliable feed. See PR/Draft in
+> ankerctl: [here](https://github.com/Ankermgmt/ankermake-m5-protocol/pull/162)
+
+## Using go2rtc
+
+`go2rtc.yaml` (https://github.com/AlexxIT/go2rtc?tab=readme-ov-file#go2rtc-home-assistant-add-on)
+
+```yaml
+streams:
+ Anker:
+ - ffmpeg:http://ankerctl-ip:4470/video
+```
+
+
+Alt: Frigate config
+
+Note: Frigate just runs go2rtc
+
+`config.yml`
+
+```yaml
+go2rtc:
+ streams:
+ Anker:
+ - "ffmpeg:http://ankerctl-ip:4470/video"
+```
+
+
+
+## Lovelace Card (Home Assistant)
+
+Add WebRTC integration from HACS (https://github.com/AlexxIT/WebRTC?tab=readme-ov-file#installation)
+
+Use either `http://:1984` or `http://:1984` when configuring the integration, reboot and add
+a `Custom: WebRTC Camera` card to the dashboard:
+
+```yaml
+type: custom:webrtc-camera
+url: Anker
+```
+
+
+
## Dependencies
For this component to work, you will need an instance of [ankerctl](https://github.com/Ankermgmt/ankermake-m5-protocol)
@@ -55,6 +104,7 @@ There are probably many issues to list...
- There are (almost) no unit tests :(
- Logging is pretty much non-existent, documentation is a bit lacking
- ankerctl can crash sometimes, hindering the integration from working until it's restarted
+- The API isn't added to ankerctl yet (showing the service statuses, etc)
## Testing
From bcbab2e1096da16e2377e2d1a88d99ea840de5b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:07:11 +0200
Subject: [PATCH 04/20] Add Placeholder image
---
.github/workflows/release.yml | 2 ++
custom_components/ankermake/anker_models.py | 1 +
.../ankermake/ankermake_mqtt_adapter.py | 5 +++++
.../ankermake/assets/placeholder_gcode.png | Bin 0 -> 5955 bytes
custom_components/ankermake/image.py | 4 ++++
5 files changed, 12 insertions(+)
create mode 100644 custom_components/ankermake/assets/placeholder_gcode.png
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a8f2d80..c711ba1 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -4,6 +4,8 @@ on:
release:
types:
- published
+ branches:
+ - main
permissions:
contents: write
diff --git a/custom_components/ankermake/anker_models.py b/custom_components/ankermake/anker_models.py
index eec00a6..a641379 100644
--- a/custom_components/ankermake/anker_models.py
+++ b/custom_components/ankermake/anker_models.py
@@ -63,6 +63,7 @@ class CommandTypes(Enum):
ZZ_MQTT_CMD_AI_INFO_CHECK = 1051 # Not used
ZZ_MQTT_CMD_MODEL_LAYER = 1052
TEMP_MAX_PRINT_SPEED = 1055 # max_print_speed: 500
+ TEMP_PRINT_STOPPED = 1068 # {'name': 'name', 'img': 'url', 'totalTime': 0, 'filamentUsed': 0, 'filamentUnit': 'mm', 'saveTime': 0, 'trigger': 2})
UNKNOWN_1081 = 1081 # Not used
UNKNOWN_1084 = 1084 # Not used
TEMP_IS_LEVELED = 1072 # isLeveled: 1
diff --git a/custom_components/ankermake/ankermake_mqtt_adapter.py b/custom_components/ankermake/ankermake_mqtt_adapter.py
index 4f32d44..f07ba36 100644
--- a/custom_components/ankermake/ankermake_mqtt_adapter.py
+++ b/custom_components/ankermake/ankermake_mqtt_adapter.py
@@ -315,6 +315,11 @@ def update(self, websocket_message: dict):
case CommandTypes.TEMP_IS_LEVELED.value:
self.bed_leveled = websocket_message.get("isLeveled") == 1
+ # When the STOP button is pressed, this message is sent
+ case CommandTypes.TEMP_PRINT_STOPPED.value:
+ # Resetting for now, which will set state to IDLE
+ self._reset()
+
# Errors (?)
case CommandTypes.TEMP_ERROR_CODE.value:
self.error_level = websocket_message.get("errorLevel")
diff --git a/custom_components/ankermake/assets/placeholder_gcode.png b/custom_components/ankermake/assets/placeholder_gcode.png
new file mode 100644
index 0000000000000000000000000000000000000000..be3a5c71916c539891f40aa436e7fadf37dc82f8
GIT binary patch
literal 5955
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 None:
@@ -34,6 +36,8 @@ def _update_from_anker(self) -> None:
async def async_image(self) -> bytes | None:
"""Return image bytes."""
+ if not self._gcode_preview_url:
+ return await self.hass.async_add_executor_job(lambda: open(self._placeholder_path, 'rb').read())
async with aiohttp.ClientSession() as session:
async with session.get(self._gcode_preview_url) as response:
return await response.read()
From d95adeca48a220e4c17e64e36dbe3fbcc7d9b7d1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:07:38 +0200
Subject: [PATCH 05/20] Create release-dev.yml
---
.github/workflows/release-dev.yml | 43 +++++++++++++++++++++++++++++++
1 file changed, 43 insertions(+)
create mode 100644 .github/workflows/release-dev.yml
diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml
new file mode 100644
index 0000000..137db84
--- /dev/null
+++ b/.github/workflows/release-dev.yml
@@ -0,0 +1,43 @@
+name: Release-Dev
+
+on:
+ push:
+ branches:
+ - dev
+
+permissions:
+ contents: write
+
+jobs:
+ hacs:
+ name: HACS Action
+ runs-on: "ubuntu-latest"
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ ref: main
+
+ - name: Get tag from commit summary with abbreviated tag
+ run: |
+ echo "tag=$(git describe --tags --abbrev=0)-0" >> $GITHUB_ENV
+
+ - name: Set version to release tag
+ run: |
+ sed -i "s/GITHUB_RELEASE_VERSION/${{ env.tag }}/g" custom_components/ankermake/manifest.json
+ sed -i "s/GITHUB_RELEASE_VERSION/${{ env.tag }}/g" custom_components/ankermake/const.py
+
+ - name: Zip ankermake
+ run: |
+ cd custom_components/ankermake
+ zip -r ankermake.zip .
+
+ - name: Upload release asset to the existing release
+ uses: svenstaro/upload-release-action@v1-release
+ with:
+ repo_token: ${{ secrets.GH_TOKEN }}
+ asset_path: custom_components/ankermake/ankermake.zip
+ asset_name: ankermake.zip
+ tag: ${{ env.tag }}
+ overwrite: true
\ No newline at end of file
From b189a01949813084019069e9bdd9753230b7ab5b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:08:45 +0200
Subject: [PATCH 06/20] Update release-dev.yml
---
.github/workflows/release-dev.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml
index 137db84..7fdf7dc 100644
--- a/.github/workflows/release-dev.yml
+++ b/.github/workflows/release-dev.yml
@@ -37,7 +37,7 @@ jobs:
uses: svenstaro/upload-release-action@v1-release
with:
repo_token: ${{ secrets.GH_TOKEN }}
- asset_path: custom_components/ankermake/ankermake.zip
+ file: custom_components/ankermake/ankermake.zip
asset_name: ankermake.zip
tag: ${{ env.tag }}
overwrite: true
\ No newline at end of file
From 170d441d49d4e394ee40526dc8edfb159ce669a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:12:07 +0200
Subject: [PATCH 07/20] Update release-dev.yml
---
.github/workflows/release-dev.yml | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml
index 7fdf7dc..3d819b9 100644
--- a/.github/workflows/release-dev.yml
+++ b/.github/workflows/release-dev.yml
@@ -36,8 +36,11 @@ jobs:
- name: Upload release asset to the existing release
uses: svenstaro/upload-release-action@v1-release
with:
- repo_token: ${{ secrets.GH_TOKEN }}
+ repo_token: ${{ secrets.GITHUB_TOKEN }}
file: custom_components/ankermake/ankermake.zip
asset_name: ankermake.zip
tag: ${{ env.tag }}
- overwrite: true
\ No newline at end of file
+ overwrite: true
+ body: "Autogenerated prerelease (dev) version of the component. See the GitHub repository for details."
+ prerelease: true
+ target_commit: dev
\ No newline at end of file
From 4118986fca715860bfed6ad5ef7b46059fc38a6e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:12:47 +0200
Subject: [PATCH 08/20] Use v2
---
.github/workflows/release-dev.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml
index 3d819b9..96b553e 100644
--- a/.github/workflows/release-dev.yml
+++ b/.github/workflows/release-dev.yml
@@ -34,7 +34,7 @@ jobs:
zip -r ankermake.zip .
- name: Upload release asset to the existing release
- uses: svenstaro/upload-release-action@v1-release
+ uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: custom_components/ankermake/ankermake.zip
From e3dac5f9fc0c59ea28da9a131f6d21faafdcfabd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:18:48 +0200
Subject: [PATCH 09/20] Use dev tag for prerelease
---
.github/workflows/release-dev.yml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml
index 96b553e..5abad07 100644
--- a/.github/workflows/release-dev.yml
+++ b/.github/workflows/release-dev.yml
@@ -21,7 +21,8 @@ jobs:
- name: Get tag from commit summary with abbreviated tag
run: |
- echo "tag=$(git describe --tags --abbrev=0)-0" >> $GITHUB_ENV
+ echo "tag=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV
+ echo "tag=$(echo ${{ env.tag }} | awk -F. '{print $1"."$2+1".0-0"}')" >> $GITHUB_ENV
- name: Set version to release tag
run: |
@@ -39,7 +40,7 @@ jobs:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: custom_components/ankermake/ankermake.zip
asset_name: ankermake.zip
- tag: ${{ env.tag }}
+ tag: dev
overwrite: true
body: "Autogenerated prerelease (dev) version of the component. See the GitHub repository for details."
prerelease: true
From 790fed268120c0dbd7f94e202a6be1ffe838a832 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:31:38 +0200
Subject: [PATCH 10/20] Update release-dev.yml
---
.github/workflows/release-dev.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml
index 5abad07..3bae1a1 100644
--- a/.github/workflows/release-dev.yml
+++ b/.github/workflows/release-dev.yml
@@ -22,7 +22,7 @@ jobs:
- name: Get tag from commit summary with abbreviated tag
run: |
echo "tag=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV
- echo "tag=$(echo ${{ env.tag }} | awk -F. '{print $1"."$2+1".0-0"}')" >> $GITHUB_ENV
+ echo "tag=$(echo ${{ env.tag }} | sed -E 's/([0-9]+\.[0-9]+)\.([0-9]+)/\1+1.\2\-0/g')" >> $GITHUB_ENV
- name: Set version to release tag
run: |
@@ -40,8 +40,8 @@ jobs:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: custom_components/ankermake/ankermake.zip
asset_name: ankermake.zip
- tag: dev
+ tag: ${{ env.tag }}
overwrite: true
body: "Autogenerated prerelease (dev) version of the component. See the GitHub repository for details."
prerelease: true
- target_commit: dev
\ No newline at end of file
+ target_commit: dev
From 1e1bd7439a94adb32ee30eae9137a17680cd2769 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:35:23 +0200
Subject: [PATCH 11/20] Trying again..
---
.github/workflows/release-dev.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml
index 3bae1a1..99bdabb 100644
--- a/.github/workflows/release-dev.yml
+++ b/.github/workflows/release-dev.yml
@@ -22,7 +22,8 @@ jobs:
- name: Get tag from commit summary with abbreviated tag
run: |
echo "tag=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV
- echo "tag=$(echo ${{ env.tag }} | sed -E 's/([0-9]+\.[0-9]+)\.([0-9]+)/\1+1.\2\-0/g')" >> $GITHUB_ENV
+ echo "tag=$(echo $tag | awk -F. '{print $1"."$2+1"."$3"-0"}')" >> $GITHUB_ENV
+ echo "${{ env.tag }}"
- name: Set version to release tag
run: |
From ac83c85a45e26a7c8be7b01dc29beba0f04fe43d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:36:56 +0200
Subject: [PATCH 12/20] Update release-dev.yml
---
.github/workflows/release-dev.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml
index 99bdabb..57cc42a 100644
--- a/.github/workflows/release-dev.yml
+++ b/.github/workflows/release-dev.yml
@@ -22,7 +22,7 @@ jobs:
- name: Get tag from commit summary with abbreviated tag
run: |
echo "tag=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV
- echo "tag=$(echo $tag | awk -F. '{print $1"."$2+1"."$3"-0"}')" >> $GITHUB_ENV
+ echo "tag=$(echo ${{ env.tag }} | awk -F. '{print $1"."$2+1"."$3"-0"}')" >> $GITHUB_ENV
echo "${{ env.tag }}"
- name: Set version to release tag
From 70537780e00db2455496ede9691e11ead74d9d4a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:38:37 +0200
Subject: [PATCH 13/20] Reverting to simpler times
---
.github/workflows/release-dev.yml | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml
index 57cc42a..63141f2 100644
--- a/.github/workflows/release-dev.yml
+++ b/.github/workflows/release-dev.yml
@@ -21,9 +21,7 @@ jobs:
- name: Get tag from commit summary with abbreviated tag
run: |
- echo "tag=$(git describe --tags --abbrev=0)" >> $GITHUB_ENV
- echo "tag=$(echo ${{ env.tag }} | awk -F. '{print $1"."$2+1"."$3"-0"}')" >> $GITHUB_ENV
- echo "${{ env.tag }}"
+ echo "tag=$(git describe --tags --abbrev=0)-0" >> $GITHUB_ENV
- name: Set version to release tag
run: |
From 54ac32e4173c13a9e7bb197ad1cdf97b8afe6a7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:40:40 +0200
Subject: [PATCH 14/20] Actually push the dev branch to dev build
---
.github/workflows/release-dev.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml
index 63141f2..99a5443 100644
--- a/.github/workflows/release-dev.yml
+++ b/.github/workflows/release-dev.yml
@@ -17,7 +17,7 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
- ref: main
+ ref: dev
- name: Get tag from commit summary with abbreviated tag
run: |
From bea1929bd279ed5557a10592cbce85c308411120 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:43:33 +0200
Subject: [PATCH 15/20] Update release-dev.yml
---
.github/workflows/release-dev.yml | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml
index 99a5443..aec0ae2 100644
--- a/.github/workflows/release-dev.yml
+++ b/.github/workflows/release-dev.yml
@@ -21,7 +21,8 @@ jobs:
- name: Get tag from commit summary with abbreviated tag
run: |
- echo "tag=$(git describe --tags --abbrev=0)-0" >> $GITHUB_ENV
+ tag=$(git describe --tags --abbrev=0)
+ echo "tag=$(echo $tag | grep -oP '\d+\.\d+\.\d+')-0" >> $GITHUB_ENV
- name: Set version to release tag
run: |
From 785440962d980e5c7b9b42d2d75a5d8f162cbff9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:51:04 +0200
Subject: [PATCH 16/20] Increment prerelease by 0.1.0-0
---
.github/workflows/release-dev.yml | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml
index aec0ae2..33fa5a9 100644
--- a/.github/workflows/release-dev.yml
+++ b/.github/workflows/release-dev.yml
@@ -22,7 +22,9 @@ jobs:
- name: Get tag from commit summary with abbreviated tag
run: |
tag=$(git describe --tags --abbrev=0)
- echo "tag=$(echo $tag | grep -oP '\d+\.\d+\.\d+')-0" >> $GITHUB_ENV
+ tag=$(echo $tag | grep -oP '\d+\.\d+\.\d+')
+ tag=$(echo $tag | awk -F. '{print $1"."$2+1"."$3"-0"}')
+ echo "tag=$tag" >> $GITHUB_ENV
- name: Set version to release tag
run: |
From 0d65cc4c924d7e7c070bbf08680e50a03c3ec355 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 10:54:02 +0200
Subject: [PATCH 17/20] Only increment non pre-release tags
---
.github/workflows/release-dev.yml | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/release-dev.yml b/.github/workflows/release-dev.yml
index 33fa5a9..62dad0a 100644
--- a/.github/workflows/release-dev.yml
+++ b/.github/workflows/release-dev.yml
@@ -22,8 +22,10 @@ jobs:
- name: Get tag from commit summary with abbreviated tag
run: |
tag=$(git describe --tags --abbrev=0)
- tag=$(echo $tag | grep -oP '\d+\.\d+\.\d+')
- tag=$(echo $tag | awk -F. '{print $1"."$2+1"."$3"-0"}')
+ if [[ $tag != *"-0" ]]; then
+ tag=$(echo $tag | grep -oP '\d+\.\d+\.\d+')
+ tag=$(echo $tag | awk -F. '{print $1"."$2+1"."$3"-0"}')
+ fi
echo "tag=$tag" >> $GITHUB_ENV
- name: Set version to release tag
From c9376663628722360732ad9915ef4e6cc47b8fdd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 11:18:46 +0200
Subject: [PATCH 18/20] Update image.py
---
custom_components/ankermake/image.py | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/custom_components/ankermake/image.py b/custom_components/ankermake/image.py
index 9fd9eef..536a438 100644
--- a/custom_components/ankermake/image.py
+++ b/custom_components/ankermake/image.py
@@ -24,11 +24,14 @@ def __init__(self, coordinator, description, dev_info, hass: HomeAssistant):
@callback
def _update_from_anker(self) -> None:
gcode_preview_url = self.coordinator.ankerdata.image
- if gcode_preview_url != self._gcode_preview_url:
- self._attr_image_last_updated = datetime.now()
+ is_new_image = gcode_preview_url != self._gcode_preview_url
+
self._gcode_preview_url = gcode_preview_url
self._attr_image_url = self._gcode_preview_url
+ if is_new_image:
+ self._attr_image_last_updated = datetime.now()
+
if self.coordinator.ankerdata.online:
self._attr_available = True
else:
From 359ca6206c6ad02e1813a34337309e51ea8ce06b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 18:46:36 +0200
Subject: [PATCH 19/20] Add docker-compose, redo some API sensors
---
README.md | 38 +++++++++++++++++++
.../ankermake/ankermake_mqtt_adapter.py | 8 ----
.../ankermake/sensor_manifest.py | 34 +++--------------
3 files changed, 44 insertions(+), 36 deletions(-)
diff --git a/README.md b/README.md
index a62dc28..f127009 100644
--- a/README.md
+++ b/README.md
@@ -90,6 +90,44 @@ Assistant add-on in their organization, but I have not tested it with this compo
(The branch of ankerctl I'm
using: https://github.com/sondregronas/ankermake-m5-protocol/tree/patch-exiles-1.1-auto-restart-on-failure)
+
+Click here for a docker-compose setup
+
+You can use this `docker-compose.yml` file to start an instance of my fork of ankerctl. Note that the container is set
+to restart every 2 hours as a workaround for some socket issues I've encountered, but isn't strictly necessary.
+
+```yaml
+services:
+ ankerctl:
+ container_name: ankerctl
+ restart: unless-stopped
+ build:
+ context: https://github.com/sondregronas/ankermake-m5-protocol.git#patch-exiles-1.1-auto-restart-on-failure
+ privileged: true
+ # host-mode networking is required for pppp communication with the
+ # printer, since it is an asymmetrical udp protocol.
+ network_mode: host
+ environment:
+ - FLASK_HOST=0.0.0.0
+ - FLASK_PORT=4470
+ volumes:
+ - ankerctl_vol:/root/.config/ankerctl
+ - ./ankermake-m5-protocol/web/:/app/web
+
+ # This container will restart the ankerctl container every 2 hours
+ # as a temporary workaround for some socket issues.
+ ankerctl_restarter:
+ image: docker
+ volumes: ["/var/run/docker.sock:/var/run/docker.sock"]
+ # 2 hours = 7200 seconds
+ command: ["/bin/sh", "-c", "while true; do sleep 7200; docker restart ankerctl; done"]
+ restart: unless-stopped
+volumes:
+ ankerctl_vol:
+```
+
+
+
## Known issues
There are probably many issues to list...
diff --git a/custom_components/ankermake/ankermake_mqtt_adapter.py b/custom_components/ankermake/ankermake_mqtt_adapter.py
index f07ba36..b334e7e 100644
--- a/custom_components/ankermake/ankermake_mqtt_adapter.py
+++ b/custom_components/ankermake/ankermake_mqtt_adapter.py
@@ -210,14 +210,6 @@ def _remove_error(self):
self.error_message = ""
self.error_level = ""
- @property
- def api_status(self) -> str:
- return self._api_status.get('status', 'Offline').capitalize()
-
- @staticmethod
- def api_status_possible_states() -> list:
- return ['Ok', 'Error', 'Offline']
-
@property
def api_service_possible_states(self) -> list:
return list(self._api_status.get('possible_states', {}).keys()) + ['Unavailable']
diff --git a/custom_components/ankermake/sensor_manifest.py b/custom_components/ankermake/sensor_manifest.py
index e070deb..5640143 100644
--- a/custom_components/ankermake/sensor_manifest.py
+++ b/custom_components/ankermake/sensor_manifest.py
@@ -41,7 +41,7 @@ def __init__(self, *args, **kwargs):
],
# Filetransfer service
[Description(
- key="filetransfer_service",
+ key="service_filetransfer",
name="Filetransfer Service",
icon="mdi:console",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
@@ -55,7 +55,7 @@ def __init__(self, *args, **kwargs):
],
# PPPPservice
[Description(
- key="pppp_service",
+ key="service_pppp",
name="PPPP Service",
icon="mdi:console",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
@@ -69,7 +69,7 @@ def __init__(self, *args, **kwargs):
],
# Videoqueue
[Description(
- key="videoqueue_service",
+ key="service_videoqueue",
name="Videoqueue Service",
icon="mdi:console",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
@@ -83,15 +83,15 @@ def __init__(self, *args, **kwargs):
],
# mqtt
[Description(
- key="mqtt_service",
+ key="service_mqtt",
name="MQTT Service",
icon="mdi:console",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
entity_registry_enabled_default=False, # TODO: Enable this when API is in master
),
{
- 'state': '%SVC_ONLINE=mqtt',
- 'status': '%SVC_STATE=mqtt',
+ 'state': '%SVC_ONLINE=mqttqueue',
+ 'status': '%SVC_STATE=mqttqueue',
'possible_states': 'api_service_possible_states',
}
],
@@ -303,26 +303,4 @@ def __init__(self, *args, **kwargs):
'error_level': 'error_level',
}
],
- # Ankerctl
- [Description(
- key="ankerctl",
- name="Ankerctl",
- icon="mdi:console",
- entity_registry_enabled_default=False, # TODO: Enable this when API is in master
- device_class='enum',
- options=AnkerData.api_status_possible_states(),
- ),
- {
- 'state': 'api_status',
- 'pppp_service': '%SVC_STATE=pppp',
- 'pppp_online': '%SVC_ONLINE=pppp',
- 'filetransfer_service': '%SVC_STATE=filetransfer',
- 'filetransfer_online': '%SVC_ONLINE=filetransfer',
- 'videoqueue_service': '%SVC_STATE=videoqueue',
- 'videoqueue_online': '%SVC_ONLINE=videoqueue',
- 'mqtt_service': '%SVC_STATE=mqtt',
- 'mqtt_online': '%SVC_ONLINE=mqtt',
- 'possible_states': 'api_service_possible_states',
- }
- ],
]
From aa8fed8c9da31488d51d85548febd4bb25f0af4a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sondre=20Gr=C3=B8n=C3=A5s?=
<44143748+sondregronas@users.noreply.github.com>
Date: Wed, 10 Jul 2024 19:34:16 +0200
Subject: [PATCH 20/20] Cleanup sensors, use unique_ids
---
custom_components/ankermake/__init__.py | 18 +++++++++++++++++-
custom_components/ankermake/binary_sensor.py | 8 --------
custom_components/ankermake/sensor.py | 19 +------------------
3 files changed, 18 insertions(+), 27 deletions(-)
diff --git a/custom_components/ankermake/__init__.py b/custom_components/ankermake/__init__.py
index 74f736e..e6cfa7e 100644
--- a/custom_components/ankermake/__init__.py
+++ b/custom_components/ankermake/__init__.py
@@ -119,7 +119,7 @@ def __init__(self, coordinator: AnkerMakeUpdateCoordinator,
self._attr_name = f"{device_info['name']} {description.name}"
self.entity_description = description
- self._attr_unique_id = description.key
+ self._attr_unique_id = f"{device_info['name']}_{description.key}"
self._attr_device_info = device_info
@property
@@ -133,3 +133,19 @@ def _handle_coordinator_update(self) -> None:
def _update_from_anker(self) -> None:
"""Update the entity. (Used by sensor.py)"""
+
+ def _filter_handler(self, key: str):
+ def td_convert(seconds):
+ return str(timedelta(seconds=seconds))
+
+ if key.startswith('%%TD='):
+ val = getattr(self.coordinator.ankerdata, key.split('=')[1])
+ return td_convert(val)
+ elif key.startswith('='):
+ return key[1:]
+ elif key.startswith('%SVC_ONLINE='):
+ return self.coordinator.ankerdata.get_api_service_online(key.split('=')[1])
+ elif key.startswith('%SVC_STATE='):
+ return self.coordinator.ankerdata.get_api_service_status(key.split('=')[1])
+
+ return getattr(self.coordinator.ankerdata, key)
diff --git a/custom_components/ankermake/binary_sensor.py b/custom_components/ankermake/binary_sensor.py
index b7e36d1..29471e7 100644
--- a/custom_components/ankermake/binary_sensor.py
+++ b/custom_components/ankermake/binary_sensor.py
@@ -36,14 +36,6 @@ def __init__(self, coordinator, description, dev_info, attrs):
self.attrs = attrs.copy()
self._attr_extra_state_attributes = dict()
- def _filter_handler(self, key: str):
- if key.startswith('%SVC_ONLINE='):
- return self.coordinator.ankerdata.get_api_service_online(key.split('=')[1])
- elif key.startswith('%SVC_STATE='):
- return self.coordinator.ankerdata.get_api_service_status(key.split('=')[1])
-
- return getattr(self.coordinator.ankerdata, key)
-
@callback
def _update_from_anker(self) -> None:
try:
diff --git a/custom_components/ankermake/sensor.py b/custom_components/ankermake/sensor.py
index 8dd9f0d..48ea549 100644
--- a/custom_components/ankermake/sensor.py
+++ b/custom_components/ankermake/sensor.py
@@ -21,7 +21,7 @@ class AnkerMakeSensor(AnkerMakeBaseEntity, SensorEntity):
@callback
def _update_from_anker(self) -> None:
try:
- value = getattr(self.coordinator.ankerdata, self.entity_description.key)
+ value = self._filter_handler(self.entity_description.key)
if self.coordinator.ankerdata.online:
self._attr_available = True
else:
@@ -39,23 +39,6 @@ def __init__(self, coordinator, description, dev_info, attrs):
self.attrs = attrs.copy()
self._attr_extra_state_attributes = dict()
- @staticmethod
- def td_convert(seconds):
- return str(timedelta(seconds=seconds))
-
- def _filter_handler(self, key: str):
- if key.startswith('%%TD='):
- val = getattr(self.coordinator.ankerdata, key.split('=')[1])
- return self.td_convert(val)
- elif key.startswith('='):
- return key[1:]
- elif key.startswith('%SVC_ONLINE='):
- return self.coordinator.ankerdata.get_api_service_online(key.split('=')[1])
- elif key.startswith('%SVC_STATE='):
- return self.coordinator.ankerdata.get_api_service_status(key.split('=')[1])
-
- return getattr(self.coordinator.ankerdata, key)
-
@callback
def _update_from_anker(self) -> None:
try: