simpleSA/data/index2.html

1265 lines
37 KiB
HTML
Raw Normal View History

<!--
This application is loosly based on the code found here:
Repository: https://github.com/krzychb/EspScopeA0
Version: Delta
Flie: index.htm
Revision: 0.1.0
Date: 10-Jul-2016
Author: krzychb at gazeta.pl
Copyright (c) 2016 Krzysztof Budzynski. All rights reserved.
This modified version takes the samples from the TinySA
spectrum analyser and displays in a web page.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-->
<!DOCTYPE html>
<html>
<head>
<title>TinySA-ESP</title>
<link rel="stylesheet" type="text/css" href="styles.css">
<!-- get file below from http://canvasjs.com/ -->
<script type="text/javascript" src="canvasjs.min.js"></script>
<script type="text/javascript" src="jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="support.js"></script>
</head>
<body style="min-width:100vw">
<div class='norm'>
<button id="homeButton" onclick="window.location.href='index.html';">Home</button>
<!-- <button id="settingsButton" onclick="window.location.href='settings.html';">Settings</button>
<button id="backupRestoreButton" onclick="window.location.href='backupRestore.html';">Backup/Restore</button>
// <button id="helpButton" onclick="window.location.href='help.html';">Help</button> -->
<button id="aboutButton" onclick="window.location.href='about.html';">About</button>
</div>
<div class ="Grid">
<div class = "Grid-cell" id="chartSA" ></div>
<br />
<div class = "Grid-cell-side" id="postSweepSettings" >
<!--<form style="width: 90vw; margin-left: 80px" action="doSetSweep" method="get"> -->
<h1>Sweep</h1>
<div class="setting" >
<label for="setStart" class="setting-label">Start:</label>
<input class="value-input" name='setStart' type="number" id="setStart" maxlength="9" min="0" max="350" required>
MHz
</div>
<div class="setting" >
<label for="setStop" class="setting-label">Stop:</label>
<input class="value-input" name='setStop' type="number" id ="setStop" maxlength="9" min="0" max="350" required>
MHz
</div>
<br />
<div class="setting" >
<label for="setCenter" class="setting-label">Centre:</label>
<input class="value-input" name='setCenter' type="number" id ="setCenter" maxlength="9" min="0" max="350" required>
MHz
</div>
<div class="setting" >
<label for="setSpan" class="setting-label">Span:</label>
<!--<select class="select-input" id="setSpan" name="setSpan">
<option class="select-option" value="250">250</option>
<option class="select-option" value="100">100</option>
<option class="select-option" value="50">50</option>
<option class="select-option" value="20">20</option>
<option class="select-option" value="10">10</option>
<option class="select-option" value="4">4</option>
<option class="select-option" value="2">2</option>
<option class="select-option" value="1">1</option>
<option class="select-option" value="0.5">0.5</option>
</select> -->
<input class="value-input" name='setSpan' type="number" id ="setSpan" maxlength="9" min="0" max="350" step="0.1" required>
MHz
</div>
<!--
<label class="setting-label">Width:</label>
<input class="value-input" name='setWidth' type="text" id ="setWidth" placeholder="width" maxlength="9" min="0" max="250" required>
MHz
</div> -->
<br />
<!-- <div style="width:180px; display: inline-block">Ext gain:<input style = "width:100px" name='setExtGain' type="text" placeholder="extGain" maxlength="9" min="-100" max="40" required></div> -->
<div id="signal_info">
<div class="setting" >
<label class="setting-label">RBW:</label>
<input class="value-display" type="text" disabled="1" id="actRBW" size="1" value="300" />
kHz
</div>
</div>
<div class="setting" >
<label for="setRBW" class="setting-label">RBW:</label>
<select class="select-input" id="setRBW" name="setRBW"></select>
kHz
</div>
<!-- <div style="width:150px; display: inline-block">
<button type="submit">Update</button>
</div> -->
<br />
<div class="setting" >
<label for="setAtten" class="setting-label">Atten:</label>
<input class="value-input" name='setAtten' type="number" step="1" id ="setAtten" maxlength="3" min="0" max="31" required>
<!--<select class="select-input" id="setAtten" name="setAtten"></select> -->
dB
</div>
<br />
<div class="setting" >
<label for="setRefOut" class="setting-label">Reference:</label>
<select class="select-input" id="setRefOut" name="setRefOut">
<option class="select-option" value="-1">Off</option>
<option class="select-option" value="0">30</option>
<option class="select-option" value="1">15</option>
<option class="select-option" value="2">10</option>
<option class="select-option" value="3">4</option>
<option class="select-option" value="4">3</option>
<option class="select-option" value="5">2</option>
<option class="select-option" value="6">1</option>
</select>
MHz
</div>
<br />
<div id="spur">
<div class="setting" >
<label class="setting-label">Spur Reduction:</label>
<input class="value-input" type="checkbox" id="spurReduction" size="1" value="0" />
</div>
</div>
<div id="tracking">
<div class="setting" >
<label class="setting-label">TrackGen:</label>
<input class="value-input" type="checkbox" id="trackGen" size="1" value="0" />
<input class="value-input" type="number" id="setTrackGenPower" placeholder="setTrackGenPower" maxlength = "9" min="-60" max="20" value="0" />
dBm
</div>
</div>
<br />
<div id="signal_info">
<div class="setting" >
<label class="setting-label">Points:</label>
<input class="value-display" type="text" disabled="1" id="sweepPoints" size="1" value="65000" />
<label class="setting-label">Time:</label>
<input class="value-display" type="text" disabled="1" id="sweepTime" size="1" value="290" />
ms
</div>
</div>
<div id="store">
<div class = "setting" >
<label class="setting-label">Store:</label>
<input class="checkbox-input" type="checkbox" id="store1" size="1" value="0" />
<input class="checkbox-input" type="checkbox" id="store2" size="1" value="0" />
<input class="checkbox-input" type="checkbox" id="store3" size="1" value="0" />
<input class="checkbox-input" type="checkbox" id="store4" size="1" value="0" />
</div>
</div>
<!-- form for device settings -->
<hr />
<h1>Settings</h1>
<div class="setting" >
<label for="levelOffset" class="setting-label">Offset:</label>
<input class="value-display" type="text" disabled="1" id="levelOffset" size="1" value="10" />
dB
</div>
<div class="setting" >
<button class = "set-button" type="submit" id="setActPower">Set Actual</button>
<input class="value-input" type="number" id="setPowerValue" placeholder="setPowerValue" maxlength = "9" min="-60" max="20" value="0" />
dBm
</div>
<br />
<div class="setting" >
<label for="setLODrive" class="setting-label">LO Drive:</label>
<select class="select-input" id="setLODrive" name="setLODrive">
<option class="select-option" value="0">-1</option>
<option class="select-option" value="1">2</option>
<option class="select-option" value="2">5</option>
<option class="select-option" value="3">8</option>
<option class="select-option" value="4">11</option>
<option class="select-option" value="5">14</option>
<option class="select-option" value="6">17</option>
<option class="select-option" value="7">20</option>
</select>
dBm
</div>
<div class="setting" >
<label for="setPreAmp" class="setting-label">Pre-amp:</label>
<select class="select-input" id="setPreAmp" name="setPreAmp">
<option value="96">Auto</option> <!--0x60 Auto -->
<option value="0">5</option> <!--0x00 LNA Min 5dB-->
<option value="1">8</option> <!--0x01 -->
<option value="2">11</option> <!--0x02 -->
<option value="3">14</option> <!--0x03 -->
<option value="4">17</option> <!--0x04 -->
<option value="5">20</option> <!--0x05 -->
<option value="6">23</option> <!--0x06 -->
<option value="7">27</option> <!--0x07 -->
<option value="8">30</option> <!--0x08 -->
<option value="16">25</option> <!--0x10 LNA Max 25dB-->
<option value="17">28</option> <!--0x11 -->
<option value="18">31</option> <!--0x12 -->
<option value="19">34</option> <!--0x13 -->
<option value="20">37</option> <!--0x14 -->
<option value="21">40</option> <!--0x15 -->
<option value="22">43</option> <!--0x16 -->
<option value="23">46</option> <!--0x17 -->
<option value="24">49</option> <!--0x18 -->
</select>
dB
</div>
<div class="setting" >
<label for="setIF" class="setting-label">IF:</label>
<input class="value-input" type="number" id="setIF" size="1" value="433.92" min="433" max=435 step=0.01 />
MHz
</div>
<div class="setting" >
<label for="Average" class="setting-label">Average:</label>
<input class="value-input" type="number" id="Average" size="1" value="10" min="2" max=100 step=1 />
</div>
</div>
<!--</form> -->
</div>
<!-- Below chart (hopefully!) -->
<div class = "Grid">
<div class = "Grid-cell-connection" id="status" >
<hr />
<div id="connection-status">
<form onsubmit="return false;">
<div style="width: 400px; display: inline-block">Host:
<input type="text" id="hostName" value="ws://hostName:81" style="width:160px;"/>
<input type="button" value="Connect" onclick="connect(hostName.value)" />
<input type="button" value="Disconnect" onclick="disconnect()" />
</div>
<div style="width: 250px; display: inline-block">Status:
<input type="text" id="connectionStatus" value="Idle" style="border: 0" />
</div>
<div style="width: 100px; display: inline-block">Pings:
<input type="text" id="connectionPings" size="3" value="-" style="border: 0" />
</div>
<div style="width: 100px; display: inline-block">Refresh Interval:
<input class="value-input" type="number" id="refreshInterval" size="3" min="100" max="3000" value="500" />
</div>
</form>
</div>
<!-- <input class="message-display" type="text" disabled="1" id="message" size="1" value="json message" /> -->
</div>
</div>
<script type="text/javascript">
var refreshInterval = document.getElementById('refreshInterval');
var sweepStart = document.getElementById('sweepStart');
var sweepStop = document.getElementById('sweepStop');
var setStart = document.getElementById('setStart');
var setStop = document.getElementById('setStop');
var setCenter = document.getElementById('setCenter');
var setSpan = document.getElementById('setSpan');
var setAtten = document.getElementById('setAtten');
var setActPower = document.getElementById('setActPower');
var levelOffset = document.getElementById('levelOffset');
var setRefOut = document.getElementById('setRefOut');
var sweepPoints = document.getElementById('sweepPoints');
var sweepTime = document.getElementById('sweepTime');
var setSpur = document.getElementById('spurReduction');
var actRBW = document.getElementById('actRBW');
var setRBW = document.getElementById('setRBW');
var setDrive = document.getElementById('setLODrive');
var setIF = document.getElementById('setIF');
var setPreAmp = document.getElementById('setPreAmp');
var setAverage = document.getElementById('Average');
var setTrackGen = document.getElementById('trackGen');
var setTrackGenPower = document.getElementById('setTrackGenPower');
var store1 = document.getElementById('store1');
var store2 = document.getElementById('store2');
var store3 = document.getElementById('store3');
var store4 = document.getElementById('store4');
//var messageWindow = document.getElementById('message');
var tempCenter;
// initialise these to silly values to force an update first time round
var oldSweepStart = -1;
var oldSweepStop = -1;
var oldSweepCenter = -1;
var oldSetRefOut = -2;
var oldSetRBW = -10;
var oldLevelOffset = 1000;
var oldAttenuation = 1000;
var oldDrive = -1;
var oldIF = 0;
var oldPreAmp = 0;
var oldSweepPoints = 0;
var oldSpur = 2;
var oldTrackGen = 2;
var oldTrackGenPower = 1000;
// Chart configuration - Scope
var RSSISamples = [
{y:10},
{y:11},
{y:12},
{y:13},
{y:14},
{y:15},
{y:16},
{y:17},
{y:18},
]; // dummy for test
var dBSamples = [
{y:-10},
{y:-20},
{y:-23},
{y:-90},
{y:-120},
{y:-100},
{y:-80},
{y:-30},
{y:-40},
]; // dummy for test
var gainSamples = [
{x:0, y:42},
{x:10, y:43},
{x:20, y:44},
{x:30, y:45},
{x:40, y:46},
{x:50, y:47},
{x:80, y:48},
{x:90, y:49},
{x:100, y:40},
]; // dummy for test
var store1Samples = [
{x:0, y:42},
{x:10, y:43},
{x:20, y:44},
{x:30, y:45},
{x:40, y:46},
{x:50, y:47},
{x:80, y:48},
{x:90, y:49},
{x:100, y:40},
];
var store2Samples = [
{x:0, y:42},
{x:10, y:43},
{x:20, y:44},
{x:30, y:45},
{x:40, y:46},
{x:50, y:47},
{x:80, y:48},
{x:90, y:49},
{x:100, y:40},
];
var store3Samples = [
{x:0, y:42},
{x:10, y:43},
{x:20, y:44},
{x:30, y:45},
{x:40, y:46},
{x:50, y:47},
{x:80, y:48},
{x:90, y:49},
{x:100, y:40},
];
var store4Samples = [
{x:0, y:42},
{x:10, y:43},
{x:20, y:44},
{x:30, y:45},
{x:40, y:46},
{x:50, y:47},
{x:80, y:48},
{x:90, y:49},
{x:100, y:40},
];
var chartSA = new CanvasJS.Chart("chartSA",
{
animationEnabled: false,
zoomEnabled: true,
zoomType: "xy",
//height:800,
title: {
text: "ESP32 TinySA",
fontSize: 28
},
axisX: {
title: "Frequency (MHz)",
titleFontSize: 24,
crosshair: {
enabled:true
},
stripLines:[
{
startValue:434.12,
thickness:1,
color:"#d8d8d8",
}
]
},
axisY:
{
title: "dB",
titleFontSize: 24,
minimum: -120,
crosshair: {
enabled:true
},
stripLines:[
{
startValue:-33,
endValue:-30,
color:"#d8d8d8",
}
]
},
axisY2: [
{
title: "RSSI",
titleFontSize: 24,
minimum: 0,
maximum: 255
},
{
title: "Gain",
titleFontSize: 24,
minimum: 0,
maximum: 50
}],
exportEnabled: true,
legend: {
cursor: "pointer",
itemclick: function (e) {
//console.log("legend click: " + e.dataPointIndex);
//console.log(e);
if (typeof (e.dataSeries.visible) === "undefined" || e.dataSeries.visible) {
e.dataSeries.visible = false;
} else {
e.dataSeries.visible = true;
}
e.chart.render();
}
},
data: [
{
type: "line",
name: "dB",
dataPoints : dBSamples,
showInLegend : true
},
{
type: "line",
name: "RSSI",
axisYType: "secondary",
dataPoints : RSSISamples,
showInLegend : true,
visible : false
},
{
type: "line",
name: "gain",
axisYType: "secondary",
axisYIndex: 1,
dataPoints : gainSamples,
showInLegend : true,
visible : false
},
{
type: "line",
name: "average",
dataPoints : dBSamples,
showInLegend : true,
visible : false
},
{
type: "line",
name: "min",
dataPoints : dBSamples,
showInLegend : true,
visible : false
},
{
type: "line",
name: "store1",
dataPoints : store1Samples,
showInLegend : true,
visible : false
},
{
type: "line",
name: "store2",
dataPoints : store2Samples,
showInLegend : true,
visible : false
},
{
type: "line",
name: "store3",
dataPoints : store3Samples,
showInLegend : true,
visible : false
},
{
type: "line",
name: "store4",
dataPoints : store4Samples,
showInLegend : true,
visible : false
}
]
});
renderChart();
// Add handlers for the change events in the input fields
setStart.addEventListener('change', (event) => {
sendValue("a", setStart.value);
});
setStop.addEventListener('change', (event) => {
sendValue("b", setStop.value);
});
setCenter.addEventListener('change', (event) => {
sendValue("c", setCenter.value);
});
setLODrive.addEventListener('change', (event) => {
if ((setLODrive.value >=0) && (setLODrive.value <= 7))
sendValue("d", setLODrive.value);
});
setIF.addEventListener('change', (event) => {
sendValue("i", setIF.value);
});
setRefOut.addEventListener('change', (event) => {
sendValue("o", setRefOut.value);
});
setActPower.addEventListener('click', (event) => {
sendValue("p", setPowerValue.value);
});
setSpan.addEventListener('change', (event) => {
sendValue("s", setSpan.value);
});
setAtten.addEventListener('change', (event) => {
sendValue("A", setAtten.value);
});
setRBW.addEventListener('change', (event) => {
sendValue("R", setRBW.value);
});
setPreAmp.addEventListener('change', (event) => {
if (setPreAmp.value == "96") {
sendValue("g", setPreAmp.value);
} else {
sendValue("g", setPreAmp.selectedOptions[0].text);
}
});
setSpur.addEventListener('change', (event) => {
if (setSpur.checked) {
sendValue("S", 1);
} else {
sendValue("S", 0);
}
});
setTrackGen.addEventListener('change', (event) => {
if (setTrackGen.checked) {
sendValue("t", 1);
} else {
sendValue("t", 0);
}
});
store1.addEventListener('change', (event) => {
if (store1.checked) {
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
chartSA.options.data[5].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
let rObj = {}
rObj.x = obj.x
rObj.y = obj.y/2+b
return rObj
})
} else {
chartSA.options.data[5].dataPoints.length = 2; // reset
}
});
store2.addEventListener('change', (event) => {
if (store2.checked) {
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
chartSA.options.data[6].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
let rObj = {}
rObj.x = obj.x
rObj.y = obj.y/2+b
return rObj
})
} else {
chartSA.options.data[6].dataPoints.length = 2; // reset
}
});
store3.addEventListener('change', (event) => {
if (store3.checked) {
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
chartSA.options.data[7].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
let rObj = {}
rObj.x = obj.x
rObj.y = obj.y/2+b
return rObj
})
} else {
chartSA.options.data[7].dataPoints.length = 2; // reset
}
});
store4.addEventListener('change', (event) => {
if (store4.checked) {
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
chartSA.options.data[8].dataPoints = chartSA.options.data[1].dataPoints.map(obj => {
let rObj = {}
rObj.x = obj.x
rObj.y = obj.y/2+b
return rObj
})
} else {
chartSA.options.data[8].dataPoints.length = 2; // reset
}
});
//var roundtripTime = document.getElementById('roundtripTime');
//var messageCount = document.getElementById('messageCount');
//var missedReplies = document.getElementById('missedReplies');
var messageCounter = 0;
var missedMessageCounter = 0;
var messageSendMilis;
var connection;
var connectionStatus = document.getElementById('connectionStatus');
var hostName = document.getElementById('hostName');
var pingCounter = 0;
var sendPingVar;
var dateObject;
/*
* Timed update of chart render to reduce load on slow smartphones or tablets
*/
function renderChart()
{
chartSA.render();
setTimeout(renderChart, refreshInterval.value);
}
//messageCount.value = messageCounter;
//missedReplies.value = missedMessageCounter;
hostName.value = "ws://" + location.host + ":81";
// connect to TinySA server
connect(hostName.value);
// At this point the page is running
$(document).ready(function () {
update();
var chartUpdateVar;
// chartUpdateVar = setInterval(renderChart, 500);
});
var initDone = false;
var indexUpdateMilliSeconds = 1 * 1000;
function handleSettings (settings)
{
actRBW.value = settings.bandwidth;
levelOffset.value = settings.levelOffset;
// console.log("levelOffset=" + settings.levelOffset);
if (settings.start/1000 != oldSweepStart) {
//console.log("Start:" + settings.start + " Stop:" + settings.stop + " oldStart:" + oldSweepStart);
//sweepStart.value = settings.start/1000;
setStart.value = settings.start/1000; // change default if changed
oldSweepStart = setStart.value;
setSpan.value = (settings.stop - settings.start)/1000;
}
if (settings.stop/1000 != oldSweepStop) {
//sweepStop.value = settings.stop/1000;
setStop.value = settings.stop/1000; // change default if changed
oldSweepStop = setStop.value;
setSpan.value = (settings.stop - settings.start)/1000;
}
tempCenter = ( (parseFloat(settings.stop) - parseFloat(settings.start) )/2 + parseFloat(settings.start) ) / 1000; // calculate center
if (tempCenter != oldSweepCenter) {
setCenter.value = tempCenter;
oldSweepCenter = tempCenter;
}
if (settings.attenuation != oldAttenuation) {
setAtten.value = settings.attenuation;
oldAttenuation = settings.attenuation;
}
if (settings.setRBW != oldSetRBW) {
setRBW.value = settings.setRBW;
oldSetRBW = settings.setRBW;
}
if (settings.RefOut != oldSetRefOut) {
setRefOut.value = settings.RefOut; // reference output dropdown
oldSetRefOut = settings.RefOut;
}
if (settings.Drive != oldDrive) {
setLODrive.value = settings.Drive; // LO Drive dropdown
oldDrive = settings.Drive;
}
if (settings.IF != oldIF) {
setIF.value = settings.IF; // IF value
oldIF = settings.IF;
}
if (settings.PreAmp != oldPreAmp) {
setPreAmp.value = settings.PreAmp; // PreAmp Gain value
oldPreAmp = settings.PreAmp;
}
if (settings.spur != oldSpur) {
if (settings.spur) {
spurReduction.checked = true; // Spur reduction checkbox
} else {
spurReduction.checked = false; // Spur reduction checkbox
}
oldSpur = settings.spur;
}
if (settings.tg != oldTrackGen) {
if (settings.tg) {
setTrackGen.checked = true; // Tracking Generator checkbox
} else {
setTrackGen.checked = false; // Tracking Generator checkbox
}
oldTrackGen = settings.tg;
}
if (settings.tgPower != oldTrackGenPower) {
setTrackGenPower.value = settings.tgPower;
oldTrackGenPower = settings.tgPower;
}
chartSA.options.axisX.minimum = setStart.value;
chartSA.options.axisX.maximum = setStop.value;
initDone = false;
}
function handleData (data)
{
if (data.sweepPoints != sweepPoints.value) {
// reset chart data
chartSA.options.data[0].dataPoints.length = 2;
chartSA.options.data[1].dataPoints.length = 2;
chartSA.options.data[3].dataPoints.length = 2;
sweepPoints.value = data.sweepPoints;
}
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
//chartSA.options.data[0].dataPoints = data.Points; // First series dB
chartSA.options.data[0].dataPoints = data.Points.map(obj => {
let rObj = {}
rObj.x = obj.x
rObj.y = obj.y/2+b
return rObj
})
chartSA.options.data[1].dataPoints = data.Points; // RSSI trace
chartSA.options.data[1].axisYType = "secondary";
if ((initDone == 0) || (oldSweepPoints != data.sweepPoints) || (oldDataPointCount != data.Points.length)) {
chartSA.options.data[3].dataPoints = chartSA.options.data[0].dataPoints // first run
initDone = 1;
oldSweepPoints = data.Points.length;
oldDataPointCount = data.Points.length;
}
chartSA.options.data[3].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
let rObj = {}
rObj.x = obj.x
rObj.y = chartSA.options.data[3].dataPoints[index].y*(1-1/setAverage) + obj.y*1/setAverage;
return rObj
})
chartSA.options.axisX.minimum = setStart.value;
chartSA.options.axisX.maximum = setStop.value;
chartSA.options.axisX.stripLines[0].value = setIF.value;
// chartSA.options.axisY.minimum = -120;
// chartSA.options.axisY.maximum = 0;
chartSA.options.axisY2.minimum = 0;
chartSA.options.axisY2.maximum = 255;
// RSSISamples.from(data.Points); // moves data
//console.log(RSSISamples[10].y);
// update the chart
chartSA.render();
}
function handleChunkData (data)
{
var init = false;
var n = data.sweepPoints;
if (n != oldSweepPoints) {
// reset chart data
chartSA.options.data[0].dataPoints.length = 0;
chartSA.options.data[1].dataPoints.length = 0;
chartSA.options.data[2].dataPoints.length = 0;
chartSA.options.data[3].dataPoints.length = 0;
chartSA.options.data[4].dataPoints.length = 0;
// add dummy data points
var i;
for (i=0; i<n; i++) {
var p = {x:250, y:-120};
var q = {x:250, y:0};
var r = {x:250, y:49};
var s = {x:250, y:-120};
var m = {x:250, y:10};
chartSA.options.data[0].dataPoints.push(p); // dB
chartSA.options.data[1].dataPoints.push(q); // RSSI
chartSA.options.data[2].dataPoints.push(r); // gain
chartSA.options.data[3].dataPoints.push(s); // average
chartSA.options.data[4].dataPoints.push(m); // min - initialise to high value
}
//chartSA.options.data[0].dataPoints.length = n; // reduces size if > no of data points
//chartSA.options.data[1].dataPoints.length = n;
//chartSA.options.data[2].dataPoints.length = n;
//chartSA.options.data[3].dataPoints.length = n;
sweepPoints.value = data.sweepPoints;
init = true;
initDone = false;
oldSweepPoints = n;
//chartSA.render();
}
var dataStart = data.StartIndex;
var b = parseInt(levelOffset.value) + parseInt(setAtten.value) - 120;
var a = 1/setAverage.value;
data.Points.forEach (function (point, index) { // copy data into the chart data series
var p = {};
p = point; // create a copy not a reference ??
var f = {};
f = point.x;
chartSA.options.data[1].dataPoints[dataStart + index] = p; // RSSI
chartSA.options.data[0].dataPoints[dataStart + index].x = f * 1;
var dB = p.y/2+b;
chartSA.options.data[0].dataPoints[dataStart + index].y = dB * 1;
//chartSA.options.data[3].dataPoints[dataStart + index] = point;
//try {
//chartSA.options.data[3].dataPoints[dataStart + index].x = f * 1;
// if (initDone) {
// var av = chartSA.options.data[3].dataPoints[dataStart + index].y*(1-a) + dB*a;
// chartSA.options.data[3].dataPoints[dataStart + index].y = av * 1;
// } else {
// chartSA.options.data[3].dataPoints[dataStart + index].y = dB * 1;
// }
//}
//catch {
// chartSA.options.data[3].dataPoints[dataStart + index].y = point.y/2+b;
//}
})
// If end of sweep update the average and min data sets
if (dataStart + data.Points.length >= data.sweepPoints) {
if (!initDone) { // If first time then set the values to current dB series
initDone = true;
chartSA.options.data[3].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
let rObj = {}
rObj.x = obj.x;
rObj.y = obj.y*1;
return rObj
})
chartSA.options.data[4].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
let rObj = {}
rObj.x = obj.x;
rObj.y = obj.y*1;
return rObj
})
} else {
chartSA.options.data[3].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
let rObj = {}
rObj.x = obj.x;
rObj.y = chartSA.options.data[3].dataPoints[index].y*(1-a) + obj.y*a;
return rObj
})
chartSA.options.data[4].dataPoints = chartSA.options.data[0].dataPoints.map((obj, index) => { // average trace
let rObj = {}
rObj.x = obj.x;
rObj.y = Math.min(chartSA.options.data[4].dataPoints[index].y, obj.y);
return rObj
})
}
if (chartSA.options.data[2].visible) {
$.getJSON( "getGainSweep") // proper line
// $.getJSON( "getGainSweep.json") // for local test
.done(function (data) {
// We have the data, process it.
chartSA.options.data[2].dataPoints = data.gainPoints; // Gain trace
});
}
}
//chartSA.render();
// dataPoints.value = chartSA.options.data[0].dataPoints.length;
sweepTime.value = data.sweepTime;
}
function update()
{
// Get the settings
$.getJSON( "getSettings")
.done(function (settings) {
handleSettings(settings);
})
.fail(function(jqxhr, textStatus, error) {
var err = textStatus +", " + error;
console.log("Settings Request Failed: " + err);
});
// Get the sweep data
$.getJSON( "getSweep") // proper line
// $.getJSON( "getSweep.json") // for local test
.done(function (data) {
// We have the data, process it.
handleData(data);
//setTimeout(update, indexUpdateMilliSeconds);
})
.fail(function(jqxhr, textStatus, error) {
var err = textStatus +", " + error;
console.log("Sweep Request Failed: " + err);
});
if (chartSA.options.data[2].visible) {
$.getJSON( "getGainSweep") // proper line
// $.getJSON( "getGainSweep.json") // for local test
.done(function (data) {
// We have the data, process it.
chartSA.options.data[2].dataPoints = data.gainPoints; // Gain trace
});
}
}
/*
// This method is called to add all necessary options to a
// select representing the available resolution bandwidths(RBW).
// default is auto
*/
function buildRBWSelect()
{
let dropdown = $('#setRBW');
dropdown.empty();
// Populate dropdown with list of RBW
$.getJSON("getRbwList", function (data) {
dropdown.append($('<option class="select-option" ></option>').attr('value', 0).text("Auto"));
$.each(data, function (key, bpf) {
dropdown.append($('<option class="select-option" ></option>').attr('value', bpf.bw10).text(bpf.bw));
})
});
//dropdown.prop('selectedIndex', 0);
}
buildRBWSelect();
/*
// This method is called to add all necessary options to a
// select representing the available attenuations.
// default is auto
*/
function buildAttenSelect()
{
let dropdown = $('#setAtten');
dropdown.empty();
// Populate dropdown with list of RBW
$.getJSON("getAttenList", function (data) {
$.each(data, function (key, att) {
dropdown.append($('<option class="select-option" ></option>').attr('value', att.dB).text(att.dB));
})
});
//dropdown.prop('selectedIndex', 0);
}
//buildAttenSelect();
function connect(host)
{
if(connection)
{
//connection.close(); // restart
return; // already connected
}
connectionStatus.value = "Connecting...";
connection = new WebSocket(host, ['arduino']);
connection.onopen = function()
{
connectionStatus.value = "Connected";
connectionStatus.style = "background-color:lightgreen";
connection.send('Hello from Browser :-) ' + new Date());
sendMessage();
sendPingVar = setInterval(function(){ sendPing() }, 30000);
// Get the settings to make sure current
$.getJSON( "getSettings")
.done(function (settings) {
handleSettings(settings);
})
.fail(function(jqxhr, textStatus, error) {
var err = textStatus +", " + error;
console.log("Settings Request Failed: " + err);
});
var items = document.querySelectorAll(".value-input");
var i;
for (i = 0; i< items.length; i++) {
items[i].disabled = false;
}
var items = document.querySelectorAll(".select-input");
var i;
for (i = 0; i< items.length; i++) {
items[i].disabled = false;
}
};
connection.onclose = function(event)
{
clearInterval(sendPingVar);
connectionStatus.value = "Disconnected";
connectionStatus.style = "background-color:red";
//connection.removeEventListeners();
connection = null;
// Disable user input
var items = document.querySelectorAll(".value-input");
var i;
for (i = 0; i< items.length; i++) {
items[i].disabled = true;
}
var items = document.querySelectorAll(".select-input");
var i;
for (i = 0; i< items.length; i++) {
items[i].disabled = true;
}
};
connection.onerror = function(error)
{
console.log("WebSocket Error ", error);
};
connection.onmessage = function(message) // to be used later when we send data at each sweep
{
//console.log("Websocket message received");
// show message
//messageWindow.value = message.data;
//messageSize.value = message.data.length;
// check only messages begining with '{'
if(message.data[0] == "{")
{
// //console.log("Parsing message");
myObject = JSON.parse(message.data);
//console.log("message type " + myObject.mType);
if (myObject.mType == "Settings")
{
pointsCount = myObject.dispPoints;
// sweepSamples = myObject.Points;
//console.log("handle settings");
handleSettings(myObject);
}
else if (myObject.mType == "fullSweep")
{
//console.log("handle full Sweep");
handleData(myObject);
}
else if (myObject.mType == "chunkSweep")
{
console.log("handle chunk Sweep:" + myObject.StartIndex);
handleChunkData(myObject);
}
else
{
console.log("Invalid json message type");
}
}
};
}
function disconnect()
{
if(connection)
{
connection.close();
}
else
{
connectionStatus.value = "Not connected yet";
}
}
function sendValue(c, val)
{
//
// Message format
// #(code) value where code is a single char. Case is important
// a start freq (MHz)
// b stop frequency
// c centre frequency
// s Span
// d Local Oscillator Drive
// g PreAmpGain/Mode
// p set actual power to peak value
// i IF frequency
// o RefOut
// A internal attenuation (PE4302)
// E external gain ( eg attenuator(-ve) or preamp(+ve) )
// R requested RBW
// S Spur reduction Off/On
// t trackGen Off/On/Fixed
// T trackGen output level
//
//connection.send("# " + messageCounter + " " + sampleThreshold + " " + sampleSize);
connection.send("#" + c + " " + val);
console.log("Command:" + c + val);
}
function sendMessage()
{
messageCounter++;
//messageCount.value = messageCounter;
dateObject = new Date();
messageSendMilis = dateObject.getTime();
//
// Message format
// # MESSAGE_NUMBER SAMPLE_THRESHOLD NUMBER_OF_SAMPLES
//
//connection.send("# " + messageCounter + " " + sampleThreshold + " " + sampleSize);
connection.send("# " + messageCounter + " " + sweepStart + " " + sweepStop);
}
function sendPing()
{
connection.send('ping');
pingCounter++;
connectionPings.value = pingCounter;
}
</script>
</body>
</html>