|
3 | 3 | <q-card-section>
|
4 | 4 | <div class="row justify-between">
|
5 | 5 | <div class="col-auto">
|
6 |
| - <code class="text-h5 block">{{ robotName }} Bash</code> |
7 |
| - <p class="text-subtitle2 text-grey-7">Seguidor de linha</p> |
| 6 | + <p class="text-h6 block">Linha de comandos</p> |
| 7 | + <p class="text-subtitle2 text-grey-7">{{ ble.name }}</p> |
8 | 8 | </div>
|
9 | 9 | </div>
|
10 | 10 | </q-card-section>
|
|
13 | 13 | <q-input
|
14 | 14 | standout
|
15 | 15 | v-model="command"
|
16 |
| - :dense="dense" |
17 | 16 | prefix="$"
|
18 |
| - @keyup.enter="sendCommand" |
| 17 | + @keyup.enter="runCommand" |
| 18 | + @keyup.arrow-up="updateCursor('up')" |
| 19 | + @keyup.arrow-down="updateCursor('down')" |
19 | 20 | >
|
20 |
| - <template v-slot:append> |
21 |
| - <q-avatar> |
22 |
| - <img src="~/assets/icons/quasar.svg" /> |
23 |
| - </q-avatar> |
24 |
| - </template> |
25 | 21 | <template v-slot:hint>Digite o comando...</template>
|
26 | 22 | </q-input>
|
27 | 23 | </q-card-section>
|
| 24 | + <q-card-section> |
| 25 | + <div |
| 26 | + :class="{ |
| 27 | + 'bg-grey-3': !!result, |
| 28 | + 'bg-negative': !!error, |
| 29 | + 'text-white': !!error, |
| 30 | + }" |
| 31 | + class="q-pa-sm rounded-borders q-m-none" |
| 32 | + > |
| 33 | + {{ result || (error && (error as BleError).message) }} |
| 34 | + </div> |
| 35 | + </q-card-section> |
| 36 | + <q-card-actions> |
| 37 | + <q-btn @click="runCommand" :loading="isLoading" color="primary" |
| 38 | + >Executar</q-btn |
| 39 | + > |
| 40 | + <template v-if="$q.platform.is.mobile"> |
| 41 | + <q-btn |
| 42 | + @click="updateCursor('up')" |
| 43 | + color="primary" |
| 44 | + flat |
| 45 | + :icon="mdiArrowUpThick" |
| 46 | + /> |
| 47 | + <q-btn |
| 48 | + @click="updateCursor('down')" |
| 49 | + color="primary" |
| 50 | + flat |
| 51 | + :icon="mdiArrowDownThick" |
| 52 | + /> |
| 53 | + </template> |
| 54 | + </q-card-actions> |
28 | 55 | </q-card>
|
29 | 56 | </template>
|
30 | 57 |
|
31 |
| -<script lang="ts"> |
32 |
| -import { defineComponent, ref } from 'vue'; |
33 |
| -import ws from 'src/ws'; |
34 |
| -
|
35 |
| -export default defineComponent({ |
36 |
| - name: 'LineFollowerCli', |
37 |
| - props: { robotName: { type: String, required: true } }, |
38 |
| - setup() { |
39 |
| - const command = ref(''); |
40 |
| - const dense = ref(false); |
| 58 | +<script lang="ts" setup> |
| 59 | +import { ref, watchEffect } from 'vue'; |
| 60 | +import useBluetooth, { BleError } from 'src/services/ble'; |
| 61 | +import { useAsyncState, useManualRefHistory } from '@vueuse/core'; |
| 62 | +import { withTimeout } from 'src/lib/promises'; |
| 63 | +import { TimeoutError } from 'src/services/ble'; |
| 64 | +import { useQuasar } from 'quasar'; |
| 65 | +import { mdiArrowUpThick, mdiArrowDownThick } from '@quasar/extras/mdi-v6'; |
41 | 66 |
|
42 |
| - function sendCommand() { |
43 |
| - ws.send(command.value); |
44 |
| - } |
| 67 | +const $q = useQuasar(); |
| 68 | +const { ble } = useBluetooth(); |
| 69 | +const cursor = ref(-1); |
| 70 | +const command = ref(''); |
| 71 | +const { history, commit } = useManualRefHistory(command); |
| 72 | +const { |
| 73 | + state: result, |
| 74 | + isLoading, |
| 75 | + error, |
| 76 | + execute, |
| 77 | +} = useAsyncState( |
| 78 | + () => |
| 79 | + withTimeout( |
| 80 | + ble.request('UART_TX', 'UART_RX', command.value), |
| 81 | + 5, |
| 82 | + new TimeoutError({ message: 'Comando excedeu o tempo limite' }) |
| 83 | + ), |
| 84 | + null, |
| 85 | + { |
| 86 | + immediate: false, |
| 87 | + } |
| 88 | +); |
45 | 89 |
|
46 |
| - return { |
47 |
| - command, |
48 |
| - dense, |
49 |
| - sendCommand, |
50 |
| - }; |
51 |
| - }, |
| 90 | +watchEffect(() => { |
| 91 | + if (cursor.value === -1) { |
| 92 | + command.value = ''; |
| 93 | + } else { |
| 94 | + command.value = history.value[cursor.value].snapshot; |
| 95 | + } |
52 | 96 | });
|
| 97 | +
|
| 98 | +function runCommand() { |
| 99 | + commit(); |
| 100 | + execute(); |
| 101 | + command.value = ''; |
| 102 | + cursor.value = -1; |
| 103 | +} |
| 104 | +
|
| 105 | +function updateCursor(direction: 'up' | 'down') { |
| 106 | + if (direction === 'up') { |
| 107 | + cursor.value = Math.min(cursor.value + 1, history.value.length - 2); |
| 108 | + } else if (direction === 'down') { |
| 109 | + cursor.value = Math.max(cursor.value - 1, -1); |
| 110 | + } |
| 111 | +} |
53 | 112 | </script>
|
0 commit comments