Skip to content

Commit

Permalink
Merge pull request #6 from sondregronas/dev
Browse files Browse the repository at this point in the history
0.5.0
  • Loading branch information
sondregronas authored Jul 9, 2024
2 parents f6af45b + 8bbe1e3 commit 70949e6
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 24 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ instance and updates the status of your printer in real-time.

[![Open your Home Assistant instance and open a repository inside the Home Assistant Community Store.](https://my.home-assistant.io/badges/hacs_repository.svg)](https://my.home-assistant.io/redirect/hacs_repository/?owner=sondregronas&repository=ankermake-hass-component&category=ankermake)

Download and install the component via hacs (alternatively copy the `custom_components/ankermake` folder to your Home
Assistant config) and reboot. You will then be able to add the AnkerMake integration in the Home Assistant integrations
page (or by clicking the badge below).
Download and install the component via hacs (alternatively copy the contents of the latest release into
`custom_components/ankermake` folder to your Home Assistant instance) and reboot, then add the integration via the
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)

Expand Down
31 changes: 23 additions & 8 deletions custom_components/ankermake/ankermake_mqtt_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,11 @@ class AnkerData:
print_target_time: datetime = None

motor_locked: bool = False

ai_enabled: bool = False
ai_level: int = 0
ai_pause_print: bool = False
ai_data_collection: bool = False

# TODO: Currently no message for filament type except for error messages (afaik). Currently derived from filename.
filament: str = FilamentType.UNKNOWN.value
Expand Down Expand Up @@ -115,23 +119,31 @@ def filament_density(self) -> float:
FILAMENT_DENSITY.get(FilamentType.PLA.value))
return round(density, 2)

def _new_status_handler(self, new_status: AnkerStatus):
def _new_status_handler(self, new_status: AnkerStatus) -> AnkerStatus:
"""Handler for new status changes."""
status = new_status

# If the status is the same as the old status, return
if new_status == self._old_status:
return
if status == self._old_status:
return status

self._update_target_time()

# Reset the error message if the status is no longer an error
if self._old_status == AnkerStatus.ERROR:
self._remove_error()

# If the printer is finished/idle and the new status is printing, it should be preheating first
# (it takes a while for the printer to send the preheating status on a new print job)
if self._old_status in [AnkerStatus.FINISHED, AnkerStatus.IDLE] and status == AnkerStatus.PRINTING:
status = AnkerStatus.PREHEATING

# Reset the data if the status is one of the reset states
if new_status in RESET_STATES:
if status in RESET_STATES:
self._reset()

self._old_status = new_status
self._old_status = status
return status

@property
def status(self) -> str:
Expand All @@ -155,8 +167,7 @@ def status(self) -> str:
elif not self.printing:
status = AnkerStatus.IDLE

self._new_status_handler(status)
return status.value
return self._new_status_handler(status).value

def _update_target_time(self):
"""Should not call this too often (on state change / new print job)"""
Expand Down Expand Up @@ -220,7 +231,11 @@ def update(self, websocket_message: dict):
self.remaining_time = _remaining_time
self.total_time = _elapsed_time + _remaining_time

self.ai_enabled = websocket_message.get("aiFlag") == 1
self.ai_enabled = max(websocket_message.get("aiFlag"),
websocket_message.get("AISwitch")) == 1
self.ai_level = websocket_message.get("AISensitivity")
self.ai_pause_print = websocket_message.get("AIPausePrint") == 1
self.ai_data_collection = websocket_message.get("AIJoinImproving") == 1

filament_used = websocket_message.get("filamentUsed") / 1000 # Get meters (from mm)
self.filament_used = round(filament_used, 2)
Expand Down
29 changes: 28 additions & 1 deletion custom_components/ankermake/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from . import AnkerMakeBaseEntity
from .const import DOMAIN, MANUFACTURER
from .sensor_manifest import BINARY_SENSOR_DESCRIPTIONS
from .sensor_manifest import BINARY_SENSOR_DESCRIPTIONS, BINARY_SENSOR_WITH_ATTR_DESCRIPTIONS

_LOGGER = logging.getLogger(__name__)

Expand All @@ -30,6 +30,31 @@ def _update_from_anker(self) -> None:
self._attr_available = False


class AnkerMakeBinarySensorWithAttr(AnkerMakeBaseEntity, BinarySensorEntity):
def __init__(self, coordinator, description, dev_info, attrs):
super().__init__(coordinator, description, dev_info)
self.attrs = attrs.copy()
self._attr_extra_state_attributes = dict()

@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':
continue
self._attr_extra_state_attributes[attr] = getattr(self.coordinator.ankerdata, key)

if not self.coordinator.ankerdata.online:
self._attr_available = True
else:
self._attr_available = False
except (AttributeError, KeyError):
self._attr_available = False


async def async_setup_entry(hass, entry, async_add_entities):
coordinator = hass.data[DOMAIN][entry.entry_id]
entities = []
Expand All @@ -40,5 +65,7 @@ async def async_setup_entry(hass, entry, async_add_entities):

for description in BINARY_SENSOR_DESCRIPTIONS:
entities.append(AnkerMakeBinarySensor(coordinator, description, dev_info))
for description, attributes in BINARY_SENSOR_WITH_ATTR_DESCRIPTIONS:
entities.append(AnkerMakeBinarySensorWithAttr(coordinator, description, dev_info, attributes))

async_add_entities(entities, True)
3 changes: 1 addition & 2 deletions custom_components/ankermake/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ def _update_from_anker(self) -> None:
self._attr_available = True
else:
self._attr_available = False
except (AttributeError, KeyError) as e:
_LOGGER.error(f"Failed to update {e}")
except (AttributeError, KeyError):
self._attr_available = False


Expand Down
30 changes: 20 additions & 10 deletions custom_components/ankermake/sensor_manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,6 @@ def __init__(self, *args, **kwargs):

# Key must match the attribute in the AnkerData class
BINARY_SENSOR_DESCRIPTIONS = [
# AI Enabled
Description(
key="ai_enabled",
name="AI Detection Enabled",
icon="mdi:brain",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
entity_registry_enabled_default=False,
),
# Motor Locked
Description(
key="motor_locked",
Expand All @@ -31,6 +23,24 @@ def __init__(self, *args, **kwargs):
),
]

BINARY_SENSOR_WITH_ATTR_DESCRIPTIONS = [
# AI Enabled
[Description(
key="ai_enabled",
name="AI Detection",
icon="mdi:brain",
device_class=BinarySensorDeviceClass.CONNECTIVITY,
entity_registry_enabled_default=False,
),
{
'state': 'ai_enabled',
'level': 'ai_level',
'pause_print': 'ai_pause_print',
'data_collection': 'ai_data_collection',
}
],
]

# Key must match the attribute in the AnkerData class
SENSOR_DESCRIPTIONS = [
# Job Name
Expand Down Expand Up @@ -81,7 +91,7 @@ def __init__(self, *args, **kwargs):
# Current Speed
Description(
key="current_speed",
name="Current Speed",
name="Speed",
icon="mdi:speedometer",
native_unit_of_measurement="mm/s",
entity_registry_enabled_default=False,
Expand All @@ -105,7 +115,7 @@ def __init__(self, *args, **kwargs):
# Current Layer
Description(
key="current_layer",
name="Current Layer",
name="Layer",
icon="mdi:layers-triple",
entity_registry_enabled_default=False,
),
Expand Down

0 comments on commit 70949e6

Please sign in to comment.