439 lines
14 KiB
Svelte
439 lines
14 KiB
Svelte
<script lang="ts">
|
|
import { createEventDispatcher, onMount } from 'svelte';
|
|
|
|
export let log_lvl: number = 0;
|
|
export let ws_connect: boolean = false;
|
|
export let ws_connect_status: null|string = null;
|
|
export let ws_server = 'dev-api.oneskyit.com';
|
|
export let base_url = `wss://${ws_server}/ws`;
|
|
export let group_id = 'ae-grp-99';
|
|
export let client_id = Date.now();
|
|
|
|
export let cmd: null|string = null;
|
|
export let msg: null|string = null;
|
|
export let type: null|string = null; // msg, cmd, json, hello, bye
|
|
export let trigger_send: any = null;
|
|
export let classes: string = 'container p-1 bg-pink-100 text-xs mx-auto pb-16 mb-20 sm:mb-12 md:mb-8';
|
|
export let hide__ws_form: boolean = true;
|
|
export let hide__ws_messages: boolean = false;
|
|
export let hide__ws_commands: boolean = false;
|
|
|
|
// *** Set initial variables
|
|
const dispatch = createEventDispatcher();
|
|
|
|
// JSON formatted data
|
|
let ws_data = {
|
|
'client_id': null, // The device or browser ID if available.
|
|
// 'src': null, // Sending client
|
|
// 'account_id': null, // Essentially the person ID or user ID if available.
|
|
// 'dest': null, // Destination client
|
|
'target': 'echo', // echo, dm (direct), grp (group), all (broadcast)
|
|
'type': 'cmd', // msg, cmd, json, hello, bye
|
|
// 'grp': null, // Destination group
|
|
'msg': null, // Message string
|
|
'cmd': null, // Command string
|
|
// 'data': null,
|
|
// 'b64': null,
|
|
}
|
|
|
|
let ws_received_list_cmd: string[] = [];
|
|
let ws_received_list_other: any[] = [];
|
|
let ws_received_list_msg: string[] = [];
|
|
|
|
|
|
onMount(async () => {
|
|
console.log('** Component Mounted: ** Element Websocket v2');
|
|
});
|
|
|
|
|
|
function ws_connect_group_id({group_id, client_id}) {
|
|
console.log(`${base_url}/group/${group_id}/client/${client_id}`);
|
|
let ws_connection = new WebSocket(`${base_url}/group/${group_id}/client/${client_id}`);
|
|
|
|
ws_connection.onopen = function() {
|
|
console.log('WS: connected');
|
|
|
|
ws_connect_status = 'connected';
|
|
|
|
dispatch('ws_conn', {
|
|
'status': 'connected'
|
|
});
|
|
|
|
// ws_connection.send(JSON.stringify({
|
|
// client_id: client_id,
|
|
// target: 'echo',
|
|
// type: 'hello',
|
|
// group_id: group_id,
|
|
// msg: 'You are connected!'
|
|
// }));
|
|
|
|
ws_connection.send(JSON.stringify({
|
|
client_id: client_id,
|
|
target: 'all',
|
|
type: 'hello',
|
|
group_id: group_id,
|
|
msg: `Client ${client_id.toString().slice(-5)} connected!`
|
|
}));
|
|
};
|
|
|
|
ws_connection.onmessage = function(event) {
|
|
if (log_lvl) {
|
|
console.log('WS: message received', event);
|
|
}
|
|
|
|
let ws_recv_data = JSON.parse(event.data);
|
|
if (log_lvl) {
|
|
console.log('WS: Received data:', ws_recv_data);
|
|
}
|
|
|
|
if (client_id == ws_recv_data.client_id) {
|
|
if (log_lvl) {
|
|
console.log('WS: Message received was sent by self and is an echo that can be ignored.');
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if (ws_recv_data.type == 'cmd') {
|
|
console.log(`WS: Type CMD: ${ws_recv_data.cmd}`);
|
|
ws_received_list_cmd.unshift(ws_recv_data); // Add to the beginning of the list
|
|
// ws_received_list_cmd.push(ws_recv_data); // Add to the end of the list
|
|
ws_received_list_cmd = ws_received_list_cmd; // trigger Svelte update -2024-10-04
|
|
} else {
|
|
console.log('WS: Type other');
|
|
ws_received_list_other.unshift(ws_recv_data); // Add to the beginning of the list
|
|
// ws_received_list_other.push(ws_recv_data); // Add to the end of the list
|
|
ws_received_list_other = ws_received_list_other; // trigger Svelte update -2024-10-04
|
|
}
|
|
|
|
dispatch('ws_recv', {
|
|
// 'client_id': ws_data.client_id, // The device or browser ID if available.
|
|
'src': ws_recv_data.client_id, // The device or browser ID if available.
|
|
// 'account_id': ws_recv_data.account_id, // Essentially the person ID or user ID if available.
|
|
'dest': group_id, // Destination client
|
|
'target': ws_recv_data.target, // echo, dm (direct), grp (group), all (broadcast)
|
|
'type': ws_recv_data.type, // Message type (msg, cmd, json, hello, bye)
|
|
// 'grp': ws_recv_data.grp, // Destination group
|
|
'msg': ws_recv_data.msg, // Message string
|
|
'cmd': ws_recv_data.cmd, // Command string
|
|
});
|
|
|
|
};
|
|
|
|
ws_connection.onclose = function(event) {
|
|
console.log('WS: connection closed');
|
|
|
|
ws_connection.send(JSON.stringify({
|
|
client_id: client_id,
|
|
target: 'all',
|
|
type: 'hello',
|
|
group_id: group_id,
|
|
msg: `Client ${client_id} is disconnecting!`
|
|
}));
|
|
|
|
ws_connect_status = 'disconnected';
|
|
|
|
let fake_ws_recv_data = {
|
|
'client_id': client_id,
|
|
'target': 'local',
|
|
'type': 'bye',
|
|
'group_id': group_id,
|
|
'msg': `LOCAL Client ${client_id} has disconnected!`
|
|
};
|
|
ws_received_list_other.unshift(fake_ws_recv_data);
|
|
ws_received_list_other = ws_received_list_other; // trigger Svelte update -2024-10-04
|
|
|
|
dispatch('ws_conn', {
|
|
'status': 'disconnected'
|
|
});
|
|
|
|
if (ws_connect) {
|
|
setTimeout(function() {
|
|
console.log('WS: Disconnected... Try again!');
|
|
ws_connect_group_id({group_id: group_id, client_id: client_id});
|
|
console.log('WS: Again done?');
|
|
}, 1000);
|
|
}
|
|
|
|
};
|
|
|
|
ws_connection.onerror = function(event) {
|
|
console.log('WS: connection error???');
|
|
|
|
ws_connection.send(JSON.stringify({
|
|
client_id: client_id,
|
|
target: 'all',
|
|
type: 'hello',
|
|
group_id: group_id,
|
|
msg: `Client ${client_id} is having trouble?!`
|
|
}));
|
|
};
|
|
|
|
// NOTE WARNING: Uncommenting this seems to break FastAPI somehow???
|
|
// NOTE: from FastAPI log: RuntimeError: Unexpected ASGI message 'websocket.send', after sending 'websocket.close'.
|
|
// ws_connection.onerror = function(err) {
|
|
// console.error('WS socket error: ', err.message, 'Closing socket');
|
|
// // ws_connection.close();
|
|
// };
|
|
|
|
return ws_connection;
|
|
}
|
|
|
|
// Start the WS function
|
|
let ws_group: any = null;
|
|
$: if (ws_connect && group_id) {
|
|
ws_group = ws_connect_group_id({group_id: group_id, client_id: client_id});
|
|
} else {
|
|
ws_group?.close();
|
|
}
|
|
|
|
$: if (trigger_send && cmd) {
|
|
trigger_send = null;
|
|
console.log('WS: Send triggered!');
|
|
console.log(cmd);
|
|
ws_data.target = 'group';
|
|
ws_data.type = 'cmd';
|
|
ws_data.cmd = cmd;
|
|
handle_send_ws_data();
|
|
cmd = '';
|
|
}
|
|
|
|
function handle_send_ws_data() {
|
|
console.log(ws_data);
|
|
if (!ws_data) {
|
|
return false;
|
|
}
|
|
if (!ws_group) {
|
|
console.log('WS: No connection!');
|
|
return false;
|
|
}
|
|
let ws_data_json_str = JSON.stringify(ws_data);
|
|
let resp = ws_group.send(ws_data_json_str);
|
|
console.log(resp);
|
|
|
|
dispatch('ws_sent', {
|
|
// 'client_id': ws_data.client_id, // The device or browser ID if available.
|
|
'src': ws_data.client_id, // The device or browser ID if available.
|
|
// 'account_id': ws_data.account_id, // Essentially the person ID or user ID if available.
|
|
'dest': group_id, // Destination client
|
|
'group_id': group_id,
|
|
'target': ws_data.target, // echo, dm (direct), grp (group), all (broadcast)
|
|
'type': ws_data.type, // Message type (msg, cmd, json, hello, bye)
|
|
// 'grp': ws_data.grp, // Destination group
|
|
'msg': ws_data.msg, // Message string
|
|
'cmd': ws_data.cmd, // Command string
|
|
});
|
|
|
|
cmd = '';
|
|
msg = '';
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
<section class="ae_element__websocket container p-1 bg-pink-100 text-xs mx-auto pb-16 mt-32 mb-32 relative">
|
|
|
|
<span class="absolute top-0 right-0 flex flex-col gap-1">
|
|
<button
|
|
type="button"
|
|
on:click={() => {
|
|
hide__ws_form = !hide__ws_form;
|
|
}}
|
|
class="btn btn-sm text-xs hover:variant-filled-tertiary"
|
|
class:variant-soft-tertiary={hide__ws_form}
|
|
class:variant-filled-tertiary={!hide__ws_form}
|
|
>
|
|
{#if hide__ws_form}
|
|
Show Form
|
|
{:else}
|
|
Hide Form?
|
|
{/if}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
on:click={() => {
|
|
hide__ws_messages = !hide__ws_messages;
|
|
}}
|
|
class="btn btn-sm text-xs hover:variant-filled-tertiary"
|
|
class:variant-soft-tertiary={hide__ws_messages}
|
|
class:variant-filled-tertiary={!hide__ws_messages}
|
|
>
|
|
{#if hide__ws_messages}
|
|
Show Messages
|
|
{:else}
|
|
Hide Messages?
|
|
{/if}
|
|
</button>
|
|
<button
|
|
type="button"
|
|
on:click={() => {
|
|
hide__ws_commands = !hide__ws_commands;
|
|
}}
|
|
class="btn btn-sm text-xs hover:variant-filled-tertiary"
|
|
class:variant-soft-tertiary={hide__ws_commands}
|
|
class:variant-filled-tertiary={!hide__ws_commands}
|
|
>
|
|
{#if hide__ws_commands}
|
|
Show Commands
|
|
{:else}
|
|
Hide Commands?
|
|
{/if}
|
|
</button>
|
|
</span>
|
|
|
|
<header>
|
|
|
|
<h1 class="h6 text-center">Websocket Messages & Commands</h1>
|
|
|
|
</header>
|
|
|
|
|
|
<!-- <form on:submit|preventDefault={handle_send_message}>
|
|
<select bind:value={type}>
|
|
<option value="">None</option>
|
|
<option value="echo">Echo</option>
|
|
<option value="dm">Direct Message</option>
|
|
<option value="group">Group Message</option>
|
|
<option value="all">Broadcast to All</option>
|
|
<option value="cmd">Command</option>
|
|
</select>
|
|
|
|
<select bind:value={group_id}>
|
|
<option value="">None</option>
|
|
<option value="test_grp_123">123</option>
|
|
<option value="test_grp_999">999</option>
|
|
<option value="test_grp_poster">A Poster Group</option>
|
|
</select>
|
|
|
|
<input type="text" bind:value={message_text} placeholder="Your message"/>
|
|
|
|
<button>Send</button>
|
|
</form> -->
|
|
|
|
{#if !hide__ws_form}
|
|
<form
|
|
on:submit|preventDefault={handle_send_ws_data}
|
|
>
|
|
<select
|
|
bind:value={ws_data.type}
|
|
class="input text-sm w-24"
|
|
>
|
|
<option value="">None</option>
|
|
<option value="echo">Echo</option>
|
|
<option value="dm">Direct Message</option>
|
|
<option value="group">Group Message</option>
|
|
<option value="all">Broadcast to All</option>
|
|
<option value="cmd">Command</option>
|
|
</select>
|
|
<input type="text" bind:value={group_id} placeholder="Group ID" class="input text-sm w-36" />
|
|
<!-- <select bind:value={group_id}>
|
|
<option value="">None</option>
|
|
<option value="test_grp_123">123</option>
|
|
<option value="test_grp_999">999</option>
|
|
<option value="test_grp_poster">A Poster Group</option>
|
|
</select> -->
|
|
|
|
<!-- <input type="text" bind:value={dm_client_id} placeholder="Direct message client ID"/> -->
|
|
|
|
<input type="text" bind:value={ws_data.cmd} placeholder="Your command" class="input text-sm w-36" />
|
|
<input type="text" bind:value={ws_data.msg} placeholder="Your message" class="input text-xs w-96" />
|
|
|
|
<button
|
|
type="submit"
|
|
class="btn btn-sm variant-soft-warning"
|
|
>Send Group</button>
|
|
</form>
|
|
{/if}
|
|
|
|
<!-- <pre>
|
|
ae_load:event_session=jEG9APQRUs8 (Poster Session #3: Work Never Ends - Pythagoras)
|
|
ae_open:event_file=CHqU5sW7xbc (jpg)
|
|
ae_open:event_file=Kljq0uiTlXt (video)
|
|
</pre> -->
|
|
|
|
<!-- <hr> -->
|
|
|
|
<section
|
|
class:hidden={hide__ws_messages}
|
|
>
|
|
<h2 class="text-center underline">Messages [grp, client, target, type]</h2>
|
|
|
|
<ol class="list-decimal list-outside max-h-24 overflow-y-auto messages">
|
|
{#each ws_received_list_other as msg_entry, index}
|
|
<li
|
|
class="ml-4"
|
|
>
|
|
<div
|
|
class="flex flex-row justify-between gap-1 w-full"
|
|
>
|
|
<span>
|
|
[{(msg_entry.group_id||'No Group ID')}]
|
|
{(msg_entry.client_id.toString().slice(-5)||'No Client ID')}
|
|
–
|
|
{(msg_entry.target||'No Target')}
|
|
|
|
|
<!-- – -->
|
|
{(msg_entry.type||'No Type')}:
|
|
</span>
|
|
<span class="justify-self-end">
|
|
"{msg_entry.msg}"
|
|
</span>
|
|
<!-- <br>{JSON.stringify(msg_entry)} -->
|
|
</div>
|
|
</li>
|
|
{/each}
|
|
</ol>
|
|
</section> <!-- End Messages -->
|
|
|
|
<hr>
|
|
|
|
<section
|
|
class:hidden={hide__ws_commands}
|
|
>
|
|
<h2 class="text-center underline">Commands</h2>
|
|
|
|
<ol class="list-decimal list-outside max-h-24 overflow-y-auto commands">
|
|
{#each ws_received_list_cmd as cmd_entry}
|
|
<li
|
|
class="ml-4"
|
|
>
|
|
<div
|
|
class="flex flex-row justify-between gap-1 w-full"
|
|
>
|
|
<span>
|
|
[{(cmd_entry.group_id||'No Group ID')}]
|
|
{(cmd_entry.client_id.toString().slice(-5)||'No Client ID')}
|
|
—
|
|
{(cmd_entry.target||'No Target')}
|
|
|
|
|
<!-- — -->
|
|
{(cmd_entry.type||'No Type')}:
|
|
</span>
|
|
<span class="justify-self-end">
|
|
"{cmd_entry.cmd}"
|
|
</span>
|
|
</div>
|
|
</li>
|
|
{/each}
|
|
</ol>
|
|
</section> <!-- End Commands -->
|
|
|
|
|
|
</section>
|
|
|
|
|
|
<style>
|
|
/* .websocket_element {
|
|
background-color: white;
|
|
border-top: dashed medium gray;
|
|
color: gray;
|
|
font-size: .7em;
|
|
}
|
|
.websocket_element header {
|
|
font-size: .7em;
|
|
}
|
|
.websocket_element h2 {
|
|
font-size: .9em;
|
|
} */
|
|
</style>
|
|
|