add bmminer docs

This commit is contained in:
UpstreamData
2022-07-13 09:13:21 -06:00
parent 5700bd1c9c
commit 0324a21e79
3 changed files with 339 additions and 129 deletions

14
docs/api.md Normal file
View File

@@ -0,0 +1,14 @@
# pyasic
## Miner APIs
Each miner has a unique API that is used to communicate with it.
Each of these API types has commands that differ between them, and some commands have data that others do not.
Each miner that is a subclass of `BaseMiner` should have an API linked to it as `Miner.api`.
All API implementations inherit from `BaseMinerAPI`, which implements the basic communications protocols.
## BMMinerAPI
::: pyasic.API.bmminer.BMMinerAPI
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -1 +1,8 @@
site_name: pyasic site_name: pyasic
repo_url: https://github.com/UpstreamData/pyasic
nav:
- Introduction: "index.md"
- API: "api.md"
plugins:
- mkdocstrings

View File

@@ -6,17 +6,17 @@ class BMMinerAPI(BaseMinerAPI):
Each method corresponds to an API command in BMMiner. Each method corresponds to an API command in BMMiner.
BMMiner API documentation: [BMMiner API documentation](https://github.com/jameshilliard/bmminer/blob/master/API-README)
https://github.com/jameshilliard/bmminer/blob/master/API-README
This class abstracts use of the BMMiner API, as well as the This class abstracts use of the BMMiner API, as well as the
methods for sending commands to it. The self.send_command() methods for sending commands to it. The `self.send_command()`
function handles sending a command to the miner asynchronously, and function handles sending a command to the miner asynchronously, and
as such is the base for many of the functions in this class, which as such is the base for many of the functions in this class, which
rely on it to send the command for them. rely on it to send the command for them.
:param ip: The IP of the miner to reference the API on. Parameters:
:param port: The port to reference the API on. Default is 4028. ip: The IP of the miner to reference the API on.
port: The port to reference the API on. Default is 4028.
""" """
def __init__(self, ip: str, port: int = 4028) -> None: def __init__(self, ip: str, port: int = 4028) -> None:
@@ -24,58 +24,81 @@ class BMMinerAPI(BaseMinerAPI):
async def version(self) -> dict: async def version(self) -> dict:
"""Get miner version info. """Get miner version info.
<details>
<summary>Expand</summary>
:return: Miner version information. Returns:
Miner version information.
</details>
""" """
return await self.send_command("version") return await self.send_command("version")
async def config(self) -> dict: async def config(self) -> dict:
"""Get some basic configuration info. """Get some basic configuration info.
<details>
<summary>Expand</summary>
:return: Some miner configuration information: Returns:
ASC Count <- the number of ASCs ## Some miner configuration information:
PGA Count <- the number of PGAs * ASC Count <- the number of ASCs
Pool Count <- the number of Pools * PGA Count <- the number of PGAs
Strategy <- the current pool strategy * Pool Count <- the number of Pools
Log Interval <- the interval of logging * Strategy <- the current pool strategy
Device Code <- list of compiled device drivers * Log Interval <- the interval of logging
OS <- the current operating system * Device Code <- list of compiled device drivers
Failover-Only <- failover-only setting * OS <- the current operating system
Scan Time <- scan-time setting * Failover-Only <- failover-only setting
Queue <- queue setting * Scan Time <- scan-time setting
Expiry <- expiry setting * Queue <- queue setting
* Expiry <- expiry setting
</details>
""" """
return await self.send_command("config") return await self.send_command("config")
async def summary(self) -> dict: async def summary(self) -> dict:
"""Get the status summary of the miner. """Get the status summary of the miner.
<details>
<summary>Expand</summary>
:return: The status summary of the miner. Returns:
The status summary of the miner.
</details>
""" """
return await self.send_command("summary") return await self.send_command("summary")
async def pools(self) -> dict: async def pools(self) -> dict:
"""Get pool information. """Get pool information.
<details>
<summary>Expand</summary>
:return: Miner pool information. Returns:
Miner pool information.
</details>
""" """
return await self.send_command("pools") return await self.send_command("pools")
async def devs(self) -> dict: async def devs(self) -> dict:
"""Get data on each PGA/ASC with their details. """Get data on each PGA/ASC with their details.
<details>
<summary>Expand</summary>
:return: Data on each PGA/ASC with their details. Returns:
Data on each PGA/ASC with their details.
</details>
""" """
return await self.send_command("devs") return await self.send_command("devs")
async def edevs(self, old: bool = False) -> dict: async def edevs(self, old: bool = False) -> dict:
"""Get data on each PGA/ASC with their details, ignoring """Get data on each PGA/ASC with their details, ignoring blacklisted and zombie devices.
blacklisted and zombie devices. <details>
<summary>Expand</summary>
:param old: Include zombie devices that became zombies less Parameters:
than 'old' seconds ago old: Include zombie devices that became zombies less than 'old' seconds ago
:return: Data on each PGA/ASC with their details. Returns:
Data on each PGA/ASC with their details.
</details>
""" """
if old: if old:
return await self.send_command("edevs", parameters=old) return await self.send_command("edevs", parameters=old)
@@ -84,46 +107,70 @@ class BMMinerAPI(BaseMinerAPI):
async def pga(self, n: int) -> dict: async def pga(self, n: int) -> dict:
"""Get data from PGA n. """Get data from PGA n.
<details>
<summary>Expand</summary>
:param n: The PGA number to get data from. Parameters:
n: The PGA number to get data from.
:return: Data on the PGA n. Returns:
Data on the PGA n.
</details>
""" """
return await self.send_command("pga", parameters=n) return await self.send_command("pga", parameters=n)
async def pgacount(self) -> dict: async def pgacount(self) -> dict:
"""Get data fon all PGAs. """Get data fon all PGAs.
<details>
<summary>Expand</summary>
:return: Data on the PGAs connected. Returns:
Data on the PGAs connected.
</details>
""" """
return await self.send_command("pgacount") return await self.send_command("pgacount")
async def switchpool(self, n: int) -> dict: async def switchpool(self, n: int) -> dict:
"""Switch pools to pool n. """Switch pools to pool n.
<details>
<summary>Expand</summary>
:param n: The pool to switch to. Parameters:
n: The pool to switch to.
:return: A confirmation of switching to pool n. Returns:
A confirmation of switching to pool n.
</details>
""" """
return await self.send_command("switchpool", parameters=n) return await self.send_command("switchpool", parameters=n)
async def enablepool(self, n: int) -> dict: async def enablepool(self, n: int) -> dict:
"""Enable pool n. """Enable pool n.
<details>
<summary>Expand</summary>
:param n: The pool to enable. Parameters:
n: The pool to enable.
:return: A confirmation of enabling pool n. Returns:
A confirmation of enabling pool n.
</details>
""" """
return await self.send_command("enablepool", parameters=n) return await self.send_command("enablepool", parameters=n)
async def addpool(self, url: str, username: str, password: str) -> dict: async def addpool(self, url: str, username: str, password: str) -> dict:
"""Add a pool to the miner. """Add a pool to the miner.
<details>
<summary>Expand</summary>
:param url: The URL of the new pool to add. Parameters:
:param username: The users username on the new pool. url: The URL of the new pool to add.
:param password: The worker password on the new pool. username: The users username on the new pool.
password: The worker password on the new pool.
:return: A confirmation of adding the pool. Returns:
A confirmation of adding the pool.
</details>
""" """
return await self.send_command( return await self.send_command(
"addpool", parameters=f"{url},{username},{password}" "addpool", parameters=f"{url},{username},{password}"
@@ -131,48 +178,73 @@ class BMMinerAPI(BaseMinerAPI):
async def poolpriority(self, *n: int) -> dict: async def poolpriority(self, *n: int) -> dict:
"""Set pool priority. """Set pool priority.
<details>
<summary>Expand</summary>
:param n: Pools in order of priority. Parameters:
n: Pools in order of priority.
:return: A confirmation of setting pool priority. Returns:
A confirmation of setting pool priority.
</details>
""" """
pools = f"{','.join([str(item) for item in n])}" pools = f"{','.join([str(item) for item in n])}"
return await self.send_command("poolpriority", parameters=pools) return await self.send_command("poolpriority", parameters=pools)
async def poolquota(self, n: int, q: int) -> dict: async def poolquota(self, n: int, q: int) -> dict:
"""Set pool quota. """Set pool quota.
<details>
<summary>Expand</summary>
:param n: Pool number to set quota on. Parameters:
:param q: Quota to set the pool to. n: Pool number to set quota on.
q: Quota to set the pool to.
:return: A confirmation of setting pool quota. Returns:
A confirmation of setting pool quota.
</details>
""" """
return await self.send_command("poolquota", parameters=f"{n},{q}") return await self.send_command("poolquota", parameters=f"{n},{q}")
async def disablepool(self, n: int) -> dict: async def disablepool(self, n: int) -> dict:
"""Disable a pool. """Disable a pool.
<details>
<summary>Expand</summary>
:param n: Pool to disable. Parameters:
n: Pool to disable.
:return: A confirmation of diabling the pool. Returns:
A confirmation of diabling the pool.
</details>
""" """
return await self.send_command("disablepool", parameters=n) return await self.send_command("disablepool", parameters=n)
async def removepool(self, n: int) -> dict: async def removepool(self, n: int) -> dict:
"""Remove a pool. """Remove a pool.
<details>
<summary>Expand</summary>
:param n: Pool to remove. Parameters:
n: Pool to remove.
:return: A confirmation of removing the pool. Returns:
A confirmation of removing the pool.
</details>
""" """
return await self.send_command("removepool", parameters=n) return await self.send_command("removepool", parameters=n)
async def save(self, filename: str = None) -> dict: async def save(self, filename: str = None) -> dict:
"""Save the config. """Save the config.
<details>
<summary>Expand</summary>
:param filename: Filename to save the config as. Parameters:
filename: Filename to save the config as.
:return: A confirmation of saving the config. Returns:
A confirmation of saving the config.
</details>
""" """
if filename: if filename:
return await self.send_command("save", parameters=filename) return await self.send_command("save", parameters=filename)
@@ -181,83 +253,123 @@ class BMMinerAPI(BaseMinerAPI):
async def quit(self) -> dict: async def quit(self) -> dict:
"""Quit BMMiner. """Quit BMMiner.
<details>
<summary>Expand</summary>
:return: A single "BYE" before BMMiner quits. Returns:
A single "BYE" before BMMiner quits.
</details>
""" """
return await self.send_command("quit") return await self.send_command("quit")
async def notify(self) -> dict: async def notify(self) -> dict:
"""Notify the user of past errors. """Notify the user of past errors.
<details>
<summary>Expand</summary>
:return: The last status and count of each devices problem(s). Returns:
The last status and count of each devices problem(s).
</details>
""" """
return await self.send_command("notify") return await self.send_command("notify")
async def privileged(self) -> dict: async def privileged(self) -> dict:
"""Check if you have privileged access. """Check if you have privileged access.
<details>
<summary>Expand</summary>
:return: The STATUS section with an error if you have no Returns:
privileged access, or success if you have privileged access. The STATUS section with an error if you have no privileged access, or success if you have privileged access.
</details>
""" """
return await self.send_command("privileged") return await self.send_command("privileged")
async def pgaenable(self, n: int) -> dict: async def pgaenable(self, n: int) -> dict:
"""Enable PGA n. """Enable PGA n.
<details>
<summary>Expand</summary>
:param n: The PGA to enable. Parameters:
n: The PGA to enable.
:return: A confirmation of enabling PGA n. Returns:
A confirmation of enabling PGA n.
</details>
""" """
return await self.send_command("pgaenable", parameters=n) return await self.send_command("pgaenable", parameters=n)
async def pgadisable(self, n: int) -> dict: async def pgadisable(self, n: int) -> dict:
"""Disable PGA n. """Disable PGA n.
<details>
<summary>Expand</summary>
:param n: The PGA to disable. Parameters:
n: The PGA to disable.
:return: A confirmation of disabling PGA n. Returns:
A confirmation of disabling PGA n.
</details>
""" """
return await self.send_command("pgadisable", parameters=n) return await self.send_command("pgadisable", parameters=n)
async def pgaidentify(self, n: int) -> dict: async def pgaidentify(self, n: int) -> dict:
"""Identify PGA n. """Identify PGA n.
<details>
<summary>Expand</summary>
:param n: The PGA to identify. Parameters:
n: The PGA to identify.
:return: A confirmation of identifying PGA n. Returns:
A confirmation of identifying PGA n.
</details>
""" """
return await self.send_command("pgaidentify", parameters=n) return await self.send_command("pgaidentify", parameters=n)
async def devdetails(self) -> dict: async def devdetails(self) -> dict:
"""Get data on all devices with their static details. """Get data on all devices with their static details.
<details>
<summary>Expand</summary>
:return: Data on all devices with their static details. Returns:
Data on all devices with their static details.
</details>
""" """
return await self.send_command("devdetails") return await self.send_command("devdetails")
async def restart(self) -> dict: async def restart(self) -> dict:
"""Restart BMMiner using the API. """Restart BMMiner using the API.
<details>
<summary>Expand</summary>
:return: A reply informing of the restart. Returns:
A reply informing of the restart.
</details>
""" """
return await self.send_command("restart") return await self.send_command("restart")
async def stats(self) -> dict: async def stats(self) -> dict:
"""Get stats of each device/pool with more than 1 getwork. """Get stats of each device/pool with more than 1 getwork.
<details>
<summary>Expand</summary>
:return: Stats of each device/pool with more than 1 getwork. Returns:
Stats of each device/pool with more than 1 getwork.
</details>
""" """
return await self.send_command("stats") return await self.send_command("stats")
async def estats(self, old: bool = False) -> dict: async def estats(self, old: bool = False) -> dict:
"""Get stats of each device/pool with more than 1 getwork, """Get stats of each device/pool with more than 1 getwork, ignoring zombie devices.
ignoring zombie devices. <details>
<summary>Expand</summary>
:param old: Include zombie devices that became zombies less Parameters:
than 'old' seconds ago. old: Include zombie devices that became zombies less than 'old' seconds ago.
:return: Stats of each device/pool with more than 1 getwork, Returns:
ignoring zombie devices. Stats of each device/pool with more than 1 getwork, ignoring zombie devices.
</details>
""" """
if old: if old:
return await self.send_command("estats", parameters=old) return await self.send_command("estats", parameters=old)
@@ -266,92 +378,126 @@ class BMMinerAPI(BaseMinerAPI):
async def check(self, command: str) -> dict: async def check(self, command: str) -> dict:
"""Check if the command command exists in BMMiner. """Check if the command command exists in BMMiner.
<details>
<summary>Expand</summary>
:param command: The command to check. Parameters:
command: The command to check.
:return: Information about a command: Returns:
Exists (Y/N) <- the command exists in this version ## Information about a command:
Access (Y/N) <- you have access to use the command * Exists (Y/N) <- the command exists in this version
* Access (Y/N) <- you have access to use the command
</details>
""" """
return await self.send_command("check", parameters=command) return await self.send_command("check", parameters=command)
async def failover_only(self, failover: bool) -> dict: async def failover_only(self, failover: bool) -> dict:
"""Set failover-only. """Set failover-only.
<details>
<summary>Expand</summary>
Parameters:
failover: What to set failover-only to.
:param failover: What to set failover-only to. Returns:
Confirmation of setting failover-only.
:return: Confirmation of setting failover-only. </details>
""" """
return await self.send_command("failover-only", parameters=failover) return await self.send_command("failover-only", parameters=failover)
async def coin(self) -> dict: async def coin(self) -> dict:
"""Get information on the current coin. """Get information on the current coin.
<details>
<summary>Expand</summary>
:return: Information about the current coin being mined: Returns:
Hash Method <- the hashing algorithm ## Information about the current coin being mined:
Current Block Time <- blocktime as a float, 0 means none * Hash Method <- the hashing algorithm
Current Block Hash <- the hash of the current block, blank * Current Block Time <- blocktime as a float, 0 means none
means none * Current Block Hash <- the hash of the current block, blank means none
LP <- whether LP is in use on at least 1 pool * LP <- whether LP is in use on at least 1 pool
Network Difficulty: the current network difficulty * Network Difficulty: the current network difficulty
</details>
""" """
return await self.send_command("coin") return await self.send_command("coin")
async def debug(self, setting: str) -> dict: async def debug(self, setting: str) -> dict:
"""Set a debug setting. """Set a debug setting.
<details>
<summary>Expand</summary>
:param setting: Which setting to switch to. Options are: Parameters:
Silent, setting: Which setting to switch to.
Quiet, ## Options are:
Verbose, * Silent
Debug, * Quiet
RPCProto, * Verbose
PerDevice, * Debug
WorkTime, * RPCProto
Normal. * PerDevice
* WorkTime
* Normal
:return: Data on which debug setting was enabled or disabled. Returns:
Data on which debug setting was enabled or disabled.
</details>
""" """
return await self.send_command("debug", parameters=setting) return await self.send_command("debug", parameters=setting)
async def setconfig(self, name: str, n: int) -> dict: async def setconfig(self, name: str, n: int) -> dict:
"""Set config of name to value n. """Set config of name to value n.
<details>
<summary>Expand</summary>
:param name: The name of the config setting to set. Options are: Parameters:
queue, name: The name of the config setting to set.
scantime, ## Options are:
expiry. * queue
:param n: The value to set the 'name' setting to. * scantime
* expiry
n: The value to set the 'name' setting to.
:return: The results of setting config of name to n. Returns:
The results of setting config of name to n.
</details>
""" """
return await self.send_command("setconfig", parameters=f"{name},{n}") return await self.send_command("setconfig", parameters=f"{name},{n}")
async def usbstats(self) -> dict: async def usbstats(self) -> dict:
"""Get stats of all USB devices except ztex. """Get stats of all USB devices except ztex.
<details>
<summary>Expand</summary>
:return: The stats of all USB devices except ztex. Returns:
The stats of all USB devices except ztex.
</details>
""" """
return await self.send_command("usbstats") return await self.send_command("usbstats")
async def pgaset(self, n: int, opt: str, val: int = None) -> dict: async def pgaset(self, n: int, opt: str, val: int = None) -> dict:
"""Set PGA option opt to val on PGA n. """Set PGA option opt to val on PGA n.
<details>
<summary>Expand</summary>
Options: Options:
```
MMQ - MMQ -
opt: clock opt: clock
val: 160 - 230 (multiple of 2) val: 160 - 230 (multiple of 2)
CMR - CMR -
opt: clock opt: clock
val: 100 - 220 val: 100 - 220
```
:param n: The PGA to set the options on. Parameters:
:param opt: The option to set. Setting this to 'help' n: The PGA to set the options on.
returns a help message. opt: The option to set. Setting this to 'help' returns a help message.
:param val: The value to set the option to. val: The value to set the option to.
:return: Confirmation of setting PGA n with opt[,val]. Returns:
Confirmation of setting PGA n with opt[,val].
</details>
""" """
if val: if val:
return await self.send_command("pgaset", parameters=f"{n},{opt},{val}") return await self.send_command("pgaset", parameters=f"{n},{opt},{val}")
@@ -360,75 +506,108 @@ class BMMinerAPI(BaseMinerAPI):
async def zero(self, which: str, summary: bool) -> dict: async def zero(self, which: str, summary: bool) -> dict:
"""Zero a device. """Zero a device.
<details>
<summary>Expand</summary>
:param which: Which device to zero. Parameters:
Setting this to 'all' zeros all devices. which: Which device to zero. Setting this to 'all' zeros all devices. Setting this to 'bestshare' zeros only the bestshare values for each pool and global.
Setting this to 'bestshare' zeros only the bestshare values summary: Whether or not to show a full summary.
for each pool and global.
:param summary: Whether or not to show a full summary.
:return: the STATUS section with info on the zero and optional Returns:
summary. the STATUS section with info on the zero and optional summary.
</details>
""" """
return await self.send_command("zero", parameters=f"{which},{summary}") return await self.send_command("zero", parameters=f"{which},{summary}")
async def hotplug(self, n: int) -> dict: async def hotplug(self, n: int) -> dict:
"""Enable hotplug. """Enable hotplug.
<details>
<summary>Expand</summary>
:param n: The device number to set hotplug on. Parameters:
n: The device number to set hotplug on.
:return: Information on hotplug status. Returns:
Information on hotplug status.
</details>
""" """
return await self.send_command("hotplug", parameters=n) return await self.send_command("hotplug", parameters=n)
async def asc(self, n: int) -> dict: async def asc(self, n: int) -> dict:
"""Get data for ASC device n. """Get data for ASC device n.
<details>
<summary>Expand</summary>
:param n: The device to get data for. Parameters:
n: The device to get data for.
:return: The data for ASC device n. Returns:
The data for ASC device n.
</details>
""" """
return await self.send_command("asc", parameters=n) return await self.send_command("asc", parameters=n)
async def ascenable(self, n: int) -> dict: async def ascenable(self, n: int) -> dict:
"""Enable ASC device n. """Enable ASC device n.
<details>
<summary>Expand</summary>
:param n: The device to enable. Parameters:
n: The device to enable.
:return: Confirmation of enabling ASC device n. Returns:
Confirmation of enabling ASC device n.
</details>
""" """
return await self.send_command("ascenable", parameters=n) return await self.send_command("ascenable", parameters=n)
async def ascdisable(self, n: int) -> dict: async def ascdisable(self, n: int) -> dict:
"""Disable ASC device n. """Disable ASC device n.
<details>
<summary>Expand</summary>
:param n: The device to disable. Parameters:
n: The device to disable.
:return: Confirmation of disabling ASC device n. Returns:
Confirmation of disabling ASC device n.
</details>
""" """
return await self.send_command("ascdisable", parameters=n) return await self.send_command("ascdisable", parameters=n)
async def ascidentify(self, n: int) -> dict: async def ascidentify(self, n: int) -> dict:
"""Identify ASC device n. """Identify ASC device n.
<details>
<summary>Expand</summary>
:param n: The device to identify. Parameters:
n: The device to identify.
:return: Confirmation of identifying ASC device n. Returns:
Confirmation of identifying ASC device n.
</details>
""" """
return await self.send_command("ascidentify", parameters=n) return await self.send_command("ascidentify", parameters=n)
async def asccount(self) -> dict: async def asccount(self) -> dict:
"""Get data on the number of ASC devices and their info. """Get data on the number of ASC devices and their info.
<details>
<summary>Expand</summary>
:return: Data on all ASC devices. Returns:
Data on all ASC devices.
</details>
""" """
return await self.send_command("asccount") return await self.send_command("asccount")
async def ascset(self, n: int, opt: str, val: int = None) -> dict: async def ascset(self, n: int, opt: str, val: int = None) -> dict:
"""Set ASC n option opt to value val. """Set ASC n option opt to value val.
<details>
<summary>Expand</summary>
Sets an option on the ASC n to a value. Allowed options are: Sets an option on the ASC n to a value. Allowed options are:
```
AVA+BTB - AVA+BTB -
opt: freq opt: freq
val: 256 - 1024 (chip frequency) val: 256 - 1024 (chip frequency)
@@ -462,14 +641,16 @@ class BMMinerAPI(BaseMinerAPI):
opt: clock opt: clock
val: 0 - 15 val: 0 - 15
```
Parameters:
n: The ASC to set the options on.
opt: The option to set. Setting this to 'help' returns a help message.
val: The value to set the option to.
:param n: The ASC to set the options on. Returns:
:param opt: The option to set. Setting this to 'help' returns a Confirmation of setting option opt to value val.
help message. </details>
:param val: The value to set the option to.
:return: Confirmation of setting option opt to value val.
""" """
if val: if val:
return await self.send_command("ascset", parameters=f"{n},{opt},{val}") return await self.send_command("ascset", parameters=f"{n},{opt},{val}")
@@ -478,14 +659,22 @@ class BMMinerAPI(BaseMinerAPI):
async def lcd(self) -> dict: async def lcd(self) -> dict:
"""Get a general all-in-one status summary of the miner. """Get a general all-in-one status summary of the miner.
<details>
<summary>Expand</summary>
:return: An all-in-one status summary of the miner. Returns:
An all-in-one status summary of the miner.
</details>
""" """
return await self.send_command("lcd") return await self.send_command("lcd")
async def lockstats(self) -> dict: async def lockstats(self) -> dict:
"""Write lockstats to STDERR. """Write lockstats to STDERR.
<details>
<summary>Expand</summary>
:return: The result of writing the lock stats to STDERR. Returns:
The result of writing the lock stats to STDERR.
</details>
""" """
return await self.send_command("lockstats") return await self.send_command("lockstats")