added supported miners to the docs
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import ipaddress
|
||||
import logging
|
||||
from typing import Union
|
||||
|
||||
|
||||
from pyasic.API.bmminer import BMMinerAPI
|
||||
@@ -11,6 +12,8 @@ from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES
|
||||
|
||||
|
||||
class BMMiner(BaseMiner):
|
||||
"""Base handler for BMMiner based miners."""
|
||||
|
||||
def __init__(self, ip: str) -> None:
|
||||
super().__init__(ip)
|
||||
self.ip = ipaddress.ip_address(ip)
|
||||
@@ -19,10 +22,11 @@ class BMMiner(BaseMiner):
|
||||
self.uname = "root"
|
||||
self.pwd = "admin"
|
||||
|
||||
async def get_model(self) -> str or None:
|
||||
async def get_model(self) -> Union[str, None]:
|
||||
"""Get miner model.
|
||||
|
||||
:return: Miner model or None.
|
||||
Returns:
|
||||
Miner model or None.
|
||||
"""
|
||||
# check if model is cached
|
||||
if self.model:
|
||||
@@ -46,7 +50,8 @@ class BMMiner(BaseMiner):
|
||||
async def get_hostname(self) -> str:
|
||||
"""Get miner hostname.
|
||||
|
||||
:return: The hostname of the miner as a string or "?"
|
||||
Returns:
|
||||
The hostname of the miner as a string or "?"
|
||||
"""
|
||||
if self.hostname:
|
||||
return self.hostname
|
||||
@@ -72,12 +77,14 @@ class BMMiner(BaseMiner):
|
||||
logging.warning(f"Failed to get hostname for miner: {self}")
|
||||
return "?"
|
||||
|
||||
async def send_ssh_command(self, cmd: str) -> str or None:
|
||||
async def send_ssh_command(self, cmd: str) -> Union[str, None]:
|
||||
"""Send a command to the miner over ssh.
|
||||
|
||||
:param cmd: The command to run.
|
||||
Parameters:
|
||||
cmd: The command to run.
|
||||
|
||||
:return: Result of the command or None.
|
||||
Returns:
|
||||
Result of the command or None.
|
||||
"""
|
||||
result = None
|
||||
|
||||
@@ -101,10 +108,11 @@ class BMMiner(BaseMiner):
|
||||
# return the result, either command output or None
|
||||
return result
|
||||
|
||||
async def get_config(self) -> list or None:
|
||||
async def get_config(self) -> Union[list, None]:
|
||||
"""Get the pool configuration of the miner.
|
||||
|
||||
:return: Pool config data or None.
|
||||
Returns:
|
||||
Pool config data or None.
|
||||
"""
|
||||
# get pool data
|
||||
pools = await self.api.pools()
|
||||
@@ -120,6 +128,11 @@ class BMMiner(BaseMiner):
|
||||
return pool_data
|
||||
|
||||
async def reboot(self) -> bool:
|
||||
"""Reboot the miner.
|
||||
|
||||
Returns:
|
||||
The result of rebooting the miner.
|
||||
"""
|
||||
logging.debug(f"{self}: Sending reboot command.")
|
||||
_ret = await self.send_ssh_command("reboot")
|
||||
logging.debug(f"{self}: Reboot command completed.")
|
||||
@@ -128,6 +141,11 @@ class BMMiner(BaseMiner):
|
||||
return False
|
||||
|
||||
async def get_data(self) -> MinerData:
|
||||
"""Get data from the miner.
|
||||
|
||||
Returns:
|
||||
A [`MinerData`][pyasic.data.MinerData] instance containing the miners data.
|
||||
"""
|
||||
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3)
|
||||
|
||||
board_offset = -1
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import ipaddress
|
||||
import logging
|
||||
import json
|
||||
from typing import Union
|
||||
|
||||
import toml
|
||||
|
||||
@@ -27,10 +28,11 @@ class BOSMiner(BaseMiner):
|
||||
self.pwd = "admin"
|
||||
self.config = None
|
||||
|
||||
async def send_ssh_command(self, cmd: str) -> str or None:
|
||||
async def send_ssh_command(self, cmd: str) -> Union[str, None]:
|
||||
"""Send a command to the miner over ssh.
|
||||
|
||||
:return: Result of the command or None.
|
||||
Returns:
|
||||
Result of the command or None.
|
||||
"""
|
||||
result = None
|
||||
|
||||
@@ -74,6 +76,7 @@ class BOSMiner(BaseMiner):
|
||||
return False
|
||||
|
||||
async def restart_backend(self) -> bool:
|
||||
"""Restart bosminer hashing process. Wraps [`restart_bosminer`][pyasic.miners._backends.bosminer.BOSMiner.restart_bosminer] to standardize."""
|
||||
return await self.restart_bosminer()
|
||||
|
||||
async def restart_bosminer(self) -> bool:
|
||||
@@ -94,7 +97,12 @@ class BOSMiner(BaseMiner):
|
||||
return True
|
||||
return False
|
||||
|
||||
async def get_config(self) -> None:
|
||||
async def get_config(self) -> str:
|
||||
"""Gets the config for the miner and sets it as `self.config`.
|
||||
|
||||
Returns:
|
||||
The config from `self.config`.
|
||||
"""
|
||||
logging.debug(f"{self}: Getting config.")
|
||||
async with (await self._get_ssh_connection()) as conn:
|
||||
logging.debug(f"{self}: Opening SFTP connection.")
|
||||
@@ -110,7 +118,8 @@ class BOSMiner(BaseMiner):
|
||||
async def get_hostname(self) -> str:
|
||||
"""Get miner hostname.
|
||||
|
||||
:return: The hostname of the miner as a string or "?"
|
||||
Returns:
|
||||
The hostname of the miner as a string or "?"
|
||||
"""
|
||||
if self.hostname:
|
||||
return self.hostname
|
||||
@@ -129,10 +138,11 @@ class BOSMiner(BaseMiner):
|
||||
logging.warning(f"Failed to get hostname for miner: {self}")
|
||||
return "?"
|
||||
|
||||
async def get_model(self) -> str or None:
|
||||
async def get_model(self) -> Union[str, None]:
|
||||
"""Get miner model.
|
||||
|
||||
:return: Miner model or None.
|
||||
Returns:
|
||||
Miner model or None.
|
||||
"""
|
||||
# check if model is cached
|
||||
if self.model:
|
||||
@@ -166,10 +176,11 @@ class BOSMiner(BaseMiner):
|
||||
logging.warning(f"Failed to get model for miner: {self}")
|
||||
return None
|
||||
|
||||
async def get_version(self):
|
||||
async def get_version(self) -> Union[str, None]:
|
||||
"""Get miner firmware version.
|
||||
|
||||
:return: Miner firmware version or None.
|
||||
Returns:
|
||||
Miner firmware version or None.
|
||||
"""
|
||||
# check if version is cached
|
||||
if self.version:
|
||||
@@ -214,57 +225,12 @@ class BOSMiner(BaseMiner):
|
||||
logging.debug(f"{self}: Restarting BOSMiner")
|
||||
await conn.run("/etc/init.d/bosminer restart")
|
||||
|
||||
async def get_board_info(self) -> dict:
|
||||
"""Gets data on each board and chain in the miner."""
|
||||
logging.debug(f"{self}: Getting board info.")
|
||||
devdetails = await self.api.devdetails()
|
||||
if not devdetails.get("DEVDETAILS"):
|
||||
print("devdetails error", devdetails)
|
||||
return {0: [], 1: [], 2: []}
|
||||
devs = devdetails["DEVDETAILS"]
|
||||
boards = {}
|
||||
offset = devs[0]["ID"]
|
||||
for board in devs:
|
||||
boards[board["ID"] - offset] = []
|
||||
if not board["Chips"] == self.nominal_chips:
|
||||
nominal = False
|
||||
else:
|
||||
nominal = True
|
||||
boards[board["ID"] - offset].append(
|
||||
{
|
||||
"chain": board["ID"] - offset,
|
||||
"chip_count": board["Chips"],
|
||||
"chip_status": "o" * board["Chips"],
|
||||
"nominal": nominal,
|
||||
}
|
||||
)
|
||||
logging.debug(f"Found board data for {self}: {boards}")
|
||||
return boards
|
||||
|
||||
async def get_bad_boards(self) -> dict:
|
||||
"""Checks for and provides list of non working boards."""
|
||||
boards = await self.get_board_info()
|
||||
bad_boards = {}
|
||||
for board in boards.keys():
|
||||
for chain in boards[board]:
|
||||
if not chain["chip_count"] == 63:
|
||||
if board not in bad_boards.keys():
|
||||
bad_boards[board] = []
|
||||
bad_boards[board].append(chain)
|
||||
return bad_boards
|
||||
|
||||
async def check_good_boards(self) -> str:
|
||||
"""Checks for and provides list for working boards."""
|
||||
devs = await self.api.devdetails()
|
||||
bad = 0
|
||||
chains = devs["DEVDETAILS"]
|
||||
for chain in chains:
|
||||
if chain["Chips"] == 0:
|
||||
bad += 1
|
||||
if not bad > 0:
|
||||
return str(self.ip)
|
||||
|
||||
async def get_data(self) -> MinerData:
|
||||
"""Get data from the miner.
|
||||
|
||||
Returns:
|
||||
A [`MinerData`][pyasic.data.MinerData] instance containing the miners data.
|
||||
"""
|
||||
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3)
|
||||
|
||||
board_offset = -1
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import ipaddress
|
||||
import logging
|
||||
from typing import Union
|
||||
|
||||
|
||||
from pyasic.API.btminer import BTMinerAPI
|
||||
@@ -19,7 +20,12 @@ class BTMiner(BaseMiner):
|
||||
self.api = BTMinerAPI(ip)
|
||||
self.api_type = "BTMiner"
|
||||
|
||||
async def get_model(self):
|
||||
async def get_model(self) -> Union[str, None]:
|
||||
"""Get miner model.
|
||||
|
||||
Returns:
|
||||
Miner model or None.
|
||||
"""
|
||||
if self.model:
|
||||
logging.debug(f"Found model for {self.ip}: {self.model}")
|
||||
return self.model
|
||||
@@ -31,7 +37,12 @@ class BTMiner(BaseMiner):
|
||||
logging.warning(f"Failed to get model for miner: {self}")
|
||||
return None
|
||||
|
||||
async def get_hostname(self) -> str or None:
|
||||
async def get_hostname(self) -> Union[str, None]:
|
||||
"""Get miner hostname.
|
||||
|
||||
Returns:
|
||||
The hostname of the miner as a string or None.
|
||||
"""
|
||||
if self.hostname:
|
||||
return self.hostname
|
||||
try:
|
||||
@@ -48,38 +59,12 @@ class BTMiner(BaseMiner):
|
||||
logging.warning(f"Failed to get hostname for miner: {self}")
|
||||
return None
|
||||
|
||||
async def get_board_info(self) -> dict:
|
||||
"""Gets data on each board and chain in the miner."""
|
||||
logging.debug(f"{self}: Getting board info.")
|
||||
devs = await self.api.devs()
|
||||
if not devs.get("DEVS"):
|
||||
print("devs error", devs)
|
||||
return {0: [], 1: [], 2: []}
|
||||
devs = devs["DEVS"]
|
||||
boards = {}
|
||||
offset = devs[0]["ID"]
|
||||
for board in devs:
|
||||
boards[board["ID"] - offset] = []
|
||||
if "Effective Chips" in board.keys():
|
||||
if not board["Effective Chips"] in self.nominal_chips:
|
||||
nominal = False
|
||||
else:
|
||||
nominal = True
|
||||
boards[board["ID"] - offset].append(
|
||||
{
|
||||
"chain": board["ID"] - offset,
|
||||
"chip_count": board["Effective Chips"],
|
||||
"chip_status": "o" * board["Effective Chips"],
|
||||
"nominal": nominal,
|
||||
}
|
||||
)
|
||||
else:
|
||||
logging.warning(f"Incorrect board data from {self}: {board}")
|
||||
print(board)
|
||||
logging.debug(f"Found board data for {self}: {boards}")
|
||||
return boards
|
||||
async def get_mac(self) -> str:
|
||||
"""Get the mac address of the miner.
|
||||
|
||||
async def get_mac(self):
|
||||
Returns:
|
||||
The mac address of the miner as a string.
|
||||
"""
|
||||
mac = ""
|
||||
data = await self.api.summary()
|
||||
if data:
|
||||
@@ -100,7 +85,12 @@ class BTMiner(BaseMiner):
|
||||
|
||||
return str(mac).upper()
|
||||
|
||||
async def get_data(self):
|
||||
async def get_data(self) -> MinerData:
|
||||
"""Get data from the miner.
|
||||
|
||||
Returns:
|
||||
A [`MinerData`][pyasic.data.MinerData] instance containing the miners data.
|
||||
"""
|
||||
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3)
|
||||
|
||||
mac = None
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import ipaddress
|
||||
import logging
|
||||
from typing import Union
|
||||
|
||||
|
||||
from pyasic.API.cgminer import CGMinerAPI
|
||||
@@ -21,7 +22,12 @@ class CGMiner(BaseMiner):
|
||||
self.pwd = "admin"
|
||||
self.config = None
|
||||
|
||||
async def get_model(self):
|
||||
async def get_model(self) -> Union[str, None]:
|
||||
"""Get miner model.
|
||||
|
||||
Returns:
|
||||
Miner model or None.
|
||||
"""
|
||||
if self.model:
|
||||
return self.model
|
||||
try:
|
||||
@@ -33,7 +39,12 @@ class CGMiner(BaseMiner):
|
||||
return self.model
|
||||
return None
|
||||
|
||||
async def get_hostname(self) -> str or None:
|
||||
async def get_hostname(self) -> Union[str, None]:
|
||||
"""Get miner hostname.
|
||||
|
||||
Returns:
|
||||
The hostname of the miner as a string or "?"
|
||||
"""
|
||||
if self.hostname:
|
||||
return self.hostname
|
||||
try:
|
||||
@@ -48,7 +59,15 @@ class CGMiner(BaseMiner):
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
async def send_ssh_command(self, cmd):
|
||||
async def send_ssh_command(self, cmd: str) -> Union[str, None]:
|
||||
"""Send a command to the miner over ssh.
|
||||
|
||||
Parameters:
|
||||
cmd: The command to run.
|
||||
|
||||
Returns:
|
||||
Result of the command or None.
|
||||
"""
|
||||
result = None
|
||||
async with (await self._get_ssh_connection()) as conn:
|
||||
for i in range(3):
|
||||
@@ -63,9 +82,11 @@ class CGMiner(BaseMiner):
|
||||
return result
|
||||
|
||||
async def restart_backend(self) -> bool:
|
||||
"""Restart cgminer hashing process. Wraps [`restart_cgminer`][pyasic.miners._backends.cgminer.CGMiner.restart_cgminer] to standardize."""
|
||||
return await self.restart_cgminer()
|
||||
|
||||
async def restart_cgminer(self) -> bool:
|
||||
"""Restart cgminer hashing process."""
|
||||
commands = ["cgminer-api restart", "/usr/bin/cgminer-monitor >/dev/null 2>&1"]
|
||||
commands = ";".join(commands)
|
||||
_ret = await self.send_ssh_command(commands)
|
||||
@@ -74,6 +95,7 @@ class CGMiner(BaseMiner):
|
||||
return False
|
||||
|
||||
async def reboot(self) -> bool:
|
||||
"""Reboots power to the physical miner."""
|
||||
logging.debug(f"{self}: Sending reboot command.")
|
||||
_ret = await self.send_ssh_command("reboot")
|
||||
logging.debug(f"{self}: Reboot command completed.")
|
||||
@@ -82,6 +104,7 @@ class CGMiner(BaseMiner):
|
||||
return False
|
||||
|
||||
async def start_cgminer(self) -> None:
|
||||
"""Start cgminer hashing process."""
|
||||
commands = [
|
||||
"mkdir -p /etc/tmp/",
|
||||
'echo "*/3 * * * * /usr/bin/cgminer-monitor" > /etc/tmp/root',
|
||||
@@ -92,6 +115,7 @@ class CGMiner(BaseMiner):
|
||||
await self.send_ssh_command(commands)
|
||||
|
||||
async def stop_cgminer(self) -> None:
|
||||
"""Restart cgminer hashing process."""
|
||||
commands = [
|
||||
"mkdir -p /etc/tmp/",
|
||||
'echo "" > /etc/tmp/root',
|
||||
@@ -101,14 +125,24 @@ class CGMiner(BaseMiner):
|
||||
commands = ";".join(commands)
|
||||
await self.send_ssh_command(commands)
|
||||
|
||||
async def get_config(self) -> None:
|
||||
async def get_config(self) -> str:
|
||||
"""Gets the config for the miner and sets it as `self.config`.
|
||||
|
||||
Returns:
|
||||
The config from `self.config`.
|
||||
"""
|
||||
async with (await self._get_ssh_connection()) as conn:
|
||||
command = "cat /etc/config/cgminer"
|
||||
result = await conn.run(command, check=True)
|
||||
self.config = result.stdout
|
||||
print(str(self.config))
|
||||
return self.config
|
||||
|
||||
async def get_data(self):
|
||||
async def get_data(self) -> MinerData:
|
||||
"""Get data from the miner.
|
||||
|
||||
Returns:
|
||||
A [`MinerData`][pyasic.data.MinerData] instance containing the miners data.
|
||||
"""
|
||||
data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3)
|
||||
|
||||
board_offset = -1
|
||||
|
||||
@@ -14,7 +14,7 @@ class BTMinerM30S(BTMiner, M30S):
|
||||
self.ip = ip
|
||||
|
||||
|
||||
class BTMinerM30SV50(BTMiner, M30SV50):
|
||||
class BTMinerM30SVE10(BTMiner, M30SVE10):
|
||||
def __init__(self, ip: str) -> None:
|
||||
super().__init__(ip)
|
||||
self.ip = ip
|
||||
@@ -32,7 +32,7 @@ class BTMinerM30SVE20(BTMiner, M30SVE20):
|
||||
self.ip = ip
|
||||
|
||||
|
||||
class BTMinerM30SVE10(BTMiner, M30SVE10):
|
||||
class BTMinerM30SV50(BTMiner, M30SV50):
|
||||
def __init__(self, ip: str) -> None:
|
||||
super().__init__(ip)
|
||||
self.ip = ip
|
||||
|
||||
@@ -13,13 +13,13 @@ class BTMinerM30SPlus(BTMiner, M30SPlus):
|
||||
self.ip = ip
|
||||
|
||||
|
||||
class BTMinerM30SPlusVE40(BTMiner, M30SPlusVE40):
|
||||
class BTMinerM30SPlusVF20(BTMiner, M30SPlusVF20):
|
||||
def __init__(self, ip: str) -> None:
|
||||
super().__init__(ip)
|
||||
self.ip = ip
|
||||
|
||||
|
||||
class BTMinerM30SPlusVF20(BTMiner, M30SPlusVF20):
|
||||
class BTMinerM30SPlusVE40(BTMiner, M30SPlusVE40):
|
||||
def __init__(self, ip: str) -> None:
|
||||
super().__init__(ip)
|
||||
self.ip = ip
|
||||
|
||||
@@ -12,13 +12,13 @@ class BTMinerM30SPlusPlus(BTMiner, M30SPlusPlus):
|
||||
self.ip = ip
|
||||
|
||||
|
||||
class BTMinerM30SPlusPlusVG40(BTMiner, M30SPlusPlusVG40):
|
||||
def __init__(self, ip: str) -> None:
|
||||
super().__init__(ip)
|
||||
self.ip = ip
|
||||
|
||||
|
||||
class BTMinerM30SPlusPlusVG30(BTMiner, M30SPlusPlusVG30):
|
||||
def __init__(self, ip: str) -> None:
|
||||
super().__init__(ip)
|
||||
self.ip = ip
|
||||
|
||||
|
||||
class BTMinerM30SPlusPlusVG40(BTMiner, M30SPlusPlusVG40):
|
||||
def __init__(self, ip: str) -> None:
|
||||
super().__init__(ip)
|
||||
self.ip = ip
|
||||
|
||||
Reference in New Issue
Block a user