From a374a7c1067ef2351ab66d395c6d61a83206c780 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 20 Feb 2019 18:59:07 +0100 Subject: [PATCH] First version. --- README.md | 16 ++++- beamerctl.py | 169 ++++++++++++++++++++++++++++++++++++++++++++++ beamerctl.service | 13 ++++ heizberry.py | 99 +++++++++++++++++++++++++++ heizberry.service | 13 ++++ requirements.txt | 3 + 6 files changed, 311 insertions(+), 2 deletions(-) create mode 100755 beamerctl.py create mode 100644 beamerctl.service create mode 100755 heizberry.py create mode 100644 heizberry.service create mode 100644 requirements.txt diff --git a/README.md b/README.md index a6c8109..bdd2093 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,14 @@ -# Heizberry -Service to control the Equiva thermostats in the foobar. +# Heizberry Pi +Service to control the Equiva thermostats in the foobar. Can be installed on Raspberry Pi. Requires Bluetooth 4.0/LE module. + +## Installation +1. Install Raspberry Pi with Raspian. +2. Find MAC-addresses of thermostats + - sudo addgroup pi bluetooth + - run bluetoothctl +2. Connect bluetooth USB dongle. +Controller will be found. +3. Type command scan on +Bluetooth devices are searched. +[NEW] Device 00:1A:22:0D:BE:EE CC-RT-BLE + diff --git a/beamerctl.py b/beamerctl.py new file mode 100755 index 0000000..bbaaa56 --- /dev/null +++ b/beamerctl.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python3 + +import argparse +import re +import serial +import time +import signal +import logging +import sys +import schedule +import paho.mqtt.client as mqtt +from beamer import acer as beamercodes +code = beamercodes.clubbeamer() + +def on_connect(client, userdata, flags, rc): + global beamer_state + global input_source + + log.debug("Connected with result code " + str(rc)) + + beamer_state = readBeamerState() + client.publish("foobar/oben/cantina/beamer/status", beamer_state, qos=1, retain=True) + + input_source = readInputSource() + client.publish("foobar/oben/cantina/beamer/source", input_source, qos=1, retain=True) + + client.subscribe("foobar/oben/cantina/beamer/action") + + +def on_publish(client, userdata, mid): + log.debug("mid: "+str(mid)) + + +def on_message(client, userdata, message): + msg = message.payload.decode("utf-8") + log.debug('received message: {}'.format(msg)) + if (msg == "on"): + ser.write(code.set['on']) + + if (msg == "off"): + ser.write(code.set['off']) + + if (msg == "vga"): + ser.write(code.set['vga']) + + if (msg == "hdmi1"): + ser.write(code.set['hdmi1'][0]) + time.sleep(1) + ser.write(code.set['hdmi1'][1]) + + if (msg == "hdmi2"): + ser.write(code.set['hdmi2'][0]) + time.sleep(0.5) + ser.write(code.set['hdmi2'][1]) + time.sleep(0.5) + ser.write(code.set['hdmi2'][2]) + + +def readBeamerState(): + ser.write(b"* 0 Lamp ?\r") + read_val = ser.read(size=64) + if(re.match(b'.*Lamp.1.*', read_val)): + status = "on" + else: + status = "off" + return status + + +def beamerStatusChanged(): + global beamer_state + if (beamer_state != readBeamerState()): + log.debug('Beamer state has changed') + beamer_state = readBeamerState() + return True + else: + return False + + +def readInputSource(): + ser.write(b"* 0 Src ?\r") + read_val = ser.read(size=64) + if(re.match(b'.*Src.0.*', read_val)): + return "no_input" + elif (re.match(b'.*Src.1.*', read_val)): + return "vga" + elif (re.match(b'.*Src.8.*', read_val)): + return "hdmi" + elif (readBeamerState()): + return "off" + +def inputSourceChanged(): + global input_source + if (input_source != readInputSource()): + log.debug('Input source has changed to {}'.format(readInputSource() )) + input_source = readInputSource() + return True + else: + return False + +def terminate(signum, frame): + log.warn('SIGTERM received. Shutting down!') + log.info('Closing serial connection') + ser.close() + log.info('stopping mqtt client') + client.loop_stop() + log.info('disconnecting mqtt client') + client.disconnect() + log.info('beamerctl stopped all functions; exit') + sys.exit(0) + + +def getArgs(): + parser = argparse.ArgumentParser() + parser.add_argument("-v", "--verbose", action="store_true", + help="increase output verbosity") + return parser.parse_args() + +def periodicUpdate(): + log.debug('run scheduled statusupdates') + client.publish("foobar/oben/cantina/beamer/status", readBeamerState(), qos=1, retain=True) + client.publish("foobar/oben/cantina/beamer/source", readInputSource(), qos=1, retain=True) + + +if __name__ == '__main__': + beamer_state = False + input_source = False + + signal.signal(signal.SIGINT, terminate) + args = getArgs() + logging.basicConfig( + level=logging.DEBUG, format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s') + log = logging.getLogger('beamerctl') + if args.verbose: + log.setLevel(logging.DEBUG) + log.info('Loglevel set to DEBUG') + else: + log.setLevel(logging.WARN) + + serialport = '/dev/ttyUSB0' + + try: + ser = serial.Serial(port=serialport, baudrate=9600, timeout=1) + except serial.serialutil.SerialException as e: + log.critical(e) + sys.exit(1) + + client = mqtt.Client() + client.on_connect = on_connect + client.on_message = on_message + client.connect("10.42.0.244", 1883, 60) + + client.loop_start() + + log.debug('schedule periodic statusupdates') + schedule.every(1).minutes.do(periodicUpdate) + + time.sleep(5) + + while True: + schedule.run_pending() + + if (inputSourceChanged()): + client.publish("foobar/oben/cantina/beamer/source", + input_source, qos=1, retain=True) + + if (beamerStatusChanged()): + client.publish("foobar/oben/cantina/beamer/status", + beamer_state, qos=1, retain=True) + time.sleep(1) diff --git a/beamerctl.service b/beamerctl.service new file mode 100644 index 0000000..d2f6711 --- /dev/null +++ b/beamerctl.service @@ -0,0 +1,13 @@ +[Unit] +Description=heizberry +After=network-online.target + +[Service] +Type=Simple +ExecStart=/srv/herizberry/heizberry.py + +Restart=always +RestartSec=3 + +[Install] +WantedBy=multi-user.target diff --git a/heizberry.py b/heizberry.py new file mode 100755 index 0000000..9ad3c7c --- /dev/null +++ b/heizberry.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 + +import argparse +import re +import time +import signal +import logging +import sys +import schedule +import paho.mqtt.client as mqtt +from eq3bt import Thermostat + +thermostatBallpit = Thermostat('00:1A:22:0D:BE:EE') + +global temperature_off = 12 +global temperature_on = 19 + + +def on_connect(client, userdata, flags, rc): + log.debug("Connected with result code " + str(rc)) + + sendReadings() + + +def on_publish(client, userdata, mid): + log.debug("mid: "+str(mid)) + + +def on_message(client, userdata, message): + msg = message.payload.decode("utf-8") + log.debug('received message: %s from %s', format(msg), format(message.topic)) + + if (message.topic == "foobar/oben/baellebad/heizung/action") + if (msg == "on"): + thermostatBallpit.target_temperature=temperature_on + else + if (msg == "on"): + thermostatBallpit.target_temperature=temperature_on + else + thermostatBallpit.target_temperature=msg + + + +def sendReadings(): + log.debug('read target temperature from thermostats') + + # Bällebad + # Update readings + thermostatBallpit.update() + + # Send target temperatures + temp=thermostatBallpit.target_temperature + if(temp == temperature_on) + temp = temp + " on" + + if(temp == temperature_off) + temp = temp + " off" + + client.publish("foobar/oben/baellebad/status", temp, qos=1, retain=True) + + +def terminate(signum, frame): + log.warn('SIGTERM received. Shutting down!') + log.info('stopping mqtt client') + client.loop_stop() + log.info('disconnecting mqtt client') + client.disconnect() + log.info('heizberry stopped all functions; exit') + sys.exit(0) + + +def getArgs(): + parser = argparse.ArgumentParser() + parser.add_argument("-v", "--verbose", action="store_true", + help="increase output verbosity") + return parser.parse_args() + + +if __name__ == '__main__': + signal.signal(signal.SIGINT, terminate) + args = getArgs() + logging.basicConfig( + level=logging.DEBUG, format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s') + log = logging.getLogger('heizberry') + if args.verbose: + log.setLevel(logging.DEBUG) + log.info('Loglevel set to DEBUG') + else: + log.setLevel(logging.WARN) + + client = mqtt.Client("Heizberry_oben") + client.on_connect = on_connect + client.on_message = on_message + client.connect("10.42.0.244", 1883, 60) + + client.loop_start() + + log.debug('schedule periodic readings') + schedule.every(1).minutes.do(sendReadings) diff --git a/heizberry.service b/heizberry.service new file mode 100644 index 0000000..d2f6711 --- /dev/null +++ b/heizberry.service @@ -0,0 +1,13 @@ +[Unit] +Description=heizberry +After=network-online.target + +[Service] +Type=Simple +ExecStart=/srv/herizberry/heizberry.py + +Restart=always +RestartSec=3 + +[Install] +WantedBy=multi-user.target diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..6542a7b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +paho_mqtt==1.3.0 +schedule==0.4.3 +python-eq3bt==0.1.10