homematic update to pyhomematic 0.1.9
This commit is contained in:
parent
ce4891fe8e
commit
c023d1d656
4 changed files with 161 additions and 50 deletions
|
@ -4,71 +4,120 @@ Support for Homematic devices.
|
||||||
For more details about this component, please refer to the documentation at
|
For more details about this component, please refer to the documentation at
|
||||||
https://home-assistant.io/components/homematic/
|
https://home-assistant.io/components/homematic/
|
||||||
"""
|
"""
|
||||||
|
import os
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from homeassistant.const import EVENT_HOMEASSISTANT_STOP, STATE_UNKNOWN
|
import voluptuous as vol
|
||||||
from homeassistant.helpers import discovery
|
|
||||||
|
from homeassistant.const import (EVENT_HOMEASSISTANT_STOP, STATE_UNKNOWN,
|
||||||
|
CONF_USERNAME, CONF_PASSWORD)
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
from homeassistant.helpers import discovery
|
||||||
|
from homeassistant.config import load_yaml_config_file
|
||||||
|
|
||||||
DOMAIN = 'homematic'
|
DOMAIN = 'homematic'
|
||||||
REQUIREMENTS = ['pyhomematic==0.1.8']
|
REQUIREMENTS = ["pyhomematic==0.1.9"]
|
||||||
|
|
||||||
HOMEMATIC = None
|
HOMEMATIC = None
|
||||||
HOMEMATIC_LINK_DELAY = 0.5
|
HOMEMATIC_LINK_DELAY = 0.5
|
||||||
|
|
||||||
DISCOVER_SWITCHES = "homematic.switch"
|
DISCOVER_SWITCHES = 'homematic.switch'
|
||||||
DISCOVER_LIGHTS = "homematic.light"
|
DISCOVER_LIGHTS = 'homematic.light'
|
||||||
DISCOVER_SENSORS = "homematic.sensor"
|
DISCOVER_SENSORS = 'homematic.sensor'
|
||||||
DISCOVER_BINARY_SENSORS = "homematic.binary_sensor"
|
DISCOVER_BINARY_SENSORS = 'homematic.binary_sensor'
|
||||||
DISCOVER_ROLLERSHUTTER = "homematic.rollershutter"
|
DISCOVER_ROLLERSHUTTER = 'homematic.rollershutter'
|
||||||
DISCOVER_THERMOSTATS = "homematic.thermostat"
|
DISCOVER_THERMOSTATS = 'homematic.thermostat'
|
||||||
|
|
||||||
ATTR_DISCOVER_DEVICES = "devices"
|
ATTR_DISCOVER_DEVICES = 'devices'
|
||||||
ATTR_PARAM = "param"
|
ATTR_PARAM = 'param'
|
||||||
ATTR_CHANNEL = "channel"
|
ATTR_CHANNEL = 'channel'
|
||||||
ATTR_NAME = "name"
|
ATTR_NAME = 'name'
|
||||||
ATTR_ADDRESS = "address"
|
ATTR_ADDRESS = 'address'
|
||||||
|
|
||||||
EVENT_KEYPRESS = "homematic.keypress"
|
EVENT_KEYPRESS = 'homematic.keypress'
|
||||||
|
EVENT_IMPULSE = 'homematic.impulse'
|
||||||
|
|
||||||
|
SERVICE_VIRTUALKEY = 'virtualkey'
|
||||||
|
|
||||||
HM_DEVICE_TYPES = {
|
HM_DEVICE_TYPES = {
|
||||||
DISCOVER_SWITCHES: ["Switch", "SwitchPowermeter"],
|
DISCOVER_SWITCHES: ['Switch', 'SwitchPowermeter'],
|
||||||
DISCOVER_LIGHTS: ["Dimmer"],
|
DISCOVER_LIGHTS: ['Dimmer'],
|
||||||
DISCOVER_SENSORS: ["SwitchPowermeter", "Motion", "MotionV2",
|
DISCOVER_SENSORS: ['SwitchPowermeter', 'Motion', 'MotionV2',
|
||||||
"RemoteMotion", "ThermostatWall", "AreaThermostat",
|
'RemoteMotion', 'ThermostatWall', 'AreaThermostat',
|
||||||
"RotaryHandleSensor", "WaterSensor"],
|
'RotaryHandleSensor', 'WaterSensor', 'PowermeterGas',
|
||||||
DISCOVER_THERMOSTATS: ["Thermostat", "ThermostatWall", "MAXThermostat"],
|
'LuxSensor'],
|
||||||
DISCOVER_BINARY_SENSORS: ["ShutterContact", "Smoke", "SmokeV2",
|
DISCOVER_THERMOSTATS: ['Thermostat', 'ThermostatWall', 'MAXThermostat'],
|
||||||
"Motion", "MotionV2", "RemoteMotion"],
|
DISCOVER_BINARY_SENSORS: ['ShutterContact', 'Smoke', 'SmokeV2', 'Motion',
|
||||||
DISCOVER_ROLLERSHUTTER: ["Blind"]
|
'MotionV2', 'RemoteMotion'],
|
||||||
|
DISCOVER_ROLLERSHUTTER: ['Blind']
|
||||||
}
|
}
|
||||||
|
|
||||||
HM_IGNORE_DISCOVERY_NODE = [
|
HM_IGNORE_DISCOVERY_NODE = [
|
||||||
"ACTUAL_TEMPERATURE"
|
'ACTUAL_TEMPERATURE'
|
||||||
]
|
]
|
||||||
|
|
||||||
HM_ATTRIBUTE_SUPPORT = {
|
HM_ATTRIBUTE_SUPPORT = {
|
||||||
"LOWBAT": ["Battery", {0: "High", 1: "Low"}],
|
'LOWBAT': ['Battery', {0: 'High', 1: 'Low'}],
|
||||||
"ERROR": ["Sabotage", {0: "No", 1: "Yes"}],
|
'ERROR': ['Sabotage', {0: 'No', 1: 'Yes'}],
|
||||||
"RSSI_DEVICE": ["RSSI", {}],
|
'RSSI_DEVICE': ['RSSI', {}],
|
||||||
"VALVE_STATE": ["Valve", {}],
|
'VALVE_STATE': ['Valve', {}],
|
||||||
"BATTERY_STATE": ["Battery", {}],
|
'BATTERY_STATE': ['Battery', {}],
|
||||||
"CONTROL_MODE": ["Mode", {0: "Auto", 1: "Manual", 2: "Away", 3: "Boost"}],
|
'CONTROL_MODE': ['Mode', {0: 'Auto', 1: 'Manual', 2: 'Away', 3: 'Boost'}],
|
||||||
"POWER": ["Power", {}],
|
'POWER': ['Power', {}],
|
||||||
"CURRENT": ["Current", {}],
|
'CURRENT': ['Current', {}],
|
||||||
"VOLTAGE": ["Voltage", {}]
|
'VOLTAGE': ['Voltage', {}]
|
||||||
}
|
}
|
||||||
|
|
||||||
HM_PRESS_EVENTS = [
|
HM_PRESS_EVENTS = [
|
||||||
"PRESS_SHORT",
|
'PRESS_SHORT',
|
||||||
"PRESS_LONG",
|
'PRESS_LONG',
|
||||||
"PRESS_CONT",
|
'PRESS_CONT',
|
||||||
"PRESS_LONG_RELEASE"
|
'PRESS_LONG_RELEASE'
|
||||||
|
]
|
||||||
|
|
||||||
|
HM_IMPULSE_EVENTS = [
|
||||||
|
'SEQUENCE_OK'
|
||||||
]
|
]
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
CONF_RESOLVENAMES_OPTIONS = [
|
||||||
|
'metadata',
|
||||||
|
'json',
|
||||||
|
'xml',
|
||||||
|
False
|
||||||
|
]
|
||||||
|
|
||||||
|
CONF_LOCAL_IP = 'local_ip'
|
||||||
|
CONF_LOCAL_PORT = 'local_port'
|
||||||
|
CONF_REMOTE_IP = 'remote_ip'
|
||||||
|
CONF_REMOTE_PORT = 'remote_port'
|
||||||
|
CONF_RESOLVENAMES = 'resolvenames'
|
||||||
|
CONF_DELAY = 'delay'
|
||||||
|
|
||||||
|
PLATFORM_SCHEMA = vol.Schema({
|
||||||
|
vol.Required(CONF_LOCAL_IP): vol.Coerce(str),
|
||||||
|
vol.Optional(CONF_LOCAL_PORT, default=8943):
|
||||||
|
vol.All(vol.Coerce(int),
|
||||||
|
vol.Range(min=1, max=65535)),
|
||||||
|
vol.Required(CONF_REMOTE_IP): vol.Coerce(str),
|
||||||
|
vol.Optional(CONF_REMOTE_PORT, default=2001):
|
||||||
|
vol.All(vol.Coerce(int),
|
||||||
|
vol.Range(min=1, max=65535)),
|
||||||
|
vol.Optional(CONF_RESOLVENAMES, default=False):
|
||||||
|
vol.In(CONF_RESOLVENAMES_OPTIONS),
|
||||||
|
vol.Optional(CONF_USERNAME, default="Admin"): vol.Coerce(str),
|
||||||
|
vol.Optional(CONF_PASSWORD, default=""): vol.Coerce(str),
|
||||||
|
vol.Optional(CONF_DELAY, default=0.5): vol.Coerce(float)
|
||||||
|
})
|
||||||
|
|
||||||
|
SCHEMA_SERVICE_VIRTUALKEY = vol.Schema({
|
||||||
|
vol.Required(ATTR_ADDRESS): vol.Coerce(str),
|
||||||
|
vol.Required(ATTR_CHANNEL): vol.Coerce(int),
|
||||||
|
vol.Required(ATTR_PARAM): vol.Coerce(str)
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=unused-argument
|
# pylint: disable=unused-argument
|
||||||
def setup(hass, config):
|
def setup(hass, config):
|
||||||
|
@ -77,14 +126,14 @@ def setup(hass, config):
|
||||||
|
|
||||||
from pyhomematic import HMConnection
|
from pyhomematic import HMConnection
|
||||||
|
|
||||||
local_ip = config[DOMAIN].get("local_ip", None)
|
local_ip = config[DOMAIN][0].get(CONF_LOCAL_IP)
|
||||||
local_port = config[DOMAIN].get("local_port", 8943)
|
local_port = config[DOMAIN][0].get(CONF_LOCAL_PORT)
|
||||||
remote_ip = config[DOMAIN].get("remote_ip", None)
|
remote_ip = config[DOMAIN][0].get(CONF_REMOTE_IP)
|
||||||
remote_port = config[DOMAIN].get("remote_port", 2001)
|
remote_port = config[DOMAIN][0].get(CONF_REMOTE_PORT)
|
||||||
resolvenames = config[DOMAIN].get("resolvenames", False)
|
resolvenames = config[DOMAIN][0].get(CONF_RESOLVENAMES)
|
||||||
username = config[DOMAIN].get("username", "Admin")
|
username = config[DOMAIN][0].get(CONF_USERNAME)
|
||||||
password = config[DOMAIN].get("password", "")
|
password = config[DOMAIN][0].get(CONF_PASSWORD)
|
||||||
HOMEMATIC_LINK_DELAY = config[DOMAIN].get("delay", 0.5)
|
HOMEMATIC_LINK_DELAY = config[DOMAIN][0].get(CONF_DELAY)
|
||||||
|
|
||||||
if remote_ip is None or local_ip is None:
|
if remote_ip is None or local_ip is None:
|
||||||
_LOGGER.error("Missing remote CCU/Homegear or local address")
|
_LOGGER.error("Missing remote CCU/Homegear or local address")
|
||||||
|
@ -109,6 +158,15 @@ def setup(hass, config):
|
||||||
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, HOMEMATIC.stop)
|
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, HOMEMATIC.stop)
|
||||||
hass.config.components.append(DOMAIN)
|
hass.config.components.append(DOMAIN)
|
||||||
|
|
||||||
|
# regeister homematic services
|
||||||
|
descriptions = load_yaml_config_file(
|
||||||
|
os.path.join(os.path.dirname(__file__), 'services.yaml'))
|
||||||
|
|
||||||
|
hass.services.register(DOMAIN, SERVICE_VIRTUALKEY,
|
||||||
|
_hm_service_virtualkey,
|
||||||
|
descriptions[DOMAIN][SERVICE_VIRTUALKEY],
|
||||||
|
SCHEMA_SERVICE_VIRTUALKEY)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
@ -302,7 +360,7 @@ def _hm_event_handler(hass, device, caller, attribute, value):
|
||||||
_LOGGER.debug("Event %s for %s channel %i", attribute,
|
_LOGGER.debug("Event %s for %s channel %i", attribute,
|
||||||
hmdevice.NAME, channel)
|
hmdevice.NAME, channel)
|
||||||
|
|
||||||
# a keypress event
|
# keypress event
|
||||||
if attribute in HM_PRESS_EVENTS:
|
if attribute in HM_PRESS_EVENTS:
|
||||||
hass.bus.fire(EVENT_KEYPRESS, {
|
hass.bus.fire(EVENT_KEYPRESS, {
|
||||||
ATTR_NAME: hmdevice.NAME,
|
ATTR_NAME: hmdevice.NAME,
|
||||||
|
@ -311,9 +369,42 @@ def _hm_event_handler(hass, device, caller, attribute, value):
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# impulse event
|
||||||
|
if attribute in HM_IMPULSE_EVENTS:
|
||||||
|
hass.bus.fire(EVENT_KEYPRESS, {
|
||||||
|
ATTR_NAME: hmdevice.NAME,
|
||||||
|
ATTR_CHANNEL: channel
|
||||||
|
})
|
||||||
|
return
|
||||||
|
|
||||||
_LOGGER.warning("Event is unknown and not forwarded to HA")
|
_LOGGER.warning("Event is unknown and not forwarded to HA")
|
||||||
|
|
||||||
|
|
||||||
|
def _hm_service_virtualkey(call):
|
||||||
|
"""Callback for handle virtualkey services."""
|
||||||
|
address = call.data.get(ATTR_ADDRESS)
|
||||||
|
channel = call.data.get(ATTR_CHANNEL)
|
||||||
|
param = call.data.get(ATTR_PARAM)
|
||||||
|
|
||||||
|
if address not in HOMEMATIC.devices:
|
||||||
|
_LOGGER.error("%s not found for service virtualkey!", address)
|
||||||
|
return
|
||||||
|
hmdevice = HOMEMATIC.devices.get(address)
|
||||||
|
|
||||||
|
# if param exists for this device
|
||||||
|
if param not in hmdevice.ACTIONNODE:
|
||||||
|
_LOGGER.error("%s not datapoint in hm device %s", param, address)
|
||||||
|
return
|
||||||
|
|
||||||
|
# channel exists?
|
||||||
|
if channel > hmdevice.ELEMENT:
|
||||||
|
_LOGGER.error("%i is not a channel in hm device %s", channel, address)
|
||||||
|
return
|
||||||
|
|
||||||
|
# call key
|
||||||
|
hmdevice.actionNodeData(param, 1, channel)
|
||||||
|
|
||||||
|
|
||||||
class HMDevice(Entity):
|
class HMDevice(Entity):
|
||||||
"""The Homematic device base object."""
|
"""The Homematic device base object."""
|
||||||
|
|
||||||
|
@ -465,7 +556,7 @@ class HMDevice(Entity):
|
||||||
channel = self._channel
|
channel = self._channel
|
||||||
# Prepare for subscription
|
# Prepare for subscription
|
||||||
try:
|
try:
|
||||||
if int(channel) > 0:
|
if int(channel) >= 0:
|
||||||
channels_to_sub.update({int(channel): True})
|
channels_to_sub.update({int(channel): True})
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
_LOGGER("Invalid channel in metadata from %s",
|
_LOGGER("Invalid channel in metadata from %s",
|
||||||
|
|
|
@ -28,7 +28,10 @@ HM_UNIT_HA_CAST = {
|
||||||
"POWER": "W",
|
"POWER": "W",
|
||||||
"CURRENT": "mA",
|
"CURRENT": "mA",
|
||||||
"VOLTAGE": "V",
|
"VOLTAGE": "V",
|
||||||
"ENERGY_COUNTER": "Wh"
|
"ENERGY_COUNTER": "Wh",
|
||||||
|
"GAS_POWER": "m3",
|
||||||
|
"GAS_ENERGY_COUNTER": "m3",
|
||||||
|
"LUX": "lux"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,3 +14,20 @@ persistent_notification:
|
||||||
notification_id:
|
notification_id:
|
||||||
description: Target ID of the notification, will replace a notification with the same Id. [Optional]
|
description: Target ID of the notification, will replace a notification with the same Id. [Optional]
|
||||||
example: 1234
|
example: 1234
|
||||||
|
|
||||||
|
homematic:
|
||||||
|
virtualkey:
|
||||||
|
description: Press a virtual key from CCU/Homegear or simulate keypress
|
||||||
|
|
||||||
|
fields:
|
||||||
|
address:
|
||||||
|
description: Address of homematic device or BidCoS-RF for virtual remote
|
||||||
|
example: BidCoS-RF
|
||||||
|
|
||||||
|
channel:
|
||||||
|
description: Channel for calling a keypress
|
||||||
|
example: 1
|
||||||
|
|
||||||
|
param:
|
||||||
|
description: Event to send i.e. PRESS_LONG, PRESS_SHORT
|
||||||
|
example: PRESS_LONG
|
||||||
|
|
|
@ -280,7 +280,7 @@ pyenvisalink==1.0
|
||||||
pyfttt==0.3
|
pyfttt==0.3
|
||||||
|
|
||||||
# homeassistant.components.homematic
|
# homeassistant.components.homematic
|
||||||
pyhomematic==0.1.8
|
pyhomematic==0.1.9
|
||||||
|
|
||||||
# homeassistant.components.device_tracker.icloud
|
# homeassistant.components.device_tracker.icloud
|
||||||
pyicloud==0.8.3
|
pyicloud==0.8.3
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue