mirror of
https://github.com/betaflight/betaflight-configurator.git
synced 2025-07-15 12:25:15 +03:00
Show SmartAudio version on VTX tab; MSP reads vtx device status
This commit is contained in:
parent
d5d0146af7
commit
f872f1375f
12 changed files with 301 additions and 9 deletions
|
@ -5651,6 +5651,10 @@
|
|||
"message": "Saved",
|
||||
"description": "Saved action button in the VTX tab"
|
||||
},
|
||||
"vtxSmartAudioUnlocked": {
|
||||
"message": "{{version}} unlocked",
|
||||
"description": "Indicates if SA device is unlocked"
|
||||
},
|
||||
|
||||
"mainHelpArmed": {
|
||||
"message": "Motor Arming"
|
||||
|
|
|
@ -153,6 +153,7 @@ const FC = {
|
|||
VTXTABLE_BAND: null,
|
||||
VTXTABLE_POWERLEVEL: null,
|
||||
VTX_CONFIG: null,
|
||||
VTX_DEVICE_STATUS: null,
|
||||
|
||||
resetState () {
|
||||
// Using `Object.assign` instead of reassigning to
|
||||
|
@ -642,6 +643,8 @@ const FC = {
|
|||
46, 90, 38, 22, 95,
|
||||
30, 90, 0, 0, 90,
|
||||
];
|
||||
|
||||
this.VTX_DEVICE_STATUS = null;
|
||||
},
|
||||
|
||||
getSerialRxTypes: () => {
|
||||
|
|
|
@ -113,6 +113,21 @@ GuiControl.prototype.interval_add = function (name, code, interval, first) {
|
|||
return data;
|
||||
};
|
||||
|
||||
// name = string
|
||||
// code = function reference (code to be executed)
|
||||
// interval = time interval in miliseconds
|
||||
// first = true/false if code should be ran initially before next timer interval hits
|
||||
// condition = function reference with true/false result, a condition to be checked before every interval code execution
|
||||
GuiControl.prototype.interval_add_condition = function (name, code, interval, first, condition) {
|
||||
this.interval_add(name, () => {
|
||||
if (condition()) {
|
||||
code();
|
||||
} else {
|
||||
this.interval_remove(name);
|
||||
}
|
||||
}, interval, first);
|
||||
}
|
||||
|
||||
// name = string
|
||||
GuiControl.prototype.interval_remove = function (name) {
|
||||
for (let i = 0; i < this.interval_array.length; i++) {
|
||||
|
|
|
@ -182,4 +182,5 @@ const MSPCodes = {
|
|||
MSP2_MOTOR_OUTPUT_REORDERING: 0x3001,
|
||||
MSP2_SET_MOTOR_OUTPUT_REORDERING: 0x3002,
|
||||
MSP2_SEND_DSHOT_COMMAND: 0x3003,
|
||||
MSP2_GET_VTX_DEVICE_STATUS: 0x3004,
|
||||
};
|
||||
|
|
|
@ -144,6 +144,17 @@ MspHelper.prototype.process_data = function(dataHandler) {
|
|||
FC.MOTOR_OUTPUT_ORDER[i] = data.readU8();
|
||||
}
|
||||
break;
|
||||
case MSPCodes.MSP2_GET_VTX_DEVICE_STATUS:
|
||||
FC.VTX_DEVICE_STATUS = null;
|
||||
const dataLength = data.byteLength;
|
||||
if (dataLength > 0) {
|
||||
const vtxDeviceStatusData = new Uint8Array(dataLength);
|
||||
for (let i = 0; i < dataLength; i++) {
|
||||
vtxDeviceStatusData[i] = data.readU8();
|
||||
}
|
||||
FC.VTX_DEVICE_STATUS = vtxDeviceStatusFactory.createVtxDeviceStatus(vtxDeviceStatusData);
|
||||
}
|
||||
break;
|
||||
case MSPCodes.MSP_MOTOR_TELEMETRY:
|
||||
const telemMotorCount = data.readU8();
|
||||
for (let i = 0; i < telemMotorCount; i++) {
|
||||
|
|
|
@ -12,6 +12,39 @@ TABS.vtx = {
|
|||
analyticsChanges: {},
|
||||
updating: true,
|
||||
env: new djv(),
|
||||
get _DEVICE_STATUS_UPDATE_INTERVAL_NAME() {
|
||||
return "vtx_device_status_request";
|
||||
}
|
||||
};
|
||||
|
||||
TABS.vtx.isVtxDeviceStatusNotReady = function()
|
||||
{
|
||||
const isReady = (null !== FC.VTX_DEVICE_STATUS) && (FC.VTX_DEVICE_STATUS.deviceIsReady);
|
||||
return !isReady;
|
||||
};
|
||||
|
||||
TABS.vtx.updateVtxDeviceStatus = function()
|
||||
{
|
||||
MSP.send_message(MSPCodes.MSP2_GET_VTX_DEVICE_STATUS, false, false, vtxDeviceStatusReceived);
|
||||
|
||||
function vtxDeviceStatusReceived()
|
||||
{
|
||||
$("#vtx_type_description").text(TABS.vtx.getVtxTypeString());
|
||||
}
|
||||
};
|
||||
|
||||
TABS.vtx.getVtxTypeString = function()
|
||||
{
|
||||
let result = i18n.getMessage(`vtxType_${FC.VTX_CONFIG.vtx_type}`);
|
||||
|
||||
const isSmartAudio = VtxDeviceTypes.VTXDEV_SMARTAUDIO === FC.VTX_CONFIG.vtx_type;
|
||||
const isVtxDeviceStatusReceived = null !== FC.VTX_DEVICE_STATUS;
|
||||
|
||||
if (isSmartAudio && isVtxDeviceStatusReceived) {
|
||||
result += ` ${FC.VTX_DEVICE_STATUS.smartAudioVersion}`;
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
TABS.vtx.initialize = function (callback) {
|
||||
|
@ -55,7 +88,19 @@ TABS.vtx.initialize = function (callback) {
|
|||
vtx_config();
|
||||
|
||||
function vtx_config() {
|
||||
MSP.send_message(MSPCodes.MSP_VTX_CONFIG, false, false, vtxtable_bands);
|
||||
MSP.send_message(MSPCodes.MSP_VTX_CONFIG, false, false, vtxConfigReceived);
|
||||
}
|
||||
|
||||
function vtxConfigReceived() {
|
||||
if (semver.gte(FC.CONFIG.apiVersion, API_VERSION_1_44)) {
|
||||
GUI.interval_add_condition(self._DEVICE_STATUS_UPDATE_INTERVAL_NAME,
|
||||
TABS.vtx.updateVtxDeviceStatus,
|
||||
1000, false,
|
||||
TABS.vtx.isVtxDeviceStatusNotReady
|
||||
);
|
||||
}
|
||||
|
||||
vtxtable_bands();
|
||||
}
|
||||
|
||||
function vtxtable_bands() {
|
||||
|
@ -196,11 +241,11 @@ TABS.vtx.initialize = function (callback) {
|
|||
});
|
||||
|
||||
// Supported?
|
||||
const vtxSupported = FC.VTX_CONFIG.vtx_type !== 0 && FC.VTX_CONFIG.vtx_type !== 255;
|
||||
const vtxSupported = FC.VTX_CONFIG.vtx_type !== VtxDeviceTypes.VTXDEV_UNSUPPORTED && FC.VTX_CONFIG.vtx_type !== VtxDeviceTypes.VTXDEV_UNKNOWN;
|
||||
const vtxTableNotConfigured = vtxSupported && FC.VTX_CONFIG.vtx_table_available &&
|
||||
(FC.VTX_CONFIG.vtx_table_bands === 0 || FC.VTX_CONFIG.vtx_table_channels === 0 || FC.VTX_CONFIG.vtx_table_powerlevels === 0);
|
||||
|
||||
TABS.vtx.vtxTableFactoryBandsSupported = FC.VTX_CONFIG.vtx_type === 3;
|
||||
TABS.vtx.vtxTableFactoryBandsSupported = FC.VTX_CONFIG.vtx_type === VtxDeviceTypes.VTXDEV_SMARTAUDIO;
|
||||
|
||||
$(".vtx_supported").toggle(vtxSupported);
|
||||
$(".vtx_not_supported").toggle(!vtxSupported);
|
||||
|
@ -234,7 +279,7 @@ TABS.vtx.initialize = function (callback) {
|
|||
const noMessage = i18n.getMessage("no");
|
||||
|
||||
$("#vtx_device_ready_description").text(FC.VTX_CONFIG.vtx_device_ready ? yesMessage : noMessage);
|
||||
$("#vtx_type_description").text(i18n.getMessage(`vtxType_${FC.VTX_CONFIG.vtx_type}`));
|
||||
$("#vtx_type_description").text(self.getVtxTypeString());
|
||||
$("#vtx_channel_description").text(FC.VTX_CONFIG.vtx_channel);
|
||||
$("#vtx_frequency_description").text(FC.VTX_CONFIG.vtx_frequency);
|
||||
$("#vtx_pit_mode_description").text(FC.VTX_CONFIG.vtx_pit_mode ? yesMessage : noMessage);
|
||||
|
@ -513,23 +558,23 @@ TABS.vtx.initialize = function (callback) {
|
|||
|
||||
switch (vtxType) {
|
||||
|
||||
case 0: // Unsupported
|
||||
case VtxDeviceTypes.VTXDEV_UNSUPPORTED:
|
||||
powerMinMax = {};
|
||||
break;
|
||||
|
||||
case 1: // RTC6705
|
||||
case VtxDeviceTypes.VTXDEV_RTC6705:
|
||||
powerMinMax = {min: 1, max: 3};
|
||||
break;
|
||||
|
||||
case 3: // SmartAudio
|
||||
case VtxDeviceTypes.VTXDEV_SMARTAUDIO:
|
||||
powerMinMax = {min: 1, max: 4};
|
||||
break;
|
||||
|
||||
case 4: // Tramp
|
||||
case VtxDeviceTypes.VTXDEV_TRAMP:
|
||||
powerMinMax = {min: 1, max: 5};
|
||||
break;
|
||||
|
||||
case 255: // Unknown
|
||||
case VtxDeviceTypes.VTXDEV_UNKNOWN:
|
||||
default:
|
||||
powerMinMax = {min: 0, max: 7};
|
||||
}
|
||||
|
@ -969,6 +1014,8 @@ TABS.vtx.cleanup = function (callback) {
|
|||
this.VTXTABLE_BAND_LIST = [];
|
||||
this.VTXTABLE_POWERLEVEL_LIST = [];
|
||||
|
||||
GUI.interval_remove(this._DEVICE_STATUS_UPDATE_INTERVAL_NAME);
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
|
|
19
src/js/utils/VtxDeviceStatus/Rtc6705DeviceStatus.js
Normal file
19
src/js/utils/VtxDeviceStatus/Rtc6705DeviceStatus.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
'use strict';
|
||||
|
||||
class VtxDeviceStatusRtc6705 extends VtxDeviceStatus {
|
||||
constructor(dataView)
|
||||
{
|
||||
super(dataView);
|
||||
|
||||
dataView.readU8(); // custom device status size
|
||||
|
||||
// Read other Tramp VTX device parameters here
|
||||
}
|
||||
|
||||
static get staticDeviceStatusType()
|
||||
{
|
||||
return VtxDeviceTypes.VTXDEV_RTC6705;
|
||||
}
|
||||
}
|
||||
|
||||
vtxDeviceStatusFactory.registerVtxDeviceStatusClass(VtxDeviceStatusRtc6705);
|
49
src/js/utils/VtxDeviceStatus/SmartAudioDeviceStatus.js
Normal file
49
src/js/utils/VtxDeviceStatus/SmartAudioDeviceStatus.js
Normal file
|
@ -0,0 +1,49 @@
|
|||
'use strict';
|
||||
|
||||
class VtxDeviceStatusSmartAudio extends VtxDeviceStatus {
|
||||
constructor(dataView)
|
||||
{
|
||||
super(dataView);
|
||||
|
||||
dataView.readU8(); // custom device status size
|
||||
|
||||
this._version = dataView.readU8();
|
||||
this._mode = dataView.readU8();
|
||||
this._orfreq = dataView.readU16();
|
||||
this._willBootIntoPitMode = Boolean(dataView.readU8());
|
||||
}
|
||||
|
||||
get smartAudioVersion()
|
||||
{
|
||||
const sa = this._version * 100 + this._mode;
|
||||
let result = "";
|
||||
|
||||
switch (this._version) {
|
||||
case 1:
|
||||
result = "1.0";
|
||||
break;
|
||||
case 2:
|
||||
result = "2.0";
|
||||
break;
|
||||
case 3:
|
||||
result = "2.1";
|
||||
break;
|
||||
default:
|
||||
// unknown SA version
|
||||
result = i18n.getMessage("vtxType_255");
|
||||
}
|
||||
|
||||
if (16 == this._mode) {
|
||||
result = i18n.getMessage("vtxSmartAudioUnlocked", {"version": result});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static get staticDeviceStatusType()
|
||||
{
|
||||
return VtxDeviceTypes.VTXDEV_SMARTAUDIO;
|
||||
}
|
||||
}
|
||||
|
||||
vtxDeviceStatusFactory.registerVtxDeviceStatusClass(VtxDeviceStatusSmartAudio);
|
19
src/js/utils/VtxDeviceStatus/TrampDeviceStatus.js
Normal file
19
src/js/utils/VtxDeviceStatus/TrampDeviceStatus.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
'use strict';
|
||||
|
||||
class VtxDeviceStatusTramp extends VtxDeviceStatus {
|
||||
constructor(dataView)
|
||||
{
|
||||
super(dataView);
|
||||
|
||||
dataView.readU8(); // custom device status size
|
||||
|
||||
// Read other Tramp VTX device parameters here
|
||||
}
|
||||
|
||||
static get staticDeviceStatusType()
|
||||
{
|
||||
return VtxDeviceTypes.VTXDEV_TRAMP;
|
||||
}
|
||||
}
|
||||
|
||||
vtxDeviceStatusFactory.registerVtxDeviceStatusClass(VtxDeviceStatusTramp);
|
79
src/js/utils/VtxDeviceStatus/VtxDeviceStatus.js
Normal file
79
src/js/utils/VtxDeviceStatus/VtxDeviceStatus.js
Normal file
|
@ -0,0 +1,79 @@
|
|||
'use strict';
|
||||
|
||||
const VtxDeviceTypes = {
|
||||
VTXDEV_UNSUPPORTED: 0, // reserved for MSP
|
||||
VTXDEV_RTC6705: 1,
|
||||
// 2 reserved
|
||||
VTXDEV_SMARTAUDIO: 3,
|
||||
VTXDEV_TRAMP: 4,
|
||||
VTXDEV_UNKNOWN: 0xFF,
|
||||
};
|
||||
|
||||
class VtxDeviceStatus
|
||||
{
|
||||
constructor(dataView)
|
||||
{
|
||||
this._deviceIsReady = dataView.readU8();
|
||||
const bandAndChannelAvailable = Boolean(dataView.readU8());
|
||||
this._band = dataView.readU8();
|
||||
this._channel = dataView.readU8();
|
||||
|
||||
if (!bandAndChannelAvailable) {
|
||||
this._band = undefined;
|
||||
this._channel = undefined;
|
||||
}
|
||||
|
||||
const powerIndexAvailable = Boolean(dataView.readU8());
|
||||
this._powerIndex = dataView.readU8();
|
||||
|
||||
if (!powerIndexAvailable) {
|
||||
this._powerIndex = undefined;
|
||||
}
|
||||
|
||||
const frequencyAvailable = Boolean(dataView.readU8());
|
||||
this._frequency = dataView.readU16();
|
||||
|
||||
if (!frequencyAvailable) {
|
||||
this._frequency = undefined;
|
||||
}
|
||||
|
||||
const vtxStatusAvailable = Boolean(dataView.readU8());
|
||||
this._vtxStatus = dataView.readU32(); // pitmode and/or locked
|
||||
|
||||
if (!vtxStatusAvailable) {
|
||||
this._vtxStatus = undefined;
|
||||
}
|
||||
|
||||
this._readPowerLevels(dataView);
|
||||
}
|
||||
|
||||
_readPowerLevels(dataView)
|
||||
{
|
||||
this._levels = [];
|
||||
this._powers = [];
|
||||
const powerLevelCount = dataView.readU8();
|
||||
|
||||
for (let i = 0; i < powerLevelCount; i++)
|
||||
{
|
||||
this._levels.push(dataView.readU16());
|
||||
this._powers.push(dataView.readU16());
|
||||
}
|
||||
}
|
||||
|
||||
get deviceIsReady()
|
||||
{
|
||||
return this._deviceIsReady;
|
||||
}
|
||||
|
||||
// overload this function in subclasses
|
||||
static get staticDeviceStatusType()
|
||||
{
|
||||
return VtxDeviceTypes.VTXDEV_UNKNOWN;
|
||||
}
|
||||
|
||||
get deviceStatusType()
|
||||
{
|
||||
// returns result of overloaded static function "staticDeviceStatusType"
|
||||
return this.constructor.staticDeviceStatusType;
|
||||
}
|
||||
}
|
40
src/js/utils/VtxDeviceStatus/VtxDeviceStatusFactory.js
Normal file
40
src/js/utils/VtxDeviceStatus/VtxDeviceStatusFactory.js
Normal file
|
@ -0,0 +1,40 @@
|
|||
'use strict';
|
||||
|
||||
const vtxDeviceStatusFactory = {
|
||||
_vtxDeviceStatusClasses: [],
|
||||
|
||||
// call this to register a new vtx type like SmartAudio, Tramp or Rtc6705
|
||||
registerVtxDeviceStatusClass: function(vtxDeviceStatusClass)
|
||||
{
|
||||
this._vtxDeviceStatusClasses.push(vtxDeviceStatusClass);
|
||||
},
|
||||
|
||||
createVtxDeviceStatus: function(byteArray)
|
||||
{
|
||||
const dataView = new DataView(byteArray.buffer);
|
||||
|
||||
const vtxTypeIndex = dataView.readU8();
|
||||
const vtxDeviceStatusClass = this._getDeviceStatusClass(vtxTypeIndex);
|
||||
|
||||
return new vtxDeviceStatusClass(dataView);
|
||||
},
|
||||
|
||||
_readVtxType: function(dataView)
|
||||
{
|
||||
return dataView.readU8();
|
||||
},
|
||||
|
||||
_getDeviceStatusClass: function(vtxTypeIndex)
|
||||
{
|
||||
let result = this._vtxDeviceStatusClasses.find(
|
||||
(vtxClass) => {
|
||||
return vtxClass.staticDeviceStatusType === vtxTypeIndex;
|
||||
});
|
||||
|
||||
if (typeof result === 'undefined') {
|
||||
result = VtxDeviceStatus;
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
};
|
|
@ -74,6 +74,11 @@
|
|||
<script type="text/javascript" src="./js/utils/css.js"></script>
|
||||
<script type="text/javascript" src="./js/utils/window_watchers.js"></script>
|
||||
<script type="text/javascript" src="./js/utils/CommonUtils.js"></script>
|
||||
<script type="text/javascript" src="./js/utils/VtxDeviceStatus/VtxDeviceStatusFactory.js"></script>
|
||||
<script type="text/javascript" src="./js/utils/VtxDeviceStatus/VtxDeviceStatus.js"></script>
|
||||
<script type="text/javascript" src="./js/utils/VtxDeviceStatus/TrampDeviceStatus.js"></script>
|
||||
<script type="text/javascript" src="./js/utils/VtxDeviceStatus/SmartAudioDeviceStatus.js"></script>
|
||||
<script type="text/javascript" src="./js/utils/VtxDeviceStatus/Rtc6705DeviceStatus.js"></script>
|
||||
<script type="text/javascript" src="./js/injected_methods.js"></script>
|
||||
<script type="text/javascript" src="./js/ConfigStorage.js"></script>
|
||||
<script type="text/javascript" src="./js/data_storage.js"></script>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue