mirror of
https://github.com/ad1217/PrinterStatus
synced 2024-11-21 15:03:48 -05:00
Add a "settings" message to send header colors and webcam transform
This should ideally be in 3 commits, but oh well.
This commit is contained in:
parent
ecd5185dc4
commit
787ec126c5
@ -3,7 +3,7 @@ import fetch from 'node-fetch';
|
||||
/// <reference path="mjpeg-proxy.d.ts"/>
|
||||
import { MjpegProxy } from 'mjpeg-proxy';
|
||||
|
||||
import {ExtendedMessage} from '../../types/messages';
|
||||
import {Message, StatusMessage, SettingsMessage} from '../../types/messages';
|
||||
import * as octoprint from '../../types/octoprint';
|
||||
|
||||
const PING_TIME = 10000;
|
||||
@ -13,13 +13,14 @@ type Timeout = ReturnType<typeof setTimeout>;
|
||||
export default class OctoprintConnection {
|
||||
public name?: string;
|
||||
public webcamProxy?: MjpegProxy;
|
||||
protected lastStatus?: ExtendedMessage;
|
||||
protected lastStatus?: StatusMessage;
|
||||
protected settingsMessage?: SettingsMessage;
|
||||
|
||||
constructor(
|
||||
public slug: string,
|
||||
public address: string,
|
||||
protected apikey: string,
|
||||
protected broadcast: (msg: ExtendedMessage) => void
|
||||
protected broadcast: (msg: Message) => void
|
||||
) {
|
||||
this.try_connect_websocket();
|
||||
}
|
||||
@ -41,7 +42,18 @@ export default class OctoprintConnection {
|
||||
if (this.webcamProxy === undefined) {
|
||||
this.webcamProxy = new MjpegProxy(webcamURL.toString());
|
||||
}
|
||||
this.name = settings.appearance.name;
|
||||
this.settingsMessage = {
|
||||
kind: "settings",
|
||||
printer: this.slug,
|
||||
name: settings.appearance.name,
|
||||
color: settings.appearance.color,
|
||||
webcam: {
|
||||
flipH: settings.webcam.flipH,
|
||||
flipV: settings.webcam.flipV,
|
||||
rotate90: settings.webcam.rotate90,
|
||||
}
|
||||
}
|
||||
this.broadcast(this.settingsMessage);
|
||||
|
||||
// do passive login to get a session key from the API key
|
||||
const login: octoprint.LoginResponse = await this.api_post('login', {
|
||||
@ -66,10 +78,10 @@ export default class OctoprintConnection {
|
||||
.on('message', (data: WebSocket.Data) => {
|
||||
const event: octoprint.Message = JSON.parse(data as string);
|
||||
|
||||
let ext_event: ExtendedMessage = {
|
||||
...event,
|
||||
let ext_event: StatusMessage = {
|
||||
kind: "status",
|
||||
printer: this.slug,
|
||||
name: this.name,
|
||||
msg: event,
|
||||
};
|
||||
this.broadcast(ext_event);
|
||||
|
||||
@ -120,12 +132,12 @@ export default class OctoprintConnection {
|
||||
}
|
||||
|
||||
send_init(ws: WebSocket) {
|
||||
let payload: ExtendedMessage;
|
||||
if (this.settingsMessage) {
|
||||
ws.send(JSON.stringify(this.settingsMessage));
|
||||
|
||||
if (this.lastStatus) {
|
||||
payload = this.lastStatus;
|
||||
} else {
|
||||
payload = { init: null, printer: this.slug, name: this.name };
|
||||
ws.send(JSON.stringify(this.lastStatus));
|
||||
}
|
||||
}
|
||||
ws.send(JSON.stringify(payload));
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import * as yaml from 'js-yaml';
|
||||
import * as expressWs from 'express-ws';
|
||||
import * as WebSocket from 'ws';
|
||||
|
||||
import { ExtendedMessage } from '../../types/messages';
|
||||
import { Message } from '../../types/messages';
|
||||
import OctoPrintConnection from './OctoPrintConnection';
|
||||
|
||||
const PORT = process.env.PORT || 1234;
|
||||
@ -31,7 +31,7 @@ function broadcast(data: WebSocket.Data) {
|
||||
});
|
||||
}
|
||||
|
||||
function broadcastPayload(payload: ExtendedMessage) {
|
||||
function broadcastPayload(payload: Message) {
|
||||
broadcast(JSON.stringify(payload));
|
||||
}
|
||||
|
||||
|
41
src/App.vue
41
src/App.vue
@ -29,17 +29,10 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, Ref } from 'vue';
|
||||
|
||||
import * as messages from '../types/messages';
|
||||
import * as octoprint from '../types/octoprint';
|
||||
import PrinterCard from './PrinterCard.vue';
|
||||
import { Message, WebcamSettings } from '../types/messages';
|
||||
import PrinterCard, { PrinterInfo } from './PrinterCard.vue';
|
||||
|
||||
const printers: Ref<{
|
||||
[key: string]: {
|
||||
name?: string;
|
||||
lastUpdate: Date;
|
||||
status: octoprint.CurrentOrHistoryPayload | null;
|
||||
};
|
||||
}> = ref({});
|
||||
const printers: Ref<{ [key: string]: PrinterInfo }> = ref({});
|
||||
const hasPrinters = computed(() => Object.keys(printers.value).length > 0);
|
||||
|
||||
let now: Ref<Date> = ref(new Date());
|
||||
@ -53,22 +46,30 @@ function connectWebsocket() {
|
||||
(loc.protocol === 'https:' ? 'wss://' : 'ws://') + loc.host + '/ws';
|
||||
websocket = new WebSocket(ws_uri);
|
||||
websocket.addEventListener('message', (ev: MessageEvent) => {
|
||||
const event: messages.ExtendedMessage = JSON.parse(ev.data as string);
|
||||
const event: Message = JSON.parse(ev.data as string);
|
||||
console.log(event);
|
||||
|
||||
if (!(event.printer in printers.value)) {
|
||||
printers.value[event.printer] = { status: null, lastUpdate: new Date() };
|
||||
printers.value[event.printer] = {
|
||||
status: null,
|
||||
webcam: null,
|
||||
color: null,
|
||||
lastUpdate: new Date(),
|
||||
};
|
||||
}
|
||||
printers.value[event.printer].name = event.name;
|
||||
printers.value[event.printer].lastUpdate = new Date();
|
||||
|
||||
if ('init' in event) {
|
||||
printers.value[event.printer].status = null;
|
||||
} else if ('current' in event && event.current) {
|
||||
printers.value[event.printer].status = event.current;
|
||||
} else if ('history' in event && event.history) {
|
||||
printers.value[event.printer].status = event.history;
|
||||
} else if ('remote_ws_status' in event) {
|
||||
if (event.kind === 'settings') {
|
||||
printers.value[event.printer].name = event.name;
|
||||
printers.value[event.printer].webcam = event.webcam;
|
||||
printers.value[event.printer].color = event.color;
|
||||
} else if (event.kind === 'status') {
|
||||
if ('current' in event.msg && event.msg.current) {
|
||||
printers.value[event.printer].status = event.msg.current;
|
||||
} else if ('history' in event.msg && event.msg.history) {
|
||||
printers.value[event.printer].status = event.msg.history;
|
||||
} else if ('remote_ws_status' in event.msg) {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,7 +1,13 @@
|
||||
<template>
|
||||
<div class="card">
|
||||
<h3 class="card-header">{{ name || 'Unknown' }}</h3>
|
||||
<img class="card-img webcam" :src="'/webcam/' + slug" />
|
||||
<h3 class="card-header" :data-color="color">
|
||||
{{ name || 'Unknown' }}
|
||||
</h3>
|
||||
<img
|
||||
class="card-img webcam"
|
||||
:style="webcamTransform"
|
||||
:src="'/webcam/' + slug"
|
||||
/>
|
||||
<div class="card-body" v-if="status">
|
||||
<div>{{ status.state.text }}</div>
|
||||
<div>Job File Name: {{ status.job.file.name || 'None' }}</div>
|
||||
@ -26,15 +32,22 @@
|
||||
import { computed } from 'vue';
|
||||
import prettyMilliseconds from 'pretty-ms';
|
||||
|
||||
import * as octoprint from '../types/octoprint';
|
||||
import { CurrentOrHistoryPayload } from '../types/octoprint';
|
||||
import { WebcamSettings, OctoprintColor } from '../types/messages';
|
||||
|
||||
const props = defineProps<{
|
||||
interface Props {
|
||||
slug: string;
|
||||
name?: string;
|
||||
lastUpdate: Date;
|
||||
now: Date;
|
||||
status: octoprint.CurrentOrHistoryPayload | null;
|
||||
}>();
|
||||
status: CurrentOrHistoryPayload | null;
|
||||
webcam: WebcamSettings | null;
|
||||
color: OctoprintColor | null;
|
||||
}
|
||||
|
||||
export type PrinterInfo = Omit<Props, 'slug' | 'now'>;
|
||||
|
||||
const props = defineProps<Props>();
|
||||
|
||||
function formatDuration(seconds: number): string {
|
||||
return prettyMilliseconds(seconds * 1000);
|
||||
@ -54,4 +67,51 @@ const lastUpdateString = computed(() => {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const webcamTransform = computed(() => {
|
||||
if (props.webcam) {
|
||||
const transforms = [];
|
||||
if (props.webcam.flipH) {
|
||||
transforms.push('scaleX(-1)');
|
||||
}
|
||||
if (props.webcam.flipV) {
|
||||
transforms.push('scaleY(-1)');
|
||||
}
|
||||
if (props.webcam.rotate90) {
|
||||
transforms.push('rotate(90)');
|
||||
}
|
||||
return { transform: transforms.join(' ') };
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
$bs-colors: ('red', 'orange', 'yellow', 'green', 'blue', 'white');
|
||||
|
||||
.card-header[data-color] {
|
||||
background-image: var(--bs-gradient);
|
||||
|
||||
@each $color in $bs-colors {
|
||||
&[data-color='#{$color}'] {
|
||||
background-color: var(--bs-#{$color});
|
||||
}
|
||||
}
|
||||
|
||||
&[data-color='violet'] {
|
||||
background-color: var(--bs-purple);
|
||||
}
|
||||
|
||||
&[data-color='black'] {
|
||||
background-color: var(--bs-purple);
|
||||
}
|
||||
|
||||
&[data-color='blue'],
|
||||
&[data-color='green'],
|
||||
&[data-color='violet'],
|
||||
&[data-color='black'] {
|
||||
color: var(--bs-light);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
29
types/messages.d.ts
vendored
29
types/messages.d.ts
vendored
@ -1,6 +1,27 @@
|
||||
import { Message } from './octoprint';
|
||||
import { Message as OctoprintMessage } from './octoprint';
|
||||
|
||||
export type ExtendedMessage = (Message | { init?: null }) & {
|
||||
interface BaseMessage {
|
||||
printer: string;
|
||||
name?: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface StatusMessage extends BaseMessage {
|
||||
kind: 'status';
|
||||
msg: OctoprintMessage;
|
||||
}
|
||||
|
||||
export interface WebcamSettings {
|
||||
flipH: boolean;
|
||||
flipV: boolean;
|
||||
rotate90: boolean;
|
||||
}
|
||||
|
||||
export type OctoprintColor = 'red' | 'orange' | 'yellow' | 'green' | 'blue' | 'violet' | 'black' | 'white' | 'default';
|
||||
|
||||
export interface SettingsMessage extends BaseMessage {
|
||||
kind: 'settings';
|
||||
name: string;
|
||||
webcam: WebcamSettings;
|
||||
color: OctoprintColor;
|
||||
}
|
||||
|
||||
export type Message = StatusMessage | SettingsMessage;
|
||||
|
Loading…
Reference in New Issue
Block a user