Skip to content

Commit bacd0c3

Browse files
WilliangalvaniES-Alexander
authored andcommitted
frontend: add relay configuration to vehicle setup
Co-authored-by: ES-Alexander <sandman.esalexander@gmail.com>
1 parent b9bd8ac commit bacd0c3

3 files changed

Lines changed: 159 additions & 22 deletions

File tree

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<template>
2+
<v-card class="mt-4 mb-4">
3+
<v-card-text>
4+
<v-row align="center">
5+
<v-col cols="6" class="pa0">
6+
<parameter-switch
7+
v-if="default_parameter"
8+
:parameter="default_parameter"
9+
:off-value="0"
10+
:on-value="1"
11+
label="Startup State"
12+
/>
13+
<parameter-switch
14+
v-if="inverted_parameter"
15+
:parameter="inverted_parameter"
16+
:off-value="0"
17+
:on-value="1"
18+
label="Invert Output"
19+
/>
20+
</v-col>
21+
<v-col cols="6">
22+
<v-row>
23+
<v-btn
24+
v-tooltip="'Turn relay on'"
25+
class="ma-4"
26+
@click="setRelay(1)"
27+
>
28+
<v-icon small left>
29+
mdi-power
30+
</v-icon>
31+
Relay On
32+
</v-btn>
33+
</v-row>
34+
<v-row>
35+
<v-btn
36+
v-tooltip="'Turn relay off'"
37+
class="ma-4"
38+
@click="setRelay(0)"
39+
>
40+
<v-icon small left>
41+
mdi-power-off
42+
</v-icon>
43+
Relay Off
44+
</v-btn>
45+
</v-row>
46+
</v-col>
47+
</v-row>
48+
</v-card-text>
49+
</v-card>
50+
</template>
51+
52+
<script lang="ts">
53+
import Vue from 'vue'
54+
55+
import mavlink2rest from '@/libs/MAVLink2Rest'
56+
import { MavCmd } from '@/libs/MAVLink2Rest/mavlink2rest-ts/messages/mavlink2rest-enum'
57+
import autopilot_data from '@/store/autopilot'
58+
import Parameter from '@/types/autopilot/parameter'
59+
60+
export default Vue.extend({
61+
name: 'RelaySetup',
62+
props: {
63+
relayParameter: {
64+
type: Object as () => Parameter,
65+
required: true,
66+
},
67+
},
68+
computed: {
69+
relay_number(): number {
70+
return parseInt(this.relayParameter.name.match(/RELAY(\d+)_FUNCTION/)?.[1] ?? '0', 10)
71+
},
72+
inverted_parameter(): Parameter | undefined {
73+
return autopilot_data.parameter(`RELAY${this.relay_number}_INVERTED`)
74+
},
75+
default_parameter(): Parameter | undefined {
76+
return autopilot_data.parameter(`RELAY${this.relay_number}_DEFAULT`)
77+
},
78+
},
79+
methods: {
80+
setRelay(setting: number): void {
81+
// MAV_CMD_DO_SET_RELAY: param1 = relay instance (0-indexed), param2 = setting (0=off, 1=on, 2=toggle)
82+
mavlink2rest.sendCommandLong(
83+
MavCmd.MAV_CMD_DO_SET_RELAY,
84+
this.relay_number - 1, // Convert to 0-indexed relay instance
85+
setting,
86+
)
87+
},
88+
},
89+
})
90+
</script>

core/frontend/src/components/parameter-editor/ServoFunctionGpioEditor.vue

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,38 @@
11
<template>
22
<div class="align-center">
3-
GPIOs can be used for Relays, Leak detection, and other functions not yet supported by this UI.
4-
This servo ({{ servo_number }}) gpio is {{ this_servo_gpio }}.
5-
6-
In use by {{ function_type_using_this_gpio?.name }}
7-
3+
<p>
4+
Some flight controller servo channels are capable of digital (GPIO) functionalities.
5+
Available options include relays, leak detection (input-capable pins only),
6+
and other functions not yet supported by this UI.
7+
</p>
8+
<p>
9+
This servo's GPIO (<strong>{{ this_servo_gpio }}</strong>) is currently in use by
10+
<strong>{{ function_type_using_this_gpio?.name ?? 'nothing' }}</strong>.
11+
</p>
812
<v-row align="end">
9-
<v-col cols="6">
10-
<span style="font-size: 1.0rem;">Change function for this servo's GPIO</span>
11-
</v-col>
12-
<v-col cols="6">
13-
<v-select
14-
v-model="selected_function_type"
15-
:items="options"
16-
item-text="text"
17-
item-value="value"
18-
return-object
19-
hide-details
20-
@change="onChange"
21-
/>
22-
</v-col>
13+
<v-col cols="6">
14+
<span style="font-size: 1.0rem;">GPIO Function:</span>
15+
</v-col>
16+
<v-col cols="6">
17+
<v-select
18+
v-model="selected_function_type"
19+
:items="options"
20+
item-text="text"
21+
item-value="value"
22+
return-object
23+
hide-details
24+
@change="onChange"
25+
/>
26+
</v-col>
2327
</v-row>
24-
28+
<relay-setup
29+
v-if="function_type_using_this_gpio?.name?.includes('RELAY')"
30+
:relay-parameter="function_type_using_this_gpio"
31+
/>
32+
<leak-setup
33+
v-if="function_type_using_this_gpio?.name?.includes('LEAK')"
34+
:leak-parameter="function_type_using_this_gpio"
35+
/>
2536
</div>
2637
</template>
2738

core/frontend/src/components/vehiclesetup/PwmSetup.vue

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@
136136
<td v-tooltip="item.name">
137137
{{ convert_servo_name(item.name) }}
138138
</td>
139-
<td>{{ stringToUserFriendlyText(printParam(item)) }}</td>
139+
<td>{{ parameterToUserFriendlyText(item) }}</td>
140140
<td>{{ servo_output[index] }}</td>
141141
</tr>
142142
</tbody>
@@ -156,6 +156,7 @@
156156
<script lang="ts">
157157
import Vue from 'vue'
158158
159+
import { fetchCurrentBoard } from '@/components/autopilot/AutopilotManagerUpdater'
159160
import ServoFunctionEditorDialog from '@/components/parameter-editor/ServoFunctionEditorDialog.vue'
160161
import MotorDetection from '@/components/vehiclesetup/MotorDetection.vue'
161162
import VehicleViewer from '@/components/vehiclesetup/viewers/VehicleViewer.vue'
@@ -173,6 +174,7 @@ import { SERVO_FUNCTION } from '@/types/autopilot/parameter-sub-enums'
173174
import { Dictionary } from '@/types/common'
174175
import { armDisarm, doMotorTest } from '@/utils/ardupilot_mavlink'
175176
import mavlink_store_get from '@/utils/mavlink'
177+
import { servoNumberToGpio } from '@/utils/servoGpio'
176178
177179
import ParameterSwitch from '../common/ParameterSwitch.vue'
178180
@@ -376,6 +378,23 @@ export default Vue.extend({
376378
return output
377379
.map((_, i) => data[`servo${i + 1}_raw`])
378380
},
381+
board_name(): string | undefined {
382+
return autopilot.current_board?.name
383+
},
384+
gpio_to_parameter(): Record<number, Parameter> {
385+
return Object.fromEntries(
386+
autopilot_data.parameterRegex('^.*_PIN$')
387+
.map((param) => [param.value, param]),
388+
)
389+
},
390+
servo_to_gpio(): Record<number, number> {
391+
return Object.fromEntries(
392+
Array.from({ length: 16 }, (_, i) => {
393+
const servo = i + 1
394+
return [servo, servoNumberToGpio(servo, this.board_name)]
395+
}),
396+
)
397+
},
379398
},
380399
watch: {
381400
is_armed() {
@@ -392,6 +411,8 @@ export default Vue.extend({
392411
mounted() {
393412
this.motor_zeroer_interval = setInterval(this.zero_motors, 300)
394413
this.motor_writer_interval = setInterval(this.write_motors, 100)
414+
fetchCurrentBoard()
415+
395416
mavlink.setMessageRefreshRate({ messageName: 'SERVO_OUTPUT_RAW', refreshRate: 10 })
396417
this.desired_armed_state = this.is_armed
397418
this.installListeners()
@@ -455,13 +476,28 @@ export default Vue.extend({
455476
this.selected_param = param
456477
this.edit_param_dialog = true
457478
},
479+
parameterToUserFriendlyText(param: Parameter): string {
480+
if (param.value === -1) { // GPIO
481+
const servo_number = parseInt(/\d+/g.exec(param.name)?.[0] ?? '0', 10)
482+
const gpio = this.servo_to_gpio[servo_number]
483+
if (!gpio) {
484+
return 'GPIO (Unknown)'
485+
}
486+
const param_using_this_gpio = this.gpio_to_parameter[gpio]
487+
if (param_using_this_gpio) {
488+
const pretty_name = param_using_this_gpio.name.split('_')[0].toLowerCase().toTitle()
489+
return `GPIO [${pretty_name}]`
490+
}
491+
return `GPIO ${gpio} (Unknown)`
492+
}
493+
return this.stringToUserFriendlyText(printParam(param))
494+
},
458495
stringToUserFriendlyText(text: string) {
459496
return param_value_map?.[this.vehicle_type ?? '']?.[text] ?? text
460497
},
461498
getParam(param: string): Parameter | undefined {
462499
return autopilot_data.parameter(param)
463500
},
464-
printParam,
465501
zero_motors() {
466502
if (!this.is_manual) {
467503
return

0 commit comments

Comments
 (0)