From 135c57fbf9cdbe64bbd9109abe25ad5b831e4581 Mon Sep 17 00:00:00 2001 From: Anna Bocharova Date: Mon, 19 Feb 2024 09:44:40 +0100 Subject: [PATCH] Feat: At-command target (#260) * Feature draft. * Adjusting the original test. * Ref: log the actually received command. * Ref: naming, ordering. * Testing the cases. * Fix quotes. * Ref: reset mock in loop. * Negative case. * Readme: listing the feature. * Changelog: proposed 4.1.0. * Fix: split only when the command is confirmed. * Ref: smarter unpack with defaults. * Fix case insensitivity. * Fix defaults. * Fix unused rest var. * Ref: smarter mapping of the target_str. --- CHANGELOG.md | 8 ++++++++ README.md | 5 +++-- octoprint_octorelay/__init__.py | 9 +++++---- tests/test_init.py | 14 +++++++++++--- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff10e8ac..e408a3f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## Version 4 +### 4.1.0 + +- New feature: target for GCODE command (at-command): + - You can now switch the relay to the desired state; + - `@OCTORELAY r1 ON` — to switch the first relay on; + - `@OCTORELAY r1 OFF` — to switch the first relay off; + - `@OCTORELAY r1` — to toggle the first relay. + ### 4.0.1 - Technical update: no new features, no fixes. diff --git a/README.md b/README.md index 7a3374a5..2d65a7d2 100644 --- a/README.md +++ b/README.md @@ -78,8 +78,9 @@ You can toggle the relays ON and OFF the following ways: - By clicking the control buttons on the navigation bar. - The icon you choose for the button will display the current state. -- By sending GCODE command `@OCTORELAY r#`. - - Where `#` is relay index from `1` to `8`. +- By sending GCODE command `@OCTORELAY r# [ON|OFF]`. + - Where `#` is relay index from `1` to `8`; + - While `[ON|OFF]` is an optional target. - Or by querying the API (see below). ## OctoRelay API diff --git a/octoprint_octorelay/__init__.py b/octoprint_octorelay/__init__.py index 8f51a77d..44fdb385 100755 --- a/octoprint_octorelay/__init__.py +++ b/octoprint_octorelay/__init__.py @@ -337,12 +337,13 @@ def update_ui(self): self._plugin_manager.send_plugin_message(self._identifier, self.model) # pylint: disable=useless-return - def process_at_command(self, _comm, _phase, command, parameters, *args, **kwargs): - self._logger.info(f"Received @{AT_COMMAND} command with params: {parameters}") + def process_at_command(self, _comm, _phase, command, params_str, *args, **kwargs): + self._logger.info(f"Received @{command} command with params: {params_str}") if command == AT_COMMAND: - index = parameters + [index, target_str, *_] = params_str.split() + [""] * 2 # unpack with default empty strings + target = { "ON": True, "OFF": False }.get(target_str.upper()) # mapped or None if index in RELAY_INDEXES: - self.toggle_relay(index) + self.toggle_relay(index, target) return None # meaning no further actions required def get_update_information(self): diff --git a/tests/test_init.py b/tests/test_init.py index 0854ee9a..09e59f38 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -1082,10 +1082,18 @@ def test_on_api_command__unknown(self, abort_mock): abort_mock.assert_called_with(400, description="Unknown command") def test_process_at_command(self): - # Should toggle the relay having index supplied as a parameter + # Should toggle or switch the relay having index and optional target supplied as a parameters self.plugin_instance.toggle_relay = Mock() - self.assertIsNone(self.plugin_instance.process_at_command(None, None, "OCTORELAY", "r4")) - self.plugin_instance.toggle_relay.assert_called_with("r4") + cases = [ + { "params": "r4", "expected": ["r4", None] }, + { "params": "r4 ON", "expected": ["r4", True] }, + { "params": " r4 off ", "expected": ["r4", False] }, + { "params": " r4 ... ", "expected": ["r4", None] } + ] + for case in cases: + self.plugin_instance.toggle_relay.reset_mock() + self.assertIsNone(self.plugin_instance.process_at_command(None, None, "OCTORELAY", case["params"])) + self.plugin_instance.toggle_relay.assert_called_with(*case["expected"]) def test_get_additional_permissions(self): # Should return the list of the plugin custom permissions