💄 Simplify calibration UX
This commit is contained in:
@@ -36,6 +36,8 @@ export { default as FileIcon } from '~icons/mdi/file'
|
|||||||
export { default as FolderIcon } from '~icons/mdi/folder-outline'
|
export { default as FolderIcon } from '~icons/mdi/folder-outline'
|
||||||
export { default as FolderOpenOutline } from '~icons/mdi/folder-open-outline'
|
export { default as FolderOpenOutline } from '~icons/mdi/folder-open-outline'
|
||||||
export { default as TrashIcon } from '~icons/mdi/trash'
|
export { default as TrashIcon } from '~icons/mdi/trash'
|
||||||
|
export { default as RotateCcw } from '~icons/mdi/rotate-left'
|
||||||
|
export { default as RotateCw } from '~icons/mdi/rotate-right'
|
||||||
|
|
||||||
export { default as Down } from '~icons/tabler/chevron-down'
|
export { default as Down } from '~icons/tabler/chevron-down'
|
||||||
export { default as Cancel } from '~icons/tabler/x'
|
export { default as Cancel } from '~icons/tabler/x'
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Servos from './servos.svelte';
|
import Servos from './servos.svelte'
|
||||||
import ServoTable from './ServoTable.svelte';
|
import ServoTable from './ServoTable.svelte'
|
||||||
|
|
||||||
|
let servoId = $state(0)
|
||||||
|
let pwm = $state(306)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="mx-0 my-1 flex flex-col space-y-4 sm:mx-8 sm:my-8">
|
<div class="mx-0 my-1 flex flex-col space-y-4 sm:mx-8 sm:my-8">
|
||||||
<Servos />
|
<Servos bind:servoId bind:pwm />
|
||||||
<ServoTable />
|
<ServoTable {servoId} {pwm} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,34 +1,57 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { api } from '$lib/api';
|
import { api } from '$lib/api'
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte'
|
||||||
|
import { RotateCw, RotateCcw } from '$lib/components/icons'
|
||||||
interface Props {
|
interface Props {
|
||||||
data?: any;
|
data?: any
|
||||||
|
servoId?: number
|
||||||
|
pwm?: number
|
||||||
}
|
}
|
||||||
|
|
||||||
let { data = $bindable({
|
let {
|
||||||
|
data = $bindable({
|
||||||
servos: []
|
servos: []
|
||||||
}) }: Props = $props();
|
}),
|
||||||
|
pwm = $bindable(306),
|
||||||
|
servoId = $bindable(0)
|
||||||
|
}: Props = $props()
|
||||||
|
|
||||||
const updateValue = (event, index, key) => {
|
const updateValue = (event: Event, index: number, key: string) => {
|
||||||
data.servos[index][key] = event.target.innerText;
|
data.servos[index][key] = Number((event.target as HTMLInputElement).value)
|
||||||
};
|
}
|
||||||
|
|
||||||
const syncConfig = async () => {
|
const syncConfig = async () => {
|
||||||
await api.post('/api/servo/config', data);
|
await api.post('/api/servo/config', data)
|
||||||
};
|
}
|
||||||
|
|
||||||
|
const toggleDirection = async (index: number) => {
|
||||||
|
data.servos[index].direction = data.servos[index].direction === 1 ? -1 : 1
|
||||||
|
await syncConfig()
|
||||||
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const result = await api.get('/api/servo/config');
|
const result = await api.get('/api/servo/config')
|
||||||
if (result.isOk()) {
|
if (result.isOk()) {
|
||||||
data = result.inner;
|
data = result.inner
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const setCenterPWM = async () => {
|
||||||
|
console.log('setCenterPWM', servoId, pwm)
|
||||||
|
data.servos[servoId]['center_pwm'] = pwm
|
||||||
|
await syncConfig()
|
||||||
}
|
}
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button class="btn btn-sm btn-primary" onclick={() => setCenterPWM()}>Set center pwm</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="table table-xs">
|
<table class="table table-xs">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Servo</th>
|
||||||
<th>Center PWM</th>
|
<th>Center PWM</th>
|
||||||
<th>Center Angle</th>
|
<th>Center Angle</th>
|
||||||
<th>Direction</th>
|
<th>Direction</th>
|
||||||
@@ -37,34 +60,51 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each data.servos as servo, index}
|
{#each data.servos as servo, index}
|
||||||
<tr>
|
<tr class="hover:bg-base-200">
|
||||||
<td
|
<td class="font-medium">Servo {index}</td>
|
||||||
contenteditable="true"
|
<td>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
class="input input-sm input-bordered w-20"
|
||||||
|
value={servo.center_pwm}
|
||||||
onblur={syncConfig}
|
onblur={syncConfig}
|
||||||
oninput={event => updateValue(event, index, 'center_pwm')}
|
oninput={event => updateValue(event, index, 'center_pwm')}
|
||||||
>
|
min="80"
|
||||||
{servo.center_pwm}
|
max="600" />
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td>
|
||||||
contenteditable="true"
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.1"
|
||||||
|
class="input input-sm input-bordered w-20"
|
||||||
|
value={servo.center_angle}
|
||||||
onblur={syncConfig}
|
onblur={syncConfig}
|
||||||
oninput={event => updateValue(event, index, 'center_angle')}
|
oninput={event => updateValue(event, index, 'center_angle')}
|
||||||
>
|
min="-90"
|
||||||
{servo.center_angle}
|
max="90" />
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td>
|
||||||
contenteditable="true"
|
<button
|
||||||
onblur={syncConfig}
|
class="btn btn-sm btn-ghost"
|
||||||
oninput={event => updateValue(event, index, 'direction')}
|
title="Toggle direction {servo.direction}"
|
||||||
>
|
onclick={() => toggleDirection(index)}>
|
||||||
{servo.direction}
|
{#if servo.direction === 1}
|
||||||
|
<RotateCw class="w-4 h-4 text-green-500" />
|
||||||
|
{:else}
|
||||||
|
<RotateCcw class="w-4 h-4" />
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td>
|
||||||
contenteditable="true"
|
<input
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
class="input input-sm input-bordered w-20"
|
||||||
|
value={servo.conversion}
|
||||||
onblur={syncConfig}
|
onblur={syncConfig}
|
||||||
oninput={event => updateValue(event, index, 'conversion')}
|
oninput={event => updateValue(event, index, 'conversion')}
|
||||||
>
|
min="0"
|
||||||
{servo.conversion}
|
max="10" />
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
@@ -1,38 +1,23 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import SettingsCard from '$lib/components/SettingsCard.svelte'
|
|
||||||
import type { ServoConfiguration, Servo } from '$lib/types/models'
|
|
||||||
import Spinner from '$lib/components/Spinner.svelte'
|
|
||||||
|
|
||||||
import { socket } from '$lib/stores'
|
import { socket } from '$lib/stores'
|
||||||
import { onDestroy, onMount } from 'svelte'
|
|
||||||
import { throttler as Throttler } from '$lib/utilities'
|
import { throttler as Throttler } from '$lib/utilities'
|
||||||
import { MotorOutline } from '$lib/components/icons'
|
|
||||||
|
|
||||||
let isLoading = false
|
let { servoId = $bindable(0), pwm = $bindable(306) } = $props()
|
||||||
|
|
||||||
let active = $state(false)
|
let active = $state(false)
|
||||||
|
|
||||||
let servoId = $state(0)
|
|
||||||
|
|
||||||
let allServos = $state(false)
|
let allServos = $state(false)
|
||||||
|
|
||||||
const throttler = new Throttler()
|
const throttler = new Throttler()
|
||||||
|
|
||||||
const sweep = (event: any) => {
|
const activateServo = () => {
|
||||||
let channel = event.detail.channel
|
|
||||||
socket.sendEvent('servoConfiguration', { servos: [{ channel, sweep: true }] })
|
|
||||||
}
|
|
||||||
|
|
||||||
const activateServo = (event: any) => {
|
|
||||||
socket.sendEvent('servoState', { active: 1 })
|
socket.sendEvent('servoState', { active: 1 })
|
||||||
}
|
}
|
||||||
|
|
||||||
const deactivateServo = (event: any) => {
|
const deactivateServo = () => {
|
||||||
socket.sendEvent('servoState', { active: 0 })
|
socket.sendEvent('servoState', { active: 0 })
|
||||||
}
|
}
|
||||||
|
|
||||||
let pwm = $state(306)
|
|
||||||
|
|
||||||
const updatePWM = () => {
|
const updatePWM = () => {
|
||||||
throttler.throttle(() => {
|
throttler.throttle(() => {
|
||||||
socket.sendEvent('servoPWM', { servo_id: servoId, pwm })
|
socket.sendEvent('servoPWM', { servo_id: servoId, pwm })
|
||||||
@@ -44,14 +29,11 @@
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<SettingsCard collapsible={false}>
|
<div class="flex flex-col">
|
||||||
{#snippet icon()}
|
<h2 class="text-lg">General servo configuration</h2>
|
||||||
<MotorOutline class="lex-shrink-0 mr-2 h-6 w-6 self-end" />
|
|
||||||
{/snippet}
|
|
||||||
{#snippet title()}
|
|
||||||
<span>Servo</span>
|
<span>Servo</span>
|
||||||
{/snippet}
|
<span>{pwm}</span>
|
||||||
{pwm}
|
</div>
|
||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
min="80"
|
min="80"
|
||||||
@@ -60,9 +42,6 @@
|
|||||||
oninput={updatePWM}
|
oninput={updatePWM}
|
||||||
class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" />
|
class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer dark:bg-gray-700" />
|
||||||
|
|
||||||
{#if isLoading}
|
|
||||||
<Spinner />
|
|
||||||
{:else}
|
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<h2 class="text-lg">General servo configuration</h2>
|
<h2 class="text-lg">General servo configuration</h2>
|
||||||
<span>
|
<span>
|
||||||
@@ -82,5 +61,3 @@
|
|||||||
<input type="range" min="0" max="11" step="1" bind:value={servoId} />
|
<input type="range" min="0" max="11" step="1" bind:value={servoId} />
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
</SettingsCard>
|
|
||||||
|
|||||||
Reference in New Issue
Block a user