Subversion Repositories alarming

Rev

Rev 3 | Rev 5 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3 Rev 4
Line 7... Line 7...
7
import cgi
7
import cgi
8
import time
8
import time
9
import requests
9
import requests
10
import subprocess
10
import subprocess
11
import config
11
import config
-
 
12
import threading
12
 
13
 
13
g_subscribed = []
14
g_subscribed = []
14
 
15
 
15
class S(BaseHTTPRequestHandler):
16
class S(BaseHTTPRequestHandler):
16
    def _output(self, code, content):
17
    def _output(self, code, content):
Line 23... Line 24...
23
        try:
24
        try:
24
                action = parse_qs(self.path[2:]).get("action")[0]
25
                action = parse_qs(self.path[2:]).get("action")[0]
25
        except:
26
        except:
26
                action = None
27
                action = None
27
 
28
 
28
        output = '''<html>
29
        output = '''<!DOCTYPE html>
-
 
30
<html lang="en">
29
 
31
 
30
<head>
32
<head>
-
 
33
        <meta charset="UTF-8">
31
        <title>Motion camera</title>
34
        <title>Motion camera</title>
32
</head>
35
</head>
33
 
36
 
34
<body onload="onload()">
37
<body onload="onload()">
35
 
38
 
Line 38... Line 41...
38
function sleep (time) {
41
function sleep (time) {
39
        return new Promise((resolve) => setTimeout(resolve, time));
42
        return new Promise((resolve) => setTimeout(resolve, time));
40
}
43
}
41
 
44
 
42
function _toggle_alarm(st) {
45
function _toggle_alarm(st) {
43
        document.getElementById("pleasewait").innerHTML = ' <i>Bitte warten</i>...';
46
        document.getElementById("pleasewait").innerHTML = ' <i>Please wait...</i>';
44
        var xhr = new XMLHttpRequest();
47
        var xhr = new XMLHttpRequest();
45
        xhr.onreadystatechange = function () {
48
        xhr.onreadystatechange = function () {
46
                var DONE = 4; // readyState 4 means the request is done.
49
                var DONE = 4; // readyState 4 means the request is done.
47
                var OK = 200; // status 200 is a successful return.
50
                var OK = 200; // status 200 is a successful return.
48
                if (xhr.readyState === DONE) {
51
                if (xhr.readyState === DONE) {
Line 56... Line 59...
56
                }
59
                }
57
        };
60
        };
58
 
61
 
59
        var data = new FormData();
62
        var data = new FormData();
60
        data.append('action', st ? 'motion_on'/*1.3.6.1.4.1.37476.2.4.1.100*/ : 'motion_off'/*1.3.6.1.4.1.37476.2.4.1.101*/);
63
        data.append('action', st ? 'motion_on'/*1.3.6.1.4.1.37476.2.4.1.100*/ : 'motion_off'/*1.3.6.1.4.1.37476.2.4.1.101*/);
61
        xhr.open('POST', '/', true);
64
        xhr.open('POST', document.location, true);
62
        xhr.send(data);
65
        xhr.send(data);
63
}
66
}
64
 
67
 
65
function onload() {
68
function onload() {
-
 
69
        if (document.getElementById('campic') != null) {
66
        document.getElementById('campic').src = 'http://' + window.location.hostname + ':'''+str(config.motion_stream_port)+'''/';
70
                document.getElementById('campic').src = 'http://' + window.location.hostname + ':'''+str(config.motion_stream_port)+'''/';
67
}
71
        }
-
 
72
}
68
 
73
 
69
</script>'''
74
</script>'''
70
 
75
 
71
        if ismotionrunning():
76
        if ismotionrunning():
72
                output = output + '<h2>Motion detection ON</h2>';
77
                output = output + '<h2>Motion detection ON</h2>'
73
                output = output + '<p><a href="javascript:_toggle_alarm(0)">Disable motion detection</a><span id="pleasewait"></span></p>';
78
                output = output + '<p><a href="javascript:_toggle_alarm(0)">Disable motion detection</a><span id="pleasewait"></span></p>'
-
 
79
                output = output + '<p>Showing camera stream from port {0}. If you don\'t see a picture, please check your configuration or firewall.</p>'.format(config.motion_stream_port)
74
                output = output + '<p><img id="campic" src="" alt="Camera picture"></p>';
80
                output = output + '<p><img id="campic" src="" alt=""></p>';
75
        else:
81
        else:
76
                output = output + '<h2>Motion detection OFF</h2>';
82
                output = output + '<h2>Motion detection OFF</h2>'
77
                output = output + '<p><a href="javascript:_toggle_alarm(1)">Enable motion detection</a><span id="pleasewait"></span></p>';
83
                output = output + '<p><a href="javascript:_toggle_alarm(1)">Enable motion detection</a><span id="pleasewait"></span></p>'
78
 
84
 
79
        output = output + '<h2>Subscribers</h2>'
85
        output = output + '<h2>Subscribers</h2>'
80
 
86
 
81
        found_subs = 0
87
        found_subs = 0
82
        for x in g_subscribed[:]:
88
        for x in g_subscribed[:]:
Line 95... Line 101...
95
        self._output(200, output)
101
        self._output(200, output)
96
 
102
 
97
    def do_HEAD(self):
103
    def do_HEAD(self):
98
        self._output(200, '')
104
        self._output(200, '')
99
 
105
 
-
 
106
    def thr_client_notify(self, client_ip, client_port, server_targets):
-
 
107
                print "ALERT: Will alert client http://{0}:{1} and tell that targets {2} sent an alert".format(client_ip, client_port, server_targets)
-
 
108
                d = {"action": "client_alert", # 1.3.6.1.4.1.37476.2.4.1.3
-
 
109
                     "targets": server_targets,
-
 
110
                     "motion_port": config.motion_stream_port,
-
 
111
                     "simulation": "0"}
-
 
112
                requests.post("http://{0}:{1}".format(client_ip, client_port), data=d)
-
 
113
 
100
    def do_POST(self):
114
    def do_POST(self):
101
        # https://stackoverflow.com/questions/4233218/python-how-do-i-get-key-value-pairs-from-the-basehttprequesthandler-http-post-h
115
        # https://stackoverflow.com/questions/4233218/python-how-do-i-get-key-value-pairs-from-the-basehttprequesthandler-http-post-h
102
        # TODO: do we need the cgi package, or can we use functions available in this class (e.g. self_parse_qs?)
116
        # Question: Do we need the cgi package, or can we use functions available in this class (e.g. self_parse_qs?)
103
        ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
117
        ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
104
        if ctype == 'multipart/form-data':
118
        if ctype == 'multipart/form-data':
105
                postvars = cgi.parse_multipart(self.rfile, pdict)
119
                postvars = cgi.parse_multipart(self.rfile, pdict)
106
        elif ctype == 'application/x-www-form-urlencoded':
120
        elif ctype == 'application/x-www-form-urlencoded':
107
                length = int(self.headers.getheader('content-length'))
121
                length = int(self.headers.getheader('content-length'))
Line 143... Line 157...
143
        if pvget(postvars, "action")[0] == "server_alert": # 1.3.6.1.4.1.37476.2.4.1.2
157
        if pvget(postvars, "action")[0] == "server_alert": # 1.3.6.1.4.1.37476.2.4.1.2
144
                server_targets = pvget(postvars, "targets")
158
                server_targets = pvget(postvars, "targets")
145
 
159
 
146
                found_g = 0
160
                found_g = 0
147
 
161
 
148
                # TODO: this should be done in parallel threads, so that we can notify every client as fast as possible!
-
 
149
                for x in g_subscribed:
162
                for subscriber in g_subscribed:
150
                        client_ip      = x[0]
163
                        client_ip      = subscriber[0]
151
                        client_port    = x[1]
164
                        client_port    = subscriber[1]
152
                        client_expires = x[2]
165
                        client_expires = subscriber[2]
153
                        client_targets = x[3]
166
                        client_targets = subscriber[3]
154
                        found_c = 0
167
                        found_c = 0
155
                        for st in server_targets:
168
                        for st in server_targets:
156
                                for ct in client_targets:
169
                                for ct in client_targets:
157
                                        if ct == st:
170
                                        if ct == st:
158
                                                found_c = found_c + 1
171
                                                found_c = found_c + 1
159
                                                found_g = found_g + 1
172
                                                found_g = found_g + 1
160
                        if found_c > 0:
173
                        if found_c > 0:
161
                                print "ALERT: Will alert client http://{0}:{1} and tell that targets {2} sent an alert".format(client_ip, client_port, server_targets)
174
                                # Notify clients via threads, so that all clients are equally fast notified
162
                                d = {"action": "client_alert", # 1.3.6.1.4.1.37476.2.4.1.3
175
                                thread = threading.Thread(target=self.thr_client_notify, args=(client_ip, client_port, server_targets, ))
163
                                     "targets": server_targets,
176
                                thread.start()
164
                                     "motion_port": config.motion_stream_port,
-
 
165
                                     "simulation": "0"}
-
 
166
                                requests.post("http://{0}:{1}".format(client_ip, client_port), data=d)
-
 
167
 
177
 
168
                if found_g == 0:
178
                if found_g == 0:
169
                        print "ALERT {0}, but nobody is listening!".format(server_targets)
179
                        print "ALERT {0}, but nobody is listening!".format(server_targets)
170
 
180
 
171
 
-
 
172
        if pvget(postvars, "action")[0] == "motion_on": # 1.3.6.1.4.1.37476.2.4.1.100
181
        if pvget(postvars, "action")[0] == "motion_on": # 1.3.6.1.4.1.37476.2.4.1.100
173
                print "Motion start"
182
                print "Motion start"
174
                os.system(os.path.dirname(os.path.abspath(__file__)) + "/motion/motion_start_safe")
183
                os.system(os.path.dirname(os.path.abspath(__file__)) + "/motion/motion_start_safe")
175
 
184
 
176
        if pvget(postvars, "action")[0] == "motion_off": # 1.3.6.1.4.1.37476.2.4.1.101
185
        if pvget(postvars, "action")[0] == "motion_off": # 1.3.6.1.4.1.37476.2.4.1.101
Line 184... Line 193...
184
                return [""]
193
                return [""]
185
        else:
194
        else:
186
                return ary.get(key)
195
                return ary.get(key)
187
 
196
 
188
def run(server_class=HTTPServer, handler_class=S, port=8085):
197
def run(server_class=HTTPServer, handler_class=S, port=8085):
-
 
198
        print 'Starting server, listening to port {0}...'.format(port)
189
        server_address = ('', port)
199
        server_address = ('', port)
190
        httpd = server_class(server_address, handler_class)
200
        httpd = server_class(server_address, handler_class)
191
        print 'Starting httpd...'
-
 
192
        httpd.serve_forever()
201
        httpd.serve_forever()
193
 
202
 
194
def ismotionrunning():
203
def ismotionrunning():
195
        p = subprocess.Popen(["ps", "aux"], stdout=subprocess.PIPE)
204
        p = subprocess.Popen(["ps", "aux"], stdout=subprocess.PIPE)
196
        out, err = p.communicate()
205
        out, err = p.communicate()