Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix navigation service error #233

Draft
wants to merge 3 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## v1.0.21

- Remove navigate service
- Remove exit navigation service
- Add Remote entity allowing to control and turn off control using a virtual joystick

## v1.0.20

- Fix navigation service schema [#223](https://github.com/sh00t2kill/dolphin-robot/issues/223)
Expand Down
23 changes: 5 additions & 18 deletions custom_components/mydolphin_plus/common/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
ATTR_ROBOT_STATE = "Robot State"
ATTR_ROBOT_TYPE = "Robot Type"
ATTR_IS_BUSY = "Busy"
ATTR_MANUAL_MODE = "Manual Mode"
ATTR_ACTIVITY = "Activity"
ATTR_TURN_ON_COUNT = "Turn On Count"
ATTR_TIME_ZONE = "Time Zone"

Expand All @@ -57,6 +59,7 @@
DYNAMIC_CONTENT_SPEED = "speed"
DYNAMIC_CONTENT_DIRECTION = "direction"

ATTR_REMOTE_CONTROL_MODE_EXIT = "exit"
ATTR_REMOTE_CONTROL_MODE_EXIT = "exit"

DATA_ROOT_STATE = "state"
Expand All @@ -76,6 +79,7 @@
DATA_SECTION_SYSTEM_STATE = "systemState"
DATA_SECTION_ROBOT_ERROR = "robotError"
DATA_SECTION_PWS_ERROR = "pwsError"
DATA_SECTION_ACTIVITY = "activity"

DATA_STATE_REPORTED = "reported"
DATA_STATE_DESIRED = "desired"
Expand Down Expand Up @@ -214,26 +218,9 @@
LED_MODE_DISCO: "mdi:lightbulb-multiple-outline",
}

CONF_DIRECTION = "direction"
CONF_DAY = "day"
CONF_TIME = "time"

JOYSTICK_SPEED = 1000

JOYSTICK_STOP = "stop"
JOYSTICK_FORWARD = "forward"
JOYSTICK_BACKWARD = "backward"
JOYSTICK_RIGHT = "right"
JOYSTICK_LEFT = "left"

JOYSTICK_DIRECTIONS = [
JOYSTICK_STOP,
JOYSTICK_FORWARD,
JOYSTICK_BACKWARD,
JOYSTICK_RIGHT,
JOYSTICK_LEFT,
]

CLOCK_HOURS_NONE = "mdi:timer-sand-paused"
CLOCK_HOURS_ICON = "mdi:clock-time-"
CLOCK_HOURS_TEXT = [
Expand Down Expand Up @@ -277,7 +264,6 @@
VacuumEntityFeature.STATE
| VacuumEntityFeature.FAN_SPEED
| VacuumEntityFeature.RETURN_HOME
| VacuumEntityFeature.SEND_COMMAND
| VacuumEntityFeature.START
| VacuumEntityFeature.PAUSE
| VacuumEntityFeature.LOCATE
Expand All @@ -292,6 +278,7 @@

DATA_KEY_STATUS = "Status"
DATA_KEY_VACUUM = "Vacuum"
DATA_KEY_REMOTE = "Remote"
DATA_KEY_LED_MODE = "LED Mode"
DATA_KEY_LED_INTENSITY = "LED Intensity"
DATA_KEY_LED = "LED"
Expand Down
21 changes: 21 additions & 0 deletions custom_components/mydolphin_plus/common/entity_descriptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
)
from homeassistant.components.light import LightEntityDescription
from homeassistant.components.number import NumberDeviceClass, NumberEntityDescription
from homeassistant.components.remote import RemoteEntityDescription, RemoteEntityFeature
from homeassistant.components.select import SelectEntityDescription
from homeassistant.components.sensor import (
SensorDeviceClass,
Expand Down Expand Up @@ -44,6 +45,7 @@
DATA_KEY_NETWORK_NAME,
DATA_KEY_POWER_SUPPLY_STATUS,
DATA_KEY_PWS_ERROR,
DATA_KEY_REMOTE,
DATA_KEY_ROBOT_ERROR,
DATA_KEY_ROBOT_STATUS,
DATA_KEY_ROBOT_TYPE,
Expand All @@ -54,6 +56,7 @@
ICON_LED_MODES,
VACUUM_FEATURES,
)
from .joystick_direction import JoystickDirection
from .robot_family import RobotFamily


Expand All @@ -74,6 +77,17 @@ class MyDolphinPlusVacuumEntityDescription(
fan_speed_list: list[str] = ()


@dataclass(frozen=True, kw_only=True)
class MyDolphinPlusRemoteEntityDescription(
RemoteEntityDescription, MyDolphinPlusEntityDescription
):
"""A class that describes vacuum entities."""

platform: Platform | None = Platform.REMOTE
features: RemoteEntityFeature = RemoteEntityFeature(0)
activity_list: list[str] = ()


@dataclass(frozen=True, kw_only=True)
class MyDolphinPlusBinarySensorEntityDescription(
BinarySensorEntityDescription, MyDolphinPlusEntityDescription
Expand Down Expand Up @@ -119,6 +133,13 @@ class MyDolphinPlusLightEntityDescription(
fan_speed_list=list(CleanModes),
translation_key=slugify(DATA_KEY_VACUUM),
),
MyDolphinPlusRemoteEntityDescription(
key=slugify(DATA_KEY_REMOTE),
name="",
features=RemoteEntityFeature.ACTIVITY,
activity_list=list(JoystickDirection),
translation_key=slugify(DATA_KEY_REMOTE),
),
MyDolphinPlusLightEntityDescription(
key=slugify(DATA_KEY_LED),
name=DATA_KEY_LED,
Expand Down
14 changes: 14 additions & 0 deletions custom_components/mydolphin_plus/common/joystick_direction.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from enum import StrEnum


class JoystickDirection(StrEnum):
STOP = "stop"
FORWARD = "forward"
BACKWARD = "backward"
LEFT = "left"
RIGHT = "right"

def get_speed(self) -> int:
speed = 0 if self == JoystickDirection.STOP else 100

return speed
14 changes: 1 addition & 13 deletions custom_components/mydolphin_plus/common/service_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,11 @@
import homeassistant.helpers.config_validation as cv

from .clean_modes import CleanModes
from .consts import CONF_DAY, CONF_DIRECTION, CONF_TIME, JOYSTICK_DIRECTIONS
from .consts import CONF_DAY, CONF_TIME

SERVICE_EXIT_NAVIGATION = "exit_navigation"
SERVICE_NAVIGATE = "navigate"
SERVICE_DAILY_SCHEDULE = "daily_schedule"
SERVICE_DELAYED_CLEAN = "delayed_clean"

SERVICE_SCHEMA_NAVIGATE = vol.Schema(
{vol.Required(CONF_DIRECTION): vol.In(JOYSTICK_DIRECTIONS)}
)

SERVICE_SCHEMA_DAILY_SCHEDULE = vol.Schema(
{
vol.Optional(CONF_ENABLED, default=False): cv.boolean,
Expand All @@ -33,9 +27,3 @@
vol.Optional(CONF_TIME, default=None): cv.string,
}
)

SERVICE_VALIDATION = {
SERVICE_NAVIGATE: SERVICE_SCHEMA_NAVIGATE,
SERVICE_DAILY_SCHEDULE: SERVICE_SCHEMA_DAILY_SCHEDULE,
SERVICE_DELAYED_CLEAN: SERVICE_SCHEMA_DELAYED_CLEAN,
}
56 changes: 41 additions & 15 deletions custom_components/mydolphin_plus/managers/aws_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
DATA_SCHEDULE_TIME,
DATA_SCHEDULE_TIME_HOURS,
DATA_SCHEDULE_TIME_MINUTES,
DATA_SECTION_ACTIVITY,
DATA_SECTION_CYCLE_INFO,
DATA_SECTION_DYNAMIC,
DATA_SECTION_FILTER_BAG_INDICATION,
Expand All @@ -66,7 +67,6 @@
DYNAMIC_DESCRIPTION_TEMPERATURE,
DYNAMIC_TYPE,
DYNAMIC_TYPE_PWS_REQUEST,
JOYSTICK_SPEED,
LED_MODE_BLINKING,
MQTT_MESSAGE_ENCODING,
SIGNAL_AWS_CLIENT_STATUS,
Expand All @@ -77,6 +77,7 @@
WS_DATA_VERSION,
WS_LAST_UPDATE,
)
from ..common.joystick_direction import JoystickDirection
from ..common.power_supply_state import PowerSupplyState
from ..common.robot_family import RobotFamily
from ..models.topic_data import TopicData
Expand Down Expand Up @@ -123,6 +124,10 @@ def __init__(self, hass: HomeAssistant | None, config_manager: ConfigManager):
ConnectionCallbacks.RESUMED: self._on_connection_resumed,
}

self._dynamic_message_handlers = {
DYNAMIC_TYPE_PWS_REQUEST: self._on_pws_request_message
}

self._on_publish_completed_callback = lambda f: self._on_publish_completed(
f
)
Expand Down Expand Up @@ -392,15 +397,7 @@ def _message_callback(self, topic, payload, dup, qos, retain, **kwargs):
)

elif topic == self._topic_data.dynamic:
_LOGGER.debug(f"Dynamic payload: {message_payload}")

response_type = payload_data.get(DYNAMIC_TYPE)
data = payload_data.get(DYNAMIC_CONTENT)

if response_type not in self.data:
self.data[DATA_SECTION_DYNAMIC] = {}

self.data[DATA_SECTION_DYNAMIC][response_type] = data
self._on_dynamic_content_received(payload_data)

elif topic.endswith(TOPIC_CALLBACK_ACCEPTED):
_LOGGER.debug(f"Payload: {message_payload}")
Expand Down Expand Up @@ -455,6 +452,31 @@ def _message_callback(self, topic, payload, dup, qos, retain, **kwargs):
f"Callback parsing failed, {message_details}, {error_details}"
)

def _on_dynamic_content_received(self, message: dict):
_LOGGER.debug(f"Dynamic payload: {message}")

message_type = message.get(DYNAMIC_TYPE)
content = message.get(DYNAMIC_CONTENT)
handler = self._dynamic_message_handlers.get(message_type)

if DATA_SECTION_DYNAMIC not in self.data:
self.data[DATA_SECTION_DYNAMIC] = {}

self.data[DATA_SECTION_DYNAMIC][message_type] = content

if handler is not None:
handler(message)

def _on_pws_request_message(self, message: dict):
direction = message.get(DYNAMIC_CONTENT_DIRECTION)
remote_control_mode = message.get(DYNAMIC_CONTENT_REMOTE_CONTROL_MODE)

if direction is not None:
self.data[DATA_SECTION_ACTIVITY] = direction

if remote_control_mode == ATTR_REMOTE_CONTROL_MODE_EXIT:
self.data[DATA_SECTION_ACTIVITY] = None

def _send_desired_command(self, payload: dict | None):
data = {DATA_ROOT_STATE: {DATA_STATE_DESIRED: payload}}

Expand Down Expand Up @@ -554,17 +576,21 @@ def set_led_enabled(self, is_enabled: bool):
_LOGGER.info(f"Set led enabled mode, Desired: {data}")
self._send_desired_command(data)

def navigate(self, direction: str):
def set_joystick_mode(self, direction: JoystickDirection):
request_data = {
DYNAMIC_CONTENT_SPEED: JOYSTICK_SPEED,
DYNAMIC_CONTENT_DIRECTION: direction,
DYNAMIC_CONTENT: {
DYNAMIC_CONTENT_SPEED: direction.get_speed(),
DYNAMIC_CONTENT_DIRECTION: direction,
}
}

self._send_dynamic_command(DYNAMIC_DESCRIPTION_JOYSTICK, request_data)

def exit_navigation(self):
def exit_joystick_mode(self):
request_data = {
DYNAMIC_CONTENT_REMOTE_CONTROL_MODE: ATTR_REMOTE_CONTROL_MODE_EXIT
DYNAMIC_CONTENT: {
DYNAMIC_CONTENT_REMOTE_CONTROL_MODE: ATTR_REMOTE_CONTROL_MODE_EXIT
}
}

self._send_dynamic_command(DYNAMIC_DESCRIPTION_JOYSTICK, request_data)
Expand Down
Loading
Loading