aboutsummaryrefslogtreecommitdiffstats
path: root/doc/lightswitch.py.ex
blob: 8648600f7c2bcc911584425d037772996819e16f (plain)
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()