request failing packets
This commit is contained in:
@@ -37,6 +37,16 @@ export const changeConfiguration = ({
|
|||||||
|
|
||||||
export const setAudioContext = ctx => audioContext = ctx;
|
export const setAudioContext = ctx => audioContext = ctx;
|
||||||
|
|
||||||
|
export const setDestination = destination => {
|
||||||
|
DESTINATION = destination;
|
||||||
|
const oscillators = getOscillators();
|
||||||
|
oscillators.forEach(
|
||||||
|
oscillator => {
|
||||||
|
oscillator?.disconnect();
|
||||||
|
oscillator?.connect(destination);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
function getAudioContext() {
|
function getAudioContext() {
|
||||||
if(!audioContext) {
|
if(!audioContext) {
|
||||||
throw 'Audio context not provided.';
|
throw 'Audio context not provided.';
|
||||||
@@ -128,10 +138,7 @@ export function stopAt(streamEndSeconds) {
|
|||||||
oscillator?.stop(streamEndSeconds);
|
oscillator?.stop(streamEndSeconds);
|
||||||
}
|
}
|
||||||
stopTimeout();
|
stopTimeout();
|
||||||
stopOscillatorsTimeoutId = window.setTimeout(
|
stopOscillatorsTimeoutId = window.setTimeout(stop, delayMs(streamEndSeconds));
|
||||||
stop,
|
|
||||||
delayMs(streamEndSeconds)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
export function stop() {
|
export function stop() {
|
||||||
const oscillators = getOscillators();
|
const oscillators = getOscillators();
|
||||||
|
|||||||
@@ -231,6 +231,14 @@ class BasePanel {
|
|||||||
const element = this.getElement(id);
|
const element = this.getElement(id);
|
||||||
element.innerHTML = html;
|
element.innerHTML = html;
|
||||||
}
|
}
|
||||||
|
getHtmlById = (id) => {
|
||||||
|
const element = this.getElement(id);
|
||||||
|
return element.innerHTML;
|
||||||
|
}
|
||||||
|
scrollToBottom = id => {
|
||||||
|
const element = this.getElement(id);
|
||||||
|
element.scrollIntoView(false);
|
||||||
|
}
|
||||||
getNumberById = id => {
|
getNumberById = id => {
|
||||||
const value = this.getValueById(id);
|
const value = this.getValueById(id);
|
||||||
return parseFloat(value);
|
return parseFloat(value);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { htmlEncode } from '../converters';
|
||||||
import BasePanel from './BasePanel';
|
import BasePanel from './BasePanel';
|
||||||
|
|
||||||
class CodePanel extends BasePanel {
|
class CodePanel extends BasePanel {
|
||||||
@@ -6,6 +7,18 @@ class CodePanel extends BasePanel {
|
|||||||
this.addCode('code');
|
this.addCode('code');
|
||||||
}
|
}
|
||||||
setCode = (html) => this.setHtmlById('code', html);
|
setCode = (html) => this.setHtmlById('code', html);
|
||||||
|
appendCode = html => {
|
||||||
|
let current = this.getHtmlById('code');
|
||||||
|
if(current !== '') current += document.createElement('br').outerHTML;
|
||||||
|
this.setHtmlById('code', current + html);
|
||||||
|
this.scrollToBottom('code');
|
||||||
|
}
|
||||||
|
appendText = text => {
|
||||||
|
let current = this.getHtmlById('code');
|
||||||
|
if(current !== '') current += document.createElement('br').outerHTML;
|
||||||
|
this.setHtmlById('code', current + htmlEncode(text));
|
||||||
|
this.scrollToBottom('code');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CodePanel;
|
export default CodePanel;
|
||||||
@@ -109,7 +109,8 @@ class FrequencyGraphPanel extends BasePanel {
|
|||||||
const canvas = this.getElement('frequency-graph');
|
const canvas = this.getElement('frequency-graph');
|
||||||
const ctx = canvas.getContext('2d');
|
const ctx = canvas.getContext('2d');
|
||||||
const {height, width} = canvas;
|
const {height, width} = canvas;
|
||||||
ctx.clearRect(0, 0, width, height);
|
ctx.fillStyle = 'black';
|
||||||
|
ctx.fillRect(0, 0, width, height);
|
||||||
let now;
|
let now;
|
||||||
|
|
||||||
if(this.samples.length > 1) {
|
if(this.samples.length > 1) {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import BasePanel from './BasePanel';
|
import BasePanel from './BasePanel';
|
||||||
|
|
||||||
class CommunicationsPanel extends BasePanel {
|
class OutputPanel extends BasePanel {
|
||||||
constructor() {
|
constructor() {
|
||||||
super('Audio Sender');
|
super('Outut');
|
||||||
this.addRadios('send-via', [
|
this.addRadios('send-via', [
|
||||||
{text: 'Analyzer', id: 'send-via-analyzer', eventName: 'sendAnalyzerChange'},
|
{text: 'Analyzer', id: 'send-via-analyzer', eventName: 'sendAnalyzerChange'},
|
||||||
{text: 'Speakers', id: 'send-via-speaker', eventName: 'sendSpeakersChange'}
|
{text: 'Speakers', id: 'send-via-speaker', eventName: 'sendSpeakersChange'}
|
||||||
@@ -12,4 +12,4 @@ class CommunicationsPanel extends BasePanel {
|
|||||||
setSendAnalyzer = checked => this.setCheckedById('send-via-analyzer', checked);
|
setSendAnalyzer = checked => this.setCheckedById('send-via-analyzer', checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CommunicationsPanel;
|
export default OutputPanel;
|
||||||
@@ -20,8 +20,8 @@ class PacketErrorPanel extends BasePanel {
|
|||||||
this.addSection('Packet Retransmission')
|
this.addSection('Packet Retransmission')
|
||||||
|
|
||||||
this.addRadios('repeat', [
|
this.addRadios('repeat', [
|
||||||
{ text: 'Automatic Repeat Request', value: 'arq', checked: true, eventName: 'hi' },
|
{ text: 'Automatic Repeat Request', id:'arq', value: 'arq', checked: true, eventName: 'automaticRepeatRequestChange' },
|
||||||
{ text: 'Manual Repeat Request', value: 'manual', checked: true, eventName: 'hi' }
|
{ text: 'Manual Repeat Request', id:'manual', value: 'manual', checked: true, eventName: 'manualRepeatRequestChange' }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this.openField('Packets');
|
this.openField('Packets');
|
||||||
@@ -30,6 +30,9 @@ class PacketErrorPanel extends BasePanel {
|
|||||||
|
|
||||||
this.addButton('request-button', 'Request', 'requestPackets');
|
this.addButton('request-button', 'Request', 'requestPackets');
|
||||||
}
|
}
|
||||||
|
getAutomaticRepeatRequest = () => {
|
||||||
|
return this.getCheckedById('arq');
|
||||||
|
}
|
||||||
reset = () => {
|
reset = () => {
|
||||||
this.setFailedPacketIndeces([]);
|
this.setFailedPacketIndeces([]);
|
||||||
this.setSizeCrcUnavailable();
|
this.setSizeCrcUnavailable();
|
||||||
@@ -41,7 +44,7 @@ class PacketErrorPanel extends BasePanel {
|
|||||||
}
|
}
|
||||||
getFailedPacketIndeces = () => {
|
getFailedPacketIndeces = () => {
|
||||||
let text = this.getValueById('request-packet-indexes');
|
let text = this.getValueById('request-packet-indexes');
|
||||||
return text.replace(/\s+/g, '').split(',').map(Number);
|
return text.replace(/\s+/g, '').split(',').filter(v => v !== '').map(Number);
|
||||||
}
|
}
|
||||||
setCrcPassed = (passed) => this.setValueById('crc', passed ? 'Pass' : 'Fail');
|
setCrcPassed = (passed) => this.setValueById('crc', passed ? 'Pass' : 'Fail');
|
||||||
setCrcUnavailable = () => this.setValueById('crc', 'N/A');
|
setCrcUnavailable = () => this.setValueById('crc', 'N/A');
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class ReceivePanel extends BasePanel {
|
|||||||
this.addNewLine();
|
this.addNewLine();
|
||||||
this.addDynamicText('id-state', 'Offline.');
|
this.addDynamicText('id-state', 'Offline.');
|
||||||
|
|
||||||
this.addProgressBar('progress', .50, .25);
|
this.addProgressBar('progress', 0, 0);
|
||||||
|
|
||||||
this.addCode('text', '', 'small');
|
this.addCode('text', '', 'small');
|
||||||
this.addImage('image', undefined, {width: 32, height: 32});
|
this.addImage('image', undefined, {width: 32, height: 32});
|
||||||
@@ -45,6 +45,10 @@ class ReceivePanel extends BasePanel {
|
|||||||
this.addEventListener('resetClick', () => {
|
this.addEventListener('resetClick', () => {
|
||||||
AudioReceiver.reset();
|
AudioReceiver.reset();
|
||||||
StreamManager.reset();
|
StreamManager.reset();
|
||||||
|
this.setReceivedBytes([]);
|
||||||
|
this.setExpectedPacketCount(0);
|
||||||
|
this.setFailedPacketCount(0);
|
||||||
|
this.setSuccessfulPacketCount(0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
isOnline = () => this.getCheckedById('is-online');
|
isOnline = () => this.getCheckedById('is-online');
|
||||||
@@ -58,17 +62,6 @@ class ReceivePanel extends BasePanel {
|
|||||||
this.setValueById('id-state', 'offline');
|
this.setValueById('id-state', 'offline');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// waitForSignal = () => {
|
|
||||||
// AudioReceiver.start();
|
|
||||||
// }
|
|
||||||
// reset = () => {
|
|
||||||
// AudioReceiver.reset();
|
|
||||||
// StreamManager.reset();
|
|
||||||
// }
|
|
||||||
// stopWaitingForSignal = () => {
|
|
||||||
// AudioReceiver.stop();
|
|
||||||
// }
|
|
||||||
setProgress = (percent, percent2 = 0) => {
|
setProgress = (percent, percent2 = 0) => {
|
||||||
this.setProgressById('progress', percent, percent2);
|
this.setProgressById('progress', percent, percent2);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,9 @@ import Dispatcher from "./Dispatcher";
|
|||||||
import * as CRC from './CRC';
|
import * as CRC from './CRC';
|
||||||
import * as PacketUtils from './PacketUtils';
|
import * as PacketUtils from './PacketUtils';
|
||||||
import {
|
import {
|
||||||
bitsToBytes,
|
|
||||||
bitsToInt,
|
bitsToInt,
|
||||||
bytesToBits,
|
bytesToBits,
|
||||||
numberToBytes,
|
numberToBytes,
|
||||||
numberToHex,
|
|
||||||
numberToAscii,
|
|
||||||
bytesToNumber
|
|
||||||
} from "./converters";
|
} from "./converters";
|
||||||
|
|
||||||
const dispatcher = new Dispatcher('StreamManager', [
|
const dispatcher = new Dispatcher('StreamManager', [
|
||||||
@@ -41,7 +37,9 @@ export const removeEventListener = dispatcher.removeListener;
|
|||||||
|
|
||||||
const isPacketInRange = (packetIndex) => {
|
const isPacketInRange = (packetIndex) => {
|
||||||
// Blindly accept. We can't do anything about it for now
|
// Blindly accept. We can't do anything about it for now
|
||||||
if(!isSizeTrusted()) return true;
|
if(!isSizeTrusted()){
|
||||||
|
return packetIndex < PacketUtils.getMaxPackets();
|
||||||
|
}
|
||||||
const { packetCount } = PacketUtils.packetStats(getSize());
|
const { packetCount } = PacketUtils.packetStats(getSize());
|
||||||
return packetIndex < packetCount;
|
return packetIndex < packetCount;
|
||||||
}
|
}
|
||||||
@@ -125,11 +123,23 @@ export const applyPacket = ({
|
|||||||
}
|
}
|
||||||
delete BITS[packetIndex]
|
delete BITS[packetIndex]
|
||||||
}
|
}
|
||||||
export const getFailedPacketIndeces = () => FAILED_SEQUENCES;
|
export const getFailedPacketIndeces = () => {
|
||||||
|
return FAILED_SEQUENCES.filter(isPacketInRange);
|
||||||
|
}
|
||||||
|
export const getNeededPacketIndeces = () => {
|
||||||
|
if(!isSizeTrusted()) return getFailedPacketIndeces();
|
||||||
|
const packetCount = countExpectedPackets();
|
||||||
|
let indeces = [];
|
||||||
|
for(let i = 0; i < packetCount; i++) {
|
||||||
|
if(SUCCESS_SEQUENCES.includes(i)) continue;
|
||||||
|
indeces.push(i);
|
||||||
|
}
|
||||||
|
return indeces;
|
||||||
|
};
|
||||||
export const countFailedPackets = () => FAILED_SEQUENCES.length;
|
export const countFailedPackets = () => FAILED_SEQUENCES.length;
|
||||||
export const countSuccessfulPackets = () => SUCCESS_SEQUENCES.length;
|
export const countSuccessfulPackets = () => SUCCESS_SEQUENCES.length;
|
||||||
export const countExpectedPackets = () => {
|
export const countExpectedPackets = () => {
|
||||||
if(!isSizeTrusted()) return 0;
|
if(!isSizeTrusted()) return PacketUtils.getMaxPackets();
|
||||||
return PacketUtils.packetStats(getSize()).packetCount;
|
return PacketUtils.packetStats(getSize()).packetCount;
|
||||||
}
|
}
|
||||||
export const setPacketsExpected = packetCount => {
|
export const setPacketsExpected = packetCount => {
|
||||||
@@ -138,11 +148,27 @@ export const setPacketsExpected = packetCount => {
|
|||||||
SAMPLES_EXPECTED = packetCount * PacketUtils.getPacketSegmentCount();
|
SAMPLES_EXPECTED = packetCount * PacketUtils.getPacketSegmentCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hasPackets = (start, end) => {
|
||||||
|
for(let packetIndex = start; packetIndex <= end; packetIndex++) {
|
||||||
|
// We need this packet, but it failed to transfer
|
||||||
|
if(FAILED_SEQUENCES.includes(packetIndex)) return false;
|
||||||
|
// We need this packet, but it hasn't come through yet
|
||||||
|
if(!SUCCESS_SEQUENCES.includes(packetIndex)) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const hasBytes = (index, length) => {
|
||||||
|
if(DATA.length < index + length) return false;
|
||||||
|
const packetSize = PacketUtils.getPacketDataByteCount();
|
||||||
|
const start = Math.floor(index / packetSize);
|
||||||
|
const end = Math.floor(index + length / packetSize);
|
||||||
|
return hasPackets(start, end);
|
||||||
|
}
|
||||||
export const getSizeAvailable = () => {
|
export const getSizeAvailable = () => {
|
||||||
if(DATA_SIZE_BIT_COUNT === 0) return 1;
|
if(DATA_SIZE_BIT_COUNT === 0) return 1;
|
||||||
let lastBit = DATA_SIZE_BIT_COUNT;
|
let lastBit = DATA_SIZE_BIT_COUNT;
|
||||||
let lastByte = Math.ceil(lastBit / 8);
|
let lastByte = Math.ceil(lastBit / 8);
|
||||||
if(DATA.length < lastByte) return false;
|
if(!hasBytes(0, lastByte)) return false;
|
||||||
|
|
||||||
// Do we have a crc check on the size?
|
// Do we have a crc check on the size?
|
||||||
if(DATA_SIZE_CRC_BIT_COUNT !== 0) {
|
if(DATA_SIZE_CRC_BIT_COUNT !== 0) {
|
||||||
@@ -209,13 +235,14 @@ export const getSizeCrcAvailable = () => {
|
|||||||
if (DATA_SIZE_BIT_COUNT === 0) return false;
|
if (DATA_SIZE_BIT_COUNT === 0) return false;
|
||||||
if (DATA_SIZE_CRC_BIT_COUNT === 0) return false;
|
if (DATA_SIZE_CRC_BIT_COUNT === 0) return false;
|
||||||
const bitsNeeded = DATA_SIZE_BIT_COUNT + DATA_SIZE_CRC_BIT_COUNT;
|
const bitsNeeded = DATA_SIZE_BIT_COUNT + DATA_SIZE_CRC_BIT_COUNT;
|
||||||
return DATA.length >= Math.ceil(bitsNeeded / 8);
|
const bytesNeeded = Math.ceil(bitsNeeded / 8);
|
||||||
|
return hasBytes(0, bytesNeeded);
|
||||||
}
|
}
|
||||||
export const getCrcAvailable = () => {
|
export const getCrcAvailable = () => {
|
||||||
if(DATA_CRC_BIT_COUNT === 0) return false;
|
if(DATA_CRC_BIT_COUNT === 0) return false;
|
||||||
if(!getSizeAvailable()) return false;
|
if(!getSizeAvailable()) return false;
|
||||||
let byteCount = getSize();
|
let byteCount = getSize();
|
||||||
if(DATA.length < byteCount) return false;
|
|
||||||
// Do we have enough bytes for the headers and underlying data?
|
// Do we have enough bytes for the headers and underlying data?
|
||||||
let headerBitCount = DATA_SIZE_BIT_COUNT + DATA_CRC_BIT_COUNT + DATA_SIZE_CRC_BIT_COUNT;
|
let headerBitCount = DATA_SIZE_BIT_COUNT + DATA_CRC_BIT_COUNT + DATA_SIZE_CRC_BIT_COUNT;
|
||||||
if(headerBitCount % 8 !== 0)
|
if(headerBitCount % 8 !== 0)
|
||||||
@@ -223,7 +250,7 @@ export const getCrcAvailable = () => {
|
|||||||
const headerByteCount = headerBitCount / 8;
|
const headerByteCount = headerBitCount / 8;
|
||||||
byteCount += headerByteCount;
|
byteCount += headerByteCount;
|
||||||
|
|
||||||
return DATA.length >= byteCount;
|
return hasBytes(0, byteCount);
|
||||||
}
|
}
|
||||||
export const getSizeCrcPassed = () => {
|
export const getSizeCrcPassed = () => {
|
||||||
if(!getSizeCrcAvailable()) return false;
|
if(!getSizeCrcAvailable()) return false;
|
||||||
|
|||||||
@@ -90,3 +90,8 @@ export const bytesToUrl = bytes => {
|
|||||||
const blob = new Blob([new Uint8Array(bytes)]);
|
const blob = new Blob([new Uint8Array(bytes)]);
|
||||||
return URL.createObjectURL(blob);
|
return URL.createObjectURL(blob);
|
||||||
}
|
}
|
||||||
|
export function htmlEncode(text) {
|
||||||
|
const element = document.createElement('div');
|
||||||
|
element.textContent = text;
|
||||||
|
return element.innerHTML;
|
||||||
|
}
|
||||||
30
index.html
30
index.html
@@ -10,12 +10,6 @@
|
|||||||
<body>
|
<body>
|
||||||
<h1>Data Over Audio</h1>
|
<h1>Data Over Audio</h1>
|
||||||
<div class="panels" id="panel-container">
|
<div class="panels" id="panel-container">
|
||||||
<div class="chart">
|
|
||||||
<h2>Channel Graph</h2>
|
|
||||||
<div>
|
|
||||||
<canvas id="received-channel-graph" width="800" height="300"></canvas>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<h2>Data</h2>
|
<h2>Data</h2>
|
||||||
<div>
|
<div>
|
||||||
@@ -28,18 +22,6 @@
|
|||||||
Unused bits in last packet: <span id="last-packet-unused-bit-count"></span><br>
|
Unused bits in last packet: <span id="last-packet-unused-bit-count"></span><br>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<h2>Original Data to send</h2>
|
|
||||||
<div>
|
|
||||||
<div class="raw-data" id="sent-data"></div><br />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h2>Encoded packets to send</h2>
|
|
||||||
<div>
|
|
||||||
<div class="raw-data" id="error-correcting-data"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<h2>Decoded</h2>
|
<h2>Decoded</h2>
|
||||||
<div>
|
<div>
|
||||||
@@ -52,18 +34,6 @@
|
|||||||
Decoded Packets: <span id="received-decoded-bits-error-percent">N/A</span>%<br />
|
Decoded Packets: <span id="received-decoded-bits-error-percent">N/A</span>%<br />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<h2>Encoded Packets Received</h2>
|
|
||||||
<div>
|
|
||||||
<div class="raw-data" id="received-encoded-bits"></div><br />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<h2>Decoded Packets Received</h2>
|
|
||||||
<div>
|
|
||||||
<div class="raw-data" id="received-decoded-bits"></div><br />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<h2>Selected</h2>
|
<h2>Selected</h2>
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
Reference in New Issue
Block a user