Skip to content

Commit

Permalink
Merge pull request #252 from UpstreamData/main
Browse files Browse the repository at this point in the history
Optimize data and improve config handling
  • Loading branch information
Schnitzel authored Jan 9, 2024
2 parents e67f559 + 1524400 commit 1a494b8
Show file tree
Hide file tree
Showing 8 changed files with 248 additions and 117 deletions.
38 changes: 14 additions & 24 deletions custom_components/miner/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,14 @@

import pyasic
import voluptuous as vol
from homeassistant import config_entries
from homeassistant import exceptions
from homeassistant.helpers.selector import TextSelector
from homeassistant.helpers.selector import TextSelectorConfig
from homeassistant.helpers.selector import TextSelectorType

from .const import CONF_IP
from .const import CONF_PASSWORD
from .const import CONF_TITLE
from .const import CONF_USERNAME
from .const import DOMAIN
from homeassistant import config_entries, exceptions
from homeassistant.helpers.selector import (
TextSelector,
TextSelectorConfig,
TextSelectorType,
)

from .const import CONF_IP, CONF_PASSWORD, CONF_TITLE, CONF_USERNAME, DOMAIN

_LOGGER = logging.getLogger(__name__)

Expand All @@ -33,20 +30,13 @@ async def validate_input(data: dict[str, str]) -> dict[str, str]:
miner_username = data.get(CONF_USERNAME)
miner_password = data.get(CONF_PASSWORD)

try:
miner = await pyasic.get_miner(miner_ip)
if miner is None:
return {"base": "Unable to connect to Miner, is IP correct?"}

miner.username = miner_username
miner.pwd = miner_password
await miner.get_data()
miner = await pyasic.get_miner(miner_ip)
if miner is None:
return {"base": "Unable to connect to Miner, is IP correct?"}

except Exception as e: # pylint: disable=broad-except
_LOGGER.error(f"Miner setup error: {e}")
return {
"base": "Unable to authenticate with Miner, is Username & Password correct?"
}
miner.username = miner_username
miner.pwd = miner_password
await miner.get_data(include=["mac"])

return {}

Expand Down
5 changes: 5 additions & 0 deletions custom_components/miner/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,8 @@
CONF_TITLE = "title"
CONF_PASSWORD = "password"
CONF_USERNAME = "username"

DEVICE_CLASS_HASHRATE = "hashrate"
DEVICE_CLASS_EFFICIENCY = "efficiency"
TERA_HASH_PER_SECOND = "TH/s"
JOULES_PER_TERA_HASH = "J/TH"
33 changes: 23 additions & 10 deletions custom_components/miner/coordinator.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
"""IoTaWatt DataUpdateCoordinator."""
"""Miner DataUpdateCoordinator."""
import logging
from datetime import timedelta

import pyasic
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.debounce import Debouncer
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from homeassistant.helpers.update_coordinator import UpdateFailed
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from .const import CONF_IP
from .const import CONF_PASSWORD
from .const import CONF_USERNAME
from .const import CONF_IP, CONF_PASSWORD, CONF_USERNAME

_LOGGER = logging.getLogger(__name__)

Expand All @@ -20,9 +17,9 @@


class MinerCoordinator(DataUpdateCoordinator):
"""Class to manage fetching update data from the IoTaWatt Energy Device."""
"""Class to manage fetching update data from the Miner."""

miner: pyasic.AnyMiner | None = None
miner: pyasic.AnyMiner = None

def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Initialize MinerCoordinator object."""
Expand Down Expand Up @@ -53,7 +50,20 @@ async def _async_update_data(self):
self.miner.username = miner_username
self.miner.pwd = miner_password

miner_data = await self.miner.get_data()
miner_data = await self.miner.get_data(
include=[
pyasic.DataOptions.HOSTNAME,
pyasic.DataOptions.MAC,
pyasic.DataOptions.IS_MINING,
pyasic.DataOptions.FW_VERSION,
pyasic.DataOptions.HASHRATE,
pyasic.DataOptions.EXPECTED_HASHRATE,
pyasic.DataOptions.HASHBOARDS,
pyasic.DataOptions.WATTAGE,
pyasic.DataOptions.WATTAGE_LIMIT,
pyasic.DataOptions.FANS,
]
)

except pyasic.APIError as err:
raise UpdateFailed("API Error") from err
Expand All @@ -73,7 +83,7 @@ async def _async_update_data(self):
"fw_ver": miner_data.fw_ver,
"miner_sensors": {
"hashrate": miner_data.hashrate,
"ideal_hashrate": miner_data.nominal_hashrate,
"ideal_hashrate": miner_data.expected_hashrate,
"temperature": miner_data.temperature_avg,
"power_limit": miner_data.wattage_limit,
"miner_consumption": miner_data.wattage,
Expand All @@ -87,5 +97,8 @@ async def _async_update_data(self):
}
for board in miner_data.hashboards
},
"fan_sensors": {
idx: {"fan_speed": fan.speed} for idx, fan in enumerate(miner_data.fans)
},
}
return data
2 changes: 1 addition & 1 deletion custom_components/miner/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"homekit": {},
"iot_class": "local_polling",
"issue_tracker": "https://github.com/Schnitzel/hass-miner/issues",
"requirements": ["pyasic==0.40.3"],
"requirements": ["pyasic==0.45.1"],
"ssdp": [],
"version": "1.0.1",
"zeroconf": []
Expand Down
60 changes: 45 additions & 15 deletions custom_components/miner/number.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
"""Support for IoTaWatt Energy monitor."""
"""Support for Bitcoin ASIC miners."""
from __future__ import annotations

import logging

import pyasic
from homeassistant.components.number import NumberEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import callback
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from pyasic.miners.backends import BOSMiner

from .const import (
DOMAIN,
)
from .const import DOMAIN
from .coordinator import MinerCoordinator

_LOGGER = logging.getLogger(__name__)
Expand All @@ -35,13 +33,14 @@ def _create_entity(key: str):
created.add(key)

await coordinator.async_config_entry_first_refresh()
async_add_entities(
[
MinerPowerLimitNumber(
coordinator=coordinator,
)
]
)
if coordinator.miner.supports_autotuning:
async_add_entities(
[
MinerPowerLimitNumber(
coordinator=coordinator,
)
]
)

# @callback
# def new_data_received():
Expand Down Expand Up @@ -118,7 +117,35 @@ async def async_set_native_value(self, value):
f"{self.coordinator.entry.title} does not support setting power limit."
)

result = await miner.set_power_limit(int(value))
if isinstance(miner, BOSMiner):
max_diff = 500
try:
try:
current_value = self._attr_native_value
diff = int(value) - int(current_value)
smooth_tune = -max_diff < diff < max_diff

if smooth_tune:
if diff < 0:
result = await miner.web.grpc.decrement_power_target(
abs(diff)
)
else:
result = await miner.web.grpc.increment_power_target(
abs(diff)
)
else:
result = await miner.web.grpc.set_power_target(int(value))
except TypeError:
result = await miner.web.grpc.set_power_target(int(value))
except pyasic.APIError:
result = await miner.set_power_limit(int(value))

else:
result = await miner.set_power_limit(
int(value)
) # noqa: ignore miner being assumed to be None

if not result:
raise pyasic.APIError("Failed to set wattage.")

Expand All @@ -127,6 +154,9 @@ async def async_set_native_value(self, value):

@callback
def _handle_coordinator_update(self) -> None:
self._attr_native_value = self.coordinator.data["miner_sensors"]["power_limit"]
if self.coordinator.data["miner_sensors"]["power_limit"] is not None:
self._attr_native_value = self.coordinator.data["miner_sensors"][
"power_limit"
]

super()._handle_coordinator_update()
Loading

0 comments on commit 1a494b8

Please sign in to comment.