diff --git a/app/js/device/CC2650/cc2650_accelerometer.js b/app/js/device/CC2650/cc2650_accelerometer.js index d724221..c7edec7 100644 --- a/app/js/device/CC2650/cc2650_accelerometer.js +++ b/app/js/device/CC2650/cc2650_accelerometer.js @@ -115,6 +115,7 @@ CC2650_ACCEL = function(p) { this.startService = function() { + this.maxLength = 255; if (this.deviceID !== null) { console.log('Starting CC2650 Accelerometer Service on ', this.deviceID); @@ -154,6 +155,114 @@ CC2650_ACCEL = function(p) { }; + this.advancedGraphFFT = function(mode, data, subID) { + var xstep; + var scalePos; + var lm; + var ceiling; + var elm; + var text2ID; + var ceilingLimit; + var calcArray; + var floor; + var _subID; + var _data; + var text1ID; + var lineID; + var max; + + var reducer = function(p, v) { + return (Math.abs(p) > Math.abs(v) ? Math.abs(p) : Math.abs(v)); + }; + + + var parts = ['x', 'y', 'z']; + var _newData = {x: [],y: [],z: []}; + + _data = data || this.data; + + _subID = subID || ''; + + // LineID = [this.frameID , _subID , '-line'].join(''); + text1ID = [this.frameID, _subID, '-txt1'].join(''); + text2ID = [this.frameID, _subID, '-txt2'].join(''); + ceiling = 0; + if (_data.x.length > 0) { + + max = 2; + + for (var lineMode = 0; lineMode < parts.length; lineMode++) { + + + lm = parts[lineMode]; + + var data = new complex_array.ComplexArray(_data[lm]); + + + data.FFT(); + + data.forEach(function(c_value, i) { + ceiling = reducer(c_value.real ,ceiling); + _newData[lm].push(c_value.real); + }); + + //Ceiling = _data[lm].reduce(reducer); + + console.log('ceiling:', ceiling); + + + } + + if (ceiling > 500) { + max = (ceiling > max) ? (Math.ceil((Math.round(ceiling) + 1) / 50) * 50) : max; + } else { + max = (ceiling > max) ? (Math.ceil((Math.round(ceiling) + 1) / 10) * 10) : max; + } + ceiling = max; + + floor = ceiling * -1; + ceilingLimit = ceiling; + console.log('ceiling:',ceiling); + + scalePos = (124 / 2) / ceiling; + + xstep = (680 - 46) / this.maxLength; + + //Var xstep = 2.34; + + for (lineMode = 0; lineMode < parts.length; lineMode++) { + + lm = parts[lineMode]; + var startX = 46 + (this.maxLength - _newData[lm].length) * xstep; + + calcArray = []; + + lineID = this.frameID + _subID + '-' + lm + '-line'; + for (var x = 0; x < _newData[lm].length; x++) { + + calcArray.push((startX + (x * xstep)).toFixed(2) + ',' + (71 - ((_newData[lm][x]) * scalePos)).toFixed( + 2)); + + } + + elm = document.getElementById(lineID); + + elm.setAttribute('points', calcArray.join(' ')); + + } + + elm = document.getElementById(text1ID); + elm.textContent = ceilingLimit; + + elm = document.getElementById(text2ID); + elm.textContent = floor; + + } + + this.previousCeil = ceiling; + }; + + this.advancedGraph = function(mode, data, subID) { var xstep; @@ -212,14 +321,14 @@ CC2650_ACCEL = function(p) { scalePos = (124 / 2) / ceiling; - xstep = (680 - 46) / 100; + xstep = (680 - 46) / this.maxLength; //Var xstep = 2.34; for (lineMode = 0; lineMode < parts.length; lineMode++) { lm = parts[lineMode]; - var startX = 46 + (100 - _data[lm].length) * xstep; + var startX = 46 + (this.maxLength - _data[lm].length) * xstep; calcArray = []; @@ -252,7 +361,7 @@ CC2650_ACCEL = function(p) { // Nothing to animate yet // return -1; - this.advancedGraph(0, this.data.gyro, 'gyro'); + this.advancedGraphFFT(0, this.data.gyro, 'gyro'); this.advancedGraph(0, this.data.accel, 'accel'); this.advancedGraph(0, this.data.mag, 'mag'); // This.simpleGraph(this.data.temp, 'temp'); diff --git a/app/js/standards/capability.js b/app/js/standards/capability.js index 7c108a8..ac9eab6 100644 --- a/app/js/standards/capability.js +++ b/app/js/standards/capability.js @@ -45,6 +45,7 @@ var CAPABILITY = function(p) { this.target = null; this.$frame = null; + this.maxLength = 99; this.previousCeil = 0; @@ -114,7 +115,7 @@ CAPABILITY.prototype.storeData = function(data, alt) { } var target = alt || this.data; - if (target.length === 99) { + if (target.length === this.maxLength) { target = target.slice(1); } diff --git a/gulpfile.js b/gulpfile.js index 2e38c35..d6b8d6a 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -70,10 +70,17 @@ gulp.task('devices', function() { .pipe(gulp.dest('www/js')); }); +/* + + + + */ gulp.task('vendor', function() { return gulp.src(['app/libs/jquery/dist/jquery.min.js', 'app/libs/mui/packages/cdn/js/mui.min.js', - 'app/libs/ejs/ejs_production.js']) + 'app/libs/ejs/ejs_production.js', + 'app/libs/jsfft/complex_array.js', + 'app/libs/jsfft/fft.js']) .pipe(concat('vendor.js')) .pipe(uglify({mangle: false})) .pipe(gulp.dest('www/libs')); diff --git a/platforms/android/.gradle/2.2.1/taskArtifacts/cache.properties.lock b/platforms/android/.gradle/2.2.1/taskArtifacts/cache.properties.lock index 2792132..d061909 100644 Binary files a/platforms/android/.gradle/2.2.1/taskArtifacts/cache.properties.lock and b/platforms/android/.gradle/2.2.1/taskArtifacts/cache.properties.lock differ diff --git a/platforms/android/.gradle/2.2.1/taskArtifacts/fileHashes.bin b/platforms/android/.gradle/2.2.1/taskArtifacts/fileHashes.bin index 81da1bf..5102f1f 100644 Binary files a/platforms/android/.gradle/2.2.1/taskArtifacts/fileHashes.bin and b/platforms/android/.gradle/2.2.1/taskArtifacts/fileHashes.bin differ diff --git a/platforms/android/.gradle/2.2.1/taskArtifacts/fileSnapshots.bin b/platforms/android/.gradle/2.2.1/taskArtifacts/fileSnapshots.bin index 1655560..85a3161 100644 Binary files a/platforms/android/.gradle/2.2.1/taskArtifacts/fileSnapshots.bin and b/platforms/android/.gradle/2.2.1/taskArtifacts/fileSnapshots.bin differ diff --git a/platforms/android/.gradle/2.2.1/taskArtifacts/taskArtifacts.bin b/platforms/android/.gradle/2.2.1/taskArtifacts/taskArtifacts.bin index 550ce22..4f62d15 100644 Binary files a/platforms/android/.gradle/2.2.1/taskArtifacts/taskArtifacts.bin and b/platforms/android/.gradle/2.2.1/taskArtifacts/taskArtifacts.bin differ diff --git a/www/js/index.js b/www/js/index.js deleted file mode 100644 index 6056a88..0000000 --- a/www/js/index.js +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* global mui, bt_company_ids, ble, LocalFileSystem, capabilityManager, MANUFACTUREDECODER */ - -var app; -app = { - mode: 0, stop: false, log: {}, activeServices: {}, - - list: {}, foundDevices: {}, - - manufactureDecoder: new MANUFACTUREDECODER(), // Application Constructor - initialize: function() { - this.bindEvents(); - }, - - arrayBufferToIntArray: function(buffer) { - var result; - - if (buffer) { - var typedArray = new Uint8Array(buffer); - result = []; - for (var i = 0; i < typedArray.length; i++) { - result[i] = typedArray[i]; - } - } - - return result; - }, - - parseAdvertisingData: function(bytes) { - var length; - var type; - var data; - var i = 0; - var advertisementData = {}; - - while (length !== 0) { - - length = bytes[i] & 0xFF; - i++; - - type = bytes[i] & 0xFF; - i++; - - data = bytes.slice(i, i + length - 1); // Length includes type byte, but not length byte - i += length - 2; // Move to end of data - i++; - - advertisementData[type] = data; - } - - return advertisementData; - }, handle255: function(buffer) { - 'use strict'; - - var company; - var cid; - var manID; - var bin = buffer; - var decoded = {}; - - console.log('Block255', bin); - manID = app.manufactureDecoder.getManID(bin); - - console.log('ManID:', manID); - - cid = '0x' + manID; - - company = bt_company_ids.find(cid); - - switch (manID) { - case '004C': { - decoded = app.manufactureDecoder.decodeIbeacon(bin); - decoded.company = company; - break; - } - case '1235': { - decoded = app.manufactureDecoder.decodeSiliconLabsSensorPuck(bin); - decoded.company = company; - break; - - } - case '0060': { - decoded = app.manufactureDecoder.decodeSansible(bin); - decoded.company = company; - break; - - } - default: { - console.log('Unknown manID: ', manID); - decoded = {company: company}; - - } - } - return decoded; - }, makeHexBuffer: function(buffer) { - 'use strict'; - return buffer.map(function(i) { - return ('00' + i.toString(16)).slice(-2) + ','; - }); - }, makeChars: function(buffer) { - 'use strict'; - return buffer.map(function(i) { - return String.fromCharCode(i); - }); - }, calculateDistance: function(txPower, rssi) { - - // If there is 0 txPower then default it to -12dBm which appears to be a general default. - - var _txPower = (txPower !== 0) ? txPower : -12; - - var ratio_db = _txPower - rssi; - var ratio_linear = Math.pow(10, ratio_db / 10); - - return Math.sqrt(ratio_linear); - - }, /** - * - * @param device - * @param device.rssi - * @param device.otherData - * @param device.id - * @param device.name - * @param device.rssiBuffer - * @returns {jQuery|HTMLElement|*} - */ - - buildNewDeviceResultPanel: function(device) { - 'use strict'; - var dString; - var accuracy; - var avg; - var sum; - var newPanel, newRow; - var otherData = device.otherData; - var newId = 'd-' + device.id.replace(/:/g, '').split('-')[0]; - var title = device.hasOwnProperty('name') ? device.name : '*** Unknown'; - - newPanel = $('
', - {id: newId, class: 'mui-panel deviceRow', style: 'min-height:75px;'}); - - newRow = $('
', {class: 'mui-row'}); - - newRow.append($('
', - {class: 'mui-col-xs-12 mui--text-title', text: device.id})); - - newPanel.append(newRow); - - newRow = $('
', {class: 'mui-row'}); - newRow.append($('
', {class: 'mui-col-xs-3', text: 'Name:'})); - newRow.append($('
', {class: 'mui-col-xs-3', text: title})); - - if (typeof otherData !== 'undefined' && otherData !== null && otherData.hasOwnProperty( - 'txpower')) { - if (device.hasOwnProperty('rssiBuffer') && (device.rssiBuffer.length > 0)) { - sum = device.rssiBuffer.reduce(function(a, b) { return a + b; }); - avg = sum / device.rssiBuffer.length; - accuracy = app.calculateDistance(otherData.txpower, avg); - } else { - accuracy = app.calculateDistance(otherData.txpower, device.rssi); - } - - dString = (accuracy <= 30.00) ? accuracy.toFixed(2) + ' m' : 'Far'; - newRow.append($('
', {class: 'mui-col-xs-3', text: 'Distance:'})); - newRow.append($('
', {class: 'mui-col-xs-3', text: dString})); - - } else { - newRow.append($('
', {class: 'mui-col-xs-3', text: 'RSSI:'})); - newRow.append($('
', - {class: 'mui-col-xs-3', text: device.rssi + ' dB'})); - - } - - newPanel.append(newRow); - - if (typeof otherData !== 'undefined' && otherData !== null) { - if (otherData.hasOwnProperty('msg')) { - newRow = $('
', {class: 'mui-row'}); - newRow.append($('
', {class: 'mui-col-xs-3', text: 'Details:'})); - newRow.append($('
', {class: 'mui-col-xs-8', text: otherData.msg})); - newPanel.append(newRow); - } - } - - return newPanel; - }, extractPData: function(prev) { - 'use strict'; - - if (typeof prev === 'undefined' || prev === null) { - return {}; - } - return prev.pData; - - }, extractRSSIBuffer: function(prev) { - 'use strict'; - - if (typeof prev === 'undefined' || prev === null) { - return []; - } - return prev.rssiBuffer; - - }, - - processPData: function(newData, oldData) { - 'use strict'; - var output = {}; - var wa = []; - if (newData === null || newData.data === null) { - return {}; - } - - for (var key in newData.data) { - - if (newData.data.hasOwnProperty(key)) { - - if (Object.keys(oldData).indexOf(key) !== -1) { - wa = oldData[key]; - } - - if (wa.length === 99) { - wa = wa.slice(1); - } - - wa.push(newData.data[key]); - - output[key] = wa; - } - } - - return output; - }, processRSSIData: function(rssi, oldBuffer) { - 'use strict'; - if (typeof oldBuffer === 'undefined' || oldBuffer === null) { - return []; - } - var wa = oldBuffer; - - if (wa.length === 10) { - wa = wa.slice(1); - } - - wa.push(rssi); - - return wa; - }, doScan: function(mode) { - 'use strict'; - app.mode = mode; - $('#ripple').show(); - if (mode !== 2) { - $('#tbody').empty(); - } - - ble.startScan([], app.foundDevice.bind(this), function(e) { - console.error(e); - }); - - var _t = [5000, 60000, 200][mode]; - - setTimeout(ble.stopScan, _t, app.scanComplete, function() { - console.log('stopScan failed'); - $('#ripple').hide(); - }); - - }, populateObject: function(source, dest) { - var rObj = dest; - for (var item in source) { - if (source.hasOwnProperty(item)) { - rObj[item] = source[item]; - } - } - - return rObj; - }, - /** - * - * @param device - * @param device.advertising - * @param device.rssi - * @param device.id - */ - - foundDevice: function(device) { - var rssiBuffer; - var oldRSSIBuffer; - var newPData; - var oldPdata; - var parsed; - var hexBuffer; - var advertBuffer; - var newTR; - var newId = 'd-' + device.id.replace(/:/g, '').split('-')[0]; - var _device = app.foundDevices[newId] || {}; - var $newID; - var otherData; - - _device = app.populateObject(device, _device); - // _device.pData = {}; - - otherData = null; - this.list[newId] = _device.id; - - if (_device.hasOwnProperty('advertising')) { - - advertBuffer = app.arrayBufferToIntArray(_device.advertising); - - hexBuffer = app.makeHexBuffer(advertBuffer); - - parsed = app.parseAdvertisingData(advertBuffer); - - if (parsed.hasOwnProperty('9')) { - - var name = app.makeChars(parsed['9']); - - _device.name = name.join(''); - console.log('Name: ', name.join('')); - - } - - if (parsed.hasOwnProperty('255')) { - - otherData = app.handle255(parsed['255']); - console.log(otherData); - _device.otherData = otherData; - } - _device.advertBuffer = advertBuffer; - _device.hexBuffer = hexBuffer; - _device.parsed = parsed; - } - - // OldPdata = app.extractPData(app.log[newId]); - oldPdata = app.extractPData(_device); - - newPData = app.processPData(otherData, oldPdata); - - // OldRSSIBuffer = app.extractRSSIBuffer(app.log[newId]); - oldRSSIBuffer = app.extractRSSIBuffer(_device); - rssiBuffer = app.processRSSIData(_device.rssi, oldRSSIBuffer); - - _device.pData = newPData; - _device.rssiBuffer = rssiBuffer; - - newTR = app.buildNewDeviceResultPanel(_device); - - $newID = $('div#' + newId); - if ($newID.length > 0) { - $newID.replaceWith(newTR); - } else { - $('#scanResults').append(newTR); - } - - app.log[newId] = _device; - app.foundDevices[newId] = _device; - - console.log(JSON.stringify(_device)); - - }, scanComplete: function() { - console.log('Scan complete'); - - if (app.mode === 1) { - app.saveLog(); - $('#ripple').hide(); - } - - if (app.mode === 2) { - if (!app.stop) { - setTimeout(function() { - app.doScan(2); - }.bind(this), 200); - } else { - app.saveLog(); - $('#ripple').hide(); - } - - } - - }, writeFile: function(fileEntry, dataObj) { - // Create a FileWriter object for our FileEntry (log.txt). - fileEntry.createWriter(function(fileWriter) { - - fileWriter.onwriteend = function() { - console.log('Successful file write...'); - // ReadFile(fileEntry); - }; - - fileWriter.onerror = function(e) { - console.error('Failed file write: ' + e.toString()); - }; - - // If data object is not passed in, - // create a new Blob instead. - if (!dataObj) { - dataObj = new Blob(['some file data'], {type: 'text/plain'}); - } - - fileWriter.write(dataObj); - }); - }, saveLog: function() { - 'use strict'; - var dt = new Date().toISOString().replace(/:|-/g, '').replace(/(\.\w+)/g, - ''); - var payload = JSON.stringify(app.log); - var filename = 'sensortoy-' + dt + '.json'; - - // Var dataObj = new Blob(payload, { type: 'text/plain' }); - window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function(fs) { - - console.log('file system open: ' + fs.name); - fs.root.getFile(filename, - {create: true, exclusive: false}, - function(fileEntry) { - - console.log('fileEntry is file?' + fileEntry.isFile.toString()); - // FileEntry.name == 'someFile.txt' - // fileEntry.fullPath == '/someFile.txt' - console.log('Path: ', fileEntry.fullPath); - app.writeFile(fileEntry, payload); - - app.log = []; - - }, - app.onError); - - }, app.onError); - }, forceStop: function() { - 'use strict'; - app.stop = true; - $('#scan').show(); - $('#stop').hide(); - }, - - // Bind Event Listeners - // - // Bind any events that are required on startup. Common events are: - // 'load', 'deviceready', 'offline', and 'online'. - bindEvents: function() { - var self = this; - document.addEventListener('deviceready', this.onDeviceReady, false); - $('#scan').on('click', function() { - 'use strict'; - this.stop = false; - this.doScan(2); - $('#scan').hide(); - $('#stop').show(); - }.bind(this)); - - $('#stop').on('click', function() { - 'use strict'; - app.forceStop(); - - }.bind(this)); - - $('#longScan').on('click', function() { - 'use strict'; - this.doScan(1); - }.bind(this)); - - $('#scanResults').on('click', 'div.mui-panel.deviceRow', function() { - 'use strict'; - var tID = $(this).context.id; - var id = self.list[tID]; - - console.log(tID, id); - - app.forceStop(); - self.connect(id); - }); - - }, addTab: function(tID) { - var appTabs = $('#app-tabs'); - var panes = $('#tab-panes'); - - var paneID = 'pane-' + tID; - - var _device = app.foundDevices[tID]; - var _name = _device.name || _device.id; - - console.log('Found:', _device); - - $('
', {class: 'mui-tabs__pane', id: paneID}).appendTo(panes); - - var li = $('
  • ').append($('', - {'data-mui-toggle': 'tab', 'data-mui-controls': paneID, text: _name})); - - appTabs.append(li); - - return paneID; - - }, - - // Deviceready Event Handler - // - // The scope of 'this' is the event. In order to call the 'receivedEvent' - // function, we must explicitly call 'app.receivedEvent(...);' - onDeviceReady: function() { - - }, - - doAnimate: function() { - for (var item in app.activeServices) { - if (app.activeServices.hasOwnProperty(item)) { - var activeService = app.activeServices[item]; - for (var t = 0; t < activeService.length; t++) { - activeService[t].animateGraph(); - } - } - } - window.requestAnimFrame(app.doAnimate.bind(this)); - }, connect: function(deviceId) { - - $('#results').slideUp(); - console.log('Connect to ', deviceId); - - var tID = 'd-' + deviceId.replace(/:/g, '').split('-')[0]; - - /** - * - * @param a - * @param a.services - */ - var onConnect = function(a) { - var services = []; - - services = a.services; - - console.log('Searching services for ', tID); - var usedServices = []; - - var target = app.addTab(tID); - - var _params = { - deviceID: deviceId, target: target - }; - - for (var t = 0; t < services.length; t++) { - - var ident = services[t].toUpperCase(); - - var SERVICE = capabilityManager.discover(ident); - - if (SERVICE !== null) { - - var newService = new SERVICE(_params); - newService.startService(); - usedServices.push(newService); - } else { - console.error('Unknown service: ', ident); - } - - } - - app.activeServices[tID] = usedServices; - - mui.tabs.activate(target); - window.requestAnimFrame(app.doAnimate.bind(this)); - }; - - if (!app.activeServices.hasOwnProperty(tID)) { - - ble.connect(deviceId, onConnect, function(e) { - 'use strict'; - console.log(e); - console.error(e); - - }); - - } - - }, onError: function(reason) { - console.error('ERROR: ' + reason); // Real apps should use notification.alert - } -}; - -window.requestAnimFrame = (function() { - return window.requestAnimationFrame || - window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || - function(callback) { - window.setTimeout(callback, 1000 / 60); - }; -})(); - -app.initialize();