@betaflight/api
Version:
A high-level API to read data from betaflight flight controllers
804 lines • 38.6 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.readAdvancedConfig = exports.writeBoardAlignmentConfig = exports.readBoardAlignmentConfig = exports.commit = exports.reboot = exports.resetConfig = exports.calibrateAccelerometer = exports.writeArming = exports.readRCDeadband = exports.readRCTuning = exports.readRcValues = exports.writeEnabledFeatures = exports.readEnabledFeatures = exports.readExtendedStatus = exports.readStatus = exports.readAttitude = exports.readIMUData = exports.readRawGPS = exports.readAnalogValues = exports.readUID = exports.writeName = exports.readName = exports.readFcVariant = exports.readBoardInfo = exports.mergeDeep = exports.blackboxDevices = exports.gpsProtocols = exports.channelLetters = exports.availableFeatures = exports.MIXER_LIST = exports.mcuGroupFromId = exports.MCU_GROUPS = exports.rcSmoothingDerivativeTypes = exports.rcSmoothingInputTypes = exports.rcSmoothingTypes = exports.rcSmoothingChannels = exports.rcInterpolations = exports.spiRxProtocols = exports.serialRxProviders = exports.escProtocols = exports.initialiseSerialBackend = exports.baudRate = exports.ports = exports.packetErrors = exports.bytesWritten = exports.bytesRead = exports.isOpen = exports.close = exports.open = exports.apiVersion = void 0;
exports.eraseDataFlash = exports.readSdCardSummary = exports.readDataFlashSummary = exports.readDataFlashChunk = exports.writePartialBlackboxConfig = exports.writeBlackboxConfig = exports.readBlackboxConfig = exports.writeGpsConfig = exports.readGpsConfig = exports.writeRssiConfig = exports.readRssiConfig = exports.writeRxMap = exports.readRxMap = exports.writePartialRxConfig = exports.writeRxConfig = exports.readRxConfig = exports.writeDisabledSensors = exports.readDisabledSensors = exports.writePartialBeeperConfig = exports.writeBeeperConfig = exports.readBeeperConfig = exports.writePartialAdvancedConfig = exports.writeAdvancedConfig = void 0;
const semver_1 = __importDefault(require("semver"));
const msp_1 = require("@betaflight/msp");
const codes_1 = __importDefault(require("./codes"));
const types_1 = require("./types");
const features_1 = require("./features");
const utils_1 = require("./utils");
const huffman_1 = require("./huffman");
__exportStar(require("./osd"), exports);
__exportStar(require("./power"), exports);
__exportStar(require("./pid"), exports);
__exportStar(require("./motors"), exports);
__exportStar(require("./serial"), exports);
__exportStar(require("./modes"), exports);
__exportStar(require("./vtx"), exports);
__exportStar(require("./types"), exports);
var msp_2 = require("@betaflight/msp");
Object.defineProperty(exports, "apiVersion", { enumerable: true, get: function () { return msp_2.apiVersion; } });
Object.defineProperty(exports, "open", { enumerable: true, get: function () { return msp_2.open; } });
Object.defineProperty(exports, "close", { enumerable: true, get: function () { return msp_2.close; } });
Object.defineProperty(exports, "isOpen", { enumerable: true, get: function () { return msp_2.isOpen; } });
Object.defineProperty(exports, "bytesRead", { enumerable: true, get: function () { return msp_2.bytesRead; } });
Object.defineProperty(exports, "bytesWritten", { enumerable: true, get: function () { return msp_2.bytesWritten; } });
Object.defineProperty(exports, "packetErrors", { enumerable: true, get: function () { return msp_2.packetErrors; } });
Object.defineProperty(exports, "ports", { enumerable: true, get: function () { return msp_2.ports; } });
Object.defineProperty(exports, "baudRate", { enumerable: true, get: function () { return msp_2.baudRate; } });
Object.defineProperty(exports, "initialiseSerialBackend", { enumerable: true, get: function () { return msp_2.initialiseSerialBackend; } });
var features_2 = require("./features");
Object.defineProperty(exports, "escProtocols", { enumerable: true, get: function () { return features_2.escProtocols; } });
Object.defineProperty(exports, "serialRxProviders", { enumerable: true, get: function () { return features_2.serialRxProviders; } });
Object.defineProperty(exports, "spiRxProtocols", { enumerable: true, get: function () { return features_2.spiRxProtocols; } });
Object.defineProperty(exports, "rcInterpolations", { enumerable: true, get: function () { return features_2.rcInterpolations; } });
Object.defineProperty(exports, "rcSmoothingChannels", { enumerable: true, get: function () { return features_2.rcSmoothingChannels; } });
Object.defineProperty(exports, "rcSmoothingTypes", { enumerable: true, get: function () { return features_2.rcSmoothingTypes; } });
Object.defineProperty(exports, "rcSmoothingInputTypes", { enumerable: true, get: function () { return features_2.rcSmoothingInputTypes; } });
Object.defineProperty(exports, "rcSmoothingDerivativeTypes", { enumerable: true, get: function () { return features_2.rcSmoothingDerivativeTypes; } });
Object.defineProperty(exports, "MCU_GROUPS", { enumerable: true, get: function () { return features_2.MCU_GROUPS; } });
Object.defineProperty(exports, "mcuGroupFromId", { enumerable: true, get: function () { return features_2.mcuGroupFromId; } });
Object.defineProperty(exports, "MIXER_LIST", { enumerable: true, get: function () { return features_2.MIXER_LIST; } });
Object.defineProperty(exports, "availableFeatures", { enumerable: true, get: function () { return features_2.availableFeatures; } });
Object.defineProperty(exports, "channelLetters", { enumerable: true, get: function () { return features_2.channelLetters; } });
Object.defineProperty(exports, "gpsProtocols", { enumerable: true, get: function () { return features_2.gpsProtocols; } });
Object.defineProperty(exports, "blackboxDevices", { enumerable: true, get: function () { return features_2.blackboxDevices; } });
var utils_2 = require("./utils");
Object.defineProperty(exports, "mergeDeep", { enumerable: true, get: function () { return utils_2.mergeDeep; } });
const readBoardInfo = async (port) => {
const api = (0, msp_1.apiVersion)(port);
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_BOARD_INFO });
return {
boardIdentifier: String.fromCharCode(...(0, utils_1.times)(() => data.readU8(), 4)),
boardVersion: data.readU16(),
boardType: semver_1.default.gte(api, "1.35.0") ? data.readU8() : 0,
targetCapabilities: (0, utils_1.unpackValues)(semver_1.default.gte(api, "1.37.0") ? data.readU8() : 0, (0, features_1.targetCapabilities)()),
targetName: semver_1.default.gte(api, "1.37.0")
? String.fromCharCode(...(0, utils_1.times)(() => data.readU8(), data.readU8()))
: "",
boardName: semver_1.default.gte(api, "1.41.0")
? String.fromCharCode(...(0, utils_1.times)(() => data.readU8(), data.readU8()))
: "",
manufacturerId: semver_1.default.gte(api, "1.41.0")
? String.fromCharCode(...(0, utils_1.times)(() => data.readU8(), data.readU8()))
: "",
signature: semver_1.default.gte(api, "1.41.0") ? (0, utils_1.times)(() => data.readU8(), 32) : [],
mcuTypeId: semver_1.default.gte(api, "1.41.0") ? data.readU8() : 255,
configurationState: semver_1.default.gte(api, "1.42.0") ? data.readU8() : undefined,
sampleRateHz: semver_1.default.gte(api, "1.43.0") ? data.readU16() : undefined,
};
};
exports.readBoardInfo = readBoardInfo;
const readFcVariant = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_FC_VARIANT });
return String.fromCharCode(...(0, utils_1.times)(() => data.readU8(), 4));
};
exports.readFcVariant = readFcVariant;
const readName = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_NAME });
return String.fromCharCode(...(0, utils_1.times)(() => data.readU8(), data.byteLength));
};
exports.readName = readName;
const MAX_NAME_BUFFER_SIZE = 64;
const writeName = async (port, name) => {
const buffer = Buffer.from(name.slice(0, MAX_NAME_BUFFER_SIZE));
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_SET_NAME, data: buffer });
};
exports.writeName = writeName;
const readUID = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_UID });
return (0, utils_1.times)(() => (data.readU32() + 16 ** 6).toString(16).substr(-6), 3).join("");
};
exports.readUID = readUID;
const readAnalogValues = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_ANALOG });
const values = {
voltage: data.readU8() / 10.0,
mahDrawn: data.readU16(),
rssi: Math.round((data.readU16() / 1023) * 100),
amperage: data.read16() / 100, // A
};
if (semver_1.default.gte((0, msp_1.apiVersion)(port), "1.41.0")) {
values.voltage = data.readU16() / 100;
}
return values;
};
exports.readAnalogValues = readAnalogValues;
const readRawGPS = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_RAW_GPS });
return {
fix: !!data.readU8(),
numSat: data.readU8(),
lat: data.read32(),
lon: data.read32(),
alt: data.readU16(),
speed: data.readU16(),
groundCourse: data.readU16(),
};
};
exports.readRawGPS = readRawGPS;
const readIMUData = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_RAW_IMU });
const accUnit = () => data.read16() / 512;
const gyroUnit = () => data.read16() * (4 / 16.4);
const mangetUnit = () => data.read16() / 1090;
return {
accelerometer: (0, utils_1.times)(accUnit, 3),
gyroscope: (0, utils_1.times)(gyroUnit, 3),
magnetometer: (0, utils_1.times)(mangetUnit, 3),
};
};
exports.readIMUData = readIMUData;
const readAttitude = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_ATTITUDE });
return {
roll: data.read16() / 10.0,
pitch: data.read16() / 10.0,
yaw: data.read16(), // z
};
};
exports.readAttitude = readAttitude;
const extractStatus = (data) => ({
cycleTime: data.readU16(),
i2cError: data.readU16(),
sensors: (0, utils_1.unpackValues)(data.readU16(), (0, features_1.sensorBits)()),
mode: data.readU32(),
profile: data.readU8(),
});
const readStatus = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_STATUS });
return extractStatus(data);
};
exports.readStatus = readStatus;
const readExtendedStatus = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_STATUS_EX });
const api = (0, msp_1.apiVersion)(port);
const status = {
...extractStatus(data),
cpuload: data.readU16(),
numProfiles: 0,
rateProfile: 0,
armingDisabledFlags: [],
};
if (semver_1.default.gte(api, "1.16.0")) {
status.numProfiles = data.readU8();
status.rateProfile = data.readU8();
}
if (semver_1.default.gte(api, "1.36.0")) {
// skip all this data for some reason
(0, utils_1.times)(() => data.readU8(), data.readU8());
const flags = (0, features_1.disarmFlagBits)(api);
// Read arming disable flags
const numFlags = data.readU8();
const flagBits = data.readU32();
// read the enabled disarm flags from the mask
status.armingDisabledFlags = (0, utils_1.times)((i) => { var _a; return (flagBits & (1 << i)) !== 0 && ((_a = flags[i]) !== null && _a !== void 0 ? _a : types_1.DisarmFlags.UNKNOWN); }, numFlags).filter((flag) => typeof flag === "number");
}
return status;
};
exports.readExtendedStatus = readExtendedStatus;
const readEnabledFeatures = async (port) => {
const schema = (0, features_1.availableFeatures)((0, msp_1.apiVersion)(port));
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_FEATURE_CONFIG });
const featureMask = data.readU32();
return Object.entries(schema)
.filter(([bit]) => (featureMask >> Number(bit)) % 2 !== 0)
.map(([, feature]) => feature);
};
exports.readEnabledFeatures = readEnabledFeatures;
const writeEnabledFeatures = async (port, features) => {
const schema = (0, features_1.availableFeatures)((0, msp_1.apiVersion)(port));
const buffer = new msp_1.WriteBuffer();
buffer.push32(Object.entries(schema)
.filter(([, feature]) => features.includes(feature))
.reduce((acc, [bit]) => acc | (1 << Number(bit)), 0));
await (0, msp_1.execute)(port, {
code: codes_1.default.MSP_SET_FEATURE_CONFIG,
data: buffer,
});
};
exports.writeEnabledFeatures = writeEnabledFeatures;
const readRcValues = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_RC });
return new Array(data.byteLength / 2).fill(0).map(() => data.readU16());
};
exports.readRcValues = readRcValues;
const readRCTuning = async (port) => {
const version = (0, msp_1.apiVersion)(port);
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_RC_TUNING });
const tuning = {
rcRate: 0,
rcExpo: 0,
rollPitchRate: 0,
pitchRate: 0,
rollRate: 0,
yawRate: 0,
dynamicThrottlePid: 0,
throttleMid: 0,
throttleExpo: 0,
dynamicThrottleBreakpoint: 0,
rcYawExpo: 0,
rcYawRate: 0,
rcPitchRate: 0,
rcPitchExpo: 0,
throttleLimitType: 0,
throttleLimitPercent: 0,
rollRateLimit: 0,
pitchRateLimit: 0,
yawRateLimit: 0,
};
tuning.rcRate = parseFloat((data.readU8() / 100).toFixed(2));
tuning.rcExpo = parseFloat((data.readU8() / 100).toFixed(2));
if (semver_1.default.lt(version, "1.7.0")) {
tuning.rollPitchRate = parseFloat((data.readU8() / 100).toFixed(2));
}
else {
tuning.rollRate = parseFloat((data.readU8() / 100).toFixed(2));
tuning.pitchRate = parseFloat((data.readU8() / 100).toFixed(2));
}
tuning.yawRate = parseFloat((data.readU8() / 100).toFixed(2));
tuning.dynamicThrottlePid = parseFloat((data.readU8() / 100).toFixed(2));
tuning.throttleMid = parseFloat((data.readU8() / 100).toFixed(2));
tuning.throttleExpo = parseFloat((data.readU8() / 100).toFixed(2));
tuning.dynamicThrottleBreakpoint = semver_1.default.gte(version, "1.7.0")
? data.readU16()
: 0;
if (semver_1.default.gte(version, "1.10.0")) {
tuning.rcYawExpo = parseFloat((data.readU8() / 100).toFixed(2));
if (semver_1.default.gte(version, "1.16.0")) {
tuning.rcYawRate = parseFloat((data.readU8() / 100).toFixed(2));
}
}
if (semver_1.default.gte(version, "1.37.0")) {
tuning.rcPitchRate = parseFloat((data.readU8() / 100).toFixed(2));
tuning.rcPitchExpo = parseFloat((data.readU8() / 100).toFixed(2));
}
if (semver_1.default.gte(version, "1.41.0")) {
tuning.throttleLimitType = data.readU8();
tuning.throttleLimitPercent = data.readU8();
}
if (semver_1.default.gte(version, "1.42.0")) {
tuning.rollRateLimit = data.readU16();
tuning.pitchRateLimit = data.readU16();
tuning.yawRateLimit = data.readU16();
}
return tuning;
};
exports.readRCTuning = readRCTuning;
const readRCDeadband = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_RC_DEADBAND });
return {
deadband: data.readU8(),
yawDeadband: data.readU8(),
altHoldDeadhand: data.readU8(),
deadband3dThrottle: semver_1.default.gte((0, msp_1.apiVersion)(port), "1.17.0")
? data.readU16()
: 0,
};
};
exports.readRCDeadband = readRCDeadband;
const writeArming = async (port, { armingDisabled, runawayTakeoffPreventionDisabled, }) => {
const data = new msp_1.WriteBuffer();
data.push8(Number(armingDisabled));
data.push8(Number(runawayTakeoffPreventionDisabled));
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_ARMING_DISABLE, data });
};
exports.writeArming = writeArming;
const calibrateAccelerometer = async (port) => {
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_ACC_CALIBRATION });
// This command executes on the device, but doesn't actually produce anything
// for about 2 seconds, so resolve after 2 seconds
await (0, utils_1.sleep)(2000);
};
exports.calibrateAccelerometer = calibrateAccelerometer;
const resetConfig = async (port) => {
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_RESET_CONF });
// This command executes on the device, but doesn't actually produce anything
// for about 2 seconds, so resolve after 2 seconds
await (0, utils_1.sleep)(2000);
};
exports.resetConfig = resetConfig;
/**
* Set the device to reboot, returning true if successful
*/
const reboot = async (port, type) => {
const api = (0, msp_1.apiVersion)(port);
const data = await (0, msp_1.execute)(port, {
code: codes_1.default.MSP_SET_REBOOT,
data: type ? [type] : undefined,
timeout: 3000,
}).catch((e) => {
if (!(0, msp_1.isOpen)(port)) {
return undefined;
}
throw e;
});
if (data && semver_1.default.gte(api, "1.40.0")) {
const rebootType = data.read8();
if (rebootType === types_1.RebootTypes.MSC || rebootType === types_1.RebootTypes.MSC_UTC) {
if (data.read8() === 0) {
return false;
}
}
}
return true;
};
exports.reboot = reboot;
const commit = async (port) => {
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_EEPROM_WRITE });
};
exports.commit = commit;
const readBoardAlignmentConfig = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_BOARD_ALIGNMENT_CONFIG });
return {
roll: data.read16(),
pitch: data.read16(),
yaw: data.read16(),
};
};
exports.readBoardAlignmentConfig = readBoardAlignmentConfig;
const writeBoardAlignmentConfig = async (port, { roll, pitch, yaw }) => {
await (0, msp_1.execute)(port, {
code: codes_1.default.MSP_SET_BOARD_ALIGNMENT_CONFIG,
data: new msp_1.WriteBuffer().push16(roll).push16(pitch).push16(yaw),
});
};
exports.writeBoardAlignmentConfig = writeBoardAlignmentConfig;
const readAdvancedConfig = async (port) => {
const api = (0, msp_1.apiVersion)(port);
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_ADVANCED_CONFIG });
const config = {
gyroSyncDenom: 0,
pidProcessDenom: 0,
useUnsyncedPwm: false,
fastPwmProtocol: 0,
gyroToUse: 0,
motorPwmRate: 0,
digitalIdlePercent: 0,
gyroUse32kHz: false,
motorPwmInversion: 0,
gyroHighFsr: 0,
gyroMovementCalibThreshold: 0,
gyroCalibDuration: 0,
gyroOffsetYaw: 0,
gyroCheckOverflow: 0,
debugMode: 0,
debugModeCount: 0,
};
config.gyroSyncDenom = data.readU8();
config.pidProcessDenom = data.readU8();
config.useUnsyncedPwm = data.readU8() !== 0;
config.fastPwmProtocol = (0, utils_1.toIdentifier)((0, features_1.escProtocols)(api), data.readU8());
config.motorPwmRate = data.readU16();
if (semver_1.default.gte(api, "1.24.0")) {
config.digitalIdlePercent = data.readU16() / 100;
}
if (semver_1.default.gte(api, "1.25.0")) {
const gyroUse32kHz = data.readU8();
if (semver_1.default.lt(api, "1.41.0")) {
config.gyroUse32kHz = gyroUse32kHz !== 0;
}
}
if (semver_1.default.gte(api, "1.42.0")) {
config.motorPwmInversion = data.readU8();
// gyroToUse (read by MSP_SENSOR_ALIGNMENT)
config.gyroToUse = data.readU8();
config.gyroHighFsr = data.readU8();
config.gyroMovementCalibThreshold = data.readU8();
config.gyroCalibDuration = data.readU16();
config.gyroOffsetYaw = data.readU16();
config.gyroCheckOverflow = data.readU8();
config.debugMode = data.readU8();
config.debugModeCount = data.readU8();
}
return config;
};
exports.readAdvancedConfig = readAdvancedConfig;
const writeAdvancedConfig = async (port, config) => {
var _a;
const api = (0, msp_1.apiVersion)(port);
const buffer = new msp_1.WriteBuffer();
buffer
.push8(config.gyroSyncDenom)
.push8(config.pidProcessDenom)
.push8(config.useUnsyncedPwm ? 1 : 0)
.push8((_a = (0, utils_1.fromIdentifier)((0, features_1.escProtocols)(api), config.fastPwmProtocol)) !== null && _a !== void 0 ? _a : config.fastPwmProtocol)
.push16(config.motorPwmRate);
if (semver_1.default.gte(api, "1.24.0")) {
buffer.push16(config.digitalIdlePercent * 100);
}
if (semver_1.default.gte(api, "1.25.0")) {
let gyroUse32kHz = 0;
if (semver_1.default.lt(api, "1.41.0")) {
gyroUse32kHz = config.gyroUse32kHz ? 1 : 0;
}
buffer.push8(gyroUse32kHz);
}
if (semver_1.default.gte(api, "1.42.0")) {
buffer
.push8(config.motorPwmInversion)
.push8(config.gyroToUse)
.push8(config.gyroHighFsr)
.push8(config.gyroMovementCalibThreshold)
.push16(config.gyroCalibDuration)
.push16(config.gyroOffsetYaw)
.push8(config.gyroCheckOverflow)
.push8(config.debugMode);
}
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_SET_ADVANCED_CONFIG, data: buffer });
};
exports.writeAdvancedConfig = writeAdvancedConfig;
exports.writePartialAdvancedConfig = (0, utils_1.partialWriteFunc)(exports.readAdvancedConfig, exports.writeAdvancedConfig);
const ALLOWED_DSHOT_CONDITIONS = [types_1.Beepers.RX_SET, types_1.Beepers.RX_LOST];
const readBeeperConfig = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_BEEPER_CONFIG });
const api = (0, msp_1.apiVersion)(port);
const beeperSchema = (0, features_1.beeperBits)(api);
return {
// For some reason, the flag bits are actually inverted for both
// read and write
conditions: (0, utils_1.unpackValues)(data.readU32(), beeperSchema, { inverted: true }),
dshot: {
tone: semver_1.default.gte(api, "1.37.0") ? data.readU8() : 0,
conditions: semver_1.default.gte(api, "1.39.0")
? (0, utils_1.unpackValues)(data.readU32(), beeperSchema, {
inverted: true,
}).filter((beeper) => ALLOWED_DSHOT_CONDITIONS.includes(beeper))
: [],
},
};
};
exports.readBeeperConfig = readBeeperConfig;
const writeBeeperConfig = async (port, config) => {
const api = (0, msp_1.apiVersion)(port);
const beeperSchema = (0, features_1.beeperBits)(api);
const buffer = new msp_1.WriteBuffer();
buffer.push32((0, utils_1.packValues)(config.conditions, beeperSchema, {
inverted: true,
}));
if (semver_1.default.gte(api, "1.37.0")) {
buffer.push8(config.dshot.tone);
}
if (semver_1.default.gte(api, "1.39.0")) {
buffer.push32((0, utils_1.packValues)(config.dshot.conditions.filter((con) => ALLOWED_DSHOT_CONDITIONS.includes(con)), beeperSchema, { inverted: true }));
}
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_SET_BEEPER_CONFIG, data: buffer });
};
exports.writeBeeperConfig = writeBeeperConfig;
exports.writePartialBeeperConfig = (0, utils_1.partialWriteFunc)(exports.readBeeperConfig, exports.writeBeeperConfig);
const readDisabledSensors = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_SENSOR_CONFIG });
const schema = (0, features_1.sensorBits)();
const disabled = [];
schema.forEach((sensor) => {
if (data.remaining() > 0 && data.read8() === 1) {
disabled.push(sensor);
}
});
return disabled;
};
exports.readDisabledSensors = readDisabledSensors;
const writeDisabledSensors = async (port, disabledSensors) => {
const buffer = new msp_1.WriteBuffer();
[types_1.Sensors.ACCELEROMETER, types_1.Sensors.BAROMETER, types_1.Sensors.MAGNETOMETER].forEach((sensor) => {
buffer.push8(disabledSensors.includes(sensor) ? 1 : 0);
});
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_SET_SENSOR_CONFIG, data: buffer });
};
exports.writeDisabledSensors = writeDisabledSensors;
const readRxConfig = async (port) => {
const api = (0, msp_1.apiVersion)(port);
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_RX_CONFIG });
const initial = {
serialProvider: (0, utils_1.toIdentifier)((0, features_1.serialRxProviders)(api), data.readU8()),
stick: {
max: data.readU16(),
center: data.readU16(),
min: data.readU16(),
},
spektrumSatBind: data.readU8(),
rxMinUsec: data.readU16(),
rxMaxUsec: data.readU16(),
...(semver_1.default.gte(api, "1.20.0")
? {
interpolation: (0, utils_1.toIdentifier)((0, features_1.rcInterpolations)(), data.readU8()),
interpolationInterval: data.readU8(),
airModeActivateThreshold: data.readU16(),
}
: {
interpolation: types_1.RcInterpolations.AUTO,
interpolationInterval: 0,
airModeActivateThreshold: 0,
}),
...(semver_1.default.gte(api, "1.31.0")
? {
spi: {
protocol: (0, utils_1.toIdentifier)((0, features_1.spiRxProtocols)(api), data.readU8()),
id: data.readU32(),
rfChannelCount: data.readU8(),
},
fpvCamAngleDegrees: data.readU8(),
}
: {
spi: {
protocol: types_1.SpiRxProtocols.NRF24_V202_250K,
id: 0,
rfChannelCount: 0,
},
fpvCamAngleDegrees: 0,
}),
};
const smoothing = semver_1.default.gte(api, "1.40.0")
? {
channels: (0, utils_1.toIdentifier)((0, features_1.rcSmoothingChannels)(), data.readU8()),
type: (0, utils_1.toIdentifier)((0, features_1.rcSmoothingTypes)(), data.readU8()),
inputCutoff: data.readU8(),
derivativeCutoff: data.readU8(),
inputType: (0, utils_1.toIdentifier)((0, features_1.rcSmoothingInputTypes)(), data.readU8()),
derivativeType: (0, utils_1.toIdentifier)((0, features_1.rcSmoothingDerivativeTypes)(api), data.readU8()),
}
: {
channels: types_1.RcSmoothingChannels.RP,
type: types_1.RcSmoothingTypes.INTERPOLATION,
inputCutoff: 0,
derivativeCutoff: 0,
inputType: types_1.RcSmoothingInputTypes.PT1,
derivativeType: types_1.RcSmoothingDerivativeTypes.AUTO,
};
return {
...initial,
...(semver_1.default.gte(api, "1.42.0")
? { usbCdcHidType: data.readU8() }
: { usbCdcHidType: 0 }),
rcSmoothing: {
...smoothing,
...(semver_1.default.gte(api, "1.42.0")
? {
autoSmoothness: data.readU8(),
}
: { autoSmoothness: 0 }),
},
};
};
exports.readRxConfig = readRxConfig;
const writeRxConfig = async (port, config) => {
var _a, _b, _c, _d, _e, _f, _g;
const api = (0, msp_1.apiVersion)(port);
const buffer = new msp_1.WriteBuffer();
buffer
.push8((_a = (0, utils_1.fromIdentifier)((0, features_1.serialRxProviders)(api), config.serialProvider)) !== null && _a !== void 0 ? _a : config.serialProvider)
.push16(config.stick.max)
.push16(config.stick.center)
.push16(config.stick.center)
.push8(config.spektrumSatBind)
.push16(config.rxMinUsec)
.push16(config.rxMaxUsec);
if (semver_1.default.gte(api, "1.20.0")) {
buffer
.push8((_b = (0, utils_1.fromIdentifier)((0, features_1.rcInterpolations)(), config.interpolation)) !== null && _b !== void 0 ? _b : config.interpolation)
.push8(config.interpolationInterval)
.push16(config.airModeActivateThreshold);
}
if (semver_1.default.gte(api, "1.31.0")) {
buffer
.push8((_c = (0, utils_1.fromIdentifier)((0, features_1.spiRxProtocols)(api), config.spi.protocol)) !== null && _c !== void 0 ? _c : config.spi.protocol)
.push32(config.spi.id)
.push8(config.spi.rfChannelCount)
.push8(config.fpvCamAngleDegrees);
}
if (semver_1.default.gte(api, "1.40.0")) {
buffer
.push8((_d = (0, utils_1.fromIdentifier)((0, features_1.rcSmoothingChannels)(), config.rcSmoothing.channels)) !== null && _d !== void 0 ? _d : config.rcSmoothing.channels)
.push8((_e = (0, utils_1.fromIdentifier)((0, features_1.rcSmoothingTypes)(), config.rcSmoothing.type)) !== null && _e !== void 0 ? _e : config.rcSmoothing.type)
.push8(config.rcSmoothing.inputCutoff)
.push8(config.rcSmoothing.derivativeCutoff)
.push8((_f = (0, utils_1.fromIdentifier)((0, features_1.rcSmoothingInputTypes)(), config.rcSmoothing.inputType)) !== null && _f !== void 0 ? _f : config.rcSmoothing.inputType)
.push8((_g = (0, utils_1.fromIdentifier)((0, features_1.rcSmoothingDerivativeTypes)(api), config.rcSmoothing.derivativeType)) !== null && _g !== void 0 ? _g : config.rcSmoothing.derivativeType);
}
if (semver_1.default.gte(api, "1.42.0")) {
buffer.push8(config.usbCdcHidType).push8(config.rcSmoothing.autoSmoothness);
}
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_SET_RX_CONFIG, data: buffer });
};
exports.writeRxConfig = writeRxConfig;
exports.writePartialRxConfig = (0, utils_1.partialWriteFunc)(exports.readRxConfig, exports.writeRxConfig);
const readRxMap = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_RX_MAP });
const schema = (0, features_1.channelLetters)();
const map = new Array(8).fill("A");
schema.forEach((letter) => {
map[data.readU8()] = letter;
});
return map;
};
exports.readRxMap = readRxMap;
const writeRxMap = async (port, map) => {
const buffer = new msp_1.WriteBuffer();
const schema = (0, features_1.channelLetters)();
schema.forEach((letter) => {
const value = typeof letter !== "number" ? map.indexOf(letter) : letter;
buffer.push8(value);
});
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_SET_RX_MAP, data: buffer });
};
exports.writeRxMap = writeRxMap;
const readRssiConfig = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_RSSI_CONFIG });
return {
channel: data.readU8(),
};
};
exports.readRssiConfig = readRssiConfig;
const writeRssiConfig = async (port, config) => {
const buffer = new msp_1.WriteBuffer();
buffer.push8(config.channel);
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_SET_RSSI_CONFIG, data: buffer });
};
exports.writeRssiConfig = writeRssiConfig;
const readGpsConfig = async (port) => {
const api = (0, msp_1.apiVersion)(port);
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_GPS_CONFIG });
// gps not enabled, not exactly good api from the FC
if (data.byteLength === 0) {
return {
provider: types_1.GpsProtocols.NMEA,
ubloxSbas: types_1.GpsSbasTypes.AUTO,
autoConfig: false,
autoBaud: false,
homePointOnce: false,
ubloxUseGalileo: false,
};
}
return {
provider: (0, utils_1.toIdentifier)((0, features_1.gpsProtocols)(api), data.readU8()),
ubloxSbas: data.readU8(),
autoConfig: semver_1.default.gte(api, "1.34.0") ? data.readU8() === 1 : false,
autoBaud: semver_1.default.gte(api, "1.34.0") ? data.readU8() === 1 : false,
homePointOnce: semver_1.default.gte(api, "1.43.0") ? data.readU8() === 1 : false,
ubloxUseGalileo: semver_1.default.gte(api, "1.43.0") ? data.readU8() === 1 : false,
};
};
exports.readGpsConfig = readGpsConfig;
const writeGpsConfig = async (port, config) => {
var _a;
const api = (0, msp_1.apiVersion)(port);
const buffer = new msp_1.WriteBuffer();
buffer
.push8((_a = (0, utils_1.fromIdentifier)((0, features_1.gpsProtocols)(api), config.provider)) !== null && _a !== void 0 ? _a : config.provider)
.push8(config.ubloxSbas);
if (semver_1.default.gte(api, "1.34.0")) {
buffer.push8(config.autoConfig ? 1 : 0).push8(config.autoBaud ? 1 : 0);
}
if (semver_1.default.gte(api, "1.43.0")) {
buffer
.push8(config.homePointOnce ? 1 : 0)
.push8(config.ubloxUseGalileo ? 1 : 0);
}
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_SET_GPS_CONFIG, data: buffer });
};
exports.writeGpsConfig = writeGpsConfig;
const readBlackboxConfig = async (port) => {
const api = (0, msp_1.apiVersion)(port);
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_BLACKBOX_CONFIG });
return {
supported: (data.readU8() & 1) !== 0,
device: (0, utils_1.toIdentifier)((0, features_1.blackboxDevices)(api), data.readU8()),
rateNum: data.readU8(),
rateDenom: data.readU8(),
pDenom: semver_1.default.gte(api, "1.36.0") ? data.readU16() : 0,
sampleRate: semver_1.default.gte(api, "1.44.0") ? data.readU8() : 0,
};
};
exports.readBlackboxConfig = readBlackboxConfig;
const writeBlackboxConfig = async (port, config) => {
var _a;
const api = (0, msp_1.apiVersion)(port);
const buffer = new msp_1.WriteBuffer();
buffer
.push8((_a = (0, utils_1.fromIdentifier)((0, features_1.blackboxDevices)(api), config.device)) !== null && _a !== void 0 ? _a : config.device)
.push8(config.rateNum)
.push8(config.rateDenom);
if (semver_1.default.gte(api, "1.36.0")) {
buffer.push16(config.pDenom);
}
if (semver_1.default.gte(api, "1.44.0")) {
buffer.push8(config.sampleRate);
}
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_SET_BLACKBOX_CONFIG, data: buffer });
};
exports.writeBlackboxConfig = writeBlackboxConfig;
exports.writePartialBlackboxConfig = (0, utils_1.partialWriteFunc)(exports.readBlackboxConfig, exports.writeBlackboxConfig);
/**
* Return the base 64 encoded result of the blackbox config
*/
const readDataFlashChunk = async (port, address, blockSize) => {
const api = (0, msp_1.apiVersion)(port);
const args = new msp_1.WriteBuffer();
args.push32(address);
if (semver_1.default.gte(api, "1.31.0")) {
args.push16(blockSize);
}
if (semver_1.default.gte(api, "1.36.0")) {
args.push8(1);
}
const data = await (0, msp_1.execute)(port, {
code: codes_1.default.MSP_DATAFLASH_READ,
data: args,
timeout: 1000,
match: (response) => response.readU32() === address,
});
// ignore the address as this was
// checked by the executor
data.readU32();
const headerSize = semver_1.default.gte(api, "1.31.0") ? 7 : 4;
const dataSize = semver_1.default.gte(api, "1.31.0")
? data.readU16()
: data.buffer.byteLength - headerSize;
const compressed = semver_1.default.gte(api, "1.31.0") && data.readU8() === 1;
/* Strip that address off the front of the reply and deliver it separately so the caller doesn't have to
* figure out the reply format:
*/
if (!compressed) {
return Buffer.from(new Uint8Array(data.buffer, data.byteOffset + headerSize, dataSize));
}
// Read compressed char count to avoid decoding stray bit sequences as bytes
const compressedCharCount = data.readU16();
// Compressed format uses 2 additional bytes as a pseudo-header to denote the number of uncompressed bytes
const compressedArray = Buffer.from(new Uint8Array(data.buffer, data.byteOffset + headerSize + 2, dataSize - 2));
const decompressedArray = (0, huffman_1.huffmanDecodeBuffer)(compressedArray, compressedCharCount);
return decompressedArray;
};
exports.readDataFlashChunk = readDataFlashChunk;
const readDataFlashSummary = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_DATAFLASH_SUMMARY });
if (data.byteLength >= 13) {
const flags = data.readU8();
return {
ready: (flags & 1) !== 0,
supported: (flags & 2) !== 0,
sectors: data.readU32(),
totalSize: data.readU32(),
usedSize: data.readU32(),
};
}
// Firmware version too old to support MSP_DATAFLASH_SUMMARY
return {
ready: false,
supported: false,
sectors: 0,
totalSize: 0,
usedSize: 0,
};
};
exports.readDataFlashSummary = readDataFlashSummary;
const readSdCardSummary = async (port) => {
const data = await (0, msp_1.execute)(port, { code: codes_1.default.MSP_SDCARD_SUMMARY });
const flags = data.readU8();
return {
supported: (flags & 0x01) !== 0,
state: data.readU8(),
filesystemLastError: data.readU8(),
freeSizeKB: data.readU32(),
totalSizeKB: data.readU32(),
};
};
exports.readSdCardSummary = readSdCardSummary;
const eraseDataFlash = async (port) => {
await (0, msp_1.execute)(port, { code: codes_1.default.MSP_DATAFLASH_ERASE });
};
exports.eraseDataFlash = eraseDataFlash;
//# sourceMappingURL=index.js.map