├── README.md ├── UI ├── README.md ├── config.json ├── data.json ├── http.js ├── internal.js ├── package.json ├── public │ ├── css │ │ ├── Rickshaw │ │ │ ├── detail.css │ │ │ ├── extensions.css │ │ │ ├── graph.css │ │ │ ├── legend.css │ │ │ └── slider.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ ├── candump.css │ │ ├── custom-theme │ │ │ ├── images │ │ │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ │ │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ │ │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ │ │ ├── ui-bg_glass_75_dadada_1x400.png │ │ │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ │ │ │ ├── ui-bg_glass_75_ffffff_1x400.png │ │ │ │ ├── ui-bg_highlight-soft_75_cccccc_1x100.png │ │ │ │ ├── ui-bg_inset-soft_95_fef1ec_1x100.png │ │ │ │ ├── ui-icons_222222_256x240.png │ │ │ │ ├── ui-icons_2e83ff_256x240.png │ │ │ │ ├── ui-icons_454545_256x240.png │ │ │ │ ├── ui-icons_888888_256x240.png │ │ │ │ ├── ui-icons_cd0a0a_256x240.png │ │ │ │ └── ui-icons_f6cf3b_256x240.png │ │ │ └── jquery-ui-1.10.2.custom.css │ │ ├── images │ │ │ ├── ajax-loader.gif │ │ │ ├── icons-18-black.png │ │ │ ├── icons-18-white.png │ │ │ ├── icons-36-black.png │ │ │ └── icons-36-white.png │ │ ├── jquery-ui.min.css │ │ ├── jquery.mobile.min.css │ │ ├── jquery.mobile.structure.min.css │ │ ├── jquery.mobile.theme.min.css │ │ ├── leaflet.css │ │ ├── rickshaw.min.css │ │ └── slider.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ ├── formelzeichen.png │ ├── js │ │ ├── bootstrap-slider.js │ │ ├── bootstrap.min.js │ │ ├── d3.min.js │ │ ├── desktop.js │ │ ├── images │ │ │ ├── layers-2x.png │ │ │ ├── layers.png │ │ │ ├── marker-icon-2x.png │ │ │ ├── marker-icon.png │ │ │ └── marker-shadow.png │ │ ├── jquery-ui.min.js │ │ ├── jquery.min.js │ │ ├── leaflet.js │ │ └── rickshaw.min.js │ └── windpower.png ├── server.js └── views │ ├── index-de.html │ └── index-en.html ├── WS100_schematics.png └── server ├── README.md └── windsensorserver.py /README.md: -------------------------------------------------------------------------------- 1 | NodeJS Windsensor 2 | ======== 3 | NodeJs webserver to display histograms, statistics and realtime wind data. 4 | 5 | Python script to collect and send realtime winddata over TCP/IP. 6 | 7 | UI: 8 | ------------- 9 | this folder contains the nodejs files. It runs a webserver, handles websockets for realtime data transmission, creates a database and acts as TCP/IP client to receive data from the python script. 10 | 11 | server: 12 | ------------------- 13 | this folder contains the python files. It samples the frequency on RaspberryPI pin3 and converts it to the actual windspeed. This script runs a TCP/IP server on port 2400. Every connected TCP/IP client receives the current wind speed once a second. 14 | 15 | license: 16 | ---------------- 17 | All serverside code is GNU General Public License v3. 18 | I'm using lot's of Javascript libraries that have it's own licenses (most MIT). 19 | * http://getbootstrap.com/getting-started/ 20 | * http://d3js.org/ 21 | * http://code.shutterstock.com/rickshaw/ 22 | * http://jquery.com/ 23 | -------------------------------------------------------------------------------- /UI/README.md: -------------------------------------------------------------------------------- 1 | NodeJS Windsensor 2 | ======== 3 | NodeJs webserver to display histograms, statistics and realtime wind data. 4 | 5 | required nodejs modules: 6 | -------------- 7 | * express 8 | * recon 9 | * socket.io 10 | 11 | run "npm install" to install all modules. 12 | 13 | run "npm start" to launch the application. 14 | 15 | nodejs configuration: 16 | ------------- 17 | file **config.json**: 18 | 19 | ``` 20 | { 21 | "windserver": { 22 | "port": 2400, 23 | "hostname": "127.0.0.1" 24 | }, 25 | "httpserver": { 26 | "port": 4800 27 | }, 28 | "datafilename": "data.json" 29 | } 30 | ``` 31 | 32 | this will configure the HTTP server to listen on port 4800, and tell the TCP client to connect to host 127.0.0.1 on port 2400. 33 | This programm assumes the windsensorserver.py script running on localhost port 2400 transmitting the current wind speed. 34 | It uses the file 'data.json' as database. The database is written on exit and every 5 minutes to conserve the raspberries flash. 35 | All graphs are generated by rickshaw. The data is transmitted in realtime using websockets. 36 | 37 | run: 38 | ---------------- 39 | 'node server.js' or 'npm start' 40 | 41 | license: 42 | ---------------- 43 | All serverside code is GNU General Public License v3. 44 | 45 | I'm using lot's of Javascript libraries that have it's own licenses (most MIT). 46 | * http://getbootstrap.com/getting-started/ 47 | * http://d3js.org/ 48 | * http://code.shutterstock.com/rickshaw/ 49 | * http://jquery.com/ 50 | -------------------------------------------------------------------------------- /UI/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "windserver": { 3 | "port": 2400, 4 | "hostname": "127.0.0.1" 5 | }, 6 | "httpserver": { 7 | "port": 4800 8 | }, 9 | "datafilename": "data.json" 10 | } 11 | -------------------------------------------------------------------------------- /UI/http.js: -------------------------------------------------------------------------------- 1 | // nodejs webserver 2 | // Copyright (C) 2014 Patrick Rudolph 3 | 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | var fs = require('fs'); 18 | var express = require('express'); 19 | var app = express(), //for socket.io 20 | http = require('http'), 21 | server = http.createServer(app); 22 | var configuration = require('./config.json'); 23 | 24 | app.use(express.static(__dirname + '/public')); 25 | 26 | app.locals.pretty = true; 27 | 28 | app.get('/', function(req, res) { 29 | if(req.headers["accept-language"].indexOf("de") > -1 ){ 30 | res.send(fs.readFileSync('./views/index-de.html', 'utf8')); 31 | } 32 | else 33 | { 34 | res.send(fs.readFileSync('./views/index-en.html', 'utf8')); 35 | } 36 | }); 37 | 38 | server.listen(configuration.httpserver.port); 39 | var io = require('socket.io').listen(server); 40 | 41 | exports.io = io; 42 | -------------------------------------------------------------------------------- /UI/internal.js: -------------------------------------------------------------------------------- 1 | // nodejs webserver and datalogger 2 | // Copyright (C) 2014 Patrick Rudolph 3 | 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | var fs = require('fs'); 18 | 19 | var monthNames = [ "January", "February", "March", "April", "May", "June", 20 | "July", "August", "September", "October", "November", "December" ]; 21 | 22 | var toYDHMS = function(seconds){ 23 | var year = parseInt(seconds/(60*60*24*365)); 24 | seconds -= year * (60*60*24*365); 25 | var days = parseInt(seconds/(60*60*24)); 26 | seconds -= days * (60*60*24); 27 | var hours = parseInt(seconds/(60*60)); 28 | seconds -= hours * (60*60); 29 | var minutes = parseInt(seconds/60); 30 | seconds -= minutes * 60; 31 | return year.toString() + "y " + days.toString() + "d " + hours.toString() + "h " + minutes.toString() + "m " + seconds.toString() + "s "; 32 | } 33 | 34 | var get_seconds_sum = function(val){ 35 | if(typeof val == "undefined") 36 | { 37 | return 0; 38 | } 39 | var total = 0; 40 | for(var i in val) 41 | { 42 | total += val[i]; 43 | } 44 | return total; 45 | }; 46 | 47 | 48 | var get_max_val = function(val) { 49 | var maxval = 0; 50 | for(var i in val) 51 | { 52 | if(!parseFloat(i).isNaN && parseFloat(i) > maxval) 53 | { 54 | maxval = parseFloat(i); 55 | } 56 | } 57 | if(maxval > 50) 58 | maxval = 50; 59 | return maxval; 60 | }; 61 | 62 | var get_average_speed = function(val){ 63 | if(typeof val == "undefined") 64 | { 65 | return 0; 66 | } 67 | var sum = 0; 68 | var count = 0; 69 | for(var i in val) 70 | { 71 | sum += parseFloat(i)*parseFloat(val[i]); 72 | count += parseFloat(val[i]); 73 | } 74 | if(count > 0){ 75 | return sum/count; 76 | } 77 | else 78 | { 79 | return 0; 80 | } 81 | } 82 | 83 | var get_power_val = function(val){ 84 | if(typeof val == "undefined") 85 | { 86 | return 0; 87 | } 88 | var sum = 0; 89 | for(var i in val) 90 | { 91 | sum += parseFloat(i)*parseFloat(i)*parseFloat(i)*val[i]; 92 | } 93 | return 0.350814814815 * sum/(1000.0*60.0*60.0); //kW/h 94 | } 95 | 96 | var get_max_speed = function(val){ 97 | if(typeof val == "undefined") 98 | { 99 | return 0; 100 | } 101 | var total = 0; 102 | for(var i in val) 103 | { 104 | if(i != 0){ 105 | total += parseFloat(val[i]); 106 | } 107 | } 108 | var sum = 0; 109 | for(i=0.5;i total*0.95) 116 | return i; 117 | } 118 | return 0; 119 | } 120 | 121 | var get_min_speed = function(val){ 122 | if(typeof val == "undefined") 123 | { 124 | return 0; 125 | } 126 | var total = 0; 127 | for(var i in val) 128 | { 129 | if(i != 0){ 130 | total += val[i]; 131 | } 132 | } 133 | var sum = 0; 134 | for(i=0.5;i total*0.05) 140 | return i; 141 | } 142 | return 0; 143 | } 144 | 145 | var get_seconds_over_4msec = function(val){ 146 | if(typeof val == "undefined") 147 | { 148 | return 0; 149 | } 150 | var sum = 0; 151 | for(var i in val) 152 | { 153 | if(parseFloat(i) > 4){ 154 | sum += val[i]; 155 | } 156 | } 157 | return sum; 158 | }; 159 | 160 | var get_min_max_area = function(val){ 161 | var hist_area_data = {}; 162 | var hist_area_max_val = 0; 163 | for(var i in val) 164 | { 165 | if(i != 0){ 166 | if(parseFloat(val[i])>hist_area_max_val){ 167 | hist_area_max_val = parseFloat(val[i]); 168 | } 169 | } 170 | } 171 | hist_area_data[get_min_speed(val)-0.001] = 0; 172 | hist_area_data[get_max_speed(val)+0.001] = 0; 173 | for(var j=get_min_speed(val);j 100) 254 | return; 255 | if(typeof data[now_year][now_month][now_day][idx] == "undefined") 256 | { 257 | data[now_year][now_month][now_day][idx] = 0; 258 | } 259 | if(typeof data[now_year]["total"][idx] == "undefined") 260 | { 261 | data[now_year]["total"][idx] = 0; 262 | } 263 | if(typeof data[now_year][now_month]["total"][idx] == "undefined") 264 | { 265 | data[now_year][now_month]["total"][idx] = 0; 266 | } 267 | data[now_year]["total"][idx] += 1; 268 | data[now_year][now_month]["total"][idx] += 1; 269 | data[now_year][now_month][now_day][idx] += 1; 270 | } 271 | 272 | exports.get_seconds_sum = get_seconds_sum; 273 | exports.get_max_val = get_max_val; 274 | exports.get_average_speed = get_average_speed; 275 | exports.get_power_val = get_power_val; 276 | exports.get_max_speed = get_max_speed; 277 | exports.get_seconds_over_4msec = get_seconds_over_4msec; 278 | exports.get_min_max_area = get_min_max_area; 279 | exports.get_min_speed = get_min_speed; 280 | exports.read_data = read_data; 281 | exports.data = data; 282 | exports.update_histogram = update_histogram; 283 | exports.toYDHMS = toYDHMS; 284 | -------------------------------------------------------------------------------- /UI/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "windsensor-ui", 3 | "version": "0.0.1", 4 | "private": true, 5 | "description": "interactive http server for wind histogramms and realtime graphs", 6 | "author": "Patrick Rudolph", 7 | "scripts": { 8 | "start": "node server.js" 9 | }, 10 | "dependencies": { 11 | "express": "~4.0.0", 12 | "recon": "~0.0.8", 13 | "socket.io": "~1.1.0" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /UI/public/css/Rickshaw/detail.css: -------------------------------------------------------------------------------- 1 | .rickshaw_graph .detail { 2 | pointer-events: none; 3 | position: absolute; 4 | top: 0; 5 | z-index: 2; 6 | background: rgba(0, 0, 0, 0.1); 7 | bottom: 0; 8 | width: 1px; 9 | transition: opacity 0.25s linear; 10 | -moz-transition: opacity 0.25s linear; 11 | -o-transition: opacity 0.25s linear; 12 | -webkit-transition: opacity 0.25s linear; 13 | } 14 | .rickshaw_graph .detail.inactive { 15 | opacity: 0; 16 | } 17 | .rickshaw_graph .detail .item.active { 18 | opacity: 1; 19 | } 20 | .rickshaw_graph .detail .x_label { 21 | font-family: Arial, sans-serif; 22 | border-radius: 3px; 23 | padding: 6px; 24 | opacity: 0.5; 25 | border: 1px solid #e0e0e0; 26 | font-size: 12px; 27 | position: absolute; 28 | background: white; 29 | white-space: nowrap; 30 | } 31 | .rickshaw_graph .detail .x_label.left { 32 | left: 0; 33 | } 34 | .rickshaw_graph .detail .x_label.right { 35 | right: 0; 36 | } 37 | .rickshaw_graph .detail .item { 38 | position: absolute; 39 | z-index: 2; 40 | border-radius: 3px; 41 | padding: 0.25em; 42 | font-size: 12px; 43 | font-family: Arial, sans-serif; 44 | opacity: 0; 45 | background: rgba(0, 0, 0, 0.4); 46 | color: white; 47 | border: 1px solid rgba(0, 0, 0, 0.4); 48 | margin-left: 1em; 49 | margin-right: 1em; 50 | margin-top: -1em; 51 | white-space: nowrap; 52 | } 53 | .rickshaw_graph .detail .item.left { 54 | left: 0; 55 | } 56 | .rickshaw_graph .detail .item.right { 57 | right: 0; 58 | } 59 | .rickshaw_graph .detail .item.active { 60 | opacity: 1; 61 | background: rgba(0, 0, 0, 0.8); 62 | } 63 | .rickshaw_graph .detail .item:after { 64 | position: absolute; 65 | display: block; 66 | width: 0; 67 | height: 0; 68 | 69 | content: ""; 70 | 71 | border: 5px solid transparent; 72 | } 73 | .rickshaw_graph .detail .item.left:after { 74 | top: 1em; 75 | left: -5px; 76 | margin-top: -5px; 77 | border-right-color: rgba(0, 0, 0, 0.8); 78 | border-left-width: 0; 79 | } 80 | .rickshaw_graph .detail .item.right:after { 81 | top: 1em; 82 | right: -5px; 83 | margin-top: -5px; 84 | border-left-color: rgba(0, 0, 0, 0.8); 85 | border-right-width: 0; 86 | } 87 | .rickshaw_graph .detail .dot { 88 | width: 4px; 89 | height: 4px; 90 | margin-left: -2px; 91 | margin-top: -2px; 92 | border-radius: 5px; 93 | position: absolute; 94 | box-shadow: 0 0 2px rgba(0, 0, 0, 0.6); 95 | background: white; 96 | border-width: 2px; 97 | border-style: solid; 98 | display: none; 99 | background-clip: padding-box; 100 | } 101 | .rickshaw_graph .detail .dot.active { 102 | display: block; 103 | } 104 | -------------------------------------------------------------------------------- /UI/public/css/Rickshaw/extensions.css: -------------------------------------------------------------------------------- 1 | div, span, p, td { 2 | font-family: Arial, sans-serif; 3 | } 4 | #content { 5 | width: 1200px; 6 | } 7 | #chart { 8 | display: inline-block; 9 | } 10 | #chart path { 11 | -webkit-transition: opacity 0.2s linear; 12 | } 13 | #preview { 14 | margin-top: 10px; 15 | } 16 | #legend { 17 | display: inline-block; 18 | position: relative; 19 | left: 8px; 20 | } 21 | #legend_container { 22 | position: absolute; 23 | right: 0; 24 | bottom: 26px; 25 | width: 0; 26 | } 27 | #chart_container { 28 | position: relative; 29 | display: inline-block; 30 | } 31 | #smoother { 32 | margin: 0 0 10px 16px; 33 | width: 100px; 34 | } 35 | .rickshaw_graph .detail { 36 | left: -1000; 37 | } 38 | #chart { 39 | border: 1px solid #f0f0f0; 40 | } 41 | #side_panel { 42 | padding: 0 20px 20px 0; 43 | width: 240px; 44 | display: inline-block; 45 | vertical-align: top; 46 | } 47 | #side_panel section { 48 | color: #505050; 49 | font-size: 12px; 50 | } 51 | #side_panel section h6 { 52 | margin: 0 0 1em 0; 53 | font-size: 12px; 54 | font-weight: normal; 55 | } 56 | #side_panel .ui-slider-horizontal { 57 | height: 1px !important; 58 | border-color: #e0e0e0; 59 | margin-bottom: 10px; 60 | } 61 | #side_panel .ui-slider-handle { 62 | border-color: #a0a0a0; 63 | height: 9px !important; 64 | width: 9px !important; 65 | top: -5px !important; 66 | border-radius: 6px; 67 | outline: none; 68 | cursor: pointer; 69 | } 70 | #legend { 71 | background-color: white; 72 | margin-left: 0; 73 | padding: 0; 74 | left: 0; 75 | } 76 | #legend .label { 77 | color: #404040; 78 | } 79 | #legend .action { 80 | color: black; 81 | opacity: 0.5; 82 | } 83 | #legend ul { 84 | padding: 0; 85 | } 86 | h1 { 87 | font-family: Franklin Gothic Medium, UnDotum, Helvetica, Arial; 88 | font-weight: normal; 89 | font-size: 20px; 90 | } 91 | section { 92 | border: none; 93 | border-top: 1px solid #eaeaea; 94 | padding: 15px 0; 95 | } 96 | #smoother { 97 | margin: 5px 0 0 10px; 98 | width: 90%; 99 | } 100 | label.disabled { 101 | opacity: 0.4; 102 | } 103 | #renderer_form.toggler { 104 | display: block; 105 | margin: 0; 106 | } 107 | #renderer_form.toggler input[type=radio]:checked { 108 | outline: 2px solid steelblue; 109 | } 110 | #renderer_form.toggler input[type=radio] { 111 | -moz-appearance: button; 112 | background: white; 113 | margin: 0 7px; 114 | width: 39px; 115 | height: 26px; 116 | position: absolute; 117 | } 118 | #renderer_form.toggler label { 119 | display: inline-block; 120 | padding: 0; 121 | width: 39px; 122 | padding-top: 27px; 123 | text-align: center; 124 | font-size: 10px; 125 | color: #808080; 126 | background-repeat: no-repeat; 127 | position: relative; 128 | margin: 0 7px; 129 | cursor: pointer; 130 | } 131 | #interpolation_form, 132 | #offset_form { 133 | vertical-align: top; 134 | display: inline-block; 135 | width: 45%; 136 | } 137 | #interpolation_form label, 138 | #offset_form label { 139 | display: block; 140 | } 141 | label[for=area] { 142 | background: url(../images/om_stack.png); 143 | } 144 | label[for=line] { 145 | background: url(../images/om_lines.png); 146 | } 147 | label[for=bar] { 148 | background: url(../images/om_bar.png); 149 | } 150 | label[for=scatter] { 151 | background: url(../images/om_scatter.png); 152 | } 153 | #offset_form label, 154 | #interpolation_form label { 155 | background-repeat: no-repeat; 156 | background-position: 2em center; 157 | cursor: pointer; 158 | cursor: hand; 159 | } 160 | #offset_form label span, 161 | #interpolation_form label span { 162 | padding-left: 36px; 163 | } 164 | label[for=stack] { 165 | background-image: url(../images/offset_stack.png); 166 | } 167 | label[for=pct] { 168 | background-image: url(../images/offset_pct.png); 169 | } 170 | label[for=stream] { 171 | background-image: url(../images/offset_stream.png); 172 | } 173 | label[for=value] { 174 | background-image: url(../images/offset_value.png); 175 | } 176 | label[for=cardinal] { 177 | background-image: url(../images/interp_cardinal.png); 178 | } 179 | label[for=linear] { 180 | background-image: url(../images/interp_linear.png); 181 | } 182 | label[for=step] { 183 | background-image: url(../images/interp_step.png); 184 | } 185 | -------------------------------------------------------------------------------- /UI/public/css/Rickshaw/graph.css: -------------------------------------------------------------------------------- 1 | /* graph */ 2 | .graph-container 3 | { 4 | position: relative; 5 | display: inline-block; 6 | font-family: Arial, Helvetica, sans-serif; 7 | margin-top: 10px; 8 | margin-bottom: 20px; 9 | } 10 | .chart { 11 | display: inline-block; 12 | margin-left: 10px; 13 | float:left; 14 | top: 0%; 15 | } 16 | .y_axis { 17 | float: left; 18 | width: 40px; 19 | } 20 | .y_label { 21 | float: left; 22 | width: 20px; 23 | } 24 | 25 | .x_axis { 26 | display: inline-block; 27 | margin-left: 70px; 28 | margin-top: -10px; 29 | opacity: 1 !important; 30 | color: #646464; 31 | } 32 | .x_label { 33 | position: absolute; 34 | right: 10%; 35 | bottom: -20; 36 | } 37 | 38 | .legend { 39 | position: absolute; 40 | right: 0; 41 | top: 0; 42 | } 43 | .rickshaw_graph { 44 | position: relative; 45 | } 46 | .rickshaw_graph svg { 47 | display: block; 48 | } 49 | -------------------------------------------------------------------------------- /UI/public/css/Rickshaw/legend.css: -------------------------------------------------------------------------------- 1 | .rickshaw_legend { 2 | font-family: Arial; 3 | font-size: 12px; 4 | color: white; 5 | background: #404040; 6 | display: inline-block; 7 | padding: 12px 5px; 8 | border-radius: 2px; 9 | position: relative; 10 | } 11 | .rickshaw_legend:hover { 12 | z-index: 10; 13 | } 14 | .rickshaw_legend .swatch { 15 | width: 10px; 16 | height: 10px; 17 | border: 1px solid rgba(0, 0, 0, 0.2); 18 | } 19 | .rickshaw_legend .line { 20 | clear: both; 21 | line-height: 140%; 22 | padding-right: 15px; 23 | } 24 | .rickshaw_legend .line .swatch { 25 | display: inline-block; 26 | margin-right: 3px; 27 | border-radius: 2px; 28 | } 29 | .rickshaw_legend .label { 30 | margin: 0; 31 | white-space: nowrap; 32 | display: inline; 33 | font-size: inherit; 34 | background-color: transparent; 35 | color: inherit; 36 | font-weight: normal; 37 | line-height: normal; 38 | padding: 0px; 39 | text-shadow: none; 40 | } 41 | .rickshaw_legend .action:hover { 42 | opacity: 0.6; 43 | } 44 | .rickshaw_legend .action { 45 | margin-right: 0.2em; 46 | font-size: 10px; 47 | opacity: 0.2; 48 | cursor: pointer; 49 | font-size: 14px; 50 | } 51 | .rickshaw_legend .line.disabled { 52 | opacity: 0.4; 53 | } 54 | .rickshaw_legend ul { 55 | list-style-type: none; 56 | margin: 0; 57 | padding: 0; 58 | margin: 2px; 59 | cursor: pointer; 60 | } 61 | .rickshaw_legend li { 62 | padding: 0 0 0 2px; 63 | min-width: 80px; 64 | white-space: nowrap; 65 | } 66 | .rickshaw_legend li:hover { 67 | background: rgba(255, 255, 255, 0.08); 68 | border-radius: 3px; 69 | } 70 | .rickshaw_legend li:active { 71 | background: rgba(255, 255, 255, 0.2); 72 | border-radius: 3px; 73 | } 74 | -------------------------------------------------------------------------------- /UI/public/css/Rickshaw/slider.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Slider for Bootstrap 3 | * 4 | * Copyright 2012 Stefan Petre 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | */ 9 | .slider { 10 | display: inline-block; 11 | vertical-align: middle; 12 | position: relative; 13 | } 14 | .slider.slider-horizontal { 15 | width: 210px; 16 | height: 20px; 17 | } 18 | .slider.slider-horizontal .slider-track { 19 | height: 10px; 20 | width: 100%; 21 | margin-top: -5px; 22 | top: 50%; 23 | left: 0; 24 | } 25 | .slider.slider-horizontal .slider-selection { 26 | height: 100%; 27 | top: 0; 28 | bottom: 0; 29 | } 30 | .slider.slider-horizontal .slider-handle { 31 | margin-left: -10px; 32 | margin-top: -5px; 33 | } 34 | .slider.slider-horizontal .slider-handle.triangle { 35 | border-width: 0 10px 10px 10px; 36 | width: 0; 37 | height: 0; 38 | border-bottom-color: #0480be; 39 | margin-top: 0; 40 | } 41 | .slider.slider-vertical { 42 | height: 210px; 43 | width: 20px; 44 | } 45 | .slider.slider-vertical .slider-track { 46 | width: 10px; 47 | height: 100%; 48 | margin-left: -5px; 49 | left: 50%; 50 | top: 0; 51 | } 52 | .slider.slider-vertical .slider-selection { 53 | width: 100%; 54 | left: 0; 55 | top: 0; 56 | bottom: 0; 57 | } 58 | .slider.slider-vertical .slider-handle { 59 | margin-left: -5px; 60 | margin-top: -10px; 61 | } 62 | .slider.slider-vertical .slider-handle.triangle { 63 | border-width: 10px 0 10px 10px; 64 | width: 1px; 65 | height: 1px; 66 | border-left-color: #0480be; 67 | margin-left: 0; 68 | } 69 | .slider input { 70 | display: none; 71 | } 72 | .slider .tooltip-inner { 73 | white-space: nowrap; 74 | } 75 | .slider-track { 76 | position: absolute; 77 | cursor: pointer; 78 | background-color: #f7f7f7; 79 | background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); 80 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); 81 | background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); 82 | background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); 83 | background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); 84 | background-repeat: repeat-x; 85 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); 86 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 87 | -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 88 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 89 | -webkit-border-radius: 4px; 90 | -moz-border-radius: 4px; 91 | border-radius: 4px; 92 | } 93 | .slider-selection { 94 | position: absolute; 95 | background-color: #f7f7f7; 96 | background-image: -moz-linear-gradient(top, #f9f9f9, #f5f5f5); 97 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f9f9f9), to(#f5f5f5)); 98 | background-image: -webkit-linear-gradient(top, #f9f9f9, #f5f5f5); 99 | background-image: -o-linear-gradient(top, #f9f9f9, #f5f5f5); 100 | background-image: linear-gradient(to bottom, #f9f9f9, #f5f5f5); 101 | background-repeat: repeat-x; 102 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#fff5f5f5', GradientType=0); 103 | -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); 104 | -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); 105 | box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); 106 | -webkit-box-sizing: border-box; 107 | -moz-box-sizing: border-box; 108 | box-sizing: border-box; 109 | -webkit-border-radius: 4px; 110 | -moz-border-radius: 4px; 111 | border-radius: 4px; 112 | } 113 | .slider-handle { 114 | position: absolute; 115 | width: 20px; 116 | height: 20px; 117 | background-color: #0e90d2; 118 | background-image: -moz-linear-gradient(top, #149bdf, #0480be); 119 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); 120 | background-image: -webkit-linear-gradient(top, #149bdf, #0480be); 121 | background-image: -o-linear-gradient(top, #149bdf, #0480be); 122 | background-image: linear-gradient(to bottom, #149bdf, #0480be); 123 | background-repeat: repeat-x; 124 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); 125 | -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); 126 | -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); 127 | box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); 128 | opacity: 0.8; 129 | border: 0px solid transparent; 130 | } 131 | .slider-handle.round { 132 | -webkit-border-radius: 20px; 133 | -moz-border-radius: 20px; 134 | border-radius: 20px; 135 | } 136 | .slider-handle.triangle { 137 | background: transparent none; 138 | } -------------------------------------------------------------------------------- /UI/public/css/bootstrap-theme.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.1.1 (http://getbootstrap.com) 3 | * Copyright 2011-2014 Twitter, Inc. 4 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 5 | */ 6 | 7 | .btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:active,.btn.active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-color:#357ebd}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} -------------------------------------------------------------------------------- /UI/public/css/candump.css: -------------------------------------------------------------------------------- 1 | table{ 2 | border: 0px solid black; 3 | table-layout: fixed; 4 | width: 440px; 5 | } 6 | 7 | td.rotate{ 8 | -moz-transform: rotate(-90.0deg); /* FF3.5+ */ 9 | -o-transform: rotate(-90.0deg); /* Opera 10.5 */ 10 | -webkit-transform: rotate(-90.0deg); /* Saf3.1+, Chrome */ 11 | /* breaks firefox: filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083); */ /* IE6,IE7 */ 12 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0.083)"; /* IE8 */ 13 | white-space:nowrap; 14 | height:200px; 15 | overflow: visible; 16 | } 17 | -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-bg_flat_0_aaaaaa_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-bg_flat_0_aaaaaa_40x100.png -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-bg_glass_55_fbf9ee_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-bg_glass_55_fbf9ee_1x400.png -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-bg_glass_75_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-bg_glass_75_dadada_1x400.png -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-bg_glass_75_e6e6e6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-bg_glass_75_e6e6e6_1x400.png -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-bg_glass_75_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-bg_glass_75_ffffff_1x400.png -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-bg_highlight-soft_75_cccccc_1x100.png -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-bg_inset-soft_95_fef1ec_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-bg_inset-soft_95_fef1ec_1x100.png -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-icons_454545_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-icons_454545_256x240.png -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-icons_888888_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-icons_888888_256x240.png -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /UI/public/css/custom-theme/images/ui-icons_f6cf3b_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/custom-theme/images/ui-icons_f6cf3b_256x240.png -------------------------------------------------------------------------------- /UI/public/css/images/ajax-loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/images/ajax-loader.gif -------------------------------------------------------------------------------- /UI/public/css/images/icons-18-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/images/icons-18-black.png -------------------------------------------------------------------------------- /UI/public/css/images/icons-18-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/images/icons-18-white.png -------------------------------------------------------------------------------- /UI/public/css/images/icons-36-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/images/icons-36-black.png -------------------------------------------------------------------------------- /UI/public/css/images/icons-36-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/css/images/icons-36-white.png -------------------------------------------------------------------------------- /UI/public/css/jquery-ui.min.css: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.10.4 - 2014-01-17 2 | * http://jqueryui.com 3 | * Includes: jquery.ui.core.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css, jquery.ui.theme.css 4 | * Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */ .ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;min-height:0}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:700;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:0;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:0}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;width:100%;list-style-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;min-height:0;font-weight:400}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:400;margin:-1px}.ui-menu .ui-state-disabled{font-weight:400;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url(images/animated-overlay.gif);height:100%;filter:alpha(opacity=25);opacity:.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted #000}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:0;background:0;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:0;border-bottom:0;border-right:0}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:0}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:700}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:400;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:400;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:400;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:700}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:400}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px} -------------------------------------------------------------------------------- /UI/public/css/jquery.mobile.theme.min.css: -------------------------------------------------------------------------------- 1 | /*! jQuery Mobile 1.4.0 | Git HEAD hash: f09aae0 <> 2013-12-19T17:34:22Z | (c) 2010, 2013 jQuery Foundation, Inc. | jquery.org/license */ 2 | 3 | html{font-size:100%}body,input,select,textarea,button,.ui-btn{font-size:1em;line-height:1.3;font-family:sans-serif}legend,.ui-input-text input,.ui-input-search input{color:inherit;text-shadow:inherit}.ui-mobile label,div.ui-controlgroup-label{font-weight:400;font-size:16px}.ui-field-contain{border-bottom-color:#828282;border-bottom-color:rgba(0,0,0,.15);border-bottom-width:1px;border-bottom-style:solid}.table-stroke thead th,.table-stripe thead th,.table-stripe tbody tr:last-child{border-bottom:1px solid #d6d6d6;border-bottom:1px solid rgba(0,0,0,.1)}.table-stroke tbody th,.table-stroke tbody td{border-bottom:1px solid #e6e6e6;border-bottom:1px solid rgba(0,0,0,.05)}.table-stripe.table-stroke tbody tr:last-child th,.table-stripe.table-stroke tbody tr:last-child td{border-bottom:0}.table-stripe tbody tr:nth-child(odd) td,.table-stripe tbody tr:nth-child(odd) th{background-color:#eee;background-color:rgba(0,0,0,.04)}.ui-btn,label.ui-btn{font-weight:700;border-width:1px;border-style:solid}.ui-btn:link{text-decoration:none!important}.ui-btn-active{cursor:pointer}.ui-corner-all{-webkit-border-radius:.3125em;border-radius:.3125em}.ui-btn-corner-all,.ui-btn.ui-corner-all,.ui-slider-track.ui-corner-all,.ui-flipswitch.ui-corner-all,.ui-li-count{-webkit-border-radius:.3125em;border-radius:.3125em}.ui-btn-icon-notext.ui-btn-corner-all,.ui-btn-icon-notext.ui-corner-all{-webkit-border-radius:1em;border-radius:1em}.ui-btn-corner-all,.ui-corner-all{-webkit-background-clip:padding;background-clip:padding-box}.ui-popup.ui-corner-all>.ui-popup-arrow-guide{left:.6em;right:.6em;top:.6em;bottom:.6em}.ui-shadow{-webkit-box-shadow:0 1px 3px rgba(0,0,0,.15);-moz-box-shadow:0 1px 3px rgba(0,0,0,.15);box-shadow:0 1px 3px rgba(0,0,0,.15)}.ui-shadow-inset{-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.2);-moz-box-shadow:inset 0 1px 3px rgba(0,0,0,.2);box-shadow:inset 0 1px 3px rgba(0,0,0,.2)}.ui-overlay-shadow{-webkit-box-shadow:0 0 12px rgba(0,0,0,.6);-moz-box-shadow:0 0 12px rgba(0,0,0,.6);box-shadow:0 0 12px rgba(0,0,0,.6)}.ui-btn-icon-left:after,.ui-btn-icon-right:after,.ui-btn-icon-top:after,.ui-btn-icon-bottom:after,.ui-btn-icon-notext:after{background-color:#666;background-color:rgba(0,0,0,.3);background-position:center center;background-repeat:no-repeat;-webkit-border-radius:1em;border-radius:1em}.ui-alt-icon.ui-btn:after,.ui-alt-icon .ui-btn:after,html .ui-alt-icon.ui-checkbox-off:after,html .ui-alt-icon.ui-radio-off:after,html .ui-alt-icon .ui-checkbox-off:after,html .ui-alt-icon .ui-radio-off:after{background-color:#666;background-color:rgba(0,0,0,.15)}.ui-nodisc-icon.ui-btn:after,.ui-nodisc-icon .ui-btn:after{background-color:transparent}.ui-shadow-icon.ui-btn:after,.ui-shadow-icon .ui-btn:after{-webkit-box-shadow:0 1px 0 rgba(255,255,255,.3);-moz-box-shadow:0 1px 0 rgba(255,255,255,.3);box-shadow:0 1px 0 rgba(255,255,255,.3)}.ui-btn.ui-checkbox-off:after,.ui-btn.ui-checkbox-on:after,.ui-btn.ui-radio-off:after,.ui-btn.ui-radio-on:after{display:block;width:18px;height:18px;margin:-9px 2px 0 2px}.ui-checkbox-off:after,.ui-btn.ui-radio-off:after{filter:Alpha(Opacity=30);opacity:.3}.ui-btn.ui-checkbox-off:after,.ui-btn.ui-checkbox-on:after{-webkit-border-radius:.1875em;border-radius:.1875em}.ui-radio .ui-btn.ui-radio-on:after{background-image:none;background-color:#fff;width:8px;height:8px;border-width:5px;border-style:solid}.ui-alt-icon.ui-btn.ui-radio-on:after,.ui-alt-icon .ui-btn.ui-radio-on:after{background-color:#000}.ui-icon-loading{background:url(images/ajax-loader.gif);background-size:2.875em 2.875em}.ui-bar-a,.ui-page-theme-a .ui-bar-inherit,html .ui-bar-a .ui-bar-inherit,html .ui-body-a .ui-bar-inherit,html body .ui-group-theme-a .ui-bar-inherit{background:#e9e9e9;border-color:#ddd;color:#333;text-shadow:0 1px 0 #eee;font-weight:700}.ui-bar-a{border-width:1px;border-style:solid}.ui-overlay-a,.ui-page-theme-a,.ui-page-theme-a .ui-panel-wrapper{background:#f9f9f9;border-color:#bbb;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-body-a,.ui-page-theme-a .ui-body-inherit,html .ui-bar-a .ui-body-inherit,html .ui-body-a .ui-body-inherit,html body .ui-group-theme-a .ui-body-inherit,html .ui-panel-page-container-a{background:#fff;border-color:#ddd;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-body-a{border-width:1px;border-style:solid}.ui-page-theme-a a,html .ui-bar-a a,html .ui-body-a a,html body .ui-group-theme-a a{color:#38c;font-weight:700}.ui-page-theme-a a:visited,html .ui-bar-a a:visited,html .ui-body-a a:visited,html body .ui-group-theme-a a:visited{color:#38c}.ui-page-theme-a a:hover,html .ui-bar-a a:hover,html .ui-body-a a:hover,html body .ui-group-theme-a a:hover{color:#059}.ui-page-theme-a a:active,html .ui-bar-a a:active,html .ui-body-a a:active,html body .ui-group-theme-a a:active{color:#059}.ui-page-theme-a .ui-btn,html .ui-bar-a .ui-btn,html .ui-body-a .ui-btn,html body .ui-group-theme-a .ui-btn,html head+body .ui-btn.ui-btn-a,.ui-page-theme-a .ui-btn:visited,html .ui-bar-a .ui-btn:visited,html .ui-body-a .ui-btn:visited,html body .ui-group-theme-a .ui-btn:visited,html head+body .ui-btn.ui-btn-a:visited{background:#f6f6f6;border-color:#ddd;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-page-theme-a .ui-btn:hover,html .ui-bar-a .ui-btn:hover,html .ui-body-a .ui-btn:hover,html body .ui-group-theme-a .ui-btn:hover,html head+body .ui-btn.ui-btn-a:hover{background:#ededed;border-color:#ddd;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-page-theme-a .ui-btn:active,html .ui-bar-a .ui-btn:active,html .ui-body-a .ui-btn:active,html body .ui-group-theme-a .ui-btn:active,html head+body .ui-btn.ui-btn-a:active{background:#e8e8e8;border-color:#ddd;color:#333;text-shadow:0 1px 0 #f3f3f3}.ui-page-theme-a .ui-btn.ui-btn-active,html .ui-bar-a .ui-btn.ui-btn-active,html .ui-body-a .ui-btn.ui-btn-active,html body .ui-group-theme-a .ui-btn.ui-btn-active,html head+body .ui-btn.ui-btn-a.ui-btn-active,.ui-page-theme-a .ui-checkbox-on:after,html .ui-bar-a .ui-checkbox-on:after,html .ui-body-a .ui-checkbox-on:after,html body .ui-group-theme-a .ui-checkbox-on:after,.ui-btn.ui-checkbox-on.ui-btn-a:after,.ui-page-theme-a .ui-flipswitch-active,html .ui-bar-a .ui-flipswitch-active,html .ui-body-a .ui-flipswitch-active,html body .ui-group-theme-a .ui-flipswitch-active,html body .ui-flipswitch.ui-bar-a.ui-flipswitch-active,.ui-page-theme-a .ui-slider-track .ui-btn-active,html .ui-bar-a .ui-slider-track .ui-btn-active,html .ui-body-a .ui-slider-track .ui-btn-active,html body .ui-group-theme-a .ui-slider-track .ui-btn-active,html body div.ui-slider-track.ui-body-a .ui-btn-active{background-color:#38c;border-color:#38c;color:#fff;text-shadow:0 1px 0 #059}.ui-page-theme-a .ui-radio-on:after,html .ui-bar-a .ui-radio-on:after,html .ui-body-a .ui-radio-on:after,html body .ui-group-theme-a .ui-radio-on:after,.ui-btn.ui-radio-on.ui-btn-a:after{border-color:#38c}.ui-page-theme-a .ui-btn:focus,html .ui-bar-a .ui-btn:focus,html .ui-body-a .ui-btn:focus,html body .ui-group-theme-a .ui-btn:focus,html head+body .ui-btn.ui-btn-a:focus,.ui-page-theme-a .ui-focus,html .ui-bar-a .ui-focus,html .ui-body-a .ui-focus,html body .ui-group-theme-a .ui-focus,html head+body .ui-btn-a.ui-focus,html head+body .ui-body-a.ui-focus{-webkit-box-shadow:0 0 12px #38c;-moz-box-shadow:0 0 12px #38c;box-shadow:0 0 12px #38c}.ui-bar-b,.ui-page-theme-b .ui-bar-inherit,html .ui-bar-b .ui-bar-inherit,html .ui-body-b .ui-bar-inherit,html body .ui-group-theme-b .ui-bar-inherit{background:#1d1d1d;border-color:#1b1b1b;color:#fff;text-shadow:0 1px 0 #111;font-weight:700}.ui-bar-b{border-width:1px;border-style:solid}.ui-overlay-b,.ui-page-theme-b,.ui-page-theme-b .ui-panel-wrapper{background:#252525;border-color:#454545;color:#fff;text-shadow:0 1px 0 #111}.ui-body-b,.ui-page-theme-b .ui-body-inherit,html .ui-bar-b .ui-body-inherit,html .ui-body-b .ui-body-inherit,html body .ui-group-theme-b .ui-body-inherit,html .ui-panel-page-container-b{background:#2a2a2a;border-color:#1d1d1d;color:#fff;text-shadow:0 1px 0 #111}.ui-body-b{border-width:1px;border-style:solid}.ui-page-theme-b a,html .ui-bar-b a,html .ui-body-b a,html body .ui-group-theme-b a{color:#2ad;font-weight:700}.ui-page-theme-b a:visited,html .ui-bar-b a:visited,html .ui-body-b a:visited,html body .ui-group-theme-b a:visited{color:#2ad}.ui-page-theme-b a:hover,html .ui-bar-b a:hover,html .ui-body-b a:hover,html body .ui-group-theme-b a:hover{color:#08b}.ui-page-theme-b a:active,html .ui-bar-b a:active,html .ui-body-b a:active,html body .ui-group-theme-b a:active{color:#08b}.ui-page-theme-b .ui-btn,html .ui-bar-b .ui-btn,html .ui-body-b .ui-btn,html body .ui-group-theme-b .ui-btn,html head+body .ui-btn.ui-btn-b,.ui-page-theme-b .ui-btn:visited,html .ui-bar-b .ui-btn:visited,html .ui-body-b .ui-btn:visited,html body .ui-group-theme-b .ui-btn:visited,html head+body .ui-btn.ui-btn-b:visited{background:#333;border-color:#1f1f1f;color:#fff;text-shadow:0 1px 0 #111}.ui-page-theme-b .ui-btn:hover,html .ui-bar-b .ui-btn:hover,html .ui-body-b .ui-btn:hover,html body .ui-group-theme-b .ui-btn:hover,html head+body .ui-btn.ui-btn-b:hover{background:#373737;border-color:#1f1f1f;color:#fff;text-shadow:0 1px 0 #111}.ui-page-theme-b .ui-btn:active,html .ui-bar-b .ui-btn:active,html .ui-body-b .ui-btn:active,html body .ui-group-theme-b .ui-btn:active,html head+body .ui-btn.ui-btn-b:active{background:#404040;border-color:#1f1f1f;color:#fff;text-shadow:0 1px 0 #111}.ui-page-theme-b .ui-btn.ui-btn-active,html .ui-bar-b .ui-btn.ui-btn-active,html .ui-body-b .ui-btn.ui-btn-active,html body .ui-group-theme-b .ui-btn.ui-btn-active,html head+body .ui-btn.ui-btn-b.ui-btn-active,.ui-page-theme-b .ui-checkbox-on:after,html .ui-bar-b .ui-checkbox-on:after,html .ui-body-b .ui-checkbox-on:after,html body .ui-group-theme-b .ui-checkbox-on:after,.ui-btn.ui-checkbox-on.ui-btn-b:after,.ui-page-theme-b .ui-flipswitch-active,html .ui-bar-b .ui-flipswitch-active,html .ui-body-b .ui-flipswitch-active,html body .ui-group-theme-b .ui-flipswitch-active,html body .ui-flipswitch.ui-bar-b.ui-flipswitch-active,.ui-page-theme-b .ui-slider-track .ui-btn-active,html .ui-bar-b .ui-slider-track .ui-btn-active,html .ui-body-b .ui-slider-track .ui-btn-active,html body .ui-group-theme-b .ui-slider-track .ui-btn-active,html body div.ui-slider-track.ui-body-b .ui-btn-active{background-color:#2ad;border-color:#2ad;color:#fff;text-shadow:0 1px 0 #08b}.ui-page-theme-b .ui-radio-on:after,html .ui-bar-b .ui-radio-on:after,html .ui-body-b .ui-radio-on:after,html body .ui-group-theme-b .ui-radio-on:after,.ui-btn.ui-radio-on.ui-btn-b:after{border-color:#2ad}.ui-page-theme-b .ui-btn:focus,html .ui-bar-b .ui-btn:focus,html .ui-body-b .ui-btn:focus,html body .ui-group-theme-b .ui-btn:focus,html head+body .ui-btn.ui-btn-b:focus,.ui-page-theme-b .ui-focus,html .ui-bar-b .ui-focus,html .ui-body-b .ui-focus,html body .ui-group-theme-b .ui-focus,html head+body .ui-btn-b.ui-focus,html head+body .ui-body-b.ui-focus{-webkit-box-shadow:0 0 12px #2ad;-moz-box-shadow:0 0 12px #2ad;box-shadow:0 0 12px #2ad}.ui-disabled,.ui-state-disabled,button[disabled],.ui-select .ui-btn.ui-state-disabled{filter:Alpha(Opacity=30);opacity:.3;cursor:default!important;pointer-events:none}.ui-btn:focus,.ui-btn.ui-focus{outline:0}.ui-noboxshadow .ui-shadow,.ui-noboxshadow .ui-shadow-inset,.ui-noboxshadow .ui-overlay-shadow,.ui-noboxshadow .ui-shadow-icon.ui-btn:after,.ui-noboxshadow .ui-shadow-icon .ui-btn:after,.ui-noboxshadow .ui-focus,.ui-noboxshadow .ui-btn:focus,.ui-noboxshadow input:focus,.ui-noboxshadow .ui-panel{-webkit-box-shadow:none!important;-moz-box-shadow:none!important;box-shadow:none!important}.ui-noboxshadow .ui-btn:focus,.ui-noboxshadow .ui-focus{outline-width:1px;outline-style:auto} -------------------------------------------------------------------------------- /UI/public/css/leaflet.css: -------------------------------------------------------------------------------- 1 | /* required styles */ 2 | 3 | .leaflet-map-pane, 4 | .leaflet-tile, 5 | .leaflet-marker-icon, 6 | .leaflet-marker-shadow, 7 | .leaflet-tile-pane, 8 | .leaflet-tile-container, 9 | .leaflet-overlay-pane, 10 | .leaflet-shadow-pane, 11 | .leaflet-marker-pane, 12 | .leaflet-popup-pane, 13 | .leaflet-overlay-pane svg, 14 | .leaflet-zoom-box, 15 | .leaflet-image-layer, 16 | .leaflet-layer { 17 | position: absolute; 18 | left: 0; 19 | top: 0; 20 | } 21 | .leaflet-container { 22 | overflow: hidden; 23 | -ms-touch-action: none; 24 | } 25 | .leaflet-tile, 26 | .leaflet-marker-icon, 27 | .leaflet-marker-shadow { 28 | -webkit-user-select: none; 29 | -moz-user-select: none; 30 | user-select: none; 31 | -webkit-user-drag: none; 32 | } 33 | .leaflet-marker-icon, 34 | .leaflet-marker-shadow { 35 | display: block; 36 | } 37 | /* map is broken in FF if you have max-width: 100% on tiles */ 38 | .leaflet-container img { 39 | max-width: none !important; 40 | } 41 | /* stupid Android 2 doesn't understand "max-width: none" properly */ 42 | .leaflet-container img.leaflet-image-layer { 43 | max-width: 15000px !important; 44 | } 45 | .leaflet-tile { 46 | filter: inherit; 47 | visibility: hidden; 48 | } 49 | .leaflet-tile-loaded { 50 | visibility: inherit; 51 | } 52 | .leaflet-zoom-box { 53 | width: 0; 54 | height: 0; 55 | } 56 | /* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ 57 | .leaflet-overlay-pane svg { 58 | -moz-user-select: none; 59 | } 60 | 61 | .leaflet-tile-pane { z-index: 2; } 62 | .leaflet-objects-pane { z-index: 3; } 63 | .leaflet-overlay-pane { z-index: 4; } 64 | .leaflet-shadow-pane { z-index: 5; } 65 | .leaflet-marker-pane { z-index: 6; } 66 | .leaflet-popup-pane { z-index: 7; } 67 | 68 | .leaflet-vml-shape { 69 | width: 1px; 70 | height: 1px; 71 | } 72 | .lvml { 73 | behavior: url(#default#VML); 74 | display: inline-block; 75 | position: absolute; 76 | } 77 | 78 | 79 | /* control positioning */ 80 | 81 | .leaflet-control { 82 | position: relative; 83 | z-index: 7; 84 | pointer-events: auto; 85 | } 86 | .leaflet-top, 87 | .leaflet-bottom { 88 | position: absolute; 89 | z-index: 1000; 90 | pointer-events: none; 91 | } 92 | .leaflet-top { 93 | top: 0; 94 | } 95 | .leaflet-right { 96 | right: 0; 97 | } 98 | .leaflet-bottom { 99 | bottom: 0; 100 | } 101 | .leaflet-left { 102 | left: 0; 103 | } 104 | .leaflet-control { 105 | float: left; 106 | clear: both; 107 | } 108 | .leaflet-right .leaflet-control { 109 | float: right; 110 | } 111 | .leaflet-top .leaflet-control { 112 | margin-top: 10px; 113 | } 114 | .leaflet-bottom .leaflet-control { 115 | margin-bottom: 10px; 116 | } 117 | .leaflet-left .leaflet-control { 118 | margin-left: 10px; 119 | } 120 | .leaflet-right .leaflet-control { 121 | margin-right: 10px; 122 | } 123 | 124 | 125 | /* zoom and fade animations */ 126 | 127 | .leaflet-fade-anim .leaflet-tile, 128 | .leaflet-fade-anim .leaflet-popup { 129 | opacity: 0; 130 | -webkit-transition: opacity 0.2s linear; 131 | -moz-transition: opacity 0.2s linear; 132 | -o-transition: opacity 0.2s linear; 133 | transition: opacity 0.2s linear; 134 | } 135 | .leaflet-fade-anim .leaflet-tile-loaded, 136 | .leaflet-fade-anim .leaflet-map-pane .leaflet-popup { 137 | opacity: 1; 138 | } 139 | 140 | .leaflet-zoom-anim .leaflet-zoom-animated { 141 | -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); 142 | -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); 143 | -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1); 144 | transition: transform 0.25s cubic-bezier(0,0,0.25,1); 145 | } 146 | .leaflet-zoom-anim .leaflet-tile, 147 | .leaflet-pan-anim .leaflet-tile, 148 | .leaflet-touching .leaflet-zoom-animated { 149 | -webkit-transition: none; 150 | -moz-transition: none; 151 | -o-transition: none; 152 | transition: none; 153 | } 154 | 155 | .leaflet-zoom-anim .leaflet-zoom-hide { 156 | visibility: hidden; 157 | } 158 | 159 | 160 | /* cursors */ 161 | 162 | .leaflet-clickable { 163 | cursor: pointer; 164 | } 165 | .leaflet-container { 166 | cursor: -webkit-grab; 167 | cursor: -moz-grab; 168 | } 169 | .leaflet-popup-pane, 170 | .leaflet-control { 171 | cursor: auto; 172 | } 173 | .leaflet-dragging .leaflet-container, 174 | .leaflet-dragging .leaflet-clickable { 175 | cursor: move; 176 | cursor: -webkit-grabbing; 177 | cursor: -moz-grabbing; 178 | } 179 | 180 | 181 | /* visual tweaks */ 182 | 183 | .leaflet-container { 184 | background: #ddd; 185 | outline: 0; 186 | } 187 | .leaflet-container a { 188 | color: #0078A8; 189 | } 190 | .leaflet-container a.leaflet-active { 191 | outline: 2px solid orange; 192 | } 193 | .leaflet-zoom-box { 194 | border: 2px dotted #38f; 195 | background: rgba(255,255,255,0.5); 196 | } 197 | 198 | 199 | /* general typography */ 200 | .leaflet-container { 201 | font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; 202 | } 203 | 204 | 205 | /* general toolbar styles */ 206 | 207 | .leaflet-bar { 208 | box-shadow: 0 1px 5px rgba(0,0,0,0.65); 209 | border-radius: 4px; 210 | } 211 | .leaflet-bar a, 212 | .leaflet-bar a:hover { 213 | background-color: #fff; 214 | border-bottom: 1px solid #ccc; 215 | width: 26px; 216 | height: 26px; 217 | line-height: 26px; 218 | display: block; 219 | text-align: center; 220 | text-decoration: none; 221 | color: black; 222 | } 223 | .leaflet-bar a, 224 | .leaflet-control-layers-toggle { 225 | background-position: 50% 50%; 226 | background-repeat: no-repeat; 227 | display: block; 228 | } 229 | .leaflet-bar a:hover { 230 | background-color: #f4f4f4; 231 | } 232 | .leaflet-bar a:first-child { 233 | border-top-left-radius: 4px; 234 | border-top-right-radius: 4px; 235 | } 236 | .leaflet-bar a:last-child { 237 | border-bottom-left-radius: 4px; 238 | border-bottom-right-radius: 4px; 239 | border-bottom: none; 240 | } 241 | .leaflet-bar a.leaflet-disabled { 242 | cursor: default; 243 | background-color: #f4f4f4; 244 | color: #bbb; 245 | } 246 | 247 | .leaflet-touch .leaflet-bar a { 248 | width: 30px; 249 | height: 30px; 250 | line-height: 30px; 251 | } 252 | 253 | 254 | /* zoom control */ 255 | 256 | .leaflet-control-zoom-in, 257 | .leaflet-control-zoom-out { 258 | font: bold 18px 'Lucida Console', Monaco, monospace; 259 | text-indent: 1px; 260 | } 261 | .leaflet-control-zoom-out { 262 | font-size: 20px; 263 | } 264 | 265 | .leaflet-touch .leaflet-control-zoom-in { 266 | font-size: 22px; 267 | } 268 | .leaflet-touch .leaflet-control-zoom-out { 269 | font-size: 24px; 270 | } 271 | 272 | 273 | /* layers control */ 274 | 275 | .leaflet-control-layers { 276 | box-shadow: 0 1px 5px rgba(0,0,0,0.4); 277 | background: #fff; 278 | border-radius: 5px; 279 | } 280 | .leaflet-control-layers-toggle { 281 | background-image: url(images/layers.png); 282 | width: 36px; 283 | height: 36px; 284 | } 285 | .leaflet-retina .leaflet-control-layers-toggle { 286 | background-image: url(images/layers-2x.png); 287 | background-size: 26px 26px; 288 | } 289 | .leaflet-touch .leaflet-control-layers-toggle { 290 | width: 44px; 291 | height: 44px; 292 | } 293 | .leaflet-control-layers .leaflet-control-layers-list, 294 | .leaflet-control-layers-expanded .leaflet-control-layers-toggle { 295 | display: none; 296 | } 297 | .leaflet-control-layers-expanded .leaflet-control-layers-list { 298 | display: block; 299 | position: relative; 300 | } 301 | .leaflet-control-layers-expanded { 302 | padding: 6px 10px 6px 6px; 303 | color: #333; 304 | background: #fff; 305 | } 306 | .leaflet-control-layers-selector { 307 | margin-top: 2px; 308 | position: relative; 309 | top: 1px; 310 | } 311 | .leaflet-control-layers label { 312 | display: block; 313 | } 314 | .leaflet-control-layers-separator { 315 | height: 0; 316 | border-top: 1px solid #ddd; 317 | margin: 5px -10px 5px -6px; 318 | } 319 | 320 | 321 | /* attribution and scale controls */ 322 | 323 | .leaflet-container .leaflet-control-attribution { 324 | background: #fff; 325 | background: rgba(255, 255, 255, 0.7); 326 | margin: 0; 327 | } 328 | .leaflet-control-attribution, 329 | .leaflet-control-scale-line { 330 | padding: 0 5px; 331 | color: #333; 332 | } 333 | .leaflet-control-attribution a { 334 | text-decoration: none; 335 | } 336 | .leaflet-control-attribution a:hover { 337 | text-decoration: underline; 338 | } 339 | .leaflet-container .leaflet-control-attribution, 340 | .leaflet-container .leaflet-control-scale { 341 | font-size: 11px; 342 | } 343 | .leaflet-left .leaflet-control-scale { 344 | margin-left: 5px; 345 | } 346 | .leaflet-bottom .leaflet-control-scale { 347 | margin-bottom: 5px; 348 | } 349 | .leaflet-control-scale-line { 350 | border: 2px solid #777; 351 | border-top: none; 352 | line-height: 1.1; 353 | padding: 2px 5px 1px; 354 | font-size: 11px; 355 | white-space: nowrap; 356 | overflow: hidden; 357 | -moz-box-sizing: content-box; 358 | box-sizing: content-box; 359 | 360 | background: #fff; 361 | background: rgba(255, 255, 255, 0.5); 362 | } 363 | .leaflet-control-scale-line:not(:first-child) { 364 | border-top: 2px solid #777; 365 | border-bottom: none; 366 | margin-top: -2px; 367 | } 368 | .leaflet-control-scale-line:not(:first-child):not(:last-child) { 369 | border-bottom: 2px solid #777; 370 | } 371 | 372 | .leaflet-touch .leaflet-control-attribution, 373 | .leaflet-touch .leaflet-control-layers, 374 | .leaflet-touch .leaflet-bar { 375 | box-shadow: none; 376 | } 377 | .leaflet-touch .leaflet-control-layers, 378 | .leaflet-touch .leaflet-bar { 379 | border: 2px solid rgba(0,0,0,0.2); 380 | background-clip: padding-box; 381 | } 382 | 383 | 384 | /* popup */ 385 | 386 | .leaflet-popup { 387 | position: absolute; 388 | text-align: center; 389 | } 390 | .leaflet-popup-content-wrapper { 391 | padding: 1px; 392 | text-align: left; 393 | border-radius: 12px; 394 | } 395 | .leaflet-popup-content { 396 | margin: 13px 19px; 397 | line-height: 1.4; 398 | } 399 | .leaflet-popup-content p { 400 | margin: 18px 0; 401 | } 402 | .leaflet-popup-tip-container { 403 | margin: 0 auto; 404 | width: 40px; 405 | height: 20px; 406 | position: relative; 407 | overflow: hidden; 408 | } 409 | .leaflet-popup-tip { 410 | width: 17px; 411 | height: 17px; 412 | padding: 1px; 413 | 414 | margin: -10px auto 0; 415 | 416 | -webkit-transform: rotate(45deg); 417 | -moz-transform: rotate(45deg); 418 | -ms-transform: rotate(45deg); 419 | -o-transform: rotate(45deg); 420 | transform: rotate(45deg); 421 | } 422 | .leaflet-popup-content-wrapper, 423 | .leaflet-popup-tip { 424 | background: white; 425 | 426 | box-shadow: 0 3px 14px rgba(0,0,0,0.4); 427 | } 428 | .leaflet-container a.leaflet-popup-close-button { 429 | position: absolute; 430 | top: 0; 431 | right: 0; 432 | padding: 4px 4px 0 0; 433 | text-align: center; 434 | width: 18px; 435 | height: 14px; 436 | font: 16px/14px Tahoma, Verdana, sans-serif; 437 | color: #c3c3c3; 438 | text-decoration: none; 439 | font-weight: bold; 440 | background: transparent; 441 | } 442 | .leaflet-container a.leaflet-popup-close-button:hover { 443 | color: #999; 444 | } 445 | .leaflet-popup-scrolled { 446 | overflow: auto; 447 | border-bottom: 1px solid #ddd; 448 | border-top: 1px solid #ddd; 449 | } 450 | 451 | .leaflet-oldie .leaflet-popup-content-wrapper { 452 | zoom: 1; 453 | } 454 | .leaflet-oldie .leaflet-popup-tip { 455 | width: 24px; 456 | margin: 0 auto; 457 | 458 | -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; 459 | filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); 460 | } 461 | .leaflet-oldie .leaflet-popup-tip-container { 462 | margin-top: -1px; 463 | } 464 | 465 | .leaflet-oldie .leaflet-control-zoom, 466 | .leaflet-oldie .leaflet-control-layers, 467 | .leaflet-oldie .leaflet-popup-content-wrapper, 468 | .leaflet-oldie .leaflet-popup-tip { 469 | border: 1px solid #999; 470 | } 471 | 472 | 473 | /* div icon */ 474 | 475 | .leaflet-div-icon { 476 | background: #fff; 477 | border: 1px solid #666; 478 | } 479 | -------------------------------------------------------------------------------- /UI/public/css/rickshaw.min.css: -------------------------------------------------------------------------------- 1 | .rickshaw_graph .detail{pointer-events:none;position:absolute;top:0;z-index:2;background:rgba(0,0,0,.1);bottom:0;width:1px;transition:opacity .25s linear;-moz-transition:opacity .25s linear;-o-transition:opacity .25s linear;-webkit-transition:opacity .25s linear}.rickshaw_graph .detail.inactive{opacity:0}.rickshaw_graph .detail .item.active{opacity:1}.rickshaw_graph .detail .x_label{font-family:Arial,sans-serif;border-radius:3px;padding:6px;opacity:.5;border:1px solid #e0e0e0;font-size:12px;position:absolute;background:#fff;white-space:nowrap}.rickshaw_graph .detail .x_label.left{left:0}.rickshaw_graph .detail .x_label.right{right:0}.rickshaw_graph .detail .item{position:absolute;z-index:2;border-radius:3px;padding:.25em;font-size:12px;font-family:Arial,sans-serif;opacity:0;background:rgba(0,0,0,.4);color:#fff;border:1px solid rgba(0,0,0,.4);margin-left:1em;margin-right:1em;margin-top:-1em;white-space:nowrap}.rickshaw_graph .detail .item.left{left:0}.rickshaw_graph .detail .item.right{right:0}.rickshaw_graph .detail .item.active{opacity:1;background:rgba(0,0,0,.8)}.rickshaw_graph .detail .item:after{position:absolute;display:block;width:0;height:0;content:"";border:5px solid transparent}.rickshaw_graph .detail .item.left:after{top:1em;left:-5px;margin-top:-5px;border-right-color:rgba(0,0,0,.8);border-left-width:0}.rickshaw_graph .detail .item.right:after{top:1em;right:-5px;margin-top:-5px;border-left-color:rgba(0,0,0,.8);border-right-width:0}.rickshaw_graph .detail .dot{width:4px;height:4px;margin-left:-2px;margin-top:-2px;border-radius:5px;position:absolute;box-shadow:0 0 2px rgba(0,0,0,.6);background:#fff;border-width:2px;border-style:solid;display:none;background-clip:padding-box}.rickshaw_graph .detail .dot.active{display:block}.rickshaw_graph{position:relative}.rickshaw_graph svg{display:block;overflow:hidden}.rickshaw_graph .x_tick{position:absolute;top:0;bottom:0;width:0;border-left:1px dotted rgba(0,0,0,.2);pointer-events:none}.rickshaw_graph .x_tick .title{position:absolute;font-size:12px;font-family:Arial,sans-serif;opacity:.5;white-space:nowrap;margin-left:3px;bottom:1px}.rickshaw_annotation_timeline{height:1px;border-top:1px solid #e0e0e0;margin-top:10px;position:relative}.rickshaw_annotation_timeline .annotation{position:absolute;height:6px;width:6px;margin-left:-2px;top:-3px;border-radius:5px;background-color:rgba(0,0,0,.25)}.rickshaw_graph .annotation_line{position:absolute;top:0;bottom:-6px;width:0;border-left:2px solid rgba(0,0,0,.3);display:none}.rickshaw_graph .annotation_line.active{display:block}.rickshaw_graph .annotation_range{background:rgba(0,0,0,.1);display:none;position:absolute;top:0;bottom:-6px}.rickshaw_graph .annotation_range.active{display:block}.rickshaw_graph .annotation_range.active.offscreen{display:none}.rickshaw_annotation_timeline .annotation .content{background:#fff;color:#000;opacity:.9;padding:5px;box-shadow:0 0 2px rgba(0,0,0,.8);border-radius:3px;position:relative;z-index:20;font-size:12px;padding:6px 8px 8px;top:18px;left:-11px;width:160px;display:none;cursor:pointer}.rickshaw_annotation_timeline .annotation .content:before{content:"\25b2";position:absolute;top:-11px;color:#fff;text-shadow:0 -1px 1px rgba(0,0,0,.8)}.rickshaw_annotation_timeline .annotation.active,.rickshaw_annotation_timeline .annotation:hover{background-color:rgba(0,0,0,.8);cursor:none}.rickshaw_annotation_timeline .annotation .content:hover{z-index:50}.rickshaw_annotation_timeline .annotation.active .content{display:block}.rickshaw_annotation_timeline .annotation:hover .content{display:block;z-index:50}.rickshaw_graph .y_axis,.rickshaw_graph .x_axis_d3{fill:none}.rickshaw_graph .y_ticks .tick,.rickshaw_graph .x_ticks_d3 .tick{stroke:rgba(0,0,0,.16);stroke-width:2px;shape-rendering:crisp-edges;pointer-events:none}.rickshaw_graph .y_grid .tick,.rickshaw_graph .x_grid_d3 .tick{z-index:-1;stroke:rgba(0,0,0,.2);stroke-width:1px;stroke-dasharray:1 1}.rickshaw_graph .y_grid .tick[data-y-value="0"]{stroke-dasharray:1 0}.rickshaw_graph .y_grid path,.rickshaw_graph .x_grid_d3 path{fill:none;stroke:none}.rickshaw_graph .y_ticks path,.rickshaw_graph .x_ticks_d3 path{fill:none;stroke:gray}.rickshaw_graph .y_ticks text,.rickshaw_graph .x_ticks_d3 text{opacity:.5;font-size:12px;pointer-events:none}.rickshaw_graph .x_tick.glow .title,.rickshaw_graph .y_ticks.glow text{fill:#000;color:#000;text-shadow:-1px 1px 0 rgba(255,255,255,.1),1px -1px 0 rgba(255,255,255,.1),1px 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1),0 -1px 0 rgba(255,255,255,.1),1px 0 0 rgba(255,255,255,.1),-1px 0 0 rgba(255,255,255,.1),-1px -1px 0 rgba(255,255,255,.1)}.rickshaw_graph .x_tick.inverse .title,.rickshaw_graph .y_ticks.inverse text{fill:#fff;color:#fff;text-shadow:-1px 1px 0 rgba(0,0,0,.8),1px -1px 0 rgba(0,0,0,.8),1px 1px 0 rgba(0,0,0,.8),0 1px 0 rgba(0,0,0,.8),0 -1px 0 rgba(0,0,0,.8),1px 0 0 rgba(0,0,0,.8),-1px 0 0 rgba(0,0,0,.8),-1px -1px 0 rgba(0,0,0,.8)}.rickshaw_legend{font-family:Arial;font-size:12px;color:#fff;background:#404040;display:inline-block;padding:12px 5px;border-radius:2px;position:relative}.rickshaw_legend:hover{z-index:10}.rickshaw_legend .swatch{width:10px;height:10px;border:1px solid rgba(0,0,0,.2)}.rickshaw_legend .line{clear:both;line-height:140%;padding-right:15px}.rickshaw_legend .line .swatch{display:inline-block;margin-right:3px;border-radius:2px}.rickshaw_legend .label{margin:0;white-space:nowrap;display:inline;font-size:inherit;background-color:transparent;color:inherit;font-weight:400;line-height:normal;padding:0;text-shadow:none}.rickshaw_legend .action:hover{opacity:.6}.rickshaw_legend .action{margin-right:.2em;font-size:10px;opacity:.2;cursor:pointer;font-size:14px}.rickshaw_legend .line.disabled{opacity:.4}.rickshaw_legend ul{list-style-type:none;margin:0;padding:0;margin:2px;cursor:pointer}.rickshaw_legend li{padding:0 0 0 2px;min-width:80px;white-space:nowrap}.rickshaw_legend li:hover{background:rgba(255,255,255,.08);border-radius:3px}.rickshaw_legend li:active{background:rgba(255,255,255,.2);border-radius:3px} -------------------------------------------------------------------------------- /UI/public/css/slider.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Slider for Bootstrap 3 | * 4 | * Copyright 2012 Stefan Petre 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | */ 9 | .slider { 10 | display: inline-block; 11 | vertical-align: middle; 12 | position: relative; 13 | } 14 | .slider.slider-horizontal { 15 | width: 210px; 16 | height: 20px; 17 | } 18 | .slider.slider-horizontal .slider-track { 19 | height: 10px; 20 | width: 100%; 21 | margin-top: -5px; 22 | top: 50%; 23 | left: 0; 24 | } 25 | .slider.slider-horizontal .slider-selection { 26 | height: 100%; 27 | top: 0; 28 | bottom: 0; 29 | } 30 | .slider.slider-horizontal .slider-handle { 31 | margin-left: -10px; 32 | margin-top: -5px; 33 | } 34 | .slider.slider-horizontal .slider-handle.triangle { 35 | border-width: 0 10px 10px 10px; 36 | width: 0; 37 | height: 0; 38 | border-bottom-color: #0480be; 39 | margin-top: 0; 40 | } 41 | .slider.slider-vertical { 42 | height: 210px; 43 | width: 20px; 44 | } 45 | .slider.slider-vertical .slider-track { 46 | width: 10px; 47 | height: 100%; 48 | margin-left: -5px; 49 | left: 50%; 50 | top: 0; 51 | } 52 | .slider.slider-vertical .slider-selection { 53 | width: 100%; 54 | left: 0; 55 | top: 0; 56 | bottom: 0; 57 | } 58 | .slider.slider-vertical .slider-handle { 59 | margin-left: -5px; 60 | margin-top: -10px; 61 | } 62 | .slider.slider-vertical .slider-handle.triangle { 63 | border-width: 10px 0 10px 10px; 64 | width: 1px; 65 | height: 1px; 66 | border-left-color: #0480be; 67 | margin-left: 0; 68 | } 69 | .slider input { 70 | display: none; 71 | } 72 | .slider .tooltip-inner { 73 | white-space: nowrap; 74 | } 75 | .slider-track { 76 | position: absolute; 77 | cursor: pointer; 78 | background-color: #f7f7f7; 79 | background-image: -moz-linear-gradient(top, #f5f5f5, #f9f9f9); 80 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f5f5f5), to(#f9f9f9)); 81 | background-image: -webkit-linear-gradient(top, #f5f5f5, #f9f9f9); 82 | background-image: -o-linear-gradient(top, #f5f5f5, #f9f9f9); 83 | background-image: linear-gradient(to bottom, #f5f5f5, #f9f9f9); 84 | background-repeat: repeat-x; 85 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#fff9f9f9', GradientType=0); 86 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 87 | -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 88 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); 89 | -webkit-border-radius: 4px; 90 | -moz-border-radius: 4px; 91 | border-radius: 4px; 92 | } 93 | .slider-selection { 94 | position: absolute; 95 | background-color: #f7f7f7; 96 | background-image: -moz-linear-gradient(top, #f9f9f9, #f5f5f5); 97 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f9f9f9), to(#f5f5f5)); 98 | background-image: -webkit-linear-gradient(top, #f9f9f9, #f5f5f5); 99 | background-image: -o-linear-gradient(top, #f9f9f9, #f5f5f5); 100 | background-image: linear-gradient(to bottom, #f9f9f9, #f5f5f5); 101 | background-repeat: repeat-x; 102 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#fff5f5f5', GradientType=0); 103 | -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); 104 | -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); 105 | box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15); 106 | -webkit-box-sizing: border-box; 107 | -moz-box-sizing: border-box; 108 | box-sizing: border-box; 109 | -webkit-border-radius: 4px; 110 | -moz-border-radius: 4px; 111 | border-radius: 4px; 112 | } 113 | .slider-handle { 114 | position: absolute; 115 | width: 20px; 116 | height: 20px; 117 | background-color: #0e90d2; 118 | background-image: -moz-linear-gradient(top, #149bdf, #0480be); 119 | background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#149bdf), to(#0480be)); 120 | background-image: -webkit-linear-gradient(top, #149bdf, #0480be); 121 | background-image: -o-linear-gradient(top, #149bdf, #0480be); 122 | background-image: linear-gradient(to bottom, #149bdf, #0480be); 123 | background-repeat: repeat-x; 124 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf', endColorstr='#ff0480be', GradientType=0); 125 | -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); 126 | -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); 127 | box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05); 128 | opacity: 0.8; 129 | border: 0px solid transparent; 130 | } 131 | .slider-handle.round { 132 | -webkit-border-radius: 20px; 133 | -moz-border-radius: 20px; 134 | border-radius: 20px; 135 | } 136 | .slider-handle.triangle { 137 | background: transparent none; 138 | } -------------------------------------------------------------------------------- /UI/public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /UI/public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /UI/public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /UI/public/formelzeichen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/formelzeichen.png -------------------------------------------------------------------------------- /UI/public/js/bootstrap-slider.js: -------------------------------------------------------------------------------- 1 | /* ========================================================= 2 | * bootstrap-slider.js v2.0.0 3 | * http://www.eyecon.ro/bootstrap-slider 4 | * ========================================================= 5 | * Copyright 2012 Stefan Petre 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ========================================================= */ 19 | 20 | !function( $ ) { 21 | 22 | var Slider = function(element, options) { 23 | this.element = $(element); 24 | this.picker = $('
'+ 25 | '
'+ 26 | '
'+ 27 | '
'+ 28 | '
'+ 29 | '
'+ 30 | '
'+ 31 | '
') 32 | .insertBefore(this.element) 33 | .append(this.element); 34 | this.id = this.element.data('slider-id')||options.id; 35 | if (this.id) { 36 | this.picker[0].id = this.id; 37 | } 38 | 39 | if (typeof Modernizr !== 'undefined' && Modernizr.touch) { 40 | this.touchCapable = true; 41 | } 42 | 43 | var tooltip = this.element.data('slider-tooltip')||options.tooltip; 44 | 45 | this.tooltip = this.picker.find('.tooltip'); 46 | this.tooltipInner = this.tooltip.find('div.tooltip-inner'); 47 | 48 | this.orientation = this.element.data('slider-orientation')||options.orientation; 49 | switch(this.orientation) { 50 | case 'vertical': 51 | this.picker.addClass('slider-vertical'); 52 | this.stylePos = 'top'; 53 | this.mousePos = 'pageY'; 54 | this.sizePos = 'offsetHeight'; 55 | this.tooltip.addClass('right')[0].style.left = '100%'; 56 | break; 57 | default: 58 | this.picker 59 | .addClass('slider-horizontal') 60 | .css('width', this.element.outerWidth()); 61 | this.orientation = 'horizontal'; 62 | this.stylePos = 'left'; 63 | this.mousePos = 'pageX'; 64 | this.sizePos = 'offsetWidth'; 65 | this.tooltip.addClass('top')[0].style.top = -this.tooltip.outerHeight() - 14 + 'px'; 66 | break; 67 | } 68 | 69 | this.min = this.element.data('slider-min')||options.min; 70 | this.max = this.element.data('slider-max')||options.max; 71 | this.step = this.element.data('slider-step')||options.step; 72 | this.value = this.element.data('slider-value')||options.value; 73 | if (this.value[1]) { 74 | this.range = true; 75 | } 76 | 77 | this.selection = this.element.data('slider-selection')||options.selection; 78 | this.selectionEl = this.picker.find('.slider-selection'); 79 | if (this.selection === 'none') { 80 | this.selectionEl.addClass('hide'); 81 | } 82 | this.selectionElStyle = this.selectionEl[0].style; 83 | 84 | 85 | this.handle1 = this.picker.find('.slider-handle:first'); 86 | this.handle1Stype = this.handle1[0].style; 87 | this.handle2 = this.picker.find('.slider-handle:last'); 88 | this.handle2Stype = this.handle2[0].style; 89 | 90 | var handle = this.element.data('slider-handle')||options.handle; 91 | switch(handle) { 92 | case 'round': 93 | this.handle1.addClass('round'); 94 | this.handle2.addClass('round'); 95 | break 96 | case 'triangle': 97 | this.handle1.addClass('triangle'); 98 | this.handle2.addClass('triangle'); 99 | break 100 | } 101 | 102 | if (this.range) { 103 | this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0])); 104 | this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1])); 105 | } else { 106 | this.value = [ Math.max(this.min, Math.min(this.max, this.value))]; 107 | this.handle2.addClass('hide'); 108 | if (this.selection == 'after') { 109 | this.value[1] = this.max; 110 | } else { 111 | this.value[1] = this.min; 112 | } 113 | } 114 | this.diff = this.max - this.min; 115 | this.percentage = [ 116 | (this.value[0]-this.min)*100/this.diff, 117 | (this.value[1]-this.min)*100/this.diff, 118 | this.step*100/this.diff 119 | ]; 120 | 121 | this.offset = this.picker.offset(); 122 | this.size = this.picker[0][this.sizePos]; 123 | 124 | this.formater = options.formater; 125 | 126 | this.layout(); 127 | 128 | if (this.touchCapable) { 129 | // Touch: Bind touch events: 130 | this.picker.on({ 131 | touchstart: $.proxy(this.mousedown, this) 132 | }); 133 | } else { 134 | this.picker.on({ 135 | mousedown: $.proxy(this.mousedown, this) 136 | }); 137 | } 138 | 139 | if (tooltip === 'show') { 140 | this.picker.on({ 141 | mouseenter: $.proxy(this.showTooltip, this), 142 | mouseleave: $.proxy(this.hideTooltip, this) 143 | }); 144 | } else { 145 | this.tooltip.addClass('hide'); 146 | } 147 | }; 148 | 149 | Slider.prototype = { 150 | constructor: Slider, 151 | 152 | over: false, 153 | inDrag: false, 154 | 155 | showTooltip: function(){ 156 | this.tooltip.addClass('in'); 157 | //var left = Math.round(this.percent*this.width); 158 | //this.tooltip.css('left', left - this.tooltip.outerWidth()/2); 159 | this.over = true; 160 | }, 161 | 162 | hideTooltip: function(){ 163 | if (this.inDrag === false) { 164 | this.tooltip.removeClass('in'); 165 | } 166 | this.over = false; 167 | }, 168 | 169 | layout: function(){ 170 | this.handle1Stype[this.stylePos] = this.percentage[0]+'%'; 171 | this.handle2Stype[this.stylePos] = this.percentage[1]+'%'; 172 | if (this.orientation == 'vertical') { 173 | this.selectionElStyle.top = Math.min(this.percentage[0], this.percentage[1]) +'%'; 174 | this.selectionElStyle.height = Math.abs(this.percentage[0] - this.percentage[1]) +'%'; 175 | } else { 176 | this.selectionElStyle.left = Math.min(this.percentage[0], this.percentage[1]) +'%'; 177 | this.selectionElStyle.width = Math.abs(this.percentage[0] - this.percentage[1]) +'%'; 178 | } 179 | if (this.range) { 180 | this.tooltipInner.text( 181 | this.formater(this.value[0]) + 182 | ' : ' + 183 | this.formater(this.value[1]) 184 | ); 185 | this.tooltip[0].style[this.stylePos] = this.size * (this.percentage[0] + (this.percentage[1] - this.percentage[0])/2)/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px'; 186 | } else { 187 | this.tooltipInner.text( 188 | this.formater(this.value[0]) 189 | ); 190 | this.tooltip[0].style[this.stylePos] = this.size * this.percentage[0]/100 - (this.orientation === 'vertical' ? this.tooltip.outerHeight()/2 : this.tooltip.outerWidth()/2) +'px'; 191 | } 192 | }, 193 | 194 | mousedown: function(ev) { 195 | 196 | // Touch: Get the original event: 197 | if (this.touchCapable && ev.type === 'touchstart') { 198 | ev = ev.originalEvent; 199 | } 200 | 201 | this.offset = this.picker.offset(); 202 | this.size = this.picker[0][this.sizePos]; 203 | 204 | var percentage = this.getPercentage(ev); 205 | 206 | if (this.range) { 207 | var diff1 = Math.abs(this.percentage[0] - percentage); 208 | var diff2 = Math.abs(this.percentage[1] - percentage); 209 | this.dragged = (diff1 < diff2) ? 0 : 1; 210 | } else { 211 | this.dragged = 0; 212 | } 213 | 214 | this.percentage[this.dragged] = percentage; 215 | this.layout(); 216 | 217 | if (this.touchCapable) { 218 | // Touch: Bind touch events: 219 | $(document).on({ 220 | touchmove: $.proxy(this.mousemove, this), 221 | touchend: $.proxy(this.mouseup, this) 222 | }); 223 | } else { 224 | $(document).on({ 225 | mousemove: $.proxy(this.mousemove, this), 226 | mouseup: $.proxy(this.mouseup, this) 227 | }); 228 | } 229 | 230 | this.inDrag = true; 231 | var val = this.calculateValue(); 232 | this.element.trigger({ 233 | type: 'slideStart', 234 | value: val 235 | }).trigger({ 236 | type: 'slide', 237 | value: val 238 | }); 239 | return false; 240 | }, 241 | 242 | mousemove: function(ev) { 243 | 244 | // Touch: Get the original event: 245 | if (this.touchCapable && ev.type === 'touchmove') { 246 | ev = ev.originalEvent; 247 | } 248 | 249 | var percentage = this.getPercentage(ev); 250 | if (this.range) { 251 | if (this.dragged === 0 && this.percentage[1] < percentage) { 252 | this.percentage[0] = this.percentage[1]; 253 | this.dragged = 1; 254 | } else if (this.dragged === 1 && this.percentage[0] > percentage) { 255 | this.percentage[1] = this.percentage[0]; 256 | this.dragged = 0; 257 | } 258 | } 259 | this.percentage[this.dragged] = percentage; 260 | this.layout(); 261 | var val = this.calculateValue(); 262 | this.element 263 | .trigger({ 264 | type: 'slide', 265 | value: val 266 | }) 267 | .data('value', val) 268 | .prop('value', val); 269 | return false; 270 | }, 271 | 272 | mouseup: function(ev) { 273 | if (this.touchCapable) { 274 | // Touch: Bind touch events: 275 | $(document).off({ 276 | touchmove: this.mousemove, 277 | touchend: this.mouseup 278 | }); 279 | } else { 280 | $(document).off({ 281 | mousemove: this.mousemove, 282 | mouseup: this.mouseup 283 | }); 284 | } 285 | 286 | this.inDrag = false; 287 | if (this.over == false) { 288 | this.hideTooltip(); 289 | } 290 | this.element; 291 | var val = this.calculateValue(); 292 | this.element 293 | .trigger({ 294 | type: 'slideStop', 295 | value: val 296 | }) 297 | .data('value', val) 298 | .prop('value', val); 299 | return false; 300 | }, 301 | 302 | calculateValue: function() { 303 | var val; 304 | if (this.range) { 305 | val = [ 306 | (this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step), 307 | (this.min + Math.round((this.diff * this.percentage[1]/100)/this.step)*this.step) 308 | ]; 309 | this.value = val; 310 | } else { 311 | val = (this.min + Math.round((this.diff * this.percentage[0]/100)/this.step)*this.step); 312 | this.value = [val, this.value[1]]; 313 | } 314 | return val; 315 | }, 316 | 317 | getPercentage: function(ev) { 318 | if (this.touchCapable) { 319 | ev = ev.touches[0]; 320 | } 321 | var percentage = (ev[this.mousePos] - this.offset[this.stylePos])*100/this.size; 322 | percentage = Math.round(percentage/this.percentage[2])*this.percentage[2]; 323 | return Math.max(0, Math.min(100, percentage)); 324 | }, 325 | 326 | getValue: function() { 327 | if (this.range) { 328 | return this.value; 329 | } 330 | return this.value[0]; 331 | }, 332 | 333 | setValue: function(val) { 334 | this.value = val; 335 | 336 | if (this.range) { 337 | this.value[0] = Math.max(this.min, Math.min(this.max, this.value[0])); 338 | this.value[1] = Math.max(this.min, Math.min(this.max, this.value[1])); 339 | } else { 340 | this.value = [ Math.max(this.min, Math.min(this.max, this.value))]; 341 | this.handle2.addClass('hide'); 342 | if (this.selection == 'after') { 343 | this.value[1] = this.max; 344 | } else { 345 | this.value[1] = this.min; 346 | } 347 | } 348 | this.diff = this.max - this.min; 349 | this.percentage = [ 350 | (this.value[0]-this.min)*100/this.diff, 351 | (this.value[1]-this.min)*100/this.diff, 352 | this.step*100/this.diff 353 | ]; 354 | this.layout(); 355 | } 356 | }; 357 | 358 | $.fn.slider = function ( option, val ) { 359 | return this.each(function () { 360 | var $this = $(this), 361 | data = $this.data('slider'), 362 | options = typeof option === 'object' && option; 363 | if (!data) { 364 | $this.data('slider', (data = new Slider(this, $.extend({}, $.fn.slider.defaults,options)))); 365 | } 366 | if (typeof option == 'string') { 367 | data[option](val); 368 | } 369 | }) 370 | }; 371 | 372 | $.fn.slider.defaults = { 373 | min: 0, 374 | max: 10, 375 | step: 1, 376 | orientation: 'horizontal', 377 | value: 5, 378 | selection: 'before', 379 | tooltip: 'show', 380 | handle: 'round', 381 | formater: function(value) { 382 | return value; 383 | } 384 | }; 385 | 386 | $.fn.slider.Constructor = Slider; 387 | 388 | }( window.jQuery ); -------------------------------------------------------------------------------- /UI/public/js/desktop.js: -------------------------------------------------------------------------------- 1 | var socket = io.connect(); 2 | var sliderTimeout = 0; 3 | var packet; 4 | var graphdata = {}; 5 | 6 | var gui_day = 0; 7 | var gui_month = ""; 8 | var gui_year = 0; 9 | var map; 10 | 11 | var conn_status = "disconnected"; 12 | var conn_info = ""; 13 | var conn_warning = ""; 14 | 15 | var set_status = function(){ 16 | $('#status-field').html(conn_status + conn_info + conn_warning); 17 | } 18 | 19 | var ua = window.navigator.userAgent; 20 | var msie = ua.indexOf("MSIE "); 21 | 22 | if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) 23 | { 24 | var ieversion = parseInt(ua.substring(msie + 5, ua.indexOf(".", msie))); 25 | if(ieversion < 10) 26 | { 27 | conn_info = "Internet Explorer " + ieversion + " is too old, please upgrade to 10!"; 28 | } 29 | } 30 | 31 | var ff = ua.indexOf("Firefox/"); 32 | if(ff > 0) 33 | { 34 | var ffversion = parseInt(ua.substring(ff+8, ua.indexOf(".", ff))); 35 | if(ffversion < 24) 36 | { 37 | conn_info = "Firefox " + ffversion + " is too old, please upgrade to 24!"; 38 | } 39 | } 40 | 41 | var cr = ua.indexOf("Chrome/"); 42 | if(cr > 0) 43 | { 44 | var crversion = parseInt(ua.substring(ff+8, ua.indexOf(".", ff))); 45 | if(crversion < 14) 46 | { 47 | conn_info = "Chrome " + ffversion + " is too old, please upgrade to 14!"; 48 | } 49 | } 50 | 51 | set_status(); 52 | 53 | socket.on('connect', function () { 54 | socket.emit('clienthello'); // sync 55 | conn_warning = ""; 56 | conn_status = "connected"; 57 | set_status(); 58 | }); 59 | 60 | socket.on('error', function (e) { 61 | conn_status = "disconnected"; 62 | conn_warning = "System error: " + e; 63 | set_status(); 64 | }); 65 | 66 | socket.on('realtimedata', function(data) { 67 | if(typeof data == "undefined"){return;}; 68 | if(typeof data.windspeed == "undefined"){return;}; 69 | 70 | graphdata['graph-windspeed-realtime'].graph.series.addData({'m/s': data.windspeed}); 71 | // graphdata['graph-windspeed-realtime'].graph.series.name ='m/s'; 72 | graphdata['graph-windspeed-realtime'].graph.render(); 73 | graphdata['graph-windspeed-realtime'].graphaxisY.render(); 74 | graphdata['graph-windspeed-realtime'].legend.render(); 75 | $('#windspeed-realtime').html(Math.floor(data.windspeed*2)/2 + ' m/s'); 76 | $('#datetime-realtime').html(data.time + "( now: " + new Date().toUTCString() + " )" ); 77 | $('#powerval-realtime').html( parseFloat(parseInt(0.350814814815 * parseFloat(data.windspeed)*parseFloat(data.windspeed)*parseFloat(data.windspeed) * 1000))/1000+ ' Ws'); 78 | $('#graph-windspeed-realtime-label0').html( 'm/s' ); 79 | $('#graph-windspeed-realtime-label1').html( 's' ); 80 | $('#electricpowerval-realtime').html( parseFloat(parseInt(0.350814814815 * parseFloat(data.windspeed)*parseFloat(data.windspeed)*parseFloat(data.windspeed) * 0.5518 * 1000))/1000+ ' Ws' ); 81 | if(typeof data.status != "undefined") 82 | $('status-realtime').html( data.status ); 83 | }); 84 | 85 | var menu_onclick = function(target){ 86 | var targetid = $(target).attr('id'); 87 | var name = $(target).attr('name'); 88 | console.log(" targetid " + targetid + " name " + name ); 89 | if(name == 'year' && targetid != gui_year) 90 | socket.emit('UpdateYear', {'year': targetid}); 91 | if(name == 'month' && targetid != gui_month) 92 | socket.emit('UpdateMonth', {'month': targetid, 'year': gui_year}); 93 | if(name == 'day' && targetid != gui_day) 94 | socket.emit('UpdateDay', {'day': targetid, 'month': gui_month, 'year': gui_year}); 95 | }; 96 | 97 | socket.on('UpdateMenu', function(data) { 98 | var tmp = ""; 99 | //console.log("update menu " + data.fkt); 100 | for(var i in data.val) 101 | { 102 | tmp += "
  • " + data.val[i] + "
  • \n"; 103 | } 104 | $("#dd_"+data.fkt).html(tmp); 105 | }); 106 | 107 | socket.on('UpdateValue', function(data) { 108 | // update internal date too 109 | if(data.id == "title-year") 110 | { 111 | gui_year = data.val; 112 | $("#title-year").html(' ' + gui_year); 113 | } 114 | else if(data.id == "title-month") 115 | { 116 | gui_month = data.val; 117 | $("#title-month").html(' ' + gui_month + ' ' + gui_year); 118 | } 119 | else if(data.id == "title-day") 120 | { 121 | gui_day = data.val; 122 | $("#title-day").html(' ' + gui_day + '. ' + gui_month + ' ' + gui_year); 123 | } 124 | else 125 | { 126 | $("#" + data.id).html(' ' + data.val); 127 | } 128 | }); 129 | 130 | var func_updateGraph = function(id){ 131 | if(typeof graphdata[id] == "undefined") 132 | { 133 | console.log('graph ' + id + ' not found !'); 134 | return; 135 | } 136 | // create a deep copy 137 | var data = jQuery.extend(true, {}, graphdata[id].rawdata); 138 | if(data.id.toString().indexOf('hist') > -1) 139 | { 140 | graphdata[id].graph.series[1].data = data.val; 141 | graphdata[id].graph.series[1].name = data.legend; 142 | graphdata[id].graph.series[0].data = data.val2; 143 | graphdata[id].graph.series[0].name = '90% ' + data.legend; 144 | //remove 0 element if button is active 145 | if($('#' + id + '-btn1').find('.enabled').hasClass('active')) 146 | { 147 | for(i in graphdata[id].graph.series[1].data) 148 | { 149 | if(graphdata[id].graph.series[1].data[i].x == 0) 150 | graphdata[id].graph.series[1].data[i].y = 0; 151 | } 152 | for(i in graphdata[id].graph.series[0].data) 153 | { 154 | if(graphdata[id].graph.series[0].data[i].x == 0) 155 | graphdata[id].graph.series[0].data[i].y = 0; 156 | } 157 | console.log("enabled"); 158 | 159 | } 160 | //console.log("setting graphdata"); 161 | } 162 | else 163 | { 164 | graphdata[id].graph.series[0].data = data.val; 165 | graphdata[id].graph.series[0].name = data.legend; 166 | } 167 | graphdata[id].graph.render(); 168 | graphdata[id].graphaxisY.render(); 169 | if(typeof data.units != "undefined"){ 170 | graphdata[id].graphaxisX.tickFormat = function(n) { 171 | var map = data.units; 172 | return map[n]; 173 | }; 174 | }; 175 | graphdata[id].graphaxisX.render(); 176 | graphdata[id].legend.render(); 177 | if(typeof data.label_y != "undefined"){ 178 | $("#" + id + "-label0").html('' + data.label_y + ''); 179 | } 180 | if(typeof data.label_x != "undefined"){ 181 | $("#" + id + "-label1").html('' + data.label_x + ''); 182 | } 183 | }; 184 | 185 | socket.on('UpdateGraph', function(data) { 186 | if(typeof graphdata[data.id] == "undefined") 187 | { 188 | console.log(data.id + ' not found !'); 189 | return; 190 | } 191 | // make a copy 192 | graphdata[data.id].rawdata = data; 193 | func_updateGraph(data.id); 194 | }); 195 | 196 | function getPPI(){ 197 | // create an empty element 198 | var div = document.createElement("div"); 199 | // give it an absolute size of one inch 200 | div.style.width="1in"; 201 | // append it to the body 202 | var body = document.getElementsByTagName("body")[0]; 203 | body.appendChild(div); 204 | // read the computed width 205 | var ppi = document.defaultView.getComputedStyle(div, null).getPropertyValue('width'); 206 | // remove it again 207 | body.removeChild(div); 208 | // and return the value 209 | return parseFloat(ppi); 210 | } 211 | 212 | //JQuery dark magic, adds 'hide()' and 'show()' to each element 213 | (function ($) { 214 | $.each(['show', 'hide'], function (i, ev) { 215 | var el = $.fn[ev]; 216 | $.fn[ev] = function () { 217 | this.trigger(ev); 218 | return el.apply(this, arguments); 219 | }; 220 | }); 221 | })(jQuery); 222 | 223 | $(document).ready(function() { 224 | $('.nav-tabs').each(function(){ 225 | $(this).css('font-size', getPPI()/5+'px'); 226 | console.log('setting fonsize ' + getPPI()/5+'px'); 227 | }); 228 | $('#map').click(function(){ 229 | if(typeof map == "undefined") 230 | { 231 | // create a map in the "map" div, set the view to a given place and zoom 232 | map = L.map('map', {center: [52.524, 13.406],zoom: 13}); 233 | 234 | // add an OpenStreetMap tile layer 235 | L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', { 236 | attribution: '© OpenStreetMap contributors' 237 | }).addTo(map); 238 | 239 | // add a marker in the given location, attach some popup content to it and open the popup 240 | L.marker([52.524, 13.406]).addTo(map); 241 | } 242 | map.invalidateSize(false); 243 | }); 244 | $('.graph-container').each(function(){ 245 | var data = [{'x':0, 'y':0}]; 246 | graphdata[this.id] = {}; 247 | $('#' + this.id + '-chart').width( $('.container').width() * 0.75 ); 248 | $('#' + this.id + '-chart').height( $('.container').width() * 0.35 ); 249 | $('#' + this.id + '-axis1').width( $('.container').width() * 0.75 ); 250 | $('#' + this.id + '-axis0').height( $('.container').width() * 0.35 ); 251 | 252 | var series = [{ 253 | color: 'steelblue', 254 | data: data, 255 | name: ''}]; 256 | 257 | var rendererstring='bar'; 258 | if($('#' + this.id ).hasClass( 'line' ) ) 259 | { 260 | rendererstring = 'line'; 261 | } 262 | else if($('#' + this.id ).hasClass( 'area' ) ) 263 | { 264 | rendererstring = 'area'; 265 | } 266 | else if($('#' + this.id ).hasClass( 'multi' ) ) 267 | { 268 | rendererstring = 'multi'; 269 | series = [ 270 | { 271 | color: 'rgba(255, 100, 100, 0.4)', 272 | data: data, 273 | name: '', 274 | renderer: 'area' }, 275 | 276 | { 277 | color: 'steelblue', 278 | data: data, 279 | name: '', 280 | renderer: 'bar'} 281 | ]; 282 | } 283 | 284 | if($('#' + this.id ).hasClass( 'realtime' ) ) 285 | { 286 | series = new Rickshaw.Series.FixedDuration([{ name: 'm/s' }], undefined, { 287 | timeInterval: 1000, 288 | maxDataPoints: 100, 289 | timeBase: new Date().getTime() / 1000 290 | }); 291 | } 292 | 293 | graphdata[this.id].graph = new Rickshaw.Graph({ 294 | element: document.getElementById(this.id + '-chart'), 295 | renderer: rendererstring, 296 | series: series 297 | }); 298 | graphdata[this.id].graph.render(); 299 | graphdata[this.id].graphaxisY = new Rickshaw.Graph.Axis.Y({ 300 | element: document.getElementById(this.id + '-axis0'), 301 | graph: graphdata[this.id].graph, 302 | orientation: 'left', 303 | tickFormat: Rickshaw.Fixtures.Number.formatKMBT 304 | }); 305 | graphdata[this.id].graphaxisY.render(); 306 | var format=function(x){return x;}; 307 | graphdata[this.id].graphaxisX = new Rickshaw.Graph.Axis.X({ 308 | graph: graphdata[this.id].graph, 309 | element: document.getElementById(this.id + '-axis1'), 310 | tickFormat: format, 311 | }); 312 | graphdata[this.id].graphaxisX.render(); 313 | graphdata[this.id].legend = new Rickshaw.Graph.Legend({ 314 | graph: graphdata[this.id].graph, 315 | element: document.getElementById(this.id + '-legend') 316 | }); 317 | 318 | $('#' + this.id + '-chart').children().width($('#' + this.id + '-chart').width()); 319 | $('#' + this.id + '-chart').children().height($('#' + this.id + '-chart').height()); 320 | }); 321 | 322 | $('.btn-toggle').click(function() { 323 | $(this).find('.btn').toggleClass('active'); 324 | if ($(this).find('.btn-primary').size()>0) { 325 | $(this).find('.btn').toggleClass('btn-primary'); 326 | } 327 | func_updateGraph(this.id.split('-btn')[0]); 328 | }); 329 | 330 | }); 331 | 332 | $( window ).resize(function() { 333 | $("img").each(function() { 334 | if(this.width > $('.container').width() * 0.75) 335 | this.width = $('.container').width() * 0.75; 336 | }); 337 | for(var i in graphdata) 338 | { 339 | $('#' + i + '-chart').width( $('.container').width() * 0.75 ); 340 | $('#' + i + '-chart').height( $('.container').width() * 0.35 ); 341 | $('#' + i + '-axis1').width( $('.container').width() * 0.75 ); 342 | $('#' + i + '-axis0').height( $('.container').width() * 0.35 ); 343 | 344 | console.log("new size " + $('#' + i + '-chart').width() + " , " + $('#' + i + '-chart').height()); 345 | graphdata[i].graph.width = $('#' + i + '-chart').width(); 346 | graphdata[i].graph.height = $('#' + i + '-chart').height(); 347 | graphdata[i].graph.render(); 348 | graphdata[i].graphaxisY.render(); 349 | graphdata[i].graphaxisX.render(); 350 | $('#' + i + '-chart').children().width($('#' + i + '-chart').width()); 351 | $('#' + i + '-chart').children().height($('#' + i + '-chart').height()); 352 | 353 | }; 354 | 355 | }); 356 | 357 | -------------------------------------------------------------------------------- /UI/public/js/images/layers-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/js/images/layers-2x.png -------------------------------------------------------------------------------- /UI/public/js/images/layers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/js/images/layers.png -------------------------------------------------------------------------------- /UI/public/js/images/marker-icon-2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/js/images/marker-icon-2x.png -------------------------------------------------------------------------------- /UI/public/js/images/marker-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/js/images/marker-icon.png -------------------------------------------------------------------------------- /UI/public/js/images/marker-shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/js/images/marker-shadow.png -------------------------------------------------------------------------------- /UI/public/windpower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/UI/public/windpower.png -------------------------------------------------------------------------------- /UI/server.js: -------------------------------------------------------------------------------- 1 | // nodejs webserver and datalogger 2 | // Copyright (C) 2014 Patrick Rudolph 3 | 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | var http = require('./http.js'); 18 | var configuration = require('./config.json'); 19 | var recon = require('recon') 20 | var internal = require('./internal.js'); 21 | var rawdatafilename = 'data.json'; 22 | 23 | var localdevice = 1; 24 | var monthNames = [ "January", "February", "March", "April", "May", "June", 25 | "July", "August", "September", "October", "November", "December" ]; 26 | 27 | var data = internal.read_data(configuration.datafilename); 28 | 29 | // socket to communicate with python script 'server' 30 | var conn = recon(configuration.windserver.hostname, configuration.windserver.port); 31 | console.log("connecting to " + configuration.windserver.hostname + " : " + configuration.windserver.port); 32 | // this is the netsocket 33 | var io = http.io; 34 | 35 | var conn_msg = {}; 36 | 37 | // receive data from 'server' 38 | var conn_data = function (buf){ 39 | if(typeof buf == "undefined") 40 | return; 41 | var msg = buf.toString().trim(); 42 | console.log(msg); 43 | try{ 44 | msg = JSON.parse(msg); 45 | } 46 | catch(err) 47 | { 48 | console.log("JSON parse failed " + msg); 49 | internal.update_histogram(0); 50 | return; 51 | } 52 | if(typeof msg["windspeed"] != "undefined") 53 | { 54 | internal.update_histogram(msg["windspeed"]); 55 | io.sockets.emit('realtimedata', msg); 56 | } 57 | }; 58 | 59 | var conn_recon = function(){ 60 | io.sockets.emit('realtimedata', {'status': 'reconnected ' + new Date()} ); 61 | }; 62 | 63 | var conn_err = function(err){ 64 | io.sockets.emit('realtimedata', {'status': 'Error: ' + err} ); 65 | conn = recon(configuration.windserver.hostname, configuration.windserver.port); 66 | conn.on('data', conn_data()); 67 | conn.on('reconnect', conn_recon()); 68 | conn.on('error', conn_err()); 69 | }; 70 | 71 | conn.on('data', conn_data); 72 | conn.on('reconnect', conn_recon); 73 | conn.on('error', conn_err); 74 | 75 | // websockets callback function 76 | io.sockets.on('connection', function (socket) { 77 | var updateMenuYear = function(){ 78 | if(typeof data != "undefined") 79 | { 80 | var tmp = []; 81 | for(var i in data) 82 | { 83 | if(i != "total") 84 | { 85 | tmp.push(i.toString()); 86 | } 87 | } 88 | socket.emit('UpdateMenu', {'fkt':'year', 'val': tmp}); 89 | } 90 | }; 91 | var updateMenuDay = function(now_year, now_month){ 92 | if(typeof data[now_year][now_month] != "undefined") 93 | { 94 | var tmp = []; 95 | for(var i in data[now_year][now_month]) 96 | { 97 | if(i != "total") 98 | { 99 | tmp.push(i.toString()); 100 | } 101 | } 102 | socket.emit('UpdateMenu', {'fkt':'day', 'val': tmp}); 103 | } 104 | }; 105 | var updateMenuMonth = function(now_year){ 106 | if(typeof data[now_year] != "undefined") 107 | { 108 | var tmp = []; 109 | for(var i in data[now_year]) 110 | { 111 | if( i != "total") 112 | { 113 | tmp.push(i.toString()); 114 | } 115 | } 116 | socket.emit('UpdateMenu', {'fkt':'month', 'val': tmp}); 117 | } 118 | }; 119 | 120 | var updategraph = function(id, datain, datain2, legend, type) 121 | { 122 | var unit_array = []; 123 | var data_array = []; 124 | var data_array2 = []; 125 | var idx = 0; 126 | var maxval = internal.get_max_val(datain); 127 | if(maxval > 0) 128 | { 129 | idx = 0; 130 | for(i=0;i<=maxval;i+=0.5) 131 | { 132 | unit_array.push(i.toString()); 133 | if(typeof datain[i] != "undefined") 134 | { 135 | data_array.push({'x': idx, 'y': datain[i]}); 136 | } 137 | else 138 | { 139 | data_array.push({'x': idx, 'y': 0}); 140 | } 141 | if(typeof datain2[i] != "undefined") 142 | { 143 | data_array2.push({'x': idx, 'y': datain2[i]}); 144 | } 145 | else 146 | { 147 | data_array2.push({'x': idx, 'y': 0}); 148 | } 149 | 150 | idx += 1; 151 | } 152 | } 153 | else 154 | { 155 | for(var i in datain) 156 | { 157 | unit_array.push(i.toString()); 158 | data_array.push({'x': idx, 'y': datain[i]}); 159 | if(typeof datain2[i] != "undefined") 160 | { 161 | data_array2.push({'x': idx, 'y': datain2[i]}); 162 | } 163 | idx += 1; 164 | } 165 | } 166 | socket.emit('UpdateGraph', {'id': id, 'graphtype': type, 'val': data_array, 'val2': data_array2, 'units': unit_array, 'legend': legend }); 167 | }; 168 | 169 | var updategraph2 = function(id, datain, legend, type, label_x, label_y) 170 | { 171 | var unit_array = []; 172 | var data_array = []; 173 | var idx = 0; 174 | var maxval = internal.get_max_val(datain); 175 | if(maxval > 0) 176 | { 177 | idx = 0; 178 | for(i=1;i<=maxval;i+=1) 179 | { 180 | unit_array.push(i.toString()); 181 | if(typeof datain[i] != "undefined") 182 | { 183 | data_array.push({'x': idx, 'y': datain[i]}); 184 | } 185 | else 186 | { 187 | data_array.push({'x': idx, 'y': 0}); 188 | } 189 | idx += 1; 190 | } 191 | } 192 | else 193 | { 194 | for(var i in datain) 195 | { 196 | unit_array.push(i.toString()); 197 | data_array.push({'x': idx, 'y': datain[i]}); 198 | idx += 1; 199 | } 200 | } 201 | socket.emit('UpdateGraph', {'id': id, 'graphtype': type, 'val': data_array, 'units': unit_array, 'legend': legend}); 202 | }; 203 | 204 | var updateGUIyear = function(gui_year) { 205 | var now = new Date(); 206 | var hist_data; 207 | var power_hist_data; 208 | 209 | console.log('updateGUIyear(' + gui_year + ')'); 210 | 211 | if(typeof gui_year == "undefined") 212 | gui_year = (1900 + now.getYear()).toString(); 213 | 214 | //update title 215 | socket.emit('UpdateValue', {'id': 'title-year','val': gui_year.toString() }); 216 | 217 | if(typeof data[gui_year]["total"] == "undefined") 218 | return; 219 | 220 | hist_data = data[gui_year]["total"]; 221 | socket.emit('UpdateValue', {'id': 'top-speed-year','val': internal.get_max_speed(hist_data).toString()+ " m/s"}); 222 | socket.emit('UpdateValue', {'id': 'aver-speed-year','val': (parseInt(internal.get_average_speed(hist_data)*1000)/1000).toString()+ " m/s"}); 223 | socket.emit('UpdateValue', {'id': 'bottom-speed-year','val': internal.get_min_speed(hist_data).toString()+ " m/s"}); 224 | socket.emit('UpdateValue', {'id': 'powerval-year','val': (parseInt(internal.get_power_val(hist_data)*1000)/1000).toString()+ " kWh"}); 225 | socket.emit('UpdateValue', {'id': 'seconds-sum-year','val':internal.get_seconds_sum(hist_data).toString()+ " s ( " + internal.toYDHMS(internal.get_seconds_sum(hist_data)) + " )" }); 226 | socket.emit('UpdateValue', {'id': 'electricpowerval-year','val':(parseInt(internal.get_power_val(hist_data)*0.5518*1000)/1000).toString() + " kWh"}); 227 | socket.emit('UpdateValue', {'id': 'seconds-over-4msec-year','val':internal.get_seconds_over_4msec(hist_data).toString() + " s ( " + internal.toYDHMS(internal.get_seconds_over_4msec(hist_data)) + " )"}); 228 | 229 | updategraph('graph-hist-year',hist_data, internal.get_min_max_area(hist_data), 'm/s', 'bar'); 230 | 231 | power_hist_data = []; 232 | //convert hist_data to Ws 233 | for(var i in hist_data) 234 | { 235 | var power_item = {}; 236 | power_item[i] = hist_data[i]; 237 | power_hist_data[i] = internal.get_power_val(power_item); 238 | } 239 | updategraph('graph-hist-power-year', power_hist_data, internal.get_min_max_area(power_hist_data),'kWh','bar'); 240 | 241 | // graph-aver-speed 242 | var graph_time_data = {}; 243 | for(var i in data[gui_year]) 244 | { 245 | if(i != "total") 246 | { 247 | graph_time_data[i] = internal.get_average_speed(data[gui_year][i]["total"]); 248 | } 249 | } 250 | updategraph2('graph-aver-speed-year',graph_time_data, 'm/s', 'bar'); 251 | 252 | // graph-powerval 253 | graph_time_data = {}; 254 | for(var i in data[gui_year]) 255 | { 256 | if(i != "total") //skip year total 257 | { 258 | graph_time_data[i] = internal.get_power_val(data[gui_year][i]["total"]); 259 | } 260 | } 261 | updategraph2('graph-powerval-year', graph_time_data, 'kWh', 'bar'); 262 | 263 | // graph-electricpowerval 264 | graph_time_data = {}; 265 | for(var i in data[gui_year]) 266 | { 267 | if(i != "total") //skip year total 268 | { 269 | graph_time_data[i] = internal.get_power_val(data[gui_year][i]["total"])*0.5518; 270 | } 271 | } 272 | updategraph2('graph-electricpowerval-year', graph_time_data, 'kWh', 'bar'); 273 | 274 | // graph-over-4msec 275 | graph_time_data = {}; 276 | for(var i in data[gui_year]) 277 | { 278 | if(i != "total") //skip year total 279 | { 280 | graph_time_data[i] = internal.get_seconds_over_4msec(data[gui_year][i]["total"]); 281 | } 282 | } 283 | updategraph2('graph-over-4msec-year', graph_time_data, 'Windgeschwindigkeit >= 4 m/s', 'bar'); 284 | 285 | // update month selection menu 286 | updateMenuMonth(gui_year); 287 | } 288 | 289 | var updateGUImonth = function(gui_year, gui_month) { 290 | var now = new Date(); 291 | var hist_data; 292 | var power_hist_data; 293 | 294 | console.log('updateGUImonth(' + gui_year + ',' + gui_month + ')'); 295 | 296 | if(typeof gui_year == "undefined") 297 | gui_year = (1900 + now.getYear()).toString(); 298 | 299 | if(typeof gui_month == "undefined") 300 | gui_month = -1; 301 | 302 | if(typeof data[gui_year][gui_month] == "undefined") 303 | gui_month = -1; 304 | 305 | if(gui_month == -1) 306 | { 307 | var i = 0; 308 | gui_month = monthNames[i]; 309 | while(typeof data[gui_year][gui_month] == "undefined" && i < 13) 310 | { i++; gui_month = monthNames[i]; } 311 | if(i == 13) 312 | return; 313 | } 314 | 315 | if(typeof data[gui_year][gui_month]["total"] == "undefined") 316 | return; 317 | 318 | //update title 319 | socket.emit('UpdateValue', {'id': 'title-month','val': gui_month.toString()}); 320 | 321 | hist_data = data[gui_year][gui_month]["total"]; 322 | socket.emit('UpdateValue', {'id': 'top-speed-month','val': internal.get_max_speed(hist_data).toString()+ " m/s"}); 323 | socket.emit('UpdateValue', {'id': 'aver-speed-month','val': (parseInt(internal.get_average_speed(hist_data)*1000)/1000).toString()+ " m/s"}); 324 | socket.emit('UpdateValue', {'id': 'bottom-speed-month','val': internal.get_min_speed(hist_data).toString()+ " m/s"}); 325 | socket.emit('UpdateValue', {'id': 'powerval-month','val': (parseInt(internal.get_power_val(hist_data)*1000)/1000).toString() + " kWh"}); 326 | socket.emit('UpdateValue', {'id': 'seconds-sum-month','val': internal.get_seconds_sum(hist_data).toString()+ " s ( " + internal.toYDHMS(internal.get_seconds_sum(hist_data)) + " )" }); 327 | socket.emit('UpdateValue', {'id': 'seconds-over-4msec-month','val': internal.get_seconds_over_4msec(hist_data).toString() + " s ( " + internal.toYDHMS(internal.get_seconds_over_4msec(hist_data)) + " )"}); 328 | socket.emit('UpdateValue', {'id': 'electricpowerval-month','val':(parseInt(internal.get_power_val(hist_data)*0.5518*1000)/1000).toString() + " kWh"}); 329 | updategraph('graph-hist-month', hist_data, internal.get_min_max_area(hist_data),'m/s', 'bar'); 330 | 331 | // graph-hist-power 332 | power_hist_data = {}; 333 | for(var i in hist_data) 334 | { 335 | var power_item = {}; 336 | power_item[i] = hist_data[i]; 337 | power_hist_data[i] = internal.get_power_val(power_item); 338 | } 339 | updategraph('graph-hist-power-month', power_hist_data, internal.get_min_max_area(power_hist_data),'kWh','bar'); 340 | 341 | // graph-powerval 342 | graph_time_data = {}; 343 | for(var i in data[gui_year][gui_month]) 344 | { 345 | if(i != "total") 346 | { 347 | graph_time_data[i] = internal.get_power_val(data[gui_year][gui_month][i]); 348 | } 349 | } 350 | updategraph2('graph-powerval-month', graph_time_data, 'kWh', 'bar'); 351 | 352 | // graph-aver-speed 353 | graph_time_data = {}; 354 | for(var i in data[gui_year][gui_month]) 355 | { 356 | if(i != "total") 357 | { 358 | graph_time_data[i] = internal.get_average_speed(data[gui_year][gui_month][i]); 359 | } 360 | } 361 | updategraph2('graph-aver-speed-month', graph_time_data, 'm/s', 'bar'); 362 | 363 | // graph-over-4msec 364 | graph_time_data = {}; 365 | for(var i in data[gui_year][gui_month]) 366 | { 367 | if(i != "total") 368 | { 369 | graph_time_data[i] = internal.get_seconds_over_4msec(data[gui_year][gui_month][i]); 370 | } 371 | } 372 | updategraph2('graph-over-4msec-month', graph_time_data, 'Windgeschwindigkeit >= 4 m/s', 'bar'); 373 | 374 | // graph-electricpowerval 375 | graph_time_data = {}; 376 | for(var i in data[gui_year][gui_month]) 377 | { 378 | if(i != "total") 379 | { 380 | graph_time_data[i] = internal.get_power_val(data[gui_year][gui_month][i])*0.5518; 381 | } 382 | } 383 | updategraph2('graph-electricpowerval-month', graph_time_data, 'kWh', 'bar'); 384 | 385 | updateMenuDay(gui_year, gui_month); 386 | } 387 | 388 | var updateGUIday = function(gui_year, gui_month, gui_day) { 389 | var now = new Date(); 390 | var hist_data; 391 | var power_hist_data; 392 | 393 | console.log('updateGUIday(' + gui_year + ',' + gui_month + ',' + gui_day + ')'); 394 | 395 | if(typeof gui_year == "undefined") 396 | gui_year = (1900 + now.getYear()).toString(); 397 | 398 | if(typeof gui_month == "undefined") 399 | gui_month = -1; 400 | 401 | if(typeof data[gui_year][gui_month] == "undefined") 402 | gui_month = -1; 403 | 404 | if(gui_month == -1) 405 | { 406 | var i = 0; 407 | gui_month = monthNames[i]; 408 | while(typeof data[gui_year][gui_month] == "undefined" && i < 13) 409 | { i++; gui_month = monthNames[i]; } 410 | if(i == 13) 411 | return; 412 | } 413 | 414 | if(typeof gui_day == "undefined") 415 | gui_day = -1; 416 | 417 | if(typeof data[gui_year][gui_month][gui_day] == "undefined") 418 | gui_day = -1; 419 | 420 | if(gui_day == -1) 421 | { 422 | gui_day = 0; 423 | while(typeof data[gui_year][gui_month][gui_day] == "undefined" && gui_day < 32) 424 | { gui_day++; } 425 | if(gui_day == 32) 426 | return; 427 | } 428 | //update title 429 | socket.emit('UpdateValue', {'id': 'title-day', 'val': gui_day.toString()}); 430 | 431 | if(typeof data[gui_year][gui_month][gui_day] == "undefined") 432 | return; 433 | 434 | hist_data = data[gui_year][gui_month][gui_day]; 435 | socket.emit('UpdateValue', {'id': 'top-speed-day','val': internal.get_max_speed(hist_data).toString() + " m/s"}); 436 | socket.emit('UpdateValue', {'id': 'aver-speed-day','val': (parseInt(internal.get_average_speed(hist_data)*1000)/1000).toString() + " m/s"}); 437 | socket.emit('UpdateValue', {'id': 'bottom-speed-day','val': internal.get_min_speed(hist_data).toString() + " m/s"}); 438 | socket.emit('UpdateValue', {'id': 'powerval-day','val': (parseInt(internal.get_power_val(hist_data)*1000)/1000).toString() + " kWh"}); 439 | socket.emit('UpdateValue', {'id': 'seconds-sum-day','val':internal.get_seconds_sum(hist_data).toString()+ " s ( " + internal.toYDHMS(internal.get_seconds_sum(hist_data)) + " )"}); 440 | socket.emit('UpdateValue', {'id': 'seconds-over-4msec-day','val':internal.get_seconds_over_4msec(hist_data).toString() + " s ( " + internal.toYDHMS(internal.get_seconds_over_4msec(hist_data)) + " )"}); 441 | socket.emit('UpdateValue', {'id': 'electricpowerval-day','val':(parseInt(internal.get_power_val(hist_data)*0.5518*1000)/1000).toString() + " kWh"}); 442 | updategraph('graph-hist-day',hist_data, internal.get_min_max_area(hist_data),'m/s', 'bar'); 443 | 444 | power_hist_data = []; 445 | //convert hist_data to kWh 446 | for(var i in hist_data) 447 | { 448 | var power_item = {}; 449 | power_item[i] = hist_data[i]; 450 | power_hist_data[i] = internal.get_power_val(power_item); 451 | } 452 | updategraph('graph-hist-power-day',power_hist_data, internal.get_min_max_area(power_hist_data),'KWh','bar'); 453 | }; 454 | 455 | socket.on('UpdateYear', function(pkt){ 456 | if(typeof pkt.year != "undefined") 457 | { 458 | updateGUIyear(pkt.year); 459 | updateGUImonth(pkt.year, -1); 460 | updateGUIday(gui_year, -1, -1); 461 | } 462 | }); 463 | socket.on('UpdateMonth', function(pkt){ 464 | if(typeof pkt.month != "undefined") 465 | { 466 | if(typeof pkt.year != "undefined") 467 | { 468 | updateGUImonth(pkt.year, pkt.month); 469 | updateGUIday(pkt.year, pkt.month, -1); 470 | } 471 | } 472 | }); 473 | socket.on('UpdateDay', function(pkt){ 474 | if(typeof pkt.day != "undefined") 475 | { 476 | if(typeof pkt.month != "undefined") 477 | { 478 | if(typeof pkt.year != "undefined") 479 | { 480 | updateGUIday(pkt.year, pkt.month, pkt.day); 481 | } 482 | } 483 | } 484 | }); 485 | // a new client connected, update all graphs 486 | socket.on('clienthello', function(){ 487 | var now = new Date(), 488 | now_day = now.getDate().toString(), 489 | now_month = monthNames[now.getMonth()], 490 | now_year = (1900 + now.getYear()).toString(); 491 | updateGUIyear(now_year); 492 | updateGUImonth(now_year, now_month); 493 | updateGUIday(now_year, now_month, now_day); 494 | }); 495 | 496 | }); 497 | 498 | -------------------------------------------------------------------------------- /UI/views/index-de.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Webinterface 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
    24 |
    25 |

    Status:

    26 |

    27 |
    28 |
    29 |
    30 | 37 |
    38 |
    39 | 47 |

    Jahr

    48 |

    49 |

    Histogramm

    50 |
    51 |
    52 |

    s

    53 |
    54 |
    55 |
    56 |
    57 |

    m/s

    58 |
    59 |
    60 | 61 | 62 |
    63 |
    64 |

    Histogramm

    65 |
    66 |
    67 |

    kWh

    68 |
    69 |
    70 |
    71 |
    72 |

    m/s

    73 |
    74 |
    75 |

    Durchschnittsgeschwindigkeit

    76 |
    77 |
    78 |

    m/s

    79 |
    80 |
    81 |
    82 |
    83 |

    Monat

    84 |
    85 |
    86 |

    Windgeschwindigkeit über 4 m/s

    87 |
    88 |
    89 |

    s

    90 |
    91 |
    92 |
    93 |
    94 |

    Monat

    95 |
    96 |
    97 |

    Windarbeit

    98 |
    99 |
    100 |

    kWh

    101 |
    102 |
    103 |
    104 |
    105 |

    Monat

    106 |
    107 |
    108 |

    Elektrische Arbeit

    109 |
    110 |
    111 |

    kWh

    112 |
    113 |
    114 |
    115 |
    116 |

    Monat

    117 |
    118 |
    119 |

    Werte

    120 |
    121 |
    122 |

    Maximale Windgeschwindigkeit:

    123 |

    124 |
    125 |
    126 |

    Durschschnittliche Windgeschwindigkeit:

    127 |

    128 |
    129 |
    130 |

    Niedrigste Windgeschwindigkeit:

    131 |

    132 |
    133 |
    134 |

    Windarbeit pro 1qm Rotorfläche:

    135 |

    136 |
    137 |
    138 |

    Sekunden gesamt:

    139 |

    140 |
    141 |
    142 |

    Windgeschwindigkeit über 4 m/s

    143 |

    144 |
    145 |
    146 |

    Elektrische Arbeit:

    147 |

    148 |
    149 |
    150 |
    151 |
    152 | 160 |

    Monat

    161 |

    162 |

    Histogramm

    163 |
    164 |
    165 |

    s

    166 |
    167 |
    168 |
    169 |
    170 |

    m/s

    171 |
    172 |
    173 | 174 | 175 |
    176 |
    177 |

    Histogramm

    178 |
    179 |
    180 |

    kWh

    181 |
    182 |
    183 |
    184 |
    185 |

    m/s

    186 |
    187 |
    188 |

    Durchschnittsgeschwindigkeit

    189 |
    190 |
    191 |

    m/s

    192 |
    193 |
    194 |
    195 |
    196 |

    Tag

    197 |
    198 |
    199 |

    Windgeschwindigkeit über 4 m/s

    200 |
    201 |
    202 |

    s

    203 |
    204 |
    205 |
    206 |
    207 |

    Tag

    208 |
    209 |
    210 |

    Windarbeit

    211 |
    212 |
    213 |

    kWh

    214 |
    215 |
    216 |
    217 |
    218 |

    Tag

    219 |
    220 |
    221 |

    Elektrische Arbeit

    222 |
    223 |
    224 |

    kWh

    225 |
    226 |
    227 |
    228 |
    229 |

    Tag

    230 |
    231 |
    232 |

    Werte

    233 |
    234 |
    235 |

    Maximale Windgeschwindigkeit:

    236 |

    237 |
    238 |
    239 |

    Durschschnittliche Windgeschwindigkeit:

    240 |

    241 |
    242 |
    243 |

    Niedrigste Windgeschwindigkeit:

    244 |

    245 |
    246 |
    247 |

    Windarbeit pro 1qm Rotorfläche:

    248 |

    249 |
    250 |
    251 |

    Sekunden gesamt:

    252 |

    253 |
    254 |
    255 |

    Windgeschwindigkeit über 4 m/s

    256 |

    257 |
    258 |
    259 |

    Elektrische Arbeit:

    260 |

    261 |
    262 |
    263 |
    264 |
    265 | 273 |

    Tag

    274 |

    275 |

    Histogramm

    276 |
    277 |
    278 |

    s

    279 |
    280 |
    281 |
    282 |
    283 |

    m/s

    284 |
    285 |
    286 | 287 | 288 |
    289 |
    290 |

    Histogramm

    291 |
    292 |
    293 |

    kWh

    294 |
    295 |
    296 |
    297 |
    298 |

    m/s

    299 |
    300 |
    301 |

    Werte

    302 |
    303 |
    304 |

    Maximale Windgeschwindigkeit:

    305 |

    306 |
    307 |
    308 |

    Durschschnittliche Windgeschwindigkeit:

    309 |

    310 |
    311 |
    312 |

    Niedrigste Windgeschwindigkeit:

    313 |

    314 |
    315 |
    316 |

    Windarbeit pro 1qm Rotorfläche

    317 |

    318 |
    319 |
    320 |

    Sekunden gesamt:

    321 |

    322 |
    323 |
    324 |

    Windgeschwindigkeit über 4 m/s:

    325 |

    326 |
    327 |
    328 |

    Elektrische Arbeit:

    329 |

    330 |
    331 |
    332 |
    333 |
    334 |

    Aktuelle Werte

    335 |
    336 |
    337 |

    Windgeschwindigkeit:

    338 |

    339 |
    340 |
    341 |

    Windarbeit pro 1qm Rotorfläche:

    342 |

    343 |
    344 |
    345 |

    Zeitpunkt der Messung:

    346 |

    347 |
    348 |
    349 |

    Elektrische Arbeit:

    350 |

    351 |
    352 |
    353 |

    354 |
    355 |
    356 |

    Graph

    357 |
    358 |
    359 |

    m/s

    360 |
    361 |
    362 |
    363 |
    364 |

    s

    365 |
    366 |
    367 |
    368 |
    369 |

    Bilder

    370 |
    371 |

    Ort

    372 |
    373 |
    374 |

    Hier klicken zum Darstellen

    375 |
    376 |
    377 |

    Formeln

    378 |

    379 |
    380 |
    381 |
    382 |
    383 |
    384 | 387 | 388 | 389 | -------------------------------------------------------------------------------- /UI/views/index-en.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Webinterface 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
    24 |
    25 |

    status:

    26 |

    27 |
    28 |
    29 |
    30 | 37 |
    38 |
    39 | 47 |

    Year

    48 |

    49 |

    Histogramm

    50 |
    51 |
    52 |

    s

    53 |
    54 |
    55 |
    56 |
    57 |

    m/s

    58 |
    59 |
    60 | 61 | 62 |
    63 |
    64 |

    Histogramm

    65 |
    66 |
    67 |

    kWh

    68 |
    69 |
    70 |
    71 |
    72 |

    m/s

    73 |
    74 |
    75 |

    Average speed

    76 |
    77 |
    78 |

    m/s

    79 |
    80 |
    81 |
    82 |
    83 |

    month

    84 |
    85 |
    86 |

    speed over 4m/s

    87 |
    88 |
    89 |

    s

    90 |
    91 |
    92 |
    93 |
    94 |

    month

    95 |
    96 |
    97 |

    work done by wind

    98 |
    99 |
    100 |

    kWh

    101 |
    102 |
    103 |
    104 |
    105 |

    month

    106 |
    107 |
    108 |

    electrical work done by wind

    109 |
    110 |
    111 |

    kWh

    112 |
    113 |
    114 |
    115 |
    116 |

    month

    117 |
    118 |
    119 |

    Werte

    120 |
    121 |
    122 |

    wind speed:

    123 |

    124 |
    125 |
    126 |

    average wind speed:

    127 |

    128 |
    129 |
    130 |

    lowest wind speed:

    131 |

    132 |
    133 |
    134 |

    work done by wind on 1qm rotorarea:

    135 |

    136 |
    137 |
    138 |

    seconds total:

    139 |

    140 |
    141 |
    142 |

    windspeed over 4 m/s:

    143 |

    144 |
    145 |
    146 |

    electrical work done by wind:

    147 |

    148 |
    149 |
    150 |
    151 |
    152 | 160 |

    month

    161 |

    162 |

    Histogramm

    163 |
    164 |
    165 |

    s

    166 |
    167 |
    168 |
    169 |
    170 |

    m/s

    171 |
    172 |
    173 | 174 | 175 |
    176 |
    177 |

    Histogramm

    178 |
    179 |
    180 |

    kWh

    181 |
    182 |
    183 |
    184 |
    185 |

    m/s

    186 |
    187 |
    188 |

    average wind speed

    189 |
    190 |
    191 |

    m/s

    192 |
    193 |
    194 |
    195 |
    196 |

    day

    197 |
    198 |
    199 |

    wind speed over 4m/s

    200 |
    201 |
    202 |

    s

    203 |
    204 |
    205 |
    206 |
    207 |

    day

    208 |
    209 |
    210 |

    work done by wind

    211 |
    212 |
    213 |

    kWh

    214 |
    215 |
    216 |
    217 |
    218 |

    day

    219 |
    220 |
    221 |

    electrical work done by wind

    222 |
    223 |
    224 |

    kWh

    225 |
    226 |
    227 |
    228 |
    229 |

    day

    230 |
    231 |
    232 |

    Werte

    233 |
    234 |
    235 |

    maximum wind speed:

    236 |

    237 |
    238 |
    239 |

    average wind speed:

    240 |

    241 |
    242 |
    243 |

    lowest wind speed:

    244 |

    245 |
    246 |
    247 |

    work done by wind on 1qm rotorarea:

    248 |

    249 |
    250 |
    251 |

    seconds total:

    252 |

    253 |
    254 |
    255 |

    wind speed over 4m/s:

    256 |

    257 |
    258 |
    259 |

    electrical work done by wind:

    260 |

    261 |
    262 |
    263 |
    264 |
    265 | 273 |

    day

    274 |

    275 |

    Histogramm

    276 |
    277 |
    278 |

    s

    279 |
    280 |
    281 |
    282 |
    283 |

    m/s

    284 |
    285 |
    286 | 287 | 288 |
    289 |
    290 |

    Histogramm

    291 |
    292 |
    293 |

    kWh

    294 |
    295 |
    296 |
    297 |
    298 |

    m/s

    299 |
    300 |
    301 |

    Werte

    302 |
    303 |
    304 |

    maximum wind speed:

    305 |

    306 |
    307 |
    308 |

    average wind speed:

    309 |

    310 |
    311 |
    312 |

    lowest wind speed:

    313 |

    314 |
    315 |
    316 |

    work done by wind on 1qm rotorarea:

    317 |

    318 |
    319 |
    320 |

    seconds total:

    321 |

    322 |
    323 |
    324 |

    wind speed over 4m/s

    325 |

    326 |
    327 |
    328 |

    electrical work done by wind:

    329 |

    330 |
    331 |
    332 |
    333 |
    334 |

    actual values

    335 |
    336 |
    337 |

    wind speed:

    338 |

    339 |
    340 |
    341 |

    work done by wind on 1qm rotor area:

    342 |

    343 |
    344 |
    345 |

    time of measurement:

    346 |

    347 |
    348 |
    349 |

    electrical work done by wind:

    350 |

    351 |
    352 |
    353 |

    354 |
    355 |
    356 |

    Graph

    357 |
    358 |
    359 |

    m/s

    360 |
    361 |
    362 |
    363 |
    364 |

    s

    365 |
    366 |
    367 |
    368 |
    369 |

    Pictures

    370 |
    371 |

    Location

    372 |
    373 |
    374 |

    Click to view

    375 |
    376 |
    377 |

    Formulas

    378 |

    379 |
    380 |
    381 |
    382 |
    383 |
    384 | 387 | 388 | 389 | -------------------------------------------------------------------------------- /WS100_schematics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siro20/windsensor/743b277d43ae2bf932181ee72457b839ebd266af/WS100_schematics.png -------------------------------------------------------------------------------- /server/README.md: -------------------------------------------------------------------------------- 1 | Python Windsensor 2 | ======== 3 | Python script to collect and send realtime winddata over TCP/IP. 4 | 5 | required python modules: 6 | -------------- 7 | * https://pypi.python.org/pypi/RPi.GPIO 8 | 9 | python configuration: 10 | ------------------- 11 | The python script runs the TCP/IP server on port 2400 as default. At the moment there's no config for the python script. 12 | It samples the frequency on Pin3, converts it to rpm, and transmit this value once a second to all connected TCP/IP clients. 13 | 14 | hardware: 15 | ---------------- 16 | * raspberry pi 17 | * connect an impulse generating wind sensor to GND and Pin3 18 | * change the conversion from impulses to m/s in windsensorserver.py 19 | * the current implementation is for Eltako WS100 20 | 21 | python windsensorserver.py 22 | 23 | license: 24 | ---------------- 25 | GNU General Public License v3. 26 | -------------------------------------------------------------------------------- /server/windsensorserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # networking daemon running on Raspberry PI for wind-measuring 3 | # Copyright (C) 2014-2015 Patrick Rudolph 4 | 5 | # This program is free software: you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation, either version 3 of the License, or 8 | # (at your option) any later version. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | 15 | # You should have received a copy of the GNU General Public License 16 | # along with this program. If not, see . 17 | 18 | import SocketServer 19 | import subprocess 20 | import sys 21 | import threading 22 | from thread import start_new_thread 23 | import time 24 | import RPi.GPIO as GPIO 25 | import math 26 | import time 27 | 28 | # RPi.GPIO Layout verwenden (wie Pin-Nummern) 29 | GPIO.setmode(GPIO.BOARD) 30 | 31 | # Pin 3 (GPIO 0) auf Input setzen 32 | GPIO.setup(3, GPIO.IN, pull_up_down=GPIO.PUD_UP) 33 | 34 | imp_per_sec = 0 35 | actual_windspeed_msec = 0 36 | events = [] 37 | def interrupt(val): 38 | global imp_per_sec 39 | imp_per_sec += 1 40 | 41 | GPIO.add_event_detect(3, GPIO.RISING, callback = interrupt, bouncetime = 5) 42 | 43 | def ws100_imp_to_mpersec(val): 44 | #y = 8E-09x5 - 2E-06x4 + 0,0002x3 - 0,0073x2 + 0,4503x + 0,11 45 | 46 | y = float("8e-9") * math.pow(val,5) - float("2e-6") * math.pow(val,4) + float("2e-4") * math.pow(val,3) - float("7.3e-3") * math.pow(val,2) + 0.4503 * val + 0.11 47 | if y < 0.2: 48 | y = 0 49 | return y 50 | 51 | def threadeval(): 52 | global imp_per_sec 53 | global actual_windspeed_msec 54 | while 1: 55 | actual_windspeed_msec = ws100_imp_to_mpersec(imp_per_sec) 56 | print "actual_windspeed_msec %f" % actual_windspeed_msec 57 | imp_per_sec = 0 58 | for x in events: 59 | x.set() 60 | time.sleep(1) 61 | 62 | start_new_thread(threadeval, ()) 63 | 64 | HOST = '' 65 | PORT = 2400 66 | 67 | ############################################################################ 68 | ''' One instance per connection. 69 | Override handle(self) to customize action. ''' 70 | 71 | class TCPConnectionHandler(SocketServer.BaseRequestHandler): 72 | def handle(self): 73 | global actual_windspeed_msec 74 | self.event = threading.Event() 75 | events.append(self.event) 76 | while 1: 77 | self.event.wait() 78 | self.event.clear() 79 | try: 80 | self.request.sendall('{"windspeed": %f, "time": "%s"}' % (actual_windspeed_msec,time.strftime('%X %x %Z'))) 81 | except: 82 | break 83 | events.remove(self.event) 84 | 85 | ############################################################################ 86 | 87 | class Server(SocketServer.ThreadingMixIn, SocketServer.TCPServer): 88 | # Ctrl-C will cleanly kill all spawned threads 89 | daemon_threads = True 90 | # much faster rebinding 91 | allow_reuse_address = True 92 | 93 | def __init__(self, server_address, RequestHandlerClass): 94 | SocketServer.TCPServer.__init__(\ 95 | self,\ 96 | server_address,\ 97 | RequestHandlerClass) 98 | 99 | ############################################################################ 100 | 101 | if __name__ == "__main__": 102 | server = Server((HOST, PORT), TCPConnectionHandler) 103 | # terminate with Ctrl-C 104 | try: 105 | server.serve_forever() 106 | except KeyboardInterrupt: 107 | sys.exit(0) 108 | 109 | ############################################################################ 110 | --------------------------------------------------------------------------------