215 lines
6.9 KiB
Python
Executable File
215 lines
6.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
|
|
import smbus
|
|
import time
|
|
import paho.mqtt.client as mqt
|
|
from datetime import datetime
|
|
import _thread
|
|
|
|
bus = smbus.SMBus(1)
|
|
mqtc = mqt.Client()
|
|
|
|
access = {}
|
|
# [ code : [last_access, penalty] ]
|
|
|
|
|
|
def allowed(code):
|
|
print (access)
|
|
if code in access:
|
|
if millis_since(access[code][0]) > 3000+access[code][1]:
|
|
access[code] = [datetime.now(),0]
|
|
return True
|
|
else:
|
|
access[code] = [datetime.now(),access[code][1]+3000]
|
|
return False
|
|
else:
|
|
access[code] = [datetime.now(),0]
|
|
return True
|
|
|
|
def millis_since(start_time):
|
|
dt = datetime.now() - start_time
|
|
ms = (dt.days * 24 * 60 * 60 + dt.seconds) * 1000 + dt.microseconds / 1000.0
|
|
return ms
|
|
|
|
def on_connect(mosq, obj, foo ,bar ):
|
|
print( "Connected" )
|
|
|
|
def on_message(mosq, obj, msg):
|
|
#print( "Received on topic: " + msg.topic + " Message: "+str(msg.payload) );
|
|
msgs(msg.payload, msg.topic)
|
|
|
|
def on_subscribe(mosq, obj, mid, granted_qos):
|
|
print("Subscribed OK")
|
|
|
|
#Funktion Setze Bit in Variable / Function Set Bit in byte
|
|
def set_bit(value, bit):
|
|
return value | (1<<bit)
|
|
|
|
#Funktion rücksetzte Bit in Variable / Function reset Bit in byte
|
|
def clear_bit(value, bit):
|
|
return value & ~(1<<bit)
|
|
|
|
def i2c_status_thread_new():
|
|
services = ["strom", "licht"]
|
|
while True:
|
|
byte = bus.read_byte(inputs[0])
|
|
for c,i in i2c_input[0].items():
|
|
on = byte | c == c
|
|
if on and state[i] == 0 or not on and state[i] == 1: #Turned on
|
|
mqtc.publish("foobar/oben/" + names[i][0] + "/" + services[names[i][1]] + "/status", states[1 if on else 0], qos=0, retain=False)
|
|
state[i] = 1 if on else 0
|
|
time.sleep(5)
|
|
|
|
#def i2c_status_thread():
|
|
# global state
|
|
#ports = (0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F)
|
|
# bael loun cant flur
|
|
# leba e ina-
|
|
# d lich
|
|
#ports = (0xF7,0,0,0xFE,0xFD,0xFB,0,0,0,0,0,0,0,0,0,0)
|
|
# while True:
|
|
# byte_ = bus.read_byte(inputs[0])
|
|
# print(byte_)
|
|
# update = list(map( lambda x: 1 if (byte_ | x == x) else 0, ports))
|
|
# byte_ = bus.read_byte(inputs[1])
|
|
# print(byte_)
|
|
# update[8:] = list(map( lambda x: 1 if (byte_ | x == x) else 0, ports[8:]))
|
|
# for i,j,n in zip(state,update,names):#
|
|
# if i != j:
|
|
# if n in power:
|
|
# mqtc.publish("foobar/oben/" + n + "/strom/status", states[j], qos=0, retain=False)
|
|
# else:
|
|
# mqtc.publish("foobar/oben/" + n + "/licht/status", states[j], qos=0, retain=False)
|
|
# state = update
|
|
# time.sleep(5)
|
|
|
|
#Buttonbefehle
|
|
def switch(i,speed=0.5):
|
|
if allowed(i):
|
|
o = 0
|
|
if i > 7:
|
|
o = set_bit(o,i-8)
|
|
bus.write_byte(0x21,255-o)
|
|
time.sleep(speed)
|
|
o = clear_bit(o,i-8)
|
|
bus.write_byte(0x21,255-o)
|
|
else:
|
|
o = set_bit(o, i)
|
|
bus.write_byte(0x3f,255-o)
|
|
time.sleep(speed)
|
|
o = clear_bit(o,i)
|
|
bus.write_byte(0x3f,255-o)
|
|
|
|
state = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
|
inputs = (0x23,0x21)
|
|
states = {0: "OFF", 1: "ON"}
|
|
commands = { "flur" : 0, "baellebad" : 1, "lounge-front": 2, "lounge-back" : 3,"baellebad-ein" : 4, "lounge-ein" : 5, "cantina-ein" : 6, "zentral-aus" : 7, "cantina" : 8, "flur-strobo": 100, "cantina-strobo": 99}
|
|
i2c_input = [{ 0xFE : 4, 0xFD : 5, 0xFB : 8, 0xF7 : 0 }, {}]
|
|
names = { 7: [ "zentral",0] , 4: ["baellebad",0], 5: ["lounge",0], 6: ["cantina",0], 0: ["flur",1], 1: ["baellebad",1], 2:["lounge-front",1], 3: ["lounge-back",1], 8: ["cantina",1]}
|
|
power = { "zentral" : 7 , "baellebad" : 4, "lounge" : 5, "cantina" : 6 }
|
|
light = { "flur" : 0, "baellebad" : 1, "lounge-front" : 2, "lounge-back" : 3, "cantina" : 8 }
|
|
|
|
# foobar/oben/lounge /licht/action
|
|
# cantina /strom/status
|
|
# flur
|
|
# baellebad
|
|
# zentral
|
|
|
|
def switch_state(i, state, speed=0.5):
|
|
if state[i] != state: # changed
|
|
switch(i,speed=0.5)
|
|
state[i] = state
|
|
return True
|
|
return False
|
|
|
|
def switch_toggle(i,speed=0.5):
|
|
switch(i, speed=0.5)
|
|
state[i] = 0 if state[i] == 1 else 1
|
|
|
|
def decode_topic(topic, state):
|
|
clist = topic.split('/')
|
|
if clist[3] == "licht":
|
|
if clist[2] in light:
|
|
if switch_state(light[clist[2]], state):
|
|
mqtc.publish(topic.replace("action", "status"), states[state], qos=0, retain=False)
|
|
elif clist[3] == "strom":
|
|
if clist[2] in power:
|
|
if switch_state(power[clist[2]], state):
|
|
mqtc.publish(topic.replace("action", "status"), states[state], qos=0, retain=False)
|
|
|
|
def msgs(inp, topic):
|
|
c = inp.decode("utf-8")
|
|
l = len(c)
|
|
# supporting number commands
|
|
if c == "OFF" or c == "ON":
|
|
if c.find("ON") >= 0:
|
|
decode_topic(topic, 1)
|
|
elif c.find("OFF") >= 0:
|
|
decode_topic(topic, 0)
|
|
return
|
|
elif l < 3:
|
|
try:
|
|
msg = int(inp)
|
|
switch_toggle(msg)
|
|
except ValueError:
|
|
return
|
|
|
|
#supporting string commmands with dimming parameters
|
|
else:
|
|
cmds = c.split(",")
|
|
if len(cmds) > 1:
|
|
command = 9001
|
|
#error checking
|
|
if cmds[0] in commands:
|
|
command = cmds[0]
|
|
try:
|
|
arg = int (cmds[1])
|
|
except ValueError:
|
|
return
|
|
|
|
#strobo
|
|
if ( command == 100 or command == 99 ):
|
|
if arg < 100:
|
|
for i in range(arg):
|
|
switch((100-command)*8, speed=0.05)
|
|
time.sleep(0.06)
|
|
|
|
#command with parameter used for dimming
|
|
else:
|
|
switch_toggle(command,speed = 4*arg/100+1 )
|
|
|
|
#single string command without parameter
|
|
else:
|
|
try:
|
|
if c in commands:
|
|
switch_toggle(commands[c])
|
|
except KeyError:
|
|
return
|
|
|
|
return
|
|
|
|
|
|
def init_mqtt():
|
|
mqtc.connect("10.42.0.244", 1883, 60)
|
|
mqtc.subscribe("foobar/oben/licht", 0)
|
|
mqtc.subscribe("foobar/oben/lounge-back/licht/action", 0)
|
|
mqtc.subscribe("foobar/oben/lounge-front/licht/action", 0)
|
|
mqtc.subscribe("foobar/oben/lounge/strom/action", 0)
|
|
mqtc.subscribe("foobar/oben/baellebad/licht/action", 0)
|
|
mqtc.subscribe("foobar/oben/baellebad/strom/action", 0)
|
|
mqtc.subscribe("foobar/oben/cantina/licht/action", 0)
|
|
mqtc.subscribe("foobar/oben/cantina/strom/action", 0)
|
|
mqtc.subscribe("foobar/oben/flur/licht/action", 0)
|
|
mqtc.subscribe("foobar/oben/licht", 0)
|
|
mqtc.on_message = on_message
|
|
mqtc.on_connect = on_connect
|
|
mqtc.on_subscribe = on_subscribe
|
|
|
|
_thread.start_new_thread(i2c_status_thread_new, ())
|
|
|
|
mqtc.loop_forever()
|
|
|
|
init_mqtt()
|
|
|
|
# vim: noai:ts=4:sw=4
|