-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlisten.py
executable file
·175 lines (148 loc) · 5.98 KB
/
listen.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#!/usr/bin/python3
import serial
import cherrypy
import threading
import time
import threading
import queue
import json
import datetime
import requests
import logging
import syslog
ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=1)
nomi = {
"11":{"on": False, "fromweb": False, "watt":270, "description": "ingresso"},
"12":{"on": False, "fromweb": False, "watt":216, "description": "ingresso laterale"},
"13":{"on": False, "fromweb": False, "watt":162, "description": "reception"},
"14":{"on": False, "fromweb": False, "watt":144, "description": "scala"},
"15":{"on": False, "fromweb": False, "watt":108, "description": "corridoio pT"},
"16":{"on": False, "fromweb": False, "watt":108, "description": "cabinati"},
"17":{"on": False, "fromweb": False, "watt":18, "description": "antibagno pT"},
"18":{"on": False, "fromweb": False, "watt":36, "description": "bagno pT"},
"21":{"on": False, "fromweb": False, "watt":324, "description": "museo 1"},
"22":{"on": False, "fromweb": False, "watt":324, "description": "museo 2"},
"23":{"on": False, "fromweb": False, "watt":324, "description": "museo 3"},
"24":{"on": False, "fromweb": False, "watt":60, "description": "sgabuzzino museo"},
"33":{"on": False, "fromweb": False, "watt":270, "description": "simulatore"},
"34":{"on": False, "fromweb": False, "watt":36, "description": "sottoscala"},
"35":{"on": False, "fromweb": False, "watt":60, "description": "rack"},
"51":{"on": False, "fromweb": False, "watt":162, "description": "corridoio p1"},
"52":{"on": False, "fromweb": False, "watt":60, "description": "sgabuzzino rack"},
"53":{"on": False, "fromweb": False, "watt":60, "description": "fablab 1"},
"54":{"on": False, "fromweb": False, "watt":108, "description": "ufficio 1"},
"55":{"on": False, "fromweb": False, "watt":60, "description": "slot car"},
"56":{"on": False, "fromweb": False, "watt":54, "description": "emeroteca"},
"57":{"on": False, "fromweb": False, "watt":60, "description": "fablab 2"},
"58":{"on": False, "fromweb": False, "watt":270, "description": "ufficio 2"},
"61":{"on": False, "fromweb": False, "watt":324, "description": "sala riunioni 2"},
"62":{"on": False, "fromweb": False, "watt":324, "description": "sala riunioni 1"},
"63":{"on": False, "fromweb": False, "watt":324, "description": "sala riunioni 3"},
"64":{"on": False, "fromweb": False, "watt":162, "description": "sala riunioni 4"},
"65":{"on": False, "fromweb": False, "watt":18, "description": "antibagno p1"},
"66":{"on": False, "fromweb": False, "watt":36, "description": "bagno p1"},
"67":{"on": False, "fromweb": False, "watt":60, "description": "sgabuzzino sala riunioni"}}
ser.write("@MA".encode())
ser.write("@l".encode())
def checkdouble(first,second):
if nomi[first]["on"] & nomi[second]["on"]:
swritequeue.put([int(second,16),0x4])
def serialread(): #Continuous loop to read serial
array = []
trasmissione = 0
while True:
line=ser.readline()
octet=line.decode('utf-8').split()
if len(octet) == 2: #Only messages from the bus, no echo
octet=octet[1]
else:
octet=None
if octet == "A8": #Start of frame
trasmissione = True
#if trasmissione is False and octet == "A5": #Acknowledgement TODO
#ackqueue.put(["ACK"])
if trasmissione is True:
array.append(octet)
if len(array) >= 7: #Reached max MTU
if octet == "A3": #End of frame
trasmissione = False
checksum = int(array[1],16)^int(array[2],16)^int(array[3],16)^int(array[4],16)
if checksum == int(array[5],16):
print(array)
sreadqueue.put(array)
else: #The packet did not terminate with A3. This is an error. Drop everything.
trasmissione = False
array = []
def serialprint(serial,message):
xor = message[0]^0x50^0x12^message[1]
key = "@W7A8"+hex(message[0])[2:4]+"50120"+hex(message[1])[2:4]+str(hex(xor)[2:4])+"A3"
serial.write(key.encode())
time.sleep(0.75)
def deduplicator():
lastpacket = ['inizio'] #Dummy packet
while True:
serialinput = sreadqueue.get()
if (set(serialinput) != set(lastpacket)): #If the queue returned something (i.e. a packet) and it's not a duplicate, forward along
inpacketqueue.put(serialinput)
lastpacket = serialinput[0:7]
def logger(packet):
if int(packet[4]) == 4:
try:
nomi[str(packet[2])]["on"] = False
nomi[str(packet[2])]["fromweb"] = False
syslog.syslog(datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')+" "+str(packet)+" OFF")
postinstconsumption()
except:
pass
elif int(packet[4]) == 8:
try:
nomi[str(packet[2])]["on"] = True
syslog.syslog(datetime.datetime.fromtimestamp(time.time()).strftime('%Y-%m-%d %H:%M:%S')+" "+str(packet)+" ON")
postinstconsumption()
except:
pass
def switch():
while True:
time.sleep(0.01)
if not swritequeue.empty():
serialprint(ser,swritequeue.get())
if not inpacketqueue.empty():
logger(inpacketqueue.get())
class LightAPI(object):
@cherrypy.expose
def action(self,id=0,status=0):
answer = ""
swritequeue.put([int(id,16),int(status,16)])
@cherrypy.expose
def statushuman(self):
tempdict = {}
for lightid in nomi:
tempdict[nomi[lightid]["description"]] = nomi[lightid]["on"]
return json.dumps(tempdict,sort_keys=True)
@cherrypy.expose
def status(self):
tempdict = {}
for lightid in nomi:
tempdict[str(lightid)] = nomi[lightid]["on"]
return json.dumps(tempdict,sort_keys=True)
@cherrypy.expose
def consumo(self):
consumption = 0
for lightid in nomi:
this = nomi[lightid]
if this["on"] == True:
consumption = consumption + this["watt"]
return str(consumption)
status.exposed = True
syslog.openlog(logoption=syslog.LOG_PID)
sreadqueue = queue.Queue() #Queue for packets coming from the serial
inpacketqueue = queue.Queue() #Queue of deduplicated packets
swritequeue = queue.Queue() #Queue of commands to write
serialreadThread = threading.Thread(target=serialread)
serialreadThread.start()
switchThread = threading.Thread(target=switch)
switchThread.start()
dedupThread = threading.Thread(target=deduplicator)
dedupThread.start()
cherrypy.server.socket_host = "0.0.0.0"
cherrypy.quickstart(LightAPI())