Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3484d43510 | ||
|
|
dd7e352391 | ||
|
|
a32b61fe5d | ||
|
|
597a178009 | ||
|
|
409b2527f0 | ||
|
|
58234fcf7f | ||
|
|
1bf863cca8 | ||
|
|
6482d04185 | ||
|
|
3b58b11501 | ||
|
|
7485b8ef77 | ||
|
|
d2bea227db | ||
|
|
1b7afaaf7e | ||
|
|
96898d639c | ||
|
|
eb439f4dcf | ||
|
|
69f4349393 |
@@ -32,6 +32,8 @@ class BaseMinerAPI:
|
|||||||
# ip address of the miner
|
# ip address of the miner
|
||||||
self.ip = ipaddress.ip_address(ip)
|
self.ip = ipaddress.ip_address(ip)
|
||||||
|
|
||||||
|
self.pwd = "admin"
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
def __new__(cls, *args, **kwargs):
|
||||||
if cls is BaseMinerAPI:
|
if cls is BaseMinerAPI:
|
||||||
raise TypeError(f"Only children of '{cls.__name__}' may be instantiated")
|
raise TypeError(f"Only children of '{cls.__name__}' may be instantiated")
|
||||||
|
|||||||
@@ -550,7 +550,7 @@ class MinerConfig:
|
|||||||
"bitmain-fan-ctrl": False,
|
"bitmain-fan-ctrl": False,
|
||||||
"bitmain-fan-pwn": "100",
|
"bitmain-fan-pwn": "100",
|
||||||
"freq-level": "100",
|
"freq-level": "100",
|
||||||
"miner-mode": str(self.miner_mode.value),
|
"miner-mode": self.miner_mode.value,
|
||||||
"pools": self.pool_groups[0].as_x19(user_suffix=user_suffix),
|
"pools": self.pool_groups[0].as_x19(user_suffix=user_suffix),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,9 +560,6 @@ class MinerConfig:
|
|||||||
if self.fan_speed:
|
if self.fan_speed:
|
||||||
cfg["bitmain-fan-pwn"] = str(self.fan_speed)
|
cfg["bitmain-fan-pwn"] = str(self.fan_speed)
|
||||||
|
|
||||||
if self.miner_mode == X19PowerMode.Sleep:
|
|
||||||
cfg["freq-level"] = "0"
|
|
||||||
|
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
def as_x17(self, user_suffix: str = None) -> dict:
|
def as_x17(self, user_suffix: str = None) -> dict:
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import logging
|
|||||||
import time
|
import time
|
||||||
from dataclasses import asdict, dataclass, field, fields
|
from dataclasses import asdict, dataclass, field, fields
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from typing import List, Union
|
from typing import List, Union, Any
|
||||||
|
|
||||||
from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error
|
from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error
|
||||||
|
|
||||||
@@ -40,13 +40,28 @@ class HashBoard:
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
slot: int = 0
|
slot: int = 0
|
||||||
hashrate: float = 0.0
|
hashrate: float = None
|
||||||
temp: int = -1
|
temp: int = None
|
||||||
chip_temp: int = -1
|
chip_temp: int = None
|
||||||
chips: int = 0
|
chips: int = None
|
||||||
expected_chips: int = 0
|
expected_chips: int = None
|
||||||
missing: bool = True
|
missing: bool = True
|
||||||
|
|
||||||
|
def get(self, __key: str, default: Any = None):
|
||||||
|
try:
|
||||||
|
val = self.__getitem__(__key)
|
||||||
|
if val is None:
|
||||||
|
return default
|
||||||
|
return val
|
||||||
|
except KeyError:
|
||||||
|
return default
|
||||||
|
|
||||||
|
def __getitem__(self, item: str):
|
||||||
|
try:
|
||||||
|
return getattr(self, item)
|
||||||
|
except AttributeError:
|
||||||
|
raise KeyError(f"{item}")
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class Fan:
|
class Fan:
|
||||||
@@ -56,7 +71,22 @@ class Fan:
|
|||||||
speed: The speed of the fan.
|
speed: The speed of the fan.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
speed: int = -1
|
speed: int = None
|
||||||
|
|
||||||
|
def get(self, __key: str, default: Any = None):
|
||||||
|
try:
|
||||||
|
val = self.__getitem__(__key)
|
||||||
|
if val is None:
|
||||||
|
return default
|
||||||
|
return val
|
||||||
|
except KeyError:
|
||||||
|
return default
|
||||||
|
|
||||||
|
def __getitem__(self, item: str):
|
||||||
|
try:
|
||||||
|
return getattr(self, item)
|
||||||
|
except AttributeError:
|
||||||
|
raise KeyError(f"{item}")
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
@@ -102,26 +132,26 @@ class MinerData:
|
|||||||
|
|
||||||
ip: str
|
ip: str
|
||||||
datetime: datetime = None
|
datetime: datetime = None
|
||||||
uptime: int = 0
|
uptime: int = None
|
||||||
mac: str = "00:00:00:00:00:00"
|
mac: str = None
|
||||||
model: str = "Unknown"
|
model: str = None
|
||||||
make: str = "Unknown"
|
make: str = None
|
||||||
api_ver: str = "Unknown"
|
api_ver: str = None
|
||||||
fw_ver: str = "Unknown"
|
fw_ver: str = None
|
||||||
hostname: str = "Unknown"
|
hostname: str = None
|
||||||
hashrate: float = field(init=False)
|
hashrate: float = field(init=False)
|
||||||
_hashrate: float = 0
|
_hashrate: float = None
|
||||||
nominal_hashrate: float = 0
|
nominal_hashrate: float = None
|
||||||
hashboards: List[HashBoard] = field(default_factory=list)
|
hashboards: List[HashBoard] = field(default_factory=list)
|
||||||
ideal_hashboards: int = 1
|
ideal_hashboards: int = None
|
||||||
temperature_avg: int = field(init=False)
|
temperature_avg: int = field(init=False)
|
||||||
env_temp: float = -1.0
|
env_temp: float = None
|
||||||
wattage: int = -1
|
wattage: int = None
|
||||||
wattage_limit: int = -1
|
wattage_limit: int = None
|
||||||
fans: List[Fan] = field(default_factory=list)
|
fans: List[Fan] = field(default_factory=list)
|
||||||
fan_psu: int = -1
|
fan_psu: int = None
|
||||||
total_chips: int = field(init=False)
|
total_chips: int = field(init=False)
|
||||||
ideal_chips: int = 1
|
ideal_chips: int = None
|
||||||
percent_ideal_chips: float = field(init=False)
|
percent_ideal_chips: float = field(init=False)
|
||||||
percent_ideal_hashrate: float = field(init=False)
|
percent_ideal_hashrate: float = field(init=False)
|
||||||
percent_ideal_wattage: float = field(init=False)
|
percent_ideal_wattage: float = field(init=False)
|
||||||
@@ -145,7 +175,16 @@ class MinerData:
|
|||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
self.datetime = datetime.now(timezone.utc).astimezone()
|
self.datetime = datetime.now(timezone.utc).astimezone()
|
||||||
|
|
||||||
def __getitem__(self, item):
|
def get(self, __key: str, default: Any = None):
|
||||||
|
try:
|
||||||
|
val = self.__getitem__(__key)
|
||||||
|
if val is None:
|
||||||
|
return default
|
||||||
|
return val
|
||||||
|
except KeyError:
|
||||||
|
return default
|
||||||
|
|
||||||
|
def __getitem__(self, item: str):
|
||||||
try:
|
try:
|
||||||
return getattr(self, item)
|
return getattr(self, item)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
@@ -197,7 +236,12 @@ class MinerData:
|
|||||||
@property
|
@property
|
||||||
def hashrate(self): # noqa - Skip PyCharm inspection
|
def hashrate(self): # noqa - Skip PyCharm inspection
|
||||||
if len(self.hashboards) > 0:
|
if len(self.hashboards) > 0:
|
||||||
return round(sum(map(lambda x: x.hashrate, self.hashboards)), 2)
|
hr_data = []
|
||||||
|
for item in self.hashboards:
|
||||||
|
if item.hashrate is not None:
|
||||||
|
hr_data.append(item.hashrate)
|
||||||
|
if len(hr_data) > 0:
|
||||||
|
return sum(hr_data)
|
||||||
return self._hashrate
|
return self._hashrate
|
||||||
|
|
||||||
@hashrate.setter
|
@hashrate.setter
|
||||||
@@ -206,7 +250,14 @@ class MinerData:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def total_chips(self): # noqa - Skip PyCharm inspection
|
def total_chips(self): # noqa - Skip PyCharm inspection
|
||||||
return sum([hb.chips for hb in self.hashboards])
|
if len(self.hashboards) > 0:
|
||||||
|
chip_data = []
|
||||||
|
for item in self.hashboards:
|
||||||
|
if item.chips is not None:
|
||||||
|
chip_data.append(item.chips)
|
||||||
|
if len(chip_data) > 0:
|
||||||
|
return sum(chip_data)
|
||||||
|
return None
|
||||||
|
|
||||||
@total_chips.setter
|
@total_chips.setter
|
||||||
def total_chips(self, val):
|
def total_chips(self, val):
|
||||||
@@ -214,6 +265,8 @@ class MinerData:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def nominal(self): # noqa - Skip PyCharm inspection
|
def nominal(self): # noqa - Skip PyCharm inspection
|
||||||
|
if self.total_chips is None or self.ideal_chips is None:
|
||||||
|
return None
|
||||||
return self.ideal_chips == self.total_chips
|
return self.ideal_chips == self.total_chips
|
||||||
|
|
||||||
@nominal.setter
|
@nominal.setter
|
||||||
@@ -222,6 +275,8 @@ class MinerData:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def percent_ideal_chips(self): # noqa - Skip PyCharm inspection
|
def percent_ideal_chips(self): # noqa - Skip PyCharm inspection
|
||||||
|
if self.total_chips is None or self.ideal_chips is None:
|
||||||
|
return None
|
||||||
if self.total_chips == 0 or self.ideal_chips == 0:
|
if self.total_chips == 0 or self.ideal_chips == 0:
|
||||||
return 0
|
return 0
|
||||||
return round((self.total_chips / self.ideal_chips) * 100)
|
return round((self.total_chips / self.ideal_chips) * 100)
|
||||||
@@ -232,6 +287,8 @@ class MinerData:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def percent_ideal_hashrate(self): # noqa - Skip PyCharm inspection
|
def percent_ideal_hashrate(self): # noqa - Skip PyCharm inspection
|
||||||
|
if self.hashrate is None or self.nominal_hashrate is None:
|
||||||
|
return None
|
||||||
if self.hashrate == 0 or self.nominal_hashrate == 0:
|
if self.hashrate == 0 or self.nominal_hashrate == 0:
|
||||||
return 0
|
return 0
|
||||||
return round((self.hashrate / self.nominal_hashrate) * 100)
|
return round((self.hashrate / self.nominal_hashrate) * 100)
|
||||||
@@ -242,6 +299,8 @@ class MinerData:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def percent_ideal_wattage(self): # noqa - Skip PyCharm inspection
|
def percent_ideal_wattage(self): # noqa - Skip PyCharm inspection
|
||||||
|
if self.wattage_limit is None or self.wattage is None:
|
||||||
|
return None
|
||||||
if self.wattage_limit == 0 or self.wattage == 0:
|
if self.wattage_limit == 0 or self.wattage == 0:
|
||||||
return 0
|
return 0
|
||||||
return round((self.wattage / self.wattage_limit) * 100)
|
return round((self.wattage / self.wattage_limit) * 100)
|
||||||
@@ -255,11 +314,11 @@ class MinerData:
|
|||||||
total_temp = 0
|
total_temp = 0
|
||||||
temp_count = 0
|
temp_count = 0
|
||||||
for hb in self.hashboards:
|
for hb in self.hashboards:
|
||||||
if hb.temp and not hb.temp == -1:
|
if hb.temp is not None:
|
||||||
total_temp += hb.temp
|
total_temp += hb.temp
|
||||||
temp_count += 1
|
temp_count += 1
|
||||||
if not temp_count > 0:
|
if not temp_count > 0:
|
||||||
return 0
|
return None
|
||||||
return round(total_temp / temp_count)
|
return round(total_temp / temp_count)
|
||||||
|
|
||||||
@temperature_avg.setter
|
@temperature_avg.setter
|
||||||
@@ -268,7 +327,9 @@ class MinerData:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def efficiency(self): # noqa - Skip PyCharm inspection
|
def efficiency(self): # noqa - Skip PyCharm inspection
|
||||||
if self.hashrate == 0 or self.wattage == -1:
|
if self.hashrate is None or self.wattage is None:
|
||||||
|
return None
|
||||||
|
if self.hashrate == 0 or self.wattage == 0:
|
||||||
return 0
|
return 0
|
||||||
return round(self.wattage / self.hashrate)
|
return round(self.wattage / self.hashrate)
|
||||||
|
|
||||||
@@ -328,7 +389,7 @@ class MinerData:
|
|||||||
tags = ["ip", "mac", "model", "hostname"]
|
tags = ["ip", "mac", "model", "hostname"]
|
||||||
for attribute in self:
|
for attribute in self:
|
||||||
if attribute in tags:
|
if attribute in tags:
|
||||||
escaped_data = self[attribute].replace(" ", "\\ ")
|
escaped_data = self.get(attribute, "Unknown").replace(" ", "\\ ")
|
||||||
tag_data.append(f"{attribute}={escaped_data}")
|
tag_data.append(f"{attribute}={escaped_data}")
|
||||||
continue
|
continue
|
||||||
elif str(attribute).startswith("_"):
|
elif str(attribute).startswith("_"):
|
||||||
@@ -345,26 +406,24 @@ class MinerData:
|
|||||||
elif isinstance(self[attribute], float):
|
elif isinstance(self[attribute], float):
|
||||||
field_data.append(f"{attribute}={self[attribute]}")
|
field_data.append(f"{attribute}={self[attribute]}")
|
||||||
continue
|
continue
|
||||||
elif attribute == "fault_light" and not self[attribute]:
|
|
||||||
field_data.append(f"{attribute}=false")
|
|
||||||
continue
|
|
||||||
elif attribute == "errors":
|
elif attribute == "errors":
|
||||||
for idx, item in enumerate(self[attribute]):
|
for idx, item in enumerate(self[attribute]):
|
||||||
field_data.append(f'error_{idx+1}="{item.error_message}"')
|
field_data.append(f'error_{idx+1}="{item.error_message}"')
|
||||||
elif attribute == "hashboards":
|
elif attribute == "hashboards":
|
||||||
for idx, item in enumerate(self[attribute]):
|
for idx, item in enumerate(self[attribute]):
|
||||||
field_data.append(f"hashboard_{idx+1}_hashrate={item.hashrate}")
|
field_data.append(f"hashboard_{idx+1}_hashrate={item.get('hashrate', 0.0)}")
|
||||||
field_data.append(f"hashboard_{idx+1}_temperature={item.temp}")
|
field_data.append(f"hashboard_{idx+1}_temperature={item.get('temp', 0)}")
|
||||||
field_data.append(
|
field_data.append(
|
||||||
f"hashboard_{idx+1}_chip_temperature={item.chip_temp}"
|
f"hashboard_{idx+1}_chip_temperature={item.get('chip_temp', 0)}"
|
||||||
)
|
)
|
||||||
field_data.append(f"hashboard_{idx+1}_chips={item.chips}")
|
field_data.append(f"hashboard_{idx+1}_chips={item.get('chips', 0)}")
|
||||||
field_data.append(
|
field_data.append(
|
||||||
f"hashboard_{idx+1}_expected_chips={item.expected_chips}"
|
f"hashboard_{idx+1}_expected_chips={item.get('expected_chips', 0)}"
|
||||||
)
|
)
|
||||||
elif attribute == "fans":
|
elif attribute == "fans":
|
||||||
for idx, item in enumerate(self[attribute]):
|
for idx, item in enumerate(self[attribute]):
|
||||||
field_data.append(f"fan_{idx+1}={item.speed}")
|
if item.speed is not None:
|
||||||
|
field_data.append(f"fan_{idx+1}={item.speed}")
|
||||||
|
|
||||||
tags_str = ",".join(tag_data)
|
tags_str = ",".join(tag_data)
|
||||||
field_str = ",".join(field_data)
|
field_str = ",".join(field_data)
|
||||||
|
|||||||
@@ -149,10 +149,10 @@ class _MinerPhaseBalancer:
|
|||||||
not self.miners[data_point.ip]["shutdown"]
|
not self.miners[data_point.ip]["shutdown"]
|
||||||
):
|
):
|
||||||
# cant do anything with it so need to find a semi-accurate power limit
|
# cant do anything with it so need to find a semi-accurate power limit
|
||||||
if not data_point.wattage_limit == -1:
|
if not data_point.wattage_limit == None:
|
||||||
self.miners[data_point.ip]["max"] = int(data_point.wattage_limit)
|
self.miners[data_point.ip]["max"] = int(data_point.wattage_limit)
|
||||||
self.miners[data_point.ip]["min"] = int(data_point.wattage_limit)
|
self.miners[data_point.ip]["min"] = int(data_point.wattage_limit)
|
||||||
elif not data_point.wattage == -1:
|
elif not data_point.wattage == None:
|
||||||
self.miners[data_point.ip]["max"] = int(data_point.wattage)
|
self.miners[data_point.ip]["max"] = int(data_point.wattage)
|
||||||
self.miners[data_point.ip]["min"] = int(data_point.wattage)
|
self.miners[data_point.ip]["min"] = int(data_point.wattage)
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ class HiveonT9(Hiveon, T9):
|
|||||||
hashrate = 0
|
hashrate = 0
|
||||||
chips = 0
|
chips = 0
|
||||||
for chipset in board_map[board]:
|
for chipset in board_map[board]:
|
||||||
if hashboard.chip_temp == -1:
|
if hashboard.chip_temp == None:
|
||||||
try:
|
try:
|
||||||
hashboard.board_temp = api_stats["STATS"][1][f"temp{chipset}"]
|
hashboard.board_temp = api_stats["STATS"][1][f"temp{chipset}"]
|
||||||
hashboard.chip_temp = api_stats["STATS"][1][f"temp2_{chipset}"]
|
hashboard.chip_temp = api_stats["STATS"][1][f"temp2_{chipset}"]
|
||||||
|
|||||||
@@ -494,7 +494,7 @@ class BOSMiner(BaseMiner):
|
|||||||
if graphql_version:
|
if graphql_version:
|
||||||
try:
|
try:
|
||||||
fw_ver = graphql_version["data"]["bos"]["info"]["version"]["full"]
|
fw_ver = graphql_version["data"]["bos"]["info"]["version"]["full"]
|
||||||
except KeyError:
|
except (KeyError, TypeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if not fw_ver:
|
if not fw_ver:
|
||||||
@@ -523,7 +523,7 @@ class BOSMiner(BaseMiner):
|
|||||||
try:
|
try:
|
||||||
hostname = graphql_hostname["data"]["bos"]["hostname"]
|
hostname = graphql_hostname["data"]["bos"]["hostname"]
|
||||||
return hostname
|
return hostname
|
||||||
except KeyError:
|
except (TypeError, KeyError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -563,7 +563,7 @@ class BOSMiner(BaseMiner):
|
|||||||
),
|
),
|
||||||
2,
|
2,
|
||||||
)
|
)
|
||||||
except (KeyError, IndexError, ValueError):
|
except (LookupError, ValueError, TypeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# get hr from API
|
# get hr from API
|
||||||
@@ -617,7 +617,7 @@ class BOSMiner(BaseMiner):
|
|||||||
boards = graphql_boards["data"]["bosminer"]["info"]["workSolver"][
|
boards = graphql_boards["data"]["bosminer"]["info"]["workSolver"][
|
||||||
"childSolvers"
|
"childSolvers"
|
||||||
]
|
]
|
||||||
except (KeyError, IndexError):
|
except (TypeError, LookupError):
|
||||||
boards = None
|
boards = None
|
||||||
|
|
||||||
if boards:
|
if boards:
|
||||||
@@ -732,7 +732,7 @@ class BOSMiner(BaseMiner):
|
|||||||
return graphql_wattage["data"]["bosminer"]["info"]["workSolver"][
|
return graphql_wattage["data"]["bosminer"]["info"]["workSolver"][
|
||||||
"power"
|
"power"
|
||||||
]["approxConsumptionW"]
|
]["approxConsumptionW"]
|
||||||
except (KeyError, TypeError):
|
except (LookupError, TypeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if not api_tunerstatus:
|
if not api_tunerstatus:
|
||||||
@@ -765,7 +765,7 @@ class BOSMiner(BaseMiner):
|
|||||||
return graphql_wattage_limit["data"]["bosminer"]["info"]["workSolver"][
|
return graphql_wattage_limit["data"]["bosminer"]["info"]["workSolver"][
|
||||||
"power"
|
"power"
|
||||||
]["limitW"]
|
]["limitW"]
|
||||||
except (KeyError, TypeError):
|
except (LookupError, TypeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if not api_tunerstatus:
|
if not api_tunerstatus:
|
||||||
@@ -801,7 +801,7 @@ class BOSMiner(BaseMiner):
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
except KeyError:
|
except (LookupError, TypeError):
|
||||||
pass
|
pass
|
||||||
return fans
|
return fans
|
||||||
|
|
||||||
@@ -941,7 +941,7 @@ class BOSMiner(BaseMiner):
|
|||||||
boards = graphql_errors["data"]["bosminer"]["info"]["workSolver"][
|
boards = graphql_errors["data"]["bosminer"]["info"]["workSolver"][
|
||||||
"childSolvers"
|
"childSolvers"
|
||||||
]
|
]
|
||||||
except (KeyError, IndexError):
|
except (LookupError, TypeError):
|
||||||
boards = None
|
boards = None
|
||||||
|
|
||||||
if boards:
|
if boards:
|
||||||
@@ -1034,17 +1034,20 @@ class BOSMiner(BaseMiner):
|
|||||||
try:
|
try:
|
||||||
self.light = graphql_fault_light["data"]["bos"]["faultLight"]
|
self.light = graphql_fault_light["data"]["bos"]["faultLight"]
|
||||||
return self.light
|
return self.light
|
||||||
except (TypeError, KeyError, ValueError, IndexError):
|
except (TypeError, ValueError, LookupError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# get light via ssh if that fails (10x slower)
|
# get light via ssh if that fails (10x slower)
|
||||||
data = (
|
try:
|
||||||
await self.send_ssh_command("cat /sys/class/leds/'Red LED'/delay_off")
|
data = (
|
||||||
).strip()
|
await self.send_ssh_command("cat /sys/class/leds/'Red LED'/delay_off")
|
||||||
self.light = False
|
).strip()
|
||||||
if data == "50":
|
self.light = False
|
||||||
self.light = True
|
if data == "50":
|
||||||
return self.light
|
self.light = True
|
||||||
|
return self.light
|
||||||
|
except TypeError:
|
||||||
|
return self.light
|
||||||
|
|
||||||
async def get_nominal_hashrate(self, api_devs: dict = None) -> Optional[float]:
|
async def get_nominal_hashrate(self, api_devs: dict = None) -> Optional[float]:
|
||||||
if not api_devs:
|
if not api_devs:
|
||||||
|
|||||||
@@ -72,6 +72,52 @@ class BaseMiner(ABC):
|
|||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
return ipaddress.ip_address(self.ip) == ipaddress.ip_address(other.ip)
|
return ipaddress.ip_address(self.ip) == ipaddress.ip_address(other.ip)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pwd(self): # noqa - Skip PyCharm inspection
|
||||||
|
data = []
|
||||||
|
try:
|
||||||
|
if self.web is not None:
|
||||||
|
data.append(f"web={self.web.pwd}")
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
if self.api is not None:
|
||||||
|
data.append(f"api={self.api.pwd}")
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
return ",".join(data)
|
||||||
|
|
||||||
|
@pwd.setter
|
||||||
|
def pwd(self, val):
|
||||||
|
try:
|
||||||
|
if self.web is not None:
|
||||||
|
self.web.pwd = val
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
if self.api is not None:
|
||||||
|
self.api.pwd = val
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def username(self): # noqa - Skip PyCharm inspection
|
||||||
|
data = []
|
||||||
|
try:
|
||||||
|
if self.web is not None:
|
||||||
|
data.append(f"web={self.web.username}")
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
return ",".join(data)
|
||||||
|
|
||||||
|
@username.setter
|
||||||
|
def username(self, val):
|
||||||
|
try:
|
||||||
|
if self.web is not None:
|
||||||
|
self.web.username = val
|
||||||
|
except TypeError:
|
||||||
|
pass
|
||||||
|
|
||||||
async def _get_ssh_connection(self) -> asyncssh.connect:
|
async def _get_ssh_connection(self) -> asyncssh.connect:
|
||||||
"""Create a new asyncssh connection"""
|
"""Create a new asyncssh connection"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "pyasic"
|
name = "pyasic"
|
||||||
version = "0.36.7"
|
version = "0.37.1"
|
||||||
description = "A set of modules for interfacing with many common types of ASIC bitcoin miners, using both their API and SSH."
|
description = "A set of modules for interfacing with many common types of ASIC bitcoin miners, using both their API and SSH."
|
||||||
authors = ["UpstreamData <brett@upstreamdata.ca>"]
|
authors = ["UpstreamData <brett@upstreamdata.ca>"]
|
||||||
repository = "https://github.com/UpstreamData/pyasic"
|
repository = "https://github.com/UpstreamData/pyasic"
|
||||||
|
|||||||
Reference in New Issue
Block a user