Skip to content
This repository was archived by the owner on Nov 6, 2024. It is now read-only.

Commit

Permalink
Rewrite of a lot of code.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelarnauts committed May 20, 2017
1 parent bbe0c4d commit de2fde1
Show file tree
Hide file tree
Showing 7 changed files with 800 additions and 596 deletions.
4 changes: 2 additions & 2 deletions PROTOCOL.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ This is a list of the commands.
| SetDeviceSettingsRequestType | SetDeviceSettingsConfirmType | | |
| VersionRequestType | VersionConfirmType | | |
| | | GatewayNotificationType | |
| | | KeepAliveType | |
| | | KeepAliveType | You should send these to keep the connection open. |
| FactoryResetType | | | |
| CnTimeRequestType | CnTimeConfirmType | | |
| CnTimeRequestType | CnTimeConfirmType | | Returns the seconds since 2000-01-01 00:00:00. |
| CnNodeRequestType | | CnNodeNotificationType | |
| CnRmiRequestType | CnRmiResponseType | | |
| CnRmiAsyncRequestType | CnRmiAsyncConfirmType | CnRmiAsyncResponseType | |
Expand Down
163 changes: 71 additions & 92 deletions example/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@
from pycomfoconnect import *

parser = argparse.ArgumentParser()
parser.add_argument("ip", help="ip address of the bridge")
parser.add_argument('--ip', help='ip address of the bridge')
args = parser.parse_args()

## Configuration #######################################################################################################

pin = 0
local_name = 'Computer'
local_uuid = bytes.fromhex('00000000000000000000000000000001')
local_uuid = bytes.fromhex('00000000000000000000000000000005')

## Bridge discovery ####################################################################################################

# Method 1: Use discovery to initialise Bridge
# bridges = Bridge.discover()
# bridges = Bridge.discover(timeout=1)
# if bridges:
# bridge = bridges[0]
# else:
Expand All @@ -37,111 +37,90 @@
print("No bridges found!")
exit(1)

print("Bridge found: %s (%s)" % (bridge.remote_uuid.hex(), bridge.ip))
print("Bridge found: %s (%s)" % (bridge.uuid.hex(), bridge.host))
bridge.debug = True


## Setting up a session ########################################################################################

def callback(var, value):
print("%s = %s" % (var, value))


def setup_comfoconnect(bridge, callback):
"""Setup a Comfoconnect session"""
comfoconnect = ComfoConnect(bridge, callback, debug=False)

try:
# Connect to the bridge
version_info = comfoconnect.connect(local_uuid, local_name, pin)
print('Connected to bridge with serial %s' % version_info['serialNumber'])

except PyComfoConnectOtherSession as e:
print('ERROR: Another session with "%s" is active.' % e.devicename)
exit(1)

except PyComfoConnectNotAllowed:
print('ERROR: Could not register. Invalid PIN!')
exit(1)

## Execute functions ###############################################################################################

# ListRegisteredApps
# for app in comfoconnect._bridge.ListRegisteredApps():
# print('%s: %s' % (app['uuid'].hex(), app['devicename']))

# DeregisterApp
# comfoconnect._bridge.DeregisterApp(bytes.fromhex('a996190220044d68a07d85a2e3866fff'))
# comfoconnect._bridge.DeregisterApp(bytes.fromhex('a996190220044d68a07d85a2e3866fce'))

# VersionRequest
# versioninfo = comfoconnect._bridge.VersionRequest()
# print(versioninfo)

# CnTimeRequest
# timeinfo = comfoconnect._bridge.CnTimeRequest()
# print(timeinfo)

## Register sensors ################################################################################################

# comfoconnect.request(const.SENSOR_FAN_NEXT_CHANGE) # General: Countdown until next fan speed change
comfoconnect.request(const.SENSOR_FAN_SPEED_MODE) # Fans: Fan speed setting
comfoconnect.request(const.SENSOR_FAN_SUPPLY_DUTY) # Fans: Supply fan duty
comfoconnect.request(const.SENSOR_FAN_EXHAUST_DUTY) # Fans: Exhaust fan duty
comfoconnect.request(const.SENSOR_FAN_SUPPLY_FLOW) # Fans: Supply fan flow
comfoconnect.request(const.SENSOR_FAN_EXHAUST_FLOW) # Fans: Exhaust fan flow
comfoconnect.request(const.SENSOR_FAN_SUPPLY_SPEED) # Fans: Supply fan speed
comfoconnect.request(const.SENSOR_FAN_EXHAUST_SPEED) # Fans: Exhaust fan speed
# comfoconnect.request(const.SENSOR_POWER_CURRENT) # Power Consumption: Current Ventilation
# comfoconnect.request(const.SENSOR_POWER_TOTAL_YEAR) # Power Consumption: Total year-to-date
# comfoconnect.request(const.SENSOR_POWER_TOTAL) # Power Consumption: Total from start
# comfoconnect.request(const.SENSOR_DAYS_TO_REPLACE_FILTER) # Days left before filters must be replaced
# comfoconnect.request(const.SENSOR_AVOIDED_HEATING_CURRENT) # Avoided Heating: Avoided actual
# comfoconnect.request(const.SENSOR_AVOIDED_HEATING_TOTAL_YEAR) # Avoided Heating: Avoided year-to-date
# comfoconnect.request(const.SENSOR_AVOIDED_HEATING_TOTAL) # Avoided Heating: Avoided total
# comfoconnect.request(const.SENSOR_TEMPERATURE_SUPPLY) # Temperature & Humidity: Supply Air (temperature)
# comfoconnect.request(const.SENSOR_TEMPERATURE_EXTRACT) # Temperature & Humidity: Extract Air (temperature)
# comfoconnect.request(const.SENSOR_TEMPERATURE_EXHAUST) # Temperature & Humidity: Exhaust Air (temperature)
# comfoconnect.request(const.SENSOR_TEMPERATURE_OUTDOOR) # Temperature & Humidity: Outdoor Air (temperature)
# comfoconnect.request(const.SENSOR_HUMIDITY_SUPPLY) # Temperature & Humidity: Supply Air (temperature)
# comfoconnect.request(const.SENSOR_HUMIDITY_EXTRACT) # Temperature & Humidity: Extract Air (temperature)
# comfoconnect.request(const.SENSOR_HUMIDITY_EXHAUST) # Temperature & Humidity: Exhaust Air (temperature)
# comfoconnect.request(const.SENSOR_HUMIDITY_OUTDOOR) # Temperature & Humidity: Outdoor Air (temperature)

return comfoconnect


try:
print('Initialising connection')
comfoconnect = setup_comfoconnect(bridge, callback)

## Executing functions #########################################################################################
# print("%s = %s" % (var, value))
pass

# comfoconnect.set_fan_mode(const.FAN_MODE_AWAY) # Go to auto mode
# comfoconnect.set_fan_mode(const.FAN_MODE_LOW) # Set fan speed to 1
# comfoconnect.set_fan_mode(const.FAN_MODE_MEDIUM) # Set fan speed to 2
# comfoconnect.set_fan_mode(const.FAN_MODE_HIGH) # Set fan speed to 3

## Example interaction #########################################################################################
# Setup a Comfoconnect session
comfoconnect = ComfoConnect(bridge, local_uuid, local_name, pin)
comfoconnect.callback = callback

print('Waiting... Stop with CTRL+C')
sleep(3)
comfoconnect.disconnect()
print('Disconnected')
try:
# Connect to the bridge
# comfoconnect.connect(False) # Don't disconnect existing clients.
comfoconnect.connect(True) # Disconnect existing clients.

sleep(1)
except Exception as e:
print('ERROR: %s' % e)
exit(1)

print('Initialising new connection')
comfoconnect = setup_comfoconnect(bridge, callback)
## Execute functions ###############################################################################################

# ListRegisteredApps
# for app in comfoconnect.cmd_list_registered_apps():
# print('%s: %s' % (app['uuid'].hex(), app['devicename']))

# DeregisterApp
# comfoconnect.cmd_deregister_app(bytes.fromhex('00000000000000000000000000000001'))

# VersionRequest
# version = comfoconnect.cmd_version_request()
# print(version)

# TimeRequest
# timeinfo = comfoconnect.cmd_time_request()
# print(timeinfo)

## Register sensors ################################################################################################

# comfoconnect.cmd_rpdo_request(SENSOR_FAN_NEXT_CHANGE) # General: Countdown until next fan speed change
comfoconnect.cmd_rpdo_request(SENSOR_FAN_SPEED_MODE) # Fans: Fan speed setting
# comfoconnect.cmd_rpdo_request(SENSOR_FAN_SUPPLY_DUTY) # Fans: Supply fan duty
# comfoconnect.cmd_rpdo_request(SENSOR_FAN_EXHAUST_DUTY) # Fans: Exhaust fan duty
# comfoconnect.cmd_rpdo_request(SENSOR_FAN_SUPPLY_FLOW) # Fans: Supply fan flow
# comfoconnect.cmd_rpdo_request(SENSOR_FAN_EXHAUST_FLOW) # Fans: Exhaust fan flow
# comfoconnect.cmd_rpdo_request(SENSOR_FAN_SUPPLY_SPEED) # Fans: Supply fan speed
# comfoconnect.cmd_rpdo_request(SENSOR_FAN_EXHAUST_SPEED) # Fans: Exhaust fan speed
# comfoconnect.cmd_rpdo_request(SENSOR_POWER_CURRENT) # Power Consumption: Current Ventilation
# comfoconnect.cmd_rpdo_request(SENSOR_POWER_TOTAL_YEAR) # Power Consumption: Total year-to-date
# comfoconnect.cmd_rpdo_request(SENSOR_POWER_TOTAL) # Power Consumption: Total from start
# comfoconnect.cmd_rpdo_request(SENSOR_DAYS_TO_REPLACE_FILTER) # Days left before filters must be replaced
# comfoconnect.cmd_rpdo_request(SENSOR_AVOIDED_HEATING_CURRENT) # Avoided Heating: Avoided actual
# comfoconnect.cmd_rpdo_request(SENSOR_AVOIDED_HEATING_TOTAL_YEAR) # Avoided Heating: Avoided year-to-date
# comfoconnect.cmd_rpdo_request(SENSOR_AVOIDED_HEATING_TOTAL) # Avoided Heating: Avoided total
# comfoconnect.cmd_rpdo_request(SENSOR_TEMPERATURE_SUPPLY) # Temperature & Humidity: Supply Air (temperature)
# comfoconnect.cmd_rpdo_request(SENSOR_TEMPERATURE_EXTRACT) # Temperature & Humidity: Extract Air (temperature)
# comfoconnect.cmd_rpdo_request(SENSOR_TEMPERATURE_EXHAUST) # Temperature & Humidity: Exhaust Air (temperature)
# comfoconnect.cmd_rpdo_request(SENSOR_TEMPERATURE_OUTDOOR) # Temperature & Humidity: Outdoor Air (temperature)
# comfoconnect.cmd_rpdo_request(SENSOR_HUMIDITY_SUPPLY) # Temperature & Humidity: Supply Air (temperature)
# comfoconnect.cmd_rpdo_request(SENSOR_HUMIDITY_EXTRACT) # Temperature & Humidity: Extract Air (temperature)
# comfoconnect.cmd_rpdo_request(SENSOR_HUMIDITY_EXHAUST) # Temperature & Humidity: Exhaust Air (temperature)
# comfoconnect.cmd_rpdo_request(SENSOR_HUMIDITY_OUTDOOR) # Temperature & Humidity: Outdoor Air (temperature)

# Executing functions #########################################################################################

# comfoconnect.cmd_rmi_request(CMD_FAN_MODE_AWAY) # Go to auto mode
# comfoconnect.cmd_rmi_request(CMD_FAN_MODE_LOW) # Set fan speed to 1
# comfoconnect.cmd_rmi_request(CMD_FAN_MODE_MEDIUM) # Set fan speed to 2
# comfoconnect.cmd_rmi_request(CMD_FAN_MODE_HIGH) # Set fan speed to 3

## Example interaction #########################################################################################

try:
print('Waiting... Stop with CTRL+C')
while True:

# Callback messages will still arrive in the callback method.
# Callback messages will arrive in the callback method.
sleep(1)

if not comfoconnect.is_connected():
print('It seems we got disconnected.')
exit()
print('We are not connected anymore...')

except KeyboardInterrupt:
pass
Expand Down
94 changes: 7 additions & 87 deletions pycomfoconnect/__init__.py
Original file line number Diff line number Diff line change
@@ -1,93 +1,13 @@
"""
PyComfoConnect: Manage your Zehnder ComfoConnect Q350/Q450/Q650 ventilation unit
"""
from __future__ import print_function

from .bridge import *
from .const import *
from .error import *
from .message import *
from .zehnder_pb2 import *


class ComfoConnect(object):
def __init__(self, bridge: Bridge, callback=None, debug=False):
self._bridge = bridge
self._callback = callback
self.requests = []

# Set debug mode
self._bridge.debug = debug

def connect(self, local_uuid, local_name, pin):
"""Connect to the bridge and login."""

try:
# Open connection
self._bridge.connect(local_uuid, self._callback_method)

# Login
self._bridge.StartSession(False)

except PyComfoConnectNotAllowed:
# Register with the bridge
self._bridge.RegisterApp(local_name, pin)

# Login
self._bridge.StartSession(False)

# Request version info
version_info = self._bridge.VersionRequest()
return version_info

def disconnect(self):
"""Logout and disconnect from the bridge."""
DEFAULT_UUID = '00000000000000000000000000000001'
DEFAULT_NAME = 'pycomfoconnect'
DEFAULT_PIN = 0

# Logout
self._bridge.CloseSession()
__author__ = 'Michaël Arnauts <[email protected]>'

# Close socket connection
self._bridge.disconnect()

def is_connected(self):
"""Check if we are still connected to the bridge."""
return self._bridge.is_connected()

def _callback_method(self, msg: Message):
if self._callback is None:
return False

if msg.cmd.type != zehnder_pb2.GatewayOperation.CnRpdoNotificationType:
return False

data = msg.msg.data.hex()
if len(data) == 2:
val = struct.unpack('b', msg.msg.data)[0]
elif len(data) == 4:
val = struct.unpack('h', msg.msg.data)[0]
elif len(data) == 8:
val = data
else:
val = data

self._callback(msg.msg.pdid, val)

def set_fan_mode(self, mode: int, node: int = 1):
if mode == FAN_MODE_AWAY:
cmd = CMD_FAN_MODE_AWAY
elif mode == FAN_MODE_LOW:
cmd = CMD_FAN_MODE_LOW
elif mode == FAN_MODE_MEDIUM:
cmd = CMD_FAN_MODE_MEDIUM
elif mode == FAN_MODE_HIGH:
cmd = CMD_FAN_MODE_HIGH
else:
raise Exception('Unknown fan mode.')

self._bridge.CnRmiRequest(node, cmd)

def request(self, parameter, node=1):
if not parameter in SIZE_MAP:
raise Exception('Unknown parameter.')

self._bridge.CnRpdoRequest(parameter, node, SIZE_MAP.get(parameter))
from .comfoconnect import *
from .error import *
from .const import *
Loading

0 comments on commit de2fde1

Please sign in to comment.