so jetzt versuche ich nochmal das Thema für mich anzugehen.
wie gesagt scheine ich wohl alles nötige bzgl. der P5 Module vom Hersteller bekommen zu haben, jedoch scheitert es an meinem Yaml Skills etwas.( stehe noch ganz am Anfang und glaube das dies für längere Zeit ohne Hilfe nicht umsetzbar sein wird für mich. böhmische Dörfer!)
hier mal code Auszüge die ich so vom Hersteller für HA bekommen habe ( mehre )
binary_sensor
#FutureNow FNIP-4xSH
import voluptuous as vol
from homeassistant.const import CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_STOP
import homeassistant.helpers.config_validation as cv
from threading import Thread
import string
import re
import queue
import socket
import uuid
from datetime import datetime
from time import sleep
import logging
CONF_CHANNELS = "channels"
CONF_MODULES = "modules"
DEFAULT_PORT = 7078
DOMAIN = "fn_blind"
DATA_FN = "fn_blind"
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
vol.Required(CONF_MODULES): vol.Schema({cv.string: cv.string}),
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
}
)
},
extra=vol.ALLOW_EXTRA,
)
# A TCP socket client for communication with FutureNow devices
_LOGGER = logging.getLogger(__name__)
class MessageThread(Thread):
# process responses & notifications and pipe data to callback(s)."""
def __init__(self, fn_client):
self.fn_client = fn_client
self.stopped = False
super(MessageThread, self).__init__()
def run(self):
while not self.stopped:
try:
# grab a message from queue
message = self.fn_client.queue.get(True, 15)
_LOGGER.debug("message thread: " + message)
except queue.Empty:
_LOGGER.debug("message thread: no messages")
# close socket then reconnect if no replies to heartbeat are received
# catch Exception "transport endpoint is not connected"
self.fn_client.disconnect()
self.fn_client.connect ()
continue
# make a copy of the current subscribers to keep this thread-safe
current_subscribers = dict(self.fn_client.subscribers)
#parsing
while True:
start = message.find("FN")
end = message.find("\r")
if end>start:
substring = message[start:end]
message =message.replace(message[start:end+1],"")
_LOGGER.debug ("FN rep " + substring)
command = re.match("FN,(\w+),", substring)
if command:
command = command.group(1)
if command == "LEV":
match = re.match ("FN,"+ command + ",(\d+),(\d+)", substring)
if match:
channel = match.group(1)
value = match.group(2)
value = int (value)
_LOGGER.info (self.fn_client.name + "LEV command received " + channel + ',' + str(value))
elif command == 'OUT':
command='OUT,STOP' # this is what subscribers subscribe for
match = re.match ("FN,"+ command + ",(\d+),(\d+)", substring)
if match:
channel = match.group(1)
value = match.group(2)
value = int (value)
_LOGGER.debug (self.fn_client.name + " module OUT, STOP status feedback received")
elif command == 'IN':
#_LOGGER.debug ("IN status feedback received")
match = re.match ("FN,"+ command + ",(\w+),(\d+)", substring)
if match:
channel = match.group(2)
value = match.group(1)
if value == 'OFF':
value = 0
elif value == 'ON':
value =1
# update subscribers
if (channel != None) and (value != None) : # Int 0 would result in False if it was if channel and value
for subscriber_id in current_subscribers:
# msg or op should match what we asked for
#_LOGGER.debug ("subscribers ")
subscriber = current_subscribers[subscriber_id]
if command == subscriber['command']:
if channel == subscriber['channel']:
_LOGGER.debug ("subscriber notified about change " + ', ' + self.name + ", " + command + ", "+ channel + ", " + str(value))
subscriber['callback'](value)
if subscriber['permanent'] is False: #if subscription was just for a one off event unsubscribe subscriber
self.fn_client.unsubscribe(subscriber_id)
else:
message = message.replace ('>',"")
break
# signals to queue job is done
self.fn_client.queue.task_done()
class ReceiveThread(Thread):
# Receive data and push it to the queue
def __init__(self, fn_client):
self.fn_client = fn_client
self.stopped = False
Thread.__init__(self)
def run(self):
while not self.stopped:
self.fn_client.receive()
class HeartBeatTimer(Thread):
def __init__(self, fn_client):
self.fn_client = fn_client
self.stopped = False
#self.stopped =Event()
Thread.__init__(self)
def run(self):
#while not self.stopped.wait(3):
while not self.stopped:
self.fn_client.heart_beat()
sleep(3)
class FNSocketClient(object):
# A tcp client to connect to and maintain connection with the FN socket server
def __init__(self, host, port, name):
self.queue = queue.Queue()
self.subscribers = {}
self._socket_recv = 1024
self.host = host
self.port = port
self.isConnected = False
self.name = name
self.connect ()
self.message_thread = MessageThread(self)
self.receive_thread = ReceiveThread(self)
self.timer_thread = HeartBeatTimer(self)
self.receive_thread.start()
self.message_thread.start()
self.timer_thread.start()
def connect(self):
while True:
try:
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.settimeout(None)
self.socket.connect((self.host, self.port))
_LOGGER.debug ('connected to: ' + self.host + str(self.port))
self.status_query('IN')
self.status_query("OUT")
self.isConnected = True
break
except Exception as e:
_LOGGER.debug ('Connection failed')
sleep(5)
def disconnect (self):
self.socket.close()
self.isConnected = False
_LOGGER.debug ("disconnected")
def heart_beat(self):
if self.isConnected:
self.send ("a\r")
def subscribe(self, command, channel, callback, permanent=False):
# add subscribers
subscriber_id = uuid.uuid4()
self.subscribers[subscriber_id] = {'command': command,
'channel': channel,
'callback': callback,
'permanent': permanent,
'time_created': datetime.now()}
def subscribe_notify(self, command, channel, callback):
# subscribe a callback to a notification event
self.subscribe(command, channel, callback, True)
def unsubscribe(self, subscriber_id):
# Unsubscribe a callback from an event
self.subscribers.pop(subscriber_id)
def send(self, data):
# send message
_LOGGER.debug("send: " + data)
try:
self.socket.send(data.encode('ascii'))
except socket.error as e:
_LOGGER.error(e)
def receive(self):
# receive data from socket
while self.isConnected :
try:
# read data from the buffer
data = self.socket.recv(self._socket_recv)
except socket.timeout as e:
_LOGGER.debug(e)
sleep(1)
return
except socket.error as e:
# Something else happened
_LOGGER.error(e)
return
else:
if len(data) == 0:
# no more data being transmitted
_LOGGER.info('orderly shutdown on server end')
return
result = data.decode('ascii')
self.queue.put(result)
def quit(self):
# stop all threads and close the socket
self.receive_thread.stopped = True
self.message_thread.stopped = True
self.timer_thread.stopped = True
self.receive_thread.join()
_LOGGER.info('receive_thread exited')
self.message_thread.join()
_LOGGER.info('message_thread exited')
self.timer_thread.join()
_LOGGER.info('heartbeat_thread exited')
self.socket.close()
_LOGGER.info("socket closed")
def status_query(self, out_in_select):
#Read the status of digital inputs and outputs
if out_in_select == 'OUT':
self.send("FN,SRE\r\n")
_LOGGER.info("querying output states")
if out_in_select == 'IN':
self.send("FN,SRI\r\n")
_LOGGER.info("querying input states")
def toggle_switch (self, module_address, callback_fn):
self.send("FN,TOG," + module_address + "\r\n")
def move_up(self, module_address, callback):
#Moving the blind up
self.send("FN,UP," + module_address + "\r\n")
def move_down(self, module_address, callback):
#Moving the blind down
self.send("FN,DOWN," + module_address + "\r\n")
def stop(self, module_address, callback):
#Stopping the blind
self.send("FN,STOP," + module_address + "\r\n")
def go_to_position (self, module_address, pos, callback):
self.send ("FN,GOTO," + module_address + "," + str(pos) + "\r\n")
def setup(hass, base_config):
# Set up the fn_blind component
config = base_config[DOMAIN]
port = config[CONF_PORT]
modules = config[CONF_MODULES]
_LOGGER.info(modules.items())
fn_device = {}
hass.data[DATA_FN] = {}
for name, ip_addr in modules.items():
fn_device[name] = FNSocketClient(ip_addr, 7078, name)
_LOGGER.info ("name " + name + ", ip address " + ip_addr)
hass.data[DATA_FN][name] = FNDevice(hass, fn_device[name], name)
#fn_device = FNSocketClient(host, port)
def cleanup_fn(event):
#stuff to do before stopping
for module in modules:
for name, ip_addr in module.items():
fn_device[name].quit()
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, cleanup_fn)
return True
class FNDevice:
# The fn_blind component
def __init__(self, hass, fn_device, name):
self.hass = hass
self.fn_device = fn_device
self.name = name
def status_query(self, out_in_select):
# read the status of digital inputs and outputs
self.fn_device.status_query(out_in_select)
def move_up(self, ch_no, callback):
# moving the blind up
self.fn_device.move_up(ch_no, callback)
def move_down(self, ch_no, callback):
# moving the blind down
self.fn_device.move_down(ch_no, callback)
def stop(self, ch_no, callback):
# stopping the blind
self.fn_device.stop(ch_no, callback)
def toggle_switch (self, ch_no, callback):
# toggle the blind
self.fn_device.toggle_switch(ch_no, callback)
def go_to_position (self, ch_no, pos, callback):
#output goes to a certain position
self.fn_device.go_to_position (ch_no, pos, callback)
def subscribe(self, command, ch_no, callback):
self.fn_device.subscribe_notify (command, ch_no, callback)