From c35a1c1abb596b919edf42b274d94c7831b93b13 Mon Sep 17 00:00:00 2001 From: Florian Date: Sun, 2 Mar 2014 14:22:10 +0300 Subject: added webinterface --- public/.gitignore | 1 + public/README | 46 +++++++ public/cam.html | 32 +++++ public/css/cam.css | 82 ++++++++++++ public/css/print.css | 24 ++++ public/img/arrow.svg | 65 +++++++++ public/img/down.png | Bin 0 -> 983 bytes public/img/left.png | Bin 0 -> 753 bytes public/img/print_button.png | Bin 0 -> 4931 bytes public/img/print_button.svg | 120 +++++++++++++++++ public/img/print_button_highlight.png | Bin 0 -> 5274 bytes public/img/right.png | Bin 0 -> 742 bytes public/img/testbild-1.png | Bin 0 -> 712957 bytes public/img/testbild-2.png | Bin 0 -> 701650 bytes public/img/testbild-3.png | Bin 0 -> 702190 bytes public/img/testbild-4.png | Bin 0 -> 699394 bytes public/img/testbild-4.xcf | Bin 0 -> 939871 bytes public/img/testbild.gif | Bin 0 -> 1097329 bytes public/img/testbild.png | Bin 0 -> 733994 bytes public/img/testbild.xcf | Bin 0 -> 1233876 bytes public/img/up.png | Bin 0 -> 977 bytes public/js/cctv-control.js | 244 ++++++++++++++++++++++++++++++++++ public/js/print.js | 72 ++++++++++ public/print.html | 24 ++++ server.js | 34 ++++- 25 files changed, 738 insertions(+), 6 deletions(-) create mode 100644 public/.gitignore create mode 100644 public/README create mode 100644 public/cam.html create mode 100644 public/css/cam.css create mode 100644 public/css/print.css create mode 100644 public/img/arrow.svg create mode 100644 public/img/down.png create mode 100644 public/img/left.png create mode 100644 public/img/print_button.png create mode 100644 public/img/print_button.svg create mode 100644 public/img/print_button_highlight.png create mode 100644 public/img/right.png create mode 100644 public/img/testbild-1.png create mode 100644 public/img/testbild-2.png create mode 100644 public/img/testbild-3.png create mode 100644 public/img/testbild-4.png create mode 100644 public/img/testbild-4.xcf create mode 100644 public/img/testbild.gif create mode 100644 public/img/testbild.png create mode 100644 public/img/testbild.xcf create mode 100644 public/img/up.png create mode 100644 public/js/cctv-control.js create mode 100644 public/js/print.js create mode 100644 public/print.html diff --git a/public/.gitignore b/public/.gitignore new file mode 100644 index 0000000..1377554 --- /dev/null +++ b/public/.gitignore @@ -0,0 +1 @@ +*.swp diff --git a/public/README b/public/README new file mode 100644 index 0000000..8d39e20 --- /dev/null +++ b/public/README @@ -0,0 +1,46 @@ +This Interface is developed to work with firefox 27.0.1. + +Installation +============ + +1. Download mjpegplexer: + http://git.sublab.org/mjpegplexer/ + +2. Setup mjpegplexer properly. + +3. Copy the contents of cctv-control to the root + of your webserver and set the camera-host-IP + to the server that runs mjpegplexer. + +Omit Printing-Dialogue +====================== + +To make firefox not display the printing dialogue a config +option needs to be added. I recommend to print to a file, +for everything to work as expected. + +1. enter "about:config" and hit enter + +2. create a new boolean (right-click) + with the name "print.always_silent_print" + and set it to "true" + +3. set "print.print_to_file" to "true" + +4. set your preferred filename in + "print.print_to_filename" + +5.(opt) adapt values of footers and headers for your needs + + +Default Values +============== + +print.always_silent_print false +print.print_to_file false + +print.footerleft &PT //Pagenumber +print.footerright &D //Date +print.headerleft &T //? +print.headerright &U //Filename + diff --git a/public/cam.html b/public/cam.html new file mode 100644 index 0000000..3196c52 --- /dev/null +++ b/public/cam.html @@ -0,0 +1,32 @@ + + + + + + + + +
+ +
+
+ +

+

+

Personalkennzeichnung

+
+

Zeitpunkt

+
+

Analyse der Aufnahme

+ +

Bemerkungen zum Untersuchungsverlauf

+ +

Persönliche Bemerkungen

+ +

+   +

+
+ + + diff --git a/public/css/cam.css b/public/css/cam.css new file mode 100644 index 0000000..d1d28f4 --- /dev/null +++ b/public/css/cam.css @@ -0,0 +1,82 @@ +body { + font-family: Helvetica, Verdana, Arial, sans-serif; + background-color: #000; + padding: 0px; + margin: 0px; +} + +.camNumber { + position: fixed; + + left: 20px; + top: -100px; + + background: rgba(0,0,0,0.6); + + width: 100px; + + text-align: center; + + color: rgba(255, 255, 255, 0.7); + font-weight: bold; + font-family: Helvetica, Verdana, Arial, sans-serif; + font-size: 120px; + line-height: 120px; + + z-index: 100; + } + +#camImage { + min-height: 100%; + min-width: 1024px; + + width: 100%; + height: auto; + + position: fixed; + top: 0; + left: 0; + + margin: 0; + padding: 0; + + z-index: 50; +} + +#form { + /*visibility: hidden;*/ + width: 800px; + height: 100%; + background-color: rgba(127, 192, 255, 0.9); + margin: 0 auto; + position: relative; + top: 0px; + + padding: 40px; + + z-index: 200; +} + +#formImage { + margin-right: 0px; + margin-left: auto; + float: right; + position: relative; + width: 400px; + +} + +#printButton { + width: 200px; + height: 100px; + display: block; + margin: 10px auto; + background-image: url('../img/print_button.png'); + text-decoration: none; +} + +#printButton:hover { + background-image: url('../img/print_button_highlight.png'); + +} + diff --git a/public/css/print.css b/public/css/print.css new file mode 100644 index 0000000..e71a0ae --- /dev/null +++ b/public/css/print.css @@ -0,0 +1,24 @@ +#page { + width: 800px; + + +} + +#camImage { + position: absolute; + top: 0px; + left: 0px; +} + +#metaContainer { + position: absolute; + top: 0px; + left: 700px; +} + +#textContainer { + position: absolute; + top: 500px; + left: 0px; + +} diff --git a/public/img/arrow.svg b/public/img/arrow.svg new file mode 100644 index 0000000..02a1b18 --- /dev/null +++ b/public/img/arrow.svg @@ -0,0 +1,65 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/public/img/down.png b/public/img/down.png new file mode 100644 index 0000000..e7cad41 Binary files /dev/null and b/public/img/down.png differ diff --git a/public/img/left.png b/public/img/left.png new file mode 100644 index 0000000..058e0d5 Binary files /dev/null and b/public/img/left.png differ diff --git a/public/img/print_button.png b/public/img/print_button.png new file mode 100644 index 0000000..1275207 Binary files /dev/null and b/public/img/print_button.png differ diff --git a/public/img/print_button.svg b/public/img/print_button.svg new file mode 100644 index 0000000..aee2cd0 --- /dev/null +++ b/public/img/print_button.svg @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + Drucken + + diff --git a/public/img/print_button_highlight.png b/public/img/print_button_highlight.png new file mode 100644 index 0000000..1cb7df5 Binary files /dev/null and b/public/img/print_button_highlight.png differ diff --git a/public/img/right.png b/public/img/right.png new file mode 100644 index 0000000..415fb5d Binary files /dev/null and b/public/img/right.png differ diff --git a/public/img/testbild-1.png b/public/img/testbild-1.png new file mode 100644 index 0000000..cae27b6 Binary files /dev/null and b/public/img/testbild-1.png differ diff --git a/public/img/testbild-2.png b/public/img/testbild-2.png new file mode 100644 index 0000000..804ca63 Binary files /dev/null and b/public/img/testbild-2.png differ diff --git a/public/img/testbild-3.png b/public/img/testbild-3.png new file mode 100644 index 0000000..cc0f3b3 Binary files /dev/null and b/public/img/testbild-3.png differ diff --git a/public/img/testbild-4.png b/public/img/testbild-4.png new file mode 100644 index 0000000..1b73190 Binary files /dev/null and b/public/img/testbild-4.png differ diff --git a/public/img/testbild-4.xcf b/public/img/testbild-4.xcf new file mode 100644 index 0000000..c844b06 Binary files /dev/null and b/public/img/testbild-4.xcf differ diff --git a/public/img/testbild.gif b/public/img/testbild.gif new file mode 100644 index 0000000..19ea023 Binary files /dev/null and b/public/img/testbild.gif differ diff --git a/public/img/testbild.png b/public/img/testbild.png new file mode 100644 index 0000000..82b1339 Binary files /dev/null and b/public/img/testbild.png differ diff --git a/public/img/testbild.xcf b/public/img/testbild.xcf new file mode 100644 index 0000000..e23beed Binary files /dev/null and b/public/img/testbild.xcf differ diff --git a/public/img/up.png b/public/img/up.png new file mode 100644 index 0000000..ed95bbd Binary files /dev/null and b/public/img/up.png differ diff --git a/public/js/cctv-control.js b/public/js/cctv-control.js new file mode 100644 index 0000000..70c68e9 --- /dev/null +++ b/public/js/cctv-control.js @@ -0,0 +1,244 @@ +// CCTV Control +// +// Author: Florian Raemisch +// Email: olf@subsignal.org +// +// cctv-control is a webinterface to control and view +// mjpeg encoded videos by cctv cameras which are +// proxied by mjpegplexer. camera control is possible +// with arrow-keys, if mjpegplexer is configured +// properly. +// +// This Software is licensed under the GPL Version 3, 29 June 2007 + +var cam = 0; +var camHost = "127.0.0.1:8080"; +var controlHost = "127.0.0.1:8080"; +var formActive = 0; //crazy errors if boolean is used here... + +//create event which is triggered when DOM is ready +window.onDomReady = initReady; + +//change from testbild to default cam when DOM is ready +window.onDomReady(initViewer); + + +function initReady(fn) { + if(document.addEventListener) { + document.addEventListener("DOMContentLoaded", fn, false); + } +} + +//hide the form, and switch on camera +function initViewer() { + var display = document.getElementById('screen'); + var tempCam = parseInt(localStorage.getItem('cam')); + + formActive = localStorage.getItem("formActive"); + if (tempCam <= 7 && tempCam >= 0) { + cam = tempCam; + } + + //if form was displayed, when page was reloaded, display form + if (formActive == 1) { + displayCamNumber(); + display.innerHTML += ''; + showForm(); + } + else { + formActive == 0; + document.getElementById('form').style.visibility = "hidden"; + changeCam(); + } +} + +function displayCamNumber() { + var display = document.getElementById('screen'); + camDisplay = cam + 1; + display.innerHTML = '

' + camDisplay + '

'; +} + +//change currently displayed camera to the one in cam variable +function changeCam() { + + var display = document.getElementById('screen'); + if (cam <= 7 && cam >= 0) { + displayCamNumber(); + display.innerHTML += ''; + localStorage.setItem("cam", cam); + } + else { + display.innerHTML = ''; + } +} + +//send control command to currently selected camera +function controlCam(direction) { + if (direction == "left" || direction == "right" || direction == "up" || direction == "down") { + var request = new XMLHttpRequest(); + request.open("get", "http://" + controlHost + "/cam/" + cam + "/control/" + direction, false); + request.send(); + return false; + } +} + +//save current screenshot in local storage +function saveImage() { + + var storageFiles = {}, //local storage object + xhr = new XMLHttpRequest(), + blob, + fileReader = new FileReader(), + snapShot = new Image(), //dummy-object to display snapshot + imgCanvas = document.createElement("canvas"), + imgContext = imgCanvas.getContext("2d"); + + + //xhr.open("GET", 'img/testbild-' + camDisplay + '.png', true); + xhr.open("GET", 'http://' + camHost + '/cam/' + cam + '/snapshot.jpg', true); + xhr.responseType = "arraybuffer"; + + xhr.addEventListener("load", function () { + if (xhr.status === 200) { + + blob = new Blob([xhr.response], {type: "image/jpg"}); + + + fileReader.onload = function (evt) { + var result = evt.target.result; + + snapShot.src = result; + + try { + localStorage.setItem("snapShot", result); + } + catch (e) { + console.log("Storage failed: " + e); + } + }; + + fileReader.readAsDataURL(blob); + + fileReader.onloadend = function() { + showForm(); + } + } + }, false); + + xhr.send(); +} + +function showForm() { + + //load snapshot from localstorage + var display1 = document.getElementById("camImage"), + display2 = document.getElementById("formImage"), + stor = localStorage.getItem("snapShot"); + + var d = new Date(); + + var date = d.getDay(); + date += '/'; + date += d.getMonth(); + date += '/'; + date += d.getFullYear(); + + var time = d.getHours(); + time += ':'; + time += d.getMinutes(); + time += ':'; + time += d.getSeconds(); + time += ' Uhr'; + + //display loaded image + if (stor) { + display1.setAttribute("src", stor); + display2.setAttribute("src", stor); + } + + //insert date in date-field + document.getElementById("formDate").value = date + ' ' + time; + + //make form visible + document.getElementById("form").style.visibility = 'visible'; + formActive = 1; + localStorage.setItem("formActive", formActive); +} + + +function hideForm() { + + //save form data in local storage for later use + localStorage.setItem("formName", document.getElementById('formName').value); + localStorage.setItem("formDate", document.getElementById('formDate').value); + localStorage.setItem("formAnalysis1", document.getElementById('formAnalysis1').value); + localStorage.setItem("formAnalysis2", document.getElementById('formAnalysis2').value); + localStorage.setItem("formAnalysis3", document.getElementById('formAnalysis3').value); + + //hide form and unfocus button + //otherwise next enter press will trigger print-function + document.getElementById('printButton').blur(); + window.open('print.html', 'Printlayout'); + document.getElementById("form").style.visibility = 'hidden'; + formActive = 0; + localStorage.setItem("formActive", formActive); + changeCam(); +} + + +function keyDown(event) { + + // chaning the camera is only possible if the form is not displayed + if (formActive != 1) { + //numpad has different keycodes! + switch(event.keyCode) { + case 49: // 1 + cam = 0; + changeCam(); + break; + case 50: // 2 + cam = 1; + changeCam(); + break; + case 51: // 3 + cam = 2; + changeCam(); + break; + case 52: // 4 + cam = 3; + changeCam(); + break; + case 53: // 5 + cam = 4; + changeCam(); + break; + case 54: // 6 + cam = 5; + changeCam(); + break; + case 55: // 7 + cam = 6; + changeCam(); + break; + case 56: // 8 + cam = 7; + changeCam(); + break; + case 37: // arrow left + controlCam("left"); + break; + case 38: // arrow up + controlCam("up"); + break; + case 39: // arrow right + controlCam("right"); + break; + case 40: // arrow down + controlCam("down"); + break; + case 13: //enter + saveImage(); + break; + } + } +} diff --git a/public/js/print.js b/public/js/print.js new file mode 100644 index 0000000..7375047 --- /dev/null +++ b/public/js/print.js @@ -0,0 +1,72 @@ +// CCTV Control +// +// Author: Florian Raemisch +// Email: olf@subsignal.org +// +// cctv-control is a webinterface to control and view +// mjpeg encoded videos by cctv cameras which are +// proxied by mjpegplexer. camera control is possible +// with arrow-keys, if mjpegplexer is configured +// properly. +// +// This Software is licensed under the GPL Version 3, 29 June 2007 + +var popen = '

', + pclose = '

'; + +//create event which is triggered when DOM is ready +window.onDomReady = initReady; + +//change from testbild to default cam when DOM is ready +window.onDomReady(initViewer); + + +function initReady(fn) { + if(document.addEventListener) { + document.addEventListener("DOMContentLoaded", fn, false); + } +} + +function initViewer() { + + //load contents from localStorage + var display = document.getElementById("camImage"), + meta = document.getElementById("metaContainer"), + text = document.getElementById("textContainer"), + formName = localStorage.getItem("formName"), + formDate = localStorage.getItem("formDate"), + formAnalysis1 = localStorage.getItem("formAnalysis1"), + formAnalysis2 = localStorage.getItem("formAnalysis2"), + formAnalysis3 = localStorage.getItem("formAnalysis3"), + camera = localStorage.getItem("cam"); + stor = localStorage.getItem("snapShot"); + + //cameraname is cameraID + 1 + camera = parseInt(camera) + 1; + + //display loaded data + if (stor) { + display.setAttribute("src", stor); + meta.innerHTML += popen + formName + pclose; + meta.innerHTML += popen + formDate + pclose; + meta.innerHTML += popen + 'Kamera ' + camera + pclose; + text.innerHTML += popen + formAnalysis1 + pclose; + text.innerHTML += popen + formAnalysis2 + pclose; + text.innerHTML += popen + formAnalysis3 + pclose; + } + + //commented out for debugging and layouting purposes + print(); + + //reset localStorage to default values + //localStorage.setItem("formName", "Untersucher"); + //localStorage.setItem("formDate", "Datum"); + //localStorage.setItem("formAnalysis1", "Dein Bericht 1"); + //localStorage.setItem("formAnalysis2", "Dein Bericht 2"); + //localStorage.setItem("formAnalysis3", "Dein Bericht 3"): + + //commented out for debugging and layouting purposes + window.close(); + +} + diff --git a/public/print.html b/public/print.html new file mode 100644 index 0000000..daaa37e --- /dev/null +++ b/public/print.html @@ -0,0 +1,24 @@ + + + + + + + + + +
+
+ +
+
+ +
+
+ +
+
+ + + + diff --git a/server.js b/server.js index 81ef373..cdcee8d 100644 --- a/server.js +++ b/server.js @@ -11,16 +11,36 @@ var app = express(); var cameras = [ { - baseurl: 'http://admin:123456@192.168.1.10', - model: 'conceptronic' + baseurl: 'http://192.168.1.20:8080/cam/0', + model: 'mjpegplexer' }, { - baseurl: 'http://admin:123456@192.168.1.11', - model: 'conceptronic' + baseurl: 'http://192.168.1.20:8080/cam/1', + model: 'mjpegplexer' }, { - baseurl: 'http://admin:123456@192.168.1.12', - model: 'conceptronic' + baseurl: 'http://192.168.1.20:8080/cam/2', + model: 'mjpegplexer' + }, + { + baseurl: 'http://192.168.1.20:8080/cam/3', + model: 'mjpegplexer' + }, + { + baseurl: 'http://192.168.1.20:8080/cam/4', + model: 'mjpegplexer' + }, + { + baseurl: 'http://192.168.1.20:8080/cam/5', + model: 'mjpegplexer' + }, + { + baseurl: 'http://192.168.1.20:8080/cam/6', + model: 'mjpegplexer' + }, + { + baseurl: 'http://192.168.1.20:8080/cam/7', + model: 'mjpegplexer' } ]; @@ -97,6 +117,8 @@ for (var camera_idx in cameras) { app.use('/cam/' + camera_idx + '/browse', express.static(__dirname + '/cam_public')); } + app.use('/interface', + express.static(__dirname + '/public')); app.get('/blackout', function(req, res) { for (var camera_idx in cameras) { -- cgit v1.2.1