Compare commits

..

206 Commits

Author SHA1 Message Date
UpstreamData
d8b938cd5b version: bump version number. 2023-11-27 10:39:10 -07:00
UpstreamData
47d76e325a docs: update docs to include new information. 2023-11-27 10:37:38 -07:00
UpstreamData
7ee7868094 feature: change so_linger_time to socket_linger_time. 2023-11-27 10:19:30 -07:00
UpstreamData
3f1183a4f9 feature: add so_linger option to settings. 2023-11-27 09:24:28 -07:00
Upstream Data
2b443497ea bug: improve handling of whatsminers in get_miner. 2023-11-25 12:48:45 -07:00
Upstream Data
c3972f9524 feature: add default ssl ctx to all httpx clients to speed up initialization. 2023-11-25 01:08:04 -07:00
Upstream Data
92bbb21c11 bug: handle OSError as ConnectionError, and handle Vnish Msg bug because of missing id key. 2023-11-25 00:05:03 -07:00
Upstream Data
1980ff2563 bug: do additional checks on refused connection when scanning. 2023-11-24 23:32:22 -07:00
Upstream Data
93d09a1483 bug: handle unhandled error in pings. 2023-11-24 23:28:16 -07:00
Upstream Data
690d0d99df feature: added new setting for api command timeouts. 2023-11-24 23:19:14 -07:00
Upstream Data
78f689eb2c feature: update scan method to use port 80 when possible, and add .scan() method. 2023-11-24 23:13:56 -07:00
Upstream Data
e68f188e8f bug: fix timeout references in MinerFactory and fix MinerNetwork instantiation. 2023-11-24 23:00:06 -07:00
Upstream Data
7eda611fe9 bug: fix scanning size being too large. 2023-11-24 22:50:43 -07:00
Upstream Data
1d12817942 feature: improve network parsing and implementation. 2023-11-24 22:38:43 -07:00
UpstreamData
b24efd4c69 bug: fix miner network not working with lists. 2023-11-24 13:27:09 -07:00
UpstreamData
5533135b05 docs: update supported miners. 2023-11-23 11:54:01 -07:00
UpstreamData
475054fbe0 feature: finish support for most whatsminer subtypes. 2023-11-23 11:52:44 -07:00
Daniel Sokil
06bad1bbe0 Add More Whatsminer Models, and Additional Config For Existing Models (#70) 2023-11-23 11:35:18 -07:00
UpstreamData
f3746ff756 version: bump version number. 2023-11-20 11:19:45 -07:00
UpstreamData
9f16d37c8b feature: hide GRPC and GQL if BOSer is not found. 2023-11-20 11:19:13 -07:00
UpstreamData
8a13c7940a docs: update pyproject.toml description. 2023-11-20 10:33:25 -07:00
UpstreamData
8bea76ff67 feature: add chip count for M30S+VG50. 2023-11-20 10:32:51 -07:00
Upstream Data
1504bd744c version: bump version number. 2023-11-18 22:45:38 -07:00
Upstream Data
6449f10615 feature: implement GPRC set commands properly. 2023-11-18 22:45:09 -07:00
UpstreamData
d79509bda7 version: bump version number. Pin httpx to 0.25.0 min. 2023-11-12 18:36:45 -07:00
UpstreamData
630b847466 version: bump version number. Pin httpx to 0.25.0 min. 2023-11-12 18:35:52 -07:00
Colin Crossman
ed11611919 Bump version number
Note: some issues with HTTPX may be resolved by using 1.0.0b, but I did not bump the requirement at this time to the beta.
2023-11-11 13:59:14 -07:00
Colin Crossman
e2431c938d Address unknown password issue on Whatsminers
When a whatsminer had an unknown password (not the default one), it would result in a timeout error. By moving the password check to before the data pull step, the timeout issue can be caught and addressed efficiently.
2023-11-11 13:52:04 -07:00
Colin Crossman
60f4b4a5ed Address a situation which causes many asyncio errors 2023-11-11 13:49:51 -07:00
UpstreamData
d41097af20 version: bump vbersion number. 2023-11-08 11:13:24 -07:00
UpstreamData
8a5d505731 bug: fix anyio stream error on some linux distros when getting miner. 2023-11-08 11:12:46 -07:00
UpstreamData
36e76c6f41 Add support for the grpc set_performance_mode command. 2023-11-07 08:54:06 -07:00
UpstreamData
717b9421dd Merge branch 'dev_grpc'
# Conflicts:
#	pyasic/web/bosminer.py
#	pyproject.toml
2023-10-30 16:36:06 -06:00
UpstreamData
d2f71e8c94 version: bump version number. 2023-10-30 16:34:05 -06:00
UpstreamData
697991f28f bug: fix some cases where a warning could still be passed when it was unexpected. 2023-10-30 16:33:01 -06:00
UpstreamData
b0e18ab766 feature: implement most of the GRPC functions for BOS, except for some configuration options which will require complex enums. 2023-10-27 16:35:09 -06:00
UpstreamData
e39a6921d0 refactor: improve settings handling to not use a dataclass, and not use singleton. 2023-10-26 10:28:59 -06:00
UpstreamData
aac1be0565 feature: refactor BOS web class into multiple classes. 2023-10-26 10:28:57 -06:00
UpstreamData
683fcb2138 version: bump version number. 2023-10-26 10:28:56 -06:00
UpstreamData
9fbbef9b18 bug: fix an issue with bosminer not responding correctly on older models with fans. 2023-10-26 10:28:56 -06:00
UpstreamData
6e0b9a0a7b version: bump version number. 2023-10-26 10:28:56 -06:00
UpstreamData
7f472f6f4f bug: fix possible missing value for bitmain work mode when checking is_mining. 2023-10-26 10:28:55 -06:00
UpstreamData
b7d7b33ab9 bug: round hashrate data in MinerData, and remove some unused imports. 2023-10-26 10:28:55 -06:00
UpstreamData
da11c0bb1f version: bump version number. 2023-10-26 10:28:55 -06:00
UpstreamData
eae433d2bd bug: update get_miner to work with latest whatsminer version. 2023-10-26 10:28:54 -06:00
UpstreamData
c16bc37aff refactor: improve settings handling to not use a dataclass, and not use singleton. 2023-10-26 10:28:53 -06:00
UpstreamData
255b06ac9e version: bump version number. 2023-10-23 13:01:44 -06:00
UpstreamData
29ec619126 bug: fix an issue with bosminer not responding correctly on older models with fans. 2023-10-23 12:59:52 -06:00
UpstreamData
247def04ff version: bump version number. 2023-10-12 13:19:38 -06:00
UpstreamData
4600e7d953 bug: fix possible missing value for bitmain work mode when checking is_mining. 2023-10-12 13:19:11 -06:00
UpstreamData
850c266555 bug: round hashrate data in MinerData, and remove some unused imports. 2023-10-10 13:59:28 -06:00
UpstreamData
ad374fe2fb version: bump version number. 2023-10-05 10:18:10 -06:00
UpstreamData
5ca39b6fe7 bug: update get_miner to work with latest whatsminer version. 2023-10-05 10:17:45 -06:00
UpstreamData
b50dd26e6f feature: refactor BOS web class into multiple classes. 2023-10-03 15:07:39 -06:00
UpstreamData
53eaccaa9b docs: update documentation. 2023-10-03 15:07:39 -06:00
UpstreamData
91f207316a version: bump version number. 2023-10-03 15:07:39 -06:00
UpstreamData
1e37418909 bug: fix some issues with early version of whatsminers, and handle some possible errors with BOS. 2023-10-03 15:07:38 -06:00
UpstreamData
4c09ba5529 version: bump version number. 2023-10-03 15:07:38 -06:00
UpstreamData
7bab4747ad refactor: improve settings handling to not use a dataclass, and not use singleton. 2023-10-03 15:07:37 -06:00
UpstreamData
fd8cc7378c version: bump version number. 2023-10-03 15:07:33 -06:00
UpstreamData
8aeef4d5e7 feature: add support for M20P, and add chips for M20SV30. 2023-10-03 15:07:33 -06:00
UpstreamData
4bafde9da7 docs: update documentation. 2023-10-03 14:59:25 -06:00
UpstreamData
5a3107aecf version: bump version number. 2023-10-03 11:12:11 -06:00
UpstreamData
7e758720f0 bug: fix some issues with early version of whatsminers, and handle some possible errors with BOS. 2023-10-03 11:11:32 -06:00
UpstreamData
39e3e249f8 version: bump version number. 2023-10-02 13:14:21 -06:00
UpstreamData
118c5b056e refactor: improve settings handling to not use a dataclass, and not use singleton. 2023-10-02 13:13:31 -06:00
UpstreamData
2c3b5599fe version: bump version number. 2023-10-02 09:20:24 -06:00
UpstreamData
e421eaa324 feature: add support for M20P, and add chips for M20SV30. 2023-10-02 09:20:01 -06:00
UpstreamData
75d6bc6808 version: bump version number. 2023-09-28 15:49:23 -06:00
UpstreamData
98c547e416 bug: fAdd new commands added in whatsminer API 2.0.5. 2023-09-28 15:49:23 -06:00
UpstreamData
45250e36e4 bug: fix whatsminer identification to work with backwards incompatible changes in API 2.0.5. 2023-09-28 15:49:23 -06:00
UpstreamData
fa7544d052 Update README.md 2023-09-28 15:49:22 -06:00
UpstreamData
53f3fc5ee9 version: bump version number. 2023-09-28 15:47:49 -06:00
UpstreamData
1b36de4131 bug: fAdd new commands added in whatsminer API 2.0.5. 2023-09-28 15:47:20 -06:00
UpstreamData
6f0c6f6284 bug: fix whatsminer identification to work with backwards incompatible changes in API 2.0.5. 2023-09-28 15:42:12 -06:00
UpstreamData
b7dda5bf87 Update README.md 2023-09-26 11:50:56 -06:00
UpstreamData
14f33a40c3 feature: add grpc BOS class and add grpc requests to requirements. 2023-09-22 09:44:25 -06:00
UpstreamData
5c904aced0 feature: refactor BOS web class into multiple classes. 2023-09-22 09:32:59 -06:00
UpstreamData
53a3bbf531 version: bump version number. 2023-09-19 13:59:56 -06:00
UpstreamData
50586f1ce7 feature: add S19+. 2023-09-19 13:59:03 -06:00
UpstreamData
9f6235a0fc feature: add S19i. 2023-09-19 13:56:40 -06:00
UpstreamData
4d21f150ce version: bump version number. 2023-09-18 09:35:38 -06:00
UpstreamData
7c0dfc49dd bug: fix wrong fault light setting when setting fault light to off. 2023-09-18 09:35:19 -06:00
UpstreamData
269b13f6c1 version: bump version number. 2023-09-15 08:57:56 -06:00
Elias Kunnas
a9bb7d2e5a Fix btminer pre_power_on (#62) 2023-09-15 08:56:29 -06:00
Upstream Data
11295f27a7 version: bump version number. 2023-09-12 19:21:04 -06:00
Upstream Data
55aa3dd85b bug: handle edge cases where a missed get_config on bosminer can cause an empty config to be applied to a miner. 2023-09-12 19:20:48 -06:00
UpstreamData
20272d4360 version: bump version number. 2023-09-11 13:45:52 -06:00
UpstreamData
623dc92ef2 feature: Add MinerData.as_dict(). 2023-09-11 13:45:23 -06:00
Upstream Data
2d59394b1e version: bump version number. 2023-09-07 19:07:11 -06:00
Upstream Data
26c2095ff1 bug: fix uncaught error in get_hashboards with BMMiner if a key doesnt exist. 2023-09-07 19:06:51 -06:00
Upstream Data
ec7d241caa version: bump version number. 2023-09-05 17:22:23 -06:00
Upstream Data
d0432ed1aa bug: handle for some weird edge cases with boards plugged into the wrong slots on X19. 2023-09-05 17:22:02 -06:00
Upstream Data
8c5503d002 version: bump version number. 2023-08-30 17:47:20 -06:00
Upstream Data
6d6f950c95 bug: add modified changed from [Issue 57](https://github.com/UpstreamData/pyasic/issues/57#issuecomment-1699984187) 2023-08-30 17:46:23 -06:00
UpstreamData
30745e54ba feature: add chip count for M30S+VE50 2023-08-30 11:18:25 -06:00
UpstreamData
c3fd94e79e version: bump version number. 2023-08-28 08:53:59 -06:00
UpstreamData
2924a8d67b feature: add more whatsminer error codes. 2023-08-28 08:53:27 -06:00
UpstreamData
9f4c4bb9cf feature: add exclude to get_data, and change data_to_get to include. 2023-08-28 08:32:29 -06:00
UpstreamData
3d6eebf06e bug: fix a bug with hostname gathering on some Avalons. 2023-08-28 08:31:54 -06:00
Upstream Data
b3d9b6ff7e version: bump version number. 2023-08-26 11:21:21 -06:00
Upstream Data
60facacc48 bug: fix a bug with bosminer commands. 2023-08-26 11:21:10 -06:00
Upstream Data
b8a6063838 version: bumnp version number. 2023-08-26 10:57:40 -06:00
Upstream Data
bcba2be524 bug: remove bad await calls to httpx response.json(). 2023-08-26 10:56:53 -06:00
UpstreamData
f7187d2017 bug: add chip count for M29V10. 2023-08-25 08:58:34 -06:00
Upstream Data
d91b7c4406 version: bump version number. 2023-08-07 17:02:50 -06:00
Upstream Data
248a7e6d69 bug: fix some WM models reporting https first and being identified as BOS+. 2023-08-07 17:02:26 -06:00
Upstream Data
4f2c3e772a version: bump version number. 2023-08-06 17:25:21 -06:00
Upstream Data
95f7146eef feature: add VNish pause/resume commands. 2023-08-06 17:24:36 -06:00
UpstreamData
9d5d19cc6b version: bump version number. 2023-07-27 20:45:42 -06:00
UpstreamData
cc38129571 bug: add back pwd for ssh connections. 2023-07-27 20:45:08 -06:00
UpstreamData
3dfd9f237d version: bump version number. 2023-07-27 20:18:58 -06:00
UpstreamData
f3fe478dbb feature: add support for S19J Pro No PIC. 2023-07-27 20:18:36 -06:00
UpstreamData
e10f32ae3d feature: speed up getting older antminer types with concurrent web and api requests. 2023-07-24 21:05:07 -06:00
UpstreamData
4e0924aa0e feature: add support for AML vnish miners. 2023-07-24 20:45:30 -06:00
UpstreamData
d0d3fd3117 bug: fix failed verification of SSL cert on whatsminer. 2023-07-24 20:19:00 -06:00
UpstreamData
4de950d8f4 feature: revert miner_factory to use httpx, as it now seems to be the same speed, and aiohttp doesnt support digest auth. 2023-07-24 13:09:30 -06:00
UpstreamData
03f2a1f9ba feature: optimize multicommand on new X19 models. 2023-07-24 11:34:16 -06:00
UpstreamData
2653db90e3 feature: optimize the way multicommand is handled on BTMiner. 2023-07-24 09:44:23 -06:00
UpstreamData
ddc8c53eb9 feature: add chip count for M50 VH60. 2023-07-13 10:59:27 -06:00
UpstreamData
eb5d1a24ea version: bump version number. 2023-07-12 08:56:59 -06:00
UpstreamData
6c0e80265b bug: revert X19 miner mode to string. 2023-07-12 08:56:23 -06:00
UpstreamData
ad3a4ae414 docs: update some bad code, and add references to new miner types and API types. 2023-07-11 11:18:28 -06:00
UpstreamData
3484d43510 version: bump version number. 2023-07-07 14:09:22 -06:00
UpstreamData
dd7e352391 bug: fix some addition issues with MinerData sums. 2023-07-07 14:09:08 -06:00
UpstreamData
a32b61fe5d version: bump version number. 2023-07-07 12:37:34 -06:00
UpstreamData
597a178009 feature: Update MinerData to use None. 2023-07-07 12:37:20 -06:00
Michael Schmid
409b2527f0 use None instead of -1 for temps and wattages (#55)
* use `None` instead of `-1` for temps and wattages
this way it's easier for other tools like HomeAssistant to understand if the temperature is really negative or not available

* also handle cases where we look for `-1`
2023-07-07 12:06:24 -06:00
UpstreamData
58234fcf7f version: bump version number. 2023-07-07 12:03:28 -06:00
UpstreamData
1bf863cca8 bug: set miner_mode to int instead of str to fix some issues with some X19 models. 2023-07-07 12:03:00 -06:00
UpstreamData
6482d04185 version: bump version number. 2023-07-07 11:56:41 -06:00
UpstreamData
3b58b11501 bug: remove 0 frequency level when setting sleep mode on X19, as it seems to bug some types. 2023-07-07 11:56:06 -06:00
UpstreamData
7485b8ef77 version: bump version number. 2023-07-04 10:04:20 -06:00
UpstreamData
d2bea227db bug: fix an issue with a possible SSH command in BOS+. 2023-07-04 10:01:24 -06:00
UpstreamData
1b7afaaf7e version: bump version number. 2023-06-30 08:49:31 -06:00
UpstreamData
96898d639c bug: fix some handling errors with graphql. 2023-06-30 08:49:08 -06:00
UpstreamData
eb439f4dcf version: bump version number. 2023-06-30 08:44:01 -06:00
UpstreamData
69f4349393 feature: create pwd and username property in miner object that sets web and api passwords and usernames. 2023-06-30 08:43:30 -06:00
UpstreamData
e371bb577c version: bump version number. 2023-06-29 18:10:35 -06:00
UpstreamData
2500ec3869 bug: fix possible None return from some bosminer webcommands. 2023-06-29 18:10:10 -06:00
UpstreamData
5be3187eec version: bump version number. 2023-06-29 16:51:29 -06:00
UpstreamData
be1e9127b0 bug: fix weird pool info when multiple groups are defined. 2023-06-29 16:51:15 -06:00
UpstreamData
13572c4770 version: bump version number. 2023-06-29 16:48:09 -06:00
UpstreamData
08fa3961fe bug: fix bosminer on X19 not reporting pause mode correctly. 2023-06-29 16:47:27 -06:00
UpstreamData
b5d2809e9c format: remove random print statements. 2023-06-29 15:53:53 -06:00
UpstreamData
aa538d3079 docs: add miner docs generation file. 2023-06-28 11:21:19 -06:00
UpstreamData
e1500bb75c docs: update docs. 2023-06-28 11:20:22 -06:00
UpstreamData
7f00a65598 version: bump version number. 2023-06-27 16:23:46 -06:00
UpstreamData
64c473a7d4 bug: fix improper stats key when getting uptime. 2023-06-27 16:23:21 -06:00
UpstreamData
96d9fe8e6c version: bump version number. 2023-06-27 14:56:11 -06:00
UpstreamData
0b27400d27 feature: add set_static_ip and set_dhcp for bosminer. 2023-06-27 14:55:05 -06:00
UpstreamData
666b9dfe94 version: bump version number. 2023-06-27 09:36:06 -06:00
UpstreamData
df3a080c9d feature: add uptime check for some miners, and fix a bug with get_mac on BOS. 2023-06-27 09:35:07 -06:00
UpstreamData
bf3bd7c2b9 feature: add basic support for LuxOS 2023-06-26 15:35:52 -06:00
UpstreamData
37fd60b462 version: bump version number. 2023-06-26 09:53:21 -06:00
UpstreamData
2245904740 feature: remove ssh references when getting MAC on bosminer. 2023-06-26 09:52:30 -06:00
UpstreamData
7b1b23016e feature: add support for VNish S19 No PIC. 2023-06-26 08:20:45 -06:00
UpstreamData
b5fcd62e23 version: bump version number. 2023-06-23 14:50:14 -06:00
UpstreamData
9057cde274 docs: add is_mining to docs. 2023-06-23 14:49:38 -06:00
UpstreamData
f6d35888fe feature: add is_mining to MinerData and get_data. 2023-06-23 14:47:12 -06:00
UpstreamData
f2abe9fd9e feature: add is_mining to all miner types. 2023-06-23 14:38:38 -06:00
UpstreamData
7d1a702804 feature: make is_mining abstract method. 2023-06-23 14:34:44 -06:00
UpstreamData
65d1695ce4 bug: fix is_mining for some miners. 2023-06-23 14:33:32 -06:00
UpstreamData
65fd66b8bf feature: add is_mining for antminer. 2023-06-23 14:08:54 -06:00
UpstreamData
5db52c46f3 feature: add is_mining for btminer, and fix some minor bugs. 2023-06-23 13:38:45 -06:00
UpstreamData
d06cb19da3 feature: add is_mining for bosminers. 2023-06-23 12:39:00 -06:00
UpstreamData
4530d086da bug: fix some cases where web command data can fail. 2023-06-23 11:23:20 -06:00
UpstreamData
0bd679f259 version: bump version number. 2023-06-22 15:07:25 -06:00
UpstreamData
1ce5bd0566 Update miner data and fix various bugs related to the fix. (#47)
* feature: fix influxdb data.

* bug: fix an issue with some avalon stats parsing.

* bug: add chip count for 1166 Pro.

* bug: fix some issues with bosminer scanning and some data bugs.

* bug: remove print statement.

* bug: fix failed data gathering multicommand via graphql.

* feature: add partial support for M50S+VK20

* version: bump version number.

* bug: add chip count for M50S+VK20.

* version: bump version number.

* bug: attempt to fix offset check issue on BOS+.

* bug: fix NoneType subscription on BOS+.

* bug: add support for Vnish S17+.

* bug: remove web references for Avalons.

* bug: add support for VNish S17Pro.

* bug: Try secondary identification method for antminers.

* feature: fix a bunch of functionality for avalonminers.

* bug: fix avalonminer fan speed being set as str.

* bug: fix fans speeds being represented as strings.

* bug: fix some get_fan formatting.

* docs: update supported miners list, and fix A10X model name.

* docs: update MinerData docstrings.

* docs: update factory documentation.
2023-06-22 15:06:30 -06:00
UpstreamData
67c3d05ac3 version: bump version number. 2023-06-20 12:11:43 -06:00
UpstreamData
c691868e9b bug: add chip count for M50S+VK20. 2023-06-20 12:11:05 -06:00
UpstreamData
f5e15b4046 version: bump version number. 2023-06-19 16:10:34 -06:00
UpstreamData
e14df696ee feature: add partial support for M50S+VK20 2023-06-19 16:10:00 -06:00
UpstreamData
ce5dfad850 version: bump version number. 2023-06-12 13:04:11 -06:00
UpstreamData
5cb45390be bug: add chip count for avalon 1246. 2023-06-12 13:03:41 -06:00
UpstreamData
b5216a24a6 version: bump version number. 2023-06-12 12:47:58 -06:00
UpstreamData
dd175ff3a2 bug: fix an issue with 2020 versions of Braiins OS not identifying correctly. 2023-06-12 12:47:38 -06:00
UpstreamData
9b504a3157 version: bump version number. 2023-06-12 12:42:16 -06:00
UpstreamData
0bc3bf20ee bug: fix possible missing models. 2023-06-12 12:41:50 -06:00
UpstreamData
de5380715c version: bump version number. 2023-06-12 11:06:20 -06:00
UpstreamData
00a108252d version: bump version number. 2023-06-12 11:04:22 -06:00
UpstreamData
e446176922 refactor: refactor miner types. 2023-06-12 11:02:51 -06:00
UpstreamData
134c44aedc Improve get_miner (#43)
* feature: Start refactor to new style of get_miner.  Needs testing and stability fixes.

* feature: refactor to aiohttp and fix a lot of bugs with factory.  Still needs support for some miners.

* feature: refactor miner class list to be much more readable.

* bug: remove some redundant .upper() calls.

* bug: remove some redundant .upper() calls.

* feature: add Avalonminer support in update miner factory, and add support for A1166 and A1246.

* feature: refactor get_miner to allow models to be selected as strings then selected in the top level get_miner function.

* bug: fix some naming issues, and add timeout to getting miner model.

* bug: fix not instantiating some web sessions properly.
2023-06-12 09:09:51 -06:00
UpstreamData
a2bb8b5d9b version: bump version number. 2023-06-02 09:29:42 -06:00
UpstreamData
62aaf36fd7 bug: re-order config sent to S19 to be consistent with stock. 2023-06-02 09:28:50 -06:00
UpstreamData
63023650a9 version: bump version number. 2023-06-01 09:57:21 -06:00
UpstreamData
0025c613f0 bug: fix 2 AA's in AANTMINER. 2023-06-01 09:56:54 -06:00
UpstreamData
e4ec3b2b28 version: bump version number. 2023-06-01 09:45:26 -06:00
UpstreamData
08af02a394 bug: fix wrong constructor for S19Pro+. 2023-06-01 09:45:05 -06:00
UpstreamData
afca497d8a version: bump version number. 2023-06-01 09:03:31 -06:00
UpstreamData
d50896a896 bug: add support for S19ProPlus 2023-06-01 09:02:54 -06:00
UpstreamData
117737afb5 version: bump version number. 2023-05-29 11:40:56 -06:00
UpstreamData
eabae92da6 bug: fix some issues with S19j88NoPic on braiinsOS. 2023-05-29 11:40:08 -06:00
Upstream Data
f816551d7a version: bump version number. 2023-05-25 21:10:04 -06:00
Upstream Data
4e3ea4eabb feature: add support for M50S++ models. 2023-05-25 21:08:47 -06:00
UpstreamData
74c13806fb bug: fix incorrect variable name in avalonminers. 2023-05-23 15:07:33 -06:00
UpstreamData
934d469def version: bump version number. 2023-05-23 09:37:23 -06:00
UpstreamData
0c563ef538 bug: Fix bad type hinting on ABCMeta instead of type. 2023-05-23 09:36:50 -06:00
Upstream Data
ecc76d09af bug: add chip count for M32V10. 2023-05-21 19:38:37 -06:00
Upstream Data
caa66531b7 version: bump version number. 2023-05-21 16:56:52 -06:00
Upstream Data
23ea90b56f bug: add chip count for M31SVE10. 2023-05-21 16:56:28 -06:00
UpstreamData
9e2d3aeebd version: bump version number. 2023-05-16 16:09:17 -06:00
UpstreamData
0cead26872 feature: add support for S9j. 2023-05-16 16:08:49 -06:00
UpstreamData
706844264b version: bump version number. 2023-05-16 13:22:59 -06:00
UpstreamData
3257af975a bug: fix error with type hinting. 2023-05-16 13:21:39 -06:00
UpstreamData
83a4f86e15 bug: fix a bug with connection errors rarely being raised on read in API commands. 2023-05-12 10:46:43 -06:00
433 changed files with 8003 additions and 6528 deletions

View File

@@ -1,5 +1,5 @@
# pyasic
*A set of modules for interfacing with many common types of ASIC bitcoin miners, using both their API and SSH.*
*A simplified and standardized interface for Bitcoin ASICs.*
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![pypi](https://img.shields.io/pypi/v/pyasic.svg)](https://pypi.org/project/pyasic/)

View File

@@ -15,6 +15,7 @@ Use these instead -
#### [BOSMiner API][pyasic.API.bosminer.BOSMinerAPI]
#### [BTMiner API][pyasic.API.btminer.BTMinerAPI]
#### [CGMiner API][pyasic.API.cgminer.CGMinerAPI]
#### [LUXMiner API][pyasic.API.luxminer.LUXMinerAPI]
#### [Unknown API][pyasic.API.unknown.UnknownAPI]
<br>

7
docs/API/luxminer.md Normal file
View File

@@ -0,0 +1,7 @@
# pyasic
## LUXMinerAPI
::: pyasic.API.luxminer.LUXMinerAPI
handler: python
options:
show_root_heading: false
heading_level: 4

163
docs/generate_miners.py Normal file
View File

@@ -0,0 +1,163 @@
import asyncio
import importlib
import os
import warnings
from pyasic.miners.miner_factory import MINER_CLASSES, MinerTypes
warnings.filterwarnings("ignore")
def path(cls):
module = importlib.import_module(cls.__module__)
return module.__name__ + "." + cls.__name__
def make(cls):
p = path(cls)
return p.split(".")[2]
def model_type(cls):
p = path(cls)
return p.split(".")[4]
def backend_str(backend: MinerTypes) -> str:
match backend:
case MinerTypes.ANTMINER:
return "Stock Firmware Antminers"
case MinerTypes.AVALONMINER:
return "Stock Firmware Avalonminers"
case MinerTypes.VNISH:
return "Vnish Firmware Miners"
case MinerTypes.BRAIINS_OS:
return "BOS+ Firmware Miners"
case MinerTypes.HIVEON:
return "HiveOS Firmware Miners"
case MinerTypes.INNOSILICON:
return "Stock Firmware Innosilicons"
case MinerTypes.WHATSMINER:
return "Stock Firmware Whatsminers"
case MinerTypes.GOLDSHELL:
return "Stock Firmware Goldshells"
case MinerTypes.LUX_OS:
return "LuxOS Firmware Miners"
def create_url_str(mtype: str):
return (
mtype.lower()
.replace(" ", "-")
.replace("(", "")
.replace(")", "")
.replace("+", "_1")
)
HEADER_FORMAT = "# pyasic\n## {} Models\n\n"
MINER_HEADER_FORMAT = "## {}\n"
DATA_FORMAT = """::: {}
handler: python
options:
show_root_heading: false
heading_level: 4
"""
SUPPORTED_TYPES_HEADER = """# 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.
##### pyasic currently supports the following miners and subtypes:
<style>
details {
margin:0px;
padding-top:0px;
padding-bottom:0px;
}
</style>
"""
BACKEND_TYPE_HEADER = """
<details>
<summary>{}:</summary>
<ul>"""
MINER_TYPE_HEADER = """
<details>
<summary>{} Series:</summary>
<ul>"""
MINER_DETAILS = """
<li><a href="../{}/{}#{}">{}</a></li>"""
MINER_TYPE_CLOSER = """
</ul>
</details>"""
BACKEND_TYPE_CLOSER = """
</ul>
</details>"""
m_data = {}
for m in MINER_CLASSES:
for t in MINER_CLASSES[m]:
if t is not None:
miner = MINER_CLASSES[m][t]
if make(miner) not in m_data:
m_data[make(miner)] = {}
if model_type(miner) not in m_data[make(miner)]:
m_data[make(miner)][model_type(miner)] = []
m_data[make(miner)][model_type(miner)].append(miner)
async def create_directory_structure(directory, data):
if not os.path.exists(directory):
os.makedirs(directory)
for key, value in data.items():
subdirectory = os.path.join(directory, key)
if isinstance(value, dict):
await create_directory_structure(subdirectory, value)
elif isinstance(value, list):
file_path = os.path.join(subdirectory + ".md")
with open(file_path, "w") as file:
file.write(HEADER_FORMAT.format(key))
for item in value:
header = await item("1.1.1.1").get_model()
file.write(MINER_HEADER_FORMAT.format(header))
file.write(DATA_FORMAT.format(path(item)))
async def create_supported_types(directory):
with open(os.path.join(directory, "supported_types.md"), "w") as file:
file.write(SUPPORTED_TYPES_HEADER)
for mback in MINER_CLASSES:
backend_types = {}
file.write(BACKEND_TYPE_HEADER.format(backend_str(mback)))
for mtype in MINER_CLASSES[mback]:
if mtype is None:
continue
m = MINER_CLASSES[mback][mtype]
if model_type(m) not in backend_types:
backend_types[model_type(m)] = []
backend_types[model_type(m)].append(m)
for mtype in backend_types:
file.write(MINER_TYPE_HEADER.format(mtype))
for minstance in backend_types[mtype]:
model = await minstance("1.1.1.1").get_model()
file.write(
MINER_DETAILS.format(
make(minstance), mtype, create_url_str(model), model
)
)
file.write(MINER_TYPE_CLOSER)
file.write(BACKEND_TYPE_CLOSER)
root_directory = os.path.join(os.getcwd(), "miners")
asyncio.run(create_directory_structure(root_directory, m_data))
asyncio.run(create_supported_types(root_directory))

View File

@@ -19,7 +19,7 @@ Getting started with pyasic is easy. First, find your miner (or miners) on the
## Scanning for miners
To scan for miners in pyasic, we use the class [`MinerNetwork`][pyasic.network.MinerNetwork], which abstracts the search, communication, identification, setup, and return of a miner to 1 command.
The command [`MinerNetwork().scan_network_for_miners()`][pyasic.network.MinerNetwork.scan_network_for_miners] returns a list that contains any miners found.
The command [`MinerNetwork.scan()`][pyasic.network.MinerNetwork.scan] returns a list that contains any miners found.
```python
import asyncio # asyncio for handling the async part
from pyasic.network import MinerNetwork # miner network handles the scanning
@@ -28,7 +28,7 @@ from pyasic.network import MinerNetwork # miner network handles the scanning
async def scan_miners(): # define async scan function to allow awaiting
# create a miner network
# you can pass in any IP and it will use that in a subnet with a /24 mask (255 IPs).
network = MinerNetwork("192.168.1.50") # this uses the 192.168.1.0-255 network
network = MinerNetwork.from_subnet("192.168.1.50/24") # this uses the 192.168.1.0-255 network
# scan for miners asynchronously
# this will return the correct type of miners if they are supported with all functionality.
@@ -42,8 +42,8 @@ if __name__ == "__main__":
<br>
## Creating miners based on IP
If you already know the IP address of your miner or miners, you can use the [`MinerFactory`][pyasic.miners.miner_factory.MinerFactory] to communicate and identify the miners, or an abstraction of its functionality, [`get_miner()`][pyasic.miners.miner_factory.MinerFactory.get_miner].
The function [`get_miner()`][pyasic.miners.miner_factory.MinerFactory.get_miner] will return any miner it found at the IP address specified, or an `UnknownMiner` if it cannot identify the miner.
If you already know the IP address of your miner or miners, you can use the [`MinerFactory`][pyasic.miners.miner_factory.MinerFactory] to communicate and identify the miners, or an abstraction of its functionality, [`get_miner()`][pyasic.miners.get_miner].
The function [`get_miner()`][pyasic.miners.get_miner] will return any miner it found at the IP address specified, or an `UnknownMiner` if it cannot identify the miner.
```python
import asyncio # asyncio for handling the async part
from pyasic import get_miner # handles miner creation
@@ -76,13 +76,14 @@ This function will return an instance of the dataclass [`MinerData`][pyasic.data
Each piece of data in a [`MinerData`][pyasic.data.MinerData] instance can be referenced by getting it as an attribute, such as [`MinerData().hashrate`][pyasic.data.MinerData].
```python
import asyncio
from pyasic.miners.miner_factory import MinerFactory
from pyasic import get_miner
async def gather_miner_data():
miner = await MinerFactory().get_miner("192.168.1.75")
miner_data = await miner.get_data()
print(miner_data) # all data from the dataclass
print(miner_data.hashrate) # hashrate of the miner in TH/s
miner = await get_miner("192.168.1.75")
if miner is not None:
miner_data = await miner.get_data()
print(miner_data) # all data from the dataclass
print(miner_data.hashrate) # hashrate of the miner in TH/s
if __name__ == "__main__":
asyncio.run(gather_miner_data())
@@ -126,6 +127,7 @@ These functions are
[`restart_backend`](#restart-backend),
[`stop_mining`](#stop-mining),
[`resume_mining`](#resume-mining),
[`is_mining`](#is-mining),
[`send_config`](#send-config), and
[`set_power_limit`](#set-power-limit).
@@ -227,6 +229,14 @@ These functions are
<br>
### Is Mining
::: pyasic.miners.BaseMiner.is_mining
handler: python
options:
heading_level: 4
<br>
### Send Config
::: pyasic.miners.BaseMiner.send_config
handler: python
@@ -253,7 +263,7 @@ Pyasic implements a few dataclasses as helpers to make data return types consist
[`MinerData`][pyasic.data.MinerData] is a return from the [`get_data()`](#get-data) function, and is used to have a consistent dataset across all returns.
You can call [`MinerData.asdict()`][pyasic.data.MinerData.asdict] to get the dataclass as a dictionary, and there are many other helper functions contained in the class to convert to different data formats.
You can call [`MinerData.as_dict()`][pyasic.data.MinerData.as_dict] to get the dataclass as a dictionary, and there are many other helper functions contained in the class to convert to different data formats.
[`MinerData`][pyasic.data.MinerData] instances can also be added to each other to combine their data and can be divided by a number to divide all their data, allowing you to get average data from many miners by doing -
```python
@@ -278,3 +288,27 @@ It is the return from [`get_config()`](#get-config).
Each miner has a unique way to convert the [`MinerConfig`][pyasic.config.MinerConfig] to their specific type, there are helper functions in the class.
In most cases these helper functions should not be used, as [`send_config()`](#send-config) takes a [`MinerConfig`][pyasic.config.MinerConfig] and will do the conversion to the right type for you.
## Settings
`pyasic` has settings designed to make using large groups of miners easier. You can set the default password for all types of miners using the [`pyasic.settings`][pyasic.settings] module, used as follows:
```python
from pyasic import settings
settings.update("default_antminer_password", "my_pwd")
```
Here are of all the settings, and their default values:
```
"network_ping_retries": 1,
"network_ping_timeout": 3,
"network_scan_threads": 300,
"factory_get_retries": 1,
"get_data_retries": 1,
"default_whatsminer_password": "admin",
"default_innosilicon_password": "admin",
"default_antminer_password": "root",
"default_bosminer_password": "root",
"default_vnish_password": "admin",
"default_goldshell_password": "123456789",
```

View File

@@ -1,11 +1,10 @@
# pyasic
## X15 Models
## Z15
::: pyasic.miners.zec.antminer.cgminer.X15.Z15.CGMinerZ15
::: pyasic.miners.antminer.cgminer.X15.Z15.CGMinerZ15
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -2,116 +2,114 @@
## X17 Models
## S17
::: pyasic.miners.btc.antminer.bmminer.X17.S17.BMMinerS17
::: pyasic.miners.antminer.bmminer.X17.S17.BMMinerS17
handler: python
options:
show_root_heading: false
heading_level: 4
## S17+
::: pyasic.miners.btc.antminer.bmminer.X17.S17_Plus.BMMinerS17Plus
::: pyasic.miners.antminer.bmminer.X17.S17.BMMinerS17Plus
handler: python
options:
show_root_heading: false
heading_level: 4
## S17 Pro
::: pyasic.miners.btc.antminer.bmminer.X17.S17_Pro.BMMinerS17Pro
::: pyasic.miners.antminer.bmminer.X17.S17.BMMinerS17Pro
handler: python
options:
show_root_heading: false
heading_level: 4
## S17e
::: pyasic.miners.btc.antminer.bmminer.X17.S17e.BMMinerS17e
::: pyasic.miners.antminer.bmminer.X17.S17.BMMinerS17e
handler: python
options:
show_root_heading: false
heading_level: 4
## T17
::: pyasic.miners.btc.antminer.bmminer.X17.T17.BMMinerT17
::: pyasic.miners.antminer.bmminer.X17.T17.BMMinerT17
handler: python
options:
show_root_heading: false
heading_level: 4
## T17+
::: pyasic.miners.btc.antminer.bmminer.X17.T17_Plus.BMMinerT17Plus
::: pyasic.miners.antminer.bmminer.X17.T17.BMMinerT17Plus
handler: python
options:
show_root_heading: false
heading_level: 4
## T17e
::: pyasic.miners.btc.antminer.bmminer.X17.T17e.BMMinerT17e
::: pyasic.miners.antminer.bmminer.X17.T17.BMMinerT17e
handler: python
options:
show_root_heading: false
heading_level: 4
## S17 (BOS)
::: pyasic.miners.btc.antminer.bosminer.X17.S17.BOSMinerS17
::: pyasic.miners.antminer.bosminer.X17.S17.BOSMinerS17
handler: python
options:
show_root_heading: false
heading_level: 4
## S17+ (BOS)
::: pyasic.miners.btc.antminer.bosminer.X17.S17_Plus.BOSMinerS17Plus
::: pyasic.miners.antminer.bosminer.X17.S17.BOSMinerS17Plus
handler: python
options:
show_root_heading: false
heading_level: 4
## S17 Pro (BOS)
::: pyasic.miners.btc.antminer.bosminer.X17.S17_Pro.BOSMinerS17Pro
::: pyasic.miners.antminer.bosminer.X17.S17.BOSMinerS17Pro
handler: python
options:
show_root_heading: false
heading_level: 4
## S17e (BOS)
::: pyasic.miners.btc.antminer.bosminer.X17.S17e.BOSMinerS17e
::: pyasic.miners.antminer.bosminer.X17.S17.BOSMinerS17e
handler: python
options:
show_root_heading: false
heading_level: 4
## T17 (BOS)
::: pyasic.miners.btc.antminer.bosminer.X17.T17.BOSMinerT17
::: pyasic.miners.antminer.bosminer.X17.T17.BOSMinerT17
handler: python
options:
show_root_heading: false
heading_level: 4
## T17+ (BOS)
::: pyasic.miners.btc.antminer.bosminer.X17.T17_Plus.BOSMinerT17Plus
::: pyasic.miners.antminer.bosminer.X17.T17.BOSMinerT17Plus
handler: python
options:
show_root_heading: false
heading_level: 4
## T17e (BOS)
::: pyasic.miners.btc.antminer.bosminer.X17.T17e.BOSMinerT17e
::: pyasic.miners.antminer.bosminer.X17.T17.BOSMinerT17e
handler: python
options:
show_root_heading: false
heading_level: 4
## S17+ (VNish)
::: pyasic.miners.antminer.vnish.X17.S17.VNishS17Plus
handler: python
options:
show_root_heading: false
heading_level: 4
## S17 Pro (VNish)
::: pyasic.miners.antminer.vnish.X17.S17.VNishS17Pro
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -2,109 +2,198 @@
## X19 Models
## S19
::: pyasic.miners.btc.antminer.bmminer.X19.S19.BMMinerS19
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19
handler: python
options:
show_root_heading: false
heading_level: 4
## S19L
::: pyasic.miners.btc.antminer.bmminer.X19.S19L.BMMinerS19L
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19L
handler: python
options:
show_root_heading: false
heading_level: 4
## S19 Pro
::: pyasic.miners.btc.antminer.bmminer.X19.S19_Pro.BMMinerS19Pro
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19Pro
handler: python
options:
show_root_heading: false
heading_level: 4
## S19a
::: pyasic.miners.btc.antminer.bmminer.X19.S19a.BMMinerS19a
handler: python
options:
show_root_heading: false
heading_level: 4
## S19j
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19j
handler: python
options:
show_root_heading: false
heading_level: 4
::: pyasic.miners.btc.antminer.bmminer.X19.S19j.BMMinerS19j
## S19i
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19i
handler: python
options:
show_root_heading: false
heading_level: 4
## S19+
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19Plus
handler: python
options:
show_root_heading: false
heading_level: 4
## S19j No PIC
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19jNoPIC
handler: python
options:
show_root_heading: false
heading_level: 4
## S19 Pro+
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19ProPlus
handler: python
options:
show_root_heading: false
heading_level: 4
## S19j Pro
::: pyasic.miners.btc.antminer.bmminer.X19.S19j_Pro.BMMinerS19jPro
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19jPro
handler: python
options:
show_root_heading: false
heading_level: 4
## S19 XP
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19XP
handler: python
options:
show_root_heading: false
heading_level: 4
::: pyasic.miners.btc.antminer.bmminer.X19.S19_XP.BMMinerS19XP
## S19a
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19a
handler: python
options:
show_root_heading: false
heading_level: 4
## S19a Pro
::: pyasic.miners.antminer.bmminer.X19.S19.BMMinerS19aPro
handler: python
options:
show_root_heading: false
heading_level: 4
## T19
::: pyasic.miners.btc.antminer.bmminer.X19.T19.BMMinerT19
::: pyasic.miners.antminer.bmminer.X19.T19.BMMinerT19
handler: python
options:
show_root_heading: false
heading_level: 4
## S19 (BOS)
::: pyasic.miners.btc.antminer.bosminer.X19.S19.BOSMinerS19
::: pyasic.miners.antminer.bosminer.X19.S19.BOSMinerS19
handler: python
options:
show_root_heading: false
heading_level: 4
## S19 Pro (BOS)
::: pyasic.miners.btc.antminer.bosminer.X19.S19_Pro.BOSMinerS19Pro
::: pyasic.miners.antminer.bosminer.X19.S19.BOSMinerS19Pro
handler: python
options:
show_root_heading: false
heading_level: 4
## S19j (BOS)
::: pyasic.miners.antminer.bosminer.X19.S19.BOSMinerS19j
handler: python
options:
show_root_heading: false
heading_level: 4
::: pyasic.miners.btc.antminer.bosminer.X19.S19j.BOSMinerS19j
## S19j No PIC (BOS)
::: pyasic.miners.antminer.bosminer.X19.S19.BOSMinerS19jNoPIC
handler: python
options:
show_root_heading: false
heading_level: 4
## S19j Pro (BOS)
::: pyasic.miners.antminer.bosminer.X19.S19.BOSMinerS19jPro
handler: python
options:
show_root_heading: false
heading_level: 4
::: pyasic.miners.btc.antminer.bosminer.X19.S19j_Pro.BOSMinerS19jPro
## S19j Pro (BOS)
::: pyasic.miners.antminer.bosminer.X19.S19.BOSMinerS19jPro
handler: python
options:
show_root_heading: false
heading_level: 4
## T19 (BOS)
::: pyasic.miners.btc.antminer.bosminer.X19.T19.BOSMinerT19
::: pyasic.miners.antminer.bosminer.X19.T19.BOSMinerT19
handler: python
options:
show_root_heading: false
heading_level: 4
## S19 (VNish)
::: pyasic.miners.antminer.vnish.X19.S19.VNishS19
handler: python
options:
show_root_heading: false
heading_level: 4
## S19 No PIC (VNish)
::: pyasic.miners.antminer.vnish.X19.S19.VNishS19NoPIC
handler: python
options:
show_root_heading: false
heading_level: 4
## S19 Pro (VNish)
::: pyasic.miners.antminer.vnish.X19.S19.VNishS19Pro
handler: python
options:
show_root_heading: false
heading_level: 4
## S19j (VNish)
::: pyasic.miners.antminer.vnish.X19.S19.VNishS19j
handler: python
options:
show_root_heading: false
heading_level: 4
## S19j Pro (VNish)
::: pyasic.miners.antminer.vnish.X19.S19.VNishS19jPro
handler: python
options:
show_root_heading: false
heading_level: 4
## S19a (VNish)
::: pyasic.miners.antminer.vnish.X19.S19.VNishS19a
handler: python
options:
show_root_heading: false
heading_level: 4
## S19a Pro (VNish)
::: pyasic.miners.antminer.vnish.X19.S19.VNishS19aPro
handler: python
options:
show_root_heading: false
heading_level: 4
## T19 (VNish)
::: pyasic.miners.antminer.vnish.X19.T19.VNishT19
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -1,11 +1,31 @@
# pyasic
## X3 Models
## HS3
::: pyasic.miners.hns.antminer.cgminer.X3.HS3.CGMinerHS3
## D3
::: pyasic.miners.antminer.cgminer.X3.D3.CGMinerD3
handler: python
options:
show_root_heading: false
heading_level: 4
## HS3
::: pyasic.miners.antminer.bmminer.X3.HS3.BMMinerHS3
handler: python
options:
show_root_heading: false
heading_level: 4
## L3+
::: pyasic.miners.antminer.bmminer.X3.L3.BMMinerL3Plus
handler: python
options:
show_root_heading: false
heading_level: 4
## L3+ (VNish)
::: pyasic.miners.antminer.vnish.X3.L3.VnishL3Plus
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -1,11 +1,10 @@
# pyasic
## X5 Models
## DR5
::: pyasic.miners.dcr.antminer.cgminer.X5.DR5.CGMinerDR5
::: pyasic.miners.antminer.cgminer.X5.DR5.CGMinerDR5
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -1,11 +1,10 @@
# pyasic
## X7 Models
## L7
::: pyasic.miners.ltc.antminer.bmminer.X7.L7.BMMinerL7
::: pyasic.miners.antminer.bmminer.X7.L7.BMMinerL7
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -1,44 +1,59 @@
# pyasic
## X9 Models
## X9 (BOS)
::: pyasic.miners.btc.antminer.bosminer.X9.S9.BOSMinerS9
## E9Pro
::: pyasic.miners.antminer.bmminer.X9.E9.BMMinerE9Pro
handler: python
options:
show_root_heading: false
heading_level: 4
## S9
::: pyasic.miners.btc.antminer.bmminer.X9.S9.BMMinerS9
::: pyasic.miners.antminer.bmminer.X9.S9.BMMinerS9
handler: python
options:
show_root_heading: false
heading_level: 4
## S9i
::: pyasic.miners.antminer.bmminer.X9.S9.BMMinerS9i
handler: python
options:
show_root_heading: false
heading_level: 4
::: pyasic.miners.btc.antminer.bmminer.X9.S9i.BMMinerS9i
## S9j
::: pyasic.miners.antminer.bmminer.X9.S9.BMMinerS9j
handler: python
options:
show_root_heading: false
heading_level: 4
## T9
::: pyasic.miners.btc.antminer.bmminer.X9.T9.BMMinerT9
::: pyasic.miners.antminer.bmminer.X9.T9.BMMinerT9
handler: python
options:
show_root_heading: false
heading_level: 4
## E9 Pro
::: pyasic.miners.etc.antminer.cgminer.X9.E9_Pro.CGMinerE9Pro
## S9 (BOS)
::: pyasic.miners.antminer.bosminer.X9.S9.BOSMinerS9
handler: python
options:
show_root_heading: false
heading_level: 4
## T9 (Hiveon)
::: pyasic.miners.antminer.hiveon.X9.T9.HiveonT9
handler: python
options:
show_root_heading: false
heading_level: 4
## S9 (LuxOS)
::: pyasic.miners.antminer.luxos.X9.S9.LUXMinerS9
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -1,26 +1,24 @@
# pyasic
## A10X Models
## A1026
::: pyasic.miners.btc.avalonminer.cgminer.A10X.A1026.CGMinerAvalon1026
## Avalon 1026
::: pyasic.miners.avalonminer.cgminer.A10X.A1026.CGMinerAvalon1026
handler: python
options:
show_root_heading: false
heading_level: 4
## A1047
::: pyasic.miners.btc.avalonminer.cgminer.A10X.A1047.CGMinerAvalon1047
## Avalon 1047
::: pyasic.miners.avalonminer.cgminer.A10X.A1047.CGMinerAvalon1047
handler: python
options:
show_root_heading: false
heading_level: 4
## A1066
::: pyasic.miners.btc.avalonminer.cgminer.A10X.A1066.CGMinerAvalon1066
## Avalon 1066
::: pyasic.miners.avalonminer.cgminer.A10X.A1066.CGMinerAvalon1066
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -0,0 +1,10 @@
# pyasic
## A11X Models
## Avalon 1166 Pro
::: pyasic.miners.avalonminer.cgminer.A11X.A1166.CGMinerAvalon1166Pro
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -0,0 +1,10 @@
# pyasic
## A12X Models
## Avalon 1246
::: pyasic.miners.avalonminer.cgminer.A12X.A1246.CGMinerAvalon1246
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -1,26 +1,24 @@
# pyasic
## A7X Models
## A721
::: pyasic.miners.btc.avalonminer.cgminer.A7X.A721.CGMinerAvalon721
## Avalon 721
::: pyasic.miners.avalonminer.cgminer.A7X.A721.CGMinerAvalon721
handler: python
options:
show_root_heading: false
heading_level: 4
## A741
::: pyasic.miners.btc.avalonminer.cgminer.A7X.A741.CGMinerAvalon741
## Avalon 741
::: pyasic.miners.avalonminer.cgminer.A7X.A741.CGMinerAvalon741
handler: python
options:
show_root_heading: false
heading_level: 4
## A761
::: pyasic.miners.btc.avalonminer.cgminer.A7X.A761.CGMinerAvalon761
## Avalon 761
::: pyasic.miners.avalonminer.cgminer.A7X.A761.CGMinerAvalon761
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -1,26 +1,24 @@
# pyasic
## A8X Models
## A821
::: pyasic.miners.btc.avalonminer.cgminer.A8X.A821.CGMinerAvalon821
## Avalon 821
::: pyasic.miners.avalonminer.cgminer.A8X.A821.CGMinerAvalon821
handler: python
options:
show_root_heading: false
heading_level: 4
## A841
::: pyasic.miners.btc.avalonminer.cgminer.A8X.A841.CGMinerAvalon841
## Avalon 841
::: pyasic.miners.avalonminer.cgminer.A8X.A841.CGMinerAvalon841
handler: python
options:
show_root_heading: false
heading_level: 4
## A851
::: pyasic.miners.btc.avalonminer.cgminer.A8X.A851.CGMinerAvalon851
## Avalon 851
::: pyasic.miners.avalonminer.cgminer.A8X.A851.CGMinerAvalon851
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -1,10 +1,10 @@
# pyasic
## A9X Models
## A921
::: pyasic.miners.btc.avalonminer.cgminer.A9X.A921.CGMinerAvalon921
## Avalon 921
::: pyasic.miners.avalonminer.cgminer.A9X.A921.CGMinerAvalon921
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -1,9 +1,7 @@
# pyasic
## CKX Models
## LUXMiner Backend
## CK5
::: pyasic.miners.ckb.goldshell.bfgminer.CKX.CK5.BFGMinerCK5
::: pyasic.miners.backends.luxminer.LUXMiner
handler: python
options:
show_root_heading: false

View File

@@ -1,9 +1,7 @@
# pyasic
## HSX Models
## VNish Backend
## HS5
::: pyasic.miners.hns.goldshell.bfgminer.HSX.HS5.BFGMinerHS5
::: pyasic.miners.backends.vnish.VNish
handler: python
options:
show_root_heading: false

View File

@@ -0,0 +1,24 @@
# pyasic
## X5 Models
## CK5
::: pyasic.miners.goldshell.bfgminer.X5.CK5.BFGMinerCK5
handler: python
options:
show_root_heading: false
heading_level: 4
## HS5
::: pyasic.miners.goldshell.bfgminer.X5.HS5.BFGMinerHS5
handler: python
options:
show_root_heading: false
heading_level: 4
## KD5
::: pyasic.miners.goldshell.bfgminer.X5.KD5.BFGMinerKD5
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -0,0 +1,10 @@
# pyasic
## XMax Models
## KD Max
::: pyasic.miners.goldshell.bfgminer.XMax.KDMax.BFGMinerKDMax
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -2,9 +2,9 @@
## A10X Models
## A10X
::: pyasic.miners.etc.innosilicon.cgminer.A10X.A10X.CGMinerA10X
::: pyasic.miners.innosilicon.cgminer.A10X.A10X.CGMinerA10X
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -2,9 +2,9 @@
## T3X Models
## T3H+
::: pyasic.miners.btc.innosilicon.cgminer.T3X.T3H_Plus.CGMinerInnosiliconT3HPlus
::: pyasic.miners.innosilicon.cgminer.T3X.T3H.CGMinerT3HPlus
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -1,6 +1,14 @@
# pyasic
## Miner Factory
[`MinerFactory`][pyasic.miners.miner_factory.MinerFactory] is the way to create miner types in `pyasic`. The most important method is [`get_miner()`][pyasic.get_miner], which is mapped to [`pyasic.get_miner()`][pyasic.get_miner], and should be used from there.
The instance used for [`pyasic.get_miner()`][pyasic.get_miner] is `pyasic.miner_factory`.
[`MinerFactory`][pyasic.MinerFactory] also keeps a cache, which can be cleared if needed with `pyasic.miner_factory.clear_cached_miners()`.
Finally, there is functionality to get multiple miners without using `asyncio.gather()` explicitly. Use `pyasic.miner_factory.get_multiple_miners()` with a list of IPs as strings to get a list of miner instances. You can also get multiple miners with an `AsyncGenerator` by using `pyasic.miner_factory.get_miner_generator()`.
::: pyasic.miners.miner_factory.MinerFactory
handler: python
options:
@@ -8,6 +16,14 @@
heading_level: 4
<br>
## Get Miner
::: pyasic.miners.get_miner
handler: python
options:
show_root_heading: false
heading_level: 4
<br>
## AnyMiner
::: pyasic.miners.miner_factory.AnyMiner
handler: python

View File

@@ -11,37 +11,74 @@ details {
padding-bottom:0px;
}
</style>
<details style="margin:0px; padding-top:0px; padding-bottom:0px;">
<summary>Braiins OS+ Devices:</summary>
<details>
<summary>Stock Firmware Antminers:</summary>
<ul>
<details>
<summary>X19 Series:</summary>
<summary>X3 Series:</summary>
<ul>
<li><a href="../antminer/X19#s19-bos">S19</a></li>
<li><a href="../antminer/X19#s19-pro-bos">S19 Pro</a></li>
<li><a href="../antminer/X19#s19j-bos">S19j</a></li>
<li><a href="../antminer/X19#s19j-pro-bos">S19j Pro</a></li>
<li><a href="../antminer/X19#t19-bos">T19</a></li>
<li><a href="../antminer/X3#d3">D3</a></li>
<li><a href="../antminer/X3#hs3">HS3</a></li>
<li><a href="../antminer/X3#l3_1">L3+</a></li>
</ul>
</details>
<details>
<summary>X17 Series:</summary>
<summary>X5 Series:</summary>
<ul>
<li><a href="../antminer/X17#s17-bos">S17</a></li>
<li><a href="../antminer/X17#s17-plus-bos">S17+</a></li>
<li><a href="../antminer/X17#s17-pro-bos">S17 Pro</a></li>
<li><a href="../antminer/X17#s17e-bos">S17e</a></li>
<li><a href="../antminer/X17#t17-bos">T17</a></li>
<li><a href="../antminer/X17#t17-plus-bos">T17+</a></li>
<li><a href="../antminer/X17#t17e-bos">T17e</a></li>
<li><a href="../antminer/X5#dr5">DR5</a></li>
</ul>
</details>
<details>
<summary>X7 Series:</summary>
<ul>
<li><a href="../antminer/X7#l7">L7</a></li>
</ul>
</details>
<details>
<summary>X9 Series:</summary>
<ul>
<li><a href="../antminer/X9#s9-bos">S9</a></li>
<li><a href="../antminer/X9#s9-bos">S9i</a></li>
<li><a href="../antminer/X9#s9-bos">S9j</a></li>
<li><a href="../antminer/X9#e9pro">E9Pro</a></li>
<li><a href="../antminer/X9#s9">S9</a></li>
<li><a href="../antminer/X9#s9i">S9i</a></li>
<li><a href="../antminer/X9#s9j">S9j</a></li>
<li><a href="../antminer/X9#t9">T9</a></li>
</ul>
</details>
<details>
<summary>X15 Series:</summary>
<ul>
<li><a href="../antminer/X15#z15">Z15</a></li>
</ul>
</details>
<details>
<summary>X17 Series:</summary>
<ul>
<li><a href="../antminer/X17#s17">S17</a></li>
<li><a href="../antminer/X17#s17_1">S17+</a></li>
<li><a href="../antminer/X17#s17-pro">S17 Pro</a></li>
<li><a href="../antminer/X17#s17e">S17e</a></li>
<li><a href="../antminer/X17#t17">T17</a></li>
<li><a href="../antminer/X17#t17_1">T17+</a></li>
<li><a href="../antminer/X17#t17e">T17e</a></li>
</ul>
</details>
<details>
<summary>X19 Series:</summary>
<ul>
<li><a href="../antminer/X19#s19">S19</a></li>
<li><a href="../antminer/X19#s19l">S19L</a></li>
<li><a href="../antminer/X19#s19-pro">S19 Pro</a></li>
<li><a href="../antminer/X19#s19j">S19j</a></li>
<li><a href="../antminer/X19#s19i">S19i</a></li>
<li><a href="../antminer/X19#s19_1">S19+</a></li>
<li><a href="../antminer/X19#s19j-no-pic">S19j No PIC</a></li>
<li><a href="../antminer/X19#s19-pro_1">S19 Pro+</a></li>
<li><a href="../antminer/X19#s19j-pro">S19j Pro</a></li>
<li><a href="../antminer/X19#s19-xp">S19 XP</a></li>
<li><a href="../antminer/X19#s19a">S19a</a></li>
<li><a href="../antminer/X19#s19a-pro">S19a Pro</a></li>
<li><a href="../antminer/X19#t19">T19</a></li>
</ul>
</details>
</ul>
@@ -51,440 +88,210 @@ details {
<ul>
<details>
<summary>M2X Series:</summary>
<ul>
<details>
<summary><a href='../whatsminer/M2X/#M20'>M20</a></summary>
<ul>
<li><a href='../whatsminer/M2X/#M20V10'>M20V10</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M2X/#M20S'>M20S</a></summary>
<ul>
<li><a href='../whatsminer/M2X/#M20SV10'>M20SV10</a></li>
<li><a href='../whatsminer/M2X/#M20SV20'>M20SV20</a></li>
<li><a href='../whatsminer/M2X/#M20SV30'>M20SV30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M2X/#M20S_1'>M20S+</a></summary>
<ul>
<li><a href='../whatsminer/M2X/#M20S_1V30'>M20S+V30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M2X/#M21'>M21</a></summary>
<ul>
<li><a href='../whatsminer/M2X/#M21V10'>M21V10</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M2X/#M21S'>M21S</a></summary>
<ul>
<li><a href='../whatsminer/M2X/#M21SV20'>M21SV20</a></li>
<li><a href='../whatsminer/M2X/#M21SV60'>M21SV60</a></li>
<li><a href='../whatsminer/M2X/#M21SV70'>M21SV70</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M2X/#M21S_1'>M21S+</a></summary>
<ul>
<li><a href='../whatsminer/M2X/#M21S_1V20'>M21S+V20</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M2X/#M29'>M29</a></summary>
<ul>
<li><a href='../whatsminer/M2X/#M29V10'>M29V10</a></li>
</ul>
</details>
</ul>
<ul>
<li><a href="../whatsminer/M2X#m20-v10">M20 V10</a></li>
<li><a href="../whatsminer/M2X#m20s-v10">M20S V10</a></li>
<li><a href="../whatsminer/M2X#m20s-v20">M20S V20</a></li>
<li><a href="../whatsminer/M2X#m20s-v30">M20S V30</a></li>
<li><a href="../whatsminer/M2X#m20p-v10">M20P V10</a></li>
<li><a href="../whatsminer/M2X#m20p-v30">M20P V30</a></li>
<li><a href="../whatsminer/M2X#m20s_1-v30">M20S+ V30</a></li>
<li><a href="../whatsminer/M2X#m21-v10">M21 V10</a></li>
<li><a href="../whatsminer/M2X#m21s-v20">M21S V20</a></li>
<li><a href="../whatsminer/M2X#m21s-v60">M21S V60</a></li>
<li><a href="../whatsminer/M2X#m21s-v70">M21S V70</a></li>
<li><a href="../whatsminer/M2X#m21s_1-v20">M21S+ V20</a></li>
<li><a href="../whatsminer/M2X#m29-v10">M29 V10</a></li>
</ul>
</details>
<details>
<summary>M3X Series:</summary>
<ul>
<details>
<summary><a href='../whatsminer/M3X/#M30'>M30</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M30V10'>M30V10</a></li>
<li><a href='../whatsminer/M3X/#M30V20'>M30V20</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M30S'>M30S</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M30SV10'>M30SV10</a></li>
<li><a href='../whatsminer/M3X/#M30SV20'>M30SV20</a></li>
<li><a href='../whatsminer/M3X/#M30SV30'>M30SV30</a></li>
<li><a href='../whatsminer/M3X/#M30SV40'>M30SV40</a></li>
<li><a href='../whatsminer/M3X/#M30SV50'>M30SV50</a></li>
<li><a href='../whatsminer/M3X/#M30SV60'>M30SV60</a></li>
<li><a href='../whatsminer/M3X/#M30SV70'>M30SV70</a></li>
<li><a href='../whatsminer/M3X/#M30SV80'>M30SV80</a></li>
<li><a href='../whatsminer/M3X/#M30SVE10'>M30SVE10</a></li>
<li><a href='../whatsminer/M3X/#M30SVE20'>M30SVE20</a></li>
<li><a href='../whatsminer/M3X/#M30SVE30'>M30SVE30</a></li>
<li><a href='../whatsminer/M3X/#M30SVE40'>M30SVE40</a></li>
<li><a href='../whatsminer/M3X/#M30SVE50'>M30SVE50</a></li>
<li><a href='../whatsminer/M3X/#M30SVE60'>M30SVE60</a></li>
<li><a href='../whatsminer/M3X/#M30SVE70'>M30SVE70</a></li>
<li><a href='../whatsminer/M3X/#M30SVF10'>M30SVF10</a></li>
<li><a href='../whatsminer/M3X/#M30SVF20'>M30SVF20</a></li>
<li><a href='../whatsminer/M3X/#M30SVF30'>M30SVF30</a></li>
<li><a href='../whatsminer/M3X/#M30SVG10'>M30SVG10</a></li>
<li><a href='../whatsminer/M3X/#M30SVG20'>M30SVG20</a></li>
<li><a href='../whatsminer/M3X/#M30SVG30'>M30SVG30</a></li>
<li><a href='../whatsminer/M3X/#M30SVG40'>M30SVG40</a></li>
<li><a href='../whatsminer/M3X/#M30SVH10'>M30SVH10</a></li>
<li><a href='../whatsminer/M3X/#M30SVH20'>M30SVH20</a></li>
<li><a href='../whatsminer/M3X/#M30SVH30'>M30SVH30</a></li>
<li><a href='../whatsminer/M3X/#M30SVH40'>M30SVH40</a></li>
<li><a href='../whatsminer/M3X/#M30SVH50'>M30SVH50</a></li>
<li><a href='../whatsminer/M3X/#M30SVH60'>M30SVH60</a></li>
<li><a href='../whatsminer/M3X/#M30SVI20'>M30SVI20</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M30S_1'>M30S+</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M30S_1V10'>M30S+V10</a></li>
<li><a href='../whatsminer/M3X/#M30S_1V20'>M30S+V20</a></li>
<li><a href='../whatsminer/M3X/#M30S_1V30'>M30S+V30</a></li>
<li><a href='../whatsminer/M3X/#M30S_1V40'>M30S+V40</a></li>
<li><a href='../whatsminer/M3X/#M30S_1V50'>M30S+V50</a></li>
<li><a href='../whatsminer/M3X/#M30S_1V60'>M30S+V60</a></li>
<li><a href='../whatsminer/M3X/#M30S_1V70'>M30S+V70</a></li>
<li><a href='../whatsminer/M3X/#M30S_1V80'>M30S+V80</a></li>
<li><a href='../whatsminer/M3X/#M30S_1V90'>M30S+V90</a></li>
<li><a href='../whatsminer/M3X/#M30S_1V100'>M30S+V100</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VE30'>M30S+VE30</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VE40'>M30S+VE40</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VE50'>M30S+VE50</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VE60'>M30S+VE60</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VE70'>M30S+VE70</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VE80'>M30S+VE80</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VE90'>M30S+VE90</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VE100'>M30S+VE100</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VF20'>M30S+VF20</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VF30'>M30S+VF30</a></li>
<li><a href='../whatsminer/M3X/#M36S_1VG30'>M36S+VG30</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VG30'>M30S+VG30</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VG40'>M30S+VG40</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VG50'>M30S+VG50</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VG60'>M30S+VG60</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VH10'>M30S+VH10</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VH20'>M30S+VH20</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VH30'>M30S+VH30</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VH40'>M30S+VH40</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VH50'>M30S+VH50</a></li>
<li><a href='../whatsminer/M3X/#M30S_1VH60'>M30S+VH60</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M30S_2'>M30S++</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M30S_2V10'>M30S++V10</a></li>
<li><a href='../whatsminer/M3X/#M30S_2V20'>M30S++V20</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VE30'>M30S++VE30</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VE40'>M30S++VE40</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VE50'>M30S++VE50</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VF40'>M30S++VF40</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VG30'>M30S++VG30</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VG40'>M30S++VG40</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VG50'>M30S++VG50</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VH10'>M30S++VH10</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VH20'>M30S++VH20</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VH30'>M30S++VH30</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VH40'>M30S++VH40</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VH50'>M30S++VH50</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VH60'>M30S++VH60</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VH70'>M30S++VH70</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VH80'>M30S++VH80</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VH90'>M30S++VH90</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VH100'>M30S++VH100</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VJ20'>M30S++VJ20</a></li>
<li><a href='../whatsminer/M3X/#M30S_2VJ30'>M30S++VJ30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M31'>M31</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M31V10'>M31V10</a></li>
<li><a href='../whatsminer/M3X/#M31V20'>M31V20</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M31S'>M31S</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M31SV10'>M31SV10</a></li>
<li><a href='../whatsminer/M3X/#M31SV20'>M31SV20</a></li>
<li><a href='../whatsminer/M3X/#M31SV30'>M31SV30</a></li>
<li><a href='../whatsminer/M3X/#M31SV40'>M31SV40</a></li>
<li><a href='../whatsminer/M3X/#M31SV50'>M31SV50</a></li>
<li><a href='../whatsminer/M3X/#M31SV60'>M31SV60</a></li>
<li><a href='../whatsminer/M3X/#M31SV70'>M31SV70</a></li>
<li><a href='../whatsminer/M3X/#M31SV80'>M31SV80</a></li>
<li><a href='../whatsminer/M3X/#M31SV90'>M31SV90</a></li>
<li><a href='../whatsminer/M3X/#M31SVE10'>M31SVE10</a></li>
<li><a href='../whatsminer/M3X/#M31SVE20'>M31SVE20</a></li>
<li><a href='../whatsminer/M3X/#M31SVE30'>M31SVE30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M31SE'>M31SE</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M31SEV10'>M31SEV10</a></li>
<li><a href='../whatsminer/M3X/#M31SEV20'>M31SEV20</a></li>
<li><a href='../whatsminer/M3X/#M31SEV30'>M31SEV30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M31H'>M31H</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M31HV40'>M31HV40</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M31S_1'>M31S+</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M31S_1V10'>M31S+V10</a></li>
<li><a href='../whatsminer/M3X/#M31S_1V20'>M31S+V20</a></li>
<li><a href='../whatsminer/M3X/#M31S_1V30'>M31S+V30</a></li>
<li><a href='../whatsminer/M3X/#M31S_1V40'>M31S+V40</a></li>
<li><a href='../whatsminer/M3X/#M31S_1V50'>M31S+V50</a></li>
<li><a href='../whatsminer/M3X/#M31S_1V60'>M31S+V60</a></li>
<li><a href='../whatsminer/M3X/#M31S_1V80'>M31S+V80</a></li>
<li><a href='../whatsminer/M3X/#M31S_1V90'>M31S+V90</a></li>
<li><a href='../whatsminer/M3X/#M31S_1V100'>M31S+V100</a></li>
<li><a href='../whatsminer/M3X/#M31S_1VE10'>M31S+VE10</a></li>
<li><a href='../whatsminer/M3X/#M31S_1VE20'>M31S+VE20</a></li>
<li><a href='../whatsminer/M3X/#M31S_1VE30'>M31S+VE30</a></li>
<li><a href='../whatsminer/M3X/#M31S_1VE40'>M31S+VE40</a></li>
<li><a href='../whatsminer/M3X/#M31S_1VE50'>M31S+VE50</a></li>
<li><a href='../whatsminer/M3X/#M31S_1VE60'>M31S+VE60</a></li>
<li><a href='../whatsminer/M3X/#M31S_1VE80'>M31S+VE80</a></li>
<li><a href='../whatsminer/M3X/#M31S_1VF20'>M31S+VF20</a></li>
<li><a href='../whatsminer/M3X/#M31S_1VF30'>M31S+VF30</a></li>
<li><a href='../whatsminer/M3X/#M31S_1VG20'>M31S+VG20</a></li>
<li><a href='../whatsminer/M3X/#M31S_1VG30'>M31S+VG30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M32'>M32</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M32V10'>M32V10</a></li>
<li><a href='../whatsminer/M3X/#M32V20'>M32V20</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M33'>M33</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M33V10'>M33V10</a></li>
<li><a href='../whatsminer/M3X/#M33V20'>M33V20</a></li>
<li><a href='../whatsminer/M3X/#M33V30'>M33V30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M33S'>M33S</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M33SVG30'>M33SVG30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M33S_1'>M33S+</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M33S_1VH20'>M33S+VH20</a></li>
<li><a href='../whatsminer/M3X/#M33S_1VH30'>M33S+VH30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M33S_2'>M33S++</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M33S_2VH20'>M33S++VH20</a></li>
<li><a href='../whatsminer/M3X/#M33S_2VH30'>M33S++VH30</a></li>
<li><a href='../whatsminer/M3X/#M33S_2VG40'>M33S++VG40</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M34S_1'>M34S+</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M34S_1VE10'>M34S+VE10</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M36S'>M36S</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M36SVE10'>M36SVE10</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M36S_1'>M36S+</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M36S_1VG30'>M36S+VG30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M36S_2'>M36S++</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M36S_2VH30'>M36S++VH30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M3X/#M39'>M39</a></summary>
<ul>
<li><a href='../whatsminer/M3X/#M39V20'>M39V20</a></li>
</ul>
</details>
</ul>
<ul>
<li><a href="../whatsminer/M3X#m30-v10">M30 V10</a></li>
<li><a href="../whatsminer/M3X#m30-v20">M30 V20</a></li>
<li><a href="../whatsminer/M3X#m30k-v10">M30K V10</a></li>
<li><a href="../whatsminer/M3X#m30l-v10">M30L V10</a></li>
<li><a href="../whatsminer/M3X#m30s-v10">M30S V10</a></li>
<li><a href="../whatsminer/M3X#m30s-v20">M30S V20</a></li>
<li><a href="../whatsminer/M3X#m30s-v30">M30S V30</a></li>
<li><a href="../whatsminer/M3X#m30s-v40">M30S V40</a></li>
<li><a href="../whatsminer/M3X#m30s-v50">M30S V50</a></li>
<li><a href="../whatsminer/M3X#m30s-v60">M30S V60</a></li>
<li><a href="../whatsminer/M3X#m30s-v70">M30S V70</a></li>
<li><a href="../whatsminer/M3X#m30s-v80">M30S V80</a></li>
<li><a href="../whatsminer/M3X#m30s-ve10">M30S VE10</a></li>
<li><a href="../whatsminer/M3X#m30s-ve20">M30S VE20</a></li>
<li><a href="../whatsminer/M3X#m30s-ve30">M30S VE30</a></li>
<li><a href="../whatsminer/M3X#m30s-ve40">M30S VE40</a></li>
<li><a href="../whatsminer/M3X#m30s-ve50">M30S VE50</a></li>
<li><a href="../whatsminer/M3X#m30s-ve60">M30S VE60</a></li>
<li><a href="../whatsminer/M3X#m30s-ve70">M30S VE70</a></li>
<li><a href="../whatsminer/M3X#m30s-vf10">M30S VF10</a></li>
<li><a href="../whatsminer/M3X#m30s-vf20">M30S VF20</a></li>
<li><a href="../whatsminer/M3X#m30s-vf30">M30S VF30</a></li>
<li><a href="../whatsminer/M3X#m30s-vg10">M30S VG10</a></li>
<li><a href="../whatsminer/M3X#m30s-vg20">M30S VG20</a></li>
<li><a href="../whatsminer/M3X#m30s-vg30">M30S VG30</a></li>
<li><a href="../whatsminer/M3X#m30s-vg40">M30S VG40</a></li>
<li><a href="../whatsminer/M3X#m30s-vh10">M30S VH10</a></li>
<li><a href="../whatsminer/M3X#m30s-vh20">M30S VH20</a></li>
<li><a href="../whatsminer/M3X#m30s-vh30">M30S VH30</a></li>
<li><a href="../whatsminer/M3X#m30s-vh40">M30S VH40</a></li>
<li><a href="../whatsminer/M3X#m30s-vh50">M30S VH50</a></li>
<li><a href="../whatsminer/M3X#m30s-vh60">M30S VH60</a></li>
<li><a href="../whatsminer/M3X#m30s-vi20">M30S VI20</a></li>
<li><a href="../whatsminer/M3X#m30s_1-v10">M30S+ V10</a></li>
<li><a href="../whatsminer/M3X#m30s_1-v20">M30S+ V20</a></li>
<li><a href="../whatsminer/M3X#m30s_1-v30">M30S+ V30</a></li>
<li><a href="../whatsminer/M3X#m30s_1-v40">M30S+ V40</a></li>
<li><a href="../whatsminer/M3X#m30s_1-v50">M30S+ V50</a></li>
<li><a href="../whatsminer/M3X#m30s_1-v60">M30S+ V60</a></li>
<li><a href="../whatsminer/M3X#m30s_1-v70">M30S+ V70</a></li>
<li><a href="../whatsminer/M3X#m30s_1-v80">M30S+ V80</a></li>
<li><a href="../whatsminer/M3X#m30s_1-v90">M30S+ V90</a></li>
<li><a href="../whatsminer/M3X#m30s_1-v100">M30S+ V100</a></li>
<li><a href="../whatsminer/M3X#m30s_1-ve30">M30S+ VE30</a></li>
<li><a href="../whatsminer/M3X#m30s_1-ve40">M30S+ VE40</a></li>
<li><a href="../whatsminer/M3X#m30s_1-ve50">M30S+ VE50</a></li>
<li><a href="../whatsminer/M3X#m30s_1-ve60">M30S+ VE60</a></li>
<li><a href="../whatsminer/M3X#m30s_1-ve70">M30S+ VE70</a></li>
<li><a href="../whatsminer/M3X#m30s_1-ve80">M30S+ VE80</a></li>
<li><a href="../whatsminer/M3X#m30s_1-ve90">M30S+ VE90</a></li>
<li><a href="../whatsminer/M3X#m30s_1-ve100">M30S+ VE100</a></li>
<li><a href="../whatsminer/M3X#m30s_1-vf20">M30S+ VF20</a></li>
<li><a href="../whatsminer/M3X#m30s_1-vf30">M30S+ VF30</a></li>
<li><a href="../whatsminer/M3X#m30s_1-vg20">M30S+ VG20</a></li>
<li><a href="../whatsminer/M3X#m30s_1-vg30">M30S+ VG30</a></li>
<li><a href="../whatsminer/M3X#m30s_1-vg40">M30S+ VG40</a></li>
<li><a href="../whatsminer/M3X#m30s_1-vg50">M30S+ VG50</a></li>
<li><a href="../whatsminer/M3X#m30s_1-vg60">M30S+ VG60</a></li>
<li><a href="../whatsminer/M3X#m30s_1-vh10">M30S+ VH10</a></li>
<li><a href="../whatsminer/M3X#m30s_1-vh20">M30S+ VH20</a></li>
<li><a href="../whatsminer/M3X#m30s_1-vh30">M30S+ VH30</a></li>
<li><a href="../whatsminer/M3X#m30s_1-vh40">M30S+ VH40</a></li>
<li><a href="../whatsminer/M3X#m30s_1-vh50">M30S+ VH50</a></li>
<li><a href="../whatsminer/M3X#m30s_1-vh60">M30S+ VH60</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-v10">M30S++ V10</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-v20">M30S++ V20</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-ve30">M30S++ VE30</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-ve40">M30S++ VE40</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-ve50">M30S++ VE50</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vf40">M30S++ VF40</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vg30">M30S++ VG30</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vg40">M30S++ VG40</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vg50">M30S++ VG50</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vh10">M30S++ VH10</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vh20">M30S++ VH20</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vh30">M30S++ VH30</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vh40">M30S++ VH40</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vh50">M30S++ VH50</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vh60">M30S++ VH60</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vh70">M30S++ VH70</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vh80">M30S++ VH80</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vh90">M30S++ VH90</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vh100">M30S++ VH100</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vj20">M30S++ VJ20</a></li>
<li><a href="../whatsminer/M3X#m30s_1_1-vj30">M30S++ VJ30</a></li>
<li><a href="../whatsminer/M3X#m31-v10">M31 V10</a></li>
<li><a href="../whatsminer/M3X#m31-v20">M31 V20</a></li>
<li><a href="../whatsminer/M3X#m31h-v10">M31H V10</a></li>
<li><a href="../whatsminer/M3X#m31h-v40">M31H V40</a></li>
<li><a href="../whatsminer/M3X#m30l-v10">M30L V10</a></li>
<li><a href="../whatsminer/M3X#m31s-v10">M31S V10</a></li>
<li><a href="../whatsminer/M3X#m31s-v20">M31S V20</a></li>
<li><a href="../whatsminer/M3X#m31s-v30">M31S V30</a></li>
<li><a href="../whatsminer/M3X#m31s-v40">M31S V40</a></li>
<li><a href="../whatsminer/M3X#m31s-v50">M31S V50</a></li>
<li><a href="../whatsminer/M3X#m31s-v60">M31S V60</a></li>
<li><a href="../whatsminer/M3X#m31s-v70">M31S V70</a></li>
<li><a href="../whatsminer/M3X#m31s-v80">M31S V80</a></li>
<li><a href="../whatsminer/M3X#m31s-v90">M31S V90</a></li>
<li><a href="../whatsminer/M3X#m31s-ve10">M31S VE10</a></li>
<li><a href="../whatsminer/M3X#m31s-ve20">M31S VE20</a></li>
<li><a href="../whatsminer/M3X#m31s-ve30">M31S VE30</a></li>
<li><a href="../whatsminer/M3X#m31se-v10">M31SE V10</a></li>
<li><a href="../whatsminer/M3X#m31se-v20">M31SE V20</a></li>
<li><a href="../whatsminer/M3X#m31se-v30">M31SE V30</a></li>
<li><a href="../whatsminer/M3X#m31s_1-v10">M31S+ V10</a></li>
<li><a href="../whatsminer/M3X#m31s_1-v20">M31S+ V20</a></li>
<li><a href="../whatsminer/M3X#m31s_1-v30">M31S+ V30</a></li>
<li><a href="../whatsminer/M3X#m31s_1-v40">M31S+ V40</a></li>
<li><a href="../whatsminer/M3X#m31s_1-v50">M31S+ V50</a></li>
<li><a href="../whatsminer/M3X#m31s_1-v60">M31S+ V60</a></li>
<li><a href="../whatsminer/M3X#m31s_1-v80">M31S+ V80</a></li>
<li><a href="../whatsminer/M3X#m31s_1-v90">M31S+ V90</a></li>
<li><a href="../whatsminer/M3X#m31s_1-v100">M31S+ V100</a></li>
<li><a href="../whatsminer/M3X#m31s_1-ve10">M31S+ VE10</a></li>
<li><a href="../whatsminer/M3X#m31s_1-ve20">M31S+ VE20</a></li>
<li><a href="../whatsminer/M3X#m31s_1-ve30">M31S+ VE30</a></li>
<li><a href="../whatsminer/M3X#m31s_1-ve40">M31S+ VE40</a></li>
<li><a href="../whatsminer/M3X#m31s_1-ve50">M31S+ VE50</a></li>
<li><a href="../whatsminer/M3X#m31s_1-ve60">M31S+ VE60</a></li>
<li><a href="../whatsminer/M3X#m31s_1-ve80">M31S+ VE80</a></li>
<li><a href="../whatsminer/M3X#m31s_1-vf20">M31S+ VF20</a></li>
<li><a href="../whatsminer/M3X#m31s_1-vf30">M31S+ VF30</a></li>
<li><a href="../whatsminer/M3X#m31s_1-vg20">M31S+ VG20</a></li>
<li><a href="../whatsminer/M3X#m31s_1-vg30">M31S+ VG30</a></li>
<li><a href="../whatsminer/M3X#m32-v10">M32 V10</a></li>
<li><a href="../whatsminer/M3X#m32-v20">M32 V20</a></li>
<li><a href="../whatsminer/M3X#m33-v10">M33 V10</a></li>
<li><a href="../whatsminer/M3X#m33-v20">M33 V20</a></li>
<li><a href="../whatsminer/M3X#m33-v30">M33 V30</a></li>
<li><a href="../whatsminer/M3X#m33s-vg30">M33S VG30</a></li>
<li><a href="../whatsminer/M3X#m33s_1-vg20">M33S+ VG20</a></li>
<li><a href="../whatsminer/M3X#m33s_1-vh20">M33S+ VH20</a></li>
<li><a href="../whatsminer/M3X#m33s_1-vh30">M33S+ VH30</a></li>
<li><a href="../whatsminer/M3X#m33s_1_1-vh20">M33S++ VH20</a></li>
<li><a href="../whatsminer/M3X#m33s_1_1-vh30">M33S++ VH30</a></li>
<li><a href="../whatsminer/M3X#m33s_1_1-vg40">M33S++ VG40</a></li>
<li><a href="../whatsminer/M3X#m34s_1-ve10">M34S+ VE10</a></li>
<li><a href="../whatsminer/M3X#m36s-ve10">M36S VE10</a></li>
<li><a href="../whatsminer/M3X#m36s_1-vg30">M36S+ VG30</a></li>
<li><a href="../whatsminer/M3X#m36s_1_1-vh30">M36S++ VH30</a></li>
<li><a href="../whatsminer/M3X#m39-v10">M39 V10</a></li>
<li><a href="../whatsminer/M3X#m39-v20">M39 V20</a></li>
<li><a href="../whatsminer/M3X#m39-v30">M39 V30</a></li>
</ul>
</details>
<details>
<summary>M5X Series:</summary>
<ul>
<details>
<summary><a href='../whatsminer/M5X/#M50'>M50</a></summary>
<ul>
<li><a href='../whatsminer/M5X/#M50VG30'>M50VG30</a></li>
<li><a href='../whatsminer/M5X/#M50VH10'>M50VH10</a></li>
<li><a href='../whatsminer/M5X/#M50VH20'>M50VH20</a></li>
<li><a href='../whatsminer/M5X/#M50VH30'>M50VH30</a></li>
<li><a href='../whatsminer/M5X/#M50VH40'>M50VH40</a></li>
<li><a href='../whatsminer/M5X/#M50VH50'>M50VH50</a></li>
<li><a href='../whatsminer/M5X/#M50VH60'>M50VH60</a></li>
<li><a href='../whatsminer/M5X/#M50VH70'>M50VH70</a></li>
<li><a href='../whatsminer/M5X/#M50VH80'>M50VH80</a></li>
<li><a href='../whatsminer/M5X/#M50VJ10'>M50VJ10</a></li>
<li><a href='../whatsminer/M5X/#M50VJ20'>M50VJ20</a></li>
<li><a href='../whatsminer/M5X/#M50VJ30'>M50VJ30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M5X/#M50S'>M50S</a></summary>
<ul>
<li><a href='../whatsminer/M5X/#M50SVJ10'>M50SVJ10</a></li>
<li><a href='../whatsminer/M5X/#M50SVJ20'>M50SVJ20</a></li>
<li><a href='../whatsminer/M5X/#M50SVJ30'>M50SVJ30</a></li>
<li><a href='../whatsminer/M5X/#M50SVH10'>M50SVH10</a></li>
<li><a href='../whatsminer/M5X/#M50SVH20'>M50SVH20</a></li>
<li><a href='../whatsminer/M5X/#M50SVH30'>M50SVH30</a></li>
<li><a href='../whatsminer/M5X/#M50SVH40'>M50SVH40</a></li>
<li><a href='../whatsminer/M5X/#M50SVH50'>M50SVH50</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M5X/#M50S_1'>M50S+</a></summary>
<ul>
<li><a href='../whatsminer/M5X/#M50S_1VH30'>M50S+VH30</a></li>
<li><a href='../whatsminer/M5X/#M50S_1VH40'>M50S+VH40</a></li>
<li><a href='../whatsminer/M5X/#M50S_1VJ30'>M50S+VJ30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M5X/#M53'>M53</a></summary>
<ul>
<li><a href='../whatsminer/M5X/#M53VH30'>M53VH30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M5X/#M53S'>M53S</a></summary>
<ul>
<li><a href='../whatsminer/M5X/#M53SVH30'>M53SVH30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M5X/#M53S_1'>M53S+</a></summary>
<ul>
<li><a href='../whatsminer/M5X/#M53S_1VJ30'>M53S+VJ30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M5X/#M56'>M56</a></summary>
<ul>
<li><a href='../whatsminer/M5X/#M56VH30'>M56VH30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M5X/#M56S'>M56S</a></summary>
<ul>
<li><a href='../whatsminer/M5X/#M56SVH30'>M56SVH30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M5X/#M56S_1'>M56S+</a></summary>
<ul>
<li><a href='../whatsminer/M5X/#M56S_1VJ30'>M56S+VJ30</a></li>
</ul>
</details>
<details>
<summary><a href='../whatsminer/M5X/#M59'>M59</a></summary>
<ul>
<li><a href='../whatsminer/M5X/#M59VH30'>M59VH30</a></li>
</ul>
</details>
</ul>
</details>
</ul>
</details>
<details>
<summary>Stock Firmware Antminers:</summary>
<ul>
<details>
<summary>X19 Series:</summary>
<ul>
<li><a href="../antminer/X19/#s19">S19</a></li>
<li><a href="../antminer/X19/#s19l">S19L</a></li>
<li><a href="../antminer/X19/#s19-pro">S19 Pro</a></li>
<li><a href="../antminer/X19/#s19a">S19a</a></li>
<li><a href="../antminer/X19/#s19j">S19j</a></li>
<li><a href="../antminer/X19/#s19j-pro">S19j Pro</a></li>
<li><a href="../antminer/X19/#s19-xp">S19 XP</a></li>
<li><a href="../antminer/X19/#t19">T19</a></li>
</ul>
</details>
<details>
<summary>X17 Series:</summary>
<ul>
<li><a href="../antminer/X17/#s17">S17</a></li>
<li><a href="../antminer/X17/#s17_1">S17+</a></li>
<li><a href="../antminer/X17/#s17-pro">S17 Pro</a></li>
<li><a href="../antminer/X17/#s17e">S17e</a></li>
<li><a href="../antminer/X17/#t17">T17</a></li>
<li><a href="../antminer/X17/#t17_1">T17+</a></li>
<li><a href="../antminer/X17/#t17e">T17e</a></li>
</ul>
</details>
<details>
<summary>X15 Series:</summary>
<ul>
<li><a href="../antminer/X15/#z15">Z15</a></li>
</ul>
</details>
<details>
<summary>X9 Series:</summary>
<ul>
<li><a href="../antminer/X9/#s9">S9</a></li>
<li><a href="../antminer/X9/#s9i">S9i</a></li>
<li><a href="../antminer/X9/#t9">T9</a></li>
<li><a href="../antminer/X9/#e9-pro">E9 Pro</a></li>
</ul>
</details>
<details>
<summary>X7 Series:</summary>
<ul>
<li><a href="../antminer/X7/#l7">L7</a></li>
</ul>
</details>
<details>
<summary>X5 Series:</summary>
<ul>
<li><a href="../antminer/X5/#dr5">DR5</a></li>
</ul>
</details>
<details>
<summary>X3 Series:</summary>
<ul>
<li><a href="../antminer/X3/#hs3">HS3</a></li>
</ul>
<ul>
<li><a href="../whatsminer/M5X#m50-ve30">M50 VE30</a></li>
<li><a href="../whatsminer/M5X#m50-vg30">M50 VG30</a></li>
<li><a href="../whatsminer/M5X#m50-vh10">M50 VH10</a></li>
<li><a href="../whatsminer/M5X#m50-vh20">M50 VH20</a></li>
<li><a href="../whatsminer/M5X#m50-vh30">M50 VH30</a></li>
<li><a href="../whatsminer/M5X#m50-vh40">M50 VH40</a></li>
<li><a href="../whatsminer/M5X#m50-vh50">M50 VH50</a></li>
<li><a href="../whatsminer/M5X#m50-vh60">M50 VH60</a></li>
<li><a href="../whatsminer/M5X#m50-vh70">M50 VH70</a></li>
<li><a href="../whatsminer/M5X#m50-vh80">M50 VH80</a></li>
<li><a href="../whatsminer/M5X#m50-vj10">M50 VJ10</a></li>
<li><a href="../whatsminer/M5X#m50-vj20">M50 VJ20</a></li>
<li><a href="../whatsminer/M5X#m50-vj30">M50 VJ30</a></li>
<li><a href="../whatsminer/M5X#m50s-vj10">M50S VJ10</a></li>
<li><a href="../whatsminer/M5X#m50s-vj20">M50S VJ20</a></li>
<li><a href="../whatsminer/M5X#m50s-vj30">M50S VJ30</a></li>
<li><a href="../whatsminer/M5X#m50s-vh10">M50S VH10</a></li>
<li><a href="../whatsminer/M5X#m50s-vh20">M50S VH20</a></li>
<li><a href="../whatsminer/M5X#m50s-vh30">M50S VH30</a></li>
<li><a href="../whatsminer/M5X#m50s-vh40">M50S VH40</a></li>
<li><a href="../whatsminer/M5X#m50s-vh50">M50S VH50</a></li>
<li><a href="../whatsminer/M5X#m50s_1-vh30">M50S+ VH30</a></li>
<li><a href="../whatsminer/M5X#m50s_1-vh40">M50S+ VH40</a></li>
<li><a href="../whatsminer/M5X#m50s_1-vj30">M50S+ VJ30</a></li>
<li><a href="../whatsminer/M5X#m50s_1-vk20">M50S+ VK20</a></li>
<li><a href="../whatsminer/M5X#m50s_1_1-vk10">M50S++ VK10</a></li>
<li><a href="../whatsminer/M5X#m50s_1_1-vk20">M50S++ VK20</a></li>
<li><a href="../whatsminer/M5X#m50s_1_1-vk30">M50S++ VK30</a></li>
<li><a href="../whatsminer/M5X#m53-vh30">M53 VH30</a></li>
<li><a href="../whatsminer/M5X#m53s-vh30">M53S VH30</a></li>
<li><a href="../whatsminer/M5X#m53s_1-vj30">M53S+ VJ30</a></li>
<li><a href="../whatsminer/M5X#m56-vh30">M56 VH30</a></li>
<li><a href="../whatsminer/M5X#m56s-vh30">M56S VH30</a></li>
<li><a href="../whatsminer/M5X#m56s_1-vj30">M56S+ VJ30</a></li>
<li><a href="../whatsminer/M5X#m59-vh30">M59 VH30</a></li>
</ul>
</details>
</ul>
</details>
@@ -492,75 +299,170 @@ details {
<summary>Stock Firmware Avalonminers:</summary>
<ul>
<details>
<summary>A7X Series:</summary>
<ul>
<li><a href="../avalonminer/A7X/#a721">A721</a></li>
<li><a href="../avalonminer/A7X/#a741">A741</a></li>
<li><a href="../avalonminer/A7X/#a761">A761</a></li>
</ul>
<summary>A7X Series:</summary>
<ul>
<li><a href="../avalonminer/A7X#avalon-721">Avalon 721</a></li>
<li><a href="../avalonminer/A7X#avalon-741">Avalon 741</a></li>
<li><a href="../avalonminer/A7X#avalon-761">Avalon 761</a></li>
</ul>
</details>
<details>
<summary>A8X Series:</summary>
<ul>
<li><a href="../avalonminer/A8X/#a821">A821</a></li>
<li><a href="../avalonminer/A8X/#a841">A841</a></li>
<li><a href="../avalonminer/A8X/#a851">A851</a></li>
</ul>
<summary>A8X Series:</summary>
<ul>
<li><a href="../avalonminer/A8X#avalon-821">Avalon 821</a></li>
<li><a href="../avalonminer/A8X#avalon-841">Avalon 841</a></li>
<li><a href="../avalonminer/A8X#avalon-851">Avalon 851</a></li>
</ul>
</details>
<details>
<summary>A9X Series:</summary>
<ul>
<li><a href="../avalonminer/A9X/#a921">A921</a></li>
</ul>
<summary>A9X Series:</summary>
<ul>
<li><a href="../avalonminer/A9X#avalon-921">Avalon 921</a></li>
</ul>
</details>
<details>
<summary>A10X Series:</summary>
<ul>
<li><a href="../avalonminer/A10X/#a1026">A1026</a></li>
<li><a href="../avalonminer/A10X/#a1047">A1047</a></li>
<li><a href="../avalonminer/A10X/#a1066">A1066</a></li>
</ul>
<summary>A10X Series:</summary>
<ul>
<li><a href="../avalonminer/A10X#avalon-1026">Avalon 1026</a></li>
<li><a href="../avalonminer/A10X#avalon-1047">Avalon 1047</a></li>
<li><a href="../avalonminer/A10X#avalon-1066">Avalon 1066</a></li>
</ul>
</details>
<details>
<summary>A11X Series:</summary>
<ul>
<li><a href="../avalonminer/A11X#avalon-1166-pro">Avalon 1166 Pro</a></li>
</ul>
</details>
<details>
<summary>A12X Series:</summary>
<ul>
<li><a href="../avalonminer/A12X#avalon-1246">Avalon 1246</a></li>
</ul>
</details>
</ul>
</details>
<details>
<summary>Stock Firmware Innosilicon Miners:</summary>
<summary>Stock Firmware Innosilicons:</summary>
<ul>
<details>
<summary>T3X Series:</summary>
<ul>
<li><a href="../innosilicon/T3X/#t3h">T3H+</a></li>
</ul>
<summary>T3X Series:</summary>
<ul>
<li><a href="../innosilicon/T3X#t3h_1">T3H+</a></li>
</ul>
</details>
<details>
<summary>A10X Series:</summary>
<ul>
<li><a href="../innosilicon/A10X/#a10x">A10X</a></li>
</ul>
<summary>A10X Series:</summary>
<ul>
<li><a href="../innosilicon/A10X#a10x">A10X</a></li>
</ul>
</details>
</ul>
</details>
<details>
<summary>Stock Firmware BFGMinerGoldshell Miners:</summary>
<summary>Stock Firmware Goldshells:</summary>
<ul>
<details>
<summary>CKX Series:</summary>
<ul>
<li><a href="../goldshell/CKX/#ck5">CK5</a></li>
</ul>
<summary>X5 Series:</summary>
<ul>
<li><a href="../goldshell/X5#ck5">CK5</a></li>
<li><a href="../goldshell/X5#hs5">HS5</a></li>
<li><a href="../goldshell/X5#kd5">KD5</a></li>
</ul>
</details>
<details>
<summary>HSX Series:</summary>
<ul>
<li><a href="../goldshell/HSX/#hs5">HS5</a></li>
</ul>
</details>
<details>
<summary>KDX Series:</summary>
<ul>
<li><a href="../goldshell/KDX/#kd5">KD5</a></li>
<li><a href="../goldshell/KDX/#kd-max">KD Max</a></li>
</ul>
<summary>XMax Series:</summary>
<ul>
<li><a href="../goldshell/XMax#kd-max">KD Max</a></li>
</ul>
</details>
</ul>
</details>
<details>
<summary>BOS+ Firmware Miners:</summary>
<ul>
<details>
<summary>X9 Series:</summary>
<ul>
<li><a href="../antminer/X9#s9-bos">S9 (BOS)</a></li>
</ul>
</details>
<details>
<summary>X17 Series:</summary>
<ul>
<li><a href="../antminer/X17#s17-bos">S17 (BOS)</a></li>
<li><a href="../antminer/X17#s17_1-bos">S17+ (BOS)</a></li>
<li><a href="../antminer/X17#s17-pro-bos">S17 Pro (BOS)</a></li>
<li><a href="../antminer/X17#s17e-bos">S17e (BOS)</a></li>
<li><a href="../antminer/X17#t17-bos">T17 (BOS)</a></li>
<li><a href="../antminer/X17#t17_1-bos">T17+ (BOS)</a></li>
<li><a href="../antminer/X17#t17e-bos">T17e (BOS)</a></li>
</ul>
</details>
<details>
<summary>X19 Series:</summary>
<ul>
<li><a href="../antminer/X19#s19-bos">S19 (BOS)</a></li>
<li><a href="../antminer/X19#s19-pro-bos">S19 Pro (BOS)</a></li>
<li><a href="../antminer/X19#s19j-bos">S19j (BOS)</a></li>
<li><a href="../antminer/X19#s19j-no-pic-bos">S19j No PIC (BOS)</a></li>
<li><a href="../antminer/X19#s19j-pro-bos">S19j Pro (BOS)</a></li>
<li><a href="../antminer/X19#s19j-pro-bos">S19j Pro (BOS)</a></li>
<li><a href="../antminer/X19#t19-bos">T19 (BOS)</a></li>
</ul>
</details>
</ul>
</details>
<details>
<summary>Vnish Firmware Miners:</summary>
<ul>
<details>
<summary>X3 Series:</summary>
<ul>
<li><a href="../antminer/X3#l3_1-vnish">L3+ (VNish)</a></li>
</ul>
</details>
<details>
<summary>X17 Series:</summary>
<ul>
<li><a href="../antminer/X17#s17_1-vnish">S17+ (VNish)</a></li>
<li><a href="../antminer/X17#s17-pro-vnish">S17 Pro (VNish)</a></li>
</ul>
</details>
<details>
<summary>X19 Series:</summary>
<ul>
<li><a href="../antminer/X19#s19-vnish">S19 (VNish)</a></li>
<li><a href="../antminer/X19#s19-no-pic-vnish">S19 No PIC (VNish)</a></li>
<li><a href="../antminer/X19#s19-pro-vnish">S19 Pro (VNish)</a></li>
<li><a href="../antminer/X19#s19j-vnish">S19j (VNish)</a></li>
<li><a href="../antminer/X19#s19j-pro-vnish">S19j Pro (VNish)</a></li>
<li><a href="../antminer/X19#s19a-vnish">S19a (VNish)</a></li>
<li><a href="../antminer/X19#s19a-pro-vnish">S19a Pro (VNish)</a></li>
<li><a href="../antminer/X19#t19-vnish">T19 (VNish)</a></li>
</ul>
</details>
</ul>
</details>
<details>
<summary>HiveOS Firmware Miners:</summary>
<ul>
<details>
<summary>X9 Series:</summary>
<ul>
<li><a href="../antminer/X9#t9-hiveon">T9 (Hiveon)</a></li>
</ul>
</details>
</ul>
</details>
<details>
<summary>LuxOS Firmware Miners:</summary>
<ul>
<details>
<summary>X9 Series:</summary>
<ul>
<li><a href="../antminer/X9#s9-luxos">S9 (LuxOS)</a></li>
</ul>
</details>
</ul>
</details>

View File

@@ -1,90 +1,94 @@
# pyasic
## M2X Models
## M20V10
::: pyasic.miners.btc.whatsminer.btminer.M2X.M20.BTMinerM20V10
## M20 V10
::: pyasic.miners.whatsminer.btminer.M2X.M20.BTMinerM20V10
handler: python
options:
show_root_heading: false
heading_level: 4
## M20SV10
::: pyasic.miners.btc.whatsminer.btminer.M2X.M20S.BTMinerM20SV10
## M20S V10
::: pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20SV10
handler: python
options:
show_root_heading: false
heading_level: 4
## M20SV20
::: pyasic.miners.btc.whatsminer.btminer.M2X.M20S.BTMinerM20SV20
## M20S V20
::: pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20SV20
handler: python
options:
show_root_heading: false
heading_level: 4
## M20SV30
::: pyasic.miners.btc.whatsminer.btminer.M2X.M20S.BTMinerM20SV30
## M20S V30
::: pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20SV30
handler: python
options:
show_root_heading: false
heading_level: 4
## M20S+V30
::: pyasic.miners.btc.whatsminer.btminer.M2X.M20S_Plus.BTMinerM20SPlusV30
## M20P V10
::: pyasic.miners.whatsminer.btminer.M2X.M20P.BTMinerM20PV10
handler: python
options:
show_root_heading: false
heading_level: 4
## M21V10
::: pyasic.miners.btc.whatsminer.btminer.M2X.M21.BTMinerM21V10
## M20P V30
::: pyasic.miners.whatsminer.btminer.M2X.M20P.BTMinerM20PV30
handler: python
options:
show_root_heading: false
heading_level: 4
## M21SV20
::: pyasic.miners.btc.whatsminer.btminer.M2X.M21S.BTMinerM21SV20
## M20S+ V30
::: pyasic.miners.whatsminer.btminer.M2X.M20S_Plus.BTMinerM20SPlusV30
handler: python
options:
show_root_heading: false
heading_level: 4
## M21SV60
::: pyasic.miners.btc.whatsminer.btminer.M2X.M21S.BTMinerM21SV60
## M21 V10
::: pyasic.miners.whatsminer.btminer.M2X.M21.BTMinerM21V10
handler: python
options:
show_root_heading: false
heading_level: 4
## M21SV70
::: pyasic.miners.btc.whatsminer.btminer.M2X.M21S.BTMinerM21SV70
## M21S V20
::: pyasic.miners.whatsminer.btminer.M2X.M21S.BTMinerM21SV20
handler: python
options:
show_root_heading: false
heading_level: 4
## M21S+V20
::: pyasic.miners.btc.whatsminer.btminer.M2X.M21S_Plus.BTMinerM21SPlusV20
## M21S V60
::: pyasic.miners.whatsminer.btminer.M2X.M21S.BTMinerM21SV60
handler: python
options:
show_root_heading: false
heading_level: 4
## M29V10
::: pyasic.miners.btc.whatsminer.btminer.M2X.M29.BTMinerM29V10
## M21S V70
::: pyasic.miners.whatsminer.btminer.M2X.M21S.BTMinerM21SV70
handler: python
options:
show_root_heading: false
heading_level: 4
## M21S+ V20
::: pyasic.miners.whatsminer.btminer.M2X.M21S_Plus.BTMinerM21SPlusV20
handler: python
options:
show_root_heading: false
heading_level: 4
## M29 V10
::: pyasic.miners.whatsminer.btminer.M2X.M29.BTMinerM29V10
handler: python
options:
show_root_heading: false
heading_level: 4

File diff suppressed because it is too large Load Diff

View File

@@ -1,242 +1,248 @@
# pyasic
## M5X Models
## M50VG30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50.BTMinerM50VG30
## M50 VE30
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VE30
handler: python
options:
show_root_heading: false
heading_level: 4
## M50VH10
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50.BTMinerM50VH10
## M50 VG30
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VG30
handler: python
options:
show_root_heading: false
heading_level: 4
## M50VH20
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50.BTMinerM50VH20
## M50 VH10
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH10
handler: python
options:
show_root_heading: false
heading_level: 4
## M50VH30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50.BTMinerM50VH30
## M50 VH20
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH20
handler: python
options:
show_root_heading: false
heading_level: 4
## M50VH40
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50.BTMinerM50VH40
## M50 VH30
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH30
handler: python
options:
show_root_heading: false
heading_level: 4
## M50VH50
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50.BTMinerM50VH50
## M50 VH40
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH40
handler: python
options:
show_root_heading: false
heading_level: 4
## M50VH60
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50.BTMinerM50VH60
## M50 VH50
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH50
handler: python
options:
show_root_heading: false
heading_level: 4
## M50VH70
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50.BTMinerM50VH70
## M50 VH60
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH60
handler: python
options:
show_root_heading: false
heading_level: 4
## M50VH80
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50.BTMinerM50VH80
## M50 VH70
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH70
handler: python
options:
show_root_heading: false
heading_level: 4
## M50VJ10
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50.BTMinerM50VJ10
## M50 VH80
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VH80
handler: python
options:
show_root_heading: false
heading_level: 4
## M50VJ20
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50.BTMinerM50VJ20
## M50 VJ10
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VJ10
handler: python
options:
show_root_heading: false
heading_level: 4
## M50VJ30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50.BTMinerM50VJ30
## M50 VJ20
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VJ20
handler: python
options:
show_root_heading: false
heading_level: 4
## M50SVJ10
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ10
## M50 VJ30
::: pyasic.miners.whatsminer.btminer.M5X.M50.BTMinerM50VJ30
handler: python
options:
show_root_heading: false
heading_level: 4
## M50SVJ20
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ20
## M50S VJ10
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ10
handler: python
options:
show_root_heading: false
heading_level: 4
## M50SVJ30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ30
## M50S VJ20
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ20
handler: python
options:
show_root_heading: false
heading_level: 4
## M50SVH10
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50S.BTMinerM50SVH10
## M50S VJ30
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVJ30
handler: python
options:
show_root_heading: false
heading_level: 4
## M50SVH20
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50S.BTMinerM50SVH20
## M50S VH10
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH10
handler: python
options:
show_root_heading: false
heading_level: 4
## M50SVH30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50S.BTMinerM50SVH30
## M50S VH20
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH20
handler: python
options:
show_root_heading: false
heading_level: 4
## M50SVH40
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50S.BTMinerM50SVH40
## M50S VH30
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH30
handler: python
options:
show_root_heading: false
heading_level: 4
## M50SVH50
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50S.BTMinerM50SVH50
## M50S VH40
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH40
handler: python
options:
show_root_heading: false
heading_level: 4
## M50S+VH30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVH30
## M50S VH50
::: pyasic.miners.whatsminer.btminer.M5X.M50S.BTMinerM50SVH50
handler: python
options:
show_root_heading: false
heading_level: 4
## M50S+VH40
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVH40
## M50S+ VH30
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVH30
handler: python
options:
show_root_heading: false
heading_level: 4
## M50S+VJ30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVJ30
## M50S+ VH40
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVH40
handler: python
options:
show_root_heading: false
heading_level: 4
## M53VH30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M53.BTMinerM53VH30
## M50S+ VJ30
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVJ30
handler: python
options:
show_root_heading: false
heading_level: 4
## M53SVH30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M53S.BTMinerM53SVH30
## M50S+ VK20
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus.BTMinerM50SPlusVK20
handler: python
options:
show_root_heading: false
heading_level: 4
## M53S+VJ30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M53S_Plus.BTMinerM53SPlusVJ30
## M50S++ VK10
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK10
handler: python
options:
show_root_heading: false
heading_level: 4
## M56VH30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M56.BTMinerM56VH30
## M50S++ VK20
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK20
handler: python
options:
show_root_heading: false
heading_level: 4
## M56SVH30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M56S.BTMinerM56SVH30
## M50S++ VK30
::: pyasic.miners.whatsminer.btminer.M5X.M50S_Plus_Plus.BTMinerM50SPlusPlusVK30
handler: python
options:
show_root_heading: false
heading_level: 4
## M56S+VJ30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M56S_Plus.BTMinerM56SPlusVJ30
## M53 VH30
::: pyasic.miners.whatsminer.btminer.M5X.M53.BTMinerM53VH30
handler: python
options:
show_root_heading: false
heading_level: 4
## M59VH30
::: pyasic.miners.btc.whatsminer.btminer.M5X.M59.BTMinerM59VH30
## M53S VH30
::: pyasic.miners.whatsminer.btminer.M5X.M53S.BTMinerM53SVH30
handler: python
options:
show_root_heading: false
heading_level: 4
## M53S+ VJ30
::: pyasic.miners.whatsminer.btminer.M5X.M53S_Plus.BTMinerM53SPlusVJ30
handler: python
options:
show_root_heading: false
heading_level: 4
## M56 VH30
::: pyasic.miners.whatsminer.btminer.M5X.M56.BTMinerM56VH30
handler: python
options:
show_root_heading: false
heading_level: 4
## M56S VH30
::: pyasic.miners.whatsminer.btminer.M5X.M56S.BTMinerM56SVH30
handler: python
options:
show_root_heading: false
heading_level: 4
## M56S+ VJ30
::: pyasic.miners.whatsminer.btminer.M5X.M56S_Plus.BTMinerM56SPlusVJ30
handler: python
options:
show_root_heading: false
heading_level: 4
## M59 VH30
::: pyasic.miners.whatsminer.btminer.M5X.M59.BTMinerM59VH30
handler: python
options:
show_root_heading: false
heading_level: 4

View File

@@ -1,12 +0,0 @@
# pyasic
## Miner Network Range
[`MinerNetworkRange`][pyasic.network.net_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

View File

@@ -1,18 +1,22 @@
# pyasic
## KDX Models
## settings
## KD5
::: pyasic.miners.kda.goldshell.bfgminer.KDX.KD5.BFGMinerKD5
::: pyasic.settings
handler: python
options:
show_root_heading: false
heading_level: 4
## KD Max
::: pyasic.miners.kda.goldshell.bfgminer.KDX.KDMax.BFGMinerKDMax
### get
::: pyasic.settings.get
handler: python
options:
show_root_heading: false
heading_level: 4
### update
::: pyasic.settings.update
handler: python
options:
show_root_heading: false

View File

@@ -20,6 +20,7 @@ nav:
- BOSMiner: "API/bosminer.md"
- BTMiner: "API/btminer.md"
- CGMiner: "API/cgminer.md"
- LUXMiner: "API/luxminer.md"
- Unknown: "API/unknown.md"
- Backends:
- BMMiner: "miners/backends/bmminer.md"
@@ -27,6 +28,8 @@ nav:
- BFGMiner: "miners/backends/bfgminer.md"
- BTMiner: "miners/backends/btminer.md"
- CGMiner: "miners/backends/cgminer.md"
- LUXMiner: "miners/backends/luxminer.md"
- VNish: "miners/backends/vnish.md"
- Hiveon: "miners/backends/hiveon.md"
- Classes:
- Antminer X3: "miners/antminer/X3.md"
@@ -40,16 +43,18 @@ nav:
- Avalon 8X: "miners/avalonminer/A8X.md"
- Avalon 9X: "miners/avalonminer/A9X.md"
- Avalon 10X: "miners/avalonminer/A10X.md"
- Avalon 11X: "miners/avalonminer/A11X.md"
- Avalon 12X: "miners/avalonminer/A12X.md"
- Whatsminer M2X: "miners/whatsminer/M2X.md"
- Whatsminer M3X: "miners/whatsminer/M3X.md"
- Whatsminer M5X: "miners/whatsminer/M5X.md"
- Innosilicon T3X: "miners/innosilicon/T3X.md"
- Innosilicon A10X: "miners/innosilicon/A10X.md"
- Goldshell CKX: "miners/goldshell/CKX.md"
- Goldshell HSX: "miners/goldshell/HSX.md"
- Goldshell KDX: "miners/goldshell/KDX.md"
- Goldshell X5: "miners/goldshell/X5.md"
- Goldshell XMax: "miners/goldshell/XMax.md"
- Base Miner: "miners/base_miner.md"
- Settings:
- Settings: "settings/settings.md"
plugins:
- mkdocstrings

View File

@@ -32,6 +32,8 @@ class BaseMinerAPI:
# ip address of the miner
self.ip = ipaddress.ip_address(ip)
self.pwd = "admin"
def __new__(cls, *args, **kwargs):
if cls is BaseMinerAPI:
raise TypeError(f"Only children of '{cls.__name__}' may be instantiated")
@@ -73,18 +75,23 @@ class BaseMinerAPI:
# send the command
data = await self._send_bytes(json.dumps(cmd).encode("utf-8"))
if data == b"Socket connect failed: Connection refused\n":
if not ignore_errors:
raise APIError(data.decode("utf-8"))
return {}
data = self._load_api_data(data)
# check for if the user wants to allow errors to return
if not ignore_errors:
# validate the command succeeded
validation = self._validate_command_output(data)
if not validation[0]:
if allow_warning:
logging.warning(
f"{self.ip}: API Command Error: {command}: {validation[1]}"
)
validation = self._validate_command_output(data)
if not validation[0]:
if not ignore_errors:
# validate the command succeeded
raise APIError(validation[1])
if allow_warning:
logging.warning(
f"{self.ip}: API Command Error: {command}: {validation[1]}"
)
logging.debug(f"{self} - (Send Command) - Received data.")
return data
@@ -111,16 +118,29 @@ class BaseMinerAPI:
data = await self.send_command(command, allow_warning=allow_warning)
except APIError as e:
# try to identify the error
if ":" in e.message:
err_command = e.message.split(":")[0]
if err_command in commands:
commands.remove(err_command)
continue
if e.message is not None:
if ":" in e.message:
err_command = e.message.split(":")[0]
if err_command in commands:
commands.remove(err_command)
continue
return {command: [{}] for command in commands}
logging.debug(f"{self} - (Multicommand) - Received data")
data["multicommand"] = True
return data
async def _handle_multicommand(self, command: str, allow_warning: bool = True):
try:
data = await self.send_command(command, allow_warning=allow_warning)
if not "+" in command:
return {command: [data]}
return data
except APIError:
if "+" in command:
return {command: [{}] for command in command.split("+")}
return {command: [{}]}
@property
def commands(self) -> list:
return self.get_commands()
@@ -164,7 +184,11 @@ If you are sure you want to use this command please use API.send_command("{comma
)
return return_commands
async def _send_bytes(self, data: bytes, timeout: int = 100) -> bytes:
async def _send_bytes(
self,
data: bytes,
timeout: int = 100,
) -> bytes:
logging.debug(f"{self} - ([Hidden] Send Bytes) - Sending")
try:
# get reader and writer streams
@@ -182,14 +206,19 @@ If you are sure you want to use this command please use API.send_command("{comma
writer.write(data)
logging.debug(f"{self} - ([Hidden] Send Bytes) - Draining")
await writer.drain()
ret_data = await asyncio.wait_for(reader.read(4096), timeout=timeout)
try:
# TO address a situation where a whatsminer has an unknown PW -AND-
# Fix for stupid whatsminer bug, reboot/restart seem to not load properly in the loop
# have to receive, save the data, check if there is more data by reading with a short timeout
# append that data if there is more, and then onto the main loop.
ret_data += await asyncio.wait_for(reader.read(1), timeout=1)
except asyncio.TimeoutError:
return ret_data
# the password timeout might need to be longer than 1, but it seems to work for now.
ret_data = await asyncio.wait_for(reader.read(1), timeout=1)
except (asyncio.TimeoutError):
return b"{}"
try:
ret_data += await asyncio.wait_for(reader.read(4096), timeout=timeout)
except (ConnectionAbortedError):
return b"{}"
# loop to receive all the data
logging.debug(f"{self} - ([Hidden] Send Bytes) - Receiving")
@@ -228,13 +257,22 @@ If you are sure you want to use this command please use API.send_command("{comma
# this is an error
return False, f"{key}: " + data[key][0]["STATUS"][0]["Msg"]
elif "id" not in data.keys():
if isinstance(data["STATUS"], list):
if data["STATUS"][0].get("STATUS", None) in ["S", "I"]:
return True, None
else:
return False, data["STATUS"][0]["Msg"]
if data["STATUS"] not in ["S", "I"]:
return False, data["Msg"]
else:
# make sure the command succeeded
if type(data["STATUS"]) == str:
if isinstance(data["STATUS"], str):
if data["STATUS"] in ["RESTART"]:
return True, None
elif isinstance(data["STATUS"], dict):
if data["STATUS"].get("STATUS") in ["S", "I"]:
return True, None
elif data["STATUS"][0]["STATUS"] not in ("S", "I"):
# this is an error
if data["STATUS"][0]["STATUS"] not in ("S", "I"):

View File

@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
import asyncio
import logging
from pyasic.API import APIError, BaseMinerAPI
@@ -56,19 +56,19 @@ class BFGMinerAPI(BaseMinerAPI):
return data
async def _x19_multicommand(self, *commands) -> dict:
data = None
try:
data = {}
# send all commands individually
for cmd in commands:
data[cmd] = []
data[cmd].append(await self.send_command(cmd, allow_warning=True))
except APIError:
pass
except Exception as e:
logging.warning(
f"{self} - ([Hidden] X19 Multicommand) - API Command Error {e}"
tasks = []
# send all commands individually
for cmd in commands:
tasks.append(
asyncio.create_task(self._handle_multicommand(cmd, allow_warning=True))
)
all_data = await asyncio.gather(*tasks)
data = {}
for item in all_data:
data.update(item)
return data
async def version(self) -> dict:

View File

@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
import asyncio
import logging
from pyasic.API import APIError, BaseMinerAPI
@@ -57,21 +58,19 @@ class BMMinerAPI(BaseMinerAPI):
return data
async def _x19_multicommand(self, *commands, allow_warning: bool = True) -> dict:
data = None
try:
data = {}
# send all commands individually
for cmd in commands:
data[cmd] = []
data[cmd].append(
await self.send_command(cmd, allow_warning=allow_warning)
)
except APIError:
pass
except Exception as e:
logging.warning(
f"{self} - ([Hidden] X19 Multicommand) - API Command Error {e}"
tasks = []
# send all commands individually
for cmd in commands:
tasks.append(
asyncio.create_task(self._handle_multicommand(cmd, allow_warning=True))
)
all_data = await asyncio.gather(*tasks)
data = {}
for item in all_data:
data.update(item)
return data
async def version(self) -> dict:

View File

@@ -22,15 +22,15 @@ import hashlib
import json
import logging
import re
from typing import Union
from typing import Literal, Union
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from passlib.handlers.md5_crypt import md5_crypt
from pyasic import settings
from pyasic.API import BaseMinerAPI
from pyasic.errors import APIError
from pyasic.misc import api_min_version
from pyasic.settings import PyasicSettings
### IMPORTANT ###
# you need to change the password of the miners using the Whatsminer
@@ -40,6 +40,12 @@ from pyasic.settings import PyasicSettings
# you change the password, you can pass that to this class as pwd,
# or add it as the Whatsminer_pwd in the settings.toml file.
PrePowerOnMessage = Union[
Literal["wait for adjust temp"],
Literal["adjust complete"],
Literal["adjust continue"],
]
def _crypt(word: str, salt: str) -> str:
"""Encrypts a word with a salt, using a standard salt format.
@@ -186,7 +192,7 @@ class BTMinerAPI(BaseMinerAPI):
ip: str,
api_ver: str = "0.0.0",
port: int = 4028,
pwd: str = PyasicSettings().global_whatsminer_password,
pwd: str = settings.get("default_whatsminer_password", "admin"),
):
super().__init__(ip, port)
self.pwd = pwd
@@ -203,27 +209,35 @@ class BTMinerAPI(BaseMinerAPI):
# make sure we can actually run each command, otherwise they will fail
commands = self._check_commands(*commands)
# standard multicommand format is "command1+command2"
# commands starting with "get_" aren't supported, but we can fake that
get_commands_data = {}
# commands starting with "get_" and the "status" command aren't supported, but we can fake that
tasks = []
for command in list(commands):
if command.startswith("get_"):
if command.startswith("get_") or command == "status":
commands.remove(command)
# send seperately and append later
try:
get_commands_data[command] = [
await self.send_command(command, allow_warning=allow_warning)
]
except APIError:
get_commands_data[command] = [{}]
tasks.append(
asyncio.create_task(
self._handle_multicommand(command, allow_warning=allow_warning)
)
)
command = "+".join(commands)
try:
main_data = await self.send_command(command, allow_warning=allow_warning)
except APIError:
main_data = {command: [{}] for command in commands}
tasks.append(
asyncio.create_task(
self._handle_multicommand(command, allow_warning=allow_warning)
)
)
all_data = await asyncio.gather(*tasks)
logging.debug(f"{self} - (Multicommand) - Received data")
data = dict(**main_data, **get_commands_data)
data = {}
for item in all_data:
data.update(item)
data["multicommand"] = True
return data
@@ -685,7 +699,7 @@ class BTMinerAPI(BaseMinerAPI):
)
return await self.send_privileged_command("set_power_pct", percent=str(percent))
async def pre_power_on(self, complete: bool, msg: str) -> dict:
async def pre_power_on(self, complete: bool, msg: PrePowerOnMessage) -> dict:
"""Configure or check status of pre power on.
<details>
@@ -705,7 +719,7 @@ class BTMinerAPI(BaseMinerAPI):
</details>
"""
if not msg == "wait for adjust temp" or "adjust complete" or "adjust continue":
if msg not in ("wait for adjust temp", "adjust complete", "adjust continue"):
raise APIError(
"Message is incorrect, please choose one of "
'["wait for adjust temp", '
@@ -721,6 +735,34 @@ class BTMinerAPI(BaseMinerAPI):
)
### ADDED IN V2.0.5 Whatsminer API ###
@api_min_version("2.0.5")
async def set_power_pct_v2(self, percent: int) -> dict:
"""Set the power percentage of the miner based on current power. Used for temporary adjustment. Added in API v2.0.5.
<details>
<summary>Expand</summary>
Set the power percentage of the miner, only works after changing
the password of the miner using the Whatsminer tool.
Parameters:
percent: The power percentage to set.
Returns:
A reply informing of the status of setting the power percentage.
</details>
"""
if not 0 < percent < 100:
raise APIError(
f"Power PCT % is outside of the allowed "
f"range. Please set a % between 0 and "
f"100"
)
return await self.send_privileged_command(
"set_power_pct_v2", percent=str(percent)
)
@api_min_version("2.0.5")
async def set_temp_offset(self, temp_offset: int) -> dict:
"""Set the offset of miner hash board target temperature.

View File

@@ -13,7 +13,7 @@
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
import asyncio
import logging
from pyasic.API import APIError, BaseMinerAPI
@@ -56,19 +56,19 @@ class CGMinerAPI(BaseMinerAPI):
return data
async def _x19_multicommand(self, *commands) -> dict:
data = None
try:
data = {}
# send all commands individually
for cmd in commands:
data[cmd] = []
data[cmd].append(await self.send_command(cmd, allow_warning=True))
except APIError:
pass
except Exception as e:
logging.warning(
f"{self} - ([Hidden] X19 Multicommand) - API Command Error {e}"
tasks = []
# send all commands individually
for cmd in commands:
tasks.append(
asyncio.create_task(self._handle_multicommand(cmd, allow_warning=True))
)
all_data = await asyncio.gather(*tasks)
data = {}
for item in all_data:
data.update(item)
return data
async def version(self) -> dict:

759
pyasic/API/luxminer.py Normal file
View File

@@ -0,0 +1,759 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from typing import Literal
from pyasic.API import BaseMinerAPI
class LUXMinerAPI(BaseMinerAPI):
"""An abstraction of the LUXMiner API.
Each method corresponds to an API command in LUXMiner.
[LUXMiner API documentation](https://docs.firmware.luxor.tech/API/intro)
This class abstracts use of the LUXMiner API, as well as the
methods for sending commands to it. The `self.send_command()`
function handles sending a command to the miner asynchronously, and
as such is the base for many of the functions in this class, which
rely on it to send the command for them.
Parameters:
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, api_ver: str = "0.0.0", port: int = 4028) -> None:
super().__init__(ip, port=port)
self.api_ver = api_ver
async def addgroup(self, name: str, quota: int) -> dict:
"""Add a pool group.
<details>
<summary>Expand</summary>
Parameters:
name: The group name.
quota: The group quota.
Returns:
Confirmation of adding a pool group.
</details>
"""
return await self.send_command("addgroup", parameters=f"{name},{quota}")
async def addpool(
self, url: str, user: str, pwd: str = "", group_id: str = None
) -> dict:
"""Add a pool.
<details>
<summary>Expand</summary>
Parameters:
url: The pool url.
user: The pool username.
pwd: The pool password.
group_id: The group ID to use.
Returns:
Confirmation of adding a pool.
</details>
"""
pool_data = [url, user, pwd]
if group_id is not None:
pool_data.append(group_id)
return await self.send_command("addpool", parameters=",".join(pool_data))
async def asc(self, n: int) -> dict:
"""Get data for ASC device n.
<details>
<summary>Expand</summary>
Parameters:
n: The device to get data for.
Returns:
The data for ASC device n.
</details>
"""
return await self.send_command("asc", parameters=n)
async def asccount(self) -> dict:
"""Get data on the number of ASC devices and their info.
<details>
<summary>Expand</summary>
Returns:
Data on all ASC devices.
</details>
"""
return await self.send_command("asccount")
async def check(self, command: str) -> dict:
"""Check if the command `command` exists in LUXMiner.
<details>
<summary>Expand</summary>
Parameters:
command: The command to check.
Returns:
## Information about a 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)
async def coin(self) -> dict:
"""Get information on the current coin.
<details>
<summary>Expand</summary>
Returns:
## Information about the current coin being mined:
* Hash Method <- the hashing algorithm
* Current Block Time <- blocktime as a float, 0 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
* Network Difficulty: the current network difficulty
</details>
"""
return await self.send_command("coin")
async def config(self) -> dict:
"""Get some basic configuration info.
<details>
<summary>Expand</summary>
Returns:
Miner configuration information.
</details>
"""
return await self.send_command("config")
async def curtail(self, session_id: str) -> dict:
"""Put the miner into sleep mode. Requires a session_id from logon.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
Returns:
A confirmation of putting the miner to sleep.
</details>
"""
return await self.send_command("curtail", parameters=session_id)
async def devdetails(self) -> dict:
"""Get data on all devices with their static details.
<details>
<summary>Expand</summary>
Returns:
Data on all devices with their static details.
</details>
"""
return await self.send_command("devdetails")
async def devs(self) -> dict:
"""Get data on each PGA/ASC with their details.
<details>
<summary>Expand</summary>
Returns:
Data on each PGA/ASC with their details.
</details>
"""
return await self.send_command("devs")
async def disablepool(self, n: int) -> dict:
"""Disable a pool.
<details>
<summary>Expand</summary>
Parameters:
n: Pool to disable.
Returns:
A confirmation of diabling the pool.
</details>
"""
return await self.send_command("disablepool", parameters=n)
async def edevs(self) -> dict:
"""Alias for devs"""
return await self.devs()
async def enablepool(self, n: int) -> dict:
"""Enable pool n.
<details>
<summary>Expand</summary>
Parameters:
n: The pool to enable.
Returns:
A confirmation of enabling pool n.
</details>
"""
return await self.send_command("enablepool", parameters=n)
async def estats(self) -> dict:
"""Alias for stats"""
return await self.stats()
async def fans(self) -> dict:
"""Get fan data.
<details>
<summary>Expand</summary>
Returns:
Data on the fans of the miner.
</details>
"""
return await self.send_command("fans")
async def fanset(self, session_id: str, speed: int, min_fans: int = None) -> dict:
"""Set fan control. Requires a session_id from logon.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
speed: The fan speed to set. Use -1 to set automatically.
min_fans: The minimum number of fans to use. Optional.
Returns:
A confirmation of setting fan control values.
</details>
"""
fanset_data = [str(session_id), str(speed)]
if min_fans is not None:
fanset_data.append(str(min_fans))
return await self.send_command("fanset", parameters=",".join(fanset_data))
async def frequencyget(self, board_n: int, chip_n: int = None) -> dict:
"""Get frequency data for a board and chips.
<details>
<summary>Expand</summary>
Parameters:
board_n: The board number to get frequency info from.
chip_n: The chip number to get frequency info from. Optional.
Returns:
Board and/or chip frequency values.
</details>
"""
frequencyget_data = [str(board_n)]
if chip_n is not None:
frequencyget_data.append(str(chip_n))
return await self.send_command(
"frequencyget", parameters=",".join(frequencyget_data)
)
async def frequencyset(self, session_id: str, board_n: int, freq: int) -> dict:
"""Set frequency. Requires a session_id from logon.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
board_n: The board number to set frequency on.
freq: The frequency to set.
Returns:
A confirmation of setting frequency values.
</details>
"""
return await self.send_command(
"frequencyset", parameters=f"{session_id},{board_n},{freq}"
)
async def frequencystop(self, session_id: str, board_n: int) -> dict:
"""Stop set frequency. Requires a session_id from logon.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
board_n: The board number to set frequency on.
Returns:
A confirmation of stopping frequencyset value.
</details>
"""
return await self.send_command(
"frequencystop", parameters=f"{session_id},{board_n}"
)
async def groupquota(self, group_n: int, quota: int) -> dict:
"""Set a group's quota.
<details>
<summary>Expand</summary>
Parameters:
group_n: The group number to set quota on.
quota: The quota to use.
Returns:
A confirmation of setting quota value.
</details>
"""
return await self.send_command("groupquota", parameters=f"{group_n},{quota}")
async def groups(self) -> dict:
"""Get pool group data.
<details>
<summary>Expand</summary>
Returns:
Data on the pool groups on the miner.
</details>
"""
return await self.send_command("groups")
async def healthchipget(self, board_n: int, chip_n: int = None) -> dict:
"""Get chip health.
<details>
<summary>Expand</summary>
Parameters:
board_n: The board number to get chip health of.
chip_n: The chip number to get chip health of. Optional.
Returns:
Chip health data.
</details>
"""
healthchipget_data = [str(board_n)]
if chip_n is not None:
healthchipget_data.append(str(chip_n))
return await self.send_command(
"healthchipget", parameters=",".join(healthchipget_data)
)
async def healthchipset(
self, session_id: str, board_n: int, chip_n: int = None
) -> dict:
"""Select the next chip to have its health checked. Requires a session_id from logon.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
board_n: The board number to next get chip health of.
chip_n: The chip number to next get chip health of. Optional.
Returns:
Confirmation of selecting the next health check chip.
</details>
"""
healthchipset_data = [session_id, str(board_n)]
if chip_n is not None:
healthchipset_data.append(str(chip_n))
return await self.send_command(
"healthchipset", parameters=",".join(healthchipset_data)
)
async def healthctrl(self) -> dict:
"""Get health check config.
<details>
<summary>Expand</summary>
Returns:
Health check config.
</details>
"""
return await self.send_command("healthctrl")
async def healthctrlset(
self, session_id: str, num_readings: int, amplified_factor: float
) -> dict:
"""Set health control config. Requires a session_id from logon.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
num_readings: The minimum number of readings for evaluation.
amplified_factor: Performance factor of the evaluation.
Returns:
A confirmation of setting health control config.
</details>
"""
return await self.send_command(
"healthctrlset",
parameters=f"{session_id},{num_readings},{amplified_factor}",
)
async def kill(self) -> dict:
"""Forced session kill. Use logoff instead.
<details>
<summary>Expand</summary>
Returns:
A confirmation of killing the active session.
</details>
"""
return await self.send_command("kill")
async def lcd(self) -> dict:
"""Get a general all-in-one status summary of the miner. Always zeros on LUXMiner.
<details>
<summary>Expand</summary>
Returns:
An all-in-one status summary of the miner.
</details>
"""
return await self.send_command("lcd")
async def ledset(
self,
session_id: str,
color: Literal["red"],
state: Literal["on", "off", "blink"],
) -> dict:
"""Set led. Requires a session_id from logon.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
color: The color LED to set. Can be "red".
state: The state to set the LED to. Can be "on", "off", or "blink".
Returns:
A confirmation of setting LED.
</details>
"""
return await self.send_command(
"ledset", parameters=f"{session_id},{color},{state}"
)
async def limits(self) -> dict:
"""Get max and min values of config parameters.
<details>
<summary>Expand</summary>
Returns:
Data on max and min values of config parameters.
</details>
"""
return await self.send_command("limits")
async def logoff(self, session_id: str) -> dict:
"""Log off of a session. Requires a session id from an active session.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
Returns:
Confirmation of logging off a session.
</details>
"""
return await self.send_command("logoff", parameters=session_id)
async def logon(self) -> dict:
"""Get or create a session.
<details>
<summary>Expand</summary>
Returns:
The Session ID to be used.
</details>
"""
return await self.send_command("logon")
async def pools(self) -> dict:
"""Get pool information.
<details>
<summary>Expand</summary>
Returns:
Miner pool information.
</details>
"""
return await self.send_command("pools")
async def power(self) -> dict:
"""Get the estimated power usage in watts.
<details>
<summary>Expand</summary>
Returns:
Estimated power usage in watts.
</details>
"""
return await self.send_command("power")
async def profiles(self) -> dict:
"""Get the available profiles.
<details>
<summary>Expand</summary>
Returns:
Data on available profiles.
</details>
"""
return await self.send_command("profiles")
async def profileset(self, session_id: str, board_n: int, profile: str) -> dict:
"""Set active profile for a board. Requires a session_id from logon.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
board_n: The board to set the profile on.
profile: The profile name to use.
Returns:
A confirmation of setting the profile on board_n.
</details>
"""
return await self.send_command(
"profileset", parameters=f"{session_id},{board_n},{profile}"
)
async def reboot(self, session_id: str, board_n: int, delay_s: int = None) -> dict:
"""Reboot a board. Requires a session_id from logon.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
board_n: The board to reboot.
delay_s: The number of seconds to delay until startup. If it is 0, the board will just stop. Optional.
Returns:
A confirmation of rebooting board_n.
</details>
"""
reboot_data = [session_id, str(board_n)]
if delay_s is not None:
reboot_data.append(str(delay_s))
return await self.send_command("reboot", parameters=",".join(reboot_data))
async def rebootdevice(self, session_id: str) -> dict:
"""Reboot the miner. Requires a session_id from logon.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
Returns:
A confirmation of rebooting the miner.
</details>
"""
return await self.send_command("rebootdevice", parameters=session_id)
async def removegroup(self, group_id: str) -> dict:
"""Remove a pool group.
<details>
<summary>Expand</summary>
Parameters:
group_id: Group id to remove.
Returns:
A confirmation of removing the pool group.
</details>
"""
return await self.send_command("removegroup", parameters=group_id)
async def resetminer(self, session_id: str) -> dict:
"""Restart the mining process. Requires a session_id from logon.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
Returns:
A confirmation of restarting the mining process.
</details>
"""
return await self.send_command("resetminer", parameters=session_id)
async def removepool(self, pool_id: int) -> dict:
"""Remove a pool.
<details>
<summary>Expand</summary>
Parameters:
pool_id: Pool to remove.
Returns:
A confirmation of removing the pool.
</details>
"""
return await self.send_command("removepool", parameters=str(pool_id))
async def session(self) -> dict:
"""Get the current session.
<details>
<summary>Expand</summary>
Returns:
Data on the current session.
</details>
"""
return await self.send_command("session")
async def tempctrlset(self, target: int, hot: int, dangerous: int) -> dict:
"""Set temp control values.
<details>
<summary>Expand</summary>
Parameters:
target: Target temp.
hot: Hot temp.
dangerous: Dangerous temp.
Returns:
A confirmation of setting the temp control config.
</details>
"""
return await self.send_command(
"tempctrlset", parameters=f"{target},{hot},{dangerous}"
)
async def stats(self) -> dict:
"""Get stats of each device/pool with more than 1 getwork.
<details>
<summary>Expand</summary>
Returns:
Stats of each device/pool with more than 1 getwork.
</details>
"""
return await self.send_command("stats")
async def summary(self) -> dict:
"""Get the status summary of the miner.
<details>
<summary>Expand</summary>
Returns:
The status summary of the miner.
</details>
"""
return await self.send_command("summary")
async def switchpool(self, pool_id: int) -> dict:
"""Switch to a pool.
<details>
<summary>Expand</summary>
Parameters:
pool_id: Pool to switch to.
Returns:
A confirmation of switching to the pool.
</details>
"""
return await self.send_command("switchpool", parameters=str(pool_id))
async def tempctrl(self) -> dict:
"""Get temperature control data.
<details>
<summary>Expand</summary>
Returns:
Data about the temp control settings of the miner.
</details>
"""
return await self.send_command("tempctrl")
async def temps(self) -> dict:
"""Get temperature data.
<details>
<summary>Expand</summary>
Returns:
Data on the temps of the miner.
</details>
"""
return await self.send_command("temps")
async def version(self) -> dict:
"""Get miner version info.
<details>
<summary>Expand</summary>
Returns:
Miner version information.
</details>
"""
return await self.send_command("version")
async def voltageget(self, board_n: int) -> dict:
"""Get voltage data for a board.
<details>
<summary>Expand</summary>
Parameters:
board_n: The board number to get voltage info from.
Returns:
Board voltage values.
</details>
"""
return await self.send_command("frequencyget", parameters=str(board_n))
async def voltageset(self, session_id: str, board_n: int, voltage: float) -> dict:
"""Set voltage values.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
board_n: The board to set the voltage on.
voltage: The voltage to use.
Returns:
A confirmation of setting the voltage.
</details>
"""
return await self.send_command(
"voltageset", parameters=f"{session_id},{board_n},{voltage}"
)
async def wakeup(self, session_id: str) -> dict:
"""Take the miner out of sleep mode. Requires a session_id from logon.
<details>
<summary>Expand</summary>
Parameters:
session_id: Session id from the logon command.
Returns:
A confirmation of resuming mining.
</details>
"""
return await self.send_command("wakeup", parameters=session_id)

View File

@@ -13,6 +13,7 @@
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic import settings
from pyasic.API.bmminer import BMMinerAPI
from pyasic.API.bosminer import BOSMinerAPI
from pyasic.API.btminer import BTMinerAPI
@@ -29,10 +30,9 @@ from pyasic.data import (
from pyasic.errors import APIError, APIWarning
from pyasic.miners import get_miner
from pyasic.miners.base import AnyMiner
from pyasic.miners.miner_factory import MinerFactory
from pyasic.miners.miner_factory import MinerFactory, miner_factory
from pyasic.miners.miner_listener import MinerListener
from pyasic.network import MinerNetwork
from pyasic.settings import PyasicSettings
__all__ = [
"BMMinerAPI",
@@ -51,7 +51,8 @@ __all__ = [
"get_miner",
"AnyMiner",
"MinerFactory",
"miner_factory",
"MinerListener",
"MinerNetwork",
"PyasicSettings",
"settings",
]

View File

@@ -215,7 +215,7 @@ class _PoolGroup:
return pools
def as_x17(self, user_suffix: str = None) -> dict:
"""Convert the data in this class to a list usable by an X5 device.
"""Convert the data in this class to a list usable by an X17 device.
Parameters:
user_suffix: The suffix to append to username.
@@ -547,11 +547,11 @@ class MinerConfig:
"""
logging.debug(f"MinerConfig - (As X19) - Generating X19 config")
cfg = {
"pools": self.pool_groups[0].as_x19(user_suffix=user_suffix),
"bitmain-fan-ctrl": False,
"bitmain-fan-pwn": "100",
"freq-level": "100",
"miner-mode": str(self.miner_mode.value),
"freq-level": "100"
"pools": self.pool_groups[0].as_x19(user_suffix=user_suffix),
}
if not self.temp_mode == "auto":
@@ -560,9 +560,6 @@ class MinerConfig:
if self.fan_speed:
cfg["bitmain-fan-pwn"] = str(self.fan_speed)
if self.miner_mode == X19PowerMode.Sleep:
cfg["freq-level"] = "0"
return cfg
def as_x17(self, user_suffix: str = None) -> dict:

View File

@@ -20,7 +20,7 @@ import logging
import time
from dataclasses import asdict, dataclass, field, fields
from datetime import datetime, timezone
from typing import List, Union
from typing import Any, List, Union
from .error_codes import BraiinsOSError, InnosiliconError, WhatsminerError, X19Error
@@ -40,13 +40,28 @@ class HashBoard:
"""
slot: int = 0
hashrate: float = 0.0
temp: int = -1
chip_temp: int = -1
chips: int = 0
expected_chips: int = 0
hashrate: float = None
temp: int = None
chip_temp: int = None
chips: int = None
expected_chips: int = None
missing: bool = True
def get(self, __key: str, default: Any = None):
try:
val = self.__getitem__(__key)
if val is None:
return default
return val
except KeyError:
return default
def __getitem__(self, item: str):
try:
return getattr(self, item)
except AttributeError:
raise KeyError(f"{item}")
@dataclass
class Fan:
@@ -56,7 +71,22 @@ class Fan:
speed: The speed of the fan.
"""
speed: int = -1
speed: int = None
def get(self, __key: str, default: Any = None):
try:
val = self.__getitem__(__key)
if val is None:
return default
return val
except KeyError:
return default
def __getitem__(self, item: str):
try:
return getattr(self, item)
except AttributeError:
raise KeyError(f"{item}")
@dataclass
@@ -66,34 +96,23 @@ class MinerData:
Attributes:
ip: The IP of the miner as a str.
datetime: The time and date this data was generated.
uptime: The uptime of the miner in seconds.
mac: The MAC address of the miner as a str.
model: The model of the miner as a str.
make: The make of the miner as a str.
api_ver: The current api version on the miner as a str.
fw_ver: The current firmware version on the miner as a str.
hostname: The network hostname of the miner as a str.
hashrate: The hashrate of the miner in TH/s as a float.
hashrate: The hashrate of the miner in TH/s as a float. Calculated automatically.
_hashrate: Backup for hashrate found via API instead of hashboards.
nominal_hashrate: The factory nominal hashrate of the miner in TH/s as a float.
left_board_hashrate: The hashrate of the left board of the miner in TH/s as a float.
center_board_hashrate: The hashrate of the center board of the miner in TH/s as a float.
right_board_hashrate: The hashrate of the right board of the miner in TH/s as a float.
hashboards: A list of hashboards on the miner with their statistics.
temperature_avg: The average temperature across the boards. Calculated automatically.
env_temp: The environment temps as a float.
left_board_temp: The temp of the left PCB as an int.
left_board_chip_temp: The temp of the left board chips as an int.
center_board_temp: The temp of the center PCB as an int.
center_board_chip_temp: The temp of the center board chips as an int.
right_board_temp: The temp of the right PCB as an int.
right_board_chip_temp: The temp of the right board chips as an int.
wattage: Current power draw of the miner as an int.
wattage_limit: Power limit of the miner as an int.
fan_1: The speed of the first fan as an int.
fan_2: The speed of the second fan as an int.
fan_3: The speed of the third fan as an int.
fan_4: The speed of the fourth fan as an int.
fans: A list of fans on the miner with their speeds.
fan_psu: The speed of the PSU on the fan if the miner collects it.
left_chips: The number of chips online in the left board as an int.
center_chips: The number of chips online in the left board as an int.
right_chips: The number of chips online in the left board as an int.
total_chips: The total number of chips on all boards. Calculated automatically.
ideal_chips: The ideal number of chips in the miner as an int.
percent_ideal_chips: The percent of total chips out of the ideal count. Calculated automatically.
@@ -106,51 +125,37 @@ class MinerData:
pool_2_url: The second pool url on the miner as a str.
pool_2_user: The second pool user on the miner as a str.
errors: A list of errors on the miner.
fault_light: Whether or not the fault light is on as a boolean.
fault_light: Whether the fault light is on as a boolean.
efficiency: Efficiency of the miner in J/TH (Watts per TH/s). Calculated automatically.
is_mining: Whether the miner is mining.
"""
ip: str
datetime: datetime = None
mac: str = "00:00:00:00:00:00"
model: str = "Unknown"
make: str = "Unknown"
api_ver: str = "Unknown"
fw_ver: str = "Unknown"
hostname: str = "Unknown"
uptime: int = None
mac: str = None
model: str = None
make: str = None
api_ver: str = None
fw_ver: str = None
hostname: str = None
hashrate: float = field(init=False)
_hashrate: float = 0
nominal_hashrate: float = 0
_hashrate: float = None
nominal_hashrate: float = None
hashboards: List[HashBoard] = field(default_factory=list)
ideal_hashboards: int = 1
left_board_hashrate: float = field(init=False)
center_board_hashrate: float = field(init=False)
right_board_hashrate: float = field(init=False)
ideal_hashboards: int = None
temperature_avg: int = field(init=False)
env_temp: float = -1.0
left_board_temp: int = field(init=False)
left_board_chip_temp: int = field(init=False)
center_board_temp: int = field(init=False)
center_board_chip_temp: int = field(init=False)
right_board_temp: int = field(init=False)
right_board_chip_temp: int = field(init=False)
wattage: int = -1
wattage_limit: int = -1
env_temp: float = None
wattage: int = None
wattage_limit: int = None
fans: List[Fan] = field(default_factory=list)
fan_1: int = field(init=False)
fan_2: int = field(init=False)
fan_3: int = field(init=False)
fan_4: int = field(init=False)
fan_psu: int = -1
left_chips: int = field(init=False)
center_chips: int = field(init=False)
right_chips: int = field(init=False)
fan_psu: int = None
total_chips: int = field(init=False)
ideal_chips: int = 1
ideal_chips: int = None
percent_ideal_chips: float = field(init=False)
percent_ideal_hashrate: float = field(init=False)
percent_ideal_wattage: float = field(init=False)
nominal: int = field(init=False)
nominal: bool = field(init=False)
pool_split: str = "0"
pool_1_url: str = "Unknown"
pool_1_user: str = "Unknown"
@@ -161,6 +166,7 @@ class MinerData:
] = field(default_factory=list)
fault_light: Union[bool, None] = None
efficiency: int = field(init=False)
is_mining: bool = True
@classmethod
def fields(cls):
@@ -169,7 +175,16 @@ class MinerData:
def __post_init__(self):
self.datetime = datetime.now(timezone.utc).astimezone()
def __getitem__(self, item):
def get(self, __key: str, default: Any = None):
try:
val = self.__getitem__(__key)
if val is None:
return default
return val
except KeyError:
return default
def __getitem__(self, item: str):
try:
return getattr(self, item)
except AttributeError:
@@ -221,204 +236,37 @@ class MinerData:
@property
def hashrate(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) > 0:
return round(sum(map(lambda x: x.hashrate, self.hashboards)), 2)
hr_data = []
for item in self.hashboards:
if item.hashrate is not None:
hr_data.append(item.hashrate)
if len(hr_data) > 0:
return round(sum(hr_data), 2)
return self._hashrate
@hashrate.setter
def hashrate(self, val):
self._hashrate = val
@property
def fan_1(self): # noqa - Skip PyCharm inspection
if len(self.fans) > 0:
return self.fans[0].speed
@fan_1.setter
def fan_1(self, val):
pass
@property
def fan_2(self): # noqa - Skip PyCharm inspection
if len(self.fans) > 1:
return self.fans[1].speed
@fan_2.setter
def fan_2(self, val):
pass
@property
def fan_3(self): # noqa - Skip PyCharm inspection
if len(self.fans) > 2:
return self.fans[2].speed
@fan_3.setter
def fan_3(self, val):
pass
@property
def fan_4(self): # noqa - Skip PyCharm inspection
if len(self.fans) > 3:
return self.fans[3].speed
@fan_4.setter
def fan_4(self, val):
pass
@property
def total_chips(self): # noqa - Skip PyCharm inspection
return sum([hb.chips for hb in self.hashboards])
if len(self.hashboards) > 0:
chip_data = []
for item in self.hashboards:
if item.chips is not None:
chip_data.append(item.chips)
if len(chip_data) > 0:
return sum(chip_data)
return None
@total_chips.setter
def total_chips(self, val):
pass
@property
def left_chips(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) in [2, 3, 4]:
return self.hashboards[0].chips
return 0
@left_chips.setter
def left_chips(self, val):
pass
@property
def center_chips(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 1:
return self.hashboards[0].chips
if len(self.hashboards) in [2, 3, 4]:
return self.hashboards[1].chips
return 0
@center_chips.setter
def center_chips(self, val):
pass
@property
def right_chips(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 2:
return self.hashboards[1].chips
if len(self.hashboards) == 3:
return self.hashboards[2].chips
if len(self.hashboards) > 3:
return self.hashboards[-1:][0].chips
return 0
@right_chips.setter
def right_chips(self, val):
pass
@property
def left_board_hashrate(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) in [2, 3, 4]:
return self.hashboards[0].hashrate
return 0
@left_board_hashrate.setter
def left_board_hashrate(self, val):
pass
@property
def center_board_hashrate(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 1:
return self.hashboards[0].hashrate
if len(self.hashboards) in [2, 3, 4]:
return self.hashboards[1].hashrate
return 0
@center_board_hashrate.setter
def center_board_hashrate(self, val):
pass
@property
def right_board_hashrate(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 2:
return self.hashboards[1].hashrate
if len(self.hashboards) == 3:
return self.hashboards[2].hashrate
if len(self.hashboards) > 3:
return self.hashboards[-1:][0].hashrate
return 0
@right_board_hashrate.setter
def right_board_hashrate(self, val):
pass
@property
def left_board_temp(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) in [2, 3, 4]:
return self.hashboards[0].temp
return 0
@left_board_temp.setter
def left_board_temp(self, val):
pass
@property
def center_board_temp(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 1:
return self.hashboards[0].temp
if len(self.hashboards) in [2, 3, 4]:
return self.hashboards[1].temp
return 0
@center_board_temp.setter
def center_board_temp(self, val):
pass
@property
def right_board_temp(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 2:
return self.hashboards[1].temp
if len(self.hashboards) == 3:
return self.hashboards[2].temp
if len(self.hashboards) > 3:
return self.hashboards[-1:][0].temp
return 0
@right_board_temp.setter
def right_board_temp(self, val):
pass
@property
def left_board_chip_temp(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) in [2, 3, 4]:
return self.hashboards[0].chip_temp
return 0
@left_board_chip_temp.setter
def left_board_chip_temp(self, val):
pass
@property
def center_board_chip_temp(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 1:
return self.hashboards[0].chip_temp
if len(self.hashboards) in [2, 3, 4]:
return self.hashboards[1].chip_temp
return 0
@center_board_chip_temp.setter
def center_board_chip_temp(self, val):
pass
@property
def right_board_chip_temp(self): # noqa - Skip PyCharm inspection
if len(self.hashboards) == 2:
return self.hashboards[1].chip_temp
if len(self.hashboards) == 3:
return self.hashboards[2].chip_temp
if len(self.hashboards) > 3:
return self.hashboards[-1:][0].chip_temp
return 0
@right_board_chip_temp.setter
def right_board_chip_temp(self, val):
pass
@property
def nominal(self): # noqa - Skip PyCharm inspection
if self.total_chips is None or self.ideal_chips is None:
return None
return self.ideal_chips == self.total_chips
@nominal.setter
@@ -427,6 +275,8 @@ class MinerData:
@property
def percent_ideal_chips(self): # noqa - Skip PyCharm inspection
if self.total_chips is None or self.ideal_chips is None:
return None
if self.total_chips == 0 or self.ideal_chips == 0:
return 0
return round((self.total_chips / self.ideal_chips) * 100)
@@ -437,6 +287,8 @@ class MinerData:
@property
def percent_ideal_hashrate(self): # noqa - Skip PyCharm inspection
if self.hashrate is None or self.nominal_hashrate is None:
return None
if self.hashrate == 0 or self.nominal_hashrate == 0:
return 0
return round((self.hashrate / self.nominal_hashrate) * 100)
@@ -447,6 +299,8 @@ class MinerData:
@property
def percent_ideal_wattage(self): # noqa - Skip PyCharm inspection
if self.wattage_limit is None or self.wattage is None:
return None
if self.wattage_limit == 0 or self.wattage == 0:
return 0
return round((self.wattage / self.wattage_limit) * 100)
@@ -460,11 +314,11 @@ class MinerData:
total_temp = 0
temp_count = 0
for hb in self.hashboards:
if hb.temp and not hb.temp == -1:
if hb.temp is not None:
total_temp += hb.temp
temp_count += 1
if not temp_count > 0:
return 0
return None
return round(total_temp / temp_count)
@temperature_avg.setter
@@ -473,7 +327,9 @@ class MinerData:
@property
def efficiency(self): # noqa - Skip PyCharm inspection
if self.hashrate == 0 or self.wattage == -1:
if self.hashrate is None or self.wattage is None:
return None
if self.hashrate == 0 or self.wattage == 0:
return 0
return round(self.wattage / self.hashrate)
@@ -482,13 +338,16 @@ class MinerData:
pass
def asdict(self) -> dict:
logging.debug(f"MinerData - (To Dict) - Dumping Dict data")
return asdict(self)
def as_dict(self) -> dict:
"""Get this dataclass as a dictionary.
Returns:
A dictionary version of this class.
"""
logging.debug(f"MinerData - (To Dict) - Dumping Dict data")
return asdict(self)
return self.asdict()
def as_json(self) -> str:
"""Get this dataclass as JSON.
@@ -533,27 +392,45 @@ class MinerData:
tags = ["ip", "mac", "model", "hostname"]
for attribute in self:
if attribute in tags:
escaped_data = self[attribute].replace(" ", "\\ ")
escaped_data = self.get(attribute, "Unknown").replace(" ", "\\ ")
tag_data.append(f"{attribute}={escaped_data}")
continue
if isinstance(self[attribute], str):
elif str(attribute).startswith("_"):
continue
elif isinstance(self[attribute], str):
field_data.append(f'{attribute}="{self[attribute]}"')
continue
if isinstance(self[attribute], bool):
elif isinstance(self[attribute], bool):
field_data.append(f"{attribute}={str(self[attribute]).lower()}")
continue
if isinstance(self[attribute], int):
elif isinstance(self[attribute], int):
field_data.append(f"{attribute}={self[attribute]}")
continue
if isinstance(self[attribute], float):
elif isinstance(self[attribute], float):
field_data.append(f"{attribute}={self[attribute]}")
continue
if attribute == "fault_light" and not self[attribute]:
field_data.append(f"{attribute}=false")
continue
if attribute == "errors":
elif attribute == "errors":
for idx, item in enumerate(self[attribute]):
field_data.append(f'error_{idx+1}="{item.error_message}"')
elif attribute == "hashboards":
for idx, item in enumerate(self[attribute]):
field_data.append(
f"hashboard_{idx+1}_hashrate={item.get('hashrate', 0.0)}"
)
field_data.append(
f"hashboard_{idx+1}_temperature={item.get('temp', 0)}"
)
field_data.append(
f"hashboard_{idx+1}_chip_temperature={item.get('chip_temp', 0)}"
)
field_data.append(f"hashboard_{idx+1}_chips={item.get('chips', 0)}")
field_data.append(
f"hashboard_{idx+1}_expected_chips={item.get('expected_chips', 0)}"
)
elif attribute == "fans":
for idx, item in enumerate(self[attribute]):
if item.speed is not None:
field_data.append(f"fan_{idx+1}={item.speed}")
tags_str = ",".join(tag_data)
field_str = ",".join(field_data)

View File

@@ -16,8 +16,6 @@
from dataclasses import asdict, dataclass, field, fields
C_N_CODES = ["52", "53", "54", "55", "56"]
@dataclass
class WhatsminerError:
@@ -37,10 +35,8 @@ class WhatsminerError:
@property
def error_message(self): # noqa - Skip PyCharm inspection
if len(str(self.error_code)) > 3 and str(self.error_code)[:2] in C_N_CODES:
# 55 error code base has chip numbers, so the format is
# 55 -> board num len 1 -> chip num len 3
err_type = 55
if len(str(self.error_code)) == 6 and not str(self.error_code)[:1] == "1":
err_type = int(str(self.error_code)[:2])
err_subtype = int(str(self.error_code)[2:3])
err_value = int(str(self.error_code)[3:])
else:
@@ -88,7 +84,9 @@ class WhatsminerError:
ERROR_CODES = {
1: { # Fan error
0: {0: "Fan unknown."},
0: {
0: "Fan unknown.",
},
1: { # Fan speed error of 1000+
0: "Intake fan speed error.",
1: "Exhaust fan speed error.",
@@ -101,7 +99,9 @@ ERROR_CODES = {
0: "Intake fan speed error. Fan speed deviates by more than 3000.",
1: "Exhaust fan speed error. Fan speed deviates by more than 3000.",
},
4: {0: "Fan speed too high."}, # High speed
4: {
0: "Fan speed too high.",
}, # High speed
},
2: { # Power error
0: {
@@ -126,6 +126,7 @@ ERROR_CODES = {
6: "Power remained unchanged for a long time.",
7: "Power set enable error.",
8: "Power input voltage is lower than 230V for high power mode.",
9: "Power input current is incorrect.",
},
3: {
3: "Power output high temperature protection error.",
@@ -159,6 +160,8 @@ ERROR_CODES = {
6: {
3: "Power communication warning.",
4: "Power communication error.",
5: "Power unknown error.",
6: "Power unknown error.",
7: "Power watchdog protection.",
8: "Power output high current protection.",
9: "Power input high current protection.",
@@ -170,57 +173,134 @@ ERROR_CODES = {
3: "Power input too high warning.",
4: "Power fan warning.",
5: "Power high temperature warning.",
6: "Power unknown error.",
7: "Power unknown error.",
8: "Power unknown error.",
9: "Power unknown error.",
},
8: {
0: "Power unknown error.",
1: "Power vendor status 1 bit 0 error.",
2: "Power vendor status 1 bit 1 error.",
3: "Power vendor status 1 bit 2 error.",
4: "Power vendor status 1 bit 3 error.",
5: "Power vendor status 1 bit 4 error.",
6: "Power vendor status 1 bit 5 error.",
7: "Power vendor status 1 bit 6 error.",
8: "Power vendor status 1 bit 7 error.",
9: "Power vendor status 2 bit 0 error.",
},
9: {
0: "Power vendor status 2 bit 1 error.",
1: "Power vendor status 2 bit 2 error.",
2: "Power vendor status 2 bit 3 error.",
3: "Power vendor status 2 bit 4 error.",
4: "Power vendor status 2 bit 5 error.",
5: "Power vendor status 2 bit 6 error.",
6: "Power vendor status 2 bit 7 error.",
},
},
3: { # temperature error
0: { # sensor detection error
"n": "Slot {n} temperature sensor detection error."
"n": "Slot {n} temperature sensor detection error.",
},
2: { # temperature reading error
"n": "Slot {n} temperature reading error.",
9: "Control board temperature sensor communication error.",
},
5: {"n": "Slot {n} temperature protecting."}, # temperature protection
6: {0: "Hashboard high temperature error."}, # high temp
5: {
"n": "Slot {n} temperature protecting.",
}, # temperature protection
6: {
0: "Hashboard high temperature error.",
1: "Hashboard high temperature error.",
2: "Hashboard high temperature error.",
3: "Hashboard high temperature error.",
}, # high temp
7: {
0: "The environment temperature fluctuates too much.",
}, # env temp
8: {
0: "Humidity sensor not found.",
1: "Humidity sensor read error.",
2: "Humidity sensor read error.",
3: "Humidity sensor protecting.",
},
}, # humidity
},
4: { # EEPROM error
0: {0: "Eeprom unknown error."},
1: {"n": "Slot {n} eeprom detection error."}, # EEPROM detection error
2: {"n": "Slot {n} eeprom parsing error."}, # EEPROM parsing error
3: {"n": "Slot {n} chip bin type error."}, # chip bin error
4: {"n": "Slot {n} eeprom chip number X error."}, # EEPROM chip number error
5: {"n": "Slot {n} eeprom xfer error."}, # EEPROM xfer error
0: {
0: "Eeprom unknown error.",
},
1: {
"n": "Slot {n} eeprom detection error.",
}, # EEPROM detection error
2: {
"n": "Slot {n} eeprom parsing error.",
}, # EEPROM parsing error
3: {
"n": "Slot {n} chip bin type error.",
}, # chip bin error
4: {
"n": "Slot {n} eeprom chip number X error.",
}, # EEPROM chip number error
5: {
"n": "Slot {n} eeprom xfer error.",
}, # EEPROM xfer error
},
5: { # hashboard error
0: {0: "Board unknown error."},
1: {"n": "Slot {n} miner type error."}, # board miner type error
2: {"n": "Slot {n} bin type error."}, # chip bin type error
3: {"n": "Slot {n} not found."}, # board not found error
4: {"n": "Slot {n} error reading chip id."}, # reading chip id error
5: {"n": "Slot {n} has bad chips."}, # board has bad chips error
6: {"n": "Slot {n} loss of balance error."}, # loss of balance error
7: {"n": "Slot {n} xfer error chip."}, # xfer error
8: {"n": "Slot {n} reset error."}, # reset error
9: {"n": "Slot {n} frequency too low."}, # freq error
0: {
0: "Board unknown error.",
},
1: {
"n": "Slot {n} miner type error.",
}, # board miner type error
2: {
"n": "Slot {n} bin type error.",
}, # chip bin type error
3: {
"n": "Slot {n} not found.",
}, # board not found error
4: {
"n": "Slot {n} error reading chip id.",
}, # reading chip id error
5: {
"n": "Slot {n} has bad chips.",
}, # board has bad chips error
6: {
"n": "Slot {n} loss of balance error.",
}, # loss of balance error
7: {
"n": "Slot {n} xfer error chip.",
}, # xfer error
8: {
"n": "Slot {n} reset error.",
}, # reset error
9: {
"n": "Slot {n} frequency too low.",
}, # freq error
},
6: { # env temp error
0: {0: "Environment temperature is too high."}, # normal env temp error
0: {
0: "Environment temperature is too high.",
}, # normal env temp error
1: { # high power env temp error
0: "Environment temperature is too high for high performance mode."
0: "Environment temperature is too high for high performance mode.",
},
},
7: { # control board error
0: {0: "MAC address invalid", 1: "Control board no support chip."},
0: {
0: "MAC address invalid",
1: "Control board no support chip.",
},
1: {
0: "Control board rebooted as an exception.",
1: "Control board rebooted as exception and cpufreq reduced, please upgrade the firmware",
2: "Control board rebooted as an exception.",
3: "The network is unstable, change time.",
4: "Unknown error.",
},
2: {
"n": "Control board slot {n} frame error.",
},
},
8: { # checksum error
@@ -228,63 +308,152 @@ ERROR_CODES = {
0: "CGMiner checksum error.",
1: "System monitor checksum error.",
2: "Remote daemon checksum error.",
}
},
1: {0: "Air to liquid PCB serial # does not match."},
},
9: {0: {1: "Power rate error."}}, # power rate error
9: {
0: {0: "Unknown error.", 1: "Power rate error.", 2: "Unknown error."}
}, # power rate error
20: { # pool error
1: {0: "All pools are disabled."}, # all disabled error
2: {"n": "Pool {n} connection failed."}, # pool connection failed error
3: {0: "High rejection rate on pool."}, # rejection rate error
0: {
0: "No pool information configured.",
},
1: {
0: "All pools are disabled.",
}, # all disabled error
2: {
"n": "Pool {n} connection failed.",
}, # pool connection failed error
3: {
0: "High rejection rate on pool.",
}, # rejection rate error
4: { # asicboost not supported error
0: "The pool does not support asicboost mode."
0: "The pool does not support asicboost mode.",
},
},
21: {1: {"n": "Slot {n} factory test step failed."}},
21: {
1: {
"n": "Slot {n} factory test step failed.",
}
},
23: { # hashrate error
1: {0: "Hashrate is too low."},
2: {0: "Hashrate is too low."},
3: {0: "Hashrate loss is too high."},
4: {0: "Hashrate loss is too high."},
5: {0: "Hashrate loss."},
1: {
0: "Hashrate is too low.",
},
2: {
0: "Hashrate is too low.",
},
3: {
0: "Hashrate loss is too high.",
},
4: {
0: "Hashrate loss is too high.",
},
5: {
0: "Hashrate loss.",
},
},
50: { # water velocity error/voltage error
1: {"n": "Slot {n} chip voltage too low."},
2: {"n": "Slot {n} chip voltage changed."},
3: {"n": "Slot {n} chip temperature difference is too large."},
4: {"n": "Slot {n} chip hottest temperature difference is too large."},
7: {"n": "Slot {n} water velocity is abnormal."}, # abnormal water velocity
8: {0: "Chip temp calibration failed, please restore factory settings."},
9: {"n": "Slot {n} chip temp calibration check no balance."},
1: {
"n": "Slot {n} chip voltage too low.",
},
2: {
"n": "Slot {n} chip voltage changed.",
},
3: {
"n": "Slot {n} chip temperature difference is too large.",
},
4: {
"n": "Slot {n} chip hottest temperature difference is too large.",
},
5: {"n": "Slot {n} stopped hashing, chips temperature protecting."},
7: {
"n": "Slot {n} water velocity is abnormal.",
}, # abnormal water velocity
8: {
0: "Chip temp calibration failed, please restore factory settings.",
},
9: {
"n": "Slot {n} chip temp calibration check no balance.",
},
},
51: { # frequency error
1: {"n": "Slot {n} frequency up timeout."}, # frequency up timeout
7: {"n": "Slot {n} frequency up timeout."}, # frequency up timeout
1: {
"n": "Slot {n} frequency up timeout.",
}, # frequency up timeout
2: {"n": "Slot {n} too many CRC errors."},
3: {"n": "Slot {n} unstable."},
7: {
"n": "Slot {n} frequency up timeout.",
}, # frequency up timeout
},
52: {
"n": {
"c": "Slot {n} chip {c} error nonce.",
},
},
53: {
"n": {
"c": "Slot {n} chip {c} too few nonce.",
},
},
54: {
"n": {
"c": "Slot {n} chip {c} temp protected.",
},
},
55: {
"n": {
"c": "Slot {n} chip {c} has been reset.",
},
},
56: {
"n": {
"c": "Slot {n} chip {c} zero nonce.",
},
},
52: {"n": {"c": "Slot {n} chip {c} error nonce."}},
53: {"n": {"c": "Slot {n} chip {c} too few nonce."}},
54: {"n": {"c": "Slot {n} chip {c} temp protected."}},
55: {"n": {"c": "Slot {n} chip {c} has been reset."}},
56: {"n": {"c": "Slot {n} chip {c} does not return to the nonce."}},
80: {
0: {0: "The tool version is too low, please update."},
1: {0: "Low freq."},
2: {0: "Low hashrate."},
3: {5: "High env temp."},
0: {
0: "The tool version is too low, please update.",
},
1: {
0: "Low freq.",
},
2: {
0: "Low hashrate.",
},
3: {
5: "High env temp.",
},
},
81: {
0: {0: "Chip data error."},
0: {
0: "Chip data error.",
},
},
82: {
0: {0: "Power version error."},
1: {0: "Miner type error."},
2: {0: "Version info error."},
0: {
0: "Power version error.",
},
1: {
0: "Miner type error.",
},
2: {
0: "Version info error.",
},
},
83: {
0: {0: "Empty level error."},
0: {
0: "Empty level error.",
},
},
84: {
0: {0: "Old firmware."},
1: {0: "Software version error."},
0: {
0: "Old firmware.",
},
1: {
0: "Software version error.",
},
},
85: {
"n": {
@@ -296,8 +465,12 @@ ERROR_CODES = {
},
},
86: {
0: {0: "Missing product serial #."},
1: {0: "Missing product type."},
0: {
0: "Missing product serial #.",
},
1: {
0: "Missing product type.",
},
2: {
0: "Missing miner serial #.",
1: "Wrong miner serial # length.",
@@ -314,12 +487,34 @@ ERROR_CODES = {
3: "Wrong power model rate.",
4: "Wrong power model format.",
},
5: {0: "Wrong hash board struct."},
6: {0: "Wrong miner cooling type."},
7: {0: "Missing PCB serial #."},
5: {
0: "Wrong hash board struct.",
},
6: {
0: "Wrong miner cooling type.",
},
7: {
0: "Missing PCB serial #.",
},
},
87: {
0: {
0: "Miner power mismatch.",
},
},
90: {
0: {
0: "Process error, exited with signal: 3.",
},
1: {
0: "Process error, exited with signal: 3.",
},
},
99: {
9: {
9: "Miner unknown error.",
},
},
87: {0: {0: "Miner power mismatch."}},
99: {9: {9: "Miner unknown error."}},
1000: {
0: {
0: "Security library error, please upgrade firmware",
@@ -328,7 +523,11 @@ ERROR_CODES = {
3: "/antiv/dig/pf_partial.dig illegal.",
},
},
1001: {0: {0: "Security BTMiner removed, please upgrade firmware."}},
1001: {
0: {
0: "Security BTMiner removed, please upgrade firmware.",
},
},
1100: {
0: {
0: "Security illegal file, please upgrade firmware.",

View File

@@ -19,21 +19,8 @@ from typing import List, Union
from pyasic.errors import APIError
from pyasic.miners import AnyMiner
from pyasic.miners.backends import ( # noqa - Ignore access to _module
AntminerModern,
BOSMiner,
BTMiner,
)
from pyasic.miners.btc._types import ( # noqa - Ignore access to _module
S9,
S17,
T17,
S17e,
S17Plus,
S17Pro,
T17e,
T17Plus,
)
from pyasic.miners.backends import AntminerModern, BOSMiner, BTMiner
from pyasic.miners.types import S9, S17, T17, S17e, S17Plus, S17Pro, T17e, T17Plus
FAN_USAGE = 50 # 50 W per fan
@@ -162,10 +149,10 @@ class _MinerPhaseBalancer:
not self.miners[data_point.ip]["shutdown"]
):
# cant do anything with it so need to find a semi-accurate power limit
if not data_point.wattage_limit == -1:
if not data_point.wattage_limit == None:
self.miners[data_point.ip]["max"] = int(data_point.wattage_limit)
self.miners[data_point.ip]["min"] = int(data_point.wattage_limit)
elif not data_point.wattage == -1:
elif not data_point.wattage == None:
self.miners[data_point.ip]["max"] = int(data_point.wattage)
self.miners[data_point.ip]["min"] = int(data_point.wattage)

View File

@@ -16,31 +16,29 @@
import logging
from pyasic.settings import PyasicSettings
def init_logger():
if PyasicSettings().logfile:
logging.basicConfig(
filename="logfile.txt",
filemode="a",
format="%(pathname)s:%(lineno)d in %(funcName)s\n[%(levelname)s][%(asctime)s](%(name)s) - %(message)s",
datefmt="%x %X",
)
else:
logging.basicConfig(
format="%(pathname)s:%(lineno)d in %(funcName)s\n[%(levelname)s][%(asctime)s](%(name)s) - %(message)s",
datefmt="%x %X",
)
# if PyasicSettings().logfile:
# logging.basicConfig(
# filename="logfile.txt",
# filemode="a",
# format="%(pathname)s:%(lineno)d in %(funcName)s\n[%(levelname)s][%(asctime)s](%(name)s) - %(message)s",
# datefmt="%x %X",
# )
# else:
logging.basicConfig(
format="%(pathname)s:%(lineno)d in %(funcName)s\n[%(levelname)s][%(asctime)s](%(name)s) - %(message)s",
datefmt="%x %X",
)
_logger = logging.getLogger()
if PyasicSettings().debug:
_logger.setLevel(logging.DEBUG)
logging.getLogger("asyncssh").setLevel(logging.DEBUG)
else:
_logger.setLevel(logging.WARNING)
logging.getLogger("asyncssh").setLevel(logging.WARNING)
# if PyasicSettings().debug:
# _logger.setLevel(logging.DEBUG)
# logging.getLogger("asyncssh").setLevel(logging.DEBUG)
# else:
_logger.setLevel(logging.WARNING)
logging.getLogger("asyncssh").setLevel(logging.WARNING)
return _logger

View File

@@ -18,9 +18,9 @@ import ipaddress
from typing import Union
from pyasic.miners.base import AnyMiner, BaseMiner
from pyasic.miners.miner_factory import MinerFactory
from pyasic.miners.miner_factory import miner_factory
# abstracted version of get miner that is easier to access
async def get_miner(ip: Union[ipaddress.ip_address, str]) -> AnyMiner:
return await MinerFactory().get_miner(ip)
return await miner_factory.get_miner(ip)

View File

@@ -18,4 +18,5 @@ from .bmminer import *
from .bosminer import *
from .cgminer import *
from .hiveon import *
from .luxos import *
from .vnish import *

View File

@@ -0,0 +1,34 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerOld
from pyasic.miners.types import S17, S17e, S17Plus, S17Pro
class BMMinerS17(AntminerOld, S17):
pass
class BMMinerS17Plus(AntminerOld, S17Plus):
pass
class BMMinerS17Pro(AntminerOld, S17Pro):
pass
class BMMinerS17e(AntminerOld, S17e):
pass

View File

@@ -15,9 +15,16 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerOld
from pyasic.miners.ltc._types import L3Plus # noqa - Ignore access to _module
from pyasic.miners.types import T17, T17e, T17Plus
class BMMinerL3Plus(AntminerOld, L3Plus):
def __init__(self, ip: str, api_ver: str = "0.0.0"):
super().__init__(ip, api_ver)
class BMMinerT17(AntminerOld, T17):
pass
class BMMinerT17Plus(AntminerOld, T17Plus):
pass
class BMMinerT17e(AntminerOld, T17e):
pass

View File

@@ -0,0 +1,18 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from .S17 import BMMinerS17, BMMinerS17e, BMMinerS17Plus, BMMinerS17Pro
from .T17 import BMMinerT17, BMMinerT17e, BMMinerT17Plus

View File

@@ -15,10 +15,65 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern
from pyasic.miners.btc._types import S19jPro # noqa - Ignore access to _module
from pyasic.miners.types import (
S19,
S19L,
S19XP,
S19a,
S19aPro,
S19i,
S19j,
S19jNoPIC,
S19jPro,
S19Plus,
S19Pro,
S19ProPlus,
)
# noqa - Ignore access to _module
class BMMinerS19(AntminerModern, S19):
pass
class BMMinerS19Plus(AntminerModern, S19Plus):
pass
class BMMinerS19i(AntminerModern, S19i):
pass
class BMMinerS19Pro(AntminerModern, S19Pro):
pass
class BMMinerS19ProPlus(AntminerModern, S19ProPlus):
pass
class BMMinerS19XP(AntminerModern, S19XP):
pass
class BMMinerS19a(AntminerModern, S19a):
pass
class BMMinerS19aPro(AntminerModern, S19aPro):
pass
class BMMinerS19j(AntminerModern, S19j):
pass
class BMMinerS19jNoPIC(AntminerModern, S19jNoPIC):
pass
class BMMinerS19jPro(AntminerModern, S19jPro):
pass
class BMMinerS19L(AntminerModern, S19L):
pass

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern
from pyasic.miners.btc._types import T19 # noqa - Ignore access to _module
from pyasic.miners.types import T19
# noqa - Ignore access to _module

View File

@@ -14,12 +14,18 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from .S19 import BMMinerS19
from .S19_Pro import BMMinerS19Pro
from .S19_XP import BMMinerS19XP
from .S19a import BMMinerS19a
from .S19a_Pro import BMMinerS19aPro
from .S19j import BMMinerS19j
from .S19j_Pro import BMMinerS19jPro
from .S19L import BMMinerS19L
from .S19 import (
BMMinerS19,
BMMinerS19a,
BMMinerS19aPro,
BMMinerS19i,
BMMinerS19j,
BMMinerS19jNoPIC,
BMMinerS19jPro,
BMMinerS19L,
BMMinerS19Plus,
BMMinerS19Pro,
BMMinerS19ProPlus,
BMMinerS19XP,
)
from .T19 import BMMinerT19

View File

@@ -15,10 +15,10 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern
from pyasic.miners.hns._types import HS3 # noqa - Ignore access to _module
from pyasic.miners.types import HS3
class CGMinerHS3(AntminerModern, HS3):
class BMMinerHS3(AntminerModern, HS3):
def __init__(self, ip: str, api_ver: str = "0.0.0"):
super().__init__(ip, api_ver)
self.supports_shutdown = False

View File

@@ -14,8 +14,9 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.backends import CGMinerAvalon # noqa - Ignore access to _module
from pyasic.miners.backends import AntminerOld
from pyasic.miners.types import L3Plus
class CGMinerA10X(CGMinerAvalon):
class BMMinerL3Plus(AntminerOld, L3Plus):
pass

View File

@@ -13,6 +13,5 @@
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from .X9 import *
from .X17 import *
from .X19 import *
from .HS3 import BMMinerHS3
from .L3 import BMMinerL3Plus

View File

@@ -14,7 +14,7 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern
from pyasic.miners.ltc._types import L7 # noqa - Ignore access to _module
from pyasic.miners.types import L7
class BMMinerL7(AntminerModern, L7):

View File

@@ -15,10 +15,10 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerModern
from pyasic.miners.etc._types import E9Pro # noqa - Ignore access to _module
from pyasic.miners.types import E9Pro
class CGMinerE9Pro(AntminerModern, E9Pro):
class BMMinerE9Pro(AntminerModern, E9Pro):
def __init__(self, ip: str, api_ver: str = "0.0.0"):
super().__init__(ip, api_ver)
self.supports_shutdown = False

View File

@@ -15,8 +15,16 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import BMMiner
from pyasic.miners.btc._types import S9i # noqa - Ignore access to _module
from pyasic.miners.types import S9, S9i, S9j
class BMMinerS9(BMMiner, S9):
pass
class BMMinerS9i(BMMiner, S9i):
pass
class BMMinerS9j(BMMiner, S9j):
pass

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import BMMiner
from pyasic.miners.btc._types import T9 # noqa - Ignore access to _module
from pyasic.miners.types import T9
class BMMinerT9(BMMiner, T9):

View File

@@ -14,6 +14,6 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from .S9 import BMMinerS9
from .S9i import BMMinerS9i
from .E9 import BMMinerE9Pro
from .S9 import BMMinerS9, BMMinerS9i, BMMinerS9j
from .T9 import BMMinerT9

View File

@@ -13,6 +13,8 @@
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from .X3 import *
from .X7 import *
from .X9 import *
from .X17 import *
from .X19 import *

View File

@@ -15,8 +15,20 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import BOSMiner
from pyasic.miners.btc._types import S17Plus # noqa - Ignore access to _module
from pyasic.miners.types import S17, S17e, S17Plus, S17Pro
class BOSMinerS17(BOSMiner, S17):
pass
class BOSMinerS17Plus(BOSMiner, S17Plus):
pass
class BOSMinerS17Pro(BOSMiner, S17Pro):
pass
class BOSMinerS17e(BOSMiner, S17e):
pass

View File

@@ -15,8 +15,16 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import BOSMiner
from pyasic.miners.btc._types import T17Plus # noqa - Ignore access to _module
from pyasic.miners.types import T17, T17e, T17Plus
class BOSMinerT17(BOSMiner, T17):
pass
class BOSMinerT17Plus(BOSMiner, T17Plus):
pass
class BOSMinerT17e(BOSMiner, T17e):
pass

View File

@@ -0,0 +1,18 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from .S17 import BOSMinerS17, BOSMinerS17e, BOSMinerS17Plus, BOSMinerS17Pro
from .T17 import BOSMinerT17, BOSMinerT17e, BOSMinerT17Plus

View File

@@ -15,7 +15,23 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import BOSMiner
from pyasic.miners.btc._types import S19jPro # noqa - Ignore access to _module
from pyasic.miners.types import S19, S19j, S19jNoPIC, S19jPro, S19Pro
class BOSMinerS19(BOSMiner, S19):
pass
class BOSMinerS19Pro(BOSMiner, S19Pro):
pass
class BOSMinerS19j(BOSMiner, S19j):
pass
class BOSMinerS19jNoPIC(BOSMiner, S19jNoPIC):
pass
class BOSMinerS19jPro(BOSMiner, S19jPro):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import BOSMiner
from pyasic.miners.btc._types import T19 # noqa - Ignore access to _module
from pyasic.miners.types import T19
class BOSMinerT19(BOSMiner, T19):

View File

@@ -14,8 +14,11 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from .S19 import BOSMinerS19
from .S19_Pro import BOSMinerS19Pro
from .S19j import BOSMinerS19j
from .S19j_Pro import BOSMinerS19jPro
from .S19 import (
BOSMinerS19,
BOSMinerS19j,
BOSMinerS19jNoPIC,
BOSMinerS19jPro,
BOSMinerS19Pro,
)
from .T19 import BOSMinerT19

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import BOSMiner
from pyasic.miners.btc._types import S9 # noqa - Ignore access to _module
from pyasic.miners.types import S9
class BOSMinerS9(BOSMiner, S9):

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerOld
from pyasic.miners.zec._types import Z15 # noqa - Ignore access to _module
from pyasic.miners.types import Z15
class CGMinerZ15(AntminerOld, Z15):

View File

@@ -13,9 +13,8 @@
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerOld
from pyasic.miners.dsh._types import D3 # noqa - Ignore access to _module
from pyasic.miners.types import D3
class CGMinerD3(AntminerOld, D3):

View File

@@ -13,4 +13,5 @@
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from .D3 import CGMinerD3

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import AntminerOld
from pyasic.miners.dcr._types import DR5 # noqa - Ignore access to _module
from pyasic.miners.types import DR5
class CGMinerDR5(AntminerOld, DR5):

View File

@@ -13,4 +13,7 @@
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from .X3 import *
from .X5 import *
from .X15 import *

View File

@@ -20,8 +20,8 @@ import asyncssh
from pyasic.data import HashBoard
from pyasic.errors import APIError
from pyasic.miners.backends import Hiveon # noqa - Ignore access to _module
from pyasic.miners.btc._types import T9 # noqa - Ignore access to _module
from pyasic.miners.backends import Hiveon
from pyasic.miners.types import T9
class HiveonT9(Hiveon, T9):
@@ -58,7 +58,7 @@ class HiveonT9(Hiveon, T9):
hashrate = 0
chips = 0
for chipset in board_map[board]:
if hashboard.chip_temp == -1:
if hashboard.chip_temp == None:
try:
hashboard.board_temp = api_stats["STATS"][1][f"temp{chipset}"]
hashboard.chip_temp = api_stats["STATS"][1][f"temp2_{chipset}"]

View File

@@ -14,8 +14,9 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.backends import CGMinerAvalon # noqa - Ignore access to _module
from pyasic.miners.backends import LUXMiner
from pyasic.miners.types import S9
class CGMinerA7X(CGMinerAvalon):
class LUXMinerS9(LUXMiner, S9):
pass

View File

@@ -14,4 +14,4 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from .A10X import A10X
from .S9 import LUXMinerS9

View File

@@ -13,4 +13,5 @@
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from .X9 import *

View File

@@ -13,11 +13,13 @@
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.btc._types import S17Pro # noqa - Ignore access to _module
from .X17 import BMMinerX17
from pyasic.miners.backends import VNish
from pyasic.miners.types import S17Plus, S17Pro
class BMMinerS17Pro(BMMinerX17, S17Pro):
class VNishS17Plus(VNish, S17Plus):
pass
class VNishS17Pro(VNish, S17Pro):
pass

View File

@@ -13,5 +13,4 @@
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from .T3H_Plus import InnosiliconT3HPlus
from .S17 import VNishS17Plus, VNishS17Pro

View File

@@ -14,8 +14,45 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.backends import VNish # noqa - Ignore access to _module
from pyasic.miners.btc._types import S19jPro # noqa - Ignore access to _module
from pyasic.miners.backends import VNish
from pyasic.miners.types import (
S19,
S19XP,
S19a,
S19aPro,
S19j,
S19jPro,
S19NoPIC,
S19Pro,
)
class VNishS19(VNish, S19):
pass
class VNishS19NoPIC(VNish, S19NoPIC):
pass
class VNishS19Pro(VNish, S19Pro):
pass
class VNishS19XP(VNish, S19XP):
pass
class VNishS19a(VNish, S19a):
pass
class VNishS19aPro(VNish, S19aPro):
pass
class VNishS19j(VNish, S19j):
pass
class VNishS19jPro(VNish, S19jPro):

View File

@@ -14,8 +14,9 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.backends import CGMinerAvalon # noqa - Ignore access to _module
from pyasic.miners.backends import VNish
from pyasic.miners.types import T19
class CGMinerA8X(CGMinerAvalon):
class VNishT19(VNish, T19):
pass

View File

@@ -14,10 +14,14 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from .S17 import S17
from .S17_Plus import S17Plus
from .S17_Pro import S17Pro
from .S17e import S17e
from .T17 import T17
from .T17_Plus import T17Plus
from .T17e import T17e
from .S19 import (
VNishS19,
VNishS19a,
VNishS19aPro,
VNishS19j,
VNishS19jPro,
VNishS19NoPIC,
VNishS19Pro,
VNishS19XP,
)
from .T19 import VNishT19

View File

@@ -15,7 +15,7 @@
# ------------------------------------------------------------------------------
from pyasic.miners.backends import VNish
from pyasic.miners.ltc._types import L3Plus # noqa - Ignore access to _module
from pyasic.miners.types import L3Plus
class VnishL3Plus(VNish, L3Plus):

View File

@@ -14,4 +14,4 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from .X19 import *
from .L3 import VnishL3Plus

View File

@@ -14,6 +14,6 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from .X9 import *
from .X3 import *
from .X17 import *
from .X19 import *

View File

@@ -14,10 +14,9 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.btc._types import Avalon1026 # noqa - Ignore access to _module
from .A10X import CGMinerA10X
from pyasic.miners.backends import CGMinerAvalon
from pyasic.miners.types import Avalon1026
class CGMinerAvalon1026(CGMinerA10X, Avalon1026):
class CGMinerAvalon1026(CGMinerAvalon, Avalon1026):
pass

View File

@@ -14,10 +14,9 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.btc._types import Avalon1047 # noqa - Ignore access to _module
from .A10X import CGMinerA10X
from pyasic.miners.backends import CGMinerAvalon
from pyasic.miners.types import Avalon1047
class CGMinerAvalon1047(CGMinerA10X, Avalon1047):
class CGMinerAvalon1047(CGMinerAvalon, Avalon1047):
pass

View File

@@ -14,10 +14,9 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.btc._types import Avalon1066 # noqa - Ignore access to _module
from .A10X import CGMinerA10X
from pyasic.miners.backends import CGMinerAvalon
from pyasic.miners.types import Avalon1066
class CGMinerAvalon1066(CGMinerA10X, Avalon1066):
class CGMinerAvalon1066(CGMinerAvalon, Avalon1066):
pass

View File

@@ -14,10 +14,9 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.btc._types import S17Plus # noqa - Ignore access to _module
from .X17 import BMMinerX17
from pyasic.miners.backends import CGMinerAvalon
from pyasic.miners.types import Avalon1166Pro
class BMMinerS17Plus(BMMinerX17, S17Plus):
class CGMinerAvalon1166Pro(CGMinerAvalon, Avalon1166Pro):
pass

View File

@@ -0,0 +1,17 @@
# ------------------------------------------------------------------------------
# Copyright 2022 Upstream Data Inc -
# -
# Licensed under the Apache License, Version 2.0 (the "License"); -
# you may not use this file except in compliance with the License. -
# You may obtain a copy of the License at -
# -
# http://www.apache.org/licenses/LICENSE-2.0 -
# -
# Unless required by applicable law or agreed to in writing, software -
# distributed under the License is distributed on an "AS IS" BASIS, -
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -
# See the License for the specific language governing permissions and -
# limitations under the License. -
# ------------------------------------------------------------------------------
from .A1166 import CGMinerAvalon1166Pro

View File

@@ -14,10 +14,9 @@
# limitations under the License. -
# ------------------------------------------------------------------------------
from pyasic.miners.btc._types import T17e # noqa - Ignore access to _module
from .X17 import BMMinerX17
from pyasic.miners.backends import CGMinerAvalon
from pyasic.miners.types import Avalon1246
class BMMinerT17e(BMMinerX17, T17e):
class CGMinerAvalon1246(CGMinerAvalon, Avalon1246):
pass

Some files were not shown because too many files have changed in this diff Show More