Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../global.css">
<link rel="stylesheet" href="preference.css">
<script type="module">
import SimpleBLEClient from './ble-client.mjs'
document.addEventListener('DOMContentLoaded', () => {
/**
* Views
*/
const settingsForm = document.getElementById('settings-form')
const bleConnectButton = document.getElementById('ble-connect-button')
const updateView = () => {
if (client.isConnected()) {
bleConnectButton.classList.remove('active')
settingsForm.classList.add('active')
} else {
settingsForm.classList.remove('active')
bleConnectButton.classList.add('active')
}
}
/**
* Event Handlers
*/
const handleConnectButtonClick = async () => {
console.log("Connecting")
await client.connect()
updateView()
}
const handleDisconnectButtonClick = async () => {
console.log("Disconnecting")
await client.disconnect()
updateView()
}
const toast = document.getElementById('toast')
toast.addEventListener('animationend', () => {
toast.className = 'toast'
})
const showToast = () => {
toast.classList.add('visible')
}
let submitting = null
const handleWifiSubmit = async (event) => {
console.log('handlewifi')
event.preventDefault();
if (!client.isConnected()) {
console.warn('Not Connected')
return;
}
const props = [
'wifi.ssid',
'wifi.password',
'driver.type',
'driver.offsetPan',
'driver.offsetTilt',
'renderer.type',
'tts.type',
'tts.host',
'tts.port',
'tts.token',
'ai.token',
'ai.context',
]
const payload = {}
for (const prop of props) {
const value = document.getElementById(prop)?.value
if (value != null && value.trimEnd().length > 0) {
payload[prop] = value
}
}
await client.send({ _batch: payload })
console.log('Sent')
submitting = setTimeout(() => {
console.error('Timeout')
}, 3000)
}
const handleCharacteristicWritten = ({ prop, value }) => {
if (submitting != null) {
toast.innerText = 'Preference set [・_・]'
showToast()
clearTimeout(submitting)
submitting = null
}
const elem = document.querySelector(`[name="${prop}"]`)
if (elem != null) {
elem.value = value
}
}
/**
* BLE Client
*/
const client = new SimpleBLEClient({
deviceName: "STK",
onCharacteristicValueChanged: handleCharacteristicWritten
})
client.onDisconnected = () => {
updateView()
}
/**
* Bind
*/
document.getElementById('ble-connect-button').addEventListener('click', handleConnectButtonClick)
document.getElementById('ble-disconnect-button').addEventListener('click', handleDisconnectButtonClick)
document.getElementById('form-preference').addEventListener('submit', handleWifiSubmit)
})
</script>
<title>Document</title>
</head>
<body>
<div class="app">
<div>
<button class="accordion active" id="ble-connect-button">
Connect Stack-chan with BLE[・_・]
</button>
</div>
<div class="accordion card" id="settings-form">
<h2>Stack-chan preferences</h2>
<div class="ble-disconnect-button" id="ble-disconnect-button" title="Disconnect">×</div>
<form class="form" id="form-preference">
<h3>WiFi</h3>
<div class="form-group">
<label for="wifi.ssid">SSID: </label>
<input type="text" name="wifi.ssid" id="wifi.ssid" autocomplete="off">
</div>
<div class="form-group">
<label for="wifi.password">Password: </label>
<input type="password" name="wifi.password" id="wifi.password" autocomplete="off">
</div>
<h3>Face</h3>
<div class="form-group">
<label for="renderer.type">Type: </label>
<select name="renderer.type" id="renderer.type">
<option value="simple">Simple</option>
<option value="dog">Dog</option>
</select>
</div>
<h3>Servo</h3>
<div class="form-group">
<label for="driver.type">Type: </label>
<select name="driver.type" id="driver.type">
<option value="scservo">SCServo</option>
<option value="dynamixel">Dynamixel(Protocol version 2)</option>
<option value="rs30x">RS30X</option>
<option value="pwm">PWM(SG-90)</option>
<option value="none">None</option>
</select>
</div>
<div class="form-group">
<label for="driver.offsetPan">Offset Pan:</label>
<input type="number" name="driver.offsetPan" id="driver.offsetPan" value="0">
</div>
<div class="form-group">
<label for="driver.offsetTilt">Offset Tilt:</label>
<input type="number" name="driver.offsetTilt" id="driver.offsetTilt" value="0">
</div>
<h3>TTS</h3>
<div class="form-group">
<label for="tts.type">Type: </label>
<select name="tts.type" id="tts.type">
<option value="voicevox">VOICEVOX</option>
<option value="elevenlabs">ElevenLabs</option>
<option value="google-tts">Google TTS</option>
<option value="local">Local</option>
</select>
</div>
<div class="form-group">
<label for="tts.host">Host:</label>
<input type="text" name="tts.host" id="tts.host" placeholder="my-tts-host.local">
</div>
<div class="form-group">
<label for="tts.port">Port:</label>
<input type="number" name="tts.port" id="tts.port" placeholder="50021">
</div>
<div class="form-group">
<label for="tts.token">Token:</label>
<input type="text" name="tts.token" id="tts.token">
</div>
<h3>AI</h3>
<div class="form-group">
<label for="ai.token">Token:</label>
<input type="text" name="ai.token" id="ai.token">
</div>
<label for="ai.context">System Role:</label>
<textarea name="ai.context" id="ai.context" cols="30" rows="5"
placeholder="You are Stack-chan(スタックチャン), the palm sized super kawaii companion robot."></textarea>
<hr>
<button type="submit">Submit</button>
</form>
</div>
</div>
<div id="toast" class="toast"></div>
</body>
</html>791c0d066This file is pinned to the selected release. Download the original to open it in your design tool.