diff --git a/docs/index.md b/docs/index.md index c2b4da1e..7ceebc6f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -118,6 +118,8 @@ These functions are [`get_model`](#get-model), [`reboot`](#reboot), [`restart_backend`](#restart-backend), and +[`stop_mining`](#stop-mining), and +[`resume_mining`](#resume-mining), and [`send_config`](#send-config).
@@ -202,6 +204,22 @@ These functions are
+### Stop Mining +::: pyasic.miners.BaseMiner.stop_mining + handler: python + options: + heading_level: 4 + +
+ +### Resume Mining +::: pyasic.miners.BaseMiner.resume_mining + handler: python + options: + heading_level: 4 + +
+ ### Send Config ::: pyasic.miners.BaseMiner.send_config handler: python diff --git a/pyasic/data/error_codes/__init__.py b/pyasic/data/error_codes/__init__.py index 219f8f1d..484a0507 100644 --- a/pyasic/data/error_codes/__init__.py +++ b/pyasic/data/error_codes/__init__.py @@ -16,3 +16,9 @@ from .whatsminer import WhatsminerError from .bos import BraiinsOSError from .X19 import X19Error from .innosilicon import InnosiliconError + +from typing import TypeVar + +MinerErrorData = TypeVar( + "MinerErrorData", WhatsminerError, BraiinsOSError, X19Error, InnosiliconError +) diff --git a/pyasic/miners/_backends/bmminer.py b/pyasic/miners/_backends/bmminer.py index 392095e5..499d5cd6 100644 --- a/pyasic/miners/_backends/bmminer.py +++ b/pyasic/miners/_backends/bmminer.py @@ -14,7 +14,7 @@ import ipaddress import logging -from typing import Union +from typing import Union, List from pyasic.API.bmminer import BMMinerAPI @@ -22,6 +22,7 @@ from pyasic.miners.base import BaseMiner from pyasic.data import MinerData from pyasic.config import MinerConfig +from pyasic.data.error_codes import MinerErrorData from pyasic.settings import PyasicSettings @@ -169,7 +170,7 @@ class BMMiner(BaseMiner): async def fault_light_on(self) -> bool: return False - async def get_errors(self) -> list: + async def get_errors(self) -> List[MinerErrorData]: return [] async def get_mac(self) -> str: @@ -178,6 +179,12 @@ class BMMiner(BaseMiner): async def restart_backend(self) -> bool: return False + async def stop_mining(self) -> bool: + return False + + async def resume_mining(self) -> bool: + return False + async def get_data(self) -> MinerData: """Get data from the miner. diff --git a/pyasic/miners/_backends/bosminer.py b/pyasic/miners/_backends/bosminer.py index 80a2e797..9263a1bf 100644 --- a/pyasic/miners/_backends/bosminer.py +++ b/pyasic/miners/_backends/bosminer.py @@ -15,7 +15,7 @@ import ipaddress import logging import json -from typing import Union +from typing import Union, List import toml @@ -24,7 +24,7 @@ from pyasic.miners.base import BaseMiner from pyasic.API.bosminer import BOSMinerAPI from pyasic.errors import APIError -from pyasic.data.error_codes import BraiinsOSError +from pyasic.data.error_codes import BraiinsOSError, MinerErrorData from pyasic.data import MinerData from pyasic.config import MinerConfig @@ -103,6 +103,20 @@ class BOSMiner(BaseMiner): return True return False + async def stop_mining(self) -> bool: + data = await self.api.pause() + if data.get("PAUSE"): + if data["PAUSE"][0]: + return True + return False + + async def resume_mining(self) -> bool: + data = await self.api.resume() + if data.get("RESUME"): + if data["RESUME"][0]: + return True + return False + async def reboot(self) -> bool: """Reboots power to the physical miner.""" logging.debug(f"{self}: Sending reboot command.") @@ -242,7 +256,7 @@ class BOSMiner(BaseMiner): self.light = True return self.light - async def get_errors(self) -> list: + async def get_errors(self) -> List[MinerErrorData]: tunerstatus = None errors = [] diff --git a/pyasic/miners/_backends/bosminer_old.py b/pyasic/miners/_backends/bosminer_old.py index 9768c1c9..eef574a6 100644 --- a/pyasic/miners/_backends/bosminer_old.py +++ b/pyasic/miners/_backends/bosminer_old.py @@ -15,12 +15,13 @@ import logging import ipaddress -from typing import Union +from typing import Union, List from pyasic.API.bosminer import BOSMinerAPI from pyasic.miners.base import BaseMiner from pyasic.config import MinerConfig from pyasic.data import MinerData +from pyasic.data.error_codes import MinerErrorData class BOSMinerOld(BaseMiner): @@ -77,7 +78,7 @@ class BOSMinerOld(BaseMiner): async def get_config(self) -> None: return None - async def get_errors(self) -> list: + async def get_errors(self) -> List[MinerErrorData]: return [] async def get_hostname(self) -> str: @@ -95,6 +96,12 @@ class BOSMinerOld(BaseMiner): async def restart_backend(self) -> bool: return False + async def stop_mining(self) -> bool: + return False + + async def resume_mining(self) -> bool: + return False + async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None: return None diff --git a/pyasic/miners/_backends/btminer.py b/pyasic/miners/_backends/btminer.py index 4df0c608..ba945026 100644 --- a/pyasic/miners/_backends/btminer.py +++ b/pyasic/miners/_backends/btminer.py @@ -14,7 +14,7 @@ import ipaddress import logging -from typing import Union +from typing import Union, List from pyasic.API.btminer import BTMinerAPI @@ -22,7 +22,7 @@ from pyasic.miners.base import BaseMiner from pyasic.errors import APIError from pyasic.data import MinerData -from pyasic.data.error_codes import WhatsminerError +from pyasic.data.error_codes import WhatsminerError, MinerErrorData from pyasic.config import MinerConfig from pyasic.settings import PyasicSettings @@ -156,13 +156,44 @@ class BTMiner(BaseMiner): return True return False - async def get_errors(self) -> list: - return [] + async def get_errors(self) -> List[MinerErrorData]: + data = [] + + summary_data = await self.api.summary() + if summary_data[0].get("Error Code Count"): + for i in range(summary_data[0]["Error Code Count"]): + if summary_data[0].get(f"Error Code {i}"): + data.append( + WhatsminerError(error_code=summary_data[0][f"Error Code {i}"]) + ) + return data async def reboot(self) -> bool: + data = await self.api.reboot() + if data.get("Msg"): + if data["Msg"] == "API command OK": + return True return False async def restart_backend(self) -> bool: + data = await self.api.restart() + if data.get("Msg"): + if data["Msg"] == "API command OK": + return True + return False + + async def stop_mining(self) -> bool: + data = await self.api.power_off(respbefore=True) + if data.get("Msg"): + if data["Msg"] == "API command OK": + return True + return False + + async def resume_mining(self) -> bool: + data = await self.api.power_on() + if data.get("Msg"): + if data["Msg"] == "API command OK": + return True return False async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None: diff --git a/pyasic/miners/_backends/cgminer.py b/pyasic/miners/_backends/cgminer.py index 89426b05..99c05e9c 100644 --- a/pyasic/miners/_backends/cgminer.py +++ b/pyasic/miners/_backends/cgminer.py @@ -14,7 +14,7 @@ import ipaddress import logging -from typing import Union +from typing import Union, List from pyasic.API.cgminer import CGMinerAPI @@ -23,6 +23,7 @@ from pyasic.errors import APIError from pyasic.config import MinerConfig from pyasic.data import MinerData +from pyasic.data.error_codes import MinerErrorData from pyasic.settings import PyasicSettings @@ -118,8 +119,7 @@ class CGMiner(BaseMiner): return True return False - async def start_cgminer(self) -> None: - """Start cgminer hashing process.""" + async def resume_mining(self) -> bool: commands = [ "mkdir -p /etc/tmp/", 'echo "*/3 * * * * /usr/bin/cgminer-monitor" > /etc/tmp/root', @@ -128,9 +128,9 @@ class CGMiner(BaseMiner): ] commands = ";".join(commands) await self.send_ssh_command(commands) + return True - async def stop_cgminer(self) -> None: - """Restart cgminer hashing process.""" + async def stop_mining(self) -> bool: commands = [ "mkdir -p /etc/tmp/", 'echo "" > /etc/tmp/root', @@ -139,6 +139,7 @@ class CGMiner(BaseMiner): ] commands = ";".join(commands) await self.send_ssh_command(commands) + return True async def get_config(self) -> str: """Gets the config for the miner and sets it as `self.config`. @@ -163,7 +164,7 @@ class CGMiner(BaseMiner): async def fault_light_on(self) -> bool: return False - async def get_errors(self) -> list: + async def get_errors(self) -> List[MinerErrorData]: return [] async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None: diff --git a/pyasic/miners/antminer/bmminer/X19/X19.py b/pyasic/miners/antminer/bmminer/X19/X19.py index 9e3ea878..c31a0ff0 100644 --- a/pyasic/miners/antminer/bmminer/X19/X19.py +++ b/pyasic/miners/antminer/bmminer/X19/X19.py @@ -15,7 +15,7 @@ from pyasic.miners._backends import BMMiner # noqa - Ignore access to _module from pyasic.config import MinerConfig -from pyasic.data.error_codes import X19Error +from pyasic.data.error_codes import X19Error, MinerErrorData from pyasic.settings import PyasicSettings import httpx @@ -132,7 +132,7 @@ class BMMinerX19(BMMiner): return True return False - async def get_errors(self) -> List[X19Error]: + async def get_errors(self) -> List[MinerErrorData]: errors = [] url = f"http://{self.ip}/cgi-bin/summary.cgi" auth = httpx.DigestAuth(self.uname, self.pwd) @@ -147,12 +147,14 @@ class BMMinerX19(BMMiner): errors.append(X19Error(item["msg"])) return errors - async def stop_mining(self) -> None: + async def stop_mining(self) -> bool: cfg = await self.get_config() cfg.autotuning_wattage = 0 await self.send_config(cfg) + return True - async def resume_mining(self): + async def resume_mining(self) -> bool: cfg = await self.get_config() cfg.autotuning_wattage = 1 await self.send_config(cfg) + return True diff --git a/pyasic/miners/avalonminer/cgminer/A10X/A10X.py b/pyasic/miners/avalonminer/cgminer/A10X/A10X.py index 9fca43b4..d4073da1 100644 --- a/pyasic/miners/avalonminer/cgminer/A10X/A10X.py +++ b/pyasic/miners/avalonminer/cgminer/A10X/A10X.py @@ -51,6 +51,12 @@ class CGMinerA10X(CGMiner): return True return False + async def stop_mining(self) -> bool: + return False + + async def resume_mining(self) -> bool: + return False + async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None: """Configures miner with yaml config.""" raise NotImplementedError diff --git a/pyasic/miners/avalonminer/cgminer/A7X/A7X.py b/pyasic/miners/avalonminer/cgminer/A7X/A7X.py index 3ca3c394..459b4af7 100644 --- a/pyasic/miners/avalonminer/cgminer/A7X/A7X.py +++ b/pyasic/miners/avalonminer/cgminer/A7X/A7X.py @@ -51,6 +51,12 @@ class CGMinerA7X(CGMiner): return True return False + async def stop_mining(self) -> bool: + return False + + async def resume_mining(self) -> bool: + return False + async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None: """Configures miner with yaml config.""" raise NotImplementedError diff --git a/pyasic/miners/avalonminer/cgminer/A8X/A8X.py b/pyasic/miners/avalonminer/cgminer/A8X/A8X.py index 76a3470a..1f47cb42 100644 --- a/pyasic/miners/avalonminer/cgminer/A8X/A8X.py +++ b/pyasic/miners/avalonminer/cgminer/A8X/A8X.py @@ -51,6 +51,12 @@ class CGMinerA8X(CGMiner): return True return False + async def stop_mining(self) -> bool: + return False + + async def resume_mining(self) -> bool: + return False + async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None: """Configures miner with yaml config.""" raise NotImplementedError diff --git a/pyasic/miners/avalonminer/cgminer/A9X/A921.py b/pyasic/miners/avalonminer/cgminer/A9X/A921.py index 8beba58f..959bc3f7 100644 --- a/pyasic/miners/avalonminer/cgminer/A9X/A921.py +++ b/pyasic/miners/avalonminer/cgminer/A9X/A921.py @@ -52,6 +52,12 @@ class CGMinerAvalon921(CGMiner, Avalon921): return True return False + async def stop_mining(self) -> bool: + return False + + async def resume_mining(self) -> bool: + return False + async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None: """Configures miner with yaml config.""" raise NotImplementedError diff --git a/pyasic/miners/base.py b/pyasic/miners/base.py index 01de23fb..fcdbe964 100644 --- a/pyasic/miners/base.py +++ b/pyasic/miners/base.py @@ -25,6 +25,7 @@ from pyasic.data.error_codes import ( BraiinsOSError, InnosiliconError, X19Error, + MinerErrorData, ) @@ -181,9 +182,7 @@ class BaseMiner(ABC): pass @abstractmethod - async def get_errors( - self, - ) -> List[Union[WhatsminerError, BraiinsOSError, InnosiliconError, X19Error]]: + async def get_errors(self) -> List[MinerErrorData]: """Get a list of the errors the miner is experiencing. Returns: @@ -200,5 +199,23 @@ class BaseMiner(ABC): """ return MinerData(ip=str(self.ip)) + @abstractmethod + async def stop_mining(self) -> bool: + """Stop the mining process of the miner. + + Returns: + A boolean value of the success of stopping the mining process. + """ + pass + + @abstractmethod + async def resume_mining(self) -> bool: + """Stop the mining process of the miner. + + Returns: + A boolean value of the success of resuming the mining process. + """ + pass + AnyMiner = TypeVar("AnyMiner", bound=BaseMiner) diff --git a/pyasic/miners/innosilicon/cgminer/T3X/T3H_Plus.py b/pyasic/miners/innosilicon/cgminer/T3X/T3H_Plus.py index 49e8365c..39331c89 100644 --- a/pyasic/miners/innosilicon/cgminer/T3X/T3H_Plus.py +++ b/pyasic/miners/innosilicon/cgminer/T3X/T3H_Plus.py @@ -15,14 +15,14 @@ from pyasic.miners._backends import CGMiner # noqa - Ignore access to _module from pyasic.miners._types import InnosiliconT3HPlus # noqa - Ignore access to _module from pyasic.data import MinerData -from pyasic.data.error_codes import InnosiliconError +from pyasic.data.error_codes import InnosiliconError, MinerErrorData from pyasic.settings import PyasicSettings from pyasic.config import MinerConfig from pyasic.errors import APIError import httpx import warnings -from typing import Union +from typing import Union, List import logging @@ -142,7 +142,7 @@ class CGMinerInnosiliconT3HPlus(CGMiner, InnosiliconT3HPlus): "updatePools", data=config.as_inno(user_suffix=user_suffix) ) - async def get_errors(self) -> list: + async def get_errors(self) -> List[MinerErrorData]: errors = [] try: data = await self.send_web_command("getErrorDetail") diff --git a/pyasic/miners/unknown.py b/pyasic/miners/unknown.py index 555110d5..4d8e1feb 100644 --- a/pyasic/miners/unknown.py +++ b/pyasic/miners/unknown.py @@ -12,10 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +from typing import List + from pyasic.API.unknown import UnknownAPI from pyasic.miners.base import BaseMiner from pyasic.config import MinerConfig from pyasic.data import MinerData +from pyasic.data.error_codes import MinerErrorData class UnknownMiner(BaseMiner): @@ -48,7 +51,7 @@ class UnknownMiner(BaseMiner): async def get_config(self) -> None: return None - async def get_errors(self) -> list: + async def get_errors(self) -> List[MinerErrorData]: return [] async def get_mac(self) -> str: @@ -60,6 +63,12 @@ class UnknownMiner(BaseMiner): async def restart_backend(self) -> bool: return False + async def stop_mining(self) -> bool: + return False + + async def resume_mining(self) -> bool: + return False + async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None: return None