Skip to content

Commit

Permalink
Merge pull request #2 from stefanriegel/main
Browse files Browse the repository at this point in the history
Fix repository structure for HACS compatibility
  • Loading branch information
DerMiika authored Nov 14, 2024
2 parents 33bbd33 + 94c13e2 commit 963bdd9
Show file tree
Hide file tree
Showing 12 changed files with 41 additions and 60 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[![Release Downloads](https://img.shields.io/github/downloads/DerMiika/Bitaxe-HA-Integration/total)](https://github.com/DerMiika/Bitaxe-HA-Integration/releases)
[![GitHub issues](https://img.shields.io/github/issues/DerMiika/Bitaxe-HA-Integration)](https://github.com/DerMiika/Bitaxe-HA-Integration/issues)
[![Version - 1.0.1](https://img.shields.io/badge/version-1.0.1-blue)](https://github.com/DerMiika/Bitaxe-HA-Integration/releases)
[![Version - 1.0.2](https://img.shields.io/badge/version-1.0.2-blue)](https://github.com/DerMiika/Bitaxe-HA-Integration/releases)

This is a custom integration for Bitaxe miners in Home Assistant.

Expand Down
37 changes: 9 additions & 28 deletions __init__.py → custom_components/bitaxe/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,59 +9,40 @@
DOMAIN = "bitaxe"
_LOGGER = logging.getLogger(__name__)

# Mapping for sensor names
SENSOR_NAME_MAP = {
"power": "Power Consumption",
"temp": "Temperature",
"hashRate": "Hash Rate",
"bestDiff": "All-Time Best Difficulty",
"bestSessionDiff": "Best Difficulty Since System Boot",
"sharesAccepted": "Shares Accepted",
"sharesRejected": "Shares Rejected",
"fanspeed": "Fan Speed",
"fanrpm": "Fan RPM",
"uptimeSeconds": "Uptime",
}

async def async_setup_entry(hass: HomeAssistant, entry: config_entries.ConfigEntry):
"""Set up BitAxe from a config entry."""
ip_address = entry.data["ip_address"]
device_id = entry.unique_id or ip_address

# Create a coordinator for the data
coordinator = DataUpdateCoordinator(
hass,
_LOGGER,
name="BitAxe Sensor Data",
name=f"BitAxe Sensor Data ({device_id})",
update_method=lambda: fetch_bitaxe_data(ip_address),
update_interval=timedelta(seconds=30), # Intervall auf 30 Sekunden setzen
update_interval=timedelta(seconds=30),
)

# Start the coordinator
await coordinator.async_refresh()

# Store the coordinator in hass.data
hass.data[DOMAIN] = {"coordinator": coordinator}
if DOMAIN not in hass.data:
hass.data[DOMAIN] = {}
hass.data[DOMAIN][device_id] = {"coordinator": coordinator}

# Set up the sensor platform
await hass.config_entries.async_forward_entry_setups(entry, ["sensor"])

# Schedule the update interval without threading issues
async_track_time_interval(
hass,
_update_coordinator(coordinator), # Callback als Funktion übergeben
timedelta(seconds=30) # Update-Intervall auf 30 Sekunden
_update_coordinator(coordinator),
timedelta(seconds=30)
)

return True

def _update_coordinator(coordinator: DataUpdateCoordinator):
"""Create a function to refresh the coordinator safely."""
async def refresh(now):
await coordinator.async_request_refresh()
return refresh

async def fetch_bitaxe_data(ip_address):
"""Fetch data from the BitAxe API."""
url = f"http://{ip_address}/api/system/info"
try:
async with aiohttp.ClientSession() as session:
Expand All @@ -72,4 +53,4 @@ async def fetch_bitaxe_data(ip_address):
return data
except Exception as e:
_LOGGER.error("Error fetching data from BitAxe API: %s", e)
return None
return None
File renamed without changes.
Binary file added custom_components/bitaxe/bitaxe_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 4 additions & 1 deletion config_flow.py → custom_components/bitaxe/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ async def async_step_user(self, user_input=None):
)

# Entry mit IP-Adresse und Gerätenamen erstellen
await self.async_set_unique_id(ip_address) # Einzigartige ID auf IP-Adresse setzen
self._abort_if_unique_id_configured() # Sicherstellen, dass die IP-Adresse nicht doppelt hinzugefügt wird

return self.async_create_entry(
title=device_name,
data={"ip_address": ip_address, "device_name": device_name}
Expand Down Expand Up @@ -58,4 +61,4 @@ def __init__(self, config_entry):

async def async_step_init(self, user_input=None):
"""Manage the options."""
return self.async_show_form(step_id="init")
return self.async_show_form(step_id="init")
File renamed without changes.
File renamed without changes
File renamed without changes
9 changes: 5 additions & 4 deletions manifest.json → custom_components/bitaxe/manifest.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"domain": "bitaxe",
"name": "Bitaxe",
"version": "1.0.1",
"name": "Bitaxe Home Assistant Integration",
"version": "1.0.2",
"config_flow": true,
"documentation": "https://github.com/DerMiika/Bitaxe-HA-Integration",
"requirements": [],
"codeowners": ["@DerMiika"],
"iot_class": "local_push"
}
"iot_class": "local_polling",
"icon": "custom_components/bitaxe/bitaxe_icon.png"
}
38 changes: 17 additions & 21 deletions sensor.py → custom_components/bitaxe/sensor.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import logging
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator

# Set up logging for debugging
_LOGGER = logging.getLogger(__name__)

# Define the integration domain
DOMAIN = "bitaxe"

# Mapping for sensor-names
SENSOR_NAME_MAP = {
"power": "Power Consumption",
"temp": "Temperature",
Expand All @@ -23,10 +21,11 @@

async def async_setup_entry(hass, entry, async_add_entities):
"""Set up BitAxe sensors from a config entry."""
coordinator = hass.data[DOMAIN]["coordinator"]
device_name = entry.data["device_name"] # Gerätname abrufen
coordinator = hass.data[DOMAIN][entry.unique_id]["coordinator"]
device_name = entry.data.get("device_name", "default_device_name") # Geräte-Namen statt IP verwenden

_LOGGER.debug(f"Setting up sensors for device: {device_name}")

# Create sensors based on the fetched data from the coordinator
sensors = [
BitAxeSensor(coordinator, "power", device_name),
BitAxeSensor(coordinator, "temp", device_name),
Expand All @@ -40,45 +39,43 @@ async def async_setup_entry(hass, entry, async_add_entities):
BitAxeSensor(coordinator, "uptimeSeconds", device_name),
]

# Add sensors to Home Assistant with an initial update
async_add_entities(sensors, update_before_add=True)

class BitAxeSensor(Entity):
"""Representation of a BitAxe sensor."""

def __init__(self, coordinator, sensor_type, device_name):
"""Initialize the sensor with its type, data coordinator, and device name."""
def __init__(self, coordinator: DataUpdateCoordinator, sensor_type: str, device_name: str):
super().__init__()
self.coordinator = coordinator
self.sensor_type = sensor_type
self._attr_name = f"{device_name} {SENSOR_NAME_MAP.get(sensor_type, f'BitAxe {sensor_type.capitalize()}')}"
self._attr_unique_id = f"{DOMAIN}_{sensor_type}"
self._device_name = device_name
self._attr_name = f"{SENSOR_NAME_MAP.get(sensor_type, f'BitAxe {sensor_type.capitalize()}')} ({device_name})"
self._attr_unique_id = f"{device_name}_{sensor_type}" # Verwenden von device_name statt IP
self._attr_icon = self._get_icon(sensor_type)

_LOGGER.debug(f"Initialized BitAxeSensor: {self._attr_name} with unique ID: {self._attr_unique_id}")

@property
def state(self):
"""Return the state of the sensor."""
value = self.coordinator.data.get(self.sensor_type)
value = self.coordinator.data.get(self.sensor_type, None)

# Handle special formatting for uptime, power, and hash rate
if self.sensor_type == "uptimeSeconds" and value is not None:
return self._format_uptime(value)
elif self.sensor_type == "power" and value is not None:
return round(value, 1) # Round power to one decimal place
return round(value, 1)
elif self.sensor_type == "hashRate" and value is not None:
return int(value) # Display hash rate in GH/s as an integer
return value
return int(value)
return value if value is not None else "N/A"

@staticmethod
def _format_uptime(seconds):
"""Convert uptime in seconds to a readable format."""
days, remainder = divmod(seconds, 86400)
hours, remainder = divmod(remainder, 3600)
minutes, seconds = divmod(remainder, 60)
return f"{days}d {hours}h {minutes}m {seconds}s"

@property
def unit_of_measurement(self):
"""Return the unit of measurement for each sensor."""
if self.sensor_type == "power":
return "W"
elif self.sensor_type == "hashRate":
Expand All @@ -92,7 +89,6 @@ def unit_of_measurement(self):
return None

def _get_icon(self, sensor_type):
"""Return the appropriate MDI icon for each sensor type."""
if sensor_type == "bestSessionDiff":
return "mdi:star"
elif sensor_type == "bestDiff":
Expand All @@ -111,4 +107,4 @@ def _get_icon(self, sensor_type):
return "mdi:thermometer"
elif sensor_type == "uptimeSeconds":
return "mdi:clock"
return "mdi:help-circle" # Default icon if none matched
return "mdi:help-circle"
File renamed without changes.
10 changes: 5 additions & 5 deletions hacs.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
{
"name": "BitAxe",
"name": "Bitaxe Home Assistant Integration",
"content_in_root": false,
"country": "DE",
"description": "Integration for monitoring BitAxe miners in Home Assistant",
"domain": "bitaxe",
"iot_class": "local_push",
"domains": ["bitaxe"],
"iot_class": "local_polling",
"render_readme": true,
"documentation": "https://github.com/DerMiika/Bitaxe-HA-Integration",
"issue_tracker": "https://github.com/DerMiika/Bitaxe-HA-Integration/issues",
"version": "1.0.1",
"version": "1.0.2",
"zip_release": false,
"filename": "custom_components/bitaxe"
"filename": "custom_components/bitaxe",
"category": "integration"
}

0 comments on commit 963bdd9

Please sign in to comment.