From 9343308f413d14aca3689ebe209cc6a7e772b354 Mon Sep 17 00:00:00 2001 From: b-rowan Date: Tue, 30 Jan 2024 21:41:10 -0700 Subject: [PATCH] feature: Add support for new whatsminers, and try to handle whatsminer errors when receiving data. --- pyasic/miners/factory.py | 3 ++ pyasic/miners/models/whatsminer/M5X/M53S.py | 5 +++ .../models/whatsminer/M5X/M53S_Plus_Plus.py | 22 ++++++++++++ .../miners/models/whatsminer/M5X/__init__.py | 3 +- pyasic/miners/whatsminer/btminer/M5X/M53S.py | 6 +++- .../whatsminer/btminer/M5X/M53S_Plus_Plus.py | 22 ++++++++++++ .../miners/whatsminer/btminer/M5X/__init__.py | 3 +- pyasic/rpc/base.py | 36 +++++++++---------- 8 files changed, 78 insertions(+), 22 deletions(-) create mode 100644 pyasic/miners/models/whatsminer/M5X/M53S_Plus_Plus.py create mode 100644 pyasic/miners/whatsminer/btminer/M5X/M53S_Plus_Plus.py diff --git a/pyasic/miners/factory.py b/pyasic/miners/factory.py index 94252067..66959c62 100644 --- a/pyasic/miners/factory.py +++ b/pyasic/miners/factory.py @@ -289,7 +289,9 @@ MINER_CLASSES = { "M50S++VK30": BTMinerM50SPlusPlusVK30, "M53VH30": BTMinerM53VH30, "M53SVH30": BTMinerM53SVH30, + "M53SVJ40": BTMinerM53SVJ40, "M53S+VJ30": BTMinerM53SPlusVJ30, + "M53S++VK10": BTMinerM53SPlusPlusVK10, "M56VH30": BTMinerM56VH30, "M56SVH30": BTMinerM56SVH30, "M56S+VJ30": BTMinerM56SPlusVJ30, @@ -968,6 +970,7 @@ class MinerFactory: miner_factory = MinerFactory() + # abstracted version of get miner that is easier to access async def get_miner(ip: ipaddress.ip_address | str) -> AnyMiner: return await miner_factory.get_miner(ip) diff --git a/pyasic/miners/models/whatsminer/M5X/M53S.py b/pyasic/miners/models/whatsminer/M5X/M53S.py index 344808da..8c86f25e 100644 --- a/pyasic/miners/models/whatsminer/M5X/M53S.py +++ b/pyasic/miners/models/whatsminer/M5X/M53S.py @@ -20,3 +20,8 @@ from pyasic.miners.makes import WhatsMinerMake class M53SVH30(WhatsMinerMake): raw_model = "M53S VH30" expected_fans = 0 + + +class M53SVJ40(WhatsMinerMake): + raw_model = "M53S VJ40" + expected_fans = 0 diff --git a/pyasic/miners/models/whatsminer/M5X/M53S_Plus_Plus.py b/pyasic/miners/models/whatsminer/M5X/M53S_Plus_Plus.py new file mode 100644 index 00000000..eb54a1bd --- /dev/null +++ b/pyasic/miners/models/whatsminer/M5X/M53S_Plus_Plus.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------------------ +# Copyright 2022 Upstream Data Inc - +# - +# Licensed under the Apache License, Version 2.0 (the "License"); - +# you may not use this file except in compliance with the License. - +# You may obtain a copy of the License at - +# - +# http://www.apache.org/licenses/LICENSE-2.0 - +# - +# Unless required by applicable law or agreed to in writing, software - +# distributed under the License is distributed on an "AS IS" BASIS, - +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - +# See the License for the specific language governing permissions and - +# limitations under the License. - +# ------------------------------------------------------------------------------ + +from pyasic.miners.makes import WhatsMinerMake + + +class M53SPlusPlusVK10(WhatsMinerMake): + raw_model = "M53S++ VK10" + expected_fans = 0 diff --git a/pyasic/miners/models/whatsminer/M5X/__init__.py b/pyasic/miners/models/whatsminer/M5X/__init__.py index b50fa464..326774b2 100644 --- a/pyasic/miners/models/whatsminer/M5X/__init__.py +++ b/pyasic/miners/models/whatsminer/M5X/__init__.py @@ -42,8 +42,9 @@ from .M50S import ( from .M50S_Plus import M50SPlusVH30, M50SPlusVH40, M50SPlusVJ30, M50SPlusVK20 from .M50S_Plus_Plus import M50SPlusPlusVK10, M50SPlusPlusVK20, M50SPlusPlusVK30 from .M53 import M53VH30 -from .M53S import M53SVH30 +from .M53S import M53SVH30, M53SVJ40 from .M53S_Plus import M53SPlusVJ30 +from .M53S_Plus_Plus import M53SPlusPlusVK10 from .M56 import M56VH30 from .M56S import M56SVH30 from .M56S_Plus import M56SPlusVJ30 diff --git a/pyasic/miners/whatsminer/btminer/M5X/M53S.py b/pyasic/miners/whatsminer/btminer/M5X/M53S.py index be275849..0766a13a 100644 --- a/pyasic/miners/whatsminer/btminer/M5X/M53S.py +++ b/pyasic/miners/whatsminer/btminer/M5X/M53S.py @@ -15,8 +15,12 @@ # ------------------------------------------------------------------------------ from pyasic.miners.backends import M5X -from pyasic.miners.models import M53SVH30 +from pyasic.miners.models import M53SVH30, M53SVJ40 class BTMinerM53SVH30(M5X, M53SVH30): pass + + +class BTMinerM53SVJ40(M5X, M53SVJ40): + pass diff --git a/pyasic/miners/whatsminer/btminer/M5X/M53S_Plus_Plus.py b/pyasic/miners/whatsminer/btminer/M5X/M53S_Plus_Plus.py new file mode 100644 index 00000000..3c70b233 --- /dev/null +++ b/pyasic/miners/whatsminer/btminer/M5X/M53S_Plus_Plus.py @@ -0,0 +1,22 @@ +# ------------------------------------------------------------------------------ +# Copyright 2022 Upstream Data Inc - +# - +# Licensed under the Apache License, Version 2.0 (the "License"); - +# you may not use this file except in compliance with the License. - +# You may obtain a copy of the License at - +# - +# http://www.apache.org/licenses/LICENSE-2.0 - +# - +# Unless required by applicable law or agreed to in writing, software - +# distributed under the License is distributed on an "AS IS" BASIS, - +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - +# See the License for the specific language governing permissions and - +# limitations under the License. - +# ------------------------------------------------------------------------------ + +from pyasic.miners.backends import M5X +from pyasic.miners.models import M53SPlusPlusVK10 + + +class BTMinerM53SPlusPlusVK10(M5X, M53SPlusPlusVK10): + pass diff --git a/pyasic/miners/whatsminer/btminer/M5X/__init__.py b/pyasic/miners/whatsminer/btminer/M5X/__init__.py index bfb4ea56..0e1790a9 100644 --- a/pyasic/miners/whatsminer/btminer/M5X/__init__.py +++ b/pyasic/miners/whatsminer/btminer/M5X/__init__.py @@ -51,8 +51,9 @@ from .M50S_Plus_Plus import ( BTMinerM50SPlusPlusVK30, ) from .M53 import BTMinerM53VH30 -from .M53S import BTMinerM53SVH30 +from .M53S import BTMinerM53SVH30, BTMinerM53SVJ40 from .M53S_Plus import BTMinerM53SPlusVJ30 +from .M53S_Plus_Plus import BTMinerM53SPlusPlusVK10 from .M56 import BTMinerM56VH30 from .M56S import BTMinerM56SVH30 from .M56S_Plus import BTMinerM56SPlusVJ30 diff --git a/pyasic/rpc/base.py b/pyasic/rpc/base.py index ccfeeb68..9238873f 100644 --- a/pyasic/rpc/base.py +++ b/pyasic/rpc/base.py @@ -78,6 +78,9 @@ class BaseMinerRPCAPI: # send the command data = await self._send_bytes(json.dumps(cmd).encode("utf-8")) + if data is None: + raise APIError("No data returned from the API.") + if data == b"Socket connect failed: Connection refused\n": if not ignore_errors: raise APIError(data.decode("utf-8")) @@ -208,23 +211,24 @@ If you are sure you want to use this command please use API.send_command("{comma return b"{}" # send the command + data_task = asyncio.create_task(self._read_bytes(reader, timeout=timeout)) logging.debug(f"{self} - ([Hidden] Send Bytes) - Writing") writer.write(data) logging.debug(f"{self} - ([Hidden] Send Bytes) - Draining") await writer.drain() - try: - # TO address a situation where a whatsminer has an unknown PW -AND- - # Fix for stupid whatsminer bug, reboot/restart seem to not load properly in the loop - # have to receive, save the data, check if there is more data by reading with a short timeout - # append that data if there is more, and then onto the main loop. - # the password timeout might need to be longer than 1, but it seems to work for now. - ret_data = await asyncio.wait_for(reader.read(1), timeout=1) - except asyncio.TimeoutError: - return b"{}" - try: - ret_data += await asyncio.wait_for(reader.read(4096), timeout=timeout) - except ConnectionAbortedError: - return b"{}" + + await data_task + ret_data = data_task.result() + + # close the connection + logging.debug(f"{self} - ([Hidden] Send Bytes) - Closing") + writer.close() + await writer.wait_closed() + + return ret_data + + async def _read_bytes(self, reader: asyncio.StreamReader, timeout: int) -> bytes: + ret_data = b"" # loop to receive all the data logging.debug(f"{self} - ([Hidden] Send Bytes) - Receiving") @@ -241,12 +245,6 @@ If you are sure you want to use this command please use API.send_command("{comma raise e except Exception as e: logging.warning(f"{self} - ([Hidden] Send Bytes) - API Command Error {e}") - - # close the connection - logging.debug(f"{self} - ([Hidden] Send Bytes) - Closing") - writer.close() - await writer.wait_closed() - return ret_data @staticmethod