improved format and readability
This commit is contained in:
@@ -18,18 +18,25 @@ class APIError(Exception):
|
|||||||
|
|
||||||
|
|
||||||
class BaseMinerAPI:
|
class BaseMinerAPI:
|
||||||
def __init__(self, ip: str, port: int):
|
def __init__(self, ip: str, port: int) -> None:
|
||||||
self.port = port
|
self.port = port
|
||||||
self.ip = ipaddress.ip_address(ip)
|
self.ip = ipaddress.ip_address(ip)
|
||||||
|
|
||||||
def get_commands(self):
|
def get_commands(self) -> list:
|
||||||
return [func for func in dir(self) if callable(getattr(self, func)) and not func.startswith("__") and func not in [func for func in dir(BaseMinerAPI) if callable(getattr(BaseMinerAPI, func))]]
|
return [func for func in
|
||||||
|
dir(self) if callable(getattr(self, func)) and
|
||||||
|
not func.startswith("__") and
|
||||||
|
func not in
|
||||||
|
[func for func in
|
||||||
|
dir(BaseMinerAPI) if callable(getattr(BaseMinerAPI, func))
|
||||||
|
]
|
||||||
|
]
|
||||||
|
|
||||||
async def multicommand(self, *commands: str) -> dict:
|
async def multicommand(self, *commands: str) -> dict:
|
||||||
command = "+".join(commands)
|
command = "+".join(commands)
|
||||||
return await self.send_command(command)
|
return await self.send_command(command)
|
||||||
|
|
||||||
async def send_command(self, command: str, parameters: str = None) -> dict:
|
async def send_command(self, command: str, parameters: str or int or bool = None) -> dict:
|
||||||
try:
|
try:
|
||||||
# get reader and writer streams
|
# get reader and writer streams
|
||||||
reader, writer = await asyncio.open_connection(str(self.ip), self.port)
|
reader, writer = await asyncio.open_connection(str(self.ip), self.port)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from API import BaseMinerAPI
|
|||||||
|
|
||||||
|
|
||||||
class BMMinerAPI(BaseMinerAPI):
|
class BMMinerAPI(BaseMinerAPI):
|
||||||
def __init__(self, ip, port=4028):
|
def __init__(self, ip: str, port: int = 4028) -> None:
|
||||||
super().__init__(ip, port)
|
super().__init__(ip, port)
|
||||||
|
|
||||||
async def version(self) -> dict:
|
async def version(self) -> dict:
|
||||||
@@ -42,7 +42,7 @@ class BMMinerAPI(BaseMinerAPI):
|
|||||||
return await self.send_command("addpool", parameters=f"{url}, {username}, {password}")
|
return await self.send_command("addpool", parameters=f"{url}, {username}, {password}")
|
||||||
|
|
||||||
async def poolpriority(self, *n: int) -> dict:
|
async def poolpriority(self, *n: int) -> dict:
|
||||||
return await self.send_command("poolpriority", parameters=f"{','.join(n)}")
|
return await self.send_command("poolpriority", parameters=f"{','.join([str(item) for item in n])}")
|
||||||
|
|
||||||
async def poolquota(self, n: int, q: int) -> dict:
|
async def poolquota(self, n: int, q: int) -> dict:
|
||||||
return await self.send_command("poolquota", parameters=f"{n}, {q}")
|
return await self.send_command("poolquota", parameters=f"{n}, {q}")
|
||||||
@@ -96,7 +96,7 @@ class BMMinerAPI(BaseMinerAPI):
|
|||||||
return await self.send_command("check", parameters=command)
|
return await self.send_command("check", parameters=command)
|
||||||
|
|
||||||
async def failover_only(self, failover: bool) -> dict:
|
async def failover_only(self, failover: bool) -> dict:
|
||||||
return self.send_command("failover-only", parameters=failover)
|
return await self.send_command("failover-only", parameters=failover)
|
||||||
|
|
||||||
async def coin(self) -> dict:
|
async def coin(self) -> dict:
|
||||||
return await self.send_command("coin")
|
return await self.send_command("coin")
|
||||||
|
|||||||
@@ -49,27 +49,27 @@ class BOSMinerAPI(BaseMinerAPI):
|
|||||||
|
|
||||||
async def switchpool(self, n: int) -> dict:
|
async def switchpool(self, n: int) -> dict:
|
||||||
# BOS has not implemented this yet, they will in the future
|
# BOS has not implemented this yet, they will in the future
|
||||||
return NotImplementedError
|
raise NotImplementedError
|
||||||
# return await self.send_command("switchpool", parameters=n)
|
# return await self.send_command("switchpool", parameters=n)
|
||||||
|
|
||||||
async def enablepool(self, n: int) -> dict:
|
async def enablepool(self, n: int) -> dict:
|
||||||
# BOS has not implemented this yet, they will in the future
|
# BOS has not implemented this yet, they will in the future
|
||||||
return NotImplementedError
|
raise NotImplementedError
|
||||||
# return await self.send_command("enablepool", parameters=n)
|
# return await self.send_command("enablepool", parameters=n)
|
||||||
|
|
||||||
async def disablepool(self, n: int) -> dict:
|
async def disablepool(self, n: int) -> dict:
|
||||||
# BOS has not implemented this yet, they will in the future
|
# BOS has not implemented this yet, they will in the future
|
||||||
return NotImplementedError
|
raise NotImplementedError
|
||||||
# return await self.send_command("disablepool", parameters=n)
|
# return await self.send_command("disablepool", parameters=n)
|
||||||
|
|
||||||
async def addpool(self, url: str, username: str, password: str) -> dict:
|
async def addpool(self, url: str, username: str, password: str) -> dict:
|
||||||
# BOS has not implemented this yet, they will in the future
|
# BOS has not implemented this yet, they will in the future
|
||||||
return NotImplementedError
|
raise NotImplementedError
|
||||||
# return await self.send_command("addpool", parameters=f"{url}, {username}, {password}")
|
# return await self.send_command("addpool", parameters=f"{url}, {username}, {password}")
|
||||||
|
|
||||||
async def removepool(self, n: int) -> dict:
|
async def removepool(self, n: int) -> dict:
|
||||||
# BOS has not implemented this yet, they will in the future
|
# BOS has not implemented this yet, they will in the future
|
||||||
return NotImplementedError
|
raise NotImplementedError
|
||||||
# return await self.send_command("removepool", parameters=n)
|
# return await self.send_command("removepool", parameters=n)
|
||||||
|
|
||||||
async def fans(self) -> dict:
|
async def fans(self) -> dict:
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ class CGMinerAPI(BaseMinerAPI):
|
|||||||
return await self.send_command("addpool", parameters=f"{url}, {username}, {password}")
|
return await self.send_command("addpool", parameters=f"{url}, {username}, {password}")
|
||||||
|
|
||||||
async def poolpriority(self, *n: int) -> dict:
|
async def poolpriority(self, *n: int) -> dict:
|
||||||
return await self.send_command("poolpriority", parameters=f"{','.join(n)}")
|
return await self.send_command("poolpriority", parameters=f"{','.join([str(item) for item in n])}")
|
||||||
|
|
||||||
async def poolquota(self, n: int, q: int) -> dict:
|
async def poolquota(self, n: int, q: int) -> dict:
|
||||||
return await self.send_command("poolquota", parameters=f"{n}, {q}")
|
return await self.send_command("poolquota", parameters=f"{n}, {q}")
|
||||||
@@ -93,7 +93,7 @@ class CGMinerAPI(BaseMinerAPI):
|
|||||||
return await self.send_command("check", parameters=command)
|
return await self.send_command("check", parameters=command)
|
||||||
|
|
||||||
async def failover_only(self, failover: bool) -> dict:
|
async def failover_only(self, failover: bool) -> dict:
|
||||||
return self.send_command("failover-only", parameters=failover)
|
return await self.send_command("failover-only", parameters=failover)
|
||||||
|
|
||||||
async def coin(self) -> dict:
|
async def coin(self) -> dict:
|
||||||
return await self.send_command("coin")
|
return await self.send_command("coin")
|
||||||
|
|||||||
@@ -49,25 +49,25 @@ class UnknownAPI(BaseMinerAPI):
|
|||||||
|
|
||||||
async def switchpool(self, n: int) -> dict:
|
async def switchpool(self, n: int) -> dict:
|
||||||
# BOS has not implemented this yet, they will in the future
|
# BOS has not implemented this yet, they will in the future
|
||||||
return NotImplementedError
|
raise NotImplementedError
|
||||||
# return await self.send_command("switchpool", parameters=n)
|
# return await self.send_command("switchpool", parameters=n)
|
||||||
|
|
||||||
async def enablepool(self, n: int) -> dict:
|
async def enablepool(self, n: int) -> dict:
|
||||||
# BOS has not implemented this yet, they will in the future
|
# BOS has not implemented this yet, they will in the future
|
||||||
return NotImplementedError
|
raise NotImplementedError
|
||||||
# return await self.send_command("enablepool", parameters=n)
|
# return await self.send_command("enablepool", parameters=n)
|
||||||
|
|
||||||
async def disablepool(self, n: int) -> dict:
|
async def disablepool(self, n: int) -> dict:
|
||||||
# BOS has not implemented this yet, they will in the future
|
# BOS has not implemented this yet, they will in the future
|
||||||
return NotImplementedError
|
raise NotImplementedError
|
||||||
# return await self.send_command("disablepool", parameters=n)
|
# return await self.send_command("disablepool", parameters=n)
|
||||||
|
|
||||||
async def addpool(self, url: str, username: str, password: str) -> dict:
|
async def addpool(self, url: str, username: str, password: str) -> dict:
|
||||||
# BOS has not implemented this yet, they will in the future
|
# BOS has not implemented this yet, they will in the future
|
||||||
return NotImplementedError
|
raise NotImplementedError
|
||||||
# return await self.send_command("addpool", parameters=f"{url}, {username}, {password}")
|
# return await self.send_command("addpool", parameters=f"{url}, {username}, {password}")
|
||||||
|
|
||||||
async def removepool(self, n: int) -> dict:
|
async def removepool(self, n: int) -> dict:
|
||||||
# BOS has not implemented this yet, they will in the future
|
# BOS has not implemented this yet, they will in the future
|
||||||
return NotImplementedError
|
raise NotImplementedError
|
||||||
# return await self.send_command("removepool", parameters=n)
|
# return await self.send_command("removepool", parameters=n)
|
||||||
|
|||||||
@@ -28,7 +28,8 @@ layout = [
|
|||||||
[sg.Listbox([], size=(20, 32), key="ip_list", select_mode='extended')]
|
[sg.Listbox([], size=(20, 32), key="ip_list", select_mode='extended')]
|
||||||
]),
|
]),
|
||||||
sg.Column([
|
sg.Column([
|
||||||
[sg.Text("Data: ", pad=(0, 0)), sg.Button('GET', key="get_data"), sg.Button('SORT IP', key="sort_data_ip"), sg.Button('SORT HR', key="sort_data_hr"), sg.Button('SORT USER', key="sort_data_user")],
|
[sg.Text("Data: ", pad=(0, 0)), sg.Button('GET', key="get_data"), sg.Button('SORT IP', key="sort_data_ip"),
|
||||||
|
sg.Button('SORT HR', key="sort_data_hr"), sg.Button('SORT USER', key="sort_data_user")],
|
||||||
[sg.Listbox([], size=(50, 32), key="hr_list")]
|
[sg.Listbox([], size=(50, 32), key="hr_list")]
|
||||||
]),
|
]),
|
||||||
sg.Column([
|
sg.Column([
|
||||||
@@ -146,17 +147,18 @@ async def get_data(ip_list: list):
|
|||||||
ips.sort()
|
ips.sort()
|
||||||
data = await asyncio.gather(*[get_formatted_data(miner) for miner in ips])
|
data = await asyncio.gather(*[get_formatted_data(miner) for miner in ips])
|
||||||
window["hr_list"].update(disabled=False)
|
window["hr_list"].update(disabled=False)
|
||||||
window["hr_list"].update([item['IP'] + " | " + str(item['TH/s']) + " TH/s | " + item['user'] for item in data])
|
window["hr_list"].update([item['IP'] + " | " + str(item['TH/s']) + " TH/s | " + item['user'] + " | " + str(item['wattage']) + " W" for item in data])
|
||||||
window["hr_list"].update(disabled=True)
|
window["hr_list"].update(disabled=True)
|
||||||
await update_ui_with_data("status", "")
|
await update_ui_with_data("status", "")
|
||||||
|
|
||||||
|
|
||||||
async def get_formatted_data(ip: ipaddress.ip_address):
|
async def get_formatted_data(ip: ipaddress.ip_address):
|
||||||
miner = await miner_factory.get_miner(ip)
|
miner = await miner_factory.get_miner(ip)
|
||||||
data = await miner.api.multicommand("summary", "pools")
|
data = await miner.api.multicommand("summary", "pools", "tunerstatus")
|
||||||
|
wattage = data['tunerstatus'][0]['TUNERSTATUS'][0]['PowerLimit']
|
||||||
mh5s = round(data['summary'][0]['SUMMARY'][0]['MHS 5s'] / 1000000, 2)
|
mh5s = round(data['summary'][0]['SUMMARY'][0]['MHS 5s'] / 1000000, 2)
|
||||||
user = data['pools'][0]['POOLS'][0]['User']
|
user = data['pools'][0]['POOLS'][0]['User']
|
||||||
return {'TH/s': mh5s, 'IP': str(miner.ip), 'user': user}
|
return {'TH/s': mh5s, 'IP': str(miner.ip), 'user': user, 'wattage': wattage}
|
||||||
|
|
||||||
|
|
||||||
async def generate_config():
|
async def generate_config():
|
||||||
@@ -195,12 +197,14 @@ async def generate_config():
|
|||||||
}
|
}
|
||||||
window['config'].update(toml.dumps(config))
|
window['config'].update(toml.dumps(config))
|
||||||
|
|
||||||
|
|
||||||
async def sort_data(index: int):
|
async def sort_data(index: int):
|
||||||
await update_ui_with_data("status", "Sorting Data")
|
await update_ui_with_data("status", "Sorting Data")
|
||||||
data_list = window['hr_list'].Values
|
data_list = window['hr_list'].Values
|
||||||
new_list = []
|
new_list = []
|
||||||
for item in data_list:
|
for item in data_list:
|
||||||
item_data = [part.strip() for part in item.split("|")]
|
item_data = [part.strip() for part in item.split("|")]
|
||||||
|
item_data[3] = item_data[3].replace(" W", "")
|
||||||
item_data[1] = item_data[1].replace(" TH/s", "")
|
item_data[1] = item_data[1].replace(" TH/s", "")
|
||||||
item_data[0] = ipaddress.ip_address(item_data[0])
|
item_data[0] = ipaddress.ip_address(item_data[0])
|
||||||
new_list.append(item_data)
|
new_list.append(item_data)
|
||||||
@@ -208,7 +212,11 @@ async def sort_data(index: int):
|
|||||||
new_data_list = sorted(new_list, key=lambda x: float(x[index]))
|
new_data_list = sorted(new_list, key=lambda x: float(x[index]))
|
||||||
else:
|
else:
|
||||||
new_data_list = sorted(new_list, key=itemgetter(index))
|
new_data_list = sorted(new_list, key=itemgetter(index))
|
||||||
new_data_list = [str(item[0]) + " | " + item[1] + " TH/s | " + item[2] for item in new_data_list]
|
new_data_list = [str(item[0]) + " | "
|
||||||
|
+ item[1] + " TH/s | "
|
||||||
|
+ item[2] + " | "
|
||||||
|
+ str(item[3]) + " W"
|
||||||
|
for item in new_data_list]
|
||||||
window["hr_list"].update(disabled=False)
|
window["hr_list"].update(disabled=False)
|
||||||
window["hr_list"].update(new_data_list)
|
window["hr_list"].update(new_data_list)
|
||||||
window["hr_list"].update(disabled=True)
|
window["hr_list"].update(disabled=True)
|
||||||
|
|||||||
1
main.py
1
main.py
@@ -12,6 +12,7 @@ async def main():
|
|||||||
print(len(good_list))
|
print(len(good_list))
|
||||||
# print('\n'.join([f"{str(miner.ip)}" for miner in miners]))
|
# print('\n'.join([f"{str(miner.ip)}" for miner in miners]))
|
||||||
|
|
||||||
|
|
||||||
async def main_bad():
|
async def main_bad():
|
||||||
miner_network = MinerNetwork('192.168.1.1')
|
miner_network = MinerNetwork('192.168.1.1')
|
||||||
miners = await miner_network.scan_network_for_miners()
|
miners = await miner_network.scan_network_for_miners()
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
from API import BaseMinerAPI
|
from API.bmminer import BMMinerAPI
|
||||||
|
from API.bosminer import BOSMinerAPI
|
||||||
|
from API.cgminer import CGMinerAPI
|
||||||
import ipaddress
|
import ipaddress
|
||||||
import typing
|
|
||||||
|
|
||||||
|
|
||||||
class BaseMiner:
|
class BaseMiner:
|
||||||
def __init__(self, ip: str, api: typing.Type[BaseMinerAPI]):
|
def __init__(self, ip: str, api: BMMinerAPI or BOSMinerAPI or CGMinerAPI) -> None:
|
||||||
self.ip = ipaddress.ip_address(ip)
|
self.ip = ipaddress.ip_address(ip)
|
||||||
self.api = api
|
self.api = api
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ from miners import BaseMiner
|
|||||||
|
|
||||||
|
|
||||||
class BMMiner(BaseMiner):
|
class BMMiner(BaseMiner):
|
||||||
def __init__(self, ip: str):
|
def __init__(self, ip: str) -> None:
|
||||||
api = BMMinerAPI(ip)
|
api = BMMinerAPI(ip)
|
||||||
super().__init__(ip, api)
|
super().__init__(ip, api)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return f"BMMiner: {str(self.ip)}"
|
return f"BMMiner: {str(self.ip)}"
|
||||||
|
|
||||||
async def send_config(self):
|
async def send_config(self):
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ import time
|
|||||||
|
|
||||||
|
|
||||||
class BOSminer(BaseMiner):
|
class BOSminer(BaseMiner):
|
||||||
def __init__(self, ip: str):
|
def __init__(self, ip: str) -> None:
|
||||||
api = BOSMinerAPI(ip)
|
api = BOSMinerAPI(ip)
|
||||||
super().__init__(ip, api)
|
super().__init__(ip, api)
|
||||||
self.config = None
|
self.config = None
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return f"BOSminer: {str(self.ip)}"
|
return f"BOSminer: {str(self.ip)}"
|
||||||
|
|
||||||
async def get_ssh_connection(self, username: str, password: str) -> asyncssh.connect:
|
async def get_ssh_connection(self, username: str, password: str) -> asyncssh.connect:
|
||||||
@@ -21,7 +21,7 @@ class BOSminer(BaseMiner):
|
|||||||
# return created connection
|
# return created connection
|
||||||
return conn
|
return conn
|
||||||
|
|
||||||
async def send_ssh_command(self, cmd):
|
async def send_ssh_command(self, cmd: str) -> None:
|
||||||
result = None
|
result = None
|
||||||
conn = await self.get_ssh_connection('root', 'admin')
|
conn = await self.get_ssh_connection('root', 'admin')
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
@@ -43,19 +43,19 @@ class BOSminer(BaseMiner):
|
|||||||
else:
|
else:
|
||||||
print(cmd)
|
print(cmd)
|
||||||
|
|
||||||
async def fault_light_on(self):
|
async def fault_light_on(self) -> None:
|
||||||
await self.send_ssh_command('miner fault_light on')
|
await self.send_ssh_command('miner fault_light on')
|
||||||
|
|
||||||
async def fault_light_off(self):
|
async def fault_light_off(self) -> None:
|
||||||
await self.send_ssh_command('miner fault_light off')
|
await self.send_ssh_command('miner fault_light off')
|
||||||
|
|
||||||
async def bosminer_restart(self):
|
async def bosminer_restart(self) -> None:
|
||||||
await self.send_ssh_command('/etc/init.d/bosminer restart')
|
await self.send_ssh_command('/etc/init.d/bosminer restart')
|
||||||
|
|
||||||
async def reboot(self):
|
async def reboot(self) -> None:
|
||||||
await self.send_ssh_command('/sbin/reboot')
|
await self.send_ssh_command('/sbin/reboot')
|
||||||
|
|
||||||
async def get_config(self):
|
async def get_config(self) -> None:
|
||||||
async with asyncssh.connect(str(self.ip), known_hosts=None, username='root', password='admin',
|
async with asyncssh.connect(str(self.ip), known_hosts=None, username='root', password='admin',
|
||||||
server_host_key_algs=['ssh-rsa']) as conn:
|
server_host_key_algs=['ssh-rsa']) as conn:
|
||||||
async with conn.start_sftp_client() as sftp:
|
async with conn.start_sftp_client() as sftp:
|
||||||
@@ -63,10 +63,10 @@ class BOSminer(BaseMiner):
|
|||||||
toml_data = toml.loads(await file.read())
|
toml_data = toml.loads(await file.read())
|
||||||
self.config = toml_data
|
self.config = toml_data
|
||||||
|
|
||||||
def update_config(self, config: dict):
|
def update_config(self, config: dict) -> None:
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
||||||
async def change_config_format(self, update_config: bool = False):
|
async def change_config_format(self, update_config: bool = False) -> dict:
|
||||||
if not self.config:
|
if not self.config:
|
||||||
await self.get_config()
|
await self.get_config()
|
||||||
config = self.config
|
config = self.config
|
||||||
@@ -76,7 +76,7 @@ class BOSminer(BaseMiner):
|
|||||||
self.update_config(config)
|
self.update_config(config)
|
||||||
return config
|
return config
|
||||||
|
|
||||||
async def change_config_tuning(self, wattage: int, enabled: bool = True, update_config: bool = False):
|
async def change_config_tuning(self, wattage: int, enabled: bool = True, update_config: bool = False) -> dict:
|
||||||
if not self.config:
|
if not self.config:
|
||||||
await self.get_config()
|
await self.get_config()
|
||||||
config = self.config
|
config = self.config
|
||||||
@@ -87,7 +87,7 @@ class BOSminer(BaseMiner):
|
|||||||
return config
|
return config
|
||||||
|
|
||||||
async def change_config_temp_ctrl(self, target: float = 80.0, hot: float = 100.0,
|
async def change_config_temp_ctrl(self, target: float = 80.0, hot: float = 100.0,
|
||||||
dangerous: float = 110.0, update_config: bool = False):
|
dangerous: float = 110.0, update_config: bool = False) -> dict:
|
||||||
if not self.config:
|
if not self.config:
|
||||||
await self.get_config()
|
await self.get_config()
|
||||||
config = self.config
|
config = self.config
|
||||||
@@ -98,7 +98,7 @@ class BOSminer(BaseMiner):
|
|||||||
self.update_config(config)
|
self.update_config(config)
|
||||||
return config
|
return config
|
||||||
|
|
||||||
async def send_config(self, config):
|
async def send_config(self, config: dict) -> None:
|
||||||
toml_conf = toml.dumps(config)
|
toml_conf = toml.dumps(config)
|
||||||
async with asyncssh.connect(str(self.ip), known_hosts=None, username='root', password='admin',
|
async with asyncssh.connect(str(self.ip), known_hosts=None, username='root', password='admin',
|
||||||
server_host_key_algs=['ssh-rsa']) as conn:
|
server_host_key_algs=['ssh-rsa']) as conn:
|
||||||
@@ -107,7 +107,7 @@ class BOSminer(BaseMiner):
|
|||||||
await file.write(toml_conf)
|
await file.write(toml_conf)
|
||||||
await conn.run("/etc/init.d/bosminer restart")
|
await conn.run("/etc/init.d/bosminer restart")
|
||||||
|
|
||||||
async def get_bad_boards(self):
|
async def get_bad_boards(self) -> list:
|
||||||
devs = await self.api.devdetails()
|
devs = await self.api.devdetails()
|
||||||
bad = 0
|
bad = 0
|
||||||
chains = devs['DEVDETAILS']
|
chains = devs['DEVDETAILS']
|
||||||
@@ -115,9 +115,9 @@ class BOSminer(BaseMiner):
|
|||||||
if chain['Chips'] == 0:
|
if chain['Chips'] == 0:
|
||||||
bad += 1
|
bad += 1
|
||||||
if bad > 0:
|
if bad > 0:
|
||||||
return (str(self.ip), bad)
|
return [str(self.ip), bad]
|
||||||
|
|
||||||
async def check_good_boards(self):
|
async def check_good_boards(self) -> str:
|
||||||
devs = await self.api.devdetails()
|
devs = await self.api.devdetails()
|
||||||
bad = 0
|
bad = 0
|
||||||
chains = devs['DEVDETAILS']
|
chains = devs['DEVDETAILS']
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ from miners import BaseMiner
|
|||||||
|
|
||||||
|
|
||||||
class CGMiner(BaseMiner):
|
class CGMiner(BaseMiner):
|
||||||
def __init__(self, ip: str):
|
def __init__(self, ip: str) -> None:
|
||||||
api = CGMinerAPI(ip)
|
api = CGMinerAPI(ip)
|
||||||
super().__init__(ip, api)
|
super().__init__(ip, api)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return f"CGMiner: {str(self.ip)}"
|
return f"CGMiner: {str(self.ip)}"
|
||||||
|
|
||||||
async def send_config(self):
|
async def send_config(self):
|
||||||
|
|||||||
@@ -6,14 +6,13 @@ from API import APIError
|
|||||||
import asyncio
|
import asyncio
|
||||||
import ipaddress
|
import ipaddress
|
||||||
import json
|
import json
|
||||||
import typing
|
|
||||||
|
|
||||||
|
|
||||||
class MinerFactory:
|
class MinerFactory:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.miners = {}
|
self.miners = {}
|
||||||
|
|
||||||
async def get_miner(self, ip: ipaddress.ip_address):
|
async def get_miner(self, ip: ipaddress.ip_address) -> BOSminer or CGMiner or BMMiner or UnknownMiner:
|
||||||
if ip in self.miners:
|
if ip in self.miners:
|
||||||
return self.miners[ip]
|
return self.miners[ip]
|
||||||
version_data = await self._get_version_data(ip)
|
version_data = await self._get_version_data(ip)
|
||||||
@@ -35,7 +34,7 @@ class MinerFactory:
|
|||||||
return miner
|
return miner
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def _get_version_data(ip: ipaddress.ip_address):
|
async def _get_version_data(ip: ipaddress.ip_address) -> dict or None:
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
try:
|
try:
|
||||||
fut = asyncio.open_connection(str(ip), 4028)
|
fut = asyncio.open_connection(str(ip), 4028)
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ from miners import BaseMiner
|
|||||||
|
|
||||||
|
|
||||||
class UnknownMiner(BaseMiner):
|
class UnknownMiner(BaseMiner):
|
||||||
def __init__(self, ip: str):
|
def __init__(self, ip: str) -> None:
|
||||||
api = UnknownAPI(ip)
|
api = UnknownAPI(ip)
|
||||||
super().__init__(ip, api)
|
super().__init__(ip, api)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self) -> str:
|
||||||
return f"Unknown: {str(self.ip)}"
|
return f"Unknown: {str(self.ip)}"
|
||||||
|
|
||||||
async def send_config(self):
|
async def send_config(self):
|
||||||
|
|||||||
@@ -2,20 +2,24 @@ import netifaces
|
|||||||
import ipaddress
|
import ipaddress
|
||||||
import asyncio
|
import asyncio
|
||||||
from miners.miner_factory import MinerFactory
|
from miners.miner_factory import MinerFactory
|
||||||
|
from miners.bmminer import BMMiner
|
||||||
|
from miners.bosminer import BOSminer
|
||||||
|
from miners.cgminer import CGMiner
|
||||||
|
from miners.unknown import UnknownMiner
|
||||||
|
|
||||||
PING_RETRIES: int = 3
|
PING_RETRIES: int = 3
|
||||||
PING_TIMEOUT: int = 1
|
PING_TIMEOUT: int = 1
|
||||||
|
|
||||||
|
|
||||||
class MinerNetwork:
|
class MinerNetwork:
|
||||||
def __init__(self, ip_addr=None, mask=None):
|
def __init__(self, ip_addr: str or None = None, mask: str or int or None = None) -> None:
|
||||||
self.network = None
|
self.network = None
|
||||||
self.miner_factory = MinerFactory()
|
self.miner_factory = MinerFactory()
|
||||||
self.ip_addr = ip_addr
|
self.ip_addr = ip_addr
|
||||||
self.connected_miners = {}
|
self.connected_miners = {}
|
||||||
self.mask = mask
|
self.mask = mask
|
||||||
|
|
||||||
def get_network(self):
|
def get_network(self) -> ipaddress.ip_network:
|
||||||
if self.network:
|
if self.network:
|
||||||
return self.network
|
return self.network
|
||||||
gateways = netifaces.gateways()
|
gateways = netifaces.gateways()
|
||||||
@@ -29,7 +33,7 @@ class MinerNetwork:
|
|||||||
subnet_mask = netifaces.ifaddresses(gateways['default'][netifaces.AF_INET][1])[netifaces.AF_INET][0]['netmask']
|
subnet_mask = netifaces.ifaddresses(gateways['default'][netifaces.AF_INET][1])[netifaces.AF_INET][0]['netmask']
|
||||||
return ipaddress.ip_network(f"{default_gateway}/{subnet_mask}", strict=False)
|
return ipaddress.ip_network(f"{default_gateway}/{subnet_mask}", strict=False)
|
||||||
|
|
||||||
async def scan_network_for_miners(self):
|
async def scan_network_for_miners(self) -> None or list[BOSminer or BMMiner or CGMiner or UnknownMiner]:
|
||||||
local_network = self.get_network()
|
local_network = self.get_network()
|
||||||
print(f"Scanning {local_network} for miners...")
|
print(f"Scanning {local_network} for miners...")
|
||||||
scan_tasks = []
|
scan_tasks = []
|
||||||
@@ -44,7 +48,8 @@ class MinerNetwork:
|
|||||||
miners = await asyncio.gather(*create_miners_tasks)
|
miners = await asyncio.gather(*create_miners_tasks)
|
||||||
return miners
|
return miners
|
||||||
|
|
||||||
async def ping_miner(self, ip: ipaddress.ip_address):
|
@staticmethod
|
||||||
|
async def ping_miner(ip: ipaddress.ip_address) -> None or ipaddress.ip_address:
|
||||||
for i in range(PING_RETRIES):
|
for i in range(PING_RETRIES):
|
||||||
connection_fut = asyncio.open_connection(str(ip), 4028)
|
connection_fut = asyncio.open_connection(str(ip), 4028)
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user