@@ -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 :
0 commit comments