diff --git a/config_creation/manual_config.yaml b/config_creation/manual_config.yaml
index 5b9df98..4d1d75f 100644
--- a/config_creation/manual_config.yaml
+++ b/config_creation/manual_config.yaml
@@ -18,6 +18,13 @@ homeassistant:
cover.*:
half_position: 25
+dimmer:
+
+#logger:
+# default: info
+# logs:
+# xknx.telegram: debug
+# xknx.knx: debug
# Sensors
#sensor:
@@ -25,23 +32,41 @@ homeassistant:
# - platform: yr
# Text to speech
+#tts:
+## - platform: google_translate
+# language: 'de'
+# base_url: http://192.168.178.73:8123
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:
rate_limit: 20
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
port: 3671
- local_ip: 192.168.178.74
+ local_ip: 192.168.178.73
fhem:
- host: 192.168.178.80
+ host: server
port: 7072
cul_device_name: CUL_HM
+media_player:
+ - platform: squeezebox
+ host: server
+ - platform: denonavr
+ host: avreceiver
+
+
+
+
+
group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
diff --git a/custom_components/dimmer/__init__.py b/custom_components/dimmer/__init__.py
new file mode 100644
index 0000000..d4b057c
--- /dev/null
+++ b/custom_components/dimmer/__init__.py
@@ -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
diff --git a/custom_components/dimmer/services.yaml b/custom_components/dimmer/services.yaml
new file mode 100644
index 0000000..ed4ba52
--- /dev/null
+++ b/custom_components/dimmer/services.yaml
@@ -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
diff --git a/fhem/README.md b/custom_components/fhem/README.md
similarity index 100%
rename from fhem/README.md
rename to custom_components/fhem/README.md
diff --git a/fhem/__init__.py b/custom_components/fhem/__init__.py
similarity index 93%
rename from fhem/__init__.py
rename to custom_components/fhem/__init__.py
index 63cb262..e7b16d6 100644
--- a/fhem/__init__.py
+++ b/custom_components/fhem/__init__.py
@@ -48,6 +48,10 @@ class FhemConnection:
def register_device(self, id, d):
self._devices[id].append(d)
+ if self._writer:
+ self._writer.writelines([
+ "displayattr .*\n".encode(),
+ ])
async def _update_all_devices(self):
for device_list in self._devices.values():
@@ -80,6 +84,9 @@ class FhemConnection:
])
while self._run:
line = await reader.readline()
+ if not line:
+ _LOGGER.warning("FHEM disconnected: {}".format(line))
+ raise OSError("Disconnect")
line = line.decode()
_LOGGER.debug("FHEM received line: {}".format(line))
await self._process_line(line)
@@ -87,13 +94,13 @@ class FhemConnection:
if self._connection_last_state != 'FAILED':
self.hass.components.persistent_notification.async_create("FHEM connection failed",
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.connected = False
await self._update_all_devices()
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())
async def _process_line(self, line):
diff --git a/fhem/binary_sensor.py b/custom_components/fhem/binary_sensor.py
similarity index 100%
rename from fhem/binary_sensor.py
rename to custom_components/fhem/binary_sensor.py
diff --git a/fhem/cover.py b/custom_components/fhem/cover.py
similarity index 97%
rename from fhem/cover.py
rename to custom_components/fhem/cover.py
index af2ac6b..70137d5 100644
--- a/fhem/cover.py
+++ b/custom_components/fhem/cover.py
@@ -88,7 +88,8 @@ class FhemCover(CoverDevice):
_, new_motor_state, new_position = line.split(':')
new_position = new_position.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_position == 'on':
self._position = 100
diff --git a/fhem/light.py b/custom_components/fhem/light.py
similarity index 89%
rename from fhem/light.py
rename to custom_components/fhem/light.py
index 5cd3c27..bfaf735 100644
--- a/fhem/light.py
+++ b/custom_components/fhem/light.py
@@ -73,22 +73,19 @@ class FhemLight(Light):
return None
async def async_turn_on(self, **kwargs):
- brightness = kwargs.get(ATTR_BRIGHTNESS, self.brightness)
- transition_time = kwargs.get(ATTR_TRANSITION, None)
+ brightness = kwargs.get(ATTR_BRIGHTNESS, None)
+ transition_time = kwargs.get(ATTR_TRANSITION, 0.5)
if brightness is None:
brightness = 255
-
if self._dimmer:
- if transition_time is not None:
- # zero in the middle is the time until light is switched off,
- # which is disabled here when passing 0
- self.connection.fhem_set(self._ids[0], brightness / 255 * 100, 0, transition_time)
- else:
- self.connection.fhem_set(self._ids[0], brightness / 255 * 100)
+ # zero in the middle is the time until light is switched off,
+ # which is disabled here when passing 0
+ self.connection.fhem_set(self._ids[0], int(brightness / 255 * 100), 0, transition_time)
else:
self.connection.fhem_set(self._ids[0], 'on')
self._brightness = brightness
+ await self.async_update_ha_state()
async def async_turn_off(self, **kwargs):
self.connection.fhem_set(self._ids[0], 'off')
diff --git a/fhem/manifest.json b/custom_components/fhem/manifest.json
similarity index 100%
rename from fhem/manifest.json
rename to custom_components/fhem/manifest.json
diff --git a/fhem/sensor.py b/custom_components/fhem/sensor.py
similarity index 100%
rename from fhem/sensor.py
rename to custom_components/fhem/sensor.py
diff --git a/fhem/switch.py b/custom_components/fhem/switch.py
similarity index 100%
rename from fhem/switch.py
rename to custom_components/fhem/switch.py
diff --git a/todo b/todo
index 6da4cc8..ac64dc1 100644
--- a/todo
+++ b/todo
@@ -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 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 brighter/darker action (service!)
+
+
+- add scenes
+
+LIRC connection:
+ -
+
+Squeezebox:
+ - standard setup
+ - radio service
FHEM:
- - reconnection & message reporting code!
- - add FHEM shutters [ok]
- - motion detector [ok]
- - service for device stuff (up/down time, auto-off stuff)
- - check FHEM reconnection
- - what happens when FHEM stops?
+ - check FHEM reconnection [ok]
+ - what happens when FHEM stops? [ok]
- what happens when stick is pulled?
Owntracks
- try basic owntracks setup
-
Other:
- grouped motion sensors (last motion where and when)
- media player card:
https://github.com/kalkih/mini-media-player
-
-2019-06-03 19:20:46 WARNING (MainThread) [xknx.log] Could not read value of 0/0/4
-2019-06-03 19:20:48 WARNING (MainThread) [xknx.log] Could not read value of 0/0/2
-