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"/>
|
/// <reference path="mjpeg-proxy.d.ts"/>
|
||||||
import { MjpegProxy } from 'mjpeg-proxy';
|
import { MjpegProxy } from 'mjpeg-proxy';
|
||||||
|
|
||||||
import {ExtendedMessage} from '../../types/messages';
|
import {Message, StatusMessage, SettingsMessage} from '../../types/messages';
|
||||||
import * as octoprint from '../../types/octoprint';
|
import * as octoprint from '../../types/octoprint';
|
||||||
|
|
||||||
const PING_TIME = 10000;
|
const PING_TIME = 10000;
|
||||||
@ -13,13 +13,14 @@ type Timeout = ReturnType<typeof setTimeout>;
|
|||||||
export default class OctoprintConnection {
|
export default class OctoprintConnection {
|
||||||
public name?: string;
|
public name?: string;
|
||||||
public webcamProxy?: MjpegProxy;
|
public webcamProxy?: MjpegProxy;
|
||||||
protected lastStatus?: ExtendedMessage;
|
protected lastStatus?: StatusMessage;
|
||||||
|
protected settingsMessage?: SettingsMessage;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public slug: string,
|
public slug: string,
|
||||||
public address: string,
|
public address: string,
|
||||||
protected apikey: string,
|
protected apikey: string,
|
||||||
protected broadcast: (msg: ExtendedMessage) => void
|
protected broadcast: (msg: Message) => void
|
||||||
) {
|
) {
|
||||||
this.try_connect_websocket();
|
this.try_connect_websocket();
|
||||||
}
|
}
|
||||||
@ -41,7 +42,18 @@ export default class OctoprintConnection {
|
|||||||
if (this.webcamProxy === undefined) {
|
if (this.webcamProxy === undefined) {
|
||||||
this.webcamProxy = new MjpegProxy(webcamURL.toString());
|
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
|
// do passive login to get a session key from the API key
|
||||||
const login: octoprint.LoginResponse = await this.api_post('login', {
|
const login: octoprint.LoginResponse = await this.api_post('login', {
|
||||||
@ -66,10 +78,10 @@ export default class OctoprintConnection {
|
|||||||
.on('message', (data: WebSocket.Data) => {
|
.on('message', (data: WebSocket.Data) => {
|
||||||
const event: octoprint.Message = JSON.parse(data as string);
|
const event: octoprint.Message = JSON.parse(data as string);
|
||||||
|
|
||||||
let ext_event: ExtendedMessage = {
|
let ext_event: StatusMessage = {
|
||||||
...event,
|
kind: "status",
|
||||||
printer: this.slug,
|
printer: this.slug,
|
||||||
name: this.name,
|
msg: event,
|
||||||
};
|
};
|
||||||
this.broadcast(ext_event);
|
this.broadcast(ext_event);
|
||||||
|
|
||||||
@ -120,12 +132,12 @@ export default class OctoprintConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
send_init(ws: WebSocket) {
|
send_init(ws: WebSocket) {
|
||||||
let payload: ExtendedMessage;
|
if (this.settingsMessage) {
|
||||||
if (this.lastStatus) {
|
ws.send(JSON.stringify(this.settingsMessage));
|
||||||
payload = this.lastStatus;
|
|
||||||
} else {
|
if (this.lastStatus) {
|
||||||
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 expressWs from 'express-ws';
|
||||||
import * as WebSocket from 'ws';
|
import * as WebSocket from 'ws';
|
||||||
|
|
||||||
import { ExtendedMessage } from '../../types/messages';
|
import { Message } from '../../types/messages';
|
||||||
import OctoPrintConnection from './OctoPrintConnection';
|
import OctoPrintConnection from './OctoPrintConnection';
|
||||||
|
|
||||||
const PORT = process.env.PORT || 1234;
|
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));
|
broadcast(JSON.stringify(payload));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
41
src/App.vue
41
src/App.vue
@ -29,17 +29,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref, Ref } from 'vue';
|
import { computed, ref, Ref } from 'vue';
|
||||||
|
|
||||||
import * as messages from '../types/messages';
|
import { Message, WebcamSettings } from '../types/messages';
|
||||||
import * as octoprint from '../types/octoprint';
|
import PrinterCard, { PrinterInfo } from './PrinterCard.vue';
|
||||||
import PrinterCard from './PrinterCard.vue';
|
|
||||||
|
|
||||||
const printers: Ref<{
|
const printers: Ref<{ [key: string]: PrinterInfo }> = ref({});
|
||||||
[key: string]: {
|
|
||||||
name?: string;
|
|
||||||
lastUpdate: Date;
|
|
||||||
status: octoprint.CurrentOrHistoryPayload | null;
|
|
||||||
};
|
|
||||||
}> = ref({});
|
|
||||||
const hasPrinters = computed(() => Object.keys(printers.value).length > 0);
|
const hasPrinters = computed(() => Object.keys(printers.value).length > 0);
|
||||||
|
|
||||||
let now: Ref<Date> = ref(new Date());
|
let now: Ref<Date> = ref(new Date());
|
||||||
@ -53,22 +46,30 @@ function connectWebsocket() {
|
|||||||
(loc.protocol === 'https:' ? 'wss://' : 'ws://') + loc.host + '/ws';
|
(loc.protocol === 'https:' ? 'wss://' : 'ws://') + loc.host + '/ws';
|
||||||
websocket = new WebSocket(ws_uri);
|
websocket = new WebSocket(ws_uri);
|
||||||
websocket.addEventListener('message', (ev: MessageEvent) => {
|
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);
|
console.log(event);
|
||||||
|
|
||||||
if (!(event.printer in printers.value)) {
|
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();
|
printers.value[event.printer].lastUpdate = new Date();
|
||||||
|
|
||||||
if ('init' in event) {
|
if (event.kind === 'settings') {
|
||||||
printers.value[event.printer].status = null;
|
printers.value[event.printer].name = event.name;
|
||||||
} else if ('current' in event && event.current) {
|
printers.value[event.printer].webcam = event.webcam;
|
||||||
printers.value[event.printer].status = event.current;
|
printers.value[event.printer].color = event.color;
|
||||||
} else if ('history' in event && event.history) {
|
} else if (event.kind === 'status') {
|
||||||
printers.value[event.printer].status = event.history;
|
if ('current' in event.msg && event.msg.current) {
|
||||||
} else if ('remote_ws_status' in event) {
|
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>
|
<template>
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h3 class="card-header">{{ name || 'Unknown' }}</h3>
|
<h3 class="card-header" :data-color="color">
|
||||||
<img class="card-img webcam" :src="'/webcam/' + slug" />
|
{{ name || 'Unknown' }}
|
||||||
|
</h3>
|
||||||
|
<img
|
||||||
|
class="card-img webcam"
|
||||||
|
:style="webcamTransform"
|
||||||
|
:src="'/webcam/' + slug"
|
||||||
|
/>
|
||||||
<div class="card-body" v-if="status">
|
<div class="card-body" v-if="status">
|
||||||
<div>{{ status.state.text }}</div>
|
<div>{{ status.state.text }}</div>
|
||||||
<div>Job File Name: {{ status.job.file.name || 'None' }}</div>
|
<div>Job File Name: {{ status.job.file.name || 'None' }}</div>
|
||||||
@ -26,15 +32,22 @@
|
|||||||
import { computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
import prettyMilliseconds from 'pretty-ms';
|
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;
|
slug: string;
|
||||||
name?: string;
|
name?: string;
|
||||||
lastUpdate: Date;
|
lastUpdate: Date;
|
||||||
now: 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 {
|
function formatDuration(seconds: number): string {
|
||||||
return prettyMilliseconds(seconds * 1000);
|
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>
|
</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;
|
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