Subversion Repositories alarming

Compare Revisions

No changes between revisions

Regard whitespace Rev 2 → Rev 3

/trunk/Server/config.py
0,0 → 1,4
#!/usr/bin/env python
 
motion_stream_port = 8081;
 
/trunk/Server/daemon.py
0,0 → 1,210
#!/usr/bin/env python
 
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import SocketServer
from urlparse import parse_qs
import os
import cgi
import time
import requests
import subprocess
import config
 
g_subscribed = []
 
class S(BaseHTTPRequestHandler):
def _output(self, code, content):
self.send_response(code)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(content)
 
def do_GET(self):
try:
action = parse_qs(self.path[2:]).get("action")[0]
except:
action = None
 
output = '''<html>
 
<head>
<title>Motion camera</title>
</head>
 
<body onload="onload()">
 
<script>
 
function sleep (time) {
return new Promise((resolve) => setTimeout(resolve, time));
}
 
function _toggle_alarm(st) {
document.getElementById("pleasewait").innerHTML = ' <i>Bitte warten</i>...';
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
var DONE = 4; // readyState 4 means the request is done.
var OK = 200; // status 200 is a successful return.
if (xhr.readyState === DONE) {
if (xhr.status === OK) {
sleep(5000).then(() => {
document.location.reload();
});
} else {
alert('Error: ' + xhr.status); // An error occurred during the request.
}
}
};
 
var data = new FormData();
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*/);
xhr.open('POST', '/', true);
xhr.send(data);
}
 
function onload() {
document.getElementById('campic').src = 'http://' + window.location.hostname + ':'''+str(config.motion_stream_port)+'''/';
}
 
</script>'''
 
if ismotionrunning():
output = output + '<h2>Motion detection ON</h2>';
output = output + '<p><a href="javascript:_toggle_alarm(0)">Disable motion detection</a><span id="pleasewait"></span></p>';
output = output + '<p><img id="campic" src="" alt="Camera picture"></p>';
else:
output = output + '<h2>Motion detection OFF</h2>';
output = output + '<p><a href="javascript:_toggle_alarm(1)">Enable motion detection</a><span id="pleasewait"></span></p>';
 
output = output + '<h2>Subscribers</h2>'
 
found_subs = 0
for x in g_subscribed[:]:
if int(time.time()) > x[2]:
g_subscribed.remove(x)
else:
found_subs = found_subs + 1
output = output + "<p>{0}:{1}</p>".format(x[0], x[1])
 
if found_subs == 0:
output = output + '<p>None</p>'
 
output = output + '</body>'
output = output + '</html>'
 
self._output(200, output)
 
def do_HEAD(self):
self._output(200, '')
 
def do_POST(self):
# https://stackoverflow.com/questions/4233218/python-how-do-i-get-key-value-pairs-from-the-basehttprequesthandler-http-post-h
# TODO: do we need the cgi package, or can we use functions available in this class (e.g. self_parse_qs?)
ctype, pdict = cgi.parse_header(self.headers.getheader('content-type'))
if ctype == 'multipart/form-data':
postvars = cgi.parse_multipart(self.rfile, pdict)
elif ctype == 'application/x-www-form-urlencoded':
length = int(self.headers.getheader('content-length'))
postvars = cgi.parse_qs(self.rfile.read(length), keep_blank_values=1)
else:
postvars = {}
 
# ---
 
global g_subscribed
 
if pvget(postvars, "action")[0] == "client_subscribe": # 1.3.6.1.4.1.37476.2.4.1.1
client_ip = self.client_address[0]
client_port = pvget(postvars, "port")[0]
client_ttl = pvget(postvars, "ttl")[0]
client_targets = pvget(postvars, "targets")
 
client_expires = int(time.time()) + int(client_ttl)
 
print "Client subscribed: {0}:{1}, searching for targets {2}".format(client_ip, client_port, client_targets)
 
# Remove all expired entries, and previous entries of that client
for x in g_subscribed[:]:
if int(time.time()) > x[2]:
g_subscribed.remove(x)
elif (x[0] == client_ip) and (x[1] == client_port) and (x[3] == client_targets):
g_subscribed.remove(x)
 
# Now add our new client
g_subscribed.append([client_ip, client_port, client_expires, client_targets])
 
# Send parameters of the device(s)
d = {"action": "client_alert", # 1.3.6.1.4.1.37476.2.4.1.3
"targets": ['1.3.6.1.4.1.37476.2.4.2.0', '1.3.6.1.4.1.37476.2.4.2.1002'],
"motion_port": config.motion_stream_port,
"simulation": "1"}
requests.post("http://{0}:{1}".format(client_ip, client_port), data=d)
 
if pvget(postvars, "action")[0] == "server_alert": # 1.3.6.1.4.1.37476.2.4.1.2
server_targets = pvget(postvars, "targets")
 
found_g = 0
 
# TODO: this should be done in parallel threads, so that we can notify every client as fast as possible!
for x in g_subscribed:
client_ip = x[0]
client_port = x[1]
client_expires = x[2]
client_targets = x[3]
found_c = 0
for st in server_targets:
for ct in client_targets:
if ct == st:
found_c = found_c + 1
found_g = found_g + 1
if found_c > 0:
print "ALERT: Will alert client http://{0}:{1} and tell that targets {2} sent an alert".format(client_ip, client_port, server_targets)
d = {"action": "client_alert", # 1.3.6.1.4.1.37476.2.4.1.3
"targets": server_targets,
"motion_port": config.motion_stream_port,
"simulation": "0"}
requests.post("http://{0}:{1}".format(client_ip, client_port), data=d)
 
if found_g == 0:
print "ALERT {0}, but nobody is listening!".format(server_targets)
 
 
if pvget(postvars, "action")[0] == "motion_on": # 1.3.6.1.4.1.37476.2.4.1.100
print "Motion start"
os.system(os.path.dirname(os.path.abspath(__file__)) + "/motion/motion_start_safe")
 
if pvget(postvars, "action")[0] == "motion_off": # 1.3.6.1.4.1.37476.2.4.1.101
print "Motion stop"
os.system(os.path.dirname(os.path.abspath(__file__)) + "/motion/motion_stop_safe")
 
self._output(200, '')
 
def pvget(ary, key):
if ary.get(key) == None:
return [""]
else:
return ary.get(key)
 
def run(server_class=HTTPServer, handler_class=S, port=8085):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
print 'Starting httpd...'
httpd.serve_forever()
 
def ismotionrunning():
p = subprocess.Popen(["ps", "aux"], stdout=subprocess.PIPE)
out, err = p.communicate()
try:
return ('/usr/bin/motion' in str(out))
except:
res = os.system("pidof -x /usr/bin/motion > /dev/null")
return (res >> 8) == 0
 
if __name__ == "__main__":
from sys import argv
 
if len(argv) == 2:
run(port=int(argv[1]))
else:
run()
 
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/Server/motion/config
0,0 → 1,0
link /etc/motion/motion.conf
Property changes:
Added: svn:special
+*
\ No newline at end of property
/trunk/Server/motion/config_settings
0,0 → 1,7
You need to change following in /etc/motion/motion.conf :
 
on_picture_save /daten/alarming/motion/motion_cb_picshot %f
on_motion_detected /daten/alarming/motion/motion_cb_detect
stream_localhost off
stream_port 8081
 
/trunk/Server/motion/detect.d/client_alert
0,0 → 1,48
#!/usr/bin/php
<?php
 
# --- PLEASE MODIFY:
 
# To which daemon server should the alarm be sent?
$url = "http://127.0.0.1:8085";
 
# Which targets should be reported?
$targets = array(
"1.3.6.1.4.1.37476.2.4.2.0", // Any
"1.3.6.1.4.1.37476.2.4.2.1002", // Motion, camera
"1.3.6.1.4.1.37476.1.2.1.1" // PRIVATE: Webcam of Daniel Marschall
);
 
# --- DON'T MODIFY AFTER THIS LINE
 
$fields = array();
$fields[] = "action=server_alert"; // 1.3.6.1.4.1.37476.2.4.1.2
foreach ($targets as $target) {
// Note: We are not using http_build_query(), because it sends targets[0]=...&targets[1]=...,
// which is not what we need. We want targets=...&targets=...
$fields[] = "targets=".urlencode($target);
}
$fields_string = implode('&', $fields);
 
echo urldecode($fields_string)."\n";
 
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 
$result = curl_exec($ch);
 
echo $result;
 
// Note: We are not using Python to send the alert, because the "import" command is extremely
// slow, and we need to send an alarm withhin milliseconds!
/*
import requests
d = {"action": "server_alert", "targets": [
"...",
"..."
]}
requests.post("http://127.0.0.1:8085", data=d)
*/
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/Server/motion/detect.d
Property changes:
Added: svn:ignore
+stop_spotify
/trunk/Server/motion/motion_cb_detect
0,0 → 1,16
#!/bin/bash
 
DIR=$( dirname "$0" )
 
# Only report every 30 seconds
DETFIL="/tmp/last_motion_detect.ts"
if [ -f "$DETFIL" ]; then
if test "`find "$DETFIL" -mmin -0,5`"; then
# Neuer als 30 Sekunden. Nix machen
exit
fi
fi
touch "$DETFIL"
 
# Execute detect.d/*
for i in "$DIR"/detect.d/*; do ( "$i" &) ; done
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/Server/motion/motion_cb_picshot
0,0 → 1,3
#!/bin/bash
 
rm "$1"
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/Server/motion/motion_start_safe
0,0 → 1,15
#!/usr/bin/php
<?php
 
// Der folgende Code resetted das USB-Gerät, da sonst bei einem Neustart von Motion der Fehler "Cannot open video device" kommen kann
// https://gist.github.com/x2q/5124616
// https://www.raspberrypi.org/forums/viewtopic.php?t=86265https://www.raspberrypi.org/forums/viewtopic.php?t=86265
$out = array();
exec("lsusb", $out, $ec);
$cont = implode("\n", $out);
if (preg_match("@Bus (.{3}) Device (.{3}): ID (.{4}):(.{4}) Logitech, Inc. Webcam C270@ismU", $cont, $m)) {
system(escapeshellcmd(__DIR__.'/usbreset').' '.escapeshellarg("/dev/bus/usb/".$m[1]."/".$m[2]));
}
 
system("service motion start");
 
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/Server/motion/motion_stop_safe
0,0 → 1,5
#!/usr/bin/php
<?php
 
system("service motion stop");
 
Property changes:
Added: svn:executable
+*
\ No newline at end of property
/trunk/Server/motion/usbreset
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Property changes:
Added: svn:executable
+*
\ No newline at end of property
Added: svn:mime-type
+application/octet-stream
\ No newline at end of property
/trunk/Server/motion/usbreset.c
0,0 → 1,52
 
// https://gist.github.com/x2q/5124616
// https://www.raspberrypi.org/forums/viewtopic.php?t=86265https://www.raspberrypi.org/forums/viewtopic.php?t=86265
 
/* usbreset -- send a USB port reset to a USB device
*
* Compile using: gcc -o usbreset usbreset.c
*
*
* */
 
 
 
 
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
 
#include <linux/usbdevice_fs.h>
 
 
int main(int argc, char **argv)
{
const char *filename;
int fd;
int rc;
 
if (argc != 2) {
fprintf(stderr, "Usage: usbreset device-filename\n");
return 1;
}
filename = argv[1];
 
fd = open(filename, O_WRONLY);
if (fd < 0) {
perror("Error opening output file");
return 1;
}
 
printf("Resetting USB device %s\n", filename);
rc = ioctl(fd, USBDEVFS_RESET, 0);
if (rc < 0) {
perror("Error in ioctl");
return 1;
}
printf("Reset successful\n");
 
close(fd);
return 0;
}
/trunk/Server
Property changes:
Added: svn:ignore
+*.pyc
+private