Files
pyasic/miners/miner_factory.py
2021-10-20 13:47:58 -06:00

93 lines
3.2 KiB
Python

from miners.bosminer import BOSminer
from miners.bmminer import BMMiner
from miners.cgminer import CGMiner
from miners.unknown import UnknownMiner
from API import APIError
import asyncio
import ipaddress
import json
class MinerFactory:
def __init__(self):
self.miners = {}
async def get_miner(self, ip: ipaddress.ip_address) -> BOSminer or CGMiner or BMMiner or UnknownMiner:
if ip in self.miners:
return self.miners[ip]
version_data = await self._get_version_data(ip)
version = None
if version_data:
version = list(version_data['VERSION'][0].keys())
if version:
if "BOSminer" in version or "BOSminer+" in version:
miner = BOSminer(str(ip))
elif version == "CGMiner":
miner = CGMiner(str(ip))
elif version == "BMMiner":
miner = BMMiner(str(ip))
else:
miner = UnknownMiner(str(ip))
else:
miner = UnknownMiner(str(ip))
self.miners[ip] = miner
return miner
@staticmethod
async def _get_version_data(ip: ipaddress.ip_address) -> dict or None:
for i in range(3):
try:
fut = asyncio.open_connection(str(ip), 4028)
# get reader and writer streams
reader, writer = await asyncio.wait_for(fut, timeout=5)
# create the command
cmd = {"command": "version"}
# send the command
writer.write(json.dumps(cmd).encode('utf-8'))
await writer.drain()
# instantiate data
data = b""
# loop to receive all the data
while True:
d = await reader.read(4096)
if not d:
break
data += d
data = json.loads(data.decode('utf-8')[:-1])
# close the connection
writer.close()
await writer.wait_closed()
# check if the data returned is correct or an error
# if status isn't a key, it is a multicommand
if "STATUS" not in data.keys():
for key in data.keys():
# make sure not to try to turn id into a dict
if not key == "id":
# make sure they succeeded
if data[key][0]["STATUS"][0]["STATUS"] not in ["S", "I"]:
# this is an error
raise APIError(data["STATUS"][0]["Msg"])
else:
# make sure the command succeeded
if data["STATUS"][0]["STATUS"] not in ("S", "I"):
# this is an error
raise APIError(data["STATUS"][0]["Msg"])
# return the data
return data
except OSError as e:
if e.winerror == 121:
return None
else:
print(ip, e)
except Exception as e:
print(ip, e)
return None