diff --git a/docs/index.md b/docs/index.md index 71b14e5a..850d62dd 100644 --- a/docs/index.md +++ b/docs/index.md @@ -9,6 +9,8 @@ ## Intro Welcome to pyasic! Pyasic uses an asynchronous method of communicating with asic miners on your network, which makes it super fast. +[Supported Miner Types](miners/supported_types.md) + Getting started with pyasic is easy. First, find your miner (or miners) on the network by scanning for them or getting the correct class automatically for them if you know the IP.
diff --git a/docs/miners/antminer/X17.md b/docs/miners/antminer/X17.md new file mode 100644 index 00000000..a4fcfa81 --- /dev/null +++ b/docs/miners/antminer/X17.md @@ -0,0 +1,59 @@ +# pyasic +## X17 Models + +## S17 + +::: pyasic.miners.antminer.bmminer.X17.S17.BMMinerS17 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## S17+ + +::: pyasic.miners.antminer.bmminer.X17.S17_Plus.BMMinerS17Plus + handler: python + options: + show_root_heading: false + heading_level: 4 + +## S17 Pro + +::: pyasic.miners.antminer.bmminer.X17.S17_Pro.BMMinerS17Pro + handler: python + options: + show_root_heading: false + heading_level: 4 + +## S17e + +::: pyasic.miners.antminer.bmminer.X17.S17e.BMMinerS17e + handler: python + options: + show_root_heading: false + heading_level: 4 + +## T17 + +::: pyasic.miners.antminer.bmminer.X17.T17.BMMinerT17 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## T17+ + +::: pyasic.miners.antminer.bmminer.X17.T17_Plus.BMMinerT17Plus + handler: python + options: + show_root_heading: false + heading_level: 4 + + +## T17e + +::: pyasic.miners.antminer.bmminer.X17.T17e.BMMinerT17e + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/miners/antminer/X19.md b/docs/miners/antminer/X19.md new file mode 100644 index 00000000..c7f4b023 --- /dev/null +++ b/docs/miners/antminer/X19.md @@ -0,0 +1,52 @@ +# pyasic +## X19 Models + +## S19 + +::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## S19 Pro + +::: pyasic.miners.antminer.bmminer.X19.S19_Pro.BMMinerS19Pro + handler: python + options: + show_root_heading: false + heading_level: 4 + + +## S19a + +::: pyasic.miners.antminer.bmminer.X19.S19a.BMMinerS19a + handler: python + options: + show_root_heading: false + heading_level: 4 + + +## S19j + +::: pyasic.miners.antminer.bmminer.X19.S19j.BMMinerS19j + handler: python + options: + show_root_heading: false + heading_level: 4 + +## S19j Pro + +::: pyasic.miners.antminer.bmminer.X19.S19j_Pro.BMMinerS19jPro + handler: python + options: + show_root_heading: false + heading_level: 4 + +## T19 + +::: pyasic.miners.antminer.bmminer.X19.T19.BMMinerT19 + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/miners/antminer/X9.md b/docs/miners/antminer/X9.md new file mode 100644 index 00000000..eb2ab0d6 --- /dev/null +++ b/docs/miners/antminer/X9.md @@ -0,0 +1,26 @@ +# pyasic +## X9 Models + +## S9 + +::: pyasic.miners.antminer.bmminer.X9.S9.BMMinerS9 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## S9i + +::: pyasic.miners.antminer.bmminer.X9.S9i.BMMinerS9i + handler: python + options: + show_root_heading: false + heading_level: 4 + +## T9 + +::: pyasic.miners.antminer.bmminer.X9.T9.BMMinerT9 + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/miners/avalonminer/A10X.md b/docs/miners/avalonminer/A10X.md new file mode 100644 index 00000000..b5b37792 --- /dev/null +++ b/docs/miners/avalonminer/A10X.md @@ -0,0 +1,26 @@ +# pyasic +## A10X Models + +## A1026 + +::: pyasic.miners.avalonminer.cgminer.A10X.A1026.CGMinerAvalon1026 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## A1047 + +::: pyasic.miners.avalonminer.cgminer.A10X.A1047.CGMinerAvalon1047 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## A1066 + +::: pyasic.miners.avalonminer.cgminer.A10X.A1066.CGMinerAvalon1066 + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/miners/avalonminer/A7X.md b/docs/miners/avalonminer/A7X.md new file mode 100644 index 00000000..09571157 --- /dev/null +++ b/docs/miners/avalonminer/A7X.md @@ -0,0 +1,26 @@ +# pyasic +## A7X Models + +## A721 + +::: pyasic.miners.avalonminer.cgminer.A7X.A721.CGMinerAvalon721 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## A741 + +::: pyasic.miners.avalonminer.cgminer.A7X.A741.CGMinerAvalon741 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## A761 + +::: pyasic.miners.avalonminer.cgminer.A7X.A761.CGMinerAvalon761 + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/miners/avalonminer/A8X.md b/docs/miners/avalonminer/A8X.md new file mode 100644 index 00000000..53ddf787 --- /dev/null +++ b/docs/miners/avalonminer/A8X.md @@ -0,0 +1,26 @@ +# pyasic +## A8X Models + +## A821 + +::: pyasic.miners.avalonminer.cgminer.A8X.A821.CGMinerAvalon821 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## A841 + +::: pyasic.miners.avalonminer.cgminer.A8X.A841.CGMinerAvalon841 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## A851 + +::: pyasic.miners.avalonminer.cgminer.A8X.A851.CGMinerAvalon851 + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/miners/avalonminer/A9X.md b/docs/miners/avalonminer/A9X.md new file mode 100644 index 00000000..41325831 --- /dev/null +++ b/docs/miners/avalonminer/A9X.md @@ -0,0 +1,10 @@ +# pyasic +## A9X Models + +## A921 + +::: pyasic.miners.avalonminer.cgminer.A9X.A921.CGMinerAvalon921 + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/miners/backends/bmminer.md b/docs/miners/backends/bmminer.md new file mode 100644 index 00000000..efd33e50 --- /dev/null +++ b/docs/miners/backends/bmminer.md @@ -0,0 +1,8 @@ +# pyasic +## BMMiner Backend + +::: pyasic.miners._backends.bmminer.BMMiner + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/miners/backends/bosminer.md b/docs/miners/backends/bosminer.md new file mode 100644 index 00000000..5b7c4cbd --- /dev/null +++ b/docs/miners/backends/bosminer.md @@ -0,0 +1,8 @@ +# pyasic +## BOSMiner Backend + +::: pyasic.miners._backends.bosminer.BOSMiner + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/miners/backends/btminer.md b/docs/miners/backends/btminer.md new file mode 100644 index 00000000..31d83372 --- /dev/null +++ b/docs/miners/backends/btminer.md @@ -0,0 +1,8 @@ +# pyasic +## BTMiner Backend + +::: pyasic.miners._backends.btminer.BTMiner + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/miners/backends/cgminer.md b/docs/miners/backends/cgminer.md new file mode 100644 index 00000000..f46e31ef --- /dev/null +++ b/docs/miners/backends/cgminer.md @@ -0,0 +1,8 @@ +# pyasic +## CGMiner Backend + +::: pyasic.miners._backends.cgminer.CGMiner + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/miners/backends/hiveon.md b/docs/miners/backends/hiveon.md new file mode 100644 index 00000000..2a2fa2f4 --- /dev/null +++ b/docs/miners/backends/hiveon.md @@ -0,0 +1,8 @@ +# pyasic +## Hiveon Backend + +::: pyasic.miners._backends.hiveon.Hiveon + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/miners/supported_types.md b/docs/miners/supported_types.md new file mode 100644 index 00000000..170edede --- /dev/null +++ b/docs/miners/supported_types.md @@ -0,0 +1,73 @@ +# pyasic +## Supported Miners + +Supported miner types are here on this list. If your miner (or miner version) is not on this list, please feel free to [open an issue on GitHub](https://github.com/UpstreamData/pyasic/issues) to get it added. + +## Miner List + +##### pyasic currently supports the following miners and subtypes: +* Braiins OS+ Devices: + * All devices supported by BraiinsOS+ are supported here. +* Stock Firmware Whatsminers: + * M3X Series: + * [M30S][pyasic.miners.whatsminer.btminer.M3X.M30S.BTMinerM30S]: + * [VE10][pyasic.miners.whatsminer.btminer.M3X.M30S.BTMinerM30SVE10] + * [VG20][pyasic.miners.whatsminer.btminer.M3X.M30S.BTMinerM30SVG20] + * [VE20][pyasic.miners.whatsminer.btminer.M3X.M30S.BTMinerM30SVE20] + * [V50][pyasic.miners.whatsminer.btminer.M3X.M30S.BTMinerM30SV50] + * [M30S+][pyasic.miners.whatsminer.btminer.M3X.M30S_Plus.BTMinerM30SPlus]: + * [VF20][pyasic.miners.whatsminer.btminer.M3X.M30S_Plus.BTMinerM30SPlusVF20] + * [VE40][pyasic.miners.whatsminer.btminer.M3X.M30S_Plus.BTMinerM30SPlusVE40] + * [VG60][pyasic.miners.whatsminer.btminer.M3X.M30S_Plus.BTMinerM30SPlusVG60] + * [M30S++][pyasic.miners.whatsminer.btminer.M3X.M30S_Plus_Plus.BTMinerM30SPlusPlus]: + * [VG30][pyasic.miners.whatsminer.btminer.M3X.M30S_Plus_Plus.BTMinerM30SPlusPlusVG30] + * [VG40][pyasic.miners.whatsminer.btminer.M3X.M30S_Plus_Plus.BTMinerM30SPlusPlusVG40] + * [M31S][pyasic.miners.whatsminer.btminer.M3X.M31S.BTMinerM31S] + * [M31S+][pyasic.miners.whatsminer.btminer.M3X.M31S_Plus.BTMinerM31SPlus]: + * [VE20][pyasic.miners.whatsminer.btminer.M3X.M31S_Plus.BTMinerM31SPlusVE20] + * [M32S][pyasic.miners.whatsminer.btminer.M3X.M32S.BTMinerM32S] + * M2X Series: + * [M20S][pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20S]: + * [V10][pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20SV10] + * [V20][pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20SV20] + * [M20S+][pyasic.miners.whatsminer.btminer.M2X.M20S_Plus.BTMinerM20SPlus] + * [M21][pyasic.miners.whatsminer.btminer.M2X.M21.BTMinerM21] + * [M21S][pyasic.miners.whatsminer.btminer.M2X.M21S.BTMinerM21S]: + * [V20][pyasic.miners.whatsminer.btminer.M2X.M21S.BTMinerM21SV20] + * [V60][pyasic.miners.whatsminer.btminer.M2X.M21S.BTMinerM21SV60] + * [M21S+][pyasic.miners.whatsminer.btminer.M2X.M21S_Plus.BTMinerM21SPlus] +* Stock Firmware Antminers: + * X19 Series: + * [S19][pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19] + * [S19 Pro][pyasic.miners.antminer.bmminer.X19.S19_Pro.BMMinerS19Pro] + * [S19a][pyasic.miners.antminer.bmminer.X19.S19a.BMMinerS19a] + * [S19j][pyasic.miners.antminer.bmminer.X19.S19j.BMMinerS19j] + * [S19j Pro][pyasic.miners.antminer.bmminer.X19.S19j_Pro.BMMinerS19jPro] + * [T19][pyasic.miners.antminer.bmminer.X19.T19.BMMinerT19] + * X17 Series: + * [S17][pyasic.miners.antminer.bmminer.X17.S17.BMMinerS17] + * [S17+][pyasic.miners.antminer.bmminer.X17.S17_Plus.BMMinerS17Plus] + * [S17 Pro][pyasic.miners.antminer.bmminer.X17.S17_Pro.BMMinerS17Pro] + * [S17e][pyasic.miners.antminer.bmminer.X17.S17e.BMMinerS17e] + * [T17][pyasic.miners.antminer.bmminer.X17.T17.BMMinerT17] + * [T17+][pyasic.miners.antminer.bmminer.X17.T17_Plus.BMMinerT17Plus] + * [T17e][pyasic.miners.antminer.bmminer.X17.T17e.BMMinerT17e] + * X9 Series: + * [S9][pyasic.miners.antminer.bmminer.X9.S9.BMMinerS9] + * [S9i][pyasic.miners.antminer.bmminer.X9.S9i.BMMinerS9i] + * [T9][pyasic.miners.antminer.bmminer.X9.T9.BMMinerT9] +* Stock Firmware Avalonminers: + * A7X Series: + * [A721][pyasic.miners.avalonminer.cgminer.A7X.A721.CGMinerAvalon721] + * [A741][pyasic.miners.avalonminer.cgminer.A7X.A741.CGMinerAvalon741] + * [A761][pyasic.miners.avalonminer.cgminer.A7X.A761.CGMinerAvalon761] + * A8X Series: + * [A821][pyasic.miners.avalonminer.cgminer.A8X.A821.CGMinerAvalon821] + * [A841][pyasic.miners.avalonminer.cgminer.A8X.A841.CGMinerAvalon841] + * [A851][pyasic.miners.avalonminer.cgminer.A8X.A851.CGMinerAvalon851] + * A9X Series: + * [A921][pyasic.miners.avalonminer.cgminer.A9X.A921.CGMinerAvalon921] + * A10X Series: + * [A1026][pyasic.miners.avalonminer.cgminer.A10X.A1026.CGMinerAvalon1026] + * [A1047][pyasic.miners.avalonminer.cgminer.A10X.A1047.CGMinerAvalon1047] + * [A1066][pyasic.miners.avalonminer.cgminer.A10X.A1066.CGMinerAvalon1066] diff --git a/docs/miners/whatsminer/M2X.md b/docs/miners/whatsminer/M2X.md new file mode 100644 index 00000000..1b0a5d3c --- /dev/null +++ b/docs/miners/whatsminer/M2X.md @@ -0,0 +1,75 @@ +# pyasic +## M2X Models + +## M20S + +::: pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20S + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M20SV10 + +::: pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20SV10 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M20SV20 + +::: pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20SV20 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M20S+ + +::: pyasic.miners.whatsminer.btminer.M2X.M20S_Plus.BTMinerM20SPlus + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M21 + +::: pyasic.miners.whatsminer.btminer.M2X.M21.BTMinerM21 + handler: python + options: + show_root_heading: false + heading_level: 4 + + +## M21S + +::: pyasic.miners.whatsminer.btminer.M2X.M21S.BTMinerM21S + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M21SV20 + +::: pyasic.miners.whatsminer.btminer.M2X.M21S.BTMinerM21SV20 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M21SV60 + +::: pyasic.miners.whatsminer.btminer.M2X.M21S.BTMinerM21SV60 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M21S+ + +::: pyasic.miners.whatsminer.btminer.M2X.M21S_Plus.BTMinerM21SPlus + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/miners/whatsminer/M3X.md b/docs/miners/whatsminer/M3X.md new file mode 100644 index 00000000..3272e70d --- /dev/null +++ b/docs/miners/whatsminer/M3X.md @@ -0,0 +1,131 @@ +# pyasic +## M3X Models + +## M30S + +::: pyasic.miners.whatsminer.btminer.M3X.M30S.BTMinerM30S + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M30SVE10 + +::: pyasic.miners.whatsminer.btminer.M3X.M30S.BTMinerM30SVE10 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M30SVG20 + +::: pyasic.miners.whatsminer.btminer.M3X.M30S.BTMinerM30SVG20 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M30SVE20 + +::: pyasic.miners.whatsminer.btminer.M3X.M30S.BTMinerM30SVE20 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M30SV50 + +::: pyasic.miners.whatsminer.btminer.M3X.M30S.BTMinerM30SV50 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M30S+ + +::: pyasic.miners.whatsminer.btminer.M3X.M30S_Plus.BTMinerM30SPlus + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M30S+VF20 + +::: pyasic.miners.whatsminer.btminer.M3X.M30S_Plus.BTMinerM30SPlusVF20 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M30S+VE40 + +::: pyasic.miners.whatsminer.btminer.M3X.M30S_Plus.BTMinerM30SPlusVE40 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M30S+VG60 + +::: pyasic.miners.whatsminer.btminer.M3X.M30S_Plus.BTMinerM30SPlusVG60 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M30S++ + +::: pyasic.miners.whatsminer.btminer.M3X.M30S_Plus_Plus.BTMinerM30SPlusPlus + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M30S++VG30 + +::: pyasic.miners.whatsminer.btminer.M3X.M30S_Plus_Plus.BTMinerM30SPlusPlusVG30 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M30S+VG40 + +::: pyasic.miners.whatsminer.btminer.M3X.M30S_Plus_Plus.BTMinerM30SPlusPlusVG40 + handler: python + options: + show_root_heading: false + heading_level: 4 + + +## M31S + +::: pyasic.miners.whatsminer.btminer.M3X.M31S.BTMinerM31S + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M31S+ + +::: pyasic.miners.whatsminer.btminer.M3X.M31S_Plus.BTMinerM31SPlus + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M31S+VE20 + +::: pyasic.miners.whatsminer.btminer.M3X.M31S_Plus.BTMinerM31SPlusVE20 + handler: python + options: + show_root_heading: false + heading_level: 4 + +## M32S + +::: pyasic.miners.whatsminer.btminer.M3X.M32S.BTMinerM32S + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/docs/network/miner_network_range.md b/docs/network/miner_network_range.md new file mode 100644 index 00000000..11ca6b06 --- /dev/null +++ b/docs/network/miner_network_range.md @@ -0,0 +1,12 @@ +# pyasic +## Miner Network Range + +`MinerNetworkRange` is a class used by [`MinerNetwork`][pyasic.network.MinerNetwork] to handle any constructor stings. +The goal is to emulate what is produced by `ipaddress.ip_network` by allowing [`MinerNetwork`][pyasic.network.MinerNetwork] to get a list of hosts. +This allows this class to be the [`MinerNetwork.network`][pyasic.network.MinerNetwork] and hence be used for scanning. + +::: pyasic.network.net_range.MinerNetworkRange + handler: python + options: + show_root_heading: false + heading_level: 4 diff --git a/mkdocs.yml b/mkdocs.yml index 34a7c0a4..74371b3c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -3,9 +3,29 @@ repo_url: https://github.com/UpstreamData/pyasic nav: - Introduction: "index.md" - Miners: + - Supported Miners: "miners/supported_types.md" - Miner Factory: "miners/miner_factory.md" + - Backends: + - BMMiner: "miners/backends/bmminer.md" + - BOSMiner: "miners/backends/bosminer.md" + - BTMiner: "miners/backends/btminer.md" + - CGMiner: "miners/backends/cgminer.md" + - Hiveon: "miners/backends/hiveon.md" + + - Classes: + - Antminer X9: "miners/antminer/X9.md" + - Antminer X17: "miners/antminer/X17.md" + - Antminer X19: "miners/antminer/X19.md" + - Avalon 7X: "miners/avalonminer/A7X.md" + - Avalon 8X: "miners/avalonminer/A8X.md" + - Avalon 9X: "miners/avalonminer/A9X.md" + - Avalon 10X: "miners/avalonminer/A10X.md" + - Whatsminer M2X: "miners/whatsminer/M2X.md" + - Whatsminer M3X: "miners/whatsminer/M3X.md" + - Network: - Miner Network: "network/miner_network.md" + - Miner Network Range: "network/miner_network_range.md" - Data: - Miner Data: "data/miner_data.md" - Config: diff --git a/pyasic/miners/_backends/bmminer.py b/pyasic/miners/_backends/bmminer.py index 5d4cb6ca..d5d573ef 100644 --- a/pyasic/miners/_backends/bmminer.py +++ b/pyasic/miners/_backends/bmminer.py @@ -1,5 +1,6 @@ import ipaddress import logging +from typing import Union from pyasic.API.bmminer import BMMinerAPI @@ -11,6 +12,8 @@ from pyasic.settings import MINER_FACTORY_GET_VERSION_RETRIES as DATA_RETRIES class BMMiner(BaseMiner): + """Base handler for BMMiner based miners.""" + def __init__(self, ip: str) -> None: super().__init__(ip) self.ip = ipaddress.ip_address(ip) @@ -19,10 +22,11 @@ class BMMiner(BaseMiner): self.uname = "root" self.pwd = "admin" - async def get_model(self) -> str or None: + async def get_model(self) -> Union[str, None]: """Get miner model. - :return: Miner model or None. + Returns: + Miner model or None. """ # check if model is cached if self.model: @@ -46,7 +50,8 @@ class BMMiner(BaseMiner): async def get_hostname(self) -> str: """Get miner hostname. - :return: The hostname of the miner as a string or "?" + Returns: + The hostname of the miner as a string or "?" """ if self.hostname: return self.hostname @@ -72,12 +77,14 @@ class BMMiner(BaseMiner): logging.warning(f"Failed to get hostname for miner: {self}") return "?" - async def send_ssh_command(self, cmd: str) -> str or None: + async def send_ssh_command(self, cmd: str) -> Union[str, None]: """Send a command to the miner over ssh. - :param cmd: The command to run. + Parameters: + cmd: The command to run. - :return: Result of the command or None. + Returns: + Result of the command or None. """ result = None @@ -101,10 +108,11 @@ class BMMiner(BaseMiner): # return the result, either command output or None return result - async def get_config(self) -> list or None: + async def get_config(self) -> Union[list, None]: """Get the pool configuration of the miner. - :return: Pool config data or None. + Returns: + Pool config data or None. """ # get pool data pools = await self.api.pools() @@ -120,6 +128,11 @@ class BMMiner(BaseMiner): return pool_data async def reboot(self) -> bool: + """Reboot the miner. + + Returns: + The result of rebooting the miner. + """ logging.debug(f"{self}: Sending reboot command.") _ret = await self.send_ssh_command("reboot") logging.debug(f"{self}: Reboot command completed.") @@ -128,6 +141,11 @@ class BMMiner(BaseMiner): return False async def get_data(self) -> MinerData: + """Get data from the miner. + + Returns: + A [`MinerData`][pyasic.data.MinerData] instance containing the miners data. + """ data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) board_offset = -1 diff --git a/pyasic/miners/_backends/bosminer.py b/pyasic/miners/_backends/bosminer.py index d44d1023..cc5d6c4d 100644 --- a/pyasic/miners/_backends/bosminer.py +++ b/pyasic/miners/_backends/bosminer.py @@ -1,6 +1,7 @@ import ipaddress import logging import json +from typing import Union import toml @@ -27,10 +28,11 @@ class BOSMiner(BaseMiner): self.pwd = "admin" self.config = None - async def send_ssh_command(self, cmd: str) -> str or None: + async def send_ssh_command(self, cmd: str) -> Union[str, None]: """Send a command to the miner over ssh. - :return: Result of the command or None. + Returns: + Result of the command or None. """ result = None @@ -74,6 +76,7 @@ class BOSMiner(BaseMiner): return False async def restart_backend(self) -> bool: + """Restart bosminer hashing process. Wraps [`restart_bosminer`][pyasic.miners._backends.bosminer.BOSMiner.restart_bosminer] to standardize.""" return await self.restart_bosminer() async def restart_bosminer(self) -> bool: @@ -94,7 +97,12 @@ class BOSMiner(BaseMiner): return True return False - async def get_config(self) -> None: + async def get_config(self) -> str: + """Gets the config for the miner and sets it as `self.config`. + + Returns: + The config from `self.config`. + """ logging.debug(f"{self}: Getting config.") async with (await self._get_ssh_connection()) as conn: logging.debug(f"{self}: Opening SFTP connection.") @@ -110,7 +118,8 @@ class BOSMiner(BaseMiner): async def get_hostname(self) -> str: """Get miner hostname. - :return: The hostname of the miner as a string or "?" + Returns: + The hostname of the miner as a string or "?" """ if self.hostname: return self.hostname @@ -129,10 +138,11 @@ class BOSMiner(BaseMiner): logging.warning(f"Failed to get hostname for miner: {self}") return "?" - async def get_model(self) -> str or None: + async def get_model(self) -> Union[str, None]: """Get miner model. - :return: Miner model or None. + Returns: + Miner model or None. """ # check if model is cached if self.model: @@ -166,10 +176,11 @@ class BOSMiner(BaseMiner): logging.warning(f"Failed to get model for miner: {self}") return None - async def get_version(self): + async def get_version(self) -> Union[str, None]: """Get miner firmware version. - :return: Miner firmware version or None. + Returns: + Miner firmware version or None. """ # check if version is cached if self.version: @@ -214,57 +225,12 @@ class BOSMiner(BaseMiner): logging.debug(f"{self}: Restarting BOSMiner") await conn.run("/etc/init.d/bosminer restart") - async def get_board_info(self) -> dict: - """Gets data on each board and chain in the miner.""" - logging.debug(f"{self}: Getting board info.") - devdetails = await self.api.devdetails() - if not devdetails.get("DEVDETAILS"): - print("devdetails error", devdetails) - return {0: [], 1: [], 2: []} - devs = devdetails["DEVDETAILS"] - boards = {} - offset = devs[0]["ID"] - for board in devs: - boards[board["ID"] - offset] = [] - if not board["Chips"] == self.nominal_chips: - nominal = False - else: - nominal = True - boards[board["ID"] - offset].append( - { - "chain": board["ID"] - offset, - "chip_count": board["Chips"], - "chip_status": "o" * board["Chips"], - "nominal": nominal, - } - ) - logging.debug(f"Found board data for {self}: {boards}") - return boards - - async def get_bad_boards(self) -> dict: - """Checks for and provides list of non working boards.""" - boards = await self.get_board_info() - bad_boards = {} - for board in boards.keys(): - for chain in boards[board]: - if not chain["chip_count"] == 63: - if board not in bad_boards.keys(): - bad_boards[board] = [] - bad_boards[board].append(chain) - return bad_boards - - async def check_good_boards(self) -> str: - """Checks for and provides list for working boards.""" - devs = await self.api.devdetails() - bad = 0 - chains = devs["DEVDETAILS"] - for chain in chains: - if chain["Chips"] == 0: - bad += 1 - if not bad > 0: - return str(self.ip) - async def get_data(self) -> MinerData: + """Get data from the miner. + + Returns: + A [`MinerData`][pyasic.data.MinerData] instance containing the miners data. + """ data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) board_offset = -1 diff --git a/pyasic/miners/_backends/btminer.py b/pyasic/miners/_backends/btminer.py index 4907ec8f..c0e4e0eb 100644 --- a/pyasic/miners/_backends/btminer.py +++ b/pyasic/miners/_backends/btminer.py @@ -1,5 +1,6 @@ import ipaddress import logging +from typing import Union from pyasic.API.btminer import BTMinerAPI @@ -19,7 +20,12 @@ class BTMiner(BaseMiner): self.api = BTMinerAPI(ip) self.api_type = "BTMiner" - async def get_model(self): + async def get_model(self) -> Union[str, None]: + """Get miner model. + + Returns: + Miner model or None. + """ if self.model: logging.debug(f"Found model for {self.ip}: {self.model}") return self.model @@ -31,7 +37,12 @@ class BTMiner(BaseMiner): logging.warning(f"Failed to get model for miner: {self}") return None - async def get_hostname(self) -> str or None: + async def get_hostname(self) -> Union[str, None]: + """Get miner hostname. + + Returns: + The hostname of the miner as a string or None. + """ if self.hostname: return self.hostname try: @@ -48,38 +59,12 @@ class BTMiner(BaseMiner): logging.warning(f"Failed to get hostname for miner: {self}") return None - async def get_board_info(self) -> dict: - """Gets data on each board and chain in the miner.""" - logging.debug(f"{self}: Getting board info.") - devs = await self.api.devs() - if not devs.get("DEVS"): - print("devs error", devs) - return {0: [], 1: [], 2: []} - devs = devs["DEVS"] - boards = {} - offset = devs[0]["ID"] - for board in devs: - boards[board["ID"] - offset] = [] - if "Effective Chips" in board.keys(): - if not board["Effective Chips"] in self.nominal_chips: - nominal = False - else: - nominal = True - boards[board["ID"] - offset].append( - { - "chain": board["ID"] - offset, - "chip_count": board["Effective Chips"], - "chip_status": "o" * board["Effective Chips"], - "nominal": nominal, - } - ) - else: - logging.warning(f"Incorrect board data from {self}: {board}") - print(board) - logging.debug(f"Found board data for {self}: {boards}") - return boards + async def get_mac(self) -> str: + """Get the mac address of the miner. - async def get_mac(self): + Returns: + The mac address of the miner as a string. + """ mac = "" data = await self.api.summary() if data: @@ -100,7 +85,12 @@ class BTMiner(BaseMiner): return str(mac).upper() - async def get_data(self): + async def get_data(self) -> MinerData: + """Get data from the miner. + + Returns: + A [`MinerData`][pyasic.data.MinerData] instance containing the miners data. + """ data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) mac = None diff --git a/pyasic/miners/_backends/cgminer.py b/pyasic/miners/_backends/cgminer.py index c16110a9..bcbd51e7 100644 --- a/pyasic/miners/_backends/cgminer.py +++ b/pyasic/miners/_backends/cgminer.py @@ -1,5 +1,6 @@ import ipaddress import logging +from typing import Union from pyasic.API.cgminer import CGMinerAPI @@ -21,7 +22,12 @@ class CGMiner(BaseMiner): self.pwd = "admin" self.config = None - async def get_model(self): + async def get_model(self) -> Union[str, None]: + """Get miner model. + + Returns: + Miner model or None. + """ if self.model: return self.model try: @@ -33,7 +39,12 @@ class CGMiner(BaseMiner): return self.model return None - async def get_hostname(self) -> str or None: + async def get_hostname(self) -> Union[str, None]: + """Get miner hostname. + + Returns: + The hostname of the miner as a string or "?" + """ if self.hostname: return self.hostname try: @@ -48,7 +59,15 @@ class CGMiner(BaseMiner): except Exception: return None - async def send_ssh_command(self, cmd): + async def send_ssh_command(self, cmd: str) -> Union[str, None]: + """Send a command to the miner over ssh. + + Parameters: + cmd: The command to run. + + Returns: + Result of the command or None. + """ result = None async with (await self._get_ssh_connection()) as conn: for i in range(3): @@ -63,9 +82,11 @@ class CGMiner(BaseMiner): return result async def restart_backend(self) -> bool: + """Restart cgminer hashing process. Wraps [`restart_cgminer`][pyasic.miners._backends.cgminer.CGMiner.restart_cgminer] to standardize.""" return await self.restart_cgminer() async def restart_cgminer(self) -> bool: + """Restart cgminer hashing process.""" commands = ["cgminer-api restart", "/usr/bin/cgminer-monitor >/dev/null 2>&1"] commands = ";".join(commands) _ret = await self.send_ssh_command(commands) @@ -74,6 +95,7 @@ class CGMiner(BaseMiner): return False async def reboot(self) -> bool: + """Reboots power to the physical miner.""" logging.debug(f"{self}: Sending reboot command.") _ret = await self.send_ssh_command("reboot") logging.debug(f"{self}: Reboot command completed.") @@ -82,6 +104,7 @@ class CGMiner(BaseMiner): return False async def start_cgminer(self) -> None: + """Start cgminer hashing process.""" commands = [ "mkdir -p /etc/tmp/", 'echo "*/3 * * * * /usr/bin/cgminer-monitor" > /etc/tmp/root', @@ -92,6 +115,7 @@ class CGMiner(BaseMiner): await self.send_ssh_command(commands) async def stop_cgminer(self) -> None: + """Restart cgminer hashing process.""" commands = [ "mkdir -p /etc/tmp/", 'echo "" > /etc/tmp/root', @@ -101,14 +125,24 @@ class CGMiner(BaseMiner): commands = ";".join(commands) await self.send_ssh_command(commands) - async def get_config(self) -> None: + async def get_config(self) -> str: + """Gets the config for the miner and sets it as `self.config`. + + Returns: + The config from `self.config`. + """ async with (await self._get_ssh_connection()) as conn: command = "cat /etc/config/cgminer" result = await conn.run(command, check=True) self.config = result.stdout - print(str(self.config)) + return self.config - async def get_data(self): + async def get_data(self) -> MinerData: + """Get data from the miner. + + Returns: + A [`MinerData`][pyasic.data.MinerData] instance containing the miners data. + """ data = MinerData(ip=str(self.ip), ideal_chips=self.nominal_chips * 3) board_offset = -1 diff --git a/pyasic/miners/whatsminer/btminer/M3X/M30S.py b/pyasic/miners/whatsminer/btminer/M3X/M30S.py index d2348c5e..ed064317 100644 --- a/pyasic/miners/whatsminer/btminer/M3X/M30S.py +++ b/pyasic/miners/whatsminer/btminer/M3X/M30S.py @@ -14,7 +14,7 @@ class BTMinerM30S(BTMiner, M30S): self.ip = ip -class BTMinerM30SV50(BTMiner, M30SV50): +class BTMinerM30SVE10(BTMiner, M30SVE10): def __init__(self, ip: str) -> None: super().__init__(ip) self.ip = ip @@ -32,7 +32,7 @@ class BTMinerM30SVE20(BTMiner, M30SVE20): self.ip = ip -class BTMinerM30SVE10(BTMiner, M30SVE10): +class BTMinerM30SV50(BTMiner, M30SV50): def __init__(self, ip: str) -> None: super().__init__(ip) self.ip = ip diff --git a/pyasic/miners/whatsminer/btminer/M3X/M30S_Plus.py b/pyasic/miners/whatsminer/btminer/M3X/M30S_Plus.py index 9c2f2909..7d91cdaa 100644 --- a/pyasic/miners/whatsminer/btminer/M3X/M30S_Plus.py +++ b/pyasic/miners/whatsminer/btminer/M3X/M30S_Plus.py @@ -13,13 +13,13 @@ class BTMinerM30SPlus(BTMiner, M30SPlus): self.ip = ip -class BTMinerM30SPlusVE40(BTMiner, M30SPlusVE40): +class BTMinerM30SPlusVF20(BTMiner, M30SPlusVF20): def __init__(self, ip: str) -> None: super().__init__(ip) self.ip = ip -class BTMinerM30SPlusVF20(BTMiner, M30SPlusVF20): +class BTMinerM30SPlusVE40(BTMiner, M30SPlusVE40): def __init__(self, ip: str) -> None: super().__init__(ip) self.ip = ip diff --git a/pyasic/miners/whatsminer/btminer/M3X/M30S_Plus_Plus.py b/pyasic/miners/whatsminer/btminer/M3X/M30S_Plus_Plus.py index e8599dc6..b837de4e 100644 --- a/pyasic/miners/whatsminer/btminer/M3X/M30S_Plus_Plus.py +++ b/pyasic/miners/whatsminer/btminer/M3X/M30S_Plus_Plus.py @@ -12,13 +12,13 @@ class BTMinerM30SPlusPlus(BTMiner, M30SPlusPlus): self.ip = ip -class BTMinerM30SPlusPlusVG40(BTMiner, M30SPlusPlusVG40): - def __init__(self, ip: str) -> None: - super().__init__(ip) - self.ip = ip - - class BTMinerM30SPlusPlusVG30(BTMiner, M30SPlusPlusVG30): def __init__(self, ip: str) -> None: super().__init__(ip) self.ip = ip + + +class BTMinerM30SPlusPlusVG40(BTMiner, M30SPlusPlusVG40): + def __init__(self, ip: str) -> None: + super().__init__(ip) + self.ip = ip