Dimmer service

This commit is contained in:
Martin Bauer 2019-06-19 16:12:22 +02:00
parent 72b4d38e80
commit 20f43f4294
12 changed files with 146 additions and 45 deletions

View File

@ -18,6 +18,13 @@ homeassistant:
cover.*: cover.*:
half_position: 25 half_position: 25
dimmer:
#logger:
# default: info
# logs:
# xknx.telegram: debug
# xknx.knx: debug
# Sensors # Sensors
#sensor: #sensor:
@ -25,23 +32,41 @@ homeassistant:
# - platform: yr # - platform: yr
# Text to speech # Text to speech
#tts:
## - platform: google_translate
# language: 'de'
# base_url: http://192.168.178.73:8123
tts: tts:
- platform: google_translate - platform: watson_tts
watson_apikey: X_tnnoaZGOwxZlqUn07wkD2G-0vaaAuOw6I6d_6jpCf7
watson_url: https://gateway-lon.watsonplatform.net/text-to-speech/api
voice: de-DE_BirgitVoice
output_format: audio/flac;rate=44100
knx: knx:
rate_limit: 20 rate_limit: 20
tunneling: tunneling:
host: 192.168.178.80 # knxd to work together with old home automation server host: server # knxd to work together with old home automation server
#host: 192.168.178.65 # network bridge #host: 192.168.178.65 # network bridge
port: 3671 port: 3671
local_ip: 192.168.178.74 local_ip: 192.168.178.73
fhem: fhem:
host: 192.168.178.80 host: server
port: 7072 port: 7072
cul_device_name: CUL_HM cul_device_name: CUL_HM
media_player:
- platform: squeezebox
host: server
- platform: denonavr
host: avreceiver
group: !include groups.yaml group: !include groups.yaml
automation: !include automations.yaml automation: !include automations.yaml
script: !include scripts.yaml script: !include scripts.yaml

View File

@ -0,0 +1,70 @@
""" Service to increase/decrease light brightness"""
import logging
import voluptuous as vol
from homeassistant.components.light import ATTR_BRIGHTNESS, DOMAIN as LIGHT_DOMAIN, ATTR_TRANSITION
from homeassistant.const import SERVICE_TURN_ON, ATTR_ENTITY_ID
# The domain of your component. Should be equal to the name of your component.
from homeassistant.helpers.service import async_extract_entity_ids
DOMAIN = "dimmer"
# List of component names (string) your component depends upon.
# We depend on group because group will be loaded after all the components that
# initialize devices have been setup.
DEPENDENCIES = ['group', 'light']
# Name of the service that we expose.
SERVICE_DIM = 'dim'
# Shortcut for the logger
_LOGGER = logging.getLogger(__name__)
# Validate that all required config options are given.
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({})
}, extra=vol.ALLOW_EXTRA)
async def async_setup(hass, config):
"""Setup example component."""
async def async_dim_service(service):
params = service.data.copy()
entity_ids = await async_extract_entity_ids(hass, service, expand_group=True)
offset = params.get('offset', None)
factor = params.get('factor', None)
min_brightness = params.get('min_brightness', 6)
transition = params.get(ATTR_TRANSITION, None)
if factor is None and offset is None:
offset = 50
assert not (factor is not None and offset is not None)
def clip_value(level):
level = int(level)
if level < min_brightness:
return min_brightness
if level > 255:
return 255
return level
for entity_id in entity_ids:
brightness = hass.states.get(entity_id).attributes.get('brightness', 0)
if factor is not None:
data = {ATTR_BRIGHTNESS: clip_value(brightness * factor)}
if offset is not None:
data = {ATTR_BRIGHTNESS: clip_value(brightness + offset)}
data[ATTR_ENTITY_ID] = entity_id
if transition:
data[ATTR_TRANSITION] = transition
await hass.services.async_call(LIGHT_DOMAIN, SERVICE_TURN_ON, data)
hass.services.async_register(DOMAIN, SERVICE_DIM, async_dim_service)
return True

View File

@ -0,0 +1,17 @@
dim:
description: Increases or decreases brightness of lights
fields:
entity_id:
description: Name(s) of entities or groups
example: 'light.living_room'
offset:
description: New light value is old value plus this offset (full brightness is 255).
Can be negative to decrease brightness
example: 30
factor:
description: Factor to multiply old light value with. Use either offset or factor, not both!
example: 1.3
transition:
description: transition time in seconds
example: 1

View File

@ -48,6 +48,10 @@ class FhemConnection:
def register_device(self, id, d): def register_device(self, id, d):
self._devices[id].append(d) self._devices[id].append(d)
if self._writer:
self._writer.writelines([
"displayattr .*\n".encode(),
])
async def _update_all_devices(self): async def _update_all_devices(self):
for device_list in self._devices.values(): for device_list in self._devices.values():
@ -80,6 +84,9 @@ class FhemConnection:
]) ])
while self._run: while self._run:
line = await reader.readline() line = await reader.readline()
if not line:
_LOGGER.warning("FHEM disconnected: {}".format(line))
raise OSError("Disconnect")
line = line.decode() line = line.decode()
_LOGGER.debug("FHEM received line: {}".format(line)) _LOGGER.debug("FHEM received line: {}".format(line))
await self._process_line(line) await self._process_line(line)
@ -87,13 +94,13 @@ class FhemConnection:
if self._connection_last_state != 'FAILED': if self._connection_last_state != 'FAILED':
self.hass.components.persistent_notification.async_create("FHEM connection failed", self.hass.components.persistent_notification.async_create("FHEM connection failed",
title="No FHEM connection") title="No FHEM connection")
_LOGGER.error("Connection to FHEM failed {}:{}".format(self._host, self._port)) _LOGGER.error("Connection to FHEM failed {}:{}".format(self._host, self._port))
self._connection_last_state = 'FAILED' self._connection_last_state = 'FAILED'
self.connected = False self.connected = False
await self._update_all_devices() await self._update_all_devices()
await asyncio.sleep(self.reconnect_time) await asyncio.sleep(self.reconnect_time)
self.reconnect_time = min(2 * self.reconnect_time, self.reconnect_time) self.reconnect_time = min(2 * self.reconnect_time, self.reconnect_time_max)
self.hass.loop.create_task(self._connection()) self.hass.loop.create_task(self._connection())
async def _process_line(self, line): async def _process_line(self, line):

View File

@ -88,7 +88,8 @@ class FhemCover(CoverDevice):
_, new_motor_state, new_position = line.split(':') _, new_motor_state, new_position = line.split(':')
new_position = new_position.strip().lower() new_position = new_position.strip().lower()
new_motor_state = new_motor_state.strip().lower() new_motor_state = new_motor_state.strip().lower()
assert new_motor_state == 'stop' or new_motor_state == 'up' or new_motor_state == 'down' assert new_motor_state == 'stop' or new_motor_state == 'up' or new_motor_state == 'down', \
'Unknown motor state ' + new_motor_state
if new_motor_state == 'stop': if new_motor_state == 'stop':
if new_position == 'on': if new_position == 'on':
self._position = 100 self._position = 100

View File

@ -73,22 +73,19 @@ class FhemLight(Light):
return None return None
async def async_turn_on(self, **kwargs): async def async_turn_on(self, **kwargs):
brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness) brightness = kwargs.get(ATTR_BRIGHTNESS, None)
transition_time = kwargs.get(ATTR_TRANSITION, None) transition_time = kwargs.get(ATTR_TRANSITION, 0.5)
if brightness is None: if brightness is None:
brightness = 255 brightness = 255
if self._dimmer: if self._dimmer:
if transition_time is not None: # zero in the middle is the time until light is switched off,
# zero in the middle is the time until light is switched off, # which is disabled here when passing 0
# which is disabled here when passing 0 self.connection.fhem_set(self._ids[0], int(brightness / 255 * 100), 0, transition_time)
self.connection.fhem_set(self._ids[0], brightness / 255 * 100, 0, transition_time)
else:
self.connection.fhem_set(self._ids[0], brightness / 255 * 100)
else: else:
self.connection.fhem_set(self._ids[0], 'on') self.connection.fhem_set(self._ids[0], 'on')
self._brightness = brightness self._brightness = brightness
await self.async_update_ha_state()
async def async_turn_off(self, **kwargs): async def async_turn_off(self, **kwargs):
self.connection.fhem_set(self._ids[0], 'off') self.connection.fhem_set(self._ids[0], 'off')

40
todo
View File

@ -1,44 +1,28 @@
- add fhem devices [ok]
- generate config [ok]
- test config [ok]
- add shutters [ok]
- add sensors [ok]
- check out read addresses [ok]
- in bus monitor [ok]
- KNX config files -> add to git [ok]
- configure frontend [ok] - add brighter/darker action (service!)
- add scenes
- add brighter/darker action (service!)
- fix door light [ok]
- check out motion detectors in frontend
- check out shutters in frontend
Frontend:
- change cover state card for half open [ok] - add scenes
LIRC connection:
-
Squeezebox:
- standard setup
- radio service
FHEM: FHEM:
- reconnection & message reporting code! - check FHEM reconnection [ok]
- add FHEM shutters [ok] - what happens when FHEM stops? [ok]
- motion detector [ok]
- service for device stuff (up/down time, auto-off stuff)
- check FHEM reconnection
- what happens when FHEM stops?
- what happens when stick is pulled? - what happens when stick is pulled?
Owntracks Owntracks
- try basic owntracks setup - try basic owntracks setup
Other: Other:
- grouped motion sensors (last motion where and when) - grouped motion sensors (last motion where and when)
- media player card: - media player card:
https://github.com/kalkih/mini-media-player https://github.com/kalkih/mini-media-player
2019-06-03 19:20:46 WARNING (MainThread) [xknx.log] Could not read value of <Light name="Haustür Licht NW" switch="GroupAddress("0/0/3")/GroupAddress("0/0/4")/None/None" /> 0/0/4
2019-06-03 19:20:48 WARNING (MainThread) [xknx.log] Could not read value of <Light name="Haustür Licht" switch="GroupAddress("0/0/1")/GroupAddress("0/0/2")/None/None" /> 0/0/2