From d4b952481460938daab9b089708d3829d9828d9a Mon Sep 17 00:00:00 2001 From: Daan Selen Date: Wed, 10 Sep 2025 16:53:48 +0200 Subject: [PATCH 1/9] feat(lib): draft function for remove_device --- src/meshctrl/session.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/meshctrl/session.py b/src/meshctrl/session.py index f047776..8ef3c40 100644 --- a/src/meshctrl/session.py +++ b/src/meshctrl/session.py @@ -1062,6 +1062,27 @@ class Session(object): raise exceptions.ServerError(data["result"]) return True + async def remove_device(self, nodeids, timeout=None): + ''' + Remove device from MeshCentral + + Args: + nodeids (str|list[str]): nodeid(s) of the device(s) that have to be removed + timeout (int): duration in seconds to wait for a response before throwing an error + + Returns: + bool: True on success, raise otherwise + + Raises: + :py:class:`~meshctrl.exceptions.ServerError`: Error text from server if there is a failure + :py:class:`~meshctrl.exceptions.SocketError`: Info about socket closure + asyncio.TimeoutError: Command timed out + ''' + if isinstance(nodeids, str): + nodeids = [nodeids] + + data = await self._send_command({ "action": 'removedevices', "nodeids": nodeids}, "remove_device_from_server", timeout=timeout) + print(data) async def add_device_group(self, name, description="", amtonly=False, features=0, consent=0, timeout=None): ''' From 1f9979ddd1179c0a6d4fce87e7ae14aa2e399a99 Mon Sep 17 00:00:00 2001 From: Daan Selen Date: Mon, 15 Sep 2025 22:28:57 +0200 Subject: [PATCH 2/9] feat: add remove_device function --- src/meshctrl/session.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/meshctrl/session.py b/src/meshctrl/session.py index 8ef3c40..7b345b5 100644 --- a/src/meshctrl/session.py +++ b/src/meshctrl/session.py @@ -1082,7 +1082,8 @@ class Session(object): nodeids = [nodeids] data = await self._send_command({ "action": 'removedevices', "nodeids": nodeids}, "remove_device_from_server", timeout=timeout) - print(data) + + return data["result"] == "ok" async def add_device_group(self, name, description="", amtonly=False, features=0, consent=0, timeout=None): ''' From c7d628716e16e2ce63e90da26eebe5af3b57e236 Mon Sep 17 00:00:00 2001 From: Daan Selen Date: Tue, 16 Sep 2025 23:12:35 +0200 Subject: [PATCH 3/9] refac: renamed and added device class impl --- src/meshctrl/device.py | 21 +++++++++++++++++++++ src/meshctrl/session.py | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/meshctrl/device.py b/src/meshctrl/device.py index 3efefe8..2b20619 100644 --- a/src/meshctrl/device.py +++ b/src/meshctrl/device.py @@ -295,6 +295,27 @@ class Device(object): ''' return await self._session.reset_devices(self.nodeid, timeout=timeout) + async def remove(self, nodeids, timeout=None): + ''' + Remove device from MeshCentral + + Args: + nodeids (str|list[str]): nodeid(s) of the device(s) that have to be removed + timeout (int): duration in seconds to wait for a response before throwing an error + + Returns: + bool: True on success, raise otherwise + + Raises: + :py:class:`~meshctrl.exceptions.ServerError`: Error text from server if there is a failure + :py:class:`~meshctrl.exceptions.SocketError`: Info about socket closure + asyncio.TimeoutError: Command timed out + ''' + if isinstance(nodeids, str): + nodeids = [nodeids] + + return self._session.remove_devices(self, nodeids, timeout) + async def sleep(self, timeout=None): ''' Sleep device diff --git a/src/meshctrl/session.py b/src/meshctrl/session.py index 7b345b5..57196bd 100644 --- a/src/meshctrl/session.py +++ b/src/meshctrl/session.py @@ -1062,7 +1062,7 @@ class Session(object): raise exceptions.ServerError(data["result"]) return True - async def remove_device(self, nodeids, timeout=None): + async def remove_devices(self, nodeids, timeout=None): ''' Remove device from MeshCentral From 6dae40eb4009fa0add89aeb1907e9c1392418675 Mon Sep 17 00:00:00 2001 From: Daan Selen Date: Tue, 16 Sep 2025 23:14:23 +0200 Subject: [PATCH 4/9] refac: copy other style --- src/meshctrl/device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meshctrl/device.py b/src/meshctrl/device.py index 2b20619..93b40a1 100644 --- a/src/meshctrl/device.py +++ b/src/meshctrl/device.py @@ -314,7 +314,7 @@ class Device(object): if isinstance(nodeids, str): nodeids = [nodeids] - return self._session.remove_devices(self, nodeids, timeout) + return self._session.remove_devices(self.nodeid, timeout) async def sleep(self, timeout=None): ''' From 748e39d5b429ccc500ed939a644df87011bd38ca Mon Sep 17 00:00:00 2001 From: Daan Selen Date: Tue, 16 Sep 2025 23:15:23 +0200 Subject: [PATCH 5/9] refac: remove nodeid parameter --- src/meshctrl/device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meshctrl/device.py b/src/meshctrl/device.py index 93b40a1..adc58b7 100644 --- a/src/meshctrl/device.py +++ b/src/meshctrl/device.py @@ -295,7 +295,7 @@ class Device(object): ''' return await self._session.reset_devices(self.nodeid, timeout=timeout) - async def remove(self, nodeids, timeout=None): + async def remove(self, timeout=None): ''' Remove device from MeshCentral From 7ba6989325eda6c5f539e8ea471dff2733fa02d3 Mon Sep 17 00:00:00 2001 From: Daan Selen Date: Tue, 16 Sep 2025 23:16:59 +0200 Subject: [PATCH 6/9] refac: I lied, this is the last... --- src/meshctrl/device.py | 4 ---- src/meshctrl/session.py | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/meshctrl/device.py b/src/meshctrl/device.py index adc58b7..ee9a651 100644 --- a/src/meshctrl/device.py +++ b/src/meshctrl/device.py @@ -307,13 +307,9 @@ class Device(object): bool: True on success, raise otherwise Raises: - :py:class:`~meshctrl.exceptions.ServerError`: Error text from server if there is a failure :py:class:`~meshctrl.exceptions.SocketError`: Info about socket closure asyncio.TimeoutError: Command timed out ''' - if isinstance(nodeids, str): - nodeids = [nodeids] - return self._session.remove_devices(self.nodeid, timeout) async def sleep(self, timeout=None): diff --git a/src/meshctrl/session.py b/src/meshctrl/session.py index 57196bd..4638863 100644 --- a/src/meshctrl/session.py +++ b/src/meshctrl/session.py @@ -1064,7 +1064,7 @@ class Session(object): async def remove_devices(self, nodeids, timeout=None): ''' - Remove device from MeshCentral + Remove device(s) from MeshCentral Args: nodeids (str|list[str]): nodeid(s) of the device(s) that have to be removed From 9c7a8c39b056e84348975aff4d2759ece706b4fc Mon Sep 17 00:00:00 2001 From: Josiah Baldwin Date: Fri, 26 Sep 2025 15:19:57 -0700 Subject: [PATCH 7/9] Modified some implementation details --- src/meshctrl/session.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/meshctrl/session.py b/src/meshctrl/session.py index 4638863..32740de 100644 --- a/src/meshctrl/session.py +++ b/src/meshctrl/session.py @@ -571,7 +571,7 @@ class Session(object): while True: data = await event_queue.get() if filter and not util.compare_dict(filter, data): - continue + continue yield data finally: self._eventer.off("server_event", _) @@ -1081,9 +1081,11 @@ class Session(object): if isinstance(nodeids, str): nodeids = [nodeids] - data = await self._send_command({ "action": 'removedevices', "nodeids": nodeids}, "remove_device_from_server", timeout=timeout) + data = await self._send_command({ "action": 'removedevices', "nodeids": nodeids}, "remove_devices", timeout=timeout) - return data["result"] == "ok" + if data.get("result", "ok").lower() != "ok": + raise exceptions.ServerError(data["result"]) + return True async def add_device_group(self, name, description="", amtonly=False, features=0, consent=0, timeout=None): ''' From 3bcedf5610cbed1384c19ce447e40500ce029c62 Mon Sep 17 00:00:00 2001 From: Josiah Baldwin Date: Fri, 26 Sep 2025 15:20:25 -0700 Subject: [PATCH 8/9] Kinda added a test for remove device --- tests/test_session.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/test_session.py b/tests/test_session.py index dd1c973..13bd48b 100644 --- a/tests/test_session.py +++ b/tests/test_session.py @@ -336,6 +336,10 @@ async def test_mesh_device(env): r = await admin_session.remove_users_from_device_group((await privileged_session.user_info())["_id"], mesh.meshid, timeout=10) print("\ninfo remove_users_from_device_group: {}\n".format(r)) assert (r[(await privileged_session.user_info())["_id"]]["success"]), "Failed to remove user from device group" + + # Dunno how to test if this actually works, so just check for errors, I guess. + admin_session.remove_devices(agent.nodeid, timeout=10) + assert (await admin_session.remove_users_from_device(agent.nodeid, (await unprivileged_session.user_info())["_id"], timeout=10)), "Failed to remove user from device" From b0d071d87f38b3a8e0229a2566a5dd2c203e7711 Mon Sep 17 00:00:00 2001 From: Daan Selen Date: Mon, 15 Sep 2025 22:28:57 +0200 Subject: [PATCH 9/9] feat: add remove_device function --- src/meshctrl/session.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/meshctrl/session.py b/src/meshctrl/session.py index 32740de..6aebdf1 100644 --- a/src/meshctrl/session.py +++ b/src/meshctrl/session.py @@ -1080,7 +1080,7 @@ class Session(object): ''' if isinstance(nodeids, str): nodeids = [nodeids] - + data = await self._send_command({ "action": 'removedevices', "nodeids": nodeids}, "remove_devices", timeout=timeout) if data.get("result", "ok").lower() != "ok":