velconnect v3 ---- GO!
parent
2555c3082f
commit
a9c74cb4ac
|
|
@ -15,6 +15,6 @@ jobs:
|
|||
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
|
||||
ssh-keyscan -H ${{ secrets.SSH_HOST }} > ~/.ssh/known_hosts
|
||||
- name: connect and pull
|
||||
run: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "cd /home/ubuntu/VEL-Connect-PB/velconnect && git pull && docker compose up -d --build --remove-orphans && exit"
|
||||
run: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "cd /home/ubuntu/VEL-Connect-v2/velconnect && git pull && docker compose up -d --build && exit"
|
||||
- name: cleanup
|
||||
run: rm -rf ~/.ssh
|
||||
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
|
||||
ssh-keyscan -H ${{ secrets.SSH_HOST }} > ~/.ssh/known_hosts
|
||||
- name: connect and pull
|
||||
run: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "cd ${{ secrets.SSH_WORK_DIR }}/../VEL-Connect-PB && git pull && docker compose up -d --build && exit"
|
||||
run: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "cd /home/ubuntu/VEL-Connect-v3/velconnect && git pull && docker compose up -d --build && exit"
|
||||
- name: cleanup
|
||||
run: rm -rf ~/.ssh
|
||||
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
import PocketBase from 'pocketbase';
|
||||
import { writable } from 'svelte/store';
|
||||
import { type Record } from 'pocketbase';
|
||||
import { get } from 'svelte/store';
|
||||
|
||||
export const pb = new PocketBase('http://127.0.0.1:8090');
|
||||
|
||||
|
|
@ -11,8 +12,7 @@ pb.authStore.onChange((auth) => {
|
|||
currentUser.set(pb.authStore.model);
|
||||
});
|
||||
|
||||
let pairedDevicesInit: string[] = [];
|
||||
export const pairedDevices = writable(pairedDevicesInit);
|
||||
export const pairedDevices = writable<string[]>([]);
|
||||
export const currentDevice = writable('');
|
||||
|
||||
interface HasData extends Record {
|
||||
|
|
@ -24,3 +24,129 @@ export interface DeviceData extends Record {
|
|||
data: { [key: string]: string };
|
||||
}
|
||||
export interface RoomData extends HasData {}
|
||||
|
||||
const device = get(currentDevice);
|
||||
if (device == '' && device.length > 0) {
|
||||
currentDevice.set(device[0]);
|
||||
}
|
||||
|
||||
let unsubscribeDeviceData: () => void;
|
||||
let unsubscribeRoomData: () => void;
|
||||
let unsubscribeCurrentDevice: () => void;
|
||||
let unsubscribeCurrentUser: () => void;
|
||||
|
||||
export let deviceData = writable<DeviceData | null>(null);
|
||||
export let roomData = writable<RoomData | null>(null);
|
||||
|
||||
export let sending = false;
|
||||
|
||||
export async function startListening() {
|
||||
if (get(currentDevice) != '') {
|
||||
deviceData = await pb.collection('Device').getOne(get(currentDevice));
|
||||
}
|
||||
|
||||
unsubscribeCurrentDevice = currentDevice.subscribe(async (val) => {
|
||||
console.log('current device changed');
|
||||
unsubscribeDeviceData?.();
|
||||
if (val != '') {
|
||||
const d = (await pb.collection('Device').getOne(get(currentDevice))) as DeviceData;
|
||||
deviceData.set(d);
|
||||
if (d != null) getRoomData(d);
|
||||
unsubscribeDeviceData = await pb.collection('Device').subscribe(val, async (data) => {
|
||||
const d = data.record as DeviceData;
|
||||
deviceData.set(d);
|
||||
getRoomData(d);
|
||||
});
|
||||
} else {
|
||||
deviceData.set(null);
|
||||
roomData.set(null);
|
||||
}
|
||||
});
|
||||
|
||||
unsubscribeCurrentUser = currentUser.subscribe((user) => {
|
||||
pairedDevices.set(user?.devices ?? []);
|
||||
});
|
||||
}
|
||||
|
||||
export function stopListening() {
|
||||
unsubscribeCurrentDevice?.();
|
||||
unsubscribeDeviceData?.();
|
||||
unsubscribeRoomData?.();
|
||||
unsubscribeCurrentUser?.();
|
||||
}
|
||||
|
||||
async function getRoomData(deviceData: DeviceData) {
|
||||
unsubscribeRoomData?.();
|
||||
|
||||
// create or just fetch room by name
|
||||
const r = await fetch(
|
||||
`${pb.baseUrl}/data_block/${deviceData.current_app}_${deviceData.current_room}`,
|
||||
{
|
||||
method: 'POST'
|
||||
}
|
||||
).then((r) => r.json());
|
||||
roomData.set(r);
|
||||
if (r) {
|
||||
unsubscribeDeviceData = await pb.collection('DataBlock').subscribe(r.id, (data) => {
|
||||
roomData.set(data.record as RoomData);
|
||||
unsubscribeRoomData?.();
|
||||
});
|
||||
} else {
|
||||
console.error('Failed to get or create room');
|
||||
}
|
||||
}
|
||||
|
||||
let abortController = new AbortController();
|
||||
export function delayedSend() {
|
||||
console.log('fn: delayedSend()');
|
||||
|
||||
// abort the previous send
|
||||
abortController.abort();
|
||||
const newAbortController = new AbortController();
|
||||
abortController = newAbortController;
|
||||
setTimeout(() => {
|
||||
if (!newAbortController.signal.aborted) {
|
||||
send();
|
||||
} else {
|
||||
console.log('aborted');
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
export function send() {
|
||||
console.log('sending...');
|
||||
sending = true;
|
||||
let promises = [];
|
||||
const r = get(roomData);
|
||||
const d = get(deviceData);
|
||||
if (d) {
|
||||
promises.push(pb.collection('Device').update(d.id, d));
|
||||
}
|
||||
if (r) {
|
||||
promises.push(pb.collection('DataBlock').update(r.id, r));
|
||||
}
|
||||
Promise.all(promises).then(() => {
|
||||
sending = false;
|
||||
});
|
||||
}
|
||||
|
||||
export function removeDevice(d: string) {
|
||||
pairedDevices.set(get(pairedDevices).filter((i) => i != d));
|
||||
|
||||
if (get(currentDevice) == d) {
|
||||
console.log('Removed current device');
|
||||
|
||||
// if there are still devices left
|
||||
if (get(pairedDevices).length > 0) {
|
||||
currentDevice.set(get(pairedDevices)[0]);
|
||||
} else {
|
||||
currentDevice.set('');
|
||||
}
|
||||
}
|
||||
|
||||
const user = get(currentUser);
|
||||
if (user) {
|
||||
user.devices.filter((i: string) => i != d);
|
||||
pb.collection('Users').update(user.id, user);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,141 +1,26 @@
|
|||
<script lang="ts">
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
import {
|
||||
currentDevice,
|
||||
type DeviceData,
|
||||
delayedSend,
|
||||
deviceData,
|
||||
pairedDevices,
|
||||
pb,
|
||||
type RoomData,
|
||||
currentUser
|
||||
removeDevice,
|
||||
roomData,
|
||||
sending,
|
||||
startListening,
|
||||
stopListening
|
||||
} from '$lib/js/velconnect';
|
||||
import Login from '$lib/components/Login.svelte';
|
||||
import Pair from '$lib/components/Pair.svelte';
|
||||
import { prettyDate } from '$lib/js/util';
|
||||
|
||||
if ($currentDevice == '' && $pairedDevices.length > 0) {
|
||||
currentDevice.set($pairedDevices[0]);
|
||||
}
|
||||
|
||||
let unsubscribeDeviceData: () => void;
|
||||
let unsubscribeRoomData: () => void;
|
||||
let unsubscribeCurrentDevice: () => void;
|
||||
let unsubscribeCurrentUser: () => void;
|
||||
|
||||
let deviceData: DeviceData | null;
|
||||
let roomData: RoomData | null;
|
||||
|
||||
let sending = false;
|
||||
|
||||
$: deviceData,
|
||||
() => {
|
||||
console.log('Device data changed');
|
||||
};
|
||||
import { onDestroy, onMount } from 'svelte';
|
||||
|
||||
onMount(async () => {
|
||||
if ($currentDevice != '') {
|
||||
deviceData = await pb.collection('Device').getOne($currentDevice);
|
||||
}
|
||||
|
||||
unsubscribeCurrentDevice = currentDevice.subscribe(async (val) => {
|
||||
console.log('current device changed');
|
||||
unsubscribeDeviceData?.();
|
||||
if (val != '') {
|
||||
deviceData = await pb.collection('Device').getOne($currentDevice);
|
||||
if (deviceData != null) getRoomData(deviceData);
|
||||
unsubscribeDeviceData = await pb.collection('Device').subscribe(val, async (data) => {
|
||||
deviceData = data.record as DeviceData;
|
||||
getRoomData(deviceData);
|
||||
await startListening();
|
||||
});
|
||||
} else {
|
||||
deviceData = null;
|
||||
roomData = null;
|
||||
}
|
||||
});
|
||||
|
||||
unsubscribeCurrentUser = currentUser.subscribe((user) => {
|
||||
pairedDevices.set(user?.devices ?? []);
|
||||
});
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
unsubscribeCurrentDevice?.();
|
||||
unsubscribeDeviceData?.();
|
||||
unsubscribeRoomData?.();
|
||||
unsubscribeCurrentUser?.();
|
||||
stopListening();
|
||||
});
|
||||
|
||||
async function getRoomData(deviceData: DeviceData) {
|
||||
// get room data
|
||||
unsubscribeRoomData?.();
|
||||
// create or just fetch room by name
|
||||
roomData = await fetch(
|
||||
`${pb.baseUrl}/data_block/${deviceData.current_app}_${deviceData.current_room}`,
|
||||
{
|
||||
method: 'POST'
|
||||
}
|
||||
).then((r) => r.json());
|
||||
console.log(roomData);
|
||||
if (roomData) {
|
||||
unsubscribeDeviceData = await pb.collection('DataBlock').subscribe(roomData.id, (data) => {
|
||||
roomData = data.record as RoomData;
|
||||
unsubscribeRoomData?.();
|
||||
});
|
||||
} else {
|
||||
console.error('Failed to get or create room');
|
||||
}
|
||||
}
|
||||
|
||||
let abortController = new AbortController();
|
||||
function delayedSend() {
|
||||
console.log('fn: delayedSend()');
|
||||
|
||||
// abort the previous send
|
||||
abortController.abort();
|
||||
const newAbortController = new AbortController();
|
||||
abortController = newAbortController;
|
||||
setTimeout(() => {
|
||||
if (!newAbortController.signal.aborted) {
|
||||
send();
|
||||
} else {
|
||||
console.log('aborted');
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function send() {
|
||||
console.log('sending...');
|
||||
sending = true;
|
||||
let promises = [];
|
||||
if (deviceData) {
|
||||
promises.push(pb.collection('Device').update(deviceData.id, deviceData));
|
||||
}
|
||||
if (roomData) {
|
||||
promises.push(pb.collection('DataBlock').update(roomData.id, roomData));
|
||||
}
|
||||
Promise.all(promises).then(() => {
|
||||
sending = false;
|
||||
});
|
||||
}
|
||||
|
||||
function removeDevice(d: string) {
|
||||
pairedDevices.set($pairedDevices.filter((i) => i != d));
|
||||
|
||||
if ($currentDevice == d) {
|
||||
console.log('Removed current device');
|
||||
|
||||
// if there are still devices left
|
||||
if ($pairedDevices.length > 0) {
|
||||
currentDevice.set($pairedDevices[0]);
|
||||
} else {
|
||||
currentDevice.set('');
|
||||
}
|
||||
}
|
||||
|
||||
if ($currentUser) {
|
||||
$currentUser.devices.filter((i: string) => i != d);
|
||||
pb.collection('Users').update($currentUser.id, $currentUser);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
|
|
@ -182,25 +67,25 @@
|
|||
</div>
|
||||
{/if}
|
||||
|
||||
{#if deviceData != null && deviceData.data != null}
|
||||
{#if $deviceData != null && $deviceData.data != null}
|
||||
<div>
|
||||
<h3>Device Info</h3>
|
||||
|
||||
<device-field>
|
||||
<h6>Device ID:</h6>
|
||||
<code>{deviceData.id}</code>
|
||||
<code>{$deviceData.id}</code>
|
||||
</device-field>
|
||||
<device-field>
|
||||
<h6>Pairing Code:</h6>
|
||||
<code>{deviceData.pairing_code}</code>
|
||||
<code>{$deviceData.pairing_code}</code>
|
||||
</device-field>
|
||||
<device-field>
|
||||
<h6>First Seen</h6>
|
||||
<p>{prettyDate(deviceData.created)}</p>
|
||||
<p>{prettyDate($deviceData.created)}</p>
|
||||
</device-field>
|
||||
<device-field>
|
||||
<h6>Last Seen</h6>
|
||||
<p>{prettyDate(deviceData.updated)}</p>
|
||||
<p>{prettyDate($deviceData.updated)}</p>
|
||||
</device-field>
|
||||
</div>
|
||||
|
||||
|
|
@ -212,7 +97,7 @@
|
|||
<input
|
||||
type="text"
|
||||
placeholder="Enter username..."
|
||||
bind:value={deviceData.friendly_name}
|
||||
bind:value={$deviceData.friendly_name}
|
||||
on:input={delayedSend}
|
||||
/>
|
||||
</label>
|
||||
|
|
@ -231,14 +116,14 @@
|
|||
<input
|
||||
type="text"
|
||||
placeholder="https://----.glb"
|
||||
bind:value={deviceData.data.avatar_url}
|
||||
bind:value={$deviceData.data.avatar_url}
|
||||
on:input={delayedSend}
|
||||
/>
|
||||
</label>
|
||||
|
||||
<device-field>
|
||||
<h6>Current Room</h6>
|
||||
<a href="/join/{deviceData.current_app}/room_name" target="blank">
|
||||
<a href="/join/{$deviceData.current_app}/room_name" target="blank">
|
||||
Shareable Link
|
||||
<svg style="width:1em;height:1em;margin-bottom:-.15em;" viewBox="0 0 24 24">
|
||||
<path
|
||||
|
|
@ -250,7 +135,7 @@
|
|||
<input
|
||||
type="text"
|
||||
placeholder="room_1"
|
||||
bind:value={deviceData.current_room}
|
||||
bind:value={$deviceData.current_room}
|
||||
on:input={delayedSend}
|
||||
/>
|
||||
</device-field>
|
||||
|
|
@ -258,9 +143,9 @@
|
|||
|
||||
<h3>Raw JSON:</h3>
|
||||
<h6>Device Data</h6>
|
||||
<pre><code>{JSON.stringify(deviceData, null, 2)}</code></pre>
|
||||
<pre><code>{JSON.stringify($deviceData, null, 2)}</code></pre>
|
||||
<h6>Room Data</h6>
|
||||
<pre><code>{JSON.stringify(roomData, null, 2)}</code></pre>
|
||||
<pre><code>{JSON.stringify($roomData, null, 2)}</code></pre>
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
version: "2.0"
|
||||
version: "3.0"
|
||||
services:
|
||||
server:
|
||||
build: .
|
||||
|
|
|
|||
Loading…
Reference in New Issue