diff --git a/pyasic/config/__init__.py b/pyasic/config/__init__.py index fff5d863..a7a67e46 100644 --- a/pyasic/config/__init__.py +++ b/pyasic/config/__init__.py @@ -91,20 +91,7 @@ class _Pool: pool = {"url": self.url, "user": username, "pass": self.password} return pool - def as_x15(self, user_suffix: str = None) -> dict: - """Convert the data in this class to a dict usable by an X15 device. - - Parameters: - user_suffix: The suffix to append to username. - """ - username = self.username - if user_suffix: - username = f"{username}{user_suffix}" - - pool = {"url": self.url, "user": username, "pass": self.password} - return pool - - def as_x5(self, user_suffix: str = None) -> dict: + def as_x17(self, user_suffix: str = None) -> dict: """Convert the data in this class to a dict usable by an X5 device. Parameters: @@ -227,33 +214,8 @@ class _PoolGroup: pools.append(pool.as_x19(user_suffix=user_suffix)) return pools - def as_x15(self, user_suffix: str = None) -> dict: - """Convert the data in this class to a list usable by an X15 device. - Parameters: - user_suffix: The suffix to append to username. - """ - pools = { - "_ant_pool1url": "", - "_ant_pool1user": "", - "_ant_pool1pw": "", - "_ant_pool2url": "", - "_ant_pool2user": "", - "_ant_pool2pw": "", - "_ant_pool3url": "", - "_ant_pool3user": "", - "_ant_pool3pw": "", - } - for idx, pool in enumerate(self.pools[:3]): - pools[f"_ant_pool{idx+1}url"] = pool.as_x15(user_suffix=user_suffix)["url"] - pools[f"_ant_pool{idx+1}user"] = pool.as_x15(user_suffix=user_suffix)[ - "user" - ] - pools[f"_ant_pool{idx+1}pw"] = pool.as_x15(user_suffix=user_suffix)["pass"] - - return pools - - def as_x5(self, user_suffix: str = None) -> dict: + def as_x17(self, user_suffix: str = None) -> dict: """Convert the data in this class to a list usable by an X5 device. Parameters: @@ -271,9 +233,9 @@ class _PoolGroup: "_ant_pool3pw": "", } for idx, pool in enumerate(self.pools[:3]): - pools[f"_ant_pool{idx+1}url"] = pool.as_x5(user_suffix=user_suffix)["url"] - pools[f"_ant_pool{idx+1}user"] = pool.as_x5(user_suffix=user_suffix)["user"] - pools[f"_ant_pool{idx+1}pw"] = pool.as_x5(user_suffix=user_suffix)["pass"] + pools[f"_ant_pool{idx+1}url"] = pool.as_x17(user_suffix=user_suffix)["url"] + pools[f"_ant_pool{idx+1}user"] = pool.as_x17(user_suffix=user_suffix)["user"] + pools[f"_ant_pool{idx+1}pw"] = pool.as_x17(user_suffix=user_suffix)["pass"] return pools @@ -598,23 +560,13 @@ class MinerConfig: return cfg - def as_x15(self, user_suffix: str = None) -> dict: - """Convert the data in this class to a config usable by an X15 device. - - Parameters: - user_suffix: The suffix to append to username. - """ - cfg = self.pool_groups[0].as_x15(user_suffix=user_suffix) - - return cfg - - def as_x5(self, user_suffix: str = None) -> dict: + def as_x17(self, user_suffix: str = None) -> dict: """Convert the data in this class to a config usable by an X5 device. Parameters: user_suffix: The suffix to append to username. """ - cfg = self.pool_groups[0].as_x5(user_suffix=user_suffix) + cfg = self.pool_groups[0].as_x17(user_suffix=user_suffix) return cfg diff --git a/pyasic/data/__init__.py b/pyasic/data/__init__.py index 6a8e6f8b..bfaab8a7 100644 --- a/pyasic/data/__init__.py +++ b/pyasic/data/__init__.py @@ -259,8 +259,9 @@ class MinerData: @property def left_chips(self): # noqa - Skip PyCharm inspection - if len(self.hashboards) in [2, 3]: + if len(self.hashboards) in [2, 3, 4]: return self.hashboards[0].chips + return 0 @left_chips.setter @@ -271,7 +272,7 @@ class MinerData: def center_chips(self): # noqa - Skip PyCharm inspection if len(self.hashboards) == 1: return self.hashboards[0].chips - if len(self.hashboards) == 3: + if len(self.hashboards) in [2, 3, 4]: return self.hashboards[1].chips return 0 @@ -285,6 +286,8 @@ class MinerData: 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 @@ -293,7 +296,7 @@ class MinerData: @property def left_board_hashrate(self): # noqa - Skip PyCharm inspection - if len(self.hashboards) in [2, 3]: + if len(self.hashboards) in [2, 3, 4]: return self.hashboards[0].hashrate return 0 @@ -305,7 +308,7 @@ class MinerData: def center_board_hashrate(self): # noqa - Skip PyCharm inspection if len(self.hashboards) == 1: return self.hashboards[0].hashrate - if len(self.hashboards) == 3: + if len(self.hashboards) in [2, 3, 4]: return self.hashboards[1].hashrate return 0 @@ -319,6 +322,8 @@ class MinerData: 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 @@ -327,7 +332,7 @@ class MinerData: @property def left_board_temp(self): # noqa - Skip PyCharm inspection - if len(self.hashboards) in [2, 3]: + if len(self.hashboards) in [2, 3, 4]: return self.hashboards[0].temp return 0 @@ -339,7 +344,7 @@ class MinerData: def center_board_temp(self): # noqa - Skip PyCharm inspection if len(self.hashboards) == 1: return self.hashboards[0].temp - if len(self.hashboards) == 3: + if len(self.hashboards) in [2, 3, 4]: return self.hashboards[1].temp return 0 @@ -353,6 +358,8 @@ class MinerData: 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 @@ -361,7 +368,7 @@ class MinerData: @property def left_board_chip_temp(self): # noqa - Skip PyCharm inspection - if len(self.hashboards) in [2, 3]: + if len(self.hashboards) in [2, 3, 4]: return self.hashboards[0].chip_temp return 0 @@ -373,7 +380,7 @@ class MinerData: 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) == 3: + if len(self.hashboards) in [2, 3, 4]: return self.hashboards[1].chip_temp return 0 @@ -387,6 +394,8 @@ class MinerData: 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 diff --git a/pyasic/miners/ckb/_backends/goldshell.py b/pyasic/miners/ckb/_backends/goldshell.py index 3e42ca00..87c722da 100644 --- a/pyasic/miners/ckb/_backends/goldshell.py +++ b/pyasic/miners/ckb/_backends/goldshell.py @@ -75,7 +75,7 @@ class Goldshell(BFGMiner): except KeyError: pass - async def get_hashboards(self, api_devs: dict = None) -> List[HashBoard]: + async def get_hashboards(self, api_devs: dict = None, api_devdetails: dict = None) -> List[HashBoard]: if not api_devs: try: api_devs = await self.api.devs() @@ -89,7 +89,7 @@ class Goldshell(BFGMiner): if api_devs: for board in api_devs["DEVS"]: - if board.get("ID"): + if board.get("ID") is not None: try: b_id = board["ID"] hashboards[b_id].hashrate = round(board["MHS 20s"] / 1000000, 2) @@ -98,4 +98,19 @@ class Goldshell(BFGMiner): except KeyError: pass + if not api_devdetails: + try: + api_devdetails = await self.api.devdetails() + except APIError: + pass + + if api_devdetails: + for board in api_devdetails["DEVS"]: + if board.get("ID") is not None: + try: + b_id = board["ID"] + hashboards[b_id].chips = board["chips-nr"] + except KeyError: + pass + return hashboards diff --git a/pyasic/miners/ckb/_types/goldshell/CK5.py b/pyasic/miners/ckb/_types/goldshell/CK5.py index 809cd386..16a28278 100644 --- a/pyasic/miners/ckb/_types/goldshell/CK5.py +++ b/pyasic/miners/ckb/_types/goldshell/CK5.py @@ -22,5 +22,5 @@ class CK5(GoldshellMiner): # noqa - ignore ABC method implementation self.ip = ip self.model = "CK5" self.ideal_hashboards = 4 - self.chip_count = 18 + self.nominal_chips = 46 self.fan_count = 4 diff --git a/pyasic/miners/dcr/_backends/X5.py b/pyasic/miners/dcr/_backends/X5.py index c331e672..f5ead4bb 100644 --- a/pyasic/miners/dcr/_backends/X5.py +++ b/pyasic/miners/dcr/_backends/X5.py @@ -20,14 +20,14 @@ from pyasic.config import MinerConfig from pyasic.data import Fan, HashBoard from pyasic.errors import APIError from pyasic.miners.zec._backends import CGMiner # noqa - Ignore access to _module -from pyasic.web.X5 import X5WebAPI +from pyasic.web.X17 import X17WebAPI class X5(CGMiner): def __init__(self, ip: str, api_ver: str = "0.0.0") -> None: super().__init__(ip, api_ver=api_ver) self.ip = ip - self.web = X5WebAPI(ip) + self.web = X17WebAPI(ip) async def get_config(self) -> MinerConfig: data = await self.web.get_miner_conf() @@ -36,7 +36,7 @@ class X5(CGMiner): return self.config async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None: - await self.web.set_miner_conf(config.as_x5(user_suffix=user_suffix)) + await self.web.set_miner_conf(config.as_x17(user_suffix=user_suffix)) async def get_mac(self) -> Union[str, None]: try: diff --git a/pyasic/miners/etc/__init__.py b/pyasic/miners/etc/__init__.py index 75f27e83..4022cf8f 100644 --- a/pyasic/miners/etc/__init__.py +++ b/pyasic/miners/etc/__init__.py @@ -14,3 +14,4 @@ # limitations under the License. - # ------------------------------------------------------------------------------ from .innosilicon import * +from .antminer import * \ No newline at end of file diff --git a/pyasic/miners/etc/_backends/X9.py b/pyasic/miners/etc/_backends/X9.py new file mode 100644 index 00000000..119a74fa --- /dev/null +++ b/pyasic/miners/etc/_backends/X9.py @@ -0,0 +1,205 @@ +# ------------------------------------------------------------------------------ +# 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 List, Optional, Union + +from pyasic.config import MinerConfig +from pyasic.data import Fan, HashBoard +from pyasic.errors import APIError +from pyasic.miners.etc._backends import CGMiner # noqa - Ignore access to _module +from pyasic.web.X19 import X19WebAPI + + +class X9(CGMiner): + def __init__(self, ip: str, api_ver: str = "0.0.0") -> None: + super().__init__(ip, api_ver=api_ver) + self.ip = ip + self.web = X19WebAPI(ip) + + async def get_config(self) -> MinerConfig: + data = await self.web.get_miner_conf() + if data: + self.config = MinerConfig().from_raw(data) + return self.config + + async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None: + await self.web.set_miner_conf(config.as_x19(user_suffix=user_suffix)) + + async def get_mac(self) -> Union[str, None]: + try: + data = await self.web.get_system_info() + if data: + return data["macaddr"] + except KeyError: + pass + + async def restart_backend(self) -> bool: + return False + + async def fault_light_on(self) -> bool: + # this should time out, after it does do a check + await self.web.blink(blink=True) + try: + data = await self.web.get_blink_status() + if data: + if data["isBlinking"]: + self.light = True + except KeyError: + pass + return self.light + + async def fault_light_off(self) -> bool: + await self.web.blink(blink=False) + try: + data = await self.web.get_blink_status() + if data: + if not data["isBlinking"]: + self.light = False + except KeyError: + pass + return self.light + + async def reboot(self) -> bool: + data = await self.web.reboot() + if data: + return True + return False + + async def get_fault_light(self, web_get_blink_status: dict = None) -> bool: + if self.light: + return self.light + + if not web_get_blink_status: + try: + web_get_blink_status = await self.web.get_blink_status() + except APIError: + pass + + if web_get_blink_status: + try: + self.light = web_get_blink_status["isBlinking"] + except KeyError: + pass + return self.light + + async def get_hostname(self, web_get_system_info: dict = None) -> Optional[str]: + if not web_get_system_info: + try: + web_get_system_info = await self.web.get_system_info() + except APIError: + pass + + if web_get_system_info: + try: + return web_get_system_info["hostname"] + except KeyError: + pass + + async def get_model(self, web_get_system_info: dict = None) -> Optional[str]: + if self.model: + return self.model + + if not web_get_system_info: + try: + web_get_system_info = await self.web.get_system_info() + except APIError: + pass + + if web_get_system_info: + try: + return web_get_system_info["minertype"] + except APIError: + pass + + async def get_fans(self, api_stats: dict = None) -> List[Fan]: + if not api_stats: + try: + api_stats = await self.api.stats() + except APIError: + pass + + fans_data = [Fan(), Fan(), Fan(), Fan()] + if api_stats: + try: + fan_offset = -1 + + for fan_num in range(1, 8, 4): + for _f_num in range(4): + f = api_stats["STATS"][1].get(f"fan{fan_num + _f_num}") + if f and not f == 0 and fan_offset == -1: + fan_offset = fan_num + 2 + if fan_offset == -1: + fan_offset = 3 + + for fan in range(self.fan_count): + fans_data[fan] = Fan( + api_stats["STATS"][1].get(f"fan{fan_offset+fan}") + ) + except (KeyError, IndexError): + pass + return fans_data + + async def get_hashboards(self, api_stats: dict = None) -> List[HashBoard]: + hashboards = [] + + if not api_stats: + try: + api_stats = await self.api.stats() + except APIError: + pass + + if api_stats: + try: + board_offset = -1 + boards = api_stats["STATS"] + if len(boards) > 1: + for board_num in range(1, 16, 5): + for _b_num in range(5): + b = boards[1].get(f"chain_acn{board_num + _b_num}") + + if b and not b == 0 and board_offset == -1: + board_offset = board_num + if board_offset == -1: + board_offset = 1 + + for i in range(board_offset, board_offset + self.ideal_hashboards): + hashboard = HashBoard( + slot=i - board_offset, expected_chips=self.nominal_chips + ) + + chip_temp = boards[1].get(f"temp{i}") + if chip_temp: + hashboard.chip_temp = round(chip_temp) + + temp = boards[1].get(f"temp2_{i}") + if temp: + hashboard.temp = round(temp) + + hashrate = boards[1].get(f"chain_rate{i}") + if hashrate: + hashboard.hashrate = round(float(hashrate) / 1000, 2) + + chips = boards[1].get(f"chain_acn{i}") + if chips: + hashboard.chips = chips + hashboard.missing = False + if (not chips) or (not chips > 0): + hashboard.missing = True + hashboards.append(hashboard) + except (IndexError, KeyError, ValueError, TypeError): + pass + + return hashboards diff --git a/pyasic/miners/etc/_backends/__init__.py b/pyasic/miners/etc/_backends/__init__.py index 700b7980..e56065e6 100644 --- a/pyasic/miners/etc/_backends/__init__.py +++ b/pyasic/miners/etc/_backends/__init__.py @@ -13,5 +13,5 @@ # See the License for the specific language governing permissions and - # limitations under the License. - # ------------------------------------------------------------------------------ - from .cgminer import CGMiner +from .X9 import X9 \ No newline at end of file diff --git a/pyasic/miners/etc/_types/__init__.py b/pyasic/miners/etc/_types/__init__.py index 64091897..9f8937dc 100644 --- a/pyasic/miners/etc/_types/__init__.py +++ b/pyasic/miners/etc/_types/__init__.py @@ -13,5 +13,5 @@ # See the License for the specific language governing permissions and - # limitations under the License. - # ------------------------------------------------------------------------------ - from .innosilicon import * +from .antminer import * diff --git a/pyasic/miners/etc/_types/antminer/X9/E9_Pro.py b/pyasic/miners/etc/_types/antminer/X9/E9_Pro.py new file mode 100644 index 00000000..98b3b3d1 --- /dev/null +++ b/pyasic/miners/etc/_types/antminer/X9/E9_Pro.py @@ -0,0 +1,27 @@ +# ------------------------------------------------------------------------------ +# 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.makes import AntMiner + + +class E9Pro(AntMiner): # noqa - ignore ABC method implementation + def __init__(self, ip: str): + super().__init__() + self.ip = ip + self.model = "E9Pro" + self.nominal_chips = 8 + self.ideal_hashboards = 2 + self.fan_count = 4 diff --git a/pyasic/miners/etc/_types/antminer/X9/__init__.py b/pyasic/miners/etc/_types/antminer/X9/__init__.py new file mode 100644 index 00000000..b2daa9d8 --- /dev/null +++ b/pyasic/miners/etc/_types/antminer/X9/__init__.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------------------ +# 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 .E9_Pro import E9Pro diff --git a/pyasic/miners/etc/_types/antminer/__init__.py b/pyasic/miners/etc/_types/antminer/__init__.py new file mode 100644 index 00000000..27ba91cc --- /dev/null +++ b/pyasic/miners/etc/_types/antminer/__init__.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------------------ +# 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 .X9 import * diff --git a/pyasic/miners/etc/antminer/__init__.py b/pyasic/miners/etc/antminer/__init__.py new file mode 100644 index 00000000..10eb58cb --- /dev/null +++ b/pyasic/miners/etc/antminer/__init__.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------------------ +# 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 .cgminer import * diff --git a/pyasic/miners/etc/antminer/cgminer/X9/E9_Pro.py b/pyasic/miners/etc/antminer/cgminer/X9/E9_Pro.py new file mode 100644 index 00000000..b45dca82 --- /dev/null +++ b/pyasic/miners/etc/antminer/cgminer/X9/E9_Pro.py @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------------ +# 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.etc._backends import X9 # noqa - Ignore access to _module +from pyasic.miners.etc._types import E9Pro # noqa - Ignore access to _module + +class CGMinerE9Pro(X9, E9Pro): + pass diff --git a/pyasic/miners/etc/antminer/cgminer/X9/__init__.py b/pyasic/miners/etc/antminer/cgminer/X9/__init__.py new file mode 100644 index 00000000..751c841c --- /dev/null +++ b/pyasic/miners/etc/antminer/cgminer/X9/__init__.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------------------ +# 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 .E9_Pro import CGMinerE9Pro diff --git a/pyasic/miners/etc/antminer/cgminer/__init__.py b/pyasic/miners/etc/antminer/cgminer/__init__.py new file mode 100644 index 00000000..27ba91cc --- /dev/null +++ b/pyasic/miners/etc/antminer/cgminer/__init__.py @@ -0,0 +1,16 @@ +# ------------------------------------------------------------------------------ +# 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 .X9 import * diff --git a/pyasic/miners/hns/_backends/X3.py b/pyasic/miners/hns/_backends/X3.py index 1be35471..7c0f29b8 100644 --- a/pyasic/miners/hns/_backends/X3.py +++ b/pyasic/miners/hns/_backends/X3.py @@ -20,14 +20,14 @@ from pyasic.config import MinerConfig from pyasic.data import Fan, HashBoard from pyasic.errors import APIError from pyasic.miners.hns._backends import CGMiner # noqa - Ignore access to _module -from pyasic.web.X3 import X3WebAPI +from pyasic.web.X19 import X19WebAPI class X3(CGMiner): def __init__(self, ip: str, api_ver: str = "0.0.0") -> None: super().__init__(ip, api_ver=api_ver) self.ip = ip - self.web = X3WebAPI(ip) + self.web = X19WebAPI(ip) async def get_config(self) -> MinerConfig: data = await self.web.get_miner_conf() @@ -36,7 +36,7 @@ class X3(CGMiner): return self.config async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None: - await self.web.set_miner_conf(config.as_x5(user_suffix=user_suffix)) + await self.web.set_miner_conf(config.as_x19(user_suffix=user_suffix)) async def get_mac(self) -> Union[str, None]: try: diff --git a/pyasic/miners/hns/_backends/goldshell.py b/pyasic/miners/hns/_backends/goldshell.py index 3df52ba3..150d36e8 100644 --- a/pyasic/miners/hns/_backends/goldshell.py +++ b/pyasic/miners/hns/_backends/goldshell.py @@ -76,7 +76,7 @@ class Goldshell(BFGMiner): except KeyError: pass - async def get_hashboards(self, api_devs: dict = None) -> List[HashBoard]: + async def get_hashboards(self, api_devs: dict = None, api_devdetails: dict = None) -> List[HashBoard]: if not api_devs: try: api_devs = await self.api.devs() @@ -90,7 +90,7 @@ class Goldshell(BFGMiner): if api_devs: for board in api_devs["DEVS"]: - if board.get("ID"): + if board.get("ID") is not None: try: b_id = board["ID"] hashboards[b_id].hashrate = round(board["MHS 20s"] / 1000000, 2) @@ -99,4 +99,19 @@ class Goldshell(BFGMiner): except KeyError: pass + if not api_devdetails: + try: + api_devdetails = await self.api.devdetails() + except APIError: + pass + + if api_devdetails: + for board in api_devdetails["DEVS"]: + if board.get("ID") is not None: + try: + b_id = board["ID"] + hashboards[b_id].chips = board["chips-nr"] + except KeyError: + pass + return hashboards diff --git a/pyasic/miners/hns/_types/antminer/X3/HS3.py b/pyasic/miners/hns/_types/antminer/X3/HS3.py index 3685d3a3..4b65ecd9 100644 --- a/pyasic/miners/hns/_types/antminer/X3/HS3.py +++ b/pyasic/miners/hns/_types/antminer/X3/HS3.py @@ -22,6 +22,6 @@ class HS3(AntMiner): # noqa - ignore ABC method implementation super().__init__() self.ip = ip self.model = "HS3" - self.nominal_chips = 72 + self.nominal_chips = 92 self.ideal_hashboards = 3 self.fan_count = 2 diff --git a/pyasic/miners/hns/_types/goldshell/HS5.py b/pyasic/miners/hns/_types/goldshell/HS5.py index e4b3d782..a2837cb7 100644 --- a/pyasic/miners/hns/_types/goldshell/HS5.py +++ b/pyasic/miners/hns/_types/goldshell/HS5.py @@ -22,5 +22,5 @@ class HS5(GoldshellMiner): # noqa - ignore ABC method implementation self.ip = ip self.model = "HS5" self.ideal_hashboards = 4 - self.chip_count = 18 + self.nominal_chips = 46 self.fan_count = 4 diff --git a/pyasic/miners/kda/_backends/goldshell.py b/pyasic/miners/kda/_backends/goldshell.py index 3df52ba3..150d36e8 100644 --- a/pyasic/miners/kda/_backends/goldshell.py +++ b/pyasic/miners/kda/_backends/goldshell.py @@ -76,7 +76,7 @@ class Goldshell(BFGMiner): except KeyError: pass - async def get_hashboards(self, api_devs: dict = None) -> List[HashBoard]: + async def get_hashboards(self, api_devs: dict = None, api_devdetails: dict = None) -> List[HashBoard]: if not api_devs: try: api_devs = await self.api.devs() @@ -90,7 +90,7 @@ class Goldshell(BFGMiner): if api_devs: for board in api_devs["DEVS"]: - if board.get("ID"): + if board.get("ID") is not None: try: b_id = board["ID"] hashboards[b_id].hashrate = round(board["MHS 20s"] / 1000000, 2) @@ -99,4 +99,19 @@ class Goldshell(BFGMiner): except KeyError: pass + if not api_devdetails: + try: + api_devdetails = await self.api.devdetails() + except APIError: + pass + + if api_devdetails: + for board in api_devdetails["DEVS"]: + if board.get("ID") is not None: + try: + b_id = board["ID"] + hashboards[b_id].chips = board["chips-nr"] + except KeyError: + pass + return hashboards diff --git a/pyasic/miners/kda/_types/goldshell/KD5.py b/pyasic/miners/kda/_types/goldshell/KD5.py index d0bb5961..bdc2488a 100644 --- a/pyasic/miners/kda/_types/goldshell/KD5.py +++ b/pyasic/miners/kda/_types/goldshell/KD5.py @@ -22,5 +22,5 @@ class KD5(GoldshellMiner): # noqa - ignore ABC method implementation self.ip = ip self.model = "KD5" self.ideal_hashboards = 4 - self.chip_count = 18 + self.nominal_chips = 46 self.fan_count = 4 diff --git a/pyasic/miners/kda/_types/goldshell/KDMax.py b/pyasic/miners/kda/_types/goldshell/KDMax.py index 354e46db..479639ac 100644 --- a/pyasic/miners/kda/_types/goldshell/KDMax.py +++ b/pyasic/miners/kda/_types/goldshell/KDMax.py @@ -21,6 +21,6 @@ class KDMax(GoldshellMiner): # noqa - ignore ABC method implementation super().__init__() self.ip = ip self.model = "KD Max" - self.ideal_hashboards = 4 - self.chip_count = 18 + self.ideal_hashboards = 3 + self.nominal_chips = 84 self.fan_count = 4 diff --git a/pyasic/miners/ltc/_backends/X7.py b/pyasic/miners/ltc/_backends/X7.py index e95b0c02..640fb255 100644 --- a/pyasic/miners/ltc/_backends/X7.py +++ b/pyasic/miners/ltc/_backends/X7.py @@ -22,14 +22,14 @@ from pyasic.config import MinerConfig, X19PowerMode from pyasic.data import HashBoard from pyasic.data.error_codes import MinerErrorData, X19Error from pyasic.miners.btc._backends import BMMiner # noqa - Ignore access to _module -from pyasic.web.X7 import X7WebAPI +from pyasic.web.X19 import X19WebAPI class X7(BMMiner): def __init__(self, ip: str, api_ver: str = "0.0.0") -> None: super().__init__(ip, api_ver=api_ver) self.ip = ip - self.web = X7WebAPI(ip) + self.web = X19WebAPI(ip) async def get_config(self) -> MinerConfig: data = await self.web.get_miner_conf() diff --git a/pyasic/miners/miner_factory.py b/pyasic/miners/miner_factory.py index 7c0668d0..f0d50cdc 100644 --- a/pyasic/miners/miner_factory.py +++ b/pyasic/miners/miner_factory.py @@ -58,6 +58,10 @@ MINER_CLASSES = { "Default": BMMinerL7, "BMMiner": BMMinerL7, }, + "ANTMINER E9 PRO": { + "Default": CGMinerE9Pro, + "BMMiner": CGMinerE9Pro, + }, "ANTMINER S9": { "Default": BOSMinerS9, "BOSMiner": BOSMinerOld, diff --git a/pyasic/miners/zec/_backends/X15.py b/pyasic/miners/zec/_backends/X15.py index 3a9fa180..f6516a01 100644 --- a/pyasic/miners/zec/_backends/X15.py +++ b/pyasic/miners/zec/_backends/X15.py @@ -20,14 +20,14 @@ from pyasic.config import MinerConfig from pyasic.data import Fan, HashBoard from pyasic.errors import APIError from pyasic.miners.zec._backends import CGMiner # noqa - Ignore access to _module -from pyasic.web.X15 import X15WebAPI +from pyasic.web.X17 import X17WebAPI class X15(CGMiner): def __init__(self, ip: str, api_ver: str = "0.0.0") -> None: super().__init__(ip, api_ver=api_ver) self.ip = ip - self.web = X15WebAPI(ip) + self.web = X17WebAPI(ip) async def get_config(self) -> MinerConfig: data = await self.web.get_miner_conf() @@ -36,7 +36,7 @@ class X15(CGMiner): return self.config async def send_config(self, config: MinerConfig, user_suffix: str = None) -> None: - await self.web.set_miner_conf(config.as_x15(user_suffix=user_suffix)) + await self.web.set_miner_conf(config.as_x17(user_suffix=user_suffix)) async def get_mac(self) -> Union[str, None]: try: diff --git a/pyasic/web/X15.py b/pyasic/web/X15.py deleted file mode 100644 index 83eee9cf..00000000 --- a/pyasic/web/X15.py +++ /dev/null @@ -1,72 +0,0 @@ -# ------------------------------------------------------------------------------ -# 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. - -# ------------------------------------------------------------------------------ -import json -from typing import Union - -import httpx - -from pyasic.settings import PyasicSettings -from pyasic.web import BaseWebAPI - - -class X15WebAPI(BaseWebAPI): - def __init__(self, ip: str) -> None: - super().__init__(ip) - self.pwd = PyasicSettings().global_x15_password - - async def send_command( - self, - command: Union[str, bytes], - ignore_errors: bool = False, - allow_warning: bool = True, - **parameters: Union[str, int, bool], - ) -> dict: - url = f"http://{self.ip}/cgi-bin/{command}.cgi" - auth = httpx.DigestAuth(self.username, self.pwd) - try: - async with httpx.AsyncClient() as client: - if parameters: - data = await client.post(url, data=parameters, auth=auth) - else: - data = await client.get(url, auth=auth) - except httpx.HTTPError: - pass - else: - if data.status_code == 200: - try: - return data.json() - except json.decoder.JSONDecodeError: - pass - - async def get_system_info(self) -> dict: - return await self.send_command("get_system_info") - - async def blink(self, blink: bool) -> dict: - if blink: - return await self.send_command("blink", action="startBlink") - return await self.send_command("blink", action="stopBlink") - - async def reboot(self) -> dict: - return await self.send_command("reboot") - - async def get_blink_status(self) -> dict: - return await self.send_command("blink", action="onPageLoaded") - - async def get_miner_conf(self) -> dict: - return await self.send_command("get_miner_conf") - - async def set_miner_conf(self, conf: dict) -> dict: - return await self.send_command("set_miner_conf", **conf) diff --git a/pyasic/web/X17.py b/pyasic/web/X17.py index a332bcf5..48181df9 100644 --- a/pyasic/web/X17.py +++ b/pyasic/web/X17.py @@ -64,3 +64,9 @@ class X17WebAPI(BaseWebAPI): async def get_blink_status(self) -> dict: return await self.send_command("blink", action="onPageLoaded") + + async def get_miner_conf(self) -> dict: + return await self.send_command("get_miner_conf") + + async def set_miner_conf(self, conf: dict) -> dict: + return await self.send_command("set_miner_conf", **conf) diff --git a/pyasic/web/X3.py b/pyasic/web/X3.py deleted file mode 100644 index 13c4e457..00000000 --- a/pyasic/web/X3.py +++ /dev/null @@ -1,72 +0,0 @@ -# ------------------------------------------------------------------------------ -# 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. - -# ------------------------------------------------------------------------------ -import json -from typing import Union - -import httpx - -from pyasic.settings import PyasicSettings -from pyasic.web import BaseWebAPI - - -class X3WebAPI(BaseWebAPI): - def __init__(self, ip: str) -> None: - super().__init__(ip) - self.pwd = PyasicSettings().global_x5_password - - async def send_command( - self, - command: Union[str, bytes], - ignore_errors: bool = False, - allow_warning: bool = True, - **parameters: Union[str, int, bool], - ) -> dict: - url = f"http://{self.ip}/cgi-bin/{command}.cgi" - auth = httpx.DigestAuth(self.username, self.pwd) - try: - async with httpx.AsyncClient() as client: - if parameters: - data = await client.post(url, data=parameters, auth=auth) - else: - data = await client.get(url, auth=auth) - except httpx.HTTPError: - pass - else: - if data.status_code == 200: - try: - return data.json() - except json.decoder.JSONDecodeError: - pass - - async def get_system_info(self) -> dict: - return await self.send_command("get_system_info") - - async def blink(self, blink: bool) -> dict: - if blink: - return await self.send_command("blink", action="startBlink") - return await self.send_command("blink", action="stopBlink") - - async def reboot(self) -> dict: - return await self.send_command("reboot") - - async def get_blink_status(self) -> dict: - return await self.send_command("blink", action="onPageLoaded") - - async def get_miner_conf(self) -> dict: - return await self.send_command("get_miner_conf") - - async def set_miner_conf(self, conf: dict) -> dict: - return await self.send_command("set_miner_conf", **conf) diff --git a/pyasic/web/X5.py b/pyasic/web/X5.py deleted file mode 100644 index 87fbc365..00000000 --- a/pyasic/web/X5.py +++ /dev/null @@ -1,72 +0,0 @@ -# ------------------------------------------------------------------------------ -# 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. - -# ------------------------------------------------------------------------------ -import json -from typing import Union - -import httpx - -from pyasic.settings import PyasicSettings -from pyasic.web import BaseWebAPI - - -class X5WebAPI(BaseWebAPI): - def __init__(self, ip: str) -> None: - super().__init__(ip) - self.pwd = PyasicSettings().global_x5_password - - async def send_command( - self, - command: Union[str, bytes], - ignore_errors: bool = False, - allow_warning: bool = True, - **parameters: Union[str, int, bool], - ) -> dict: - url = f"http://{self.ip}/cgi-bin/{command}.cgi" - auth = httpx.DigestAuth(self.username, self.pwd) - try: - async with httpx.AsyncClient() as client: - if parameters: - data = await client.post(url, data=parameters, auth=auth) - else: - data = await client.get(url, auth=auth) - except httpx.HTTPError: - pass - else: - if data.status_code == 200: - try: - return data.json() - except json.decoder.JSONDecodeError: - pass - - async def get_system_info(self) -> dict: - return await self.send_command("get_system_info") - - async def blink(self, blink: bool) -> dict: - if blink: - return await self.send_command("blink", action="startBlink") - return await self.send_command("blink", action="stopBlink") - - async def reboot(self) -> dict: - return await self.send_command("reboot") - - async def get_blink_status(self) -> dict: - return await self.send_command("blink", action="onPageLoaded") - - async def get_miner_conf(self) -> dict: - return await self.send_command("get_miner_conf") - - async def set_miner_conf(self, conf: dict) -> dict: - return await self.send_command("set_miner_conf", **conf) diff --git a/pyasic/web/X7.py b/pyasic/web/X7.py deleted file mode 100644 index 975aa5f5..00000000 --- a/pyasic/web/X7.py +++ /dev/null @@ -1,99 +0,0 @@ -# ------------------------------------------------------------------------------ -# 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. - -# ------------------------------------------------------------------------------ -import json -from typing import Union - -import httpx - -from pyasic.settings import PyasicSettings -from pyasic.web import BaseWebAPI - - -class X7WebAPI(BaseWebAPI): - def __init__(self, ip: str) -> None: - super().__init__(ip) - self.pwd = PyasicSettings().global_x7_password - - async def send_command( - self, - command: Union[str, bytes], - ignore_errors: bool = False, - allow_warning: bool = True, - **parameters: Union[str, int, bool], - ) -> dict: - url = f"http://{self.ip}/cgi-bin/{command}.cgi" - auth = httpx.DigestAuth(self.username, self.pwd) - try: - async with httpx.AsyncClient() as client: - if parameters: - data = await client.post( - url, data=json.dumps(parameters), auth=auth # noqa - ) - else: - data = await client.get(url, auth=auth) - except httpx.HTTPError: - pass - else: - if data.status_code == 200: - try: - return data.json() - except json.decoder.JSONDecodeError: - pass - - async def get_miner_conf(self) -> dict: - return await self.send_command("get_miner_conf") - - async def set_miner_conf(self, conf: dict) -> dict: - return await self.send_command("set_miner_conf", **conf) - - async def blink(self, blink: bool) -> dict: - if blink: - return await self.send_command("blink", blink="true") - return await self.send_command("blink", blink="false") - - async def reboot(self) -> dict: - return await self.send_command("reboot") - - async def get_system_info(self) -> dict: - return await self.send_command("get_system_info") - - async def get_network_info(self) -> dict: - return await self.send_command("get_network_info") - - async def summary(self) -> dict: - return await self.send_command("summary") - - async def get_blink_status(self) -> dict: - return await self.send_command("get_blink_status") - - async def set_network_conf( - self, - ip: str, - dns: str, - gateway: str, - subnet_mask: str, - hostname: str, - protocol: int, - ) -> dict: - return await self.send_command( - "set_network_conf", - ipAddress=ip, - ipDns=dns, - ipGateway=gateway, - ipHost=hostname, - ipPro=protocol, - ipSub=subnet_mask, - ) diff --git a/pyasic/web/inno.py b/pyasic/web/inno.py index 7c6d837e..2908e574 100644 --- a/pyasic/web/inno.py +++ b/pyasic/web/inno.py @@ -65,7 +65,6 @@ class InnosiliconWebAPI(BaseWebAPI): json=parameters, ) json_data = response.json() - print(json_data) if ( not json_data.get("success") and "token" in json_data