add mavlink sigining and wss support
This commit is contained in:
@@ -1,13 +1,15 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import {
|
||||
Dialog, DialogTitle, DialogContent, DialogActions,
|
||||
Dialog, DialogTitle, DialogContent,
|
||||
Button, FormControl, InputLabel, Select, MenuItem,
|
||||
Typography, Box, Divider, RadioGroup, FormControlLabel, Radio, Chip,
|
||||
TextField, Tabs, Tab, Paper, IconButton
|
||||
Typography, Box, Divider, Chip,
|
||||
TextField, Paper, IconButton
|
||||
} from '@mui/material';
|
||||
import RefreshIcon from '@mui/icons-material/Refresh';
|
||||
import UsbIcon from '@mui/icons-material/Usb';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import Visibility from '@mui/icons-material/Visibility';
|
||||
import VisibilityOff from '@mui/icons-material/VisibilityOff';
|
||||
import WebSerial from './web_serial';
|
||||
|
||||
// Add this constant at the top of your file, outside the component
|
||||
@@ -74,6 +76,11 @@ const ConnectionSettingsModal = ({
|
||||
selectedBus, // New prop
|
||||
onBusChange // New prop
|
||||
}) => {
|
||||
// State for showing/hiding mavlink signing
|
||||
const [showMavlinkSigning, setShowMavlinkSigning] = useState(false);
|
||||
const handleToggleMavlinkSigning = () => {
|
||||
setShowMavlinkSigning((show) => !show);
|
||||
};
|
||||
// Port and connection management
|
||||
const [ports, setPorts] = useState([]);
|
||||
const [selectedPort, setSelectedPort] = useState(null);
|
||||
@@ -88,11 +95,13 @@ const ConnectionSettingsModal = ({
|
||||
const [activeConnection, setActiveConnection] = useState(null); // null, 'serial', or 'websocket'
|
||||
|
||||
// Add these state variables after your other state declarations
|
||||
const [ipError, setIpError] = useState('');
|
||||
const [hostError, setHostError] = useState('');
|
||||
const [portError, setPortError] = useState('');
|
||||
|
||||
// Add nodeId state to use the prop value
|
||||
const [nodeId, setNodeId] = useState(127);
|
||||
// Add mavlink signing state
|
||||
const [mavlinkSigning, setMavlinkSigning] = useState('');
|
||||
|
||||
// Add state for the forwarding interval
|
||||
const [forwardingInterval, setForwardingInterval] = useState(null);
|
||||
@@ -315,34 +324,27 @@ const ConnectionSettingsModal = ({
|
||||
return '';
|
||||
}
|
||||
|
||||
// Check for IPv4 format
|
||||
if (input.includes('.')) {
|
||||
// If input matches IPv4 pattern, validate as IPv4, else treat as hostname/domain
|
||||
const ipv4Pattern = /^\d{1,3}(\.\d{1,3}){3}$/;
|
||||
if (ipv4Pattern.test(input)) {
|
||||
const octets = input.split('.');
|
||||
|
||||
// An IPv4 address must have exactly 4 octets
|
||||
if (octets.length !== 4) {
|
||||
return 'Invalid IPv4 format';
|
||||
}
|
||||
|
||||
// Each octet must be a number between 0 and 255
|
||||
for (const octet of octets) {
|
||||
const num = parseInt(octet, 10);
|
||||
if (isNaN(num) || num < 0 || num > 255 || octet !== num.toString()) {
|
||||
return 'Each part must be a number between 0-255';
|
||||
}
|
||||
}
|
||||
|
||||
// Valid IPv4
|
||||
return '';
|
||||
}
|
||||
|
||||
// Check for hostname format
|
||||
const hostnamePattern = /^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])(\.[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])*$/;
|
||||
|
||||
// Check for hostname or domain (including subdomains)
|
||||
// Allow domains like 'support.ardupilot.org', 'foo.local', etc.
|
||||
const hostnamePattern = /^([a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?\.)*[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?$/;
|
||||
|
||||
if (hostnamePattern.test(input)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
return 'Invalid IP address or hostname';
|
||||
};
|
||||
|
||||
@@ -377,11 +379,16 @@ const ConnectionSettingsModal = ({
|
||||
}
|
||||
};
|
||||
|
||||
// Handler for Mavlink Signing input
|
||||
const handleMavlinkSigningChange = (e) => {
|
||||
setMavlinkSigning(e.target.value);
|
||||
};
|
||||
|
||||
// Update the ws host/port change handlers
|
||||
const handleWsHostChange = (e) => {
|
||||
const value = e.target.value;
|
||||
setWsHost(value);
|
||||
setIpError(validateIpAddress(value));
|
||||
setHostError(validateIpAddress(value));
|
||||
};
|
||||
|
||||
const handleWsPortChange = (e) => {
|
||||
@@ -396,54 +403,48 @@ const ConnectionSettingsModal = ({
|
||||
if (activeConnection === 'websocket') {
|
||||
// Force close the connection
|
||||
window.mavlinkSession.close();
|
||||
|
||||
// Always update the UI state regardless of actual connection state
|
||||
setActiveConnection(null);
|
||||
onConnectionStatusChange(false);
|
||||
showMessage('WebSocket connection closed', 'info');
|
||||
|
||||
// Clear the forwarding interval
|
||||
if (forwardingInterval) {
|
||||
clearInterval(forwardingInterval);
|
||||
setForwardingInterval(null);
|
||||
}
|
||||
} else {
|
||||
// Set in-progress state before attempting to connect
|
||||
setConnectionInProgress(true);
|
||||
|
||||
// Validate both fields before connecting
|
||||
const hostError = validateIpAddress(wsHost);
|
||||
const portError = validatePort(wsPort);
|
||||
|
||||
setIpError(hostError);
|
||||
setPortError(portError);
|
||||
|
||||
// Only connect if both validations pass
|
||||
if (!hostError && !portError) {
|
||||
const hostErr = validateIpAddress(wsHost);
|
||||
const portErr = validatePort(wsPort);
|
||||
setHostError(hostErr);
|
||||
setPortError(portErr);
|
||||
if (!hostErr && !portErr) {
|
||||
if (activeConnection) {
|
||||
window.mavlinkSession.close();
|
||||
// Clear any existing interval
|
||||
if (forwardingInterval) {
|
||||
clearInterval(forwardingInterval);
|
||||
}
|
||||
}
|
||||
|
||||
// Use window.mavlinkSession consistently
|
||||
window.mavlinkSession.initWebSocketConnection(wsHost, parseInt(wsPort, 10));
|
||||
// Use wss if signing is present, else ws
|
||||
const wsProtocol = mavlinkSigning ? 'wss' : 'ws';
|
||||
// Compose the full URL for the websocket
|
||||
const wsUrl = `${wsProtocol}://${wsHost}:${wsPort}`;
|
||||
if (window.mavlinkSession.initWebSocketConnection.length === 1) {
|
||||
// If the function expects a URL
|
||||
window.mavlinkSession.initWebSocketConnection(wsUrl);
|
||||
} else {
|
||||
// Fallback to old signature (host, port)
|
||||
window.mavlinkSession.initWebSocketConnection(wsHost, parseInt(wsPort, 10), mavlinkSigning);
|
||||
}
|
||||
|
||||
window.mavlinkSession.addWebSocketOpenHandler(() => {
|
||||
console.log('WebSocket connection open');
|
||||
// Set Node ID and Bus for the local node
|
||||
window.localNode.setNodeId(parseInt(nodeId, 10));
|
||||
window.localNode.setBus(selectedBus);
|
||||
|
||||
// Start the mavlinkCanForward interval
|
||||
const intervalId = setInterval(() => {
|
||||
if (window.mavlinkSession) {
|
||||
window.mavlinkSession.enableMavlinkCanForward(window.localNode.bus);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
setForwardingInterval(intervalId);
|
||||
setActiveConnection('websocket');
|
||||
onConnectionStatusChange(true);
|
||||
@@ -453,20 +454,13 @@ const ConnectionSettingsModal = ({
|
||||
|
||||
window.mavlinkSession.addWebSocketErrorHandler((error) => {
|
||||
console.error('WebSocket error:', error);
|
||||
|
||||
// Clear any existing interval
|
||||
if (forwardingInterval) {
|
||||
clearInterval(forwardingInterval);
|
||||
setForwardingInterval(null);
|
||||
}
|
||||
|
||||
setActiveConnection(null);
|
||||
onConnectionStatusChange(false);
|
||||
|
||||
// Reset in-progress state on error
|
||||
setConnectionInProgress(false);
|
||||
|
||||
// Show error message using App's showMessage function
|
||||
let errorMsg = 'Connection failed';
|
||||
if (error && error.message) {
|
||||
errorMsg = `Connection failed: ${error.message}`;
|
||||
@@ -478,14 +472,12 @@ const ConnectionSettingsModal = ({
|
||||
|
||||
window.mavlinkSession.webSocketConnect();
|
||||
} else {
|
||||
// If validation fails, reset the in-progress state
|
||||
setConnectionInProgress(false);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error with WebSocket connection:', error);
|
||||
showMessage(`WebSocket error: ${error.message || 'Unknown error'}`, 'error');
|
||||
// Reset in-progress state on any error
|
||||
setConnectionInProgress(false);
|
||||
}
|
||||
};
|
||||
@@ -650,8 +642,8 @@ const ConnectionSettingsModal = ({
|
||||
disabled={activeConnection !== null}
|
||||
size="small"
|
||||
sx={{ flex: 3 }}
|
||||
error={!!ipError}
|
||||
helperText={ipError}
|
||||
error={!!hostError}
|
||||
helperText={hostError}
|
||||
/>
|
||||
<TextField
|
||||
label="Port"
|
||||
@@ -667,23 +659,23 @@ const ConnectionSettingsModal = ({
|
||||
</Box>
|
||||
|
||||
<Box sx={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||
<Button
|
||||
onClick={handleWebSocketConnect}
|
||||
color={activeConnection === 'websocket' ? "error" : "primary"}
|
||||
variant="contained"
|
||||
disabled={
|
||||
connectionInProgress || // Disable when connection attempt is in progress
|
||||
!!ipError ||
|
||||
!!portError ||
|
||||
!wsHost ||
|
||||
!wsPort ||
|
||||
(activeConnection !== null && activeConnection !== 'websocket')
|
||||
}
|
||||
size="small"
|
||||
>
|
||||
{activeConnection === 'websocket' ? 'Disconnect' :
|
||||
connectionInProgress && !activeConnection ? 'Connecting...' : 'Connect'}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleWebSocketConnect}
|
||||
color={activeConnection === 'websocket' ? "error" : "primary"}
|
||||
variant="contained"
|
||||
disabled={
|
||||
connectionInProgress || // Disable when connection attempt is in progress
|
||||
!!hostError ||
|
||||
!!portError ||
|
||||
!wsHost ||
|
||||
!wsPort ||
|
||||
(activeConnection !== null && activeConnection !== 'websocket')
|
||||
}
|
||||
size="small"
|
||||
>
|
||||
{activeConnection === 'websocket' ? 'Disconnect' :
|
||||
connectionInProgress && !activeConnection ? 'Connecting...' : 'Connect'}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</Paper>
|
||||
@@ -691,7 +683,7 @@ const ConnectionSettingsModal = ({
|
||||
|
||||
<Divider />
|
||||
|
||||
{/* Bus Selection */}
|
||||
{/* Bus Selection and Mavlink Signing */}
|
||||
<Box>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>
|
||||
<TextField
|
||||
@@ -708,6 +700,29 @@ const ConnectionSettingsModal = ({
|
||||
error={validateNodeId(nodeId) !== ''}
|
||||
helperText={validateNodeId(nodeId)}
|
||||
/>
|
||||
<TextField
|
||||
label="Mavlink Signing"
|
||||
value={mavlinkSigning}
|
||||
onChange={handleMavlinkSigningChange}
|
||||
disabled={activeConnection !== null}
|
||||
size="small"
|
||||
placeholder="Secret Key"
|
||||
type={showMavlinkSigning ? 'text' : 'password'}
|
||||
sx={{ flex: 1 }}
|
||||
InputProps={{
|
||||
endAdornment: (
|
||||
<IconButton
|
||||
aria-label={showMavlinkSigning ? 'Hide secret' : 'Show secret'}
|
||||
onClick={handleToggleMavlinkSigning}
|
||||
edge="end"
|
||||
size="small"
|
||||
tabIndex={-1}
|
||||
>
|
||||
{showMavlinkSigning ? <VisibilityOff fontSize="small" /> : <Visibility fontSize="small" />}
|
||||
</IconButton>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
270
src/local_modules/jspack/jspack.js
Normal file
270
src/local_modules/jspack/jspack.js
Normal file
@@ -0,0 +1,270 @@
|
||||
/*!
|
||||
* Copyright © 2008 Fair Oaks Labs, Inc.
|
||||
* All rights reserved.
|
||||
*/
|
||||
|
||||
// Utility object: Encode/Decode C-style binary primitives to/from octet arrays
|
||||
function JSPack()
|
||||
{
|
||||
// Module-level (private) variables
|
||||
var el, bBE = false, m = this;
|
||||
|
||||
|
||||
// Raw byte arrays
|
||||
m._DeArray = function (a, p, l)
|
||||
{
|
||||
return [a.slice(p,p+l)];
|
||||
};
|
||||
m._EnArray = function (a, p, l, v)
|
||||
{
|
||||
for (var i = 0; i < l; a[p+i] = v[i]?v[i]:0, i++);
|
||||
};
|
||||
|
||||
// ASCII characters
|
||||
m._DeChar = function (a, p)
|
||||
{
|
||||
return String.fromCharCode(a[p]);
|
||||
};
|
||||
m._EnChar = function (a, p, v)
|
||||
{
|
||||
a[p] = v.charCodeAt(0);
|
||||
};
|
||||
|
||||
// Little-endian (un)signed N-byte integers
|
||||
m._DeInt = function (a, p)
|
||||
{
|
||||
var lsb = bBE?(el.len-1):0, nsb = bBE?-1:1, stop = lsb+nsb*el.len, rv, i, f;
|
||||
for (rv = 0, i = lsb, f = 1; i != stop; rv+=(a[p+i]*f), i+=nsb, f*=256);
|
||||
if (el.bSigned && (rv & Math.pow(2, el.len*8-1))) { rv -= Math.pow(2, el.len*8); }
|
||||
return rv;
|
||||
};
|
||||
m._EnInt = function (a, p, v)
|
||||
{
|
||||
var lsb = bBE?(el.len-1):0, nsb = bBE?-1:1, stop = lsb+nsb*el.len, i;
|
||||
v = (v<el.min)?el.min:(v>el.max)?el.max:v;
|
||||
for (i = lsb; i != stop; a[p+i]=v&0xff, i+=nsb, v>>=8);
|
||||
};
|
||||
|
||||
// ASCII character strings
|
||||
m._DeString = function (a, p, l)
|
||||
{
|
||||
for (var rv = new Array(l), i = 0; i < l; rv[i] = String.fromCharCode(a[p+i]), i++);
|
||||
return rv.join('');
|
||||
};
|
||||
m._EnString = function (a, p, l, v)
|
||||
{
|
||||
for (var t, i = 0; i < l; a[p+i] = (t=v.charCodeAt(i))?t:0, i++);
|
||||
};
|
||||
|
||||
// Little-endian N-bit IEEE 754 floating point
|
||||
m._De754 = function (a, p)
|
||||
{
|
||||
var s, e, m, i, d, nBits, mLen, eLen, eBias, eMax;
|
||||
mLen = el.mLen, eLen = el.len*8-el.mLen-1, eMax = (1<<eLen)-1, eBias = eMax>>1;
|
||||
|
||||
i = bBE?0:(el.len-1); d = bBE?1:-1; s = a[p+i]; i+=d; nBits = -7;
|
||||
for (e = s&((1<<(-nBits))-1), s>>=(-nBits), nBits += eLen; nBits > 0; e=e*256+a[p+i], i+=d, nBits-=8);
|
||||
for (m = e&((1<<(-nBits))-1), e>>=(-nBits), nBits += mLen; nBits > 0; m=m*256+a[p+i], i+=d, nBits-=8);
|
||||
|
||||
switch (e)
|
||||
{
|
||||
case 0:
|
||||
// Zero, or denormalized number
|
||||
e = 1-eBias;
|
||||
break;
|
||||
case eMax:
|
||||
// NaN, or +/-Infinity
|
||||
return m?NaN:((s?-1:1)*Infinity);
|
||||
default:
|
||||
// Normalized number
|
||||
m = m + Math.pow(2, mLen);
|
||||
e = e - eBias;
|
||||
break;
|
||||
}
|
||||
return (s?-1:1) * m * Math.pow(2, e-mLen);
|
||||
};
|
||||
m._En754 = function (a, p, v)
|
||||
{
|
||||
var s, e, m, i, d, c, mLen, eLen, eBias, eMax;
|
||||
mLen = el.mLen, eLen = el.len*8-el.mLen-1, eMax = (1<<eLen)-1, eBias = eMax>>1;
|
||||
|
||||
s = v<0?1:0;
|
||||
v = Math.abs(v);
|
||||
if (isNaN(v) || (v == Infinity))
|
||||
{
|
||||
m = isNaN(v)?1:0;
|
||||
e = eMax;
|
||||
}
|
||||
else
|
||||
{
|
||||
e = Math.floor(Math.log(v)/Math.LN2); // Calculate log2 of the value
|
||||
if (v*(c = Math.pow(2, -e)) < 1) { e--; c*=2; } // Math.log() isn't 100% reliable
|
||||
|
||||
// Round by adding 1/2 the significand's LSD
|
||||
if (e+eBias >= 1) { v += el.rt/c; } // Normalized: mLen significand digits
|
||||
else { v += el.rt*Math.pow(2, 1-eBias); } // Denormalized: <= mLen significand digits
|
||||
if (v*c >= 2) { e++; c/=2; } // Rounding can increment the exponent
|
||||
|
||||
if (e+eBias >= eMax)
|
||||
{
|
||||
// Overflow
|
||||
m = 0;
|
||||
e = eMax;
|
||||
}
|
||||
else if (e+eBias >= 1)
|
||||
{
|
||||
// Normalized - term order matters, as Math.pow(2, 52-e) and v*Math.pow(2, 52) can overflow
|
||||
m = (v*c-1)*Math.pow(2, mLen);
|
||||
e = e + eBias;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Denormalized - also catches the '0' case, somewhat by chance
|
||||
m = v*Math.pow(2, eBias-1)*Math.pow(2, mLen);
|
||||
e = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = bBE?(el.len-1):0, d=bBE?-1:1; mLen >= 8; a[p+i]=m&0xff, i+=d, m/=256, mLen-=8);
|
||||
for (e=(e<<mLen)|m, eLen+=mLen; eLen > 0; a[p+i]=e&0xff, i+=d, e/=256, eLen-=8);
|
||||
a[p+i-d] |= s*128;
|
||||
};
|
||||
|
||||
// Convert int64 to array with 3 elements: [lowBits, highBits, unsignedFlag]
|
||||
// '>>>' trick to convert signed 32bit int to unsigned int (because << always results in a signed 32bit int)
|
||||
m._DeInt64 = function (a, p) {
|
||||
var start = bBE ? 0 : 7, nsb = bBE ? 1 : -1, stop = start + nsb * 8, rv = [0,0, !el.bSigned], i, f, rvi;
|
||||
for (i = start, rvi = 1, f = 0;
|
||||
i != stop;
|
||||
rv[rvi] = (((rv[rvi]<<8)>>>0) + a[p + i]), i += nsb, f++, rvi = (f < 4 ? 1 : 0));
|
||||
return rv;
|
||||
};
|
||||
m._EnInt64 = function (a, p, v) {
|
||||
var start = bBE ? 0 : 7, nsb = bBE ? 1 : -1, stop = start + nsb * 8, i, f, rvi, s;
|
||||
for (i = start, rvi = 1, f = 0, s = 24;
|
||||
i != stop;
|
||||
a[p + i] = v[rvi]>>s & 0xff, i += nsb, f++, rvi = (f < 4 ? 1 : 0), s = 24 - (8 * (f % 4)));
|
||||
};
|
||||
|
||||
|
||||
// Class data
|
||||
m._sPattern = '(\\d+)?([AxcbBhHsfdiIlLqQ])';
|
||||
m._lenLut = {'A':1, 'x':1, 'c':1, 'b':1, 'B':1, 'h':2, 'H':2, 's':1, 'f':4, 'd':8, 'i':4, 'I':4, 'l':4, 'L':4, 'q':8, 'Q':8};
|
||||
m._elLut = { 'A': {en:m._EnArray, de:m._DeArray},
|
||||
's': {en:m._EnString, de:m._DeString},
|
||||
'c': {en:m._EnChar, de:m._DeChar},
|
||||
'b': {en:m._EnInt, de:m._DeInt, len:1, bSigned:true, min:-Math.pow(2, 7), max:Math.pow(2, 7)-1},
|
||||
'B': {en:m._EnInt, de:m._DeInt, len:1, bSigned:false, min:0, max:Math.pow(2, 8)-1},
|
||||
'h': {en:m._EnInt, de:m._DeInt, len:2, bSigned:true, min:-Math.pow(2, 15), max:Math.pow(2, 15)-1},
|
||||
'H': {en:m._EnInt, de:m._DeInt, len:2, bSigned:false, min:0, max:Math.pow(2, 16)-1},
|
||||
'i': {en:m._EnInt, de:m._DeInt, len:4, bSigned:true, min:-Math.pow(2, 31), max:Math.pow(2, 31)-1},
|
||||
'I': {en:m._EnInt, de:m._DeInt, len:4, bSigned:false, min:0, max:Math.pow(2, 32)-1},
|
||||
'l': {en:m._EnInt, de:m._DeInt, len:4, bSigned:true, min:-Math.pow(2, 31), max:Math.pow(2, 31)-1},
|
||||
'L': {en:m._EnInt, de:m._DeInt, len:4, bSigned:false, min:0, max:Math.pow(2, 32)-1},
|
||||
'f': {en:m._En754, de:m._De754, len:4, mLen:23, rt:Math.pow(2, -24)-Math.pow(2, -77)},
|
||||
'd': {en:m._En754, de:m._De754, len:8, mLen:52, rt:0},
|
||||
'q': {en:m._EnInt64, de:m._DeInt64, bSigned:true},
|
||||
'Q': {en:m._EnInt64, de:m._DeInt64, bSigned:false}};
|
||||
|
||||
// Unpack a series of n elements of size s from array a at offset p with fxn
|
||||
m._UnpackSeries = function (n, s, a, p)
|
||||
{
|
||||
for (var fxn = el.de, rv = [], i = 0; i < n; rv.push(fxn(a, p+i*s)), i++);
|
||||
return rv;
|
||||
};
|
||||
|
||||
// Pack a series of n elements of size s from array v at offset i to array a at offset p with fxn
|
||||
m._PackSeries = function (n, s, a, p, v, i)
|
||||
{
|
||||
for (var fxn = el.en, o = 0; o < n; fxn(a, p+o*s, v[i+o]), o++);
|
||||
};
|
||||
|
||||
// Unpack the octet array a, beginning at offset p, according to the fmt string
|
||||
m.Unpack = function (fmt, a, p)
|
||||
{
|
||||
// Set the private bBE flag based on the format string - assume big-endianness
|
||||
bBE = (fmt.charAt(0) != '<');
|
||||
|
||||
p = p?p:0;
|
||||
var re = new RegExp(this._sPattern, 'g'), m, n, s, rv = [];
|
||||
while (m = re.exec(fmt))
|
||||
{
|
||||
n = ((m[1]==undefined)||(m[1]==''))?1:parseInt(m[1]);
|
||||
s = this._lenLut[m[2]];
|
||||
if ((p + n*s) > a.length)
|
||||
{
|
||||
return undefined;
|
||||
}
|
||||
switch (m[2])
|
||||
{
|
||||
case 'A': case 's':
|
||||
rv.push(this._elLut[m[2]].de(a, p, n));
|
||||
break;
|
||||
case 'c': case 'b': case 'B': case 'h': case 'H':
|
||||
case 'i': case 'I': case 'l': case 'L': case 'f': case 'd': case 'q': case 'Q':
|
||||
el = this._elLut[m[2]];
|
||||
rv.push(this._UnpackSeries(n, s, a, p));
|
||||
break;
|
||||
}
|
||||
p += n*s;
|
||||
}
|
||||
return Array.prototype.concat.apply([], rv);
|
||||
};
|
||||
|
||||
// Pack the supplied values into the octet array a, beginning at offset p, according to the fmt string
|
||||
m.PackTo = function (fmt, a, p, values)
|
||||
{
|
||||
// Set the private bBE flag based on the format string - assume big-endianness
|
||||
bBE = (fmt.charAt(0) != '<');
|
||||
|
||||
var re = new RegExp(this._sPattern, 'g'), m, n, s, i = 0, j;
|
||||
while (m = re.exec(fmt))
|
||||
{
|
||||
n = ((m[1]==undefined)||(m[1]==''))?1:parseInt(m[1]);
|
||||
s = this._lenLut[m[2]];
|
||||
if ((p + n*s) > a.length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
switch (m[2])
|
||||
{
|
||||
case 'A': case 's':
|
||||
if ((i + 1) > values.length) { return false; }
|
||||
this._elLut[m[2]].en(a, p, n, values[i]);
|
||||
i += 1;
|
||||
break;
|
||||
case 'c': case 'b': case 'B': case 'h': case 'H':
|
||||
case 'i': case 'I': case 'l': case 'L': case 'f': case 'd': case 'q': case 'Q':
|
||||
el = this._elLut[m[2]];
|
||||
if ((i + n) > values.length) { return false; }
|
||||
this._PackSeries(n, s, a, p, values, i);
|
||||
i += n;
|
||||
break;
|
||||
case 'x':
|
||||
for (j = 0; j < n; j++) { a[p+j] = 0; }
|
||||
break;
|
||||
}
|
||||
p += n*s;
|
||||
}
|
||||
return a;
|
||||
};
|
||||
|
||||
// Pack the supplied values into a new octet array, according to the fmt string
|
||||
m.Pack = function (fmt, values)
|
||||
{
|
||||
return this.PackTo(fmt, new Array(this.CalcLength(fmt)), 0, values);
|
||||
};
|
||||
|
||||
// Determine the number of bytes represented by the format string
|
||||
m.CalcLength = function (fmt)
|
||||
{
|
||||
var re = new RegExp(this._sPattern, 'g'), m, sum = 0;
|
||||
while (m = re.exec(fmt))
|
||||
{
|
||||
sum += (((m[1]==undefined)||(m[1]==''))?1:parseInt(m[1])) * this._lenLut[m[2]];
|
||||
}
|
||||
return sum;
|
||||
};
|
||||
};
|
||||
|
||||
exports.jspack = new JSPack();
|
||||
9516
src/mavlink.js
9516
src/mavlink.js
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
||||
import { EventEmitter } from 'events';
|
||||
import WebSocketClient from './ws_client';
|
||||
import WebSerial from './web_serial';
|
||||
import { mavlink20, MAVLink20Processor } from './mavlink';
|
||||
import dronecan from './dronecan';
|
||||
import './mavlink';
|
||||
|
||||
class MavlinkSession extends EventEmitter {
|
||||
constructor() {
|
||||
@@ -27,8 +27,17 @@ class MavlinkSession extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
initWebSocketConnection(ip, port) {
|
||||
this.wsClient = new WebSocketClient(`ws://${ip}:${port}`);
|
||||
initWebSocketConnection(ip, port, mavlinkSigning='') {
|
||||
if (mavlinkSigning) {
|
||||
const enc = new TextEncoder();
|
||||
const data = enc.encode(mavlinkSigning);
|
||||
const hash = mavlink20.sha256(data);
|
||||
this.mavlinkProcessor.signing.secret_key = new Uint8Array(hash);
|
||||
this.mavlinkProcessor.signing.sign_outgoing = true;
|
||||
this.wsClient = new WebSocketClient(`wss://${ip}:${port}`);
|
||||
} else {
|
||||
this.wsClient = new WebSocketClient(`ws://${ip}:${port}`);
|
||||
}
|
||||
this.mavlinkProcessor.file = this.wsClient;
|
||||
|
||||
this.wsClient.addMessageHandler((buffer) => {
|
||||
|
||||
@@ -12,6 +12,7 @@ class WebSocketClient {
|
||||
connect() {
|
||||
// Reset connected status before attempting a new connection
|
||||
this.connected = false;
|
||||
console.log(`Connecting to WebSocket at ${this.url}`);
|
||||
this.socket = new WebSocket(this.url);
|
||||
|
||||
this.socket.addEventListener('open', (event) => {
|
||||
|
||||
Reference in New Issue
Block a user