diff --git a/pyasic/data/__init__.py b/pyasic/data/__init__.py index 3a515f7e..3ab29346 100644 --- a/pyasic/data/__init__.py +++ b/pyasic/data/__init__.py @@ -66,6 +66,7 @@ class MinerData: Attributes: ip: The IP of the miner as a str. datetime: The time and date this data was generated. + uptime: The uptime of the miner in seconds. mac: The MAC address of the miner as a str. model: The model of the miner as a str. make: The make of the miner as a str. @@ -101,6 +102,7 @@ class MinerData: ip: str datetime: datetime = None + uptime: int = 0 mac: str = "00:00:00:00:00:00" model: str = "Unknown" make: str = "Unknown" diff --git a/pyasic/miners/backends/antminer.py b/pyasic/miners/backends/antminer.py index 9d4820d7..3fb15b2c 100644 --- a/pyasic/miners/backends/antminer.py +++ b/pyasic/miners/backends/antminer.py @@ -49,6 +49,10 @@ ANTMINER_MODERN_DATA_LOC = { "cmd": "is_mining", "kwargs": {"web_get_conf": {"web": "get_miner_conf"}}, }, + "uptime": { + "cmd": "get_uptime", + "kwargs": {"api_stats": {"api": "stats"}}, + }, } @@ -244,6 +248,19 @@ class AntminerModern(BMMiner): except LookupError: pass + async def get_uptime(self, api_stats: dict = None) -> Optional[int]: + if not api_stats: + try: + api_stats = await self.api.stats() + except APIError: + pass + + if api_stats: + try: + return int(api_stats["STATS"][0]["Elapsed"]) + except LookupError: + pass + ANTMINER_OLD_DATA_LOC = { "mac": {"cmd": "get_mac", "kwargs": {}}, @@ -278,6 +295,10 @@ ANTMINER_OLD_DATA_LOC = { "cmd": "is_mining", "kwargs": {"web_get_conf": {"web": "get_miner_conf"}}, }, + "uptime": { + "cmd": "get_uptime", + "kwargs": {"api_stats": {"api": "stats"}}, + }, } @@ -471,3 +492,16 @@ class AntminerOld(CGMiner): return True else: return False + + async def get_uptime(self, api_stats: dict = None) -> Optional[int]: + if not api_stats: + try: + api_stats = await self.api.stats() + except APIError: + pass + + if api_stats: + try: + return int(api_stats["STATS"][0]["Elapsed"]) + except LookupError: + pass diff --git a/pyasic/miners/backends/bfgminer.py b/pyasic/miners/backends/bfgminer.py index 391763b9..0f2229cb 100644 --- a/pyasic/miners/backends/bfgminer.py +++ b/pyasic/miners/backends/bfgminer.py @@ -45,6 +45,7 @@ BFGMINER_DATA_LOC = { "fault_light": {"cmd": "get_fault_light", "kwargs": {}}, "pools": {"cmd": "get_pools", "kwargs": {"api_pools": {"api": "pools"}}}, "is_mining": {"cmd": "is_mining", "kwargs": {}}, + "uptime": {"cmd": "get_uptime", "kwargs": {}}, } @@ -322,3 +323,6 @@ class BFGMiner(BaseMiner): async def is_mining(self, *args, **kwargs) -> Optional[bool]: return None + + async def get_uptime(self, *args, **kwargs) -> Optional[int]: + return None diff --git a/pyasic/miners/backends/bfgminer_goldshell.py b/pyasic/miners/backends/bfgminer_goldshell.py index f2f93b72..74641e49 100644 --- a/pyasic/miners/backends/bfgminer_goldshell.py +++ b/pyasic/miners/backends/bfgminer_goldshell.py @@ -48,6 +48,7 @@ GOLDSHELL_DATA_LOC = { "fault_light": {"cmd": "get_fault_light", "kwargs": {}}, "pools": {"cmd": "get_pools", "kwargs": {"api_pools": {"api": "pools"}}}, "is_mining": {"cmd": "is_mining", "kwargs": {}}, + "uptime": {"cmd": "get_uptime", "kwargs": {}}, } @@ -161,3 +162,6 @@ class BFGMinerGoldshell(BFGMiner): async def is_mining(self, *args, **kwargs) -> Optional[bool]: return None + + async def get_uptime(self, *args, **kwargs) -> Optional[int]: + return None diff --git a/pyasic/miners/backends/bmminer.py b/pyasic/miners/backends/bmminer.py index 7c351ca4..e4e666a1 100644 --- a/pyasic/miners/backends/bmminer.py +++ b/pyasic/miners/backends/bmminer.py @@ -46,6 +46,10 @@ BMMINER_DATA_LOC = { "fault_light": {"cmd": "get_fault_light", "kwargs": {}}, "pools": {"cmd": "get_pools", "kwargs": {"api_pools": {"api": "pools"}}}, "is_mining": {"cmd": "is_mining", "kwargs": {}}, + "uptime": { + "cmd": "get_uptime", + "kwargs": {"api_stats": {"api": "stats"}}, + }, } @@ -356,3 +360,16 @@ class BMMiner(BaseMiner): async def is_mining(self, *args, **kwargs) -> Optional[bool]: return None + + async def get_uptime(self, api_stats: dict = None) -> Optional[int]: + if not api_stats: + try: + api_stats = await self.web.get_miner_conf() + except APIError: + pass + + if api_stats: + try: + return int(api_stats["STATS"][0]["Elapsed"]) + except LookupError: + pass diff --git a/pyasic/miners/backends/bosminer.py b/pyasic/miners/backends/bosminer.py index 1ba2ca24..3f414fb3 100644 --- a/pyasic/miners/backends/bosminer.py +++ b/pyasic/miners/backends/bosminer.py @@ -176,6 +176,10 @@ BOSMINER_DATA_LOC = { "cmd": "is_mining", "kwargs": {"api_tunerstatus": {"api": "tunerstatus"}}, }, + "uptime": { + "cmd": "get_uptime", + "kwargs": {"api_summary": {"api": "summary"}}, + }, } @@ -382,6 +386,8 @@ class BOSMiner(BaseMiner): except APIError: pass + print(web_net_conf) + if isinstance(web_net_conf, dict): if "/cgi-bin/luci/admin/network/iface_status/lan" in web_net_conf.keys(): web_net_conf = web_net_conf[ @@ -1040,3 +1046,16 @@ class BOSMiner(BaseMiner): return running except LookupError: pass + + async def get_uptime(self, api_summary: dict = None) -> Optional[int]: + if not api_summary: + try: + api_summary = await self.api.summary() + except APIError: + pass + + if api_summary: + try: + return int(api_summary["SUMMARY"][0]["Elapsed"]) + except LookupError: + pass diff --git a/pyasic/miners/backends/bosminer_old.py b/pyasic/miners/backends/bosminer_old.py index af2eba84..c1d2b2fc 100644 --- a/pyasic/miners/backends/bosminer_old.py +++ b/pyasic/miners/backends/bosminer_old.py @@ -153,3 +153,6 @@ class BOSMinerOld(BOSMiner): async def is_mining(self, *args, **kwargs) -> Optional[bool]: return None + + async def get_uptime(self, *args, **kwargs) -> Optional[int]: + return None diff --git a/pyasic/miners/backends/btminer.py b/pyasic/miners/backends/btminer.py index dd6a17d7..e1026b26 100644 --- a/pyasic/miners/backends/btminer.py +++ b/pyasic/miners/backends/btminer.py @@ -89,6 +89,10 @@ BTMINER_DATA_LOC = { }, "pools": {"cmd": "get_pools", "kwargs": {"api_pools": {"api": "pools"}}}, "is_mining": {"cmd": "is_mining", "kwargs": {"api_status": {"api": "status"}}}, + "uptime": { + "cmd": "get_uptime", + "kwargs": {"api_summary": {"api": "summary"}}, + }, } @@ -636,3 +640,16 @@ class BTMiner(BaseMiner): return True if api_status["Msg"]["mineroff"] == "false" else False except LookupError: pass + + async def get_uptime(self, api_summary: dict = None) -> Optional[int]: + if not api_summary: + try: + api_summary = await self.api.summary() + except APIError: + pass + + if api_summary: + try: + return int(api_summary["SUMMARY"][0]["Elapsed"]) + except LookupError: + pass diff --git a/pyasic/miners/backends/cgminer.py b/pyasic/miners/backends/cgminer.py index c1179c39..8ceb9e63 100644 --- a/pyasic/miners/backends/cgminer.py +++ b/pyasic/miners/backends/cgminer.py @@ -46,6 +46,10 @@ CGMINER_DATA_LOC = { "fault_light": {"cmd": "get_fault_light", "kwargs": {}}, "pools": {"cmd": "get_pools", "kwargs": {"api_pools": {"api": "pools"}}}, "is_mining": {"cmd": "is_mining", "kwargs": {}}, + "uptime": { + "cmd": "get_uptime", + "kwargs": {"api_stats": {"api": "stats"}}, + }, } @@ -379,3 +383,16 @@ class CGMiner(BaseMiner): async def is_mining(self, *args, **kwargs) -> Optional[bool]: return None + + async def get_uptime(self, api_stats: dict = None) -> Optional[int]: + if not api_stats: + try: + api_stats = await self.api.stats() + except APIError: + pass + + if api_stats: + try: + return int(api_stats["STATS"][0]["Elapsed"]) + except LookupError: + pass diff --git a/pyasic/miners/backends/cgminer_avalon.py b/pyasic/miners/backends/cgminer_avalon.py index 570203b1..26e53d2b 100644 --- a/pyasic/miners/backends/cgminer_avalon.py +++ b/pyasic/miners/backends/cgminer_avalon.py @@ -51,6 +51,7 @@ AVALON_DATA_LOC = { }, "pools": {"cmd": "get_pools", "kwargs": {"api_pools": {"api": "pools"}}}, "is_mining": {"cmd": "is_mining", "kwargs": {}}, + "uptime": {"cmd": "get_uptime", "kwargs": {}}, } diff --git a/pyasic/miners/backends/luxminer.py b/pyasic/miners/backends/luxminer.py index 0efeef8f..04e66037 100644 --- a/pyasic/miners/backends/luxminer.py +++ b/pyasic/miners/backends/luxminer.py @@ -89,6 +89,10 @@ LUXMINER_DATA_LOC = { "cmd": "is_mining", "kwargs": {}, }, + "uptime": { + "cmd": "get_uptime", + "kwargs": {"api_stats": {"api": "stats"}}, + }, } @@ -429,3 +433,16 @@ class LUXMiner(BaseMiner): async def is_mining(self) -> Optional[bool]: pass + + async def get_uptime(self, api_stats: dict = None) -> Optional[int]: + if not api_stats: + try: + api_stats = await self.api.stats() + except APIError: + pass + + if api_stats: + try: + return int(api_stats["STATS"][0]["Elapsed"]) + except LookupError: + pass diff --git a/pyasic/miners/backends/vnish.py b/pyasic/miners/backends/vnish.py index 121c244a..a11a40b2 100644 --- a/pyasic/miners/backends/vnish.py +++ b/pyasic/miners/backends/vnish.py @@ -44,6 +44,7 @@ VNISH_DATA_LOC = { "fault_light": {"cmd": "get_fault_light", "kwargs": {}}, "pools": {"cmd": "get_pools", "kwargs": {"api_pools": {"api": "pools"}}}, "is_mining": {"cmd": "is_mining", "kwargs": {}}, + "uptime": {"cmd": "get_uptime", "kwargs": {}}, } @@ -173,3 +174,6 @@ class VNish(BMMiner): async def is_mining(self, *args, **kwargs) -> Optional[bool]: return None + + async def get_uptime(self, *args, **kwargs) -> Optional[int]: + return None diff --git a/pyasic/miners/base.py b/pyasic/miners/base.py index d9fce351..a815e6a0 100644 --- a/pyasic/miners/base.py +++ b/pyasic/miners/base.py @@ -354,6 +354,15 @@ class BaseMiner(ABC): """ pass + @abstractmethod + async def get_uptime(self, *args, **kwargs) -> Optional[int]: + """Get the uptime of the miner in seconds. + + Returns: + The uptime of the miner in seconds. + """ + pass + async def _get_data(self, allow_warning: bool, data_to_get: list = None) -> dict: if not data_to_get: # everything @@ -375,6 +384,7 @@ class BaseMiner(ABC): "fault_light", "pools", "is_mining", + "uptime", ] api_multicommand = [] web_multicommand = [] diff --git a/pyasic/miners/unknown.py b/pyasic/miners/unknown.py index 3a37d853..7d78452d 100644 --- a/pyasic/miners/unknown.py +++ b/pyasic/miners/unknown.py @@ -151,6 +151,9 @@ class UnknownMiner(BaseMiner): async def is_mining(self, *args, **kwargs) -> Optional[bool]: return None + async def get_uptime(self, *args, **kwargs) -> Optional[int]: + return None + async def get_data( self, allow_warning: bool = False, data_to_get: list = None ) -> MinerData: diff --git a/pyasic/web/bosminer.py b/pyasic/web/bosminer.py index ef500f2a..1a7316a8 100644 --- a/pyasic/web/bosminer.py +++ b/pyasic/web/bosminer.py @@ -141,7 +141,11 @@ class BOSMinerWebAPI(BaseWebAPI): try: async with httpx.AsyncClient() as client: await self.luci_auth(client) - data = await client.get(f"http://{self.ip}{path}") + data = await client.get( + f"http://{self.ip}{path}", headers={"User-Agent": "BTC Tools v0.1"} + ) + print(data.status_code) + print(data.text) if data.status_code == 200: return data.json() if ignore_errors: @@ -161,7 +165,7 @@ class BOSMinerWebAPI(BaseWebAPI): "User-Agent": "BTC Tools v0.1", # only seems to respond if this user-agent is set "Content-Type": "application/x-www-form-urlencoded", } - d = await session.post(url, headers=headers, data=login) + await session.post(url, headers=headers, data=login) async def get_net_conf(self): return await self.send_luci_command(