feature: Add support for new whatsminers, and try to handle whatsminer errors when receiving data.
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
22
pyasic/miners/models/whatsminer/M5X/M53S_Plus_Plus.py
Normal file
22
pyasic/miners/models/whatsminer/M5X/M53S_Plus_Plus.py
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
22
pyasic/miners/whatsminer/btminer/M5X/M53S_Plus_Plus.py
Normal file
22
pyasic/miners/whatsminer/btminer/M5X/M53S_Plus_Plus.py
Normal file
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user