forked from platypush/platypush
Removed legacy zwave backend.
This commit is contained in:
parent
190cfa21b5
commit
46167a6c2a
2 changed files with 0 additions and 398 deletions
|
@ -1,350 +0,0 @@
|
||||||
import inspect
|
|
||||||
import logging
|
|
||||||
import queue
|
|
||||||
import os
|
|
||||||
import threading
|
|
||||||
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from platypush.backend import Backend
|
|
||||||
from platypush.config import Config
|
|
||||||
from platypush.message.event.zwave import (
|
|
||||||
ZwaveNetworkReadyEvent,
|
|
||||||
ZwaveNetworkStoppedEvent,
|
|
||||||
ZwaveEvent,
|
|
||||||
ZwaveNodeAddedEvent,
|
|
||||||
ZwaveValueAddedEvent,
|
|
||||||
ZwaveNodeQueryCompletedEvent,
|
|
||||||
ZwaveValueChangedEvent,
|
|
||||||
ZwaveValueRefreshedEvent,
|
|
||||||
ZwaveValueRemovedEvent,
|
|
||||||
ZwaveNetworkResetEvent,
|
|
||||||
ZwaveCommandEvent,
|
|
||||||
ZwaveCommandWaitingEvent,
|
|
||||||
ZwaveNodeRemovedEvent,
|
|
||||||
ZwaveNodeRenamedEvent,
|
|
||||||
ZwaveNodeReadyEvent,
|
|
||||||
ZwaveButtonRemovedEvent,
|
|
||||||
ZwaveButtonCreatedEvent,
|
|
||||||
ZwaveButtonOnEvent,
|
|
||||||
ZwaveButtonOffEvent,
|
|
||||||
ZwaveNetworkErrorEvent,
|
|
||||||
ZwaveNodeGroupEvent,
|
|
||||||
ZwaveNodePollingEnabledEvent,
|
|
||||||
ZwaveNodePollingDisabledEvent,
|
|
||||||
ZwaveNodeSceneEvent,
|
|
||||||
ZwaveNodeEvent,
|
|
||||||
)
|
|
||||||
|
|
||||||
event_queue = queue.Queue()
|
|
||||||
network_ready = threading.Event()
|
|
||||||
|
|
||||||
|
|
||||||
class _ZWEvent:
|
|
||||||
def __init__(self, signal: str, sender: str, network=None, **kwargs):
|
|
||||||
self.signal = signal
|
|
||||||
self.sender = sender
|
|
||||||
self.network = network
|
|
||||||
self.args = kwargs
|
|
||||||
|
|
||||||
|
|
||||||
def _zwcallback(signal, sender, network, **kwargs):
|
|
||||||
if signal == network.SIGNAL_NETWORK_AWAKED:
|
|
||||||
network_ready.set()
|
|
||||||
event_queue.put(_ZWEvent(signal=signal, sender=sender, network=network, **kwargs))
|
|
||||||
|
|
||||||
|
|
||||||
class ZwaveBackend(Backend):
|
|
||||||
"""
|
|
||||||
Start and manage a Z-Wave network.
|
|
||||||
|
|
||||||
If you are using a USB adapter and want a consistent naming for the device paths, you can use udev.
|
|
||||||
|
|
||||||
.. code-block:: shell
|
|
||||||
|
|
||||||
# Get the vendorID and productID of your device through lsusb.
|
|
||||||
# Then add a udev rule for it to link it e.g. to /dev/zwave.
|
|
||||||
|
|
||||||
cat <<EOF > /etc/udev/rules.d/92-zwave.rules
|
|
||||||
SUBSYSTEM=="tty", ATTRS{idVendor}=="0658", ATTRS{idProduct}=="0200", SYMLINK+="zwave"
|
|
||||||
EOF
|
|
||||||
|
|
||||||
# Restart the udev service
|
|
||||||
systemctl restart systemd-udevd.service
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
This backend is deprecated, since the underlying ``python-openzwave`` is
|
|
||||||
quite buggy and largely unmaintained.
|
|
||||||
|
|
||||||
Use the `zwave.mqtt` backend instead
|
|
||||||
(:class:`platypush.backend.zwave.mqtt.ZwaveMqttBackend`).
|
|
||||||
|
|
||||||
Triggers:
|
|
||||||
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNetworkReadyEvent` when the network is up and running.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNetworkStoppedEvent` when the network goes down.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNetworkResetEvent` when the network is reset.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNetworkErrorEvent` when an error occurs on the network.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNodeQueryCompletedEvent` when all the nodes on the network
|
|
||||||
have been queried.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNodeEvent` when a node attribute changes.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNodeAddedEvent` when a node is added to the network.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNodeRemovedEvent` when a node is removed from the network.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNodeRenamedEvent` when a node is renamed.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNodeReadyEvent` when a node is ready.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNodeGroupEvent` when a node is associated/de-associated to a
|
|
||||||
group.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNodeSceneEvent` when a scene is set on a node.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNodePollingEnabledEvent` when the polling is successfully turned
|
|
||||||
on a node.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveNodePollingDisabledEvent` when the polling is successfully turned
|
|
||||||
off a node.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveButtonCreatedEvent` when a button is added to the network.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveButtonRemovedEvent` when a button is removed from the network.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveButtonOnEvent` when a button is pressed.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveButtonOffEvent` when a button is released.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveValueAddedEvent` when a value is added to a node on the network.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveValueChangedEvent` when the value of a node on the network
|
|
||||||
changes.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveValueRefreshedEvent` when the value of a node on the network
|
|
||||||
is refreshed.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveValueRemovedEvent` when the value of a node on the network
|
|
||||||
is removed.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveCommandEvent` when a command is received on the network.
|
|
||||||
* :class:`platypush.message.event.zwave.ZwaveCommandWaitingEvent` when a command is waiting for a message
|
|
||||||
to complete.
|
|
||||||
|
|
||||||
Requires:
|
|
||||||
|
|
||||||
* **python-openzwave** (``pip install python-openzwave``)
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
device: str,
|
|
||||||
config_path: Optional[str] = None,
|
|
||||||
user_path: Optional[str] = None,
|
|
||||||
ready_timeout: float = 10.0,
|
|
||||||
*args,
|
|
||||||
**kwargs
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
:param device: Path to the Z-Wave adapter (e.g. /dev/ttyUSB0 or /dev/ttyACM0).
|
|
||||||
:param config_path: Z-Wave configuration path (default: ``<OPENZWAVE_PATH>/ozw_config``).
|
|
||||||
:param user_path: Z-Wave user path where runtime and configuration files will be stored
|
|
||||||
(default: ``<PLATYPUSH_WORKDIR>/zwave``).
|
|
||||||
:param ready_timeout: Network ready timeout in seconds (default: 60).
|
|
||||||
"""
|
|
||||||
import python_openzwave
|
|
||||||
from openzwave.network import ZWaveNetwork
|
|
||||||
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.device = device
|
|
||||||
|
|
||||||
if not config_path:
|
|
||||||
# noinspection PyTypeChecker
|
|
||||||
config_path = os.path.join(
|
|
||||||
os.path.dirname(inspect.getfile(python_openzwave)), 'ozw_config'
|
|
||||||
)
|
|
||||||
if not user_path:
|
|
||||||
user_path = os.path.join(Config.get('workdir'), 'zwave')
|
|
||||||
os.makedirs(user_path, mode=0o770, exist_ok=True)
|
|
||||||
|
|
||||||
self.config_path = config_path
|
|
||||||
self.user_path = user_path
|
|
||||||
self.ready_timeout = ready_timeout
|
|
||||||
self.network: Optional[ZWaveNetwork] = None
|
|
||||||
|
|
||||||
def start_network(self):
|
|
||||||
if self.network and self.network.state >= self.network.STATE_AWAKED:
|
|
||||||
self.logger.info('Z-Wave network already started')
|
|
||||||
return
|
|
||||||
|
|
||||||
from openzwave.network import ZWaveNetwork, dispatcher
|
|
||||||
from openzwave.option import ZWaveOption
|
|
||||||
|
|
||||||
network_ready.clear()
|
|
||||||
logging.getLogger('openzwave').addHandler(self.logger)
|
|
||||||
opts = ZWaveOption(
|
|
||||||
self.device, config_path=self.config_path, user_path=self.user_path
|
|
||||||
)
|
|
||||||
opts.set_console_output(False)
|
|
||||||
opts.lock()
|
|
||||||
|
|
||||||
self.network = ZWaveNetwork(opts, log=None)
|
|
||||||
dispatcher.connect(_zwcallback)
|
|
||||||
ready = network_ready.wait(self.ready_timeout)
|
|
||||||
|
|
||||||
if not ready:
|
|
||||||
self.logger.warning(
|
|
||||||
'Driver not ready after {} seconds: continuing anyway'.format(
|
|
||||||
self.ready_timeout
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def stop_network(self):
|
|
||||||
if self.network:
|
|
||||||
self.network.stop()
|
|
||||||
network_ready.clear()
|
|
||||||
self.network = None
|
|
||||||
|
|
||||||
def _process_event(self, event: _ZWEvent):
|
|
||||||
from platypush.plugins.zwave import ZwavePlugin
|
|
||||||
|
|
||||||
network = (
|
|
||||||
event.network
|
|
||||||
if hasattr(event, 'network') and event.network
|
|
||||||
else self.network
|
|
||||||
)
|
|
||||||
|
|
||||||
if (
|
|
||||||
event.signal == network.SIGNAL_NETWORK_STOPPED
|
|
||||||
or event.signal == network.SIGNAL_DRIVER_REMOVED
|
|
||||||
):
|
|
||||||
event = ZwaveNetworkStoppedEvent(device=self.device)
|
|
||||||
elif (
|
|
||||||
event.signal == network.SIGNAL_ALL_NODES_QUERIED
|
|
||||||
or event.signal == network.SIGNAL_ALL_NODES_QUERIED_SOME_DEAD
|
|
||||||
):
|
|
||||||
event = ZwaveNodeQueryCompletedEvent(device=self.device)
|
|
||||||
elif event.signal == network.SIGNAL_NETWORK_FAILED:
|
|
||||||
event = ZwaveNetworkErrorEvent(device=self.device)
|
|
||||||
self.logger.warning('Z-Wave network error')
|
|
||||||
elif (
|
|
||||||
event.signal == network.SIGNAL_NETWORK_RESETTED
|
|
||||||
or event.signal == network.SIGNAL_DRIVER_RESET
|
|
||||||
):
|
|
||||||
event = ZwaveNetworkResetEvent(device=self.device)
|
|
||||||
elif event.signal == network.SIGNAL_BUTTON_ON:
|
|
||||||
event = ZwaveButtonOnEvent(
|
|
||||||
device=self.device, node=ZwavePlugin.node_to_dict(event.args['node'])
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_BUTTON_OFF:
|
|
||||||
event = ZwaveButtonOffEvent(
|
|
||||||
device=self.device, node=ZwavePlugin.node_to_dict(event.args['node'])
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_CONTROLLER_COMMAND:
|
|
||||||
event = ZwaveCommandEvent(
|
|
||||||
device=self.device,
|
|
||||||
state=event.args['state'],
|
|
||||||
state_description=event.args['state_full'],
|
|
||||||
error=event.args['error'] if event.args['error_int'] else None,
|
|
||||||
error_description=event.args['error_full']
|
|
||||||
if event.args['error_int']
|
|
||||||
else None,
|
|
||||||
node=ZwavePlugin.node_to_dict(event.args['node'])
|
|
||||||
if event.args['node']
|
|
||||||
else None,
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_CONTROLLER_WAITING:
|
|
||||||
event = ZwaveCommandWaitingEvent(
|
|
||||||
device=self.device,
|
|
||||||
state=event.args['state'],
|
|
||||||
state_description=event.args['state_full'],
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_CREATE_BUTTON:
|
|
||||||
event = ZwaveButtonCreatedEvent(
|
|
||||||
device=self.device, node=ZwavePlugin.node_to_dict(event.args['node'])
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_DELETE_BUTTON:
|
|
||||||
event = ZwaveButtonRemovedEvent(
|
|
||||||
device=self.device, node=ZwavePlugin.node_to_dict(event.args['node'])
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_GROUP:
|
|
||||||
event = ZwaveNodeGroupEvent(
|
|
||||||
device=self.device,
|
|
||||||
node=ZwavePlugin.node_to_dict(event.args['node']),
|
|
||||||
group_index=event.args['groupidx'],
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_NETWORK_AWAKED:
|
|
||||||
event = ZwaveNetworkReadyEvent(
|
|
||||||
device=self.device,
|
|
||||||
ozw_library_version=self.network.controller.ozw_library_version,
|
|
||||||
python_library_version=self.network.controller.python_library_version,
|
|
||||||
zwave_library=self.network.controller.library_description,
|
|
||||||
home_id=self.network.controller.home_id,
|
|
||||||
node_id=self.network.controller.node_id,
|
|
||||||
node_version=self.network.controller.node.version,
|
|
||||||
nodes_count=self.network.nodes_count,
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_NODE_EVENT:
|
|
||||||
event = ZwaveNodeEvent(
|
|
||||||
device=self.device, node=ZwavePlugin.node_to_dict(event.args['node'])
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_NODE_ADDED:
|
|
||||||
event = ZwaveNodeAddedEvent(
|
|
||||||
device=self.device, node=ZwavePlugin.node_to_dict(event.args['node'])
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_NODE_NAMING:
|
|
||||||
event = ZwaveNodeRenamedEvent(
|
|
||||||
device=self.device, node=ZwavePlugin.node_to_dict(event.args['node'])
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_NODE_READY:
|
|
||||||
event = ZwaveNodeReadyEvent(
|
|
||||||
device=self.device, node=ZwavePlugin.node_to_dict(event.args['node'])
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_NODE_REMOVED:
|
|
||||||
event = ZwaveNodeRemovedEvent(
|
|
||||||
device=self.device, node=ZwavePlugin.node_to_dict(event.args['node'])
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_POLLING_DISABLED:
|
|
||||||
event = ZwaveNodePollingEnabledEvent(
|
|
||||||
device=self.device, node=ZwavePlugin.node_to_dict(event.args['node'])
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_POLLING_ENABLED:
|
|
||||||
event = ZwaveNodePollingDisabledEvent(
|
|
||||||
device=self.device, node=ZwavePlugin.node_to_dict(event.args['node'])
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_SCENE_EVENT:
|
|
||||||
event = ZwaveNodeSceneEvent(
|
|
||||||
device=self.device,
|
|
||||||
scene_id=event.args['scene_id'],
|
|
||||||
node=ZwavePlugin.node_to_dict(event.args['node']),
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_VALUE_ADDED:
|
|
||||||
event = ZwaveValueAddedEvent(
|
|
||||||
device=self.device,
|
|
||||||
node=ZwavePlugin.node_to_dict(event.args['node']),
|
|
||||||
value=ZwavePlugin.value_to_dict(event.args['value']),
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_VALUE_CHANGED:
|
|
||||||
event = ZwaveValueChangedEvent(
|
|
||||||
device=self.device,
|
|
||||||
node=ZwavePlugin.node_to_dict(event.args['node']),
|
|
||||||
value=ZwavePlugin.value_to_dict(event.args['value']),
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_VALUE_REFRESHED:
|
|
||||||
event = ZwaveValueRefreshedEvent(
|
|
||||||
device=self.device,
|
|
||||||
node=ZwavePlugin.node_to_dict(event.args['node']),
|
|
||||||
value=ZwavePlugin.value_to_dict(event.args['value']),
|
|
||||||
)
|
|
||||||
elif event.signal == network.SIGNAL_VALUE_REMOVED:
|
|
||||||
event = ZwaveValueRemovedEvent(
|
|
||||||
device=self.device,
|
|
||||||
node=ZwavePlugin.node_to_dict(event.args['node']),
|
|
||||||
value=ZwavePlugin.value_to_dict(event.args['value']),
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
self.logger.info('Received unhandled ZWave event: {}'.format(event))
|
|
||||||
|
|
||||||
if isinstance(event, ZwaveEvent):
|
|
||||||
self.bus.post(event)
|
|
||||||
|
|
||||||
def __enter__(self):
|
|
||||||
self.start_network()
|
|
||||||
|
|
||||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
||||||
self.stop_network()
|
|
||||||
|
|
||||||
def loop(self):
|
|
||||||
try:
|
|
||||||
event = event_queue.get(block=True, timeout=1.0)
|
|
||||||
self._process_event(event)
|
|
||||||
except queue.Empty:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
# vim:sw=4:ts=4:et:
|
|
|
@ -1,48 +0,0 @@
|
||||||
manifest:
|
|
||||||
events:
|
|
||||||
platypush.message.event.zwave.ZwaveButtonCreatedEvent: when a button is added
|
|
||||||
to the network.
|
|
||||||
platypush.message.event.zwave.ZwaveButtonOffEvent: when a button is released.
|
|
||||||
platypush.message.event.zwave.ZwaveButtonOnEvent: when a button is pressed.
|
|
||||||
platypush.message.event.zwave.ZwaveButtonRemovedEvent: when a button is removed
|
|
||||||
from the network.
|
|
||||||
platypush.message.event.zwave.ZwaveCommandEvent: when a command is received on
|
|
||||||
the network.
|
|
||||||
platypush.message.event.zwave.ZwaveCommandWaitingEvent: when a command is waiting
|
|
||||||
for a messageto complete.
|
|
||||||
platypush.message.event.zwave.ZwaveNetworkErrorEvent: when an error occurs on
|
|
||||||
the network.
|
|
||||||
platypush.message.event.zwave.ZwaveNetworkReadyEvent: when the network is up and
|
|
||||||
running.
|
|
||||||
platypush.message.event.zwave.ZwaveNetworkResetEvent: when the network is reset.
|
|
||||||
platypush.message.event.zwave.ZwaveNetworkStoppedEvent: when the network goes
|
|
||||||
down.
|
|
||||||
platypush.message.event.zwave.ZwaveNodeAddedEvent: when a node is added to the
|
|
||||||
network.
|
|
||||||
platypush.message.event.zwave.ZwaveNodeEvent: when a node attribute changes.
|
|
||||||
platypush.message.event.zwave.ZwaveNodeGroupEvent: when a node is associated/de-associated
|
|
||||||
to agroup.
|
|
||||||
platypush.message.event.zwave.ZwaveNodePollingDisabledEvent: when the polling
|
|
||||||
is successfully turnedoff a node.
|
|
||||||
platypush.message.event.zwave.ZwaveNodePollingEnabledEvent: when the polling is
|
|
||||||
successfully turnedon a node.
|
|
||||||
platypush.message.event.zwave.ZwaveNodeQueryCompletedEvent: when all the nodes
|
|
||||||
on the networkhave been queried.
|
|
||||||
platypush.message.event.zwave.ZwaveNodeReadyEvent: when a node is ready.
|
|
||||||
platypush.message.event.zwave.ZwaveNodeRemovedEvent: when a node is removed from
|
|
||||||
the network.
|
|
||||||
platypush.message.event.zwave.ZwaveNodeRenamedEvent: when a node is renamed.
|
|
||||||
platypush.message.event.zwave.ZwaveNodeSceneEvent: when a scene is set on a node.
|
|
||||||
platypush.message.event.zwave.ZwaveValueAddedEvent: when a value is added to a
|
|
||||||
node on the network.
|
|
||||||
platypush.message.event.zwave.ZwaveValueChangedEvent: when the value of a node
|
|
||||||
on the networkchanges.
|
|
||||||
platypush.message.event.zwave.ZwaveValueRefreshedEvent: when the value of a node
|
|
||||||
on the networkis refreshed.
|
|
||||||
platypush.message.event.zwave.ZwaveValueRemovedEvent: when the value of a node
|
|
||||||
on the networkis removed.
|
|
||||||
install:
|
|
||||||
pip:
|
|
||||||
- python-openzwave
|
|
||||||
package: platypush.backend.zwave
|
|
||||||
type: backend
|
|
Loading…
Reference in a new issue