Skip to content

Commit

Permalink
Working pages for CO2, distance, temperature and dust.
Browse files Browse the repository at this point in the history
Added a chime sound when the maximum of the bar is updated
Updated README file
  • Loading branch information
Gustavo Olivares committed Nov 25, 2015
1 parent 79b191f commit 9f1b7ea
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 229 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@ Once you have cloned the repository locally, fire your terminal in the project d
Different web pages have been implemented to test different visualization methods:
* `http://localhost:8080/index.html` Basic "hello world" page showing the live feed from PACMAN as a table of values and as simple visualizations. Intended to illustrate the data and general visualization capabilities.
* `http://localhost:8080/bars.html` Vertical bars covering the screen, one for each sensor in different colours that reflect the measurements, taller bar means higher measurements.
* `http://localhost:8080/bars.html` The screen is divided in 4 sections dealing with specific sensors.
The range of the bars is defined by the last 60 readings (max/min).
The distance sensor also controls the sounds emitted (think theremin).
* `http://localhost:8080/grid.html` The screen is divided in 4 sections dealing with specific sensors.
* `http://localhost:8080/temperature.html` The screen shows a single vertical bar scaled according to the last 60 readings (max/min) and if the max is reached, a chime plays.
* `http://localhost:8080/co2.html` The screen shows a single vertical bar scaled according to the last 60 readings (max/min) and if the max is reached, a chime plays.
* `http://localhost:8080/distance.html` The screen shows a single vertical bar scaled from 0 to ~60cm. The distance sensor also controls the sounds emitted (think theremin).
* `http://localhost:8080/dust.html` The screen shows a field of particles floating. The number of particles in the window is controlled by the readings of the dust sensor.
If the current reading is the max over the past 60 readings, a chime plays.

It will call the main method in the web_server.py script, which starts i) a Tornado web application with some handlers, a WebSocket server, two queues and a periodic callback (to check one of the queues), and ii) another "agent" thread.

Expand Down
1 change: 1 addition & 0 deletions air1/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def get_metrics(self):
metrics['time'] = datetime.datetime.now().strftime('%H:%M:%S')
pacman_data = self.pacman.read_data()
metrics['pacman_data'] = pacman_data
print(pacman_data)

return metrics

Expand Down
48 changes: 30 additions & 18 deletions air1/pacman.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ def __init__(self):
file.close()
# Initialise the activity counter
self.movlist = [0] * 60
# Initialise the frames for scaling Output
self.frameCO2 = [0] * 60
self.frameDUST = [0] * 60
self.frameTEMP = [10] * 60
# Initialise max/min for scaling Output
self.frameCO2[59] = -2500
self.frameDUST[59] = 3000
self.frameTEMP[59] = 30
# Initialise the max/min for scales
self.maxCO2 = max(self.frameCO2)
self.minCO2 = min(self.frameCO2)
self.maxDUST = max(self.frameDUST)
self.minDUST = min(self.frameDUST)
self.maxTEMP = max(self.frameTEMP)
self.minTEMP = min(self.frameTEMP)

# Initialise the CO handling containers
self.entry = self.parse_line("a")
self.rawentry = self.entry
Expand Down Expand Up @@ -128,23 +144,19 @@ def parse_line(self, line):
activity = sum(self.movlist)/len(self.movlist)
if (1 < 0.5):
os.system("xscreensaver-command -activate &") ##If there is little movement ... activate the screensaver
# Play a sound file that changes with distance
# Update the frame of data for scale
self.frameCO2 = [co2] + self.frameCO2[:-1]
self.frameDUST = [dust] + self.frameDUST[:-1]
self.frameTEMP = [t2] + self.frameTEMP[:-1]
# Calculate the max/min for each stream only for valid data lines
if (indx>0):
self.maxCO2 = max(self.frameCO2)
self.minCO2 = min(self.frameCO2)
self.maxDUST = max(self.frameDUST)
self.minDUST = min(self.frameDUST)
self.maxTEMP = max(self.frameTEMP)
self.minTEMP = min(self.frameTEMP)
# C D E F G A B
print(distance)
#if (distance < 30) & (distance>0):
#os.system('mpg123 -q C.mp3 &')
#elif distance < 45:
#os.system('mpg123 -q D.mp3 &')
#elif distance < 60:
#os.system('mpg123 -q E.mp3 &')
#elif distance < 75:
#os.system('mpg123 -q F.mp3 &')
#elif distance < 90:
#os.system('mpg123 -q G.mp3 &')
#elif distance < 105:
#os.system('mpg123 -q A.mp3 &')
#elif distance < 120:
#os.system('mpg123 -q B.mp3 &')
#else:
#os.system('mpg123 -q silence.mp3 &')
return (indx, dust, distance, t1, t1, co2, co, activity, co_st)
# 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
return (indx, dust, distance, t1, t1, co2, co, activity, co_st, self.minCO2, self.maxCO2, self.minDUST, self.maxDUST, self.minTEMP, self.maxTEMP)
23 changes: 8 additions & 15 deletions air1/templates/bars.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,25 @@
</center>
<div class="gridster">
<ul>
<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
<li data-row="1" data-col="4" data-sizex="1" data-sizey="1">
<div class="widget_bar">
<h1>Temperature</h1>
<div id="temperature_widget" style="background-color: #0000ff"></div>
</div>
</li>
<li data-row="1" data-col="3" data-sizex="1" data-sizey="1">
<li data-row="1" data-col="2" data-sizex="1" data-sizey="1">
<div class="widget_bar">
<h1>Dust</h1>
<div id="dust_widget" style="background-color: #008000"></div>
</div>
</li>
<li data-row="1" data-col="5" data-sizex="1" data-sizey="1">
<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
<div class="widget_bar">
<h1>CO2</h1>
<div id="co2_widget" style="background-color: #800080"></div>
</div>
</li>
<li data-row="1" data-col="2" data-sizex="1" data-sizey="1">
<div class="widget_bar">
<h1>Movement</h1>
<div id="movement_widget" style="background-color: #ffff00"></div>
</div>
</li>
<li data-row="1" data-col="4" data-sizex="1" data-sizey="1">
<li data-row="1" data-col="3" data-sizex="1" data-sizey="1">
<div class="widget_bar">
<h1>Distance</h1>
<div id="distance_widget" style="background-color: #ffa500"></div>
Expand All @@ -62,7 +56,7 @@ <h1>Distance</h1>
// start gridster
$('.gridster ul').gridster({
widget_margins: [5, 5],
widget_base_dimensions: [330, 1000],
widget_base_dimensions: [400, 1000],
max_cols: 5
});

Expand Down Expand Up @@ -138,10 +132,9 @@ <h1>Distance</h1>
setValue('co_status', data[key][8]);
setValue('movement', data[key][7]);

setProgressBarHeight("temperature_widget", data[key][4], 10, 40, '#0000ff');
setProgressBarHeight("dust_widget", data[key][1], 600, 1200, '#008000');
setProgressBarHeight("co2_widget", data[key][5], -1200,-700, '#800080');
setProgressBarHeight("movement_widget", data[key][7], 0, 1, '#ffff00');
setProgressBarHeight("temperature_widget", data[key][4], data[key][13], data[key][14], '#0000ff');
setProgressBarHeight("dust_widget", data[key][1], data[key][11], data[key][12], '#008000');
setProgressBarHeight("co2_widget", data[key][5], data[key][9],data[key][10], '#800080');
setProgressBarHeight("distance_widget", data[key][2], 10, 120, '#ffa500');
if (data[key][2] < 30 && data[key][2] > 0) {
document.getElementById("audiosource").setAttribute("src", '{{ static_url("sounds/C.mp3") }}');
Expand Down
115 changes: 43 additions & 72 deletions air1/templates/co2.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,26 @@
<title>air 1</title>
<link rel="stylesheet" href="{{ static_url("jquery.gridster.css") }}" type="text/css"/>
<link rel="stylesheet" href="{{ static_url("app.css") }}" type="text/css"/>
<script src="script_min.js"></script>
</head>
<body style="background-color: black; margin: 0;">
<body style="background-color: black; margin: 0;" onload="setTimeout('init();', 100);">
<center>
<div><img id="mjpeg_dest" /></div>
</center>
<div class="gridster">
<ul>
<li data-row="1" data-col="1" data-sizex="1" data-sizey="1" id="temperature_widget" style="background-color: #f1c40f">
<div class="widget">
<img style="display: inline-block; vertical-align: middle; width: 128px; height: 128px;" src="{{ static_url('images/0101-sun-smile-glasses-icon_128.png') }}" id="temperature_image" />
<li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
<div class="widget_bar">
<h1>CO2</h1>
<div id="co2_widget" style="background-color: #800080"></div>
</div>
</li>
<li data-row="1" data-col="2" data-sizex="1" data-sizey="1" id="dust_widget" style="background-color: #2c3e50">
<div id="particles-js" width="940px" height="510px" style="width: 940px; height: 510px; min-height: 510px;"></div>
</li>
<li data-row="2" data-col="1" data-sizex="1" data-sizey="1" id="co2_widget" style="background-color: #ecf0f1">
<div class="widget">
<img src="{{ static_url("co2.png") }}" id="co2_image" />
</div>
</li>
<li data-row="2" data-col="2" data-sizex="1" data-sizey="1" id="movement_widget" style="background-color: #3498db">
<video width="100%" height="100%" id="movement_video">
<source src="{{ static_url("jake.mp4") }}" type="video/mp4" id="movement_video_source" />
<object data="{{ static_url("jake.mp4") }}" width="100%" height="100%" id="movement_video_object"></object>
</video>
</li>
</ul>
</ul>
</div>
<audio id="audiosource">
<source type="audio/mp3" />
Your browser does not support the audio element.
</audio>
</body>
<script src="{{ static_url("jquery.min.js") }}" type="text/javascript"></script>
<script src="{{ static_url("jquery.gridster.js") }}" type="text/javascript"></script>
Expand All @@ -42,14 +37,9 @@
$(function() { // only when the page has loaded and jQuery is ready
// start gridster
$('.gridster ul').gridster({
widget_margins: [10, 10],
widget_base_dimensions: [940, 510],
max_cols: 2
});

// start particles-js
particlesJS.load('particles-js', '{{ static_url("particles.json") }}', function() {
console.log('callback - particles.js config loaded');
widget_margins: [5, 5],
widget_base_dimensions: [1000, 1000],
max_cols: 5
});

var isopen = false;
Expand Down Expand Up @@ -93,54 +83,20 @@
});
};

var setCo2InElement = function(id, value) {
var setProgressBarHeight = function(id, value, min, max, color) {
var element = document.getElementById(id);
if (undefined !== element && null !== element) {
// TODO: remove duplication; see setTemperatureThermometer
var inputLow = 800;
var inputHigh = 1100;
var inputLow = min;
var inputHigh = max;

var outputLow = 100;
var outputHigh = 500;
var outputLow = 0;
var outputHigh = 100;

var result = ((value - inputLow) / (inputHigh - inputLow)) * (outputHigh - outputLow) + outputLow;
var rounded = Number(result).toFixed(2);

element.setAttribute('height', '' + rounded + 'px');
}
};

var setTemperatureImage = function(id, value) {
var coldThreshold = 25;
var element = document.getElementById(id);
if (undefined !== element && null !== element) {
if (value < coldThreshold) {
element.setAttribute('src', '{{ static_url("images/0302-snow-snowflakes-icon_128.png") }}');
element.parentElement.parentElement.setAttribute('style', 'background-image: #2980b9;');
} else {
element.setAttribute('src', '{{ static_url("images/0101-sun-smile-glasses-icon_128.png") }}');
element.parentElement.parentElement.setAttribute('style', 'background-color: #f1c40f');
}
}
};

var playVideo = function(id, value) {
var movementThreshold = 100;
var element = document.getElementById(id);
if (undefined !== element && null !== element) {
if (value < movementThreshold) {
element.pause();
} else {
element.play();
}
}
};

var updateParticles = function(amount) {
window.pJSDom[0].pJS.particles.number.value = (amount/100)^3;
window.pJSDom[0].pJS.fn.particlesEmpty();
window.pJSDom[0].pJS.fn.particlesCreate();
//window.pJSDom[0].pJS.fn.particlesRefresh();
element.setAttribute('style', 'height: ' + rounded + '%; width: 100%; background-color: ' + color + ';');
}
};

var onHeartbeat = function(data) {
Expand All @@ -158,10 +114,11 @@
setValue('co_status', data[key][8]);
setValue('movement', data[key][7]);

setCo2InElement('co2_image', data[key][5]);
setTemperatureImage('temperature_image', data[key][4]);
playVideo('movement_video', data[key][7]);
updateParticles(data[key][1]);
setProgressBarHeight("co2_widget", data[key][5], data[key][9],data[key][10], '#800080');
if (data[key][5]>=data[key][10]) {
document.getElementById("audiosource").setAttribute("src", '{{ static_url("sounds/win.mp3") }}');
document.getElementById("audiosource").setAttribute("autoplay", "autoplay");
}
}
}
};
Expand All @@ -175,6 +132,20 @@
socket = null;
isopen = false;
}
// For the camera
var mjpeg_img;
function reload_img () {
mjpeg_img.src = "cam_pic.php?time=" + new Date().getTime();
}
function error_img () {
setTimeout("mjpeg_img.src = 'cam_pic.php?time=' + new Date().getTime();", 100);
}
function init() {
mjpeg_img = document.getElementById("mjpeg_dest");
mjpeg_img.onload = reload_img;
mjpeg_img.onerror = error_img;
reload_img();
}

// Handling actions in the UI
// $('#my_button').click(function() {
Expand Down
6 changes: 1 addition & 5 deletions air1/templates/distance.html
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,7 @@ <h1>Distance</h1>
setValue('co2', data[key][5]);
setValue('co_status', data[key][8]);
setValue('movement', data[key][7]);

setProgressBarHeight("temperature_widget", data[key][4], 10, 40, '#0000ff');
setProgressBarHeight("dust_widget", data[key][1], 600, 1200, '#008000');
setProgressBarHeight("co2_widget", data[key][5], -1200,-700, '#800080');
setProgressBarHeight("movement_widget", data[key][7], 0, 1, '#ffff00');

setProgressBarHeight("distance_widget", data[key][2], 10, 120, '#ffa500');
if (data[key][2] < 30 && data[key][2] > 0) {
document.getElementById("audiosource").setAttribute("src", '{{ static_url("sounds/C.mp3") }}');
Expand Down
54 changes: 8 additions & 46 deletions air1/templates/dust.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
</li>
</ul>
</div>
<audio id="audiosource">
<source type="audio/mp3" />
Your browser does not support the audio element.
</audio>
</body>
<script src="{{ static_url("jquery.min.js") }}" type="text/javascript"></script>
<script src="{{ static_url("jquery.gridster.js") }}" type="text/javascript"></script>
Expand Down Expand Up @@ -77,49 +81,6 @@
});
};

var setCo2InElement = function(id, value) {
var element = document.getElementById(id);
if (undefined !== element && null !== element) {
// TODO: remove duplication; see setTemperatureThermometer
var inputLow = 800;
var inputHigh = 1100;

var outputLow = 100;
var outputHigh = 500;

var result = ((value - inputLow) / (inputHigh - inputLow)) * (outputHigh - outputLow) + outputLow;
var rounded = Number(result).toFixed(2);

element.setAttribute('height', '' + rounded + 'px');
}
};

var setTemperatureImage = function(id, value) {
var coldThreshold = 25;
var element = document.getElementById(id);
if (undefined !== element && null !== element) {
if (value < coldThreshold) {
element.setAttribute('src', '{{ static_url("images/0302-snow-snowflakes-icon_128.png") }}');
element.parentElement.parentElement.setAttribute('style', 'background-image: #2980b9;');
} else {
element.setAttribute('src', '{{ static_url("images/0101-sun-smile-glasses-icon_128.png") }}');
element.parentElement.parentElement.setAttribute('style', 'background-color: #f1c40f');
}
}
};

var playVideo = function(id, value) {
var movementThreshold = 100;
var element = document.getElementById(id);
if (undefined !== element && null !== element) {
if (value < movementThreshold) {
element.pause();
} else {
element.play();
}
}
};

var updateParticles = function(amount) {
window.pJSDom[0].pJS.particles.number.value = (amount/100)^3;
window.pJSDom[0].pJS.fn.particlesEmpty();
Expand All @@ -142,10 +103,11 @@
setValue('co_status', data[key][8]);
setValue('movement', data[key][7]);

setCo2InElement('co2_image', data[key][5]);
setTemperatureImage('temperature_image', data[key][4]);
playVideo('movement_video', data[key][7]);
updateParticles(data[key][1]);
if (data[key][1]>=data[key][12]) {
document.getElementById("audiosource").setAttribute("src", '{{ static_url("sounds/win.mp3") }}');
document.getElementById("audiosource").setAttribute("autoplay", "autoplay");
}
}
}
};
Expand Down
Loading

0 comments on commit 9f1b7ea

Please sign in to comment.