{"id":21035316,"url":"https://github.com/upstreamdata/pyasic","last_synced_at":"2026-02-06T23:05:53.290Z","repository":{"id":38378885,"uuid":"409345141","full_name":"UpstreamData/pyasic","owner":"UpstreamData","description":"A simplified and standardized interface for Bitcoin ASICs.","archived":false,"fork":false,"pushed_at":"2025-03-31T19:16:09.000Z","size":4708,"stargazers_count":116,"open_issues_count":30,"forks_count":61,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-04-01T03:27:58.386Z","etag":null,"topics":["antminer","asic","asyncio","bitcoin","braiins-os","luxos","python","python3","vnish","whatsminer"],"latest_commit_sha":null,"homepage":"https://docs.pyasic.org","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/UpstreamData.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-22T20:21:30.000Z","updated_at":"2025-03-27T17:09:52.000Z","dependencies_parsed_at":"2023-10-02T19:02:40.138Z","dependency_job_id":"228e061a-e4e0-4074-8c7a-4f7725e78f9d","html_url":"https://github.com/UpstreamData/pyasic","commit_stats":{"total_commits":995,"total_committers":10,"mean_commits":99.5,"dds":"0.17286432160804022","last_synced_commit":"a67e4ada8e216f58b07cb24847a62e4d607960e1"},"previous_names":[],"tags_count":414,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UpstreamData%2Fpyasic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UpstreamData%2Fpyasic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UpstreamData%2Fpyasic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/UpstreamData%2Fpyasic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/UpstreamData","download_url":"https://codeload.github.com/UpstreamData/pyasic/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247773719,"owners_count":20993639,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["antminer","asic","asyncio","bitcoin","braiins-os","luxos","python","python3","vnish","whatsminer"],"created_at":"2024-11-19T13:14:32.192Z","updated_at":"2026-02-06T23:05:53.278Z","avatar_url":"https://github.com/UpstreamData.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pyasic\n*A simplified and standardized interface for Bitcoin ASICs.*\n\n[![PyPI - Version](https://img.shields.io/pypi/v/pyasic.svg)](https://pypi.org/project/pyasic/)\n[![PyPI - Downloads](https://img.shields.io/pypi/dm/pyasic)](https://pypi.org/project/pyasic/)\n\n[![Python - Supported Versions](https://img.shields.io/pypi/pyversions/pyasic.svg)](https://pypi.org/project/pyasic/)\n[![CodeFactor - Grade](https://img.shields.io/codefactor/grade/github/UpstreamData/pyasic)](https://www.codefactor.io/repository/github/upstreamdata/pyasic)\n[![Commit Activity - master](https://img.shields.io/github/commit-activity/y/UpstreamData/pyasic)](https://github.com/UpstreamData/pyasic/commits/master/)\n\n[![Code Style - Black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)\n[![Read The Docs - Docs](https://img.shields.io/readthedocs/pyasic)](https://docs.pyasic.org)\n[![License - Apache 2.0](https://img.shields.io/github/license/UpstreamData/pyasic)](https://github.com/UpstreamData/pyasic/blob/master/LICENSE.txt)\n\n---\n## Intro\n\nWelcome to `pyasic`!  `pyasic` uses an asynchronous method of communicating with ASIC miners on your network, which makes it super fast.\n\n[Click here to view supported miner types](https://docs.pyasic.org/en/latest/miners/supported_types/)\n\n---\n## Installation\n\nIt is recommended to install `pyasic` in a [virtual environment](https://realpython.com/python-virtual-environments-a-primer/#what-other-popular-options-exist-aside-from-venv) to isolate it from the rest of your system. Options include:\n  - [pypoetry](https://python-poetry.org/): the reccommended way, since pyasic already uses it by default. Use version 2.0+\n\n```\n    poetry install\n```\n\n  - [venv](https://docs.python.org/3/library/venv.html): included in Python standard library but has fewer features than other options\n  - [pyenv-virtualenv](https://github.com/pyenv/pyenv-virtualenv): [pyenv](https://github.com/pyenv/pyenv) plugin for managing virtualenvs\n\n```\n    pyenv install \u003cpython version number\u003e\n    pyenv virtualenv \u003cpython version number\u003e \u003cenv name\u003e\n    pyenv activate \u003cenv name\u003e\n```\n\n  - [conda](https://docs.conda.io/en/latest/)\n\n##### Installing `pyasic`\n\n`python -m pip install pyasic` or `poetry install`\n\n##### Additional Developer Setup\n```\npoetry install --with dev\npre-commit install\n```\n\n##### Building Documentation Locally\n```\npoetry install --with docs\npython docs/generate_miners.py\npoetry run mkdocs serve\n```\n\n---\n## Getting started\n\nGetting started with `pyasic` is easy.  First, find your miner (or miners) on the network by scanning for them or getting the correct class automatically for them if you know the IP.\n\n##### Scanning for miners\nTo scan for miners in `pyasic`, we use the class `MinerNetwork`, which abstracts the search, communication, identification, setup, and return of a miner to 1 command.\nThe command `MinerNetwork.scan()` returns a list that contains any miners found.\n```python\nimport asyncio  # asyncio for handling the async part\nfrom pyasic.network import MinerNetwork  # miner network handles the scanning\n\n\nasync def scan_miners():  # define async scan function to allow awaiting\n    # create a miner network\n    # you can pass in any IP and it will use that in a subnet with a /24 mask (255 IPs).\n    network = MinerNetwork.from_subnet(\"192.168.1.50/24\")  # this uses the 192.168.1.0-255 network\n\n    # scan for miners asynchronously\n    # this will return the correct type of miners if they are supported with all functionality.\n    miners = await network.scan()\n    print(miners)\n\nif __name__ == \"__main__\":\n    asyncio.run(scan_miners())  # run the scan asynchronously with asyncio.run()\n```\n\n---\n##### Creating miners based on IP\nIf you already know the IP address of your miner or miners, you can use the `MinerFactory` to communicate and identify the miners, or an abstraction of its functionality, `get_miner()`.\nThe function `get_miner()` will return any miner it found at the IP address specified, or an `UnknownMiner` if it cannot identify the miner.\n```python\nimport asyncio  # asyncio for handling the async part\nfrom pyasic import get_miner # handles miner creation\n\n\nasync def get_miners():  # define async scan function to allow awaiting\n    # get the miner with the miner factory\n    # the miner factory is a singleton, and will always use the same object and cache\n    # this means you can always call it as MinerFactory().get_miner(), or just get_miner()\n    miner_1 = await get_miner(\"192.168.1.75\")\n    miner_2 = await get_miner(\"192.168.1.76\")\n    print(miner_1, miner_2)\n\n    # can also gather these, since they are async\n    # gathering them will get them both at the same time\n    # this makes it much faster to get a lot of miners at a time\n    tasks = [get_miner(\"192.168.1.75\"), get_miner(\"192.168.1.76\")]\n    miners = await asyncio.gather(*tasks)\n    print(miners)\n\n\nif __name__ == \"__main__\":\n    asyncio.run(get_miners())  # get the miners asynchronously with asyncio.run()\n```\n\n---\n## Data gathering\n\nOnce you have your miner(s) identified, you will likely want to get data from the miner(s).  You can do this using a built-in function in each miner called `get_data()`.\nThis function will return an instance of the dataclass `MinerData` with all data it can gather from the miner.\nEach piece of data in a `MinerData` instance can be referenced by getting it as an attribute, such as `MinerData().hashrate`.\n\n##### One miner\n```python\nimport asyncio\nfrom pyasic import get_miner\n\nasync def gather_miner_data():\n    miner = await get_miner(\"192.168.1.75\")\n    if miner is not None:\n        miner_data = await miner.get_data()\n        print(miner_data)  # all data from the dataclass\n        print(miner_data.hashrate)  # hashrate of the miner in TH/s\n\nif __name__ == \"__main__\":\n    asyncio.run(gather_miner_data())\n```\n---\n##### Multiple miners\nYou can do something similar with multiple miners, with only needing to make a small change to get all the data at once.\n```python\nimport asyncio  # asyncio for handling the async part\nfrom pyasic.network import MinerNetwork  # miner network handles the scanning\n\n\nasync def gather_miner_data():  # define async scan function to allow awaiting\n    network = MinerNetwork.from_subnet(\"192.168.1.50/24\")\n    miners = await network.scan()\n\n    # we need to asyncio.gather() all the miners get_data() functions to make them run together\n    all_miner_data = await asyncio.gather(*[miner.get_data() for miner in miners])\n\n    for miner_data in all_miner_data:\n        print(miner_data)    # print out all the data one by one\n\nif __name__ == \"__main__\":\n    asyncio.run(gather_miner_data())\n```\n\n---\n## Miner control\n\n`pyasic` exposes a standard interface for each miner using control functions.\nEvery miner class in `pyasic` must implement all the control functions defined in `BaseMiner`.\n\nThese functions are\n`check_light`,\n`fault_light_off`,\n`fault_light_on`,\n`get_config`,\n`get_data`,\n`get_errors`,\n`get_hostname`,\n`get_model`,\n`reboot`,\n`restart_backend`,\n`stop_mining`,\n`resume_mining`,\n`is_mining`,\n`send_config`, and\n`set_power_limit`.\n\n##### Usage\n```python\nimport asyncio\nfrom pyasic import get_miner\n\n\nasync def set_fault_light():\n    miner = await get_miner(\"192.168.1.20\")\n\n    # call control function\n    await miner.fault_light_on()\n\nif __name__ == \"__main__\":\n    asyncio.run(set_fault_light())\n```\n\n---\n## Helper dataclasses\n\n##### `MinerConfig` and `MinerData`\n\n`pyasic` implements a few dataclasses as helpers to make data return types consistent across different miners and miner APIs.  The different fields of these dataclasses can all be viewed with the classmethod `cls.fields()`.\n\n---\n\n##### MinerData\n\n`MinerData` is a return from the [`get_data()`](#get-data) function, and is used to have a consistent dataset across all returns.\n\nYou can call `MinerData.as_dict()` to get the dataclass as a dictionary, and there are many other helper functions contained in the class to convert to different data formats.\n\n`MinerData` instances can also be added to each other to combine their data and can be divided by a number to divide all their data, allowing you to get average data from many miners by doing -\n```python\nfrom pyasic import MinerData\n\n# examples of miner data\nd1 = MinerData(\"192.168.1.1\")\nd2 = MinerData(\"192.168.1.2\")\n\nlist_of_miner_data = [d1, d2]\n\naverage_data = sum(list_of_miner_data, start=MinerData(\"0.0.0.0\"))/len(list_of_miner_data)\n```\n\n---\n\n##### MinerConfig\n\n`MinerConfig` is `pyasic`'s way to represent a configuration file from a miner.\nIt is designed to unionize the configuration of all supported miner types, and is the return from [`get_config()`](#get-config).\n\nEach miner has a unique way to convert the `MinerConfig` to their specific type, there are helper functions in the class.\nIn most cases these helper functions should not be used, as [`send_config()`](#send-config) takes a [`MinerConfig` and will do the conversion to the right type for you.\n\nYou can use the `MinerConfig` as follows:\n```python\nimport asyncio\nfrom pyasic import get_miner\n\n\nasync def set_fault_light():\n    miner = await get_miner(\"192.168.1.20\")\n\n    # get config\n    cfg = await miner.get_config()\n\n    # send config\n    await miner.send_config(cfg)\n\nif __name__ == \"__main__\":\n    asyncio.run(set_fault_light())\n\n```\n\n---\n## Settings\n\n`pyasic` has settings designed to make using large groups of miners easier.  You can set the default password for all types of miners using the `pyasic.settings` module, used as follows:\n\n```python\nfrom pyasic import settings\n\nsettings.update(\"default_antminer_web_password\", \"my_pwd\")\n```\n\n##### Default values:\n```\n\"network_ping_retries\": 1,\n\"network_ping_timeout\": 3,\n\"network_scan_semaphore\": None,\n\"factory_get_retries\": 1,\n\"factory_get_timeout\": 3,\n\"get_data_retries\": 1,\n\"api_function_timeout\": 5,\n\"antminer_mining_mode_as_str\": False,\n\"default_whatsminer_rpc_password\": \"admin\",\n\"default_innosilicon_web_password\": \"admin\",\n\"default_antminer_web_password\": \"root\",\n\"default_bosminer_web_password\": \"root\",\n\"default_vnish_web_password\": \"admin\",\n\"default_goldshell_web_password\": \"123456789\",\n\"default_auradine_web_password\": \"admin\",\n\"default_epic_web_password\": \"letmein\",\n\"default_hive_web_password\": \"admin\",\n\"default_antminer_ssh_password\": \"miner\",\n\"default_bosminer_ssh_password\": \"root\",\n\n# ADVANCED\n# Only use this if you know what you are doing\n\"socket_linger_time\": 1000,\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fupstreamdata%2Fpyasic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fupstreamdata%2Fpyasic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fupstreamdata%2Fpyasic/lists"}