From d00444ec56d22dd38d1bd514523a164e6b7d07d6 Mon Sep 17 00:00:00 2001 From: 1e9abhi1e10 <2311abhiptdr@gmail.com> Date: Sun, 18 Aug 2024 01:18:42 +0530 Subject: [PATCH 1/3] feat: Add update firmware for Antminer --- pyasic/miners/backends/antminer.py | 28 ++++++++++++++++++++ pyasic/web/antminer.py | 41 +++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/pyasic/miners/backends/antminer.py b/pyasic/miners/backends/antminer.py index 5d162730..b96eb687 100644 --- a/pyasic/miners/backends/antminer.py +++ b/pyasic/miners/backends/antminer.py @@ -15,6 +15,8 @@ # ------------------------------------------------------------------------------ from typing import List, Optional, Union +from pathlib import Path +import logging from pyasic.config import MinerConfig, MiningModeConfig from pyasic.data import AlgoHashRate, Fan, HashBoard, HashUnit @@ -124,6 +126,32 @@ class AntminerModern(BMMiner): # break # await asyncio.sleep(1) + async def upgrade_firmware(self, file: Path, keep_settings: bool = True) -> str: + """ + Upgrade the firmware of the AntMiner device. + + Args: + file (Path): Path to the firmware file. + keep_settings (bool): Whether to keep current settings after the upgrade. Defaults to True. + + Returns: + str: Result of the upgrade process. + """ + if not file: + raise ValueError("File location must be provided for firmware upgrade.") + + try: + result = await self.web.update_firmware(file=file, keep_settings=keep_settings) + + if 'Success' in result: + logging.info("Firmware upgrade process completed successfully for Antminer.") + else: + logging.error(f"Firmware upgrade failed. Response: {result}") + raise + except Exception as e: + logging.error(f"An error occurred during the firmware upgrade process: {e}", exc_info=True) + raise + async def fault_light_on(self) -> bool: data = await self.web.blink(blink=True) if data: diff --git a/pyasic/web/antminer.py b/pyasic/web/antminer.py index 9a7a8118..6c38cd94 100644 --- a/pyasic/web/antminer.py +++ b/pyasic/web/antminer.py @@ -18,8 +18,9 @@ from __future__ import annotations import asyncio import json from typing import Any - +import aiofiles import httpx +from pathlib import Path from pyasic import settings from pyasic.web.base import BaseWebAPI @@ -59,9 +60,26 @@ class AntminerModernWebAPI(BaseWebAPI): url = f"http://{self.ip}:{self.port}/cgi-bin/{command}.cgi" auth = httpx.DigestAuth(self.username, self.pwd) try: - async with httpx.AsyncClient( - transport=settings.transport(), - ) as client: + async with httpx.AsyncClient(transport=settings.transport()) as client: + if command == "upgrade": + file = parameters.get("file") + keep_settings = parameters.get("keep_settings", True) + if file: + upload_url = f"http://{self.ip}:{self.port}/cgi-bin/firmware_upload.cgi" + with open(file, "rb") as firmware: + files = {"file": (file.name, firmware, "application/octet-stream")} + upload_response = await client.post( + upload_url, + auth=auth, + files=files, + timeout=settings.get("firmware_upload_timeout", 300) + ) + if upload_response.status_code != 200: + return {"success": False, "message": "Failed to upload firmware file"} + + parameters["filename"] = file.name + parameters["keep_settings"] = keep_settings + if parameters: data = await client.post( url, @@ -71,14 +89,15 @@ class AntminerModernWebAPI(BaseWebAPI): ) else: data = await client.get(url, auth=auth) - except httpx.HTTPError: - pass + except httpx.HTTPError as e: + return {"success": False, "message": f"HTTP error occurred: {str(e)}"} else: if data.status_code == 200: try: return data.json() except json.decoder.JSONDecodeError: - pass + return {"success": False, "message": "Failed to decode JSON"} + return {"success": False, "message": "Unknown error occurred"} async def multicommand( self, *commands: str, ignore_errors: bool = False, allow_warning: bool = True @@ -403,3 +422,11 @@ class AntminerOldWebAPI(BaseWebAPI): dict: Information about the mining pools configured in the miner. """ return await self.send_command("miner_pools") + + async def update_firmware(self, file: Path, keep_settings: bool = True) -> dict: + """Perform a system update by uploading a firmware file and sending a command to initiate the update.""" + return await self.send_command( + command="upgrade", + file=file, + keep_settings=keep_settings + ) From 6b50bf0cf7b838f3be65a1e6c0d5137641cc6b02 Mon Sep 17 00:00:00 2001 From: 1e9abhi1e10 <2311abhiptdr@gmail.com> Date: Sun, 18 Aug 2024 01:45:03 +0530 Subject: [PATCH 2/3] Fix some minor issues --- pyasic/miners/backends/antminer.py | 5 +++-- pyasic/web/antminer.py | 7 ++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/pyasic/miners/backends/antminer.py b/pyasic/miners/backends/antminer.py index b96eb687..41a41b33 100644 --- a/pyasic/miners/backends/antminer.py +++ b/pyasic/miners/backends/antminer.py @@ -132,7 +132,7 @@ class AntminerModern(BMMiner): Args: file (Path): Path to the firmware file. - keep_settings (bool): Whether to keep current settings after the upgrade. Defaults to True. + keep_settings (bool): Whether to keep the current settings after the update. Returns: str: Result of the upgrade process. @@ -145,9 +145,10 @@ class AntminerModern(BMMiner): if 'Success' in result: logging.info("Firmware upgrade process completed successfully for Antminer.") + return "Firmware upgrade completed successfully." else: logging.error(f"Firmware upgrade failed. Response: {result}") - raise + return f"Firmware upgrade failed. Response: {result}" except Exception as e: logging.error(f"An error occurred during the firmware upgrade process: {e}", exc_info=True) raise diff --git a/pyasic/web/antminer.py b/pyasic/web/antminer.py index 6c38cd94..2c7893bc 100644 --- a/pyasic/web/antminer.py +++ b/pyasic/web/antminer.py @@ -66,8 +66,9 @@ class AntminerModernWebAPI(BaseWebAPI): keep_settings = parameters.get("keep_settings", True) if file: upload_url = f"http://{self.ip}:{self.port}/cgi-bin/firmware_upload.cgi" - with open(file, "rb") as firmware: - files = {"file": (file.name, firmware, "application/octet-stream")} + async with aiofiles.open(file, "rb") as firmware: + file_content = await firmware.read() + files = {"file": (file.name, file_content, "application/octet-stream")} upload_response = await client.post( upload_url, auth=auth, @@ -76,7 +77,7 @@ class AntminerModernWebAPI(BaseWebAPI): ) if upload_response.status_code != 200: return {"success": False, "message": "Failed to upload firmware file"} - + parameters["filename"] = file.name parameters["keep_settings"] = keep_settings From 28642cc52138f6a0e3c60a6dfbf4e4a826e5f372 Mon Sep 17 00:00:00 2001 From: 1e9abhi1e10 <2311abhiptdr@gmail.com> Date: Tue, 27 Aug 2024 02:34:23 +0530 Subject: [PATCH 3/3] Refactor firmware upgrade process --- pyasic/miners/backends/antminer.py | 9 +++++---- pyasic/web/antminer.py | 32 ++++++++++-------------------- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/pyasic/miners/backends/antminer.py b/pyasic/miners/backends/antminer.py index 41a41b33..38f133ee 100644 --- a/pyasic/miners/backends/antminer.py +++ b/pyasic/miners/backends/antminer.py @@ -143,12 +143,13 @@ class AntminerModern(BMMiner): try: result = await self.web.update_firmware(file=file, keep_settings=keep_settings) - if 'Success' in result: - logging.info("Firmware upgrade process completed successfully for Antminer.") + if result.get("success"): + logging.info("Firmware upgrade process completed successfully for AntMiner.") return "Firmware upgrade completed successfully." else: - logging.error(f"Firmware upgrade failed. Response: {result}") - return f"Firmware upgrade failed. Response: {result}" + error_message = result.get("message", "Unknown error") + logging.error(f"Firmware upgrade failed. Response: {error_message}") + return f"Firmware upgrade failed. Response: {error_message}" except Exception as e: logging.error(f"An error occurred during the firmware upgrade process: {e}", exc_info=True) raise diff --git a/pyasic/web/antminer.py b/pyasic/web/antminer.py index 2c7893bc..13e91d49 100644 --- a/pyasic/web/antminer.py +++ b/pyasic/web/antminer.py @@ -61,25 +61,6 @@ class AntminerModernWebAPI(BaseWebAPI): auth = httpx.DigestAuth(self.username, self.pwd) try: async with httpx.AsyncClient(transport=settings.transport()) as client: - if command == "upgrade": - file = parameters.get("file") - keep_settings = parameters.get("keep_settings", True) - if file: - upload_url = f"http://{self.ip}:{self.port}/cgi-bin/firmware_upload.cgi" - async with aiofiles.open(file, "rb") as firmware: - file_content = await firmware.read() - files = {"file": (file.name, file_content, "application/octet-stream")} - upload_response = await client.post( - upload_url, - auth=auth, - files=files, - timeout=settings.get("firmware_upload_timeout", 300) - ) - if upload_response.status_code != 200: - return {"success": False, "message": "Failed to upload firmware file"} - - parameters["filename"] = file.name - parameters["keep_settings"] = keep_settings if parameters: data = await client.post( @@ -426,8 +407,17 @@ class AntminerOldWebAPI(BaseWebAPI): async def update_firmware(self, file: Path, keep_settings: bool = True) -> dict: """Perform a system update by uploading a firmware file and sending a command to initiate the update.""" + + async with aiofiles.open(file, "rb") as firmware: + file_content = await firmware.read() + + parameters = { + "file": (file.name, file_content, "application/octet-stream"), + "filename": file.name, + "keep_settings": keep_settings + } + return await self.send_command( command="upgrade", - file=file, - keep_settings=keep_settings + **parameters )