Compare commits
10 Commits
v0.50.7rc1
...
v0.51.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c50d55e87c | ||
|
|
5e5516bfb3 | ||
|
|
4b068c57c5 | ||
|
|
203f199aec | ||
|
|
895f17aaf9 | ||
|
|
8a64ff3559 | ||
|
|
4c45d356c4 | ||
|
|
4dec329f11 | ||
|
|
b563ed118e | ||
|
|
75b2ec40b1 |
@@ -108,31 +108,31 @@ class MiningModeHPM(MinerConfigValue):
|
||||
return {"mode": {"mode": "turbo"}}
|
||||
|
||||
|
||||
class StandardPowerTuneAlgo(MinerConfigValue):
|
||||
class StandardTuneAlgo(MinerConfigValue):
|
||||
mode: str = field(init=False, default="standard")
|
||||
|
||||
def as_epic(self) -> str:
|
||||
return VOptPowerTuneAlgo().as_epic()
|
||||
return VOptAlgo().as_epic()
|
||||
|
||||
|
||||
class VOptPowerTuneAlgo(MinerConfigValue):
|
||||
class VOptAlgo(MinerConfigValue):
|
||||
mode: str = field(init=False, default="standard")
|
||||
|
||||
def as_epic(self) -> str:
|
||||
return "VoltageOptimizer"
|
||||
|
||||
|
||||
class ChipTunePowerTuneAlgo(MinerConfigValue):
|
||||
class ChipTuneAlgo(MinerConfigValue):
|
||||
mode: str = field(init=False, default="standard")
|
||||
|
||||
def as_epic(self) -> str:
|
||||
return "ChipTune"
|
||||
|
||||
|
||||
class PowerTunerAlgo(MinerConfigOption):
|
||||
standard = StandardPowerTuneAlgo
|
||||
voltage_optimizer = VOptPowerTuneAlgo
|
||||
chip_tune = ChipTunePowerTuneAlgo
|
||||
class TunerAlgo(MinerConfigOption):
|
||||
standard = StandardTuneAlgo
|
||||
voltage_optimizer = VOptAlgo
|
||||
chip_tune = ChipTuneAlgo
|
||||
|
||||
@classmethod
|
||||
def default(cls):
|
||||
@@ -143,7 +143,7 @@ class PowerTunerAlgo(MinerConfigOption):
|
||||
class MiningModePowerTune(MinerConfigValue):
|
||||
mode: str = field(init=False, default="power_tuning")
|
||||
power: int = None
|
||||
algo: PowerTunerAlgo = field(default_factory=PowerTunerAlgo.default)
|
||||
algo: TunerAlgo = field(default_factory=TunerAlgo.default)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, dict_conf: dict | None) -> "MiningModePowerTune":
|
||||
@@ -183,14 +183,12 @@ class MiningModePowerTune(MinerConfigValue):
|
||||
def as_auradine(self) -> dict:
|
||||
return {"mode": {"mode": "custom", "tune": "power", "power": self.power}}
|
||||
|
||||
def as_epic(self) -> dict:
|
||||
return {"ptune": {"algo": self.algo.as_epic(), "target": self.power}}
|
||||
|
||||
|
||||
@dataclass
|
||||
class MiningModeHashrateTune(MinerConfigValue):
|
||||
mode: str = field(init=False, default="hashrate_tuning")
|
||||
hashrate: int = None
|
||||
algo: TunerAlgo = field(default_factory=TunerAlgo.default)
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, dict_conf: dict | None) -> "MiningModeHashrateTune":
|
||||
@@ -218,6 +216,9 @@ class MiningModeHashrateTune(MinerConfigValue):
|
||||
def as_auradine(self) -> dict:
|
||||
return {"mode": {"mode": "custom", "tune": "ths", "ths": self.hashrate}}
|
||||
|
||||
def as_epic(self) -> dict:
|
||||
return {"ptune": {"algo": self.algo.as_epic(), "target": self.hashrate}}
|
||||
|
||||
|
||||
@dataclass
|
||||
class ManualBoardSettings(MinerConfigValue):
|
||||
@@ -313,14 +314,14 @@ class MiningModeConfig(MinerConfigOption):
|
||||
if tuner_running:
|
||||
algo_info = web_conf["PerpetualTune"]["Algorithm"]
|
||||
if algo_info.get("VoltageOptimizer") is not None:
|
||||
return cls.power_tuning(
|
||||
power=algo_info["VoltageOptimizer"]["Target"],
|
||||
algo=PowerTunerAlgo.voltage_optimizer,
|
||||
return cls.hashrate_tuning(
|
||||
hashrate=algo_info["VoltageOptimizer"]["Target"],
|
||||
algo=TunerAlgo.voltage_optimizer,
|
||||
)
|
||||
else:
|
||||
return cls.power_tuning(
|
||||
power=algo_info["ChipTune"]["Target"],
|
||||
algo=PowerTunerAlgo.chip_tune,
|
||||
return cls.hashrate_tuning(
|
||||
hashrate=algo_info["ChipTune"]["Target"],
|
||||
algo=TunerAlgo.chip_tune,
|
||||
)
|
||||
else:
|
||||
return cls.normal()
|
||||
|
||||
@@ -206,7 +206,7 @@ class AntminerModern(BMMiner):
|
||||
]
|
||||
|
||||
try:
|
||||
rpc_stats = await self.rpc.send_command("stats", new_rpc=True)
|
||||
rpc_stats = await self.rpc.send_command("stats", new_api=True)
|
||||
except APIError:
|
||||
return hashboards
|
||||
|
||||
|
||||
@@ -205,13 +205,14 @@ class VNish(BMMiner):
|
||||
if web_summary is None:
|
||||
web_summary = await self.web.summary()
|
||||
|
||||
fw_ver = None
|
||||
if web_summary is not None:
|
||||
try:
|
||||
fw_ver = web_summary["miner"]["miner_type"]
|
||||
fw_ver = fw_ver.split("(Vnish ")[1].replace(")", "")
|
||||
return fw_ver
|
||||
except KeyError:
|
||||
pass
|
||||
except LookupError:
|
||||
return fw_ver
|
||||
|
||||
async def get_config(self) -> MinerConfig:
|
||||
try:
|
||||
|
||||
@@ -196,12 +196,15 @@ If you are sure you want to use this command please use API.send_command("{comma
|
||||
async def _send_bytes(
|
||||
self,
|
||||
data: bytes,
|
||||
port: int = None,
|
||||
timeout: int = 100,
|
||||
) -> bytes:
|
||||
if port is None:
|
||||
port = self.port
|
||||
logging.debug(f"{self} - ([Hidden] Send Bytes) - Sending")
|
||||
try:
|
||||
# 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), port)
|
||||
# handle OSError 121
|
||||
except OSError as e:
|
||||
if e.errno == 121:
|
||||
@@ -233,14 +236,7 @@ If you are sure you want to use this command please use API.send_command("{comma
|
||||
# loop to receive all the data
|
||||
logging.debug(f"{self} - ([Hidden] Send Bytes) - Receiving")
|
||||
try:
|
||||
while True:
|
||||
try:
|
||||
d = await asyncio.wait_for(reader.read(4096), timeout=timeout)
|
||||
if not d:
|
||||
break
|
||||
ret_data += d
|
||||
except (asyncio.CancelledError, asyncio.TimeoutError) as e:
|
||||
raise e
|
||||
ret_data = await asyncio.wait_for(reader.read(), timeout=timeout)
|
||||
except (asyncio.CancelledError, asyncio.TimeoutError) as e:
|
||||
raise e
|
||||
except Exception as e:
|
||||
|
||||
@@ -24,6 +24,7 @@ import logging
|
||||
import re
|
||||
from typing import Literal, Union
|
||||
|
||||
import httpx
|
||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||
from passlib.handlers.md5_crypt import md5_crypt
|
||||
|
||||
@@ -240,6 +241,28 @@ class BTMinerRPCAPI(BaseMinerRPCAPI):
|
||||
ignore_errors: bool = False,
|
||||
timeout: int = 10,
|
||||
**kwargs,
|
||||
) -> dict:
|
||||
try:
|
||||
return await self._send_privileged_command(
|
||||
command=command, ignore_errors=ignore_errors, timeout=timeout, **kwargs
|
||||
)
|
||||
except APIError as e:
|
||||
if not e.message == "can't access write cmd":
|
||||
raise
|
||||
try:
|
||||
await self.open_api()
|
||||
except Exception as e:
|
||||
raise APIError("Failed to open whatsminer API.") from e
|
||||
return await self._send_privileged_command(
|
||||
command=command, ignore_errors=ignore_errors, timeout=timeout, **kwargs
|
||||
)
|
||||
|
||||
async def _send_privileged_command(
|
||||
self,
|
||||
command: Union[str, bytes],
|
||||
ignore_errors: bool = False,
|
||||
timeout: int = 10,
|
||||
**kwargs,
|
||||
) -> dict:
|
||||
logging.debug(
|
||||
f"{self} - (Send Privileged Command) - {command} " + f"with args {kwargs}"
|
||||
@@ -321,6 +344,30 @@ class BTMinerRPCAPI(BaseMinerRPCAPI):
|
||||
logging.debug(f"{self} - (Get Token) - Gathered token data: {self.token}")
|
||||
return self.token
|
||||
|
||||
async def open_api(self):
|
||||
async with httpx.AsyncClient() as c:
|
||||
stage1_req = (
|
||||
await c.post(
|
||||
"https://wmt.pyasic.org/v1/stage1",
|
||||
json={"ip": self.ip},
|
||||
follow_redirects=True,
|
||||
)
|
||||
).json()
|
||||
stage1_res = binascii.hexlify(
|
||||
await self._send_bytes(binascii.unhexlify(stage1_req), port=8889)
|
||||
)
|
||||
stage2_req = (
|
||||
await c.post(
|
||||
"https://wmt.pyasic.org/v1/stage2",
|
||||
json={"ip": self.ip, "stage1_result": stage1_res.decode("utf-8")},
|
||||
)
|
||||
).json()
|
||||
try:
|
||||
await self._send_bytes(binascii.unhexlify(stage2_req), timeout=3, port=8889)
|
||||
except asyncio.TimeoutError:
|
||||
pass
|
||||
return True
|
||||
|
||||
#### PRIVILEGED COMMANDS ####
|
||||
# Please read the top of this file to learn
|
||||
# how to configure the Whatsminer API to
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "pyasic"
|
||||
version = "0.50.7rc1"
|
||||
version = "0.51.1"
|
||||
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