diff --git a/api/maxhold.js b/api/maxhold.js
new file mode 100644
index 0000000..e3b1425
--- /dev/null
+++ b/api/maxhold.js
@@ -0,0 +1,77 @@
+const http = require('http');
+
+var nCpi = 10;
+var map = [];
+var maxhold = '';
+var timestamp = '';
+const options_timestamp = {
+ host: '127.0.0.1',
+ path: '/timestamp',
+ port: 3000
+};
+const options_map = {
+ host: '127.0.0.1',
+ path: '/map',
+ port: 3000
+};
+
+function process(matrixArray) {
+
+ const result = [];
+
+ for (let i = 0; i < matrixArray[0].length; i++) {
+ const row = [];
+ for (let j = 0; j < matrixArray[0][0].length; j++) {
+ let maxVal = matrixArray[0][i][j];
+ for (let k = 1; k < matrixArray.length; k++) {
+ maxVal = Math.max(maxVal, matrixArray[k][i][j]);
+ }
+ row.push(maxVal);
+ }
+ result.push(row);
+}
+
+ return result;
+}
+
+function update_data() {
+
+ // check if timestamp is updated
+ http.get(options_timestamp, function(res) {
+ res.setEncoding('utf8');
+ res.on('data', function (body) {
+ if (timestamp != body)
+ {
+ timestamp = body;
+ http.get(options_map, function(res) {
+ let body_map = '';
+ res.setEncoding('utf8');
+ res.on('data', (chunk) => {
+ body_map += chunk;
+ });
+ res.on('end', () => {
+ try {
+ maxhold = JSON.parse(body_map);
+ map.push(maxhold.data);
+ if (map.length > nCpi) {
+ map.shift();
+ }
+ maxhold.data = process(map);
+ } catch (e) {
+ console.error(e.message);
+ }
+ });
+ });
+ }
+ });
+ });
+
+};
+
+setInterval(update_data, 100);
+
+function get_data() {
+ return maxhold;
+};
+
+module.exports.get_data = get_data;
\ No newline at end of file
diff --git a/api/server.js b/api/server.js
index a2f3f63..8cb4e29 100644
--- a/api/server.js
+++ b/api/server.js
@@ -2,6 +2,9 @@ const express = require('express');
const dgram = require('dgram');
const net = require("net");
+var maxhold = require('./maxhold.js');
+module.exports = Object.assign({}, maxhold)
+
// constants
const PORT = 3000;
const HOST = '0.0.0.0';
@@ -33,6 +36,9 @@ app.get('/detection', (req, res) => {
app.get('/timestamp', (req, res) => {
res.send(timestamp);
});
+app.get('/maxhold', (req, res) => {
+ res.send(maxhold.get_data());
+});
// read state of capture
app.get('/capture', (req, res) => {
res.send(capture);
diff --git a/html/maxhold/index.html b/html/maxhold/index.html
new file mode 100644
index 0000000..35a6432
--- /dev/null
+++ b/html/maxhold/index.html
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/html/maxhold/plot_maxhold.js b/html/maxhold/plot_maxhold.js
new file mode 100644
index 0000000..a3fd2b5
--- /dev/null
+++ b/html/maxhold/plot_maxhold.js
@@ -0,0 +1,166 @@
+var nRows = 3;
+var nCols = 3;
+var host = window.location.hostname;
+var timestamp = '';
+
+var isLocalHost = (host === "localhost" || host === "127.0.0.1" || host === "192.168.0.112");
+
+var urlMap = ''
+if (isLocalHost) {
+ urlMap = '//' + host + ':3000/maxhold?timestamp=' + Date.now();
+} else {
+ urlMap = '//' + host + '/api/maxhold?timestamp=' + Date.now();
+}
+
+var urlTimestamp = '';
+if (isLocalHost) {
+ urlTimestamp = '//' + host + ':3000/timestamp?timestamp=' + Date.now();
+} else {
+ urlTimestamp = '//' + host + '/api/timestamp?timestamp=' + Date.now();
+}
+
+var data = [
+ {
+ z: [[0, 0, 0], [0, 0, 0], [0, 0, 0]],
+ colorscale: 'Jet',
+ type: 'heatmap'
+ }
+];
+
+var layout = {
+ autosize: false,
+ margin: {
+ l: 50,
+ r: 50,
+ b: 50,
+ t: 50,
+ pad: 0
+ },
+ width: document.getElementById('ddmap').offsetWidth,
+ height: document.getElementById('ddmap').offsetHeight,
+ plot_bgcolor: "rgba(0,0,0,0)",
+ paper_bgcolor: "rgba(0,0,0,0)",
+ annotations: [],
+ coloraxis: {
+ cmin: 0,
+ cmax: 1
+ },
+ displayModeBar: false,
+ xaxis: {
+ ticks: '',
+ side: 'bottom'
+ },
+ yaxis: {
+ ticks: '',
+ ticksuffix: ' ',
+ autosize: false
+ }
+};
+
+var config = {
+ displayModeBar: false,
+ responsive: true
+}
+
+Plotly.newPlot('ddmap', data, layout, config);
+
+var intervalId = window.setInterval(function () {
+
+ // check if timestamp is updated
+ var timestampData = $.get(urlTimestamp, function () { })
+
+ .done(function (data) {
+ if (timestamp != data) {
+ timestamp = data;
+ // get new map data
+ var apiData = $.getJSON(urlMap, function () { })
+ .done(function (data) {
+ // case draw new plot
+ if (data.nRows != nRows || data.nCols != nCols) {
+ nRows = data.nRows;
+ nCols = data.nCols;
+
+ data = [
+ {
+ z: data.data,
+ x: data.delay,
+ y: data.doppler,
+ colorscale: 'Jet',
+ zauto: false,
+ zmin: 0,
+ zmax: Math.max(13, data.maxPower),
+ type: 'heatmap'
+ }
+ ];
+ layout = {
+ autosize: false,
+ margin: {
+ l: 50,
+ r: 50,
+ b: 50,
+ t: 50,
+ pad: 0
+ },
+ width: document.getElementById('ddmap').offsetWidth,
+ height: document.getElementById('ddmap').offsetHeight,
+ plot_bgcolor: "rgba(0,0,0,0)",
+ paper_bgcolor: "rgba(0,0,0,0)",
+ annotations: [],
+ displayModeBar: false,
+ xaxis: {
+ title: {
+ text: 'Bistatic Range (km)',
+ font: {
+ size: 24
+ }
+ },
+ ticks: '',
+ side: 'bottom'
+ },
+ yaxis: {
+ title: {
+ text: 'Bistatic Doppler (Hz)',
+ font: {
+ size: 24
+ }
+ },
+ ticks: '',
+ ticksuffix: ' ',
+ autosize: false,
+ categoryorder: "total descending"
+ }
+ };
+ Plotly.newPlot('ddmap', data, layout, { displayModeBar: false });
+ }
+ else {
+ data_update =
+ {
+ 'z': [data.data],
+ 'zmax': Math.max(13, data.maxPower)
+ };
+ layout_update = {
+ };
+ Plotly.update('ddmap', data_update, layout_update, { displayModeBar: false });
+ }
+
+ })
+
+ .fail(function () {
+ console.log('API Fail');
+ })
+
+ .always(function () {
+
+ });
+ }
+ })
+
+ .fail(function () {
+ console.log('API Fail');
+ })
+
+ .always(function () {
+
+ });
+
+}, 100);
diff --git a/html/plot.js b/html/plot.js
index 99350a0..e95de3a 100644
--- a/html/plot.js
+++ b/html/plot.js
@@ -164,4 +164,4 @@ var intervalId = window.setInterval(function () {
});
-}, 500);
+}, 100);