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

Refactoring Services #273

Merged
merged 4 commits into from
Nov 17, 2024
Merged

Refactoring Services #273

merged 4 commits into from
Nov 17, 2024

Conversation

sca075
Copy link
Owner

@sca075 sca075 commented Nov 17, 2024

The init.py and common.py are not the correct place for logics, in order to improve the project we did create a vaccum specific folder for the services that are group in the mqtt_vacuum_services.py

Summary by CodeRabbit

  • New Features

    • Introduced a more centralized service management approach for vacuum operations.
    • Added new asynchronous service functions for vacuum control, including cleaning segments, zones, and map management.
    • Added new camera-related service functions for resetting trims and reloading configuration.
  • Bug Fixes

    • Streamlined error handling for service functions to improve reliability.
  • Chores

    • Updated version number from 2024.11.0 to 2024.11.1.
    • Removed obsolete functions to enhance code clarity and focus.

@sca075 sca075 self-assigned this Nov 17, 2024
@sca075 sca075 added the enhancement New feature or request label Nov 17, 2024
Copy link

coderabbitai bot commented Nov 17, 2024

Walkthrough

The recent changes in the mqtt_vacuum_camera component involve a restructuring of service management for vacuum operations. Several vacuum-related service functions have been removed, and new modular service registration functions have been introduced. The version number has been updated from 2024.11.0 to 2024.11.1. The modifications streamline the codebase and centralize service handling, impacting the overall functionality of vacuum commands and interactions.

Changes

File Path Change Summary
custom_components/mqtt_vacuum_camera/__init__.py - Removed service functions: vacuum_clean_segments, vacuum_clean_zone, vacuum_goto, vacuum_map_save, vacuum_map_load.
- Added functions: async_register_vacuums_services, async_remove_vacuums_services.
- Updated async_unload_entry for service unregistration.
custom_components/mqtt_vacuum_camera/common.py - Removed functions: generate_service_data_go_to, generate_service_data_clean_zone, generate_zone_payload, generate_service_data_clean_segments, convert_string_ids_to_integers.
custom_components/mqtt_vacuum_camera/utils/vacuum/mqtt_vacuum_services.py - Added service functions: vacuum_clean_segments, vacuum_clean_zone, vacuum_goto, vacuum_map_save, vacuum_map_load.
- Added utility functions: resolve_datas, generate_service_data_*, generate_zone_payload.
- Added service registration functions: async_register_vacuums_services, async_remove_vacuums_services.
custom_components/mqtt_vacuum_camera/utils/camera/camera_services.py - Added camera service functions: reset_trims, reload_config.

Possibly related PRs

Suggested labels

Fixes for issues


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 12

🧹 Outside diff range and nitpick comments (10)
custom_components/mqtt_vacuum_camera/common.py (3)

Line range hint 160-177: Heads up: Type mismatches in from_device_ids_to_entity_ids need fixing

The function from_device_ids_to_entity_ids is annotated with device_ids: str, but it iterates over device_ids as if it's a list or iterable. Additionally, it returns resolved_entity_ids, a list, while the return type is annotated as -> str. This mismatch might cause unexpected behavior.

Here's a diff to get things back on track:

-from_device_ids_to_entity_ids(device_ids: str, hass: HomeAssistant) -> str:
+from_device_ids_to_entity_ids(device_ids: List[str], hass: HomeAssistant) -> List[str]:

Make sure that device_ids is a list when you call this function, or adjust the code to handle a single device_id.


Line range hint 193-204: In get_entity_id, let's keep return types consistent

In get_entity_id, when a device_id is provided, vacuum_entity_id gets assigned resolved_entities, which may be a list of entity IDs. However, the return type is annotated as -> str | None, indicating it should return a single string or None. Mixing lists and strings could lead to issues.

Consider updating the return type and logic to handle multiple entity IDs or ensure it returns a single entity ID. Here's a helpful diff:

-def get_entity_id(
-    entity_id: str | None, device_id: str | None, hass: HomeAssistant
-) -> str | None:
+def get_entity_id(
+    entity_id: str | None, device_id: str | None, hass: HomeAssistant
+) -> List[str] | None:

Line range hint 119-121: Simplify variable assignment in update_options

The variable updated_bk_options is assigned from updated_options but is returned immediately without further modification. You can streamline the function by returning updated_options directly.

Apply this diff to simplify:

-    updated_bk_options = updated_options  # or backup_options, as needed
-    return updated_bk_options
+    return updated_options
custom_components/mqtt_vacuum_camera/utils/vacuum/mqtt_vacuum_services.py (7)

44-45: Consider removing commented-out code for a cleaner codebase

Keeping old code commented out can clutter up your script. Let's keep it sleek by removing unnecessary comments.

Here's how you can update:

-    # elif not service_data["have_rooms"]:
-    #     raise ServiceValidationError("No rooms found in the vacuum map.")

514-514: Simplify your dictionary iteration—drop the .keys()

When you're looping through a dictionary, it's cooler to iterate directly over the keys.

Here's the tweak:

-    for service_name in SERVICES.keys():
+    for service_name in SERVICES:
🧰 Tools
🪛 Ruff

514-514: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)


52-52: Catch specific exceptions instead of the generic Exception

Catching Exception can inadvertently hide bugs. It's cooler to catch specific exceptions to handle known error scenarios.

Consider specifying the exact exception you expect.


97-97: Be precise with exception handling

Using except Exception is a bit broad. Tightening it up by catching specific exceptions keeps things sharp.

Specify the exception type you're expecting here.


136-136: Narrow down your exception catch

Catching all exceptions might mask underlying issues. Let's keep it cool by specifying the exact exception.

Consider replacing except Exception with a more specific exception type.


179-179: Keep exception handling specific

Catching broad exceptions can hide problems. Specify the exact exception to keep your code styling.

Update except Exception to catch a specific exception.


222-222: Fine-tune your exception catching

Using except Exception is a bit too broad. Let's hone it down to the specific exception you're expecting.

Replace except Exception with a specific exception type.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0855a5d and 0b5584c.

📒 Files selected for processing (3)
  • custom_components/mqtt_vacuum_camera/__init__.py (5 hunks)
  • custom_components/mqtt_vacuum_camera/common.py (1 hunks)
  • custom_components/mqtt_vacuum_camera/utils/vacuum/mqtt_vacuum_services.py (1 hunks)
🧰 Additional context used
🪛 Ruff
custom_components/mqtt_vacuum_camera/utils/vacuum/mqtt_vacuum_services.py

53-53: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


65-65: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


98-98: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


109-109: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


141-141: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


149-149: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


184-184: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


192-192: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


227-227: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


236-236: Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling

(B904)


514-514: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

🔇 Additional comments (4)
custom_components/mqtt_vacuum_camera/common.py (1)

3-3: Version bump to 2024.11.1—looking good!

The version update reflects the latest changes and ensures consistency across the integration.

custom_components/mqtt_vacuum_camera/__init__.py (3)

2-2: Version bump approved!

Nice upgrade to version 2024.11.1.


17-17: Importing ConfigEntryNotReady is spot on

Good call importing ConfigEntryNotReady for handling config entry readiness.


35-39: Slick import of vacuum services modules

Modularizing with mqtt_vacuum_services keeps things clean and organized.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Outside diff range and nitpick comments (7)
custom_components/mqtt_vacuum_camera/utils/camera/camera_services.py (1)

3-11: Yo, let's add some breathing room to those imports! 🎭

Add a blank line between third-party imports (homeassistant) and local imports (utils.files_operations) to keep things organized and fresh.

 from homeassistant.config_entries import ConfigEntryState
 from homeassistant.const import SERVICE_RELOAD
 
+
 from ...utils.files_operations import async_clean_up_all_auto_crop_files
custom_components/mqtt_vacuum_camera/__init__.py (1)

32-32: Yo, we've got an unused import hanging around! 🧹

The async_clean_up_all_auto_crop_files import isn't being used anywhere in this file.

-    async_clean_up_all_auto_crop_files,
     async_get_translations_vacuum_id,
     async_rename_room_description,
🧰 Tools
🪛 Ruff

32-32: .utils.files_operations.async_clean_up_all_auto_crop_files imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

custom_components/mqtt_vacuum_camera/utils/vacuum/mqtt_vacuum_services.py (5)

1-3: Fix the typo in the docstring

There's a small typo in the author attribution.

-Autor: @sca075
+Author: @sca075

44-45: Clean up commented code

Either remove or uncomment this code block based on whether the room validation is needed.


47-54: Be more specific with exception handling

Instead of catching all exceptions with bare except Exception, consider catching specific exceptions that might occur during MQTT operations (e.g., ConnectionError, TimeoutError).

Example for one instance:

-            try:
-                await coordinator.connector.publish_to_broker(
-                    service_data["topic"],
-                    service_data["payload"],
-                )
-            except Exception as e:
-                raise ServiceValidationError(f"Error sending command to vacuum: {e}") from e
+            try:
+                await coordinator.connector.publish_to_broker(
+                    service_data["topic"],
+                    service_data["payload"],
+                )
+            except (ConnectionError, TimeoutError) as e:
+                raise ServiceValidationError(f"MQTT connection error: {e}") from e
+            except ValueError as e:
+                raise ServiceValidationError(f"Invalid payload format: {e}") from e

Also applies to: 92-98, 135-141, 178-184, 221-227


254-341: Consider breaking down the complex zone payload generation

The generate_zone_payload function handles multiple zone formats and firmware types, making it quite complex. Consider splitting it into smaller, more focused functions.

Example refactoring:

def _generate_rand256_zone_ids_payload(zones, repeat, after_cleaning):
    return {
        "command": "zoned_cleanup",
        "zone_ids": [
            {"id": zone, "repeats": repeat} if isinstance(zone, str) else zone
            for zone in zones
        ],
        "afterCleaning": after_cleaning,
    }

def _generate_rectangle_zone_payload(zone, repeat, is_rand256):
    x1, y1, x2, y2 = zone
    if is_rand256:
        return {"x1": x1, "y1": y1, "x2": x2, "y2": y2, "repeats": repeat}
    return {
        "points": {
            "pA": {"x": x1, "y": y1},
            "pB": {"x": x2, "y": y1},
            "pC": {"x": x2, "y": y2},
            "pD": {"x": x1, "y": y2},
        }
    }

def _generate_polygon_zone_payload(zone, repeat, is_rand256):
    x1, y1, x2, y2, x3, y3, x4, y4 = zone
    if is_rand256:
        return {
            "x1": x1, "y1": y1, "x2": x2, "y2": y2,
            "x3": x3, "y3": y3, "x4": x4, "y4": y4,
            "repeats": repeat
        }
    return {
        "points": {
            "pA": {"x": x1, "y": y1},
            "pB": {"x": x2, "y": y2},
            "pC": {"x": x3, "y": y3},
            "pD": {"x": x4, "y": y4},
        }
    }

514-515: Optimize dictionary keys iteration

Use in operator directly with the dictionary instead of calling .keys().

-    for service_name in SERVICES.keys():
+    for service_name in SERVICES:
         hass.services.async_remove(DOMAIN, service_name)
🧰 Tools
🪛 Ruff

514-514: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 0b5584c and 76a582c.

📒 Files selected for processing (3)
  • custom_components/mqtt_vacuum_camera/__init__.py (4 hunks)
  • custom_components/mqtt_vacuum_camera/utils/camera/camera_services.py (1 hunks)
  • custom_components/mqtt_vacuum_camera/utils/vacuum/mqtt_vacuum_services.py (1 hunks)
🧰 Additional context used
🪛 Ruff
custom_components/mqtt_vacuum_camera/__init__.py

32-32: .utils.files_operations.async_clean_up_all_auto_crop_files imported but unused; consider removing, adding to __all__, or using a redundant alias

(F401)

custom_components/mqtt_vacuum_camera/utils/vacuum/mqtt_vacuum_services.py

514-514: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

🔇 Additional comments (5)
custom_components/mqtt_vacuum_camera/utils/camera/camera_services.py (1)

1-39: Let's make sure these cool services are properly wired up! 🔌

Since this is part of a larger refactoring effort, we should verify that these services are properly registered in the main component.

✅ Verification successful

All good in the hood! Services are properly wired up! 🎸

The camera services are perfectly integrated:

  • Both reset_trims and reload_config are imported in __init__.py
  • reset_trims is registered as a service with the correct domain
  • reload_config is properly hooked up to the admin reload service

Rock on! 🤘

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check if these services are properly registered in the main component
rg -l "async_register.*service" custom_components/mqtt_vacuum_camera/

Length of output: 194


Script:

#!/bin/bash
# Let's check the content of __init__.py to see how services are registered
rg -A 10 "async_register.*service" custom_components/mqtt_vacuum_camera/__init__.py

# Also check the mqtt_vacuum_services.py for comparison
rg -A 10 "async_register.*service" custom_components/mqtt_vacuum_camera/utils/vacuum/mqtt_vacuum_services.py

# Let's also check if our camera services are imported and used
rg "from.*camera_services import" custom_components/mqtt_vacuum_camera/

Length of output: 2410

custom_components/mqtt_vacuum_camera/__init__.py (3)

2-2: Version bump looks good! 🚀

The version increment to 2024.11.1 aligns with the refactoring changes.


125-128: Clean unload logic! 🧼

The service removal logic has been properly implemented with the domain check, ensuring services aren't removed prematurely when other entries are still active.


83-91: Sweet service registration setup! 🎯

The service registration is well-structured with proper checks before registration. The use of lambdas for simple handlers is clean.

Let's verify the service registration:

✅ Verification successful

Let me check the service registration implementation to ensure there are no conflicts.


Service registration is totally rad! 🎸

The service registration setup is clean and well-implemented:

  • Services are properly registered only once through the has_service check
  • Each service has its own dedicated handler with proper error handling
  • The async_register_vacuums_services function cleanly registers all vacuum-specific services using a dictionary-based approach
  • There's even a matching async_remove_vacuums_services for cleanup
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for any other service registration points that might conflict
rg -A 2 "async_register.*service" --type py

Length of output: 1583


Script:

#!/bin/bash
# Check the implementation of async_register_vacuums_services
cat custom_components/mqtt_vacuum_camera/utils/vacuum/mqtt_vacuum_services.py

Length of output: 17581

custom_components/mqtt_vacuum_camera/utils/vacuum/mqtt_vacuum_services.py (1)

1-515: Overall implementation looks solid! 🚀

The code successfully centralizes vacuum services with good error handling, clear documentation, and proper separation of concerns. The suggested improvements are mostly optimizations rather than critical issues.

🧰 Tools
🪛 Ruff

514-514: Use key in dict instead of key in dict.keys()

Remove .keys()

(SIM118)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (2)
custom_components/mqtt_vacuum_camera/utils/camera/camera_services.py (2)

23-24: Keep exceptions cool by being specific!

Catching the generic Exception is a bit too broad. For smoother debugging and cleaner code, consider catching specific exceptions.

Here's how you can refine it in reset_trims:

-except Exception as err:
+except SpecificException as err:

Replace SpecificException with the exact exception(s) you expect.


48-49: Stay frosty with precise exception handling here too!

Same groove applies in reload_config. Narrowing down the exceptions you catch keeps your code sleek.

Update it like this:

-except Exception as err:
+except SpecificException as err:

Again, swap in the specific exceptions you anticipate.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 76a582c and a5dc8f5.

📒 Files selected for processing (1)
  • custom_components/mqtt_vacuum_camera/utils/camera/camera_services.py (1 hunks)
🔇 Additional comments (1)
custom_components/mqtt_vacuum_camera/utils/camera/camera_services.py (1)

16-59: This refactor is smooth as ice! 😎

The reset_trims and reload_config functions are looking sharp. Solid use of async operations and error handling. The logging adds that extra layer of coolness.

@sca075 sca075 merged commit d5d0b80 into main Nov 17, 2024
6 checks passed
This was referenced Nov 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant