forked from Chaospott/Heizberry
First version.
This commit is contained in:
parent
8a23323ac0
commit
a374a7c106
16
README.md
16
README.md
@ -1,2 +1,14 @@
|
|||||||
# Heizberry
|
# Heizberry Pi
|
||||||
Service to control the Equiva thermostats in the foobar.
|
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
|
||||||
|
|
||||||
|
169
beamerctl.py
Executable file
169
beamerctl.py
Executable file
@ -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)
|
13
beamerctl.service
Normal file
13
beamerctl.service
Normal file
@ -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
|
99
heizberry.py
Executable file
99
heizberry.py
Executable file
@ -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)
|
13
heizberry.service
Normal file
13
heizberry.service
Normal file
@ -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
|
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
paho_mqtt==1.3.0
|
||||||
|
schedule==0.4.3
|
||||||
|
python-eq3bt==0.1.10
|
Loading…
Reference in New Issue
Block a user