Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d59394b1e | ||
|
|
26c2095ff1 | ||
|
|
ec7d241caa | ||
|
|
d0432ed1aa | ||
|
|
8c5503d002 | ||
|
|
6d6f950c95 | ||
|
|
30745e54ba | ||
|
|
c3fd94e79e | ||
|
|
2924a8d67b | ||
|
|
9f4c4bb9cf | ||
|
|
3d6eebf06e | ||
|
|
b3d9b6ff7e | ||
|
|
60facacc48 | ||
|
|
b8a6063838 | ||
|
|
bcba2be524 | ||
|
|
f7187d2017 | ||
|
|
d91b7c4406 | ||
|
|
248a7e6d69 |
@@ -258,9 +258,12 @@ If you are sure you want to use this command please use API.send_command("{comma
|
|||||||
return False, data["Msg"]
|
return False, data["Msg"]
|
||||||
else:
|
else:
|
||||||
# make sure the command succeeded
|
# make sure the command succeeded
|
||||||
if type(data["STATUS"]) == str:
|
if isinstance(data["STATUS"], str):
|
||||||
if data["STATUS"] in ["RESTART"]:
|
if data["STATUS"] in ["RESTART"]:
|
||||||
return True, None
|
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"):
|
elif data["STATUS"][0]["STATUS"] not in ("S", "I"):
|
||||||
# this is an error
|
# this is an error
|
||||||
if data["STATUS"][0]["STATUS"] not in ("S", "I"):
|
if data["STATUS"][0]["STATUS"] not in ("S", "I"):
|
||||||
|
|||||||
@@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
from dataclasses import asdict, dataclass, field, fields
|
from dataclasses import asdict, dataclass, field, fields
|
||||||
|
|
||||||
C_N_CODES = ["52", "53", "54", "55", "56"]
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class WhatsminerError:
|
class WhatsminerError:
|
||||||
@@ -37,10 +35,8 @@ class WhatsminerError:
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def error_message(self): # noqa - Skip PyCharm inspection
|
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:
|
if len(str(self.error_code)) == 6 and not str(self.error_code)[:1] == "1":
|
||||||
# 55 error code base has chip numbers, so the format is
|
err_type = int(str(self.error_code)[:2])
|
||||||
# 55 -> board num len 1 -> chip num len 3
|
|
||||||
err_type = 55
|
|
||||||
err_subtype = int(str(self.error_code)[2:3])
|
err_subtype = int(str(self.error_code)[2:3])
|
||||||
err_value = int(str(self.error_code)[3:])
|
err_value = int(str(self.error_code)[3:])
|
||||||
else:
|
else:
|
||||||
@@ -88,7 +84,9 @@ class WhatsminerError:
|
|||||||
|
|
||||||
ERROR_CODES = {
|
ERROR_CODES = {
|
||||||
1: { # Fan error
|
1: { # Fan error
|
||||||
0: {0: "Fan unknown."},
|
0: {
|
||||||
|
0: "Fan unknown.",
|
||||||
|
},
|
||||||
1: { # Fan speed error of 1000+
|
1: { # Fan speed error of 1000+
|
||||||
0: "Intake fan speed error.",
|
0: "Intake fan speed error.",
|
||||||
1: "Exhaust 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.",
|
0: "Intake fan speed error. Fan speed deviates by more than 3000.",
|
||||||
1: "Exhaust 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
|
2: { # Power error
|
||||||
0: {
|
0: {
|
||||||
@@ -126,6 +126,7 @@ ERROR_CODES = {
|
|||||||
6: "Power remained unchanged for a long time.",
|
6: "Power remained unchanged for a long time.",
|
||||||
7: "Power set enable error.",
|
7: "Power set enable error.",
|
||||||
8: "Power input voltage is lower than 230V for high power mode.",
|
8: "Power input voltage is lower than 230V for high power mode.",
|
||||||
|
9: "Power input current is incorrect.",
|
||||||
},
|
},
|
||||||
3: {
|
3: {
|
||||||
3: "Power output high temperature protection error.",
|
3: "Power output high temperature protection error.",
|
||||||
@@ -159,6 +160,8 @@ ERROR_CODES = {
|
|||||||
6: {
|
6: {
|
||||||
3: "Power communication warning.",
|
3: "Power communication warning.",
|
||||||
4: "Power communication error.",
|
4: "Power communication error.",
|
||||||
|
5: "Power unknown error.",
|
||||||
|
6: "Power unknown error.",
|
||||||
7: "Power watchdog protection.",
|
7: "Power watchdog protection.",
|
||||||
8: "Power output high current protection.",
|
8: "Power output high current protection.",
|
||||||
9: "Power input high current protection.",
|
9: "Power input high current protection.",
|
||||||
@@ -170,57 +173,134 @@ ERROR_CODES = {
|
|||||||
3: "Power input too high warning.",
|
3: "Power input too high warning.",
|
||||||
4: "Power fan warning.",
|
4: "Power fan warning.",
|
||||||
5: "Power high temperature 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
|
3: { # temperature error
|
||||||
0: { # sensor detection error
|
0: { # sensor detection error
|
||||||
"n": "Slot {n} temperature sensor detection error."
|
"n": "Slot {n} temperature sensor detection error.",
|
||||||
},
|
},
|
||||||
2: { # temperature reading error
|
2: { # temperature reading error
|
||||||
"n": "Slot {n} temperature reading error.",
|
"n": "Slot {n} temperature reading error.",
|
||||||
9: "Control board temperature sensor communication error.",
|
9: "Control board temperature sensor communication error.",
|
||||||
},
|
},
|
||||||
5: {"n": "Slot {n} temperature protecting."}, # temperature protection
|
5: {
|
||||||
6: {0: "Hashboard high temperature error."}, # high temp
|
"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: {
|
8: {
|
||||||
0: "Humidity sensor not found.",
|
0: "Humidity sensor not found.",
|
||||||
1: "Humidity sensor read error.",
|
1: "Humidity sensor read error.",
|
||||||
2: "Humidity sensor read error.",
|
2: "Humidity sensor read error.",
|
||||||
3: "Humidity sensor protecting.",
|
3: "Humidity sensor protecting.",
|
||||||
},
|
}, # humidity
|
||||||
},
|
},
|
||||||
4: { # EEPROM error
|
4: { # EEPROM error
|
||||||
0: {0: "Eeprom unknown error."},
|
0: {
|
||||||
1: {"n": "Slot {n} eeprom detection error."}, # EEPROM detection error
|
0: "Eeprom unknown error.",
|
||||||
2: {"n": "Slot {n} eeprom parsing error."}, # EEPROM parsing error
|
},
|
||||||
3: {"n": "Slot {n} chip bin type error."}, # chip bin error
|
1: {
|
||||||
4: {"n": "Slot {n} eeprom chip number X error."}, # EEPROM chip number error
|
"n": "Slot {n} eeprom detection error.",
|
||||||
5: {"n": "Slot {n} eeprom xfer error."}, # EEPROM xfer 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
|
5: { # hashboard error
|
||||||
0: {0: "Board unknown error."},
|
0: {
|
||||||
1: {"n": "Slot {n} miner type error."}, # board miner type error
|
0: "Board unknown error.",
|
||||||
2: {"n": "Slot {n} bin type error."}, # chip bin type error
|
},
|
||||||
3: {"n": "Slot {n} not found."}, # board not found error
|
1: {
|
||||||
4: {"n": "Slot {n} error reading chip id."}, # reading chip id error
|
"n": "Slot {n} miner type error.",
|
||||||
5: {"n": "Slot {n} has bad chips."}, # board has bad chips error
|
}, # board miner type error
|
||||||
6: {"n": "Slot {n} loss of balance error."}, # loss of balance error
|
2: {
|
||||||
7: {"n": "Slot {n} xfer error chip."}, # xfer error
|
"n": "Slot {n} bin type error.",
|
||||||
8: {"n": "Slot {n} reset error."}, # reset error
|
}, # chip bin type error
|
||||||
9: {"n": "Slot {n} frequency too low."}, # freq 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
|
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
|
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
|
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: {
|
1: {
|
||||||
0: "Control board rebooted as an exception.",
|
0: "Control board rebooted as an exception.",
|
||||||
1: "Control board rebooted as exception and cpufreq reduced, please upgrade the firmware",
|
1: "Control board rebooted as exception and cpufreq reduced, please upgrade the firmware",
|
||||||
2: "Control board rebooted as an exception.",
|
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
|
8: { # checksum error
|
||||||
@@ -228,63 +308,152 @@ ERROR_CODES = {
|
|||||||
0: "CGMiner checksum error.",
|
0: "CGMiner checksum error.",
|
||||||
1: "System monitor checksum error.",
|
1: "System monitor checksum error.",
|
||||||
2: "Remote daemon 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
|
20: { # pool error
|
||||||
1: {0: "All pools are disabled."}, # all disabled error
|
0: {
|
||||||
2: {"n": "Pool {n} connection failed."}, # pool connection failed error
|
0: "No pool information configured.",
|
||||||
3: {0: "High rejection rate on pool."}, # rejection rate 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
|
||||||
4: { # asicboost not supported 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
|
23: { # hashrate error
|
||||||
1: {0: "Hashrate is too low."},
|
1: {
|
||||||
2: {0: "Hashrate is too low."},
|
0: "Hashrate is too low.",
|
||||||
3: {0: "Hashrate loss is too high."},
|
},
|
||||||
4: {0: "Hashrate loss is too high."},
|
2: {
|
||||||
5: {0: "Hashrate loss."},
|
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
|
50: { # water velocity error/voltage error
|
||||||
1: {"n": "Slot {n} chip voltage too low."},
|
1: {
|
||||||
2: {"n": "Slot {n} chip voltage changed."},
|
"n": "Slot {n} chip voltage too low.",
|
||||||
3: {"n": "Slot {n} chip temperature difference is too large."},
|
},
|
||||||
4: {"n": "Slot {n} chip hottest temperature difference is too large."},
|
2: {
|
||||||
7: {"n": "Slot {n} water velocity is abnormal."}, # abnormal water velocity
|
"n": "Slot {n} chip voltage changed.",
|
||||||
8: {0: "Chip temp calibration failed, please restore factory settings."},
|
},
|
||||||
9: {"n": "Slot {n} chip temp calibration check no balance."},
|
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
|
51: { # frequency error
|
||||||
1: {"n": "Slot {n} frequency up timeout."}, # frequency up timeout
|
1: {
|
||||||
7: {"n": "Slot {n} frequency up timeout."}, # frequency up timeout
|
"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: {
|
80: {
|
||||||
0: {0: "The tool version is too low, please update."},
|
0: {
|
||||||
1: {0: "Low freq."},
|
0: "The tool version is too low, please update.",
|
||||||
2: {0: "Low hashrate."},
|
},
|
||||||
3: {5: "High env temp."},
|
1: {
|
||||||
|
0: "Low freq.",
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
0: "Low hashrate.",
|
||||||
|
},
|
||||||
|
3: {
|
||||||
|
5: "High env temp.",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
81: {
|
81: {
|
||||||
0: {0: "Chip data error."},
|
0: {
|
||||||
|
0: "Chip data error.",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
82: {
|
82: {
|
||||||
0: {0: "Power version error."},
|
0: {
|
||||||
1: {0: "Miner type error."},
|
0: "Power version error.",
|
||||||
2: {0: "Version info error."},
|
},
|
||||||
|
1: {
|
||||||
|
0: "Miner type error.",
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
0: "Version info error.",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
83: {
|
83: {
|
||||||
0: {0: "Empty level error."},
|
0: {
|
||||||
|
0: "Empty level error.",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
84: {
|
84: {
|
||||||
0: {0: "Old firmware."},
|
0: {
|
||||||
1: {0: "Software version error."},
|
0: "Old firmware.",
|
||||||
|
},
|
||||||
|
1: {
|
||||||
|
0: "Software version error.",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
85: {
|
85: {
|
||||||
"n": {
|
"n": {
|
||||||
@@ -296,8 +465,12 @@ ERROR_CODES = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
86: {
|
86: {
|
||||||
0: {0: "Missing product serial #."},
|
0: {
|
||||||
1: {0: "Missing product type."},
|
0: "Missing product serial #.",
|
||||||
|
},
|
||||||
|
1: {
|
||||||
|
0: "Missing product type.",
|
||||||
|
},
|
||||||
2: {
|
2: {
|
||||||
0: "Missing miner serial #.",
|
0: "Missing miner serial #.",
|
||||||
1: "Wrong miner serial # length.",
|
1: "Wrong miner serial # length.",
|
||||||
@@ -314,12 +487,34 @@ ERROR_CODES = {
|
|||||||
3: "Wrong power model rate.",
|
3: "Wrong power model rate.",
|
||||||
4: "Wrong power model format.",
|
4: "Wrong power model format.",
|
||||||
},
|
},
|
||||||
5: {0: "Wrong hash board struct."},
|
5: {
|
||||||
6: {0: "Wrong miner cooling type."},
|
0: "Wrong hash board struct.",
|
||||||
7: {0: "Missing PCB serial #."},
|
},
|
||||||
|
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: {
|
1000: {
|
||||||
0: {
|
0: {
|
||||||
0: "Security library error, please upgrade firmware",
|
0: "Security library error, please upgrade firmware",
|
||||||
@@ -328,7 +523,11 @@ ERROR_CODES = {
|
|||||||
3: "/antiv/dig/pf_partial.dig illegal.",
|
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: {
|
1100: {
|
||||||
0: {
|
0: {
|
||||||
0: "Security illegal file, please upgrade firmware.",
|
0: "Security illegal file, please upgrade firmware.",
|
||||||
|
|||||||
@@ -235,7 +235,20 @@ class BMMiner(BaseMiner):
|
|||||||
if board_offset == -1:
|
if board_offset == -1:
|
||||||
board_offset = 1
|
board_offset = 1
|
||||||
|
|
||||||
for i in range(board_offset, board_offset + self.ideal_hashboards):
|
real_slots = []
|
||||||
|
|
||||||
|
for i in range(board_offset, board_offset + 4):
|
||||||
|
try:
|
||||||
|
key = f'chain_acs{i}'
|
||||||
|
if boards[1].get(key, '') != '':
|
||||||
|
real_slots.append(i)
|
||||||
|
except LookupError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if len(real_slots) < 3:
|
||||||
|
real_slots = list(range(board_offset, board_offset + self.ideal_hashboards))
|
||||||
|
|
||||||
|
for i in real_slots:
|
||||||
hashboard = HashBoard(
|
hashboard = HashBoard(
|
||||||
slot=i - board_offset, expected_chips=self.nominal_chips
|
slot=i - board_offset, expected_chips=self.nominal_chips
|
||||||
)
|
)
|
||||||
@@ -259,7 +272,7 @@ class BMMiner(BaseMiner):
|
|||||||
if (not chips) or (not chips > 0):
|
if (not chips) or (not chips > 0):
|
||||||
hashboard.missing = True
|
hashboard.missing = True
|
||||||
hashboards.append(hashboard)
|
hashboards.append(hashboard)
|
||||||
except (IndexError, KeyError, ValueError, TypeError):
|
except (LookupError, ValueError, TypeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return hashboards
|
return hashboards
|
||||||
|
|||||||
@@ -179,11 +179,12 @@ class CGMinerAvalon(CGMiner):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
async def get_hostname(self, mac: str = None) -> Optional[str]:
|
async def get_hostname(self, mac: str = None) -> Optional[str]:
|
||||||
if not mac:
|
return None
|
||||||
mac = await self.get_mac()
|
# if not mac:
|
||||||
|
# mac = await self.get_mac()
|
||||||
if mac:
|
#
|
||||||
return f"Avalon{mac.replace(':', '')[-6:]}"
|
# if mac:
|
||||||
|
# return f"Avalon{mac.replace(':', '')[-6:]}"
|
||||||
|
|
||||||
async def get_hashrate(self, api_devs: dict = None) -> Optional[float]:
|
async def get_hashrate(self, api_devs: dict = None) -> Optional[float]:
|
||||||
if not api_devs:
|
if not api_devs:
|
||||||
|
|||||||
@@ -413,21 +413,29 @@ class BaseMiner(ABC):
|
|||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def _get_data(self, allow_warning: bool, data_to_get: list = None) -> dict:
|
async def _get_data(
|
||||||
if not data_to_get:
|
self, allow_warning: bool, include: list = None, exclude: list = None
|
||||||
|
) -> dict:
|
||||||
|
if include is None:
|
||||||
# everything
|
# everything
|
||||||
data_to_get = list(self.data_locations.keys())
|
include = list(self.data_locations.keys())
|
||||||
|
|
||||||
|
if exclude is not None:
|
||||||
|
for item in exclude:
|
||||||
|
if item in include:
|
||||||
|
include.remove(item)
|
||||||
|
|
||||||
api_multicommand = set()
|
api_multicommand = set()
|
||||||
web_multicommand = set()
|
web_multicommand = []
|
||||||
for data_name in data_to_get:
|
for data_name in include:
|
||||||
try:
|
try:
|
||||||
fn_args = self.data_locations[data_name]["kwargs"]
|
fn_args = self.data_locations[data_name]["kwargs"]
|
||||||
for arg_name in fn_args:
|
for arg_name in fn_args:
|
||||||
if fn_args[arg_name].get("api"):
|
if fn_args[arg_name].get("api"):
|
||||||
api_multicommand.add(fn_args[arg_name]["api"])
|
api_multicommand.add(fn_args[arg_name]["api"])
|
||||||
if fn_args[arg_name].get("web"):
|
if fn_args[arg_name].get("web"):
|
||||||
web_multicommand.add(fn_args[arg_name]["web"])
|
if not fn_args[arg_name]["web"] in web_multicommand:
|
||||||
|
web_multicommand.append(fn_args[arg_name]["web"])
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
logger.error(e, data_name)
|
logger.error(e, data_name)
|
||||||
continue
|
continue
|
||||||
@@ -445,8 +453,6 @@ class BaseMiner(ABC):
|
|||||||
else:
|
else:
|
||||||
web_command_task = asyncio.sleep(0)
|
web_command_task = asyncio.sleep(0)
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
web_command_data = await web_command_task
|
web_command_data = await web_command_task
|
||||||
if web_command_data is None:
|
if web_command_data is None:
|
||||||
web_command_data = {}
|
web_command_data = {}
|
||||||
@@ -457,7 +463,7 @@ class BaseMiner(ABC):
|
|||||||
|
|
||||||
miner_data = {}
|
miner_data = {}
|
||||||
|
|
||||||
for data_name in data_to_get:
|
for data_name in include:
|
||||||
try:
|
try:
|
||||||
fn_args = self.data_locations[data_name]["kwargs"]
|
fn_args = self.data_locations[data_name]["kwargs"]
|
||||||
args_to_send = {k: None for k in fn_args}
|
args_to_send = {k: None for k in fn_args}
|
||||||
@@ -511,13 +517,14 @@ class BaseMiner(ABC):
|
|||||||
return miner_data
|
return miner_data
|
||||||
|
|
||||||
async def get_data(
|
async def get_data(
|
||||||
self, allow_warning: bool = False, data_to_get: list = None
|
self, allow_warning: bool = False, include: list = None, exclude: list = None
|
||||||
) -> MinerData:
|
) -> MinerData:
|
||||||
"""Get data from the miner in the form of [`MinerData`][pyasic.data.MinerData].
|
"""Get data from the miner in the form of [`MinerData`][pyasic.data.MinerData].
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
allow_warning: Allow warning when an API command fails.
|
allow_warning: Allow warning when an API command fails.
|
||||||
data_to_get: Names of data items you want to gather. Defaults to all data.
|
include: Names of data items you want to gather. Defaults to all data.
|
||||||
|
exclude: Names of data items to exclude. Exclusion happens after considering included items.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
A [`MinerData`][pyasic.data.MinerData] instance containing data from the miner.
|
A [`MinerData`][pyasic.data.MinerData] instance containing data from the miner.
|
||||||
@@ -533,7 +540,9 @@ class BaseMiner(ABC):
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
gathered_data = await self._get_data(allow_warning, data_to_get=data_to_get)
|
gathered_data = await self._get_data(
|
||||||
|
allow_warning, include=include, exclude=exclude
|
||||||
|
)
|
||||||
for item in gathered_data:
|
for item in gathered_data:
|
||||||
if gathered_data[item] is not None:
|
if gathered_data[item] is not None:
|
||||||
setattr(data, item, gathered_data[item])
|
setattr(data, item, gathered_data[item])
|
||||||
|
|||||||
@@ -486,7 +486,7 @@ class MinerFactory:
|
|||||||
"location", ""
|
"location", ""
|
||||||
):
|
):
|
||||||
return MinerTypes.WHATSMINER
|
return MinerTypes.WHATSMINER
|
||||||
if "Braiins OS" in web_text or 'href="/cgi-bin/luci"' in web_text:
|
if "Braiins OS" in web_text:
|
||||||
return MinerTypes.BRAIINS_OS
|
return MinerTypes.BRAIINS_OS
|
||||||
if "cloud-box" in web_text:
|
if "cloud-box" in web_text:
|
||||||
return MinerTypes.GOLDSHELL
|
return MinerTypes.GOLDSHELL
|
||||||
@@ -775,15 +775,13 @@ class MinerFactory:
|
|||||||
f"http://{ip}/api/auth",
|
f"http://{ip}/api/auth",
|
||||||
data={"username": "admin", "password": "admin"},
|
data={"username": "admin", "password": "admin"},
|
||||||
)
|
)
|
||||||
auth = (await auth_req.json())["jwt"]
|
auth = auth_req.json()["jwt"]
|
||||||
|
|
||||||
web_data = await (
|
web_data = (await session.post(
|
||||||
await session.post(
|
|
||||||
f"http://{ip}/api/type",
|
f"http://{ip}/api/type",
|
||||||
headers={"Authorization": "Bearer " + auth},
|
headers={"Authorization": "Bearer " + auth},
|
||||||
data={},
|
data={},
|
||||||
)
|
)).json()
|
||||||
).json()
|
|
||||||
return web_data["type"]
|
return web_data["type"]
|
||||||
except (httpx.HTTPError, LookupError):
|
except (httpx.HTTPError, LookupError):
|
||||||
pass
|
pass
|
||||||
@@ -806,7 +804,7 @@ class MinerFactory:
|
|||||||
json={"query": "{bosminer {info{modelName}}}"},
|
json={"query": "{bosminer {info{modelName}}}"},
|
||||||
)
|
)
|
||||||
if d.status_code == 200:
|
if d.status_code == 200:
|
||||||
json_data = await d.json()
|
json_data = d.json()
|
||||||
miner_model = json_data["data"]["bosminer"]["info"]["modelName"]
|
miner_model = json_data["data"]["bosminer"]["info"]["modelName"]
|
||||||
return miner_model
|
return miner_model
|
||||||
except (httpx.HTTPError, LookupError):
|
except (httpx.HTTPError, LookupError):
|
||||||
|
|||||||
@@ -24,8 +24,5 @@ class M29V10(WhatsMiner): # noqa - ignore ABC method implementation
|
|||||||
super().__init__(ip, api_ver)
|
super().__init__(ip, api_ver)
|
||||||
self.ip = ip
|
self.ip = ip
|
||||||
self.model = "M29 V10"
|
self.model = "M29 V10"
|
||||||
self.nominal_chips = 0
|
self.nominal_chips = 50
|
||||||
warnings.warn(
|
|
||||||
"Unknown chip count for miner type M29V10, please open an issue on GitHub (https://github.com/UpstreamData/pyasic)."
|
|
||||||
)
|
|
||||||
self.fan_count = 2
|
self.fan_count = 2
|
||||||
|
|||||||
@@ -165,10 +165,7 @@ class M30SPlusVE50(WhatsMiner): # noqa - ignore ABC method implementation
|
|||||||
super().__init__(ip, api_ver)
|
super().__init__(ip, api_ver)
|
||||||
self.ip = ip
|
self.ip = ip
|
||||||
self.model = "M30S+ VE50"
|
self.model = "M30S+ VE50"
|
||||||
self.nominal_chips = 0
|
self.nominal_chips = 164
|
||||||
warnings.warn(
|
|
||||||
"Unknown chip count for miner type M30S+ VE50, please open an issue on GitHub (https://github.com/UpstreamData/pyasic)."
|
|
||||||
)
|
|
||||||
self.fan_count = 2
|
self.fan_count = 2
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "pyasic"
|
name = "pyasic"
|
||||||
version = "0.37.5"
|
version = "0.38.3"
|
||||||
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