Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d39d278296 | ||
|
|
ea8b922367 | ||
|
|
0d1c8d80e0 | ||
|
|
494d25da97 | ||
|
|
0327d93a35 | ||
|
|
680584c468 | ||
|
|
c0dbafb198 | ||
|
|
97d2c4ac34 | ||
|
|
055d633c91 | ||
|
|
68c57f265f | ||
|
|
1ba0f8ed83 | ||
|
|
7f74b083d3 | ||
|
|
97c20dae0a |
@@ -245,13 +245,13 @@ class MinerConfig(BaseModel):
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_vnish(cls, web_settings: dict) -> "MinerConfig":
|
||||
def from_vnish(cls, web_settings: dict, web_presets: list[dict]) -> "MinerConfig":
|
||||
"""Constructs a MinerConfig object from web settings for VNish miners."""
|
||||
return cls(
|
||||
pools=PoolConfig.from_vnish(web_settings),
|
||||
fan_mode=FanModeConfig.from_vnish(web_settings),
|
||||
temperature=TemperatureConfig.from_vnish(web_settings),
|
||||
mining_mode=MiningModeConfig.from_vnish(web_settings),
|
||||
mining_mode=MiningModeConfig.from_vnish(web_settings, web_presets),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
@@ -299,3 +299,7 @@ class MinerConfig(BaseModel):
|
||||
@classmethod
|
||||
def from_hammer(cls, *args, **kwargs) -> "MinerConfig":
|
||||
return cls.from_am_modern(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def from_hiveon_modern(cls, web_conf: dict) -> "MinerConfig":
|
||||
return cls.from_am_modern(web_conf)
|
||||
|
||||
@@ -36,6 +36,7 @@ from pyasic.web.braiins_os.proto.braiins.bos.v1 import (
|
||||
)
|
||||
|
||||
from .algo import TunerAlgo, TunerAlgoType
|
||||
from .presets import MiningPreset
|
||||
from .scaling import ScalingConfig
|
||||
|
||||
|
||||
@@ -251,9 +252,9 @@ class MiningModeHashrateTune(MinerConfigValue):
|
||||
arbitrary_types_allowed = True
|
||||
|
||||
mode: str = field(init=False, default="hashrate_tuning")
|
||||
hashrate: int = None
|
||||
hashrate: int | None = None
|
||||
algo: TunerAlgoType = field(default_factory=TunerAlgo.default)
|
||||
scaling: ScalingConfig = None
|
||||
scaling: ScalingConfig | None = None
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, dict_conf: dict | None) -> "MiningModeHashrateTune":
|
||||
@@ -344,6 +345,29 @@ class MiningModeHashrateTune(MinerConfigValue):
|
||||
return {"autotunerset": {"enabled": True}}
|
||||
|
||||
|
||||
class MiningModePreset(MinerConfigValue):
|
||||
mode: str = field(init=False, default="preset")
|
||||
|
||||
active_preset: MiningPreset
|
||||
available_presets: list[MiningPreset] = field(default_factory=list)
|
||||
|
||||
def as_vnish(self) -> dict:
|
||||
return {"overclock": {**self.active_preset.as_vnish()}}
|
||||
|
||||
@classmethod
|
||||
def from_vnish(
|
||||
cls, web_overclock_settings: dict, web_presets: list[dict]
|
||||
) -> "MiningModePreset":
|
||||
active_preset = None
|
||||
for preset in web_presets:
|
||||
if preset["name"] == web_overclock_settings["preset"]:
|
||||
active_preset = preset
|
||||
return cls(
|
||||
active_preset=MiningPreset.from_vnish(active_preset),
|
||||
available_presets=[MiningPreset.from_vnish(p) for p in web_presets],
|
||||
)
|
||||
|
||||
|
||||
class ManualBoardSettings(MinerConfigValue):
|
||||
freq: float
|
||||
volt: float
|
||||
@@ -444,6 +468,7 @@ class MiningModeConfig(MinerConfigOption):
|
||||
sleep = MiningModeSleep
|
||||
power_tuning = MiningModePowerTune
|
||||
hashrate_tuning = MiningModeHashrateTune
|
||||
preset = MiningModePreset
|
||||
manual = MiningModeManual
|
||||
|
||||
@classmethod
|
||||
@@ -561,7 +586,7 @@ class MiningModeConfig(MinerConfigOption):
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_vnish(cls, web_settings: dict):
|
||||
def from_vnish(cls, web_settings: dict, web_presets: list[dict]):
|
||||
try:
|
||||
mode_settings = web_settings["miner"]["overclock"]
|
||||
except KeyError:
|
||||
@@ -570,7 +595,7 @@ class MiningModeConfig(MinerConfigOption):
|
||||
if mode_settings["preset"] == "disabled":
|
||||
return MiningModeManual.from_vnish(mode_settings)
|
||||
else:
|
||||
return cls.power_tuning(power=int(mode_settings["preset"]))
|
||||
return MiningModePreset.from_vnish(mode_settings, web_presets)
|
||||
|
||||
@classmethod
|
||||
def from_boser(cls, grpc_miner_conf: dict):
|
||||
@@ -673,5 +698,6 @@ MiningMode = TypeVar(
|
||||
MiningModeManual,
|
||||
MiningModePowerTune,
|
||||
MiningModeHashrateTune,
|
||||
MiningModePreset,
|
||||
],
|
||||
)
|
||||
|
||||
34
pyasic/config/mining/presets.py
Normal file
34
pyasic/config/mining/presets.py
Normal file
@@ -0,0 +1,34 @@
|
||||
from pyasic.config.base import MinerConfigValue
|
||||
|
||||
|
||||
class MiningPreset(MinerConfigValue):
|
||||
name: str | None = None
|
||||
power: int | None = None
|
||||
hashrate: int | None = None
|
||||
tuned: bool | None = None
|
||||
modded_psu: bool = False
|
||||
|
||||
def as_vnish(self) -> dict:
|
||||
if self.name is not None:
|
||||
return {"preset": self.name}
|
||||
return {}
|
||||
|
||||
@classmethod
|
||||
def from_vnish(cls, web_preset: dict):
|
||||
name = web_preset["name"]
|
||||
hr_power_split = web_preset["pretty"].split("~")
|
||||
if len(hr_power_split) == 1:
|
||||
power = None
|
||||
hashrate = None
|
||||
else:
|
||||
power = hr_power_split[0].replace("watt", "").strip()
|
||||
hashrate = hr_power_split[1].replace("TH", "").strip()
|
||||
tuned = web_preset["status"] == "tuned"
|
||||
modded_psu = web_preset["modded_psu_required"]
|
||||
return cls(
|
||||
name=name,
|
||||
power=power,
|
||||
hashrate=hashrate,
|
||||
tuned=tuned,
|
||||
modded_psu=modded_psu,
|
||||
)
|
||||
@@ -14,7 +14,7 @@
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
from pyasic.miners.backends import Hiveon
|
||||
from pyasic.miners.backends import HiveonModern
|
||||
from pyasic.miners.device.models import (
|
||||
S19,
|
||||
S19L,
|
||||
@@ -35,65 +35,65 @@ from pyasic.miners.device.models import (
|
||||
)
|
||||
|
||||
|
||||
class HiveonS19(Hiveon, S19):
|
||||
class HiveonS19(HiveonModern, S19):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19Plus(Hiveon, S19Plus):
|
||||
class HiveonS19Plus(HiveonModern, S19Plus):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19i(Hiveon, S19i):
|
||||
class HiveonS19i(HiveonModern, S19i):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19Pro(Hiveon, S19Pro):
|
||||
class HiveonS19Pro(HiveonModern, S19Pro):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19ProPlus(Hiveon, S19ProPlus):
|
||||
class HiveonS19ProPlus(HiveonModern, S19ProPlus):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19XP(Hiveon, S19XP):
|
||||
class HiveonS19XP(HiveonModern, S19XP):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19a(Hiveon, S19a):
|
||||
class HiveonS19a(HiveonModern, S19a):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19aPro(Hiveon, S19aPro):
|
||||
class HiveonS19aPro(HiveonModern, S19aPro):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19j(Hiveon, S19j):
|
||||
class HiveonS19j(HiveonModern, S19j):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19jNoPIC(Hiveon, S19jNoPIC):
|
||||
class HiveonS19jNoPIC(HiveonModern, S19jNoPIC):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19jPro(Hiveon, S19jPro):
|
||||
class HiveonS19jPro(HiveonModern, S19jPro):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19L(Hiveon, S19L):
|
||||
class HiveonS19L(HiveonModern, S19L):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19ProHydro(Hiveon, S19ProHydro):
|
||||
class HiveonS19ProHydro(HiveonModern, S19ProHydro):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19Hydro(Hiveon, S19Hydro):
|
||||
class HiveonS19Hydro(HiveonModern, S19Hydro):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19ProPlusHydro(Hiveon, S19ProPlusHydro):
|
||||
class HiveonS19ProPlusHydro(HiveonModern, S19ProPlusHydro):
|
||||
pass
|
||||
|
||||
|
||||
class HiveonS19KPro(Hiveon, S19KPro):
|
||||
class HiveonS19KPro(HiveonModern, S19KPro):
|
||||
pass
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
# limitations under the License. -
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
from pyasic.miners.backends import Hiveon
|
||||
from pyasic.miners.backends import HiveonModern
|
||||
from pyasic.miners.device.models import T19
|
||||
|
||||
|
||||
class HiveonT19(Hiveon, T19):
|
||||
class HiveonT19(HiveonModern, T19):
|
||||
pass
|
||||
|
||||
@@ -21,7 +21,7 @@ import asyncssh
|
||||
from pyasic.data import HashBoard
|
||||
from pyasic.device.algorithm import AlgoHashRate, HashUnit
|
||||
from pyasic.errors import APIError
|
||||
from pyasic.miners.backends import Hiveon
|
||||
from pyasic.miners.backends import HiveonOld
|
||||
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
|
||||
from pyasic.miners.device.models import T9
|
||||
|
||||
@@ -71,7 +71,7 @@ HIVEON_T9_DATA_LOC = DataLocations(
|
||||
)
|
||||
|
||||
|
||||
class HiveonT9(Hiveon, T9):
|
||||
class HiveonT9(HiveonOld, T9):
|
||||
data_locations = HIVEON_T9_DATA_LOC
|
||||
|
||||
##################################################
|
||||
|
||||
@@ -25,7 +25,7 @@ from .cgminer import CGMiner
|
||||
from .epic import ePIC
|
||||
from .goldshell import GoldshellMiner
|
||||
from .hammer import BlackMiner
|
||||
from .hiveon import Hiveon
|
||||
from .hiveon import HiveonModern, HiveonOld
|
||||
from .iceriver import IceRiver
|
||||
from .innosilicon import Innosilicon
|
||||
from .luxminer import LUXMiner
|
||||
|
||||
@@ -746,7 +746,7 @@ class BOSer(BraiinsOSFirmware):
|
||||
"""Handler for new versions of BraiinsOS+ (post-gRPC)"""
|
||||
|
||||
_rpc_cls = BOSMinerRPCAPI
|
||||
web: BOSMinerRPCAPI
|
||||
rpc: BOSMinerRPCAPI
|
||||
_web_cls = BOSerWebAPI
|
||||
web: BOSerWebAPI
|
||||
|
||||
|
||||
@@ -16,13 +16,28 @@
|
||||
from typing import Optional
|
||||
|
||||
from pyasic import APIError
|
||||
from pyasic.config import MinerConfig, MiningModeConfig
|
||||
from pyasic.miners.backends import BMMiner
|
||||
from pyasic.miners.data import DataFunction, DataLocations, DataOptions, RPCAPICommand
|
||||
from pyasic.miners.data import (
|
||||
DataFunction,
|
||||
DataLocations,
|
||||
DataOptions,
|
||||
RPCAPICommand,
|
||||
WebAPICommand,
|
||||
)
|
||||
from pyasic.miners.device.firmware import HiveonFirmware
|
||||
from pyasic.web.hiveon import HiveonWebAPI
|
||||
|
||||
HIVEON_DATA_LOC = DataLocations(
|
||||
HIVEON_MODERN_DATA_LOC = DataLocations(
|
||||
**{
|
||||
str(DataOptions.MAC): DataFunction(
|
||||
"_get_mac",
|
||||
[WebAPICommand("web_get_system_info", "get_system_info")],
|
||||
),
|
||||
str(DataOptions.HOSTNAME): DataFunction(
|
||||
"_get_hostname",
|
||||
[WebAPICommand("web_get_system_info", "get_system_info")],
|
||||
),
|
||||
str(DataOptions.API_VERSION): DataFunction(
|
||||
"_get_api_ver",
|
||||
[RPCAPICommand("rpc_version", "version")],
|
||||
@@ -59,16 +74,194 @@ HIVEON_DATA_LOC = DataLocations(
|
||||
"_get_pools",
|
||||
[RPCAPICommand("rpc_pools", "pools")],
|
||||
),
|
||||
str(DataOptions.FAULT_LIGHT): DataFunction(
|
||||
"_get_fault_light",
|
||||
[WebAPICommand("web_get_blink_status", "get_blink_status")],
|
||||
),
|
||||
str(DataOptions.IS_MINING): DataFunction(
|
||||
"_is_mining",
|
||||
[WebAPICommand("web_get_conf", "get_miner_conf")],
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class Hiveon(HiveonFirmware, BMMiner):
|
||||
data_locations = HIVEON_DATA_LOC
|
||||
class HiveonModern(HiveonFirmware, BMMiner):
|
||||
data_locations = HIVEON_MODERN_DATA_LOC
|
||||
|
||||
web: HiveonWebAPI
|
||||
_web_cls = HiveonWebAPI
|
||||
|
||||
async def get_config(self) -> MinerConfig:
|
||||
data = await self.web.get_miner_conf()
|
||||
if data:
|
||||
self.config = MinerConfig.from_hiveon_modern(data)
|
||||
return self.config
|
||||
|
||||
async def fault_light_on(self) -> bool:
|
||||
data = await self.web.blink(blink=True)
|
||||
if data:
|
||||
if data.get("code") == "B000":
|
||||
self.light = True
|
||||
return self.light
|
||||
|
||||
async def fault_light_off(self) -> bool:
|
||||
data = await self.web.blink(blink=False)
|
||||
if data:
|
||||
if data.get("code") == "B100":
|
||||
self.light = False
|
||||
return self.light
|
||||
|
||||
async def reboot(self) -> bool:
|
||||
data = await self.web.reboot()
|
||||
if data:
|
||||
return True
|
||||
return False
|
||||
|
||||
async def stop_mining(self) -> bool:
|
||||
cfg = await self.get_config()
|
||||
cfg.miner_mode = MiningModeConfig.sleep()
|
||||
await self.send_config(cfg)
|
||||
return True
|
||||
|
||||
async def resume_mining(self) -> bool:
|
||||
cfg = await self.get_config()
|
||||
cfg.miner_mode = MiningModeConfig.normal()
|
||||
await self.send_config(cfg)
|
||||
return True
|
||||
|
||||
async def _get_wattage(self, rpc_stats: dict = None) -> Optional[int]:
|
||||
if not rpc_stats:
|
||||
try:
|
||||
rpc_stats = await self.rpc.stats()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if rpc_stats:
|
||||
boards = rpc_stats.get("STATS")
|
||||
try:
|
||||
wattage_raw = boards[1]["chain_power"]
|
||||
except (KeyError, IndexError):
|
||||
pass
|
||||
else:
|
||||
# parse wattage position out of raw data
|
||||
return round(float(wattage_raw.split(" ")[0]))
|
||||
|
||||
async def _get_hostname(self, web_get_system_info: dict = None) -> Optional[str]:
|
||||
if web_get_system_info is None:
|
||||
try:
|
||||
web_get_system_info = await self.web.get_system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_get_system_info is not None:
|
||||
try:
|
||||
return web_get_system_info["hostname"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_mac(self, web_get_system_info: dict = None) -> Optional[str]:
|
||||
if web_get_system_info is None:
|
||||
try:
|
||||
web_get_system_info = await self.web.get_system_info()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_get_system_info is not None:
|
||||
try:
|
||||
return web_get_system_info["macaddr"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
data = await self.web.get_network_info()
|
||||
if data:
|
||||
return data["macaddr"]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
async def _get_fault_light(
|
||||
self, web_get_blink_status: dict = None
|
||||
) -> Optional[bool]:
|
||||
if self.light:
|
||||
return self.light
|
||||
|
||||
if web_get_blink_status is None:
|
||||
try:
|
||||
web_get_blink_status = await self.web.get_blink_status()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_get_blink_status is not None:
|
||||
try:
|
||||
self.light = web_get_blink_status["blink"]
|
||||
except KeyError:
|
||||
pass
|
||||
return self.light
|
||||
|
||||
async def _is_mining(self, web_get_conf: dict = None) -> Optional[bool]:
|
||||
if web_get_conf is None:
|
||||
try:
|
||||
web_get_conf = await self.web.get_miner_conf()
|
||||
except APIError:
|
||||
pass
|
||||
|
||||
if web_get_conf is not None:
|
||||
try:
|
||||
if str(web_get_conf["bitmain-work-mode"]).isdigit():
|
||||
return (
|
||||
False if int(web_get_conf["bitmain-work-mode"]) == 1 else True
|
||||
)
|
||||
return False
|
||||
except LookupError:
|
||||
pass
|
||||
|
||||
|
||||
HIVEON_OLD_DATA_LOC = DataLocations(
|
||||
**{
|
||||
str(DataOptions.API_VERSION): DataFunction(
|
||||
"_get_api_ver",
|
||||
[RPCAPICommand("rpc_version", "version")],
|
||||
),
|
||||
str(DataOptions.FW_VERSION): DataFunction(
|
||||
"_get_fw_ver",
|
||||
[RPCAPICommand("rpc_version", "version")],
|
||||
),
|
||||
str(DataOptions.HASHRATE): DataFunction(
|
||||
"_get_hashrate",
|
||||
[RPCAPICommand("rpc_summary", "summary")],
|
||||
),
|
||||
str(DataOptions.EXPECTED_HASHRATE): DataFunction(
|
||||
"_get_expected_hashrate",
|
||||
[RPCAPICommand("rpc_stats", "stats")],
|
||||
),
|
||||
str(DataOptions.HASHBOARDS): DataFunction(
|
||||
"_get_hashboards",
|
||||
[RPCAPICommand("rpc_stats", "stats")],
|
||||
),
|
||||
str(DataOptions.FANS): DataFunction(
|
||||
"_get_fans",
|
||||
[RPCAPICommand("rpc_stats", "stats")],
|
||||
),
|
||||
str(DataOptions.UPTIME): DataFunction(
|
||||
"_get_uptime",
|
||||
[RPCAPICommand("rpc_stats", "stats")],
|
||||
),
|
||||
str(DataOptions.POOLS): DataFunction(
|
||||
"_get_pools",
|
||||
[RPCAPICommand("rpc_pools", "pools")],
|
||||
),
|
||||
str(DataOptions.WATTAGE): DataFunction(
|
||||
"_get_wattage",
|
||||
[RPCAPICommand("rpc_stats", "stats")],
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class HiveonOld(HiveonFirmware, BMMiner):
|
||||
data_locations = HIVEON_OLD_DATA_LOC
|
||||
|
||||
async def _get_wattage(self, rpc_stats: dict = None) -> Optional[int]:
|
||||
if not rpc_stats:
|
||||
try:
|
||||
|
||||
@@ -95,6 +95,7 @@ class VNish(VNishFirmware, BMMiner):
|
||||
web: VNishWebAPI
|
||||
|
||||
supports_shutdown = True
|
||||
supports_presets = True
|
||||
|
||||
data_locations = VNISH_DATA_LOC
|
||||
|
||||
@@ -266,7 +267,8 @@ class VNish(VNishFirmware, BMMiner):
|
||||
async def get_config(self) -> MinerConfig:
|
||||
try:
|
||||
web_settings = await self.web.settings()
|
||||
web_presets = await self.web.autotune_presets()
|
||||
except APIError:
|
||||
return self.config
|
||||
self.config = MinerConfig.from_vnish(web_settings)
|
||||
self.config = MinerConfig.from_vnish(web_settings, web_presets)
|
||||
return self.config
|
||||
|
||||
@@ -56,6 +56,7 @@ class MinerProtocol(Protocol):
|
||||
|
||||
supports_shutdown: bool = False
|
||||
supports_power_modes: bool = False
|
||||
supports_presets: bool = False
|
||||
supports_autotuning: bool = False
|
||||
|
||||
api_ver: str = None
|
||||
|
||||
@@ -424,9 +424,10 @@ MINER_CLASSES = {
|
||||
"BLOCKMINER 720I": ePICBlockMiner720i,
|
||||
},
|
||||
MinerTypes.HIVEON: {
|
||||
None: Hiveon,
|
||||
None: HiveonModern,
|
||||
"ANTMINER T9": HiveonT9,
|
||||
"ANTMINER S19JPRO": HiveonS19jPro,
|
||||
"ANTMINER S19": HiveonS19,
|
||||
},
|
||||
MinerTypes.LUX_OS: {
|
||||
None: LUXMiner,
|
||||
@@ -864,7 +865,7 @@ class MinerFactory:
|
||||
miner_type: MinerTypes | None,
|
||||
) -> AnyMiner | None:
|
||||
# special case since hiveon miners return web results copying the antminer stock FW
|
||||
if "HIVEON" in str(miner_model).upper() and miner_type == MinerTypes.ANTMINER:
|
||||
if "HIVEON" in str(miner_model).upper():
|
||||
miner_model = str(miner_model).upper().replace(" HIVEON", "")
|
||||
miner_type = MinerTypes.HIVEON
|
||||
try:
|
||||
@@ -873,7 +874,7 @@ class MinerFactory:
|
||||
if miner_type in MINER_CLASSES:
|
||||
if miner_model is not None:
|
||||
warnings.warn(
|
||||
f"Partially supported miner found: {miner_model}, please open an issue with miner data "
|
||||
f"Partially supported miner found: {miner_model}, type: {miner_type}, please open an issue with miner data "
|
||||
f"and this model on GitHub (https://github.com/UpstreamData/pyasic/issues)."
|
||||
)
|
||||
return MINER_CLASSES[miner_type][None](ip)
|
||||
|
||||
@@ -37,7 +37,7 @@ _settings = { # defaults
|
||||
"default_goldshell_web_password": "123456789",
|
||||
"default_auradine_web_password": "admin",
|
||||
"default_epic_web_password": "letmein",
|
||||
"default_hive_web_password": "admin",
|
||||
"default_hive_web_password": "root",
|
||||
"default_iceriver_web_password": "12345678",
|
||||
"default_antminer_ssh_password": "miner",
|
||||
"default_bosminer_ssh_password": "root",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "pyasic"
|
||||
version = "0.64.14"
|
||||
version = "0.65.3"
|
||||
description = "A simplified and standardized interface for Bitcoin ASICs."
|
||||
authors = ["UpstreamData <brett@upstreamdata.ca>"]
|
||||
repository = "https://github.com/UpstreamData/pyasic"
|
||||
|
||||
Reference in New Issue
Block a user