diff --git a/.github/workflows/hacs.yml b/.github/workflows/hacs.yml new file mode 100644 index 0000000..9e555c7 --- /dev/null +++ b/.github/workflows/hacs.yml @@ -0,0 +1,18 @@ +name: HACS Validation + +on: + push: + pull_request: + workflow_dispatch: + +jobs: + hacs: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: HACS validation + uses: hacs/action@main + with: + category: integration diff --git a/README.md b/README.md index 9845aec..6bc841f 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ To set up the integration, follow these steps: 5. Complete the setup. ## Version -This is version (v1.1.0) compatible with HACS! +This is version (v1.3.0) compatible with HACS! ## Screenshots diff --git a/custom_components/bitaxe/__init__.py b/custom_components/bitaxe/__init__.py index 59b55fc..fcc16d3 100644 --- a/custom_components/bitaxe/__init__.py +++ b/custom_components/bitaxe/__init__.py @@ -6,19 +6,21 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator from homeassistant.helpers.event import async_track_time_interval -DOMAIN = "bitaxe" +from .const import DOMAIN, CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL + _LOGGER = logging.getLogger(__name__) async def async_setup_entry(hass: HomeAssistant, entry: config_entries.ConfigEntry): ip_address = entry.data["ip_address"] device_id = entry.unique_id or ip_address + scan_interval = entry.options.get(CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL) coordinator = DataUpdateCoordinator( hass, _LOGGER, name=f"BitAxe Sensor Data ({device_id})", update_method=lambda: fetch_bitaxe_data(ip_address), - update_interval=timedelta(seconds=30), + update_interval=timedelta(seconds=scan_interval), ) await coordinator.async_refresh() @@ -27,16 +29,29 @@ async def async_setup_entry(hass: HomeAssistant, entry: config_entries.ConfigEnt hass.data[DOMAIN] = {} hass.data[DOMAIN][device_id] = {"coordinator": coordinator} + # Add option to edit settings after creating instance + entry.async_on_unload( + entry.add_update_listener(_options_update_listener) + ) + await hass.config_entries.async_forward_entry_setups(entry, ["sensor"]) async_track_time_interval( hass, _update_coordinator(coordinator), - timedelta(seconds=30) + timedelta(seconds=scan_interval) ) return True +async def _options_update_listener(hass, entry): + await hass.config_entries.async_reload(entry.entry_id) + +async def async_unload_entry(hass, entry): + unload_ok = await hass.config_entries.async_unload_platforms(entry, ["sensor"]) + hass.data[DOMAIN].pop(entry.unique_id, None) + return unload_ok + def _update_coordinator(coordinator: DataUpdateCoordinator): async def refresh(now): await coordinator.async_request_refresh() diff --git a/custom_components/bitaxe/config_flow.py b/custom_components/bitaxe/config_flow.py index 8529271..25b2b56 100644 --- a/custom_components/bitaxe/config_flow.py +++ b/custom_components/bitaxe/config_flow.py @@ -1,9 +1,12 @@ import voluptuous as vol from homeassistant import config_entries from homeassistant.core import callback -import ipaddress # Import für IP-Adressenvalidierung +import ipaddress # Import für IP-Adressenvalidierung -from .const import DOMAIN +from .const import ( + DOMAIN, MIN_SCAN_INTERVAL, MAX_SCAN_INTERVAL, + CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL +) class BitAxeConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): VERSION = 1 @@ -15,6 +18,7 @@ async def async_step_user(self, user_input=None): if user_input is not None: ip_address = user_input["ip_address"] device_name = user_input["device_name"] + scan_interval = user_input[CONF_SCAN_INTERVAL] # Validierung der IP-Adresse try: @@ -24,7 +28,7 @@ async def async_step_user(self, user_input=None): return self.async_show_form( step_id="user", data_schema=self.get_data_schema(), - errors=errors + errors=errors, ) # Entry mit IP-Adresse und Gerätenamen erstellen @@ -33,32 +37,60 @@ async def async_step_user(self, user_input=None): return self.async_create_entry( title=device_name, - data={"ip_address": ip_address, "device_name": device_name} + data={ + "ip_address": ip_address, + "device_name": device_name, + }, + options={ + CONF_SCAN_INTERVAL: scan_interval, + }, ) return self.async_show_form( step_id="user", data_schema=self.get_data_schema(), - errors=errors + errors=errors, ) def get_data_schema(self): - """Return the schema for user input.""" + """Return the schema for user input and check for validity.""" return vol.Schema({ vol.Required("ip_address"): str, vol.Required("device_name"): str, + vol.Optional( + CONF_SCAN_INTERVAL, + default=DEFAULT_SCAN_INTERVAL, + ): vol.All( + vol.Coerce(int), + vol.Range(min=MIN_SCAN_INTERVAL, max=MAX_SCAN_INTERVAL), + ), }) - + @staticmethod @callback def async_get_options_flow(config_entry): - return BitAxeOptionsFlowHandler(config_entry) + return BitAxeOptionsFlowHandler() -class BitAxeOptionsFlowHandler(config_entries.OptionsFlow): - def __init__(self, config_entry): - """Initialize options flow.""" - self.config_entry = config_entry +class BitAxeOptionsFlowHandler(config_entries.OptionsFlow): async def async_step_init(self, user_input=None): """Manage the options.""" - return self.async_show_form(step_id="init") \ No newline at end of file + if user_input is not None: + return self.async_create_entry(title="", data=user_input) + + return self.async_show_form( + step_id="init", + data_schema=vol.Schema({ + vol.Optional( + CONF_SCAN_INTERVAL, + default=self.config_entry.options.get( + CONF_SCAN_INTERVAL, + DEFAULT_SCAN_INTERVAL, + ), + ): vol.All( + vol.Coerce(int), + vol.Range(min=MIN_SCAN_INTERVAL, max=MAX_SCAN_INTERVAL), + ), + }), + ) + diff --git a/custom_components/bitaxe/const.py b/custom_components/bitaxe/const.py index 4d33878..a41141d 100644 --- a/custom_components/bitaxe/const.py +++ b/custom_components/bitaxe/const.py @@ -1 +1,7 @@ DOMAIN = "bitaxe" + +CONF_SCAN_INTERVAL = "Polling_Rate_(s)" + +DEFAULT_SCAN_INTERVAL = 60 # seconds +MIN_SCAN_INTERVAL = 30 +MAX_SCAN_INTERVAL = 3600 diff --git a/custom_components/bitaxe/hacs.json b/custom_components/bitaxe/hacs.json deleted file mode 100644 index 2cd6512..0000000 --- a/custom_components/bitaxe/hacs.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "Bitaxe Home Assistant Integration", - "content_in_root": false, - "country": "DE", - "description": "Integration for monitoring BitAxe miners in Home Assistant", - "domains": ["bitaxe"], - "iot_class": "local_polling", - "render_readme": true, - "documentation": "https://github.com/DerMiika/Bitaxe-HA-Integration", - "version": "1.1.0", - "zip_release": false, - "filename": "custom_components/bitaxe", - "codeowners": ["@DerMiika"] -} diff --git a/custom_components/bitaxe/manifest.json b/custom_components/bitaxe/manifest.json index 45d3308..4d41adf 100644 --- a/custom_components/bitaxe/manifest.json +++ b/custom_components/bitaxe/manifest.json @@ -1,7 +1,7 @@ { "domain": "bitaxe", "name": "Bitaxe Home Assistant Integration", - "version": "v1.1.0", + "version": "v1.1.2", "config_flow": true, "documentation": "https://github.com/DerMiika/Bitaxe-HA-Integration", "issue_tracker": "https://github.com/DerMiika/Bitaxe-HA-Integration/issues", diff --git a/custom_components/bitaxe/sensor.py b/custom_components/bitaxe/sensor.py index 470926d..c633bb8 100644 --- a/custom_components/bitaxe/sensor.py +++ b/custom_components/bitaxe/sensor.py @@ -44,11 +44,17 @@ async def async_setup_entry(hass, entry, async_add_entities): async_add_entities(sensors, update_before_add=True) -def format_difficulty(value: int) -> str: - """Convert difficulty values into human-readable units.""" +def format_difficulty(value) -> str | None: + """Convert difficulty values into human-readable units (k, M, G, T, P, E).""" if value is None: return None + # AxeOS may return difficulty as string or float + try: + value = float(value) + except (ValueError, TypeError): + return str(value) + units = [ (1e18, "E"), (1e15, "P"), @@ -62,7 +68,8 @@ def format_difficulty(value: int) -> str: if value >= factor: return f"{value / factor:.2f} {suffix}" - return str(value) + return str(int(value)) + class BitAxeSensor(Entity): diff --git a/hacs.json b/hacs.json index 6f34860..592e9af 100644 --- a/hacs.json +++ b/hacs.json @@ -1,5 +1,5 @@ { - "name": "Bitaxe Home Assistant Integration", + "name": "Bitaxe Monitoring", "content_in_root": false, "country": "DE", "description": "Integration for monitoring BitAxe miners in Home Assistant", @@ -7,9 +7,7 @@ "iot_class": "local_polling", "render_readme": true, "documentation": "https://github.com/DerMiika/Bitaxe-HA-Integration", - "version": "1.1.0", + "version": "1.3.0", "zip_release": false, "filename": "custom_components/bitaxe", - "codeowners": ["@DerMiika"] - "logo": "custom_components/bitaxe/images/bitaxe_icon.png" }