Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a81844898 | ||
|
|
0ac80fb205 | ||
|
|
9494018c12 | ||
|
|
0bc86c98c5 | ||
|
|
f0d69c9ca7 | ||
|
|
b81590bd2e | ||
|
|
a53e01df6f | ||
|
|
f63e063954 | ||
|
|
9cbaf7076a | ||
|
|
daa5ac5870 | ||
|
|
0b8c08016b | ||
|
|
8c768d351b | ||
|
|
c9e7fa2629 | ||
|
|
9d3f2b5968 | ||
|
|
283e3d5e11 | ||
|
|
add4b575c2 | ||
|
|
af2f1e9ad5 | ||
|
|
8258320a7b |
@@ -5,8 +5,8 @@
|
|||||||
[](https://pypi.org/project/pyasic/)
|
[](https://pypi.org/project/pyasic/)
|
||||||
[](https://pypi.org/project/pyasic/)
|
[](https://pypi.org/project/pyasic/)
|
||||||
[](https://pyasic.readthedocs.io/en/latest/)
|
[](https://pyasic.readthedocs.io/en/latest/)
|
||||||

|
[](https://github.com/UpstreamData/pyasic/blob/master/LICENSE.txt)
|
||||||

|
[](https://www.codefactor.io/repository/github/upstreamdata/pyasic)
|
||||||
## Documentation
|
## Documentation
|
||||||
Documentation is located on Read the Docs as [pyasic](https://pyasic.readthedocs.io/en/latest/)
|
Documentation is located on Read the Docs as [pyasic](https://pyasic.readthedocs.io/en/latest/)
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
[](https://pypi.org/project/pyasic/)
|
[](https://pypi.org/project/pyasic/)
|
||||||
[](https://pypi.org/project/pyasic/)
|
[](https://pypi.org/project/pyasic/)
|
||||||
[](https://pyasic.readthedocs.io/en/latest/)
|
[](https://pyasic.readthedocs.io/en/latest/)
|
||||||
|
[](https://github.com/UpstreamData/pyasic/blob/master/LICENSE.txt)
|
||||||
|
[](https://www.codefactor.io/repository/github/upstreamdata/pyasic)
|
||||||
|
|
||||||
## Intro
|
## Intro
|
||||||
Welcome to pyasic! Pyasic uses an asynchronous method of communicating with asic miners on your network, which makes it super fast.
|
Welcome to pyasic! Pyasic uses an asynchronous method of communicating with asic miners on your network, which makes it super fast.
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ Supported miner types are here on this list. If your miner (or miner version) i
|
|||||||
* [VE20][pyasic.miners.whatsminer.btminer.M3X.M31S_Plus.BTMinerM31SPlusVE20]
|
* [VE20][pyasic.miners.whatsminer.btminer.M3X.M31S_Plus.BTMinerM31SPlusVE20]
|
||||||
* [M32S][pyasic.miners.whatsminer.btminer.M3X.M32S.BTMinerM32S]
|
* [M32S][pyasic.miners.whatsminer.btminer.M3X.M32S.BTMinerM32S]
|
||||||
* M2X Series:
|
* M2X Series:
|
||||||
|
* [M20][pyasic.miners.whatsminer.btminer.M2X.M20.BTMinerM20]:
|
||||||
|
* [V10][pyasic.miners.whatsminer.btminer.M2X.M20.BTMinerM20V10]
|
||||||
* [M20S][pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20S]:
|
* [M20S][pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20S]:
|
||||||
* [V10][pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20SV10]
|
* [V10][pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20SV10]
|
||||||
* [V20][pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20SV20]
|
* [V20][pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20SV20]
|
||||||
|
|||||||
@@ -1,6 +1,22 @@
|
|||||||
# pyasic
|
# pyasic
|
||||||
## M2X Models
|
## M2X Models
|
||||||
|
|
||||||
|
## M20
|
||||||
|
|
||||||
|
::: pyasic.miners.whatsminer.btminer.M2X.M20.BTMinerM20
|
||||||
|
handler: python
|
||||||
|
options:
|
||||||
|
show_root_heading: false
|
||||||
|
heading_level: 4
|
||||||
|
|
||||||
|
## M20V10
|
||||||
|
|
||||||
|
::: pyasic.miners.whatsminer.btminer.M2X.M20.BTMinerM20V10
|
||||||
|
handler: python
|
||||||
|
options:
|
||||||
|
show_root_heading: false
|
||||||
|
heading_level: 4
|
||||||
|
|
||||||
## M20S
|
## M20S
|
||||||
|
|
||||||
::: pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20S
|
::: pyasic.miners.whatsminer.btminer.M2X.M20S.BTMinerM20S
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ class MinerData:
|
|||||||
pool_2_url: The second pool url on the miner as a str.
|
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.
|
pool_2_user: The second pool user on the miner as a str.
|
||||||
errors: A list of errors on the miner.
|
errors: A list of errors on the miner.
|
||||||
|
fault_light: Whether or not the fault light is on as a boolean.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ip: str
|
ip: str
|
||||||
|
|||||||
25
pyasic/data/error_codes/X19.py
Normal file
25
pyasic/data/error_codes/X19.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
# 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 dataclasses import dataclass, asdict
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class X19Error:
|
||||||
|
"""A Dataclass to handle error codes of X19 miners."""
|
||||||
|
|
||||||
|
error_message: str
|
||||||
|
|
||||||
|
def asdict(self):
|
||||||
|
return asdict(self)
|
||||||
@@ -14,3 +14,4 @@
|
|||||||
|
|
||||||
from .whatsminer import WhatsminerError
|
from .whatsminer import WhatsminerError
|
||||||
from .bos import BraiinsOSError
|
from .bos import BraiinsOSError
|
||||||
|
from .X19 import X19Error
|
||||||
|
|||||||
@@ -112,5 +112,8 @@ class BaseMiner:
|
|||||||
async def get_mac(self):
|
async def get_mac(self):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
async def get_errors(self):
|
||||||
|
return None
|
||||||
|
|
||||||
async def get_data(self) -> MinerData:
|
async def get_data(self) -> MinerData:
|
||||||
return MinerData(ip=str(self.ip))
|
return MinerData(ip=str(self.ip))
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ class BMMiner(BaseMiner):
|
|||||||
model = await self.get_model()
|
model = await self.get_model()
|
||||||
hostname = await self.get_hostname()
|
hostname = await self.get_hostname()
|
||||||
mac = await self.get_mac()
|
mac = await self.get_mac()
|
||||||
|
errors = await self.get_errors()
|
||||||
|
|
||||||
if model:
|
if model:
|
||||||
data.model = model
|
data.model = model
|
||||||
@@ -178,6 +179,10 @@ class BMMiner(BaseMiner):
|
|||||||
if mac:
|
if mac:
|
||||||
data.mac = mac
|
data.mac = mac
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
for error in errors:
|
||||||
|
data.errors.append(error)
|
||||||
|
|
||||||
data.fault_light = await self.check_light()
|
data.fault_light = await self.check_light()
|
||||||
|
|
||||||
miner_data = None
|
miner_data = None
|
||||||
|
|||||||
33
pyasic/miners/_types/whatsminer/M2X/M20.py
Normal file
33
pyasic/miners/_types/whatsminer/M2X/M20.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# 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 import BaseMiner
|
||||||
|
|
||||||
|
|
||||||
|
class M20(BaseMiner):
|
||||||
|
def __init__(self, ip: str):
|
||||||
|
super().__init__()
|
||||||
|
self.ip = ip
|
||||||
|
self.model = "M20"
|
||||||
|
self.nominal_chips = 70
|
||||||
|
self.fan_count = 2
|
||||||
|
|
||||||
|
|
||||||
|
class M20V10(BaseMiner):
|
||||||
|
def __init__(self, ip: str):
|
||||||
|
super().__init__()
|
||||||
|
self.ip = ip
|
||||||
|
self.model = "M20 V10"
|
||||||
|
self.nominal_chips = 70
|
||||||
|
self.fan_count = 2
|
||||||
@@ -28,7 +28,7 @@ class M20SV10(BaseMiner):
|
|||||||
def __init__(self, ip: str):
|
def __init__(self, ip: str):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.ip = ip
|
self.ip = ip
|
||||||
self.model = "M20S"
|
self.model = "M20S V10"
|
||||||
self.nominal_chips = 105
|
self.nominal_chips = 105
|
||||||
self.fan_count = 2
|
self.fan_count = 2
|
||||||
|
|
||||||
@@ -37,6 +37,6 @@ class M20SV20(BaseMiner):
|
|||||||
def __init__(self, ip: str):
|
def __init__(self, ip: str):
|
||||||
super().__init__()
|
super().__init__()
|
||||||
self.ip = ip
|
self.ip = ip
|
||||||
self.model = "M20S"
|
self.model = "M20S V20"
|
||||||
self.nominal_chips = 111
|
self.nominal_chips = 111
|
||||||
self.fan_count = 2
|
self.fan_count = 2
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from .M20 import M20, M20V10
|
||||||
from .M20S import M20S, M20SV10, M20SV20
|
from .M20S import M20S, M20SV10, M20SV20
|
||||||
from .M20S_Plus import M20SPlus
|
from .M20S_Plus import M20SPlus
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class BMMinerX17(BMMiner):
|
|||||||
hostname = data["hostname"]
|
hostname = data["hostname"]
|
||||||
return hostname
|
return hostname
|
||||||
|
|
||||||
async def get_mac(self):
|
async def get_mac(self) -> Union[str, None]:
|
||||||
mac = None
|
mac = None
|
||||||
url = f"http://{self.ip}/cgi-bin/get_system_info.cgi"
|
url = f"http://{self.ip}/cgi-bin/get_system_info.cgi"
|
||||||
auth = httpx.DigestAuth("root", "root")
|
auth = httpx.DigestAuth("root", "root")
|
||||||
@@ -62,6 +62,7 @@ class BMMinerX17(BMMiner):
|
|||||||
if data.status_code == 200:
|
if data.status_code == 200:
|
||||||
data = data.json()
|
data = data.json()
|
||||||
if data["isBlinking"]:
|
if data["isBlinking"]:
|
||||||
|
self.light = True
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -74,10 +75,13 @@ class BMMinerX17(BMMiner):
|
|||||||
if data.status_code == 200:
|
if data.status_code == 200:
|
||||||
data = data.json()
|
data = data.json()
|
||||||
if not data["isBlinking"]:
|
if not data["isBlinking"]:
|
||||||
|
self.light = False
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
async def check_light(self):
|
async def check_light(self) -> Union[bool, None]:
|
||||||
|
if self.light:
|
||||||
|
return self.light
|
||||||
url = f"http://{self.ip}/cgi-bin/blink.cgi"
|
url = f"http://{self.ip}/cgi-bin/blink.cgi"
|
||||||
auth = httpx.DigestAuth("root", "root")
|
auth = httpx.DigestAuth("root", "root")
|
||||||
async with httpx.AsyncClient() as client:
|
async with httpx.AsyncClient() as client:
|
||||||
@@ -85,8 +89,12 @@ class BMMinerX17(BMMiner):
|
|||||||
if data.status_code == 200:
|
if data.status_code == 200:
|
||||||
data = data.json()
|
data = data.json()
|
||||||
if data["isBlinking"]:
|
if data["isBlinking"]:
|
||||||
|
self.light = True
|
||||||
return True
|
return True
|
||||||
return False
|
else:
|
||||||
|
self.light = False
|
||||||
|
return False
|
||||||
|
return None
|
||||||
|
|
||||||
async def reboot(self) -> bool:
|
async def reboot(self) -> bool:
|
||||||
url = f"http://{self.ip}/cgi-bin/reboot.cgi"
|
url = f"http://{self.ip}/cgi-bin/reboot.cgi"
|
||||||
|
|||||||
@@ -15,10 +15,12 @@
|
|||||||
from pyasic.miners._backends import BMMiner # noqa - Ignore access to _module
|
from pyasic.miners._backends import BMMiner # noqa - Ignore access to _module
|
||||||
|
|
||||||
from pyasic.config import MinerConfig
|
from pyasic.config import MinerConfig
|
||||||
|
from pyasic.data.error_codes import X19Error
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
import json
|
import json
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from typing import Union, List
|
||||||
|
|
||||||
|
|
||||||
class BMMinerX19(BMMiner):
|
class BMMinerX19(BMMiner):
|
||||||
@@ -26,7 +28,7 @@ class BMMinerX19(BMMiner):
|
|||||||
super().__init__(ip)
|
super().__init__(ip)
|
||||||
self.ip = ip
|
self.ip = ip
|
||||||
|
|
||||||
async def check_light(self) -> bool:
|
async def check_light(self) -> Union[bool, None]:
|
||||||
if self.light:
|
if self.light:
|
||||||
return self.light
|
return self.light
|
||||||
url = f"http://{self.ip}/cgi-bin/get_blink_status.cgi"
|
url = f"http://{self.ip}/cgi-bin/get_blink_status.cgi"
|
||||||
@@ -36,8 +38,9 @@ class BMMinerX19(BMMiner):
|
|||||||
if data.status_code == 200:
|
if data.status_code == 200:
|
||||||
data = data.json()
|
data = data.json()
|
||||||
light = data["blink"]
|
light = data["blink"]
|
||||||
|
self.light = light
|
||||||
return light
|
return light
|
||||||
return False
|
return None
|
||||||
|
|
||||||
async def get_config(self) -> MinerConfig:
|
async def get_config(self) -> MinerConfig:
|
||||||
url = f"http://{self.ip}/cgi-bin/get_miner_conf.cgi"
|
url = f"http://{self.ip}/cgi-bin/get_miner_conf.cgi"
|
||||||
@@ -69,7 +72,7 @@ class BMMinerX19(BMMiner):
|
|||||||
break
|
break
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
|
|
||||||
async def get_hostname(self) -> str or None:
|
async def get_hostname(self) -> Union[str, None]:
|
||||||
hostname = None
|
hostname = None
|
||||||
url = f"http://{self.ip}/cgi-bin/get_system_info.cgi"
|
url = f"http://{self.ip}/cgi-bin/get_system_info.cgi"
|
||||||
auth = httpx.DigestAuth("root", "root")
|
auth = httpx.DigestAuth("root", "root")
|
||||||
@@ -82,7 +85,7 @@ class BMMinerX19(BMMiner):
|
|||||||
hostname = data["hostname"]
|
hostname = data["hostname"]
|
||||||
return hostname
|
return hostname
|
||||||
|
|
||||||
async def get_mac(self):
|
async def get_mac(self) -> Union[str, None]:
|
||||||
mac = None
|
mac = None
|
||||||
url = f"http://{self.ip}/cgi-bin/get_system_info.cgi"
|
url = f"http://{self.ip}/cgi-bin/get_system_info.cgi"
|
||||||
auth = httpx.DigestAuth("root", "root")
|
auth = httpx.DigestAuth("root", "root")
|
||||||
@@ -129,3 +132,18 @@ class BMMinerX19(BMMiner):
|
|||||||
if data.status_code == 200:
|
if data.status_code == 200:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
async def get_errors(self) -> List[X19Error]:
|
||||||
|
errors = []
|
||||||
|
url = f"http://{self.ip}/cgi-bin/summary.cgi"
|
||||||
|
auth = httpx.DigestAuth("root", "root")
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
data = await client.get(url, auth=auth)
|
||||||
|
if data:
|
||||||
|
data = data.json()
|
||||||
|
if "SUMMARY" in data.keys():
|
||||||
|
if "status" in data["SUMMARY"][0].keys():
|
||||||
|
for item in data["SUMMARY"][0]["status"]:
|
||||||
|
if not item["status"] == "s":
|
||||||
|
errors.append(X19Error(item["msg"]))
|
||||||
|
return errors
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from A8X import CGMinerA8X # noqa - Ignore access to _module
|
from .A8X import CGMinerA8X # noqa - Ignore access to _module
|
||||||
from pyasic.miners._types import Avalon821 # noqa - Ignore access to _module
|
from pyasic.miners._types import Avalon821 # noqa - Ignore access to _module
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from A8X import CGMinerA8X # noqa - Ignore access to _module
|
from .A8X import CGMinerA8X # noqa - Ignore access to _module
|
||||||
from pyasic.miners._types import Avalon841 # noqa - Ignore access to _module
|
from pyasic.miners._types import Avalon841 # noqa - Ignore access to _module
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from A8X import CGMinerA8X # noqa - Ignore access to _module
|
from .A8X import CGMinerA8X # noqa - Ignore access to _module
|
||||||
from pyasic.miners._types import Avalon851 # noqa - Ignore access to _module
|
from pyasic.miners._types import Avalon851 # noqa - Ignore access to _module
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -45,93 +45,98 @@ import asyncssh
|
|||||||
AnyMiner = TypeVar("AnyMiner", bound=BaseMiner)
|
AnyMiner = TypeVar("AnyMiner", bound=BaseMiner)
|
||||||
|
|
||||||
MINER_CLASSES = {
|
MINER_CLASSES = {
|
||||||
"Antminer S9": {
|
"ANTMINER S9": {
|
||||||
"Default": BOSMinerS9,
|
"Default": BOSMinerS9,
|
||||||
"BOSMiner": BOSMinerOld,
|
"BOSMiner": BOSMinerOld,
|
||||||
"BOSMiner+": BOSMinerS9,
|
"BOSMiner+": BOSMinerS9,
|
||||||
"BMMiner": BMMinerS9,
|
"BMMiner": BMMinerS9,
|
||||||
"CGMiner": CGMinerS9,
|
"CGMiner": CGMinerS9,
|
||||||
},
|
},
|
||||||
"Antminer S9i": {
|
"ANTMINER S9I": {
|
||||||
"Default": BMMinerS9i,
|
"Default": BMMinerS9i,
|
||||||
"BMMiner": BMMinerS9i,
|
"BMMiner": BMMinerS9i,
|
||||||
},
|
},
|
||||||
"Antminer S17": {
|
"ANTMINER S17": {
|
||||||
"Default": BMMinerS17,
|
"Default": BMMinerS17,
|
||||||
"BOSMiner+": BOSMinerS17,
|
"BOSMiner+": BOSMinerS17,
|
||||||
"BMMiner": BMMinerS17,
|
"BMMiner": BMMinerS17,
|
||||||
"CGMiner": CGMinerS17,
|
"CGMiner": CGMinerS17,
|
||||||
},
|
},
|
||||||
"Antminer S17+": {
|
"ANTMINER S17+": {
|
||||||
"Default": BMMinerS17Plus,
|
"Default": BMMinerS17Plus,
|
||||||
"BOSMiner+": BOSMinerS17Plus,
|
"BOSMiner+": BOSMinerS17Plus,
|
||||||
"BMMiner": BMMinerS17Plus,
|
"BMMiner": BMMinerS17Plus,
|
||||||
"CGMiner": CGMinerS17Plus,
|
"CGMiner": CGMinerS17Plus,
|
||||||
},
|
},
|
||||||
"Antminer S17 Pro": {
|
"ANTMINER S17 PRO": {
|
||||||
"Default": BMMinerS17Pro,
|
"Default": BMMinerS17Pro,
|
||||||
"BOSMiner+": BOSMinerS17Pro,
|
"BOSMiner+": BOSMinerS17Pro,
|
||||||
"BMMiner": BMMinerS17Pro,
|
"BMMiner": BMMinerS17Pro,
|
||||||
"CGMiner": CGMinerS17Pro,
|
"CGMiner": CGMinerS17Pro,
|
||||||
},
|
},
|
||||||
"Antminer S17e": {
|
"ANTMINER S17E": {
|
||||||
"Default": BMMinerS17e,
|
"Default": BMMinerS17e,
|
||||||
"BOSMiner+": BOSMinerS17e,
|
"BOSMiner+": BOSMinerS17e,
|
||||||
"BMMiner": BMMinerS17e,
|
"BMMiner": BMMinerS17e,
|
||||||
"CGMiner": CGMinerS17e,
|
"CGMiner": CGMinerS17e,
|
||||||
},
|
},
|
||||||
"Antminer T17": {
|
"ANTMINER T17": {
|
||||||
"Default": BMMinerT17,
|
"Default": BMMinerT17,
|
||||||
"BOSMiner+": BOSMinerT17,
|
"BOSMiner+": BOSMinerT17,
|
||||||
"BMMiner": BMMinerT17,
|
"BMMiner": BMMinerT17,
|
||||||
"CGMiner": CGMinerT17,
|
"CGMiner": CGMinerT17,
|
||||||
},
|
},
|
||||||
"Antminer T17+": {
|
"ANTMINER T17+": {
|
||||||
"Default": BMMinerT17Plus,
|
"Default": BMMinerT17Plus,
|
||||||
"BOSMiner+": BOSMinerT17Plus,
|
"BOSMiner+": BOSMinerT17Plus,
|
||||||
"BMMiner": BMMinerT17Plus,
|
"BMMiner": BMMinerT17Plus,
|
||||||
"CGMiner": CGMinerT17Plus,
|
"CGMiner": CGMinerT17Plus,
|
||||||
},
|
},
|
||||||
"Antminer T17e": {
|
"ANTMINER T17E": {
|
||||||
"Default": BMMinerT17e,
|
"Default": BMMinerT17e,
|
||||||
"BOSMiner+": BOSMinerT17e,
|
"BOSMiner+": BOSMinerT17e,
|
||||||
"BMMiner": BMMinerT17e,
|
"BMMiner": BMMinerT17e,
|
||||||
"CGMiner": CGMinerT17e,
|
"CGMiner": CGMinerT17e,
|
||||||
},
|
},
|
||||||
"Antminer S19": {
|
"ANTMINER S19": {
|
||||||
"Default": BMMinerS19,
|
"Default": BMMinerS19,
|
||||||
"BOSMiner+": BOSMinerS19,
|
"BOSMiner+": BOSMinerS19,
|
||||||
"BMMiner": BMMinerS19,
|
"BMMiner": BMMinerS19,
|
||||||
"CGMiner": CGMinerS19,
|
"CGMiner": CGMinerS19,
|
||||||
},
|
},
|
||||||
"Antminer S19 Pro": {
|
"ANTMINER S19 PRO": {
|
||||||
"Default": BMMinerS19Pro,
|
"Default": BMMinerS19Pro,
|
||||||
"BOSMiner+": BOSMinerS19Pro,
|
"BOSMiner+": BOSMinerS19Pro,
|
||||||
"BMMiner": BMMinerS19Pro,
|
"BMMiner": BMMinerS19Pro,
|
||||||
"CGMiner": CGMinerS19Pro,
|
"CGMiner": CGMinerS19Pro,
|
||||||
},
|
},
|
||||||
"Antminer S19j": {
|
"ANTMINER S19J": {
|
||||||
"Default": BMMinerS19j,
|
"Default": BMMinerS19j,
|
||||||
"BOSMiner+": BOSMinerS19j,
|
"BOSMiner+": BOSMinerS19j,
|
||||||
"BMMiner": BMMinerS19j,
|
"BMMiner": BMMinerS19j,
|
||||||
"CGMiner": CGMinerS19j,
|
"CGMiner": CGMinerS19j,
|
||||||
},
|
},
|
||||||
"Antminer S19j Pro": {
|
"ANTMINER S19J PRO": {
|
||||||
"Default": BMMinerS19jPro,
|
"Default": BMMinerS19jPro,
|
||||||
"BOSMiner+": BOSMinerS19jPro,
|
"BOSMiner+": BOSMinerS19jPro,
|
||||||
"BMMiner": BMMinerS19jPro,
|
"BMMiner": BMMinerS19jPro,
|
||||||
"CGMiner": CGMinerS19jPro,
|
"CGMiner": CGMinerS19jPro,
|
||||||
},
|
},
|
||||||
"Antminer S19a": {
|
"ANTMINER S19A": {
|
||||||
"Default": BMMinerS19a,
|
"Default": BMMinerS19a,
|
||||||
"BMMiner": BMMinerS19a,
|
"BMMiner": BMMinerS19a,
|
||||||
},
|
},
|
||||||
"Antminer T19": {
|
"ANTMINER T19": {
|
||||||
"Default": BMMinerT19,
|
"Default": BMMinerT19,
|
||||||
"BOSMiner+": BOSMinerT19,
|
"BOSMiner+": BOSMinerT19,
|
||||||
"BMMiner": BMMinerT19,
|
"BMMiner": BMMinerT19,
|
||||||
"CGMiner": CGMinerT19,
|
"CGMiner": CGMinerT19,
|
||||||
},
|
},
|
||||||
|
"M20": {
|
||||||
|
"Default": BTMinerM20,
|
||||||
|
"BTMiner": BTMinerM20,
|
||||||
|
"10": BTMinerM20V10,
|
||||||
|
},
|
||||||
"M20S": {
|
"M20S": {
|
||||||
"Default": BTMinerM20S,
|
"Default": BTMinerM20S,
|
||||||
"BTMiner": BTMinerM20S,
|
"BTMiner": BTMinerM20S,
|
||||||
@@ -426,9 +431,9 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
|
|
||||||
if board_name:
|
if board_name:
|
||||||
if board_name == "am1-s9":
|
if board_name == "am1-s9":
|
||||||
model = "Antminer S9"
|
model = "ANTMINER S9"
|
||||||
if board_name == "am2-s17":
|
if board_name == "am2-s17":
|
||||||
model = "Antminer S17"
|
model = "ANTMINER S17"
|
||||||
api = "BOSMiner+"
|
api = "BOSMiner+"
|
||||||
return model, api, None
|
return model, api, None
|
||||||
|
|
||||||
@@ -441,7 +446,7 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
if data.status_code == 200:
|
if data.status_code == 200:
|
||||||
data = data.json()
|
data = data.json()
|
||||||
if "minertype" in data.keys():
|
if "minertype" in data.keys():
|
||||||
model = data["minertype"]
|
model = data["minertype"].upper()
|
||||||
if "bmminer" in "\t".join(data.keys()):
|
if "bmminer" in "\t".join(data.keys()):
|
||||||
api = "BMMiner"
|
api = "BMMiner"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@@ -454,15 +459,15 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
# check for model, for most miners
|
# check for model, for most miners
|
||||||
if not devdetails["DEVDETAILS"][0]["Model"] == "":
|
if not devdetails["DEVDETAILS"][0]["Model"] == "":
|
||||||
# model of most miners
|
# model of most miners
|
||||||
model = devdetails["DEVDETAILS"][0]["Model"]
|
model = devdetails["DEVDETAILS"][0]["Model"].upper()
|
||||||
|
|
||||||
# if model fails, try driver
|
# if model fails, try driver
|
||||||
else:
|
else:
|
||||||
# some avalonminers have model in driver
|
# some avalonminers have model in driver
|
||||||
model = devdetails["DEVDETAILS"][0]["Driver"]
|
model = devdetails["DEVDETAILS"][0]["Driver"].upper()
|
||||||
else:
|
else:
|
||||||
if "s9" in devdetails["STATUS"][0]["Description"]:
|
if "s9" in devdetails["STATUS"][0]["Description"]:
|
||||||
model = "Antminer S9"
|
model = "ANTMINER S9"
|
||||||
|
|
||||||
# if we have version we can get API type from here
|
# if we have version we can get API type from here
|
||||||
if version:
|
if version:
|
||||||
@@ -497,7 +502,7 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
# check for avalonminers
|
# check for avalonminers
|
||||||
if version["VERSION"][0].get("PROD"):
|
if version["VERSION"][0].get("PROD"):
|
||||||
_data = version["VERSION"][0]["PROD"].split("-")
|
_data = version["VERSION"][0]["PROD"].split("-")
|
||||||
model = _data[0]
|
model = _data[0].upper()
|
||||||
if len(data) > 1:
|
if len(data) > 1:
|
||||||
ver = _data[1]
|
ver = _data[1]
|
||||||
elif version["VERSION"][0].get("MODEL"):
|
elif version["VERSION"][0].get("MODEL"):
|
||||||
@@ -522,11 +527,23 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
):
|
):
|
||||||
# try to get "Type" which is model
|
# try to get "Type" which is model
|
||||||
if version["VERSION"][0].get("Type"):
|
if version["VERSION"][0].get("Type"):
|
||||||
model = version["VERSION"][0]["Type"]
|
model = version["VERSION"][0]["Type"].upper()
|
||||||
|
|
||||||
# braiins OS bug check just in case
|
# braiins OS bug check just in case
|
||||||
elif "am2-s17" in version["STATUS"][0]["Description"]:
|
elif "am2-s17" in version["STATUS"][0]["Description"]:
|
||||||
model = "Antminer S17"
|
model = "ANTMINER S17"
|
||||||
|
|
||||||
|
if not model:
|
||||||
|
stats = await self._send_api_command(str(ip), "stats")
|
||||||
|
if stats:
|
||||||
|
if stats["STATS"][0].get("Type"):
|
||||||
|
_model = stats["STATS"][0]["Type"].upper()
|
||||||
|
if " BB" in _model:
|
||||||
|
_model = _model.split(" BB")[0]
|
||||||
|
if " XILINX" in _model:
|
||||||
|
_model = _model.split(" XILINX")[0]
|
||||||
|
if "PRO" in _model and not " PRO" in _model:
|
||||||
|
model = _model.replace("PRO", " PRO")
|
||||||
|
|
||||||
if model:
|
if model:
|
||||||
# whatsminer have a V in their version string (M20SV41), remove everything after it
|
# whatsminer have a V in their version string (M20SV41), remove everything after it
|
||||||
@@ -535,9 +552,9 @@ class MinerFactory(metaclass=Singleton):
|
|||||||
if len(_ver) > 1:
|
if len(_ver) > 1:
|
||||||
ver = model.split("V")[1]
|
ver = model.split("V")[1]
|
||||||
model = model.split("V")[0]
|
model = model.split("V")[0]
|
||||||
# don't need "Bitmain", just "Antminer XX" as model
|
# don't need "Bitmain", just "ANTMINER XX" as model
|
||||||
if "Bitmain " in model:
|
if "BITMAIN " in model:
|
||||||
model = model.replace("Bitmain ", "")
|
model = model.replace("BITMAIN ", "")
|
||||||
return model, api, ver
|
return model, api, ver
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
31
pyasic/miners/whatsminer/btminer/M2X/M20.py
Normal file
31
pyasic/miners/whatsminer/btminer/M2X/M20.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# 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 BTMiner # noqa - Ignore access to _module
|
||||||
|
from pyasic.miners._types import ( # noqa - Ignore access to _module
|
||||||
|
M20,
|
||||||
|
M20V10,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class BTMinerM20(BTMiner, M20):
|
||||||
|
def __init__(self, ip: str) -> None:
|
||||||
|
super().__init__(ip)
|
||||||
|
self.ip = ip
|
||||||
|
|
||||||
|
|
||||||
|
class BTMinerM20V10(BTMiner, M20V10):
|
||||||
|
def __init__(self, ip: str) -> None:
|
||||||
|
super().__init__(ip)
|
||||||
|
self.ip = ip
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from .M20 import BTMinerM20, BTMinerM20V10
|
||||||
from .M20S import BTMinerM20S, BTMinerM20SV10, BTMinerM20SV20
|
from .M20S import BTMinerM20S, BTMinerM20SV10, BTMinerM20SV20
|
||||||
from .M20S_Plus import BTMinerM20SPlus
|
from .M20S_Plus import BTMinerM20SPlus
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "pyasic"
|
name = "pyasic"
|
||||||
version = "0.13.0"
|
version = "0.14.6"
|
||||||
description = "A set of modules for interfacing with many common types of ASIC bitcoin miners, using both their API and SSH."
|
description = "A set of modules for interfacing with many common types of ASIC bitcoin miners, using both their API and SSH."
|
||||||
authors = ["UpstreamData <brett@upstreamdata.ca>"]
|
authors = ["UpstreamData <brett@upstreamdata.ca>"]
|
||||||
repository = "https://github.com/UpstreamData/pyasic"
|
repository = "https://github.com/UpstreamData/pyasic"
|
||||||
|
|||||||
Reference in New Issue
Block a user