@betaflight/msp
Advanced tools
Comparing version 0.2.0 to 0.3.0
@@ -6,2 +6,18 @@ # Change Log | ||
# [0.3.0](https://github.com/freshollie/fresh-configurator/tree/master/packages/msp/compare/@betaflight/msp@0.2.0...@betaflight/msp@0.3.0) (2020-06-05) | ||
### Bug Fixes | ||
* **msp:** fix issues with read8 on MspDataView, better logging, start tests for dataview ([7835832](https://github.com/freshollie/fresh-configurator/tree/master/packages/msp/commit/7835832c3907804696aa7634b115c5b84cd196bc)) | ||
### Features | ||
* **msp:** added better detection for device disconnect, reject all pending requests on connection close ([23c693a](https://github.com/freshollie/fresh-configurator/tree/master/packages/msp/commit/23c693a9ffe0bb496400f8f2eb459e2ce62b45b5)) | ||
# 0.2.0 (2020-05-15) | ||
@@ -8,0 +24,0 @@ |
@@ -19,7 +19,2 @@ /** | ||
export declare const execute: (port: string, { code, data, timeout }: MspCommand) => Promise<MspDataView>; | ||
/** | ||
* Private, used for testing | ||
*/ | ||
export declare const raw: (port: string) => SerialPort | undefined; | ||
export declare const reset: () => void; | ||
export declare const ports: () => Promise<string[]>; | ||
@@ -42,1 +37,9 @@ /** | ||
export declare const apiVersion: (port: string) => string; | ||
/** | ||
* Private, used for testing | ||
*/ | ||
export declare const raw: (port: string) => SerialPort | undefined; | ||
/** | ||
* Private, used for testing | ||
*/ | ||
export declare const reset: () => Promise<void>; |
@@ -45,7 +45,9 @@ "use strict"; | ||
const requestKey = request.toString("utf-8"); | ||
let dataRequest = requests[requestKey]; | ||
let mspRequest = requests[requestKey]; | ||
// Prevent FC lockup by checking if this request is currently being performed | ||
// and if not, making the request | ||
if (dataRequest === undefined) { | ||
dataRequest = new Promise((resolve, reject) => { | ||
if (mspRequest === undefined) { | ||
let rejector; | ||
const response = new Promise((resolve, reject) => { | ||
rejector = reject; | ||
// Throw an error if timeout is reached | ||
@@ -64,3 +66,3 @@ const timeoutId = setTimeout(() => { | ||
} | ||
log(`${request.toJSON().data} response: ${Buffer.from(message.data).toJSON().data}`); | ||
log(`${request.toJSON().data} response: ${Buffer.from(message.data).toJSON().data}, byteLength: ${message.data.byteLength}`); | ||
delete requests[requestKey]; | ||
@@ -74,3 +76,7 @@ clearTimeout(timeoutId); | ||
}); | ||
requests[requestKey] = dataRequest; | ||
mspRequest = { | ||
response, | ||
close: () => rejector === null || rejector === void 0 ? void 0 : rejector(new Error("Connection closed")), | ||
}; | ||
requests[requestKey] = mspRequest; | ||
log(`Writing ${request.toJSON().data} to ${port}`); | ||
@@ -82,13 +88,4 @@ serial.write(request); | ||
// they are accessing the same set of data | ||
return dataRequest.then((responseData) => new dataview_1.default(responseData)); | ||
return mspRequest.response.then((responseData) => new dataview_1.default(responseData)); | ||
}; | ||
/** | ||
* Private, used for testing | ||
*/ | ||
exports.raw = (port) => { var _a; return (_a = connectionsMap[port]) === null || _a === void 0 ? void 0 : _a.serial; }; | ||
exports.reset = () => { | ||
Object.keys(connectionsMap).forEach((port) => { | ||
delete connectionsMap[port]; | ||
}); | ||
}; | ||
exports.ports = async () => { | ||
@@ -109,5 +106,10 @@ if (!stream_1.default.Binding) { | ||
const { serial } = connection; | ||
const closePromise = new Promise((resolve) => serial.on("close", resolve)); | ||
serial.close(); | ||
delete connectionsMap[port]; | ||
const closePromise = serial.isOpen | ||
? new Promise((resolve) => serial.on("close", resolve)) | ||
: Promise.resolve(); | ||
await new Promise((resolve) => serial.close(resolve)); | ||
Object.values(connection.requests).forEach((request) => { | ||
request === null || request === void 0 ? void 0 : request.close(); | ||
}); | ||
await closePromise; | ||
@@ -176,2 +178,12 @@ }; | ||
} | ||
// Disconnect isn't notified unless we write to the serial | ||
// port after it disconnects. This interval constantly checks | ||
// the available ports, and issues a disconnect if the port | ||
// is removed | ||
const disconnectMonitor = setInterval(async () => { | ||
const list = await exports.ports(); | ||
if (!list.includes(port) && serial.isOpen) { | ||
exports.close(port); | ||
} | ||
}, 250); | ||
// valid connection, setup listeners | ||
@@ -183,7 +195,13 @@ serial.on("data", (data) => { | ||
log(`${port} on error received`); | ||
exports.close(port); | ||
// Don't trigger close if this serial port is already | ||
// closed, as it means that the closing | ||
// will be dealt with by the close event | ||
if (serial.isOpen) { | ||
exports.close(port); | ||
} | ||
}); | ||
serial.on("close", () => { | ||
serial.on("close", async () => { | ||
log(`${port} on close received`); | ||
exports.close(port); | ||
clearInterval(disconnectMonitor); | ||
await exports.close(port); | ||
onCloseCallback === null || onCloseCallback === void 0 ? void 0 : onCloseCallback(); | ||
@@ -201,2 +219,12 @@ }); | ||
exports.apiVersion = (port) => { var _a, _b; return (_b = (_a = connectionsMap[port]) === null || _a === void 0 ? void 0 : _a.mspInfo.apiVersion) !== null && _b !== void 0 ? _b : "0.0.0"; }; | ||
/** | ||
* Private, used for testing | ||
*/ | ||
exports.raw = (port) => { var _a; return (_a = connectionsMap[port]) === null || _a === void 0 ? void 0 : _a.serial; }; | ||
/** | ||
* Private, used for testing | ||
*/ | ||
exports.reset = async () => { | ||
await Promise.all(Object.keys(connectionsMap).map((port) => exports.close(port))); | ||
}; | ||
//# sourceMappingURL=connection.js.map |
@@ -36,3 +36,3 @@ "use strict"; | ||
this.offset += 1; | ||
return this.getInt8(this.offset); | ||
return this.getInt8(this.offset - 1); | ||
} | ||
@@ -39,0 +39,0 @@ return MspDataView.error(); |
@@ -239,3 +239,3 @@ "use strict"; | ||
} | ||
log(`Parsed message: ${data}`); | ||
log(`Parsed message: ${Buffer.from(data).toJSON().data}`); | ||
this.emit("data", { | ||
@@ -242,0 +242,0 @@ code: this.code, |
@@ -11,6 +11,10 @@ /// <reference types="serialport" /> | ||
export declare type ExecutionLocks = Record<number, Promise<void> | undefined>; | ||
export declare type MspRequest = { | ||
close: () => void; | ||
response: Promise<ArrayBuffer>; | ||
}; | ||
export declare type Connection = { | ||
serial: SerialPort; | ||
parser: MspParser; | ||
requests: Record<string, Promise<ArrayBuffer> | undefined>; | ||
requests: Record<string, MspRequest | undefined>; | ||
bytesWritten: number; | ||
@@ -17,0 +21,0 @@ bytesRead: number; |
@@ -1,2 +0,2 @@ | ||
export default class WriteBuffer extends Array { | ||
export default class WriteBuffer extends Array<number> { | ||
push8(val: number): WriteBuffer; | ||
@@ -3,0 +3,0 @@ push16(val: number): WriteBuffer; |
@@ -19,7 +19,2 @@ /** | ||
export declare const execute: (port: string, { code, data, timeout }: MspCommand) => Promise<MspDataView>; | ||
/** | ||
* Private, used for testing | ||
*/ | ||
export declare const raw: (port: string) => SerialPort | undefined; | ||
export declare const reset: () => void; | ||
export declare const ports: () => Promise<string[]>; | ||
@@ -42,1 +37,9 @@ /** | ||
export declare const apiVersion: (port: string) => string; | ||
/** | ||
* Private, used for testing | ||
*/ | ||
export declare const raw: (port: string) => SerialPort | undefined; | ||
/** | ||
* Private, used for testing | ||
*/ | ||
export declare const reset: () => Promise<void>; |
@@ -40,7 +40,9 @@ /** | ||
const requestKey = request.toString("utf-8"); | ||
let dataRequest = requests[requestKey]; | ||
let mspRequest = requests[requestKey]; | ||
// Prevent FC lockup by checking if this request is currently being performed | ||
// and if not, making the request | ||
if (dataRequest === undefined) { | ||
dataRequest = new Promise((resolve, reject) => { | ||
if (mspRequest === undefined) { | ||
let rejector; | ||
const response = new Promise((resolve, reject) => { | ||
rejector = reject; | ||
// Throw an error if timeout is reached | ||
@@ -59,3 +61,3 @@ const timeoutId = setTimeout(() => { | ||
} | ||
log(`${request.toJSON().data} response: ${Buffer.from(message.data).toJSON().data}`); | ||
log(`${request.toJSON().data} response: ${Buffer.from(message.data).toJSON().data}, byteLength: ${message.data.byteLength}`); | ||
delete requests[requestKey]; | ||
@@ -69,3 +71,7 @@ clearTimeout(timeoutId); | ||
}); | ||
requests[requestKey] = dataRequest; | ||
mspRequest = { | ||
response, | ||
close: () => rejector === null || rejector === void 0 ? void 0 : rejector(new Error("Connection closed")), | ||
}; | ||
requests[requestKey] = mspRequest; | ||
log(`Writing ${request.toJSON().data} to ${port}`); | ||
@@ -77,13 +83,4 @@ serial.write(request); | ||
// they are accessing the same set of data | ||
return dataRequest.then((responseData) => new MspDataView(responseData)); | ||
return mspRequest.response.then((responseData) => new MspDataView(responseData)); | ||
}; | ||
/** | ||
* Private, used for testing | ||
*/ | ||
export const raw = (port) => { var _a; return (_a = connectionsMap[port]) === null || _a === void 0 ? void 0 : _a.serial; }; | ||
export const reset = () => { | ||
Object.keys(connectionsMap).forEach((port) => { | ||
delete connectionsMap[port]; | ||
}); | ||
}; | ||
export const ports = async () => { | ||
@@ -104,5 +101,10 @@ if (!SerialPort.Binding) { | ||
const { serial } = connection; | ||
const closePromise = new Promise((resolve) => serial.on("close", resolve)); | ||
serial.close(); | ||
delete connectionsMap[port]; | ||
const closePromise = serial.isOpen | ||
? new Promise((resolve) => serial.on("close", resolve)) | ||
: Promise.resolve(); | ||
await new Promise((resolve) => serial.close(resolve)); | ||
Object.values(connection.requests).forEach((request) => { | ||
request === null || request === void 0 ? void 0 : request.close(); | ||
}); | ||
await closePromise; | ||
@@ -171,2 +173,12 @@ }; | ||
} | ||
// Disconnect isn't notified unless we write to the serial | ||
// port after it disconnects. This interval constantly checks | ||
// the available ports, and issues a disconnect if the port | ||
// is removed | ||
const disconnectMonitor = setInterval(async () => { | ||
const list = await ports(); | ||
if (!list.includes(port) && serial.isOpen) { | ||
close(port); | ||
} | ||
}, 250); | ||
// valid connection, setup listeners | ||
@@ -178,7 +190,13 @@ serial.on("data", (data) => { | ||
log(`${port} on error received`); | ||
close(port); | ||
// Don't trigger close if this serial port is already | ||
// closed, as it means that the closing | ||
// will be dealt with by the close event | ||
if (serial.isOpen) { | ||
close(port); | ||
} | ||
}); | ||
serial.on("close", () => { | ||
serial.on("close", async () => { | ||
log(`${port} on close received`); | ||
close(port); | ||
clearInterval(disconnectMonitor); | ||
await close(port); | ||
onCloseCallback === null || onCloseCallback === void 0 ? void 0 : onCloseCallback(); | ||
@@ -196,2 +214,12 @@ }); | ||
export const apiVersion = (port) => { var _a, _b; return (_b = (_a = connectionsMap[port]) === null || _a === void 0 ? void 0 : _a.mspInfo.apiVersion) !== null && _b !== void 0 ? _b : "0.0.0"; }; | ||
/** | ||
* Private, used for testing | ||
*/ | ||
export const raw = (port) => { var _a; return (_a = connectionsMap[port]) === null || _a === void 0 ? void 0 : _a.serial; }; | ||
/** | ||
* Private, used for testing | ||
*/ | ||
export const reset = async () => { | ||
await Promise.all(Object.keys(connectionsMap).map((port) => close(port))); | ||
}; | ||
//# sourceMappingURL=connection.js.map |
@@ -34,3 +34,3 @@ /** | ||
this.offset += 1; | ||
return this.getInt8(this.offset); | ||
return this.getInt8(this.offset - 1); | ||
} | ||
@@ -37,0 +37,0 @@ return MspDataView.error(); |
@@ -234,3 +234,3 @@ /** | ||
} | ||
log(`Parsed message: ${data}`); | ||
log(`Parsed message: ${Buffer.from(data).toJSON().data}`); | ||
this.emit("data", { | ||
@@ -237,0 +237,0 @@ code: this.code, |
@@ -11,6 +11,10 @@ /// <reference types="serialport" /> | ||
export declare type ExecutionLocks = Record<number, Promise<void> | undefined>; | ||
export declare type MspRequest = { | ||
close: () => void; | ||
response: Promise<ArrayBuffer>; | ||
}; | ||
export declare type Connection = { | ||
serial: SerialPort; | ||
parser: MspParser; | ||
requests: Record<string, Promise<ArrayBuffer> | undefined>; | ||
requests: Record<string, MspRequest | undefined>; | ||
bytesWritten: number; | ||
@@ -17,0 +21,0 @@ bytesRead: number; |
@@ -1,2 +0,2 @@ | ||
export default class WriteBuffer extends Array { | ||
export default class WriteBuffer extends Array<number> { | ||
push8(val: number): WriteBuffer; | ||
@@ -3,0 +3,0 @@ push16(val: number): WriteBuffer; |
{ | ||
"name": "@betaflight/msp", | ||
"version": "0.2.0", | ||
"version": "0.3.0", | ||
"description": "A MultiWii Serial Protocol library to connect and communicate with flight controllers", | ||
@@ -42,3 +42,3 @@ "license": "MIT", | ||
}, | ||
"gitHead": "37d7d212123ed5d806f8bf54a976f91886601693" | ||
"gitHead": "688344fb75f271b76389d903f2ab1373f5916b28" | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
1212235
1585
0