feature: add more hiveon functionality
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -424,7 +424,7 @@ MINER_CLASSES = {
|
||||
"BLOCKMINER 720I": ePICBlockMiner720i,
|
||||
},
|
||||
MinerTypes.HIVEON: {
|
||||
None: Hiveon,
|
||||
None: HiveonModern,
|
||||
"ANTMINER T9": HiveonT9,
|
||||
"ANTMINER S19JPRO": HiveonS19jPro,
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user