Login | ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/alarming/trunk/Server/daemon.py
(Generate patch)

Comparing trunk/Server/daemon.py (file contents):
Revision 3 by daniel-marschall, Mon May 6 21:25:33 2019 UTC vs.
Revision 4 by daniel-marschall, Tue May 7 09:36:39 2019 UTC

# Line 9 | Line 9 | import time
9   import requests
10   import subprocess
11   import config
12 + import threading
13  
14   g_subscribed = []
15  
# Line 25 | Line 26 | class S(BaseHTTPRequestHandler):
26          except:
27                  action = None
28  
29 <        output = '''<html>
29 >        output = '''<!DOCTYPE html>
30 > <html lang="en">
31  
32   <head>
33 +        <meta charset="UTF-8">
34          <title>Motion camera</title>
35   </head>
36  
# Line 40 | Line 43 | function sleep (time) {
43   }
44  
45   function _toggle_alarm(st) {
46 <        document.getElementById("pleasewait").innerHTML = ' <i>Bitte warten</i>...';
46 >        document.getElementById("pleasewait").innerHTML = ' <i>Please wait...</i>';
47          var xhr = new XMLHttpRequest();
48          xhr.onreadystatechange = function () {
49                  var DONE = 4; // readyState 4 means the request is done.
# Line 58 | Line 61 | function _toggle_alarm(st) {
61  
62          var data = new FormData();
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*/);
64 <        xhr.open('POST', '/', true);
64 >        xhr.open('POST', document.location, true);
65          xhr.send(data);
66   }
67  
68   function onload() {
69 <        document.getElementById('campic').src = 'http://' + window.location.hostname + ':'''+str(config.motion_stream_port)+'''/';
69 >        if (document.getElementById('campic') != null) {
70 >                document.getElementById('campic').src = 'http://' + window.location.hostname + ':'''+str(config.motion_stream_port)+'''/';
71 >        }
72   }
73  
74   </script>'''
75  
76          if ismotionrunning():
77 <                output = output + '<h2>Motion detection ON</h2>';
78 <                output = output + '<p><a href="javascript:_toggle_alarm(0)">Disable motion detection</a><span id="pleasewait"></span></p>';
79 <                output = output + '<p><img id="campic" src="" alt="Camera picture"></p>';
77 >                output = output + '<h2>Motion detection ON</h2>'
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)
80 >                output = output + '<p><img id="campic" src="" alt=""></p>';
81          else:
82 <                output = output + '<h2>Motion detection OFF</h2>';
83 <                output = output + '<p><a href="javascript:_toggle_alarm(1)">Enable motion detection</a><span id="pleasewait"></span></p>';
82 >                output = output + '<h2>Motion detection OFF</h2>'
83 >                output = output + '<p><a href="javascript:_toggle_alarm(1)">Enable motion detection</a><span id="pleasewait"></span></p>'
84  
85          output = output + '<h2>Subscribers</h2>'
86  
# Line 97 | Line 103 | function onload() {
103      def do_HEAD(self):
104          self._output(200, '')
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 +
114      def do_POST(self):
115          # https://stackoverflow.com/questions/4233218/python-how-do-i-get-key-value-pairs-from-the-basehttprequesthandler-http-post-h
116 <        # 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?)
117          ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
118          if ctype == 'multipart/form-data':
119                  postvars = cgi.parse_multipart(self.rfile, pdict)
# Line 145 | Line 159 | function onload() {
159  
160                  found_g = 0
161  
162 <                # TODO: this should be done in parallel threads, so that we can notify every client as fast as possible!
163 <                for x in g_subscribed:
164 <                        client_ip      = x[0]
165 <                        client_port    = x[1]
166 <                        client_expires = x[2]
153 <                        client_targets = x[3]
162 >                for subscriber in g_subscribed:
163 >                        client_ip      = subscriber[0]
164 >                        client_port    = subscriber[1]
165 >                        client_expires = subscriber[2]
166 >                        client_targets = subscriber[3]
167                          found_c = 0
168                          for st in server_targets:
169                                  for ct in client_targets:
# Line 158 | Line 171 | function onload() {
171                                                  found_c = found_c + 1
172                                                  found_g = found_g + 1
173                          if found_c > 0:
174 <                                print "ALERT: Will alert client http://{0}:{1} and tell that targets {2} sent an alert".format(client_ip, client_port, server_targets)
175 <                                d = {"action": "client_alert", # 1.3.6.1.4.1.37476.2.4.1.3
176 <                                     "targets": server_targets,
164 <                                     "motion_port": config.motion_stream_port,
165 <                                     "simulation": "0"}
166 <                                requests.post("http://{0}:{1}".format(client_ip, client_port), data=d)
174 >                                # Notify clients via threads, so that all clients are equally fast notified
175 >                                thread = threading.Thread(target=self.thr_client_notify, args=(client_ip, client_port, server_targets, ))
176 >                                thread.start()
177  
178                  if found_g == 0:
179                          print "ALERT {0}, but nobody is listening!".format(server_targets)
180  
171
181          if pvget(postvars, "action")[0] == "motion_on": # 1.3.6.1.4.1.37476.2.4.1.100
182                  print "Motion start"
183                  os.system(os.path.dirname(os.path.abspath(__file__)) + "/motion/motion_start_safe")
# Line 186 | Line 195 | def pvget(ary, key):
195                  return ary.get(key)
196  
197   def run(server_class=HTTPServer, handler_class=S, port=8085):
198 +        print 'Starting server, listening to port {0}...'.format(port)
199          server_address = ('', port)
200          httpd = server_class(server_address, handler_class)
191        print 'Starting httpd...'
201          httpd.serve_forever()
202  
203   def ismotionrunning():

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines