Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
juanillo62gm committed Nov 15, 2024
2 parents d57c88f + 6e94fee commit 5e779e6
Show file tree
Hide file tree
Showing 10 changed files with 249 additions and 125 deletions.
2 changes: 1 addition & 1 deletion .devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "juanillo62gm/panda_pwr",
"image": "mcr.microsoft.com/devcontainers/python:3.12",
"postCreateCommand": "scripts/setup",
"postCreateCommand": "scripts/setup.sh",
"forwardPorts": [8123],
"portsAttributes": {
"8123": {
Expand Down
2 changes: 2 additions & 0 deletions custom_components/pandapwr/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""PandaPWR integration for Home Assistant."""

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
Expand Down
59 changes: 38 additions & 21 deletions custom_components/pandapwr/api.py
Original file line number Diff line number Diff line change
@@ -1,44 +1,61 @@
"""API client for interacting with PandaPWR devices."""

import aiohttp
import async_timeout

HTTP_OK = 200


class PandaPWRApi:
def __init__(self, ip_address: str):
"""API client for PandaPWR devices."""

def __init__(self, ip_address: str) -> None:
"""Initialize the API client."""
self._base_url = f"http://{ip_address}"
self._session = aiohttp.ClientSession()

async def test_connection(self) -> bool:
"""Test if the connection to the device can be established."""
try:
async with async_timeout.timeout(10):
async with self._session.get(
f"{self._base_url}/update_ele_data"
) as response:
return response.status == 200
except Exception:
async with (
async_timeout.timeout(10),
self._session.get(f"{self._base_url}/update_ele_data") as response,
):
return response.status == HTTP_OK
except aiohttp.ClientError:
return False

async def get_data(self) -> dict:
"""Fetch data from the device."""
async with async_timeout.timeout(10):
async with self._session.get(
f"{self._base_url}/update_ele_data"
) as response:
try:
async with (
async_timeout.timeout(10),
self._session.get(f"{self._base_url}/update_ele_data") as response,
):
return await response.json()
except aiohttp.ClientError:
return {}

async def set_power_state(self, state: int):
async def set_power_state(self, state: int) -> bool:
"""Set power state (0 for off, 1 for on) using RAW payload."""
payload = f"power={state}"
async with self._session.post(
f"{self._base_url}/set", data=payload
) as response:
return response.status == 200
try:
async with (
async_timeout.timeout(10),
self._session.post(f"{self._base_url}/set", data=payload) as response,
):
return response.status == HTTP_OK
except aiohttp.ClientError:
return False

async def set_usb_state(self, state: int):
async def set_usb_state(self, state: int) -> bool:
"""Set USB state (0 for off, 1 for on) using RAW payload."""
payload = f"usb={state}"
async with self._session.post(
f"{self._base_url}/set", data=payload
) as response:
return response.status == 200
try:
async with (
async_timeout.timeout(10),
self._session.post(f"{self._base_url}/set", data=payload) as response,
):
return response.status == HTTP_OK
except aiohttp.ClientError:
return False
62 changes: 43 additions & 19 deletions custom_components/pandapwr/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -1,37 +1,55 @@
from homeassistant.components.binary_sensor import BinarySensorEntity
"""Binary sensor platform for PandaPWR integration in Home Assistant."""

from typing import Any

import aiohttp
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import EntityCategory
from homeassistant.helpers.entity_platform import (
AddEntitiesCallback,
)

from .const import DOMAIN


async def async_setup_entry(hass, entry, async_add_entities):
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the binary sensor platform from a config entry."""
api = hass.data[DOMAIN][entry.entry_id]
async_add_entities(
[PowerStateBinarySensor(api, entry), UsbStateBinarySensor(api, entry)], True
[PowerStateBinarySensor(api, entry), UsbStateBinarySensor(api, entry)],
update_before_add=True,
)


class PandaPWRBinarySensor(BinarySensorEntity):
def __init__(self, api, entry):
"""Base class for a PandaPWR binary sensor."""

def __init__(self, api: Any, entry: ConfigEntry) -> None:
"""Initialize the binary sensor."""
self._api = api
self._entry = entry
self._attr_is_on = None
self._attr_available = False
self._device_id = f"pandapwr_{self._entry.data['ip_address']}"

async def async_update(self):
async def async_update(self) -> None:
"""Fetch new state data for the sensor."""
try:
data = await self._api.get_data()
self._attr_available = True
self.process_data(data)
except Exception:
except aiohttp.ClientError:
self._attr_available = False

async def async_added_to_hass(self):
async def async_added_to_hass(self) -> None:
"""Subscribe to update signal."""
self.async_on_remove(
async_dispatcher_connect(
Expand All @@ -40,7 +58,7 @@ async def async_added_to_hass(self):
)

@property
def device_info(self):
def device_info(self) -> dict:
"""Return device information for grouping in the UI."""
return {
"identifiers": {(DOMAIN, self._device_id)},
Expand All @@ -50,32 +68,38 @@ def device_info(self):
"sw_version": "1.0",
}

def process_data(self, data):
def process_data(self, data: Any) -> None:
"""Process data received from the API."""
raise NotImplementedError


class PowerStateBinarySensor(PandaPWRBinarySensor):
def __init__(self, api, entry):
"""Binary sensor for monitoring the power state of a PandaPWR device."""

def __init__(self, api: Any, entry: ConfigEntry) -> None:
"""Initialize the PowerStateBinarySensor."""
super().__init__(api, entry)
self._attr_name = "Power State"
self._attr_device_class = "power"
self._attr_device_class = BinarySensorDeviceClass.POWER
self._attr_entity_category = EntityCategory.DIAGNOSTIC
self._attr_unique_id = f"{self._device_id}_power_state"

def process_data(self, data):
def process_data(self, data: Any) -> None:
"""Process power state data from the API."""
self._attr_is_on = data.get("power_state") == 1


class UsbStateBinarySensor(PandaPWRBinarySensor):
def __init__(self, api, entry):
"""Binary sensor for monitoring the USB state of a PandaPWR device."""

def __init__(self, api: Any, entry: ConfigEntry) -> None:
"""Initialize the UsbStateBinarySensor."""
super().__init__(api, entry)
self._attr_name = "USB State"
self._attr_device_class = "power" # Cambiado a "power" para mostrar "on/off"
self._attr_device_class = BinarySensorDeviceClass.POWER
self._attr_entity_category = EntityCategory.DIAGNOSTIC
self._attr_unique_id = f"{self._device_id}_usb_state"

def process_data(self, data):
self._attr_is_on = (
data.get("usb_state") == 1
) # Mostrar como "on" cuando es 1, "off" cuando es 0
def process_data(self, data: Any) -> None:
"""Process USB state data from the API."""
self._attr_is_on = data.get("usb_state") == 1
9 changes: 8 additions & 1 deletion custom_components/pandapwr/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"""Config flow for PandaPWR integration in Home Assistant."""

import voluptuous as vol
from homeassistant import config_entries

Expand All @@ -6,9 +8,14 @@


class PandaPWRConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for PandaPWR."""

VERSION = 1

async def async_step_user(self, user_input=None):
async def async_step_user(
self, user_input: dict | None = None
) -> config_entries.ConfigFlowResult:
"""Handle the initial step for setting up the integration."""
errors = {}
if user_input:
ip_address = user_input["ip_address"]
Expand Down
Loading

0 comments on commit 5e779e6

Please sign in to comment.