Skip to content

Commit

Permalink
Images (#43)
Browse files Browse the repository at this point in the history
* Friendlier friendly names

* mdi icons for images to match sensors

* mdi icons for images to match sensors

* more icons

* last updated attribute

* semi-working animations

* semi-working animations

* working ish

* will need to test if this blocks when there's >1 core
  • Loading branch information
tcarwash authored Apr 18, 2024
1 parent 6f24da4 commit 649132a
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/configuration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ logger:
logs:
custom_components.noaa_space_weather: debug
# If you need to debug uncommment the line below (doc: https://www.home-assistant.io/integrations/debugpy/)
debugpy:
#debugpy:
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ pythonenv*
venv
.venv
config/*
swpclib/*
8 changes: 8 additions & 0 deletions custom_components/noaa_space_weather/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,11 @@ async def async_get_data(self) -> dict:
data = {}

return data

async def async_get_first_frame(self, product) -> bytes:
response_json = await self.swpc.get_data_method(product)
first_frame_url = response_json[0].get("url")
return await self.swpc.get_bytes_method(first_frame_url)

async def async_load_animation(self, product) -> bytes:
return await self.swpc.gen_gif(product)
107 changes: 106 additions & 1 deletion custom_components/noaa_space_weather/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from .const import DOMAIN, ICON
import logging
import asyncio
from .entity import NoaaSpaceWeatherImageEntity
from homeassistant.core import callback
from datetime import datetime
Expand All @@ -13,6 +14,38 @@
async def async_setup_entry(hass, entry, async_add_devices):
"""Setup camera platform."""
coordinator = hass.data[DOMAIN][entry.entry_id]
animationmap = [
{
"name": "Animated SUVI Secondary 284 Angstroms",
"product": "/products/animations/suvi-secondary-284.json",
"device_class": "animation",
},
{
"name": "Animated SUVI Primary 195 Angstroms",
"product": "/products/animations/suvi-primary-195.json",
"device_class": "animation",
},
{
"name": "Animated SUVI Primary 304 Angstroms",
"product": "/products/animations/suvi-primary-304.json",
"device_class": "animation",
},
{
"name": "Animated WFS Ionosphere",
"product": "/products/animations/wam-ipe/wfs_ionosphere_new.json",
"device_class": "animation",
},
{
"name": "Animated Lasco C2",
"product": "/products/animations/lasco-c2.json",
"device_class": "animation",
},
{
"name": "Animated Lasco C3",
"product": "/products/animations/lasco-c3.json",
"device_class": "animation",
},
]
imagemap = [
{
"name": "Ace Solar Wind 3 Hour",
Expand Down Expand Up @@ -40,10 +73,82 @@ async def async_setup_entry(hass, entry, async_add_devices):
},
]
async_add_devices(
[NoaaSpaceWeatherImage(coordinator, entry, image=i) for i in imagemap]
[NoaaSpaceWeatherImage(coordinator, entry, image=i) for i in imagemap],
update_before_add=True,
)
async_add_devices(
[NoaaSpaceWeatherAnimation(coordinator, entry, image=i) for i in animationmap],
)


class NoaaSpaceWeatherAnimation(NoaaSpaceWeatherImageEntity):
"""noaa_space_weather Image class."""

def __init__(self, coordinator, entry, image):
self.image_data = image
self.entry = entry
self.coordinator = coordinator
super().__init__(coordinator, entry)

@property
def unique_id(self):
return f"swpc {self.image_data['name']}"

@property
def name(self):
return self.image_data.get("name")

@property
def state(self):
if self._cached_image:
return "available"
else:
return "available"

@property
def device_class(self):
"""Return the device class of the image."""
return f"noaa_space_weather__{self.image_data.get('device_class', 'image')}"

@property
def icon(self):
"""Return the icon of the image."""
try:
icon = self.image_data["icon"]
except KeyError:
icon = ICON
return icon

async def async_update(self):
if not self._cached_image:
_LOGGER.debug(f"Returning still for {self.name}")
image_bytes = await self.coordinator.api.async_get_first_frame(
self.image_data["product"]
)
asyncio.run_coroutine_threadsafe(self.async_update(), self.hass.loop)
else:
_LOGGER.debug(f"Returning still for {self.name}")
image_bytes = await self.coordinator.api.async_load_animation(
self.image_data["product"]
)
_LOGGER.debug(f"Updated animation for {self.name}, caching image")
self._cached_image = image_bytes
self.image_last_updated = datetime.now()
self._attr_image_last_updated = self.image_last_updated
_LOGGER.debug(f"Writing {self.name} state")
return image_bytes

@callback
def _handle_coordinator_update(self):
self.image_last_updated = datetime.now()
self._attr_image_last_updated = self.image_last_updated
asyncio.run_coroutine_threadsafe(self.async_update(), self.hass.loop)
self.async_write_ha_state()

async def async_image(self):
return self._cached_image or await self.async_update()


class NoaaSpaceWeatherImage(NoaaSpaceWeatherImageEntity):
"""noaa_space_weather Image class."""

Expand Down
4 changes: 2 additions & 2 deletions custom_components/noaa_space_weather/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
"documentation": "https://github.com/tcarwash/home-assistant_noaa-space-weather",
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/tcarwash/home-assistant_noaa-space-weather/issues",
"requirements": ["swpclib>=4.2.0"],
"version": "2.1.0-beta"
"requirements": ["swpclib==4.3.6"],
"version": "2.1.0-beta3"
}

0 comments on commit 649132a

Please sign in to comment.