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
|
#!/usr/bin/python3
import time
import datetime
import subprocess
import select
import atexit
import serial
import socket
procs = []
timerange_start = dict(hour=18, minute=30, second=0, microsecond=0)
timerange_stop = dict(hour=22, minute=00, second=0, microsecond=0)
listen_addr = '192.168.1.1'
listen_port = 1078
@atexit.register
def kill_subprocesses():
for proc in procs:
proc.kill()
class Tailer:
def __init__(self):
command1 = '/usr/bin/tail /var/log/syslog -f'
command2 = '/bin/grep --line-buffered "DHCPREQUEST.*AA:BB:CC:DD:EE:FF"'
self.tailpipe = subprocess.Popen(
'{} | {}'.format(command1, command2),
shell=True,
stdout=subprocess.PIPE,
universal_newlines=True,
)
procs.append(self.tailpipe)
def in_correct_timerange(self):
line = self.tailpipe.stdout.readline().strip()
line = ' '.join(line.split()[:3])
current_dt = datetime.datetime.strptime(
line, '%b %d %H:%M:%S').replace(
year=datetime.datetime.now().year)
start_dt = current_dt.replace(**timerange_start)
stop_dt = current_dt.replace(**timerange_stop)
return start_dt < current_dt < stop_dt
def get_fd(self):
return self.tailpipe.stdout
class LightCommand:
def __init__(self):
self.serial = serial.Serial('/dev/serial/by-id/device', baudrate=9600)
self.state = None
def toggle(self):
print('Toggling light')
self.serial.write(b'T')
if self.state is not None:
self.state != self.state
def on(self):
print('Turn on light')
if not self.state:
self.serial.write(b'1')
self.state = True
def off(self):
print('Turn off light')
if self.state:
self.serial.write(b'0')
self.state = False
class Server:
def __init__(self):
self.ssock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.ssock.bind((listen_addr, listen_port))
def get_fd(self):
return self.ssock
def get_command(self):
data, _ = self.ssock.recvfrom(32)
return data.strip().strip(b'\r\n').lower()
tailer = Tailer()
lightcommand = LightCommand()
server = Server()
while True:
fdlist, _, _ = select.select([
tailer.get_fd(), server.get_fd()], [], [])
for fd in fdlist:
if fd is tailer.get_fd() and tailer.in_correct_timerange():
print('Ok, in correct timerange, turning light on')
lightcommand.on()
elif fd is server.get_fd():
command = server.get_command()
print('Received command "{}" on udp socket'.format(command))
if command == b'on':
lightcommand.on()
elif command == b'off':
lightcommand.off()
elif command == b'toggle':
lightcommand.toggle()
|