Commit fa478c42 authored by cjandl's avatar cjandl
Browse files

Carma for Desktop

parents
letter frequency
A .08167
B .01492
C .02782
D .04253
E .12702
F .02288
G .02015
H .06094
I .06966
J .00153
K .00772
L .04025
M .02406
N .06749
O .07507
P .01929
Q .00095
R .05987
S .06327
T .09056
U .02758
V .00978
W .02360
X .00150
Y .01974
Z .00074
This diff is collapsed.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="client/style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.6/css/materialize.min.css">
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
</head>
<body>
<div class="section " id="index-banner">
<div class="container">
<br><br>
<h3 class="header center orange-text">Sonigait-Desktop</h3>
<br><br>
</div>
</div>
<div class="container">
<div id="subscription"><p>Verfügbare Geräte (Bitte 2 auswählen): </p></div>
<div id="list" class="col s24">
<!-- List of available Carmas -->
</div>
<br>
<input type="button" value="Connect" id="connectBtn">
<input type="button" value="Disconnect" id="disconnectBtn">
<input type="button" value="Reload" id="reloadBtn"><br>
<div id="visuals">
<div class="col s24">
<div class="card-panel blue lighten-2" style="height:400px;">
<div style="width:45%; float:right;">
<h5>Sohle rechts</h5>
<svg class="chart" style="width:100%"></svg>
</div>
<div style="width:45%; float:left;">
<h5>Sohle links</h5>
<svg class="chart2" style="width:100%"></svg>
</div>
<br><br>
</div>
</div>
<div class="col s24">
<div class="card-panel blue lighten-3">
<br><br>
<div class="graph">
<svg class="linegraph"></svg>
</div>
<br><br>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.6/js/materialize.min.js"></script>
<script src="http://cdn.socket.io/socket.io-1.4.5.js"></script>
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="//d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="client/js/client.js"></script>
<script src="https://code.jquery.com/jquery-latest.js"></script>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</body>
</html>
var socket = io.connect();
var initValue = 2000;
var dataArray = [initValue, initValue, initValue, initValue, initValue, initValue,initValue];
var width = 800
var barHeight = 40;
var sum = 0,
sum1 = 0;
var peripherals = [];
var barX = d3.scale.linear()
//.domain([0, 1600])
.domain([0, 800])
.range([0, width]);
// Sohle 1
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", barHeight * dataArray.length-1);
// Sohle 2
var chart2 = d3.select(".chart2")
.attr("width", width)
.attr("height", barHeight * dataArray.length-1);
var counter = 0;
var counter2 = 0;
var limit = 60 * 1,
duration = 750,
now = new Date(Date.now() - duration)
var width = 800,
height = 200
var groups = {
current: {
value: sum1,
color: 'orange',
data: d3.range(limit).map(function() {
return 0
})
},
target: {
value: sum,
color: 'green',
data: d3.range(limit).map(function() {
return 0
})
}
}
var x = d3.time.scale()
.domain([now - (limit - 2), now - duration])
.range([0, width])
var y = d3.scale.linear()
.domain([0, 5000])
.range([height, 0])
var line = d3.svg.line()
.interpolate('basis')
.x(function(d, i) {
return x(now - (limit - 1 - i) * duration)
})
.y(function(d) {
return y(d)
})
var svg = d3.select('.linegraph')
.attr('class', 'chart')
.attr('width', width)
.attr('height', height + 50)
var axis = svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(x.axis = d3.svg.axis().scale(x).orient('bottom'))
var paths = svg.append('g')
for (var name in groups) {
var group = groups[name]
group.path = paths.append('path')
.data([group.data])
.attr('class', name + ' group')
.style('stroke', group.color)
}
// Graphics are hidden until connected with de CARMAS
$(visuals).hide();
//---------------Socket.IO
socket.on('data', function(msg) {
console.log(msg.length);
if(msg.length > 9) {
// Liste füllen zur Auswahl der Sohlen
peripherals = JSON.parse(msg);
console.log(peripherals);
makeList(peripherals);
}
// linke Sohle
if(msg[7] == 0){
drawBarChart(msg);
counter++;
if (counter == 20) {
drawLine(msg);
counter = 0;
}
}
//rechte Sohle
if(msg[7] == 1){
drawBarChart2(msg);
counter2++;
if (counter2 == 20) {
drawLine(msg);
counter2 = 0;
}
}
});
// Draw Line in Linechart------------------------------
function drawLine(sensordata) {
var summe = 0;
for (var i = 0; i < 7; i++) {
summe = summe + sensordata[i];
}
if(sensordata[7] == 0){
sum1 = summe;
groups.current.value = summe;
groups.current.path.attr('d', line);
}
else{
sum = summe;
groups.target.value = summe;
groups.target.path.attr('d', line);
}
// Add new values
for (var name in groups) {
var group = groups[name]
group.data.push(group.value) // Real values arrive at irregular intervals
//group.data.push(20 + Math.random() * 10)
group.path.attr('d', line)
}
now = new Date()
x.domain([now - (limit - 2) * duration, now - duration])
// Slide x-axis left
axis.transition()
.duration(duration)
.ease('linear')
.call(x.axis)
// Slide paths left
paths.attr('transform', null)
.transition()
.duration(duration)
.ease('linear')
.attr('transform', 'translate(' + x(now - (limit - 1) * duration) + ')')
.each('end', drawLine)
// Remove oldest data point from each group
for (var name in groups) {
var group = groups[name]
group.data.shift()
}
}
//----------------------Bar Chart 1
function drawBarChart(sensordata) {
chart.selectAll("g").remove();
var bar = chart.selectAll("g")
.data(sensordata)
.enter().append("g")
.attr("transform", function(d, i) {
return "translate(0," + i * barHeight + ")";
});
bar.append("rect")
.attr("width", barX)
.attr("height", barHeight - 10);
bar.append("text")
.attr("x", function(d) {
return barX(d) - 3;
})
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) {
return d;
});
}
//----------------------Bar Chart 2
function drawBarChart2(sensordata) {
chart2.selectAll("g").remove();
var bar2 = chart2.selectAll("g")
.data(sensordata)
.enter().append("g")
.attr("transform", function(d, i) {
return "translate(0," + i * barHeight + ")";
});
bar2.append("rect")
.attr("width", barX)
.attr("height", barHeight - 10);
bar2.append("text")
.attr("x", function(d) {
return barX(d) - 3;
})
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) {
return d;
});
}
// Liste aller verfügbaren Geräte
function makeList(array) {
$(list).empty();
root = $(list);
var fieldset = $("<fieldset class='col s24'></fieldset>");
root.append(fieldset);
console.log(JSON.toString(array[i]));
for (var i = 0; i < array.length; i++) {
if(array!= null) {
var namestring = array[i].name;
var stringID = array[i].id;
}
var input = $("<input type='checkbox' id= " + stringID + " name='connect' value=" + stringID + ">");
var label = $("<label for=" + stringID + ">" + namestring + "</label>");
var br = $("<br>");
fieldset.append(input);
fieldset.append(label);
fieldset.append(br);
}
}
//----------------------------connectBtn
//send ids OF CARMAS to server
$(connectBtn).click(function() {
var connectWith = [];
$(visuals).show();
// checkboxen auslesen
for (var i = 0; i < peripherals.length; i++) {
var checked = $('#' + peripherals[i].id).is(':checked') // Boolean true
console.log(checked);
if(checked == true){
connectWith.push(peripherals[i].id);
}
}
if (connectWith.length > 2 || connectWith.length < 2 ){
alert("Es müssen 2 Geräte ausgewählt sein ! Es sind " + connectWith.length + "verbunden");
}else {
console.log("Verbinde mit " + connectWith);
if (socket != null) {
socket.emit('connectWith', connectWith);
}
}
})
$(disconnectBtn).click(function() {
if (socket != null) {
socket.emit('connectWith', "disconnect");
}
// nach 2 Sekunden neu laden
setTimeout(location.reload(), 2000);
})
$(reloadBtn).click(function() {
location.reload();
})
\ No newline at end of file
.chart rect {
fill: steelblue;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: end;
}
.graph .axis {
stroke-width: 1;
}
.graph .axis .tick line {
stroke: black;
}
.graph .axis .tick text {
fill: black;
font-size: 0.7em;
}
.graph .axis .domain {
fill: none;
stroke: black;
}
.graph .group {
fill: none;
stroke: black;
stroke-width: 1.5;
}
#feedback { font-size: 1.4em; }
#selectable .ui-selecting { background: #FECA40; }
#selectable .ui-selected { background: #F39814; color: white; }
#selectable { list-style-type: none; margin: 0; padding: 0; width: 60%; }
#selectable li { margin: 3px; padding: 0.4em; font-size: 1.4em; height: 18px; }
\ No newline at end of file
var noble = require('noble');
var express = require('express');
var app = express();
var server = require('http').Server(app);
var io = require('socket.io')(server);
var osc = require('osc-min');
var dgram = require("dgram");
var multiplier = require('./soledata.json');
var pressureValues = []; // pressureValues[7] = 0 (right) 1 (left)
var peripheralAbleToConnect = [];
var peripheralIdOrAddress,peripheralIdOrAddress2;
var peripheralLeft ,peripheralRight;
var characteristicLeft, characteristicRight;
var pheripheralLeftFactors = [], pheripheralRightFactors = [];
var peripherals = [];// alle gefundenen GeräteIDs
// OSC Stream
var udp = dgram.createSocket("udp4");
//var outport = 41234;
// ---------------Socket IO------------------------------------------------------------
app.use(express.static(__dirname));
server.listen(3000);
var ioSocket;
app.get('/', function(request, respond) {
respond.sendFile(__dirname + '/client/index.html');
});
// verfügbare Geräteliste an website schicken
io.sockets.on('connection', function(socket) {
ioSocket = socket;
sendPeripherals();
});
// von Client ausgewählte CARMAS
io.on('connection', function(socket){
socket.on('connectWith', function(msg){
peripheralIdOrAddress = msg[0];
peripheralIdOrAddress2 = msg[1];
if(msg == "disconnect") {
// ruft Methode in Callback auf
peripheralLeft.disconnect();
}
// in verfügbaren Geräten suchen und verbinden
for(var i =0; i < peripheralAbleToConnect.length; i++) {
if (peripheralAbleToConnect[i].id === peripheralIdOrAddress || peripheralAbleToConnect[i].address === peripheralIdOrAddress) {
peripheralLeft = peripheralAbleToConnect[i];
// Multiplikationsfaktoren für einelene Sensoren auslesen
pheripheralLeftFactors = findMultiplier(peripheralLeft.advertisement.localName);
}
if (peripheralAbleToConnect[i].id === peripheralIdOrAddress2 || peripheralAbleToConnect[i].address === peripheralIdOrAddress2) {
peripheralRight = peripheralAbleToConnect[i];
// Multiplikationsfaktoren für einelene Sensoren auslesen
pheripheralRightFactors = findMultiplier(peripheralRight.advertisement.localName);
}
}
if(msg != "disconnect"){
// 2 Karmas gefunden - jetzt mit beiden verbinden
if (peripheralLeft && peripheralRight) {
console.log("Found Both devices !");
noble.stopScanning();
setTimeout(function () {
explore(peripheralLeft);
}, 100);
setTimeout(function () {
explore(peripheralRight);
}, 100);
}
}
});
});
// Noble Implementation -----------------------------------------------------------------
noble.on('stateChange', function(state) {
if (state === 'poweredOn') {
noble.startScanning();
} else {
noble.stopScanning();
}
});
// wird jedesmal aufgerufen, wenn ein Pheripheriegerät gefunden wird während dem Scannen
noble.on('discover', function (peripheral) {
var advertisement = peripheral.advertisement;
var substring = "Soni";
var peri = {
"name": advertisement.localName,
"id": peripheral.id
}
console.log("SoleId: " + advertisement.localName);
if(advertisement.localName && advertisement.localName.indexOf(substring) != -1) {
peripherals.push(peri);
console.log("peripheral pushed");
}
peripheralAbleToConnect.push(peripheral);
});
// verfügbare Pheripheriegeräte an Client senden
function sendPeripherals() {
//console.log(peripherals);
if (ioSocket != null) {
ioSocket.emit('data', JSON.stringify(peripherals));
console.log("data sent! " + JSON.stringify(peripherals));
}
}
// mit Peripheriegerät verbinden
function explore(peripheral) {
peripheral.connect(function (error) {
if(error) {
// console.log('Unknown Error' + error);
return;
}
console.log(peripheral.state + peripheral.id);
peripheral.discoverAllServicesAndCharacteristics(function (error, services, characteristics) {
services.forEach(function (service) {
// console.log('found service:', service.uuid);
if (service.uuid == '713d0000503e4c75ba943148f18d941e') {
}
});
characteristics.forEach(function (characteristic) {
//console.log(characteristic.uuid);
if (characteristic.uuid == '713d0002503e4c75ba943148f18d941e') {
// console.log('global to delete it easier !');
characteristicLeft = characteristic;
characteristic.notify(true, function (error) {
});
characteristic.on('data', function (data, isNotification) {
pressureValues[0] = ((data[4] & 0xFF) << 4) | ((data[5] >> 4) & 0xF);
pressureValues[1] = ((data[5] & 0xF) << 8) | (data[6] & 0xFF);
pressureValues[2] = ((data[7] & 0xFF) << 4) | ((data[8] >> 4) & 0xF);
pressureValues[3] = ((data[8] & 0xF) << 8) | (data[9] & 0xFF);
pressureValues[4] = ((data[10] & 0xFF) << 4) | ((data[11] >> 4) & 0xF);
pressureValues[5] = ((data[11] & 0xF) << 8) | (data[12] & 0xFF);
pressureValues[6] = ((data[13] & 0xFF) << 4) | ((data[14] >> 4) & 0xF);
if(peripheral.id === peripheralLeft.id) {
// console.log("Left Sole: " + pressureValues);