Skip to content
This repository was archived by the owner on Jul 6, 2026. It is now read-only.

Commit c8e2489

Browse files
bugy855jamaalpre-commit-ci[bot]
authored
fix v3 btminers timing out when getting their data (#422)
Co-authored-by: jamaal <jamaal@sustainhash.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 79b98a5 commit c8e2489

2 files changed

Lines changed: 66 additions & 2 deletions

File tree

pyasic/miners/factory.py

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -956,8 +956,16 @@ async def _get_miner_socket(self, ip: str) -> MinerTypes | None:
956956
lambda x: x is not None and self._parse_socket_type(x) is not None,
957957
)
958958
if data is not None:
959-
d = self._parse_socket_type(data)
960-
return d
959+
return self._parse_socket_type(data)
960+
961+
data_v3 = await self._socket_ping_btminer_v3(ip, "get.device.info")
962+
if data_v3 is not None:
963+
try:
964+
parsed = json.loads(data_v3)
965+
if isinstance(parsed.get("msg"), dict) and "miner" in parsed["msg"]:
966+
return MinerTypes.WHATSMINER
967+
except (json.JSONDecodeError, AttributeError):
968+
pass
961969
return None
962970

963971
@staticmethod
@@ -1011,6 +1019,51 @@ async def _socket_ping(ip: str, cmd: str) -> str | None:
10111019
return data.decode("utf-8")
10121020
return None
10131021

1022+
@staticmethod
1023+
async def _socket_ping_btminer_v3(ip: str, cmd: str) -> str | None:
1024+
try:
1025+
reader, writer = await asyncio.wait_for(
1026+
asyncio.open_connection(str(ip), 4433),
1027+
timeout=settings.get("factory_get_timeout", 3),
1028+
)
1029+
except (ConnectionError, OSError, asyncio.TimeoutError):
1030+
return None
1031+
1032+
command_dict = {"cmd": cmd}
1033+
json_cmd = json.dumps(command_dict).encode("utf-8")
1034+
try:
1035+
writer.write(len(json_cmd).to_bytes(4, byteorder="little"))
1036+
writer.write(json_cmd)
1037+
await writer.drain()
1038+
1039+
resp_len_bytes = await asyncio.wait_for(
1040+
reader.readexactly(4),
1041+
timeout=settings.get("btminer_v3_ping_timeout", 1),
1042+
)
1043+
data = await asyncio.wait_for(
1044+
reader.readexactly(int.from_bytes(resp_len_bytes, byteorder="little")),
1045+
timeout=settings.get("factory_get_timeout", 3),
1046+
)
1047+
except (
1048+
ConnectionError,
1049+
OSError,
1050+
asyncio.TimeoutError,
1051+
asyncio.IncompleteReadError,
1052+
):
1053+
return None
1054+
except asyncio.CancelledError:
1055+
raise
1056+
finally:
1057+
writer.close()
1058+
try:
1059+
await writer.wait_closed()
1060+
except (ConnectionError, OSError):
1061+
pass
1062+
1063+
if data:
1064+
return data.decode("utf-8")
1065+
return None
1066+
10141067
@staticmethod
10151068
def _parse_socket_type(data: str) -> MinerTypes | None:
10161069
upper_data = data.upper()
@@ -1308,6 +1361,16 @@ async def get_miner_version_whatsminer(self, ip: str) -> str | None:
13081361
return version
13091362
except LookupError:
13101363
pass
1364+
1365+
sock_json_data_v3 = await self.send_btminer_v3_api_command(
1366+
ip, "get.device.info"
1367+
)
1368+
if sock_json_data_v3 is not None:
1369+
try:
1370+
version = sock_json_data_v3["msg"]["system"]["fwversion"]
1371+
return version
1372+
except (TypeError, LookupError):
1373+
pass
13111374
return None
13121375

13131376
async def get_miner_model_avalonminer(self, ip: str) -> str | None:

pyasic/settings/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class Settings(BaseModel):
2727
network_scan_semaphore: int | None = Field(default=None)
2828
factory_get_retries: int = Field(default=1)
2929
factory_get_timeout: int = Field(default=3)
30+
btminer_v3_ping_timeout: int = Field(default=1)
3031
get_data_retries: int = Field(default=1)
3132
api_function_timeout: int = Field(default=5)
3233
antminer_mining_mode_as_str: bool = Field(default=False)

0 commit comments

Comments
 (0)