Skip to content

Commit

Permalink
Version 1.3.0
Browse files Browse the repository at this point in the history
- Preparation for weather module - weather icons added.
- .show_message service reworked - it is now possible to show multiple texts and images at once!
- Light entity has been revised here the old one must be deleted!
- The entire custom component has been tidied up a bit more clearly.
  • Loading branch information
gickowtf committed Nov 17, 2023
1 parent 1409a26 commit e2ffee1
Show file tree
Hide file tree
Showing 21 changed files with 161 additions and 73 deletions.
24 changes: 13 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,22 +125,24 @@ If you have any further questions, I will be happy to help.

You can use it for Push Notifications.
```
alias: Pixoo Notification
description: ""
alias: YOUR TITEL
trigger:
- platform: state
entity_id:
- event.ANY-EVENT
condition: []
- platform: YOUR PLATFORM
e.g. entity_id: YOUR ENTITY
action:
- service: divoom_pixoo.show_message
data:
entity_id: sensor.divoom_pixoo
message: HELLO WORLD
position: [0,0]
color: [255, 0, 255]
font: FONT_GICKO
mode: single
#If you want draw more than 1 Message u have to need more positions, colors and fonts too
messages: ["Message 1", "Message 2"]
positions: [[1, 1], [1, 20]]
colors: [[255, 0, 0], [0, 255, 0]]
fonts: ["FONT_GICKO", "FONT_PICO_8"]
#same as Messages at images u need for each image an image_positions
images : ["/config/custom_components/divoom_pixoo/img/sunpower.png",
"/config/custom_components/divoom_pixoo/img/haus.png"]
image_positions : [[1, 30],
[20, 30]]
```

## Font
Expand Down
17 changes: 9 additions & 8 deletions custom_components/divoom_pixoo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from homeassistant.helpers import config_validation as cv

DOMAIN = "divoom_pixoo"
VERSION = "1.2.0"


async def async_setup(hass: HomeAssistant, config: dict):
Expand Down Expand Up @@ -37,16 +38,16 @@ async def async_setup(hass: HomeAssistant, config: dict):
async def async_show_message(service: ServiceCall):
"""Handle the service call to show a message on the Pixoo device."""
entity_id = service.data.get('entity_id')
message = service.data.get('message')
position = service.data.get('position')
color = service.data.get('color')
font = service.data.get('font')
image = service.data.get('image')
image_position = service.data.get('image_position')

messages = service.data.get('messages')
positions = service.data.get('positions')
colors = service.data.get('colors')
fonts = service.data.get('fonts')
images = service.data.get('images', [])
image_positions = service.data.get('image_positions', [])
...
for entity in hass.data[DOMAIN].get('entities', []):
if entity.entity_id == entity_id:
await entity.async_show_message(message, position, color, font, image, image_position)
await entity.async_show_message(messages, positions, colors, fonts, images, image_positions)
break

# Service registrieren
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 21 additions & 2 deletions custom_components/divoom_pixoo/light.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
from homeassistant.components.light import (ATTR_BRIGHTNESS, PLATFORM_SCHEMA, LightEntity)
from homeassistant.const import CONF_IP_ADDRESS
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from . import DOMAIN
from . import DOMAIN, VERSION

from .pixoo64._pixoo import Pixoo
import logging
Expand Down Expand Up @@ -38,7 +39,7 @@ def setup_platform(
class DivoomLight(LightEntity):
def __init__(self, ip_address):
self._ip_address = ip_address
self._name = "divoom_pixoo"
self._name = "Divoom Pixoo 64 Light"
self._state = None
self._brightness = None
self._pixoo = Pixoo(self._ip_address)
Expand Down Expand Up @@ -69,3 +70,21 @@ def turn_off(self, **kwargs):

def update(self) -> None:
self._state = self._pixoo.get_state()

@property
def name(self):
return self._name

@property
def unique_id(self):
return f"divoom_pixoo_light"

@property
def device_info(self) -> DeviceInfo:
return DeviceInfo(
identifiers={(DOMAIN, self.unique_id)},
name=self.name,
manufacturer="Divoom",
model="Pixoo",
sw_version=VERSION,
)
6 changes: 6 additions & 0 deletions custom_components/divoom_pixoo/schemas/channel_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import voluptuous as vol
from homeassistant.helpers import config_validation as cv

CHANNEL_SCHEMA = vol.Schema({
vol.Required('number'): cv.positive_int,
})
6 changes: 6 additions & 0 deletions custom_components/divoom_pixoo/schemas/clockid_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import voluptuous as vol
from homeassistant.helpers import config_validation as cv

CLOCKID_SCHEMA = vol.Schema({
vol.Required('number'): cv.positive_int,
})
7 changes: 7 additions & 0 deletions custom_components/divoom_pixoo/schemas/image_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import voluptuous as vol
from homeassistant.helpers import config_validation as cv

IMAGE_SCHEMA = vol.Schema({
vol.Required('image'): cv.string,
vol.Required('position'): vol.All(cv.ensure_list, [cv.positive_int], vol.Length(min=2, max=2)),
})
17 changes: 17 additions & 0 deletions custom_components/divoom_pixoo/schemas/page_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import voluptuous as vol
from homeassistant.helpers import config_validation as cv
from .text_schema import TEXT_SCHEMA
from .image_schema import IMAGE_SCHEMA
from .pv_schema import PV_SCHEMA
from .channel_schema import CHANNEL_SCHEMA
from .clockid_schema import CLOCKID_SCHEMA

PAGE_SCHEMA = vol.Schema({
vol.Required('page'): cv.positive_int,
vol.Optional('condition'): cv.template,
vol.Optional('texts'): vol.All(cv.ensure_list, [TEXT_SCHEMA]),
vol.Optional('images'): vol.All(cv.ensure_list, [IMAGE_SCHEMA]),
vol.Optional('PV'): PV_SCHEMA,
vol.Optional('channel'): vol.All(cv.ensure_list, [CHANNEL_SCHEMA]),
vol.Optional('clockId'): vol.All(cv.ensure_list, [CLOCKID_SCHEMA]),
})
12 changes: 12 additions & 0 deletions custom_components/divoom_pixoo/schemas/pv_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# pv_schema.py
import voluptuous as vol
from homeassistant.helpers import config_validation as cv

PV_SCHEMA = vol.Schema({
vol.Required('power'): cv.string,
vol.Required('storage'): cv.string,
vol.Required('discharge'): cv.string,
vol.Required('powerhousetotal'): cv.string,
vol.Required('vomNetz'): cv.string,
vol.Required('time'): cv.string,
})
9 changes: 9 additions & 0 deletions custom_components/divoom_pixoo/schemas/text_schema.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import voluptuous as vol
from homeassistant.helpers import config_validation as cv

TEXT_SCHEMA = vol.Schema({
vol.Required('text'): cv.string,
vol.Required('position'): vol.All(cv.ensure_list, [cv.positive_int], vol.Length(min=2, max=2)),
vol.Required('font'): cv.string,
vol.Required('font_color'): vol.All(cv.ensure_list, [cv.positive_int], vol.Length(min=3, max=3)),
})
113 changes: 61 additions & 52 deletions custom_components/divoom_pixoo/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,70 +6,43 @@
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.helpers.entity import Entity
from homeassistant.const import CONF_IP_ADDRESS
from homeassistant.helpers.template import Template
from homeassistant.helpers.template import Template, TemplateError
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_platform
from . import DOMAIN
from .schemas.page_schema import PAGE_SCHEMA

from .pages.solar import solar

from .pixoo64._pixoo import Pixoo
from .pixoo64._font import FONT_PICO_8, FONT_GICKO


import logging

_LOGGER = logging.getLogger(__name__)


PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_IP_ADDRESS): cv.string,
vol.Optional('scan_interval'): cv.time_period,
vol.Required('pages'): vol.All(cv.ensure_list, [
vol.Schema({
vol.Required('page'): cv.positive_int,
vol.Optional('texts'): vol.All(cv.ensure_list, [
vol.Schema({
vol.Required('text'): cv.string,
vol.Required('position'): vol.All(cv.ensure_list, [cv.positive_int], vol.Length(min=2, max=2)),
vol.Required('font'): cv.string,
vol.Required('font_color'): vol.All(cv.ensure_list, [cv.positive_int], vol.Length(min=3, max=3)),
})
]),
vol.Optional('images'): vol.All(cv.ensure_list, [
vol.Schema({
vol.Required('image'): cv.string,
vol.Required('position'): vol.All(cv.ensure_list, [cv.positive_int], vol.Length(min=2, max=2)),
})
]),
vol.Optional('PV'): vol.All(cv.ensure_list, [
vol.Schema({
vol.Required('power'): cv.string,
vol.Required('storage'): cv.string,
vol.Required('discharge'): cv.string,
vol.Required('powerhousetotal'): cv.string,
vol.Required('vomNetz'): cv.string,
vol.Required('time'): cv.string,
})
]),
vol.Optional('channel'): vol.All(cv.ensure_list, [
vol.Schema({
vol.Required('number'): cv.positive_int,
})
]),
vol.Optional('clockId'): vol.All(cv.ensure_list, [
vol.Schema({
vol.Required('number'): cv.positive_int,
})
]),
})
]),
vol.Required('pages'): vol.All(cv.ensure_list, [PAGE_SCHEMA]),
})


async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
if discovery_info is None:
discovery_info = config.get(DOMAIN)
if discovery_info is None:
return
ip_address = discovery_info[CONF_IP_ADDRESS]
pages = discovery_info.get('pages', [])
for page in pages:
condition_template = page.get('condition')
if condition_template is not None:
try:
page['condition_template'] = Template(condition_template, hass)
except (TemplateError, ValueError) as e:
_LOGGER.error("Error in condition template: %s", e)
page['condition_template'] = None

scan_interval_config = discovery_info.get('scan_interval')
_LOGGER.debug("Scan interval config: %s", scan_interval_config)
Expand All @@ -86,6 +59,19 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
entity = Pixoo64(ip_address, pages, scan_interval)
async_add_entities([entity], True)

platform = entity_platform.current_platform.get()
platform.async_register_entity_service(
'show_message',
{
vol.Required('messages'): [cv.string],
vol.Required('positions'): [[cv.positive_int]],
vol.Required('colors'): [[cv.positive_int]],
vol.Required('fonts'): [cv.string],
vol.Optional('images', default=[]): [cv.string],
vol.Optional('image_positions', default=[]): [[cv.positive_int]],
},
'async_show_message',
)


class Pixoo64(Entity):
Expand Down Expand Up @@ -114,7 +100,7 @@ async def async_added_to_hass(self):
async def async_will_remove_from_hass(self):
"""When entity is being removed from hass."""
if self._update_interval is not None:
self._update_interval() # Dies stoppt das Zeitintervall
self._update_interval()
self._update_interval = None

async def _async_update(self, now=None):
Expand All @@ -125,11 +111,24 @@ async def _async_update_data(self):
if self.showing_notification:
return

self._current_page = self._pages[self._current_page_index]
current_page_data = self._pages[self._current_page_index]
_LOGGER.debug(f"current page: {current_page_data}")
self._current_page = self._pages[self._current_page_index]
self._attr_extra_state_attributes['page'] = self._current_page['page']
self._current_page_index = (self._current_page_index + 1) % len(self._pages)
self._attr_extra_state_attributes['page'] = current_page_data['page']


if 'condition_template' in current_page_data:
condition = current_page_data['condition_template']
condition.hass = self.hass
try:
if not condition.async_render():
self._current_page_index = (self._current_page_index + 1) % len(self._pages)
return
except TemplateError as e:
_LOGGER.error("Error rendering condition template: %s", e)
self._current_page_index = (self._current_page_index + 1) % len(self._pages)
return


def update():
pixoo = Pixoo(self._ip_address)
Expand Down Expand Up @@ -168,9 +167,13 @@ def update():
pixoo.push()

await self.hass.async_add_executor_job(update)
self._current_page_index = (self._current_page_index + 1) % len(self._pages)

async def async_show_message(self, message, position, color, font, image=None, image_position=None):
if self.hass is None:


async def async_show_message(self, messages, positions, colors, fonts, images=None, image_positions=None):
if not all([messages, positions, colors, fonts]) or len(messages) != len(positions) != len(colors) != len(fonts):
_LOGGER.error("Lists for messages, positions, colors, and fonts must all be present and have the same length.")
return

self.showing_notification = True
Expand All @@ -179,17 +182,23 @@ def draw():
pixoo = Pixoo(self._ip_address)
pixoo.clear()

if image and image_position:
pixoo.draw_image(image, tuple(image_position))
for img, img_pos in zip(images, image_positions):
pixoo.draw_image(img, tuple(img_pos))

for message, position, color, font in zip(messages, positions, colors, fonts):
selected_font = FONT_PICO_8 if font == 'FONT_PICO_8' else FONT_GICKO
if font == 'FONT_PICO_8':
pixoo.draw_text(message, tuple(position), tuple(color), selected_font)
else:
pixoo.draw_text(message.upper(), tuple(position), tuple(color), selected_font)

selected_font = FONT_PICO_8 if font == 'FONT_PICO_8' else FONT_GICKO
pixoo.draw_text(message, tuple(position), tuple(color), selected_font)
pixoo.push()

await self.hass.async_add_executor_job(draw)
await asyncio.sleep(self._scan_interval.total_seconds())
self.showing_notification = False


@property
def state(self):
return self._current_page['page']

0 comments on commit e2ffee1

Please sign in to comment.