Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing the VeryGenericIndicator #474

Merged
6 changes: 3 additions & 3 deletions src/components/MiniWidgetInstantiator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
<template v-if="widgetType === MiniWidgetType.DepthIndicator">
<DepthIndicator :options="options" />
</template>
<template v-if="widgetType === MiniWidgetType.GenericIndicator">
<GenericIndicator :options="options" />
<template v-if="widgetType === MiniWidgetType.VeryGenericIndicator">
<VeryGenericIndicator :options="options" />
</template>
<template v-if="widgetType === MiniWidgetType.JoystickCommIndicator">
<JoystickCommIndicator :options="options" />
Expand Down Expand Up @@ -40,11 +40,11 @@ import ArmerButton from './mini-widgets/ArmerButton.vue'
import BaseCommIndicator from './mini-widgets/BaseCommIndicator.vue'
import BatteryIndicator from './mini-widgets/BatteryIndicator.vue'
import DepthIndicator from './mini-widgets/DepthIndicator.vue'
import GenericIndicator from './mini-widgets/GenericIndicator.vue'
import JoystickCommIndicator from './mini-widgets/JoystickCommIndicator.vue'
import MiniVideoRecorder from './mini-widgets/MiniVideoRecorder.vue'
import ModeSelector from './mini-widgets/ModeSelector.vue'
import SatelliteIndicator from './mini-widgets/SatelliteIndicator.vue'
import VeryGenericIndicator from './mini-widgets/VeryGenericIndicator.vue'
import ViewSelector from './mini-widgets/ViewSelector.vue'
const props = defineProps<{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
<template>
<div
class="flex items-center w-[6.25rem] h-12 py-1 text-white justify-center cursor-pointer hover:bg-slate-100/20 transition-all"
class="flex items-center justify-center h-12 py-1 text-white transition-all cursor-pointer w-fit hover:bg-slate-100/20"
@click="showConfigurationMenu = !showConfigurationMenu"
>
<span class="relative w-[2rem] mdi icon-symbol" :class="[options.iconName]"></span>
<div class="flex flex-col items-start justify-center ml-1 min-w-[4rem] max-w-[6rem] select-none">
<span class="text-xl font-semibold leading-6 w-fit">{{ parsedState }} {{ options.variableUnit }}</span>
<span class="w-full text-sm font-semibold leading-4 whitespace-nowrap">{{ options.variableName }}</span>
<div class="flex flex-col items-start justify-center mx-1 select-none w-fit min-w-[3rem]">
<div>
<span class="font-mono text-xl font-semibold leading-6 w-fit">{{ parsedState }}</span>
<span class="text-xl font-semibold leading-6 w-fit">
{{ String.fromCharCode(0x20) }} {{ options.variableUnit }}
</span>
</div>
<span class="w-full text-sm font-semibold leading-4 whitespace-nowrap">{{ options.displayName }}</span>
</div>
</div>
<Dialog v-model:show="showConfigurationMenu" class="w-80">
Expand All @@ -29,11 +34,19 @@
</div>
<div v-if="currentTab === 'custom'" class="flex flex-col items-center justify-around">
<div class="flex items-center justify-between w-full my-1">
<span class="mr-1 text-slate-100">Name</span>
<span class="mr-1 text-slate-100">Display name</span>
<input v-model="options.displayName" class="w-48 px-2 py-1 rounded-md bg-slate-200" />
</div>
<div class="flex items-center justify-between w-full my-1">
<span class="mr-1 text-slate-100">Variable</span>
<div class="w-48">
<Dropdown v-model="options.variableName" :options="Object.keys(store.genericVariables)" />
</div>
</div>
<div class="flex items-center justify-between w-full my-1">
<span class="mr-1 text-slate-100">Fractional digits</span>
<input v-model="options.fractionalDigits" class="w-48 px-2 py-1 rounded-md bg-slate-200" />
</div>
<div class="flex items-center justify-between w-full my-1">
<span class="mr-1 text-slate-100">Unit</span>
<input v-model="options.variableUnit" class="w-48 px-2 py-1 rounded-md bg-slate-200" />
Expand Down Expand Up @@ -82,7 +95,7 @@
</div>
<div v-if="currentTab === 'templates'" class="flex flex-wrap items-center justify-around">
<div
v-for="(template, i) in genericIndicatorTemplates"
v-for="(template, i) in veryGenericIndicatorTemplates"
:key="i"
class="flex items-center w-[6.25rem] h-12 py-1 pl-6 pr-1 rounded-md text-white justify-center cursor-pointer hover:bg-slate-100/20 transition-all"
@click="setIndicatorFromTemplate(template)"
Expand All @@ -92,7 +105,7 @@
<span class="text-xl font-semibold leading-6 w-fit">
{{ round(Math.random() * Number(template.variableMultiplier)).toFixed(0) }} {{ template.variableUnit }}
</span>
<span class="w-full text-sm font-semibold leading-4 whitespace-nowrap">{{ template.variableName }}</span>
<span class="w-full text-sm font-semibold leading-4 whitespace-nowrap">{{ template.displayName }}</span>
</div>
</div>
</div>
Expand All @@ -108,7 +121,7 @@ import { computed, onBeforeMount, onMounted, ref, toRefs, watch } from 'vue'
import Dropdown from '@/components/Dropdown.vue'
import { round } from '@/libs/utils'
import { useMainVehicleStore } from '@/stores/mainVehicle'
import { type GenericIndicatorTemplate, genericIndicatorTemplates } from '@/types/genericIndicator'
import { type VeryGenericIndicatorTemplate, veryGenericIndicatorTemplates } from '@/types/genericIndicator'

import Dialog from '../Dialog.vue'

Expand All @@ -124,7 +137,9 @@ onBeforeMount(() => {
// Set initial widget options if they don't exist
if (Object.keys(options).length === 0) {
Object.assign(options, {
displayName: '',
variableName: '',
fractionalDigits: 1,
iconName: 'mdi-help-box',
variableUnit: '%',
variableMultiplier: 1,
Expand All @@ -141,7 +156,10 @@ const store = useMainVehicleStore()
const currentState = ref<unknown>(0)
const parsedState = computed(() => {
if (currentState.value !== undefined) {
return round(Number(options.variableMultiplier) * Number(currentState.value)).toString()
return round(
Number(options.variableMultiplier) * Number(currentState.value),
options.fractionalDigits as number
).toFixed(options.fractionalDigits as number)
}
return '--'
})
Expand All @@ -159,7 +177,8 @@ const showConfigurationMenu = ref(false)
const iconSearchString = ref('')
const currentTab = ref('templates')

const setIndicatorFromTemplate = (template: GenericIndicatorTemplate): void => {
const setIndicatorFromTemplate = (template: VeryGenericIndicatorTemplate): void => {
options.displayName = template.displayName
options.variableName = template.variableName
options.iconName = template.iconName
options.variableUnit = template.variableUnit
Expand Down
49 changes: 49 additions & 0 deletions src/libs/vehicle/ardupilot/ardupilot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,55 @@ export abstract class ArduPilotVehicle<Modes> extends Vehicle.AbstractVehicle<Mo
// Update our internal messages
this._messages.set(mavlink_message.message.type, { ...mavlink_message.message, epoch: new Date().getTime() })

const mavlinkIdentificationKeys = [
'cam_idx',
'camera_id',
'compass_id',
'gcs_system_id',
'gimbal_device_id',
'gps_id',
'hw_unique_id',
'id',
'idx',
'rtk_receiver_id',
'sensor_id',
'storage_id',
'stream_id',
'uas_id',
]

/**
* Allows handling messages that are shared by multiple devices, splitting them out by detected device IDs.
* @param { Record<string, unknown> } obj The object to be searched for
* @param { Record<string, unknown> } acc The destination object for the variables found
* @param { string } baseKey A string to be added in front of the actual object keys. Used for deep nested key-value pairs
*/
const getDeepVariables = (obj: Record<string, unknown>, acc: Record<string, unknown>, baseKey?: string): void => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there should be a comment here explaining what this method is for. Maybe something like

/**
 * Allows handling messages that are shared by multiple devices, splitting them out by detected device IDs.
 */

It may also be worth noting that NAMED_VALUE_* messages are split out via a different function.

Object.entries(obj).forEach(([k, v]) => {
if (v instanceof Object) {
let identifier: string | undefined = undefined
Object.keys(v).forEach((subKey) => {
if (mavlinkIdentificationKeys.includes(subKey)) {
identifier = subKey
}
})
if (identifier === undefined) {
getDeepVariables(v as Record<string, unknown>, acc, k)
} else {
getDeepVariables(v as Record<string, unknown>, acc, `${k}.ID${v[identifier]}`)
}
} else {
if (baseKey === undefined) {
acc[k] = v
} else {
acc[`${baseKey}.${k}`] = v
}
}
})
}

getDeepVariables(Object.fromEntries(this._messages), this._genericVariables)

// TODO: Maybe create a signal class to deal with MAVLink only
// Where add will use the template argument type to define the lambda argument type
this.onMAVLinkMessage.emit_value(mavlink_message.message.type, mavlink_message)
Expand Down
28 changes: 26 additions & 2 deletions src/types/genericIndicator.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
/**
* Variables that define generic indicator
*/
export interface GenericIndicatorTemplate {
export interface VeryGenericIndicatorTemplate {
/**
* Name to be displayed on the widget
*/
displayName: string
/**
* Name of the variable to be fetched
*/
Expand All @@ -14,59 +18,79 @@ export interface GenericIndicatorTemplate {
* Symbols representing the unit system of the variable
*/
variableUnit: string
/**
* Number of digits to be displayed after the decimal separator (usually dot)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a setting somewhere that allows people to change the decimal separator, or does it automatically use the separator for the locale of the browser device or something? Would be nice if europeans can use their comma decimal separators, even though they hurt my eyeballs 😂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤣

There isn't, and I actually think we shouldn't add it.

We Brazilians also use commas as decimal separators, but this was clearly a big mistake, and softwares like Excel suffer a lot for adding the possibility of changing it, as it causes huge confusions when receiving a spreadsheet.

*/
fractionalDigits: number
/**
* Value that multiplies the original value to bring it to a representative unit system
*/
variableMultiplier: number
}

export const genericIndicatorTemplates: GenericIndicatorTemplate[] = [
export const veryGenericIndicatorTemplates: VeryGenericIndicatorTemplate[] = [
{
displayName: 'Cam Tilt',
variableName: 'CamTilt',
iconName: 'mdi-camera-retake',
variableUnit: '%',
fractionalDigits: 0,
variableMultiplier: 100,
},
{
displayName: 'Cam Pan',
variableName: 'CamPan',
iconName: 'mdi-camera-retake',
variableUnit: '%',
fractionalDigits: 0,
variableMultiplier: 100,
},
{
displayName: 'Tether Turns',
variableName: 'TetherTrn',
iconName: 'mdi-horizontal-rotate-clockwise',
variableUnit: 'x',
fractionalDigits: 0,
variableMultiplier: 100,
},
{
displayName: 'Lights (1)',
variableName: 'Lights1',
iconName: 'mdi-flashlight',
variableUnit: '%',
fractionalDigits: 0,
variableMultiplier: 100,
},
{
displayName: 'Lights (2)',
variableName: 'Lights2',
iconName: 'mdi-flashlight',
variableUnit: '%',
fractionalDigits: 0,
variableMultiplier: 100,
},
{
displayName: 'Pilot Gain',
variableName: 'PilotGain',
iconName: 'mdi-account-hard-hat',
variableUnit: '%',
fractionalDigits: 0,
variableMultiplier: 100,
},
{
displayName: 'Input Hold',
variableName: 'InputHold',
iconName: 'mdi-gesture-tap-hold',
variableUnit: '',
fractionalDigits: 0,
variableMultiplier: 1,
},
{
displayName: 'Roll Pitch',
variableName: 'RollPitch',
iconName: 'mdi-controller',
variableUnit: '',
fractionalDigits: 0,
variableMultiplier: 1,
},
]
2 changes: 1 addition & 1 deletion src/types/miniWidgets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export enum MiniWidgetType {
BaseCommIndicator = 'BaseCommIndicator',
BatteryIndicator = 'BatteryIndicator',
DepthIndicator = 'DepthIndicator',
GenericIndicator = 'GenericIndicator',
VeryGenericIndicator = 'VeryGenericIndicator',
JoystickCommIndicator = 'JoystickCommIndicator',
MiniVideoRecorder = 'MiniVideoRecorder',
ModeSelector = 'ModeSelector',
Expand Down