diff --git a/package-lock.json b/package-lock.json index e0ed3dd7f..46813fa9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -79,7 +79,7 @@ "start-server-and-test": "^2.0.0", "typescript": "^4.5.5", "unplugin-vue-components": "^0.22.12", - "vite": "^4.4.9", + "vite": "^4.4.12", "vite-plugin-checker": "^0.6.0", "vite-plugin-package-version": "^1.0.2", "vite-plugin-pwa": "^0.16.4", @@ -9593,9 +9593,9 @@ } }, "node_modules/vite": { - "version": "4.4.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.10.tgz", - "integrity": "sha512-TzIjiqx9BEXF8yzYdF2NTf1kFFbjMjUSV0LFZ3HyHoI3SGSPLnnFUKiIQtL3gl2AjHvMrprOvQ3amzaHgQlAxw==", + "version": "4.4.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.12.tgz", + "integrity": "sha512-KtPlUbWfxzGVul8Nut8Gw2Qe8sBzWY+8QVc5SL8iRFnpnrcoCaNlzO40c1R6hPmcdTwIPEDkq0Y9+27a5tVbdQ==", "dev": true, "dependencies": { "esbuild": "^0.18.10", diff --git a/package.json b/package.json index ce340e1cd..24a1efda6 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "start-server-and-test": "^2.0.0", "typescript": "^4.5.5", "unplugin-vue-components": "^0.22.12", - "vite": "^4.4.9", + "vite": "^4.4.12", "vite-plugin-checker": "^0.6.0", "vite-plugin-package-version": "^1.0.2", "vite-plugin-pwa": "^0.16.4", diff --git a/src/components/dialogs/StartPrintDialog.vue b/src/components/dialogs/StartPrintDialog.vue index df282f951..e0642a80c 100644 --- a/src/components/dialogs/StartPrintDialog.vue +++ b/src/components/dialogs/StartPrintDialog.vue @@ -1,7 +1,13 @@ - + + + + + + + + +
@@ -231,6 +240,7 @@ export default class WebcamForm extends Mixins(BaseMixin, WebcamMixin) { { value: 'uv4l-mjpeg', text: this.$t('Settings.WebcamsTab.Uv4lMjpeg') }, { value: 'ipstream', text: this.$t('Settings.WebcamsTab.Ipstream') }, { value: 'webrtc-camerastreamer', text: this.$t('Settings.WebcamsTab.WebrtcCameraStreamer') }, + { value: 'webrtc-go2rtc', text: this.$t('Settings.WebcamsTab.WebrtcGo2rtc') }, { value: 'webrtc-mediamtx', text: this.$t('Settings.WebcamsTab.WebrtcMediaMTX') }, { value: 'hlsstream', text: this.$t('Settings.WebcamsTab.Hlsstream') }, { value: 'jmuxer-stream', text: this.$t('Settings.WebcamsTab.JMuxerStream') }, @@ -263,6 +273,10 @@ export default class WebcamForm extends Mixins(BaseMixin, WebcamMixin) { return ['mjpegstreamer', 'mjpegstreamer-adaptive'].includes(this.webcam.service) } + get hasAudioOption() { + return ['webrtc-go2rtc'].includes(this.webcam.service) + } + get hideFps() { return this.webcam.extra_data?.hideFps ?? false } @@ -280,6 +294,23 @@ export default class WebcamForm extends Mixins(BaseMixin, WebcamMixin) { this.webcam.extra_data.hideFps = newVal } + get enableAudio() { + return this.webcam.extra_data?.enableAudio ?? false + } + + set enableAudio(newVal) { + if (!('extra_data' in this.webcam)) { + this.webcam.extra_data = { + enableAudio: newVal, + } + + return + } + + // @ts-ignore + this.webcam.extra_data.enableAudio = newVal + } + mounted() { this.oldWebcamName = this.webcam.name } diff --git a/src/components/webcams/WebcamWrapperItem.vue b/src/components/webcams/WebcamWrapperItem.vue index 989a88e07..4e7217ef1 100644 --- a/src/components/webcams/WebcamWrapperItem.vue +++ b/src/components/webcams/WebcamWrapperItem.vue @@ -27,6 +27,9 @@ + @@ -51,6 +54,7 @@ import { DynamicCamLoader } from '@/components/webcams/streamers/DynamicCamLoade Uv4lMjpegAsync: DynamicCamLoader('Uv4lMjpeg'), WebrtcCameraStreamerAsync: DynamicCamLoader('WebrtcCameraStreamer'), WebrtcMediaMTXAsync: DynamicCamLoader('WebrtcMediaMTX'), + WebrtcGo2rtcAsync: DynamicCamLoader('WebrtcGo2rtc'), }, }) export default class WebcamWrapperItem extends Mixins(BaseMixin) { diff --git a/src/components/webcams/streamers/DynamicCamLoader.ts b/src/components/webcams/streamers/DynamicCamLoader.ts index 663206e51..a41182f37 100644 --- a/src/components/webcams/streamers/DynamicCamLoader.ts +++ b/src/components/webcams/streamers/DynamicCamLoader.ts @@ -10,6 +10,7 @@ type StreamerTypes = | 'Uv4lMjpeg' | 'WebrtcCameraStreamer' | 'WebrtcMediaMTX' + | 'WebrtcGo2rtc' function getDynamicCamImport(componentName: StreamerTypes) { // split each webcam streamer into its own chunk @@ -32,6 +33,8 @@ function getDynamicCamImport(componentName: StreamerTypes) { return () => import('@/components/webcams/streamers/WebrtcCameraStreamer.vue') case 'WebrtcMediaMTX': return () => import('@/components/webcams/streamers/WebrtcMediaMTX.vue') + case 'WebrtcGo2rtc': + return () => import('@/components/webcams/streamers/WebrtcGo2rtc.vue') } } diff --git a/src/components/webcams/streamers/WebrtcGo2rtc.vue b/src/components/webcams/streamers/WebrtcGo2rtc.vue new file mode 100644 index 000000000..f3bb47926 --- /dev/null +++ b/src/components/webcams/streamers/WebrtcGo2rtc.vue @@ -0,0 +1,247 @@ + + + + + diff --git a/src/locales/de.json b/src/locales/de.json index b6e494ec9..10ab43ba8 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -17,7 +17,9 @@ }, "MoonrakerWarnings": { "MoonrakerComponent": "Moonraker: {component}", - "MoonrakerFailedComponentDescription": "Beim Laden der Moonraker-Komponenten wurde ein Fehler festgestellt. Bitte prüfe die Logdatei und behebe das Problem.", + "MoonrakerFailedComponentDescription": "Beim Laden der Moonraker-Komponente '{component}' wurde ein Fehler festgestellt. Bitte prüfe die Logdatei und behebe das Problem.", + "MoonrakerFailedInitComponentDescription": "Beim Initialisieren der Moonraker-Komponente '{component}' wurde ein Fehler festgestellt. Bitte prüfe die Logdatei und behebe das Problem.", + "MoonrakerInitComponent": "Init. Moonraker: {component}", "MoonrakerWarning": "Moonraker Warnung", "UnparsedConfigOption": "Nicht erkannte Config-Option '{option}: {value}' in Abschnitt [{section}] entdeckt. Dies kann eine Option sein, die nicht mehr verfügbar ist, oder das Ergebnis eines Moduls sein, das nicht geladen werden konnte. In Zukunft wird dies zu einem Startfehler führen.", "UnparsedConfigSection": "Nicht erkannter Config-Abschnitt [{section}] gefunden. Dies kann das Ergebnis einer Komponente sein, die nicht geladen werden konnte. In Zukunft wird dies zu einem Startfehler führen." @@ -539,10 +541,12 @@ "CleanNozzle": "Düse reinigen", "EstimatedExtrusion": "Extrusion:", "Extrude": "Extrudieren", + "ExtruderControl": "Extruder Control", "ExtruderTempTooLow": "Extruder Temp. <", "ExtrusionFactor": "Extrusionsfaktor", "ExtrusionFeedrate": "Extrusionsgeschwindigkeit", "FilamentLength": "Filamentlänge", + "FirmwareRetraction": "Firmware Rückzug", "FirmwareRetractionSettings": { "RetractLength": "Rückzugslänge", "RetractSpeed": "Rückzuggeschwindigkeit", @@ -551,6 +555,7 @@ }, "Headline": "Extruder", "LoadFilament": "Filament laden", + "PressureAdvance": "Pressure Advance", "PressureAdvanceSettings": { "Advance": "Pressure Advance", "Extruder": "Extruder", @@ -560,6 +565,7 @@ "Requested": "Angefordert", "Retract": "Rückzug", "TooLargeExtrusion": "Extrusion zu groß!", + "Tools": "Werkzeuge", "UnloadFilament": "Filament entladen" }, "FarmPrinterPanel": { @@ -582,6 +588,7 @@ "MotionSettings": { "Acceleration": "Beschleunigung", "MaxAccelToDecel": "Max. Beschl. zu Verz.", + "MinimumCruiseRatio": "Min. Kreuzfahr Quote", "SquareCornerVelocity": "Eck-Geschwindigkeit", "Velocity": "Geschwindigkeit" } @@ -614,8 +621,7 @@ }, "RunoutSensor": { "Detected": "erkannt", - "Disabled": "deaktiviert", - "Empty": "Leer" + "Empty": "leer" } }, "PowerControlPanel": { @@ -1142,6 +1148,7 @@ "CreateWebcam": "Erstelle Webcam", "EditCrowsnestConf": "crowsnest.conf bearbeiten", "EditWebcam": "Webcam bearbeiten", + "EnableAudio": "Ton einschalten", "FlipWebcam": "Webcam-Bild spiegeln:", "HideFps": "FPS-Anzeige verstecken", "Hlsstream": "HLS-Stream", diff --git a/src/locales/en.json b/src/locales/en.json index 54427a36f..dae617c70 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -18,6 +18,8 @@ "MoonrakerWarnings": { "MoonrakerComponent": "Moonraker: {component}", "MoonrakerFailedComponentDescription": "An error was detected while loading the moonraker component '{component}'. Please check the log file and fix the issue.", + "MoonrakerFailedInitComponentDescription": "An error was detected during initialization the moonraker component '{component}'. Please check the log file and fix the issue.", + "MoonrakerInitComponent": "Init. Moonraker: {component}", "MoonrakerWarning": "Moonraker warning", "UnparsedConfigOption": "Unparsed config option '{option}: {value}' detected in section [{section}]. This may be an option no longer available or could be the result of a module that failed to load. In the future this will result in a startup error.", "UnparsedConfigSection": "Unparsed config section [{section}] detected. This may be the result of a component that failed to load. In the future this will result in a startup error." @@ -541,10 +543,12 @@ "CleanNozzle": "Clean Nozzle", "EstimatedExtrusion": "Extrusion:", "Extrude": "Extrude", + "ExtruderControl": "Extruder Control", "ExtruderTempTooLow": "Extruder temp. <", "ExtrusionFactor": "Extrusion factor", "ExtrusionFeedrate": "Extrusion Feedrate", "FilamentLength": "Filament Length", + "FirmwareRetraction": "Firmware Retraction", "FirmwareRetractionSettings": { "RetractLength": "Retract Length", "RetractSpeed": "Retract Speed", @@ -553,6 +557,7 @@ }, "Headline": "Extruder", "LoadFilament": "Load Filament", + "PressureAdvance": "Pressure Advance", "PressureAdvanceSettings": { "Advance": "Pressure Advance", "Extruder": "Extruder", @@ -562,6 +567,7 @@ "Requested": "Requested", "Retract": "Retract", "TooLargeExtrusion": "Extrusion too large!", + "Tools": "Tools", "UnloadFilament": "Unload Filament" }, "FarmPrinterPanel": { @@ -584,6 +590,7 @@ "MotionSettings": { "Acceleration": "Acceleration", "MaxAccelToDecel": "Max Accel. to Decel.", + "MinimumCruiseRatio": "Min. Cruise Ratio", "SquareCornerVelocity": "Square Corner Velocity", "Velocity": "Velocity" } @@ -616,8 +623,7 @@ }, "RunoutSensor": { "Detected": "detected", - "Disabled": "disabled", - "Empty": "Empty" + "Empty": "empty" } }, "PowerControlPanel": { @@ -1162,6 +1168,7 @@ "CreateWebcam": "Create Webcam", "EditCrowsnestConf": "Edit crowsnest.conf", "EditWebcam": "Edit Webcam", + "EnableAudio": "Enable audio", "FlipWebcam": "Flip webcam image:", "HideFps": "Hide FPS counter", "Hlsstream": "HLS Stream", @@ -1192,6 +1199,7 @@ "Vertically": "vertically", "Webcams": "Webcams", "WebrtcCameraStreamer": "WebRTC (camera-streamer)", + "WebrtcGo2rtc": "WebRTC (go2rtc)", "WebrtcJanus": "WebRTC (janus-gateway)", "WebrtcMediaMTX": "WebRTC (MediaMTX)" } diff --git a/src/pages/Heightmap.vue b/src/pages/Heightmap.vue index f193982fa..062ac7b15 100644 --- a/src/pages/Heightmap.vue +++ b/src/pages/Heightmap.vue @@ -89,7 +89,7 @@ ref="heightmap" :option="chartOptions" :init-options="{ renderer: 'canvas' }" - style="height: 400px; width: 100%; overflow: hidden" /> + style="height: 600px; width: 100%; overflow: hidden" /> @@ -546,7 +546,7 @@ export default class PageHeightmap extends Mixins(BaseMixin, ControlMixin) { top: 20, bottom: 0, itemWidth: this.isMobile ? 10 : 30, - itemHeight: 350, + itemHeight: 550, precision: 3, textStyle: { color: this.colorVisualMap, @@ -619,6 +619,9 @@ export default class PageHeightmap extends Mixins(BaseMixin, ControlMixin) { }, boxWidth: 100 * this.scaleX, boxDepth: 100 * this.scaleY, + viewControl: { + distance: 150, + }, }, series: this.series, } diff --git a/src/plugins/webSocketClient.ts b/src/plugins/webSocketClient.ts index b79d5cc35..ec5a34f84 100644 --- a/src/plugins/webSocketClient.ts +++ b/src/plugins/webSocketClient.ts @@ -61,10 +61,21 @@ export class WebSocketClient { // report error messages if (data.error?.message) { - if (data.error?.message !== 'Klippy Disconnected') + // only report errors, if not disconnected and no init component + if (data.error?.message !== 'Klippy Disconnected' && !wait?.action?.startsWith('server/')) { window.console.error(`Response Error: ${data.error.message} (${wait?.action ?? 'no action'})`) - - if (wait?.id) this.removeWaitById(wait.id) + } + + if (wait?.id) { + if (wait.action?.startsWith('server/')) { + const component = wait.action.replace('server/', '').split('/')[0] + window.console.error(`init server component ${component} failed`) + this.store?.dispatch('server/addFailedInitComponent', component) + this.store?.dispatch('socket/removeInitComponent', `server/${component}/`) + } + + this.removeWaitById(wait.id) + } return } diff --git a/src/store/gui/index.ts b/src/store/gui/index.ts index 67e08dbd4..4420c0167 100644 --- a/src/store/gui/index.ts +++ b/src/store/gui/index.ts @@ -183,6 +183,13 @@ export const getDefaultState = (): GuiState => { rootPath: 'config', selectedFiles: [], }, + extruder: { + showTools: true, + showExtrusionFactor: true, + showPressureAdvance: true, + showFirmwareRetraction: true, + showExtruderControl: true, + }, gcodefiles: { countPerPage: 10, sortBy: 'modified', diff --git a/src/store/gui/notifications/getters.ts b/src/store/gui/notifications/getters.ts index a4072f186..2384c1d90 100644 --- a/src/store/gui/notifications/getters.ts +++ b/src/store/gui/notifications/getters.ts @@ -28,6 +28,9 @@ export const getters: GetterTree = { // moonraker failed components notifications = notifications.concat(getters['getNotificationsMoonrakerFailedComponents']) + // moonraker failed init components + notifications = notifications.concat(getters['getNotificationsMoonrakerFailedInitComponents']) + // klipper warnings notifications = notifications.concat(getters['getNotificationsKlipperWarnings']) @@ -224,6 +227,44 @@ export const getters: GetterTree = { return notifications }, + getNotificationsMoonrakerFailedInitComponents: (state, getters, rootState, rootGetters) => { + const notifications: GuiNotificationStateEntry[] = [] + + let failedInitCompontents = rootState.server.failed_init_components ?? [] + if (failedInitCompontents.length) { + const date = rootState.server.system_boot_at ?? new Date() + + // get all dismissed failed components and convert it to a string[] + const flagDismisses = rootGetters['gui/notifications/getDismissByCategory']( + 'moonrakerFailedInitComponent' + ).map((dismiss: GuiNotificationStateDismissEntry) => { + return dismiss.id + }) + + // filter all dismissed failed init components + failedInitCompontents = failedInitCompontents.filter( + (component: string) => !flagDismisses.includes(component) + ) + + failedInitCompontents.forEach((component: string) => { + notifications.push({ + id: `moonrakerFailedInitComponent/${component}`, + priority: 'high', + title: i18n + .t('App.Notifications.MoonrakerWarnings.MoonrakerInitComponent', { component }) + .toString(), + description: i18n + .t('App.Notifications.MoonrakerWarnings.MoonrakerFailedInitComponentDescription', { component }) + .toString(), + date, + dismissed: false, + } as GuiNotificationStateEntry) + }) + } + + return notifications + }, + getNotificationsKlipperWarnings: (state, getters, rootState, rootGetters) => { const notifications: GuiNotificationStateEntry[] = [] diff --git a/src/store/gui/types.ts b/src/store/gui/types.ts index 3122373e5..7b879d35f 100644 --- a/src/store/gui/types.ts +++ b/src/store/gui/types.ts @@ -132,6 +132,13 @@ export interface GuiState { rootPath: string selectedFiles: FileStateFile[] } + extruder: { + showTools: boolean + showExtrusionFactor: boolean + showPressureAdvance: boolean + showFirmwareRetraction: boolean + showExtruderControl: boolean + } gcodefiles: { countPerPage: number sortBy: string diff --git a/src/store/gui/webcams/types.ts b/src/store/gui/webcams/types.ts index 50f03153b..a5566b62c 100644 --- a/src/store/gui/webcams/types.ts +++ b/src/store/gui/webcams/types.ts @@ -26,6 +26,7 @@ export interface GuiWebcamStateWebcam { rotation: number aspect_ratio?: string extra_data?: { + enableAudio?: boolean hideFps?: boolean } source?: 'config' | 'database' diff --git a/src/store/server/actions.ts b/src/store/server/actions.ts index b5a915735..93aeb4ce3 100644 --- a/src/store/server/actions.ts +++ b/src/store/server/actions.ts @@ -292,4 +292,9 @@ export const actions: ActionTree = { serviceStateChanged({ commit }, payload) { commit('updateServiceState', payload) }, + + addFailedInitComponent({ commit }, payload) { + commit('removeComponent', payload) + commit('addFailedInitComponent', payload) + }, } diff --git a/src/store/server/index.ts b/src/store/server/index.ts index 643e9ce4c..1fde111a3 100644 --- a/src/store/server/index.ts +++ b/src/store/server/index.ts @@ -23,6 +23,7 @@ export const getDefaultState = (): ServerState => { klippy_message: '', components: [], failed_components: [], + failed_init_components: [], warnings: [], registered_directories: [], events: [], diff --git a/src/store/server/mutations.ts b/src/store/server/mutations.ts index d31d00693..da2777490 100644 --- a/src/store/server/mutations.ts +++ b/src/store/server/mutations.ts @@ -160,4 +160,21 @@ export const mutations: MutationTree = { if (state.system_info?.service_state) Vue.set(state.system_info.service_state, name, payload[name]) }, + + addFailedInitComponent(state, payload) { + const failed_init_components = state.failed_init_components + if (!failed_init_components.includes(payload)) failed_init_components.push(payload) + + Vue.set(state, 'failed_init_components', failed_init_components) + }, + + removeComponent(state, payload) { + const components = state.components + const index = components.indexOf(payload) + + if (index === -1) return + + components.splice(index, 1) + Vue.set(state, 'components', components) + }, } diff --git a/src/store/server/types.ts b/src/store/server/types.ts index 03c5f0c11..69d6fe399 100644 --- a/src/store/server/types.ts +++ b/src/store/server/types.ts @@ -11,6 +11,7 @@ export interface ServerState { klippy_message: string components: string[] failed_components: string[] + failed_init_components: string[] warnings: string[] registered_directories: string[] events: ServerStateEvent[] diff --git a/src/store/socket/actions.ts b/src/store/socket/actions.ts index a58a016d1..30f8cf7c8 100644 --- a/src/store/socket/actions.ts +++ b/src/store/socket/actions.ts @@ -153,10 +153,16 @@ export const actions: ActionTree = { commit('addInitModule', payload) }, + // remove only one module from init component like 'server/spoolman/getActiveSpoolId' removeInitModule({ commit }, payload: string) { commit('removeInitModule', payload) }, + // remove a complete init component like 'server/spoolman' + removeInitComponent({ commit }, payload: string) { + commit('removeInitComponent', payload) + }, + reportDebug(_, payload) { window.console.log(payload) }, diff --git a/src/store/socket/mutations.ts b/src/store/socket/mutations.ts index 61972f40f..9399eb169 100644 --- a/src/store/socket/mutations.ts +++ b/src/store/socket/mutations.ts @@ -61,4 +61,22 @@ export const mutations: MutationTree = { list.splice(index, 1) Vue.set(state, 'initializationList', list) }, + + removeInitComponent(state, payload) { + const list = [...state.initializationList] + + // remove all components witch starts with payload + const indexes = list.reduce((acc: number[], item, index) => { + if (item.startsWith(payload)) acc.push(index) + return acc + }, []) + + // stop if no items found + if (!indexes.length) return + + // remove all items + indexes.forEach((index) => list.splice(index, 1)) + + Vue.set(state, 'initializationList', list) + }, } diff --git a/src/store/variables.ts b/src/store/variables.ts index 5673c35ce..71c6ca2f2 100644 --- a/src/store/variables.ts +++ b/src/store/variables.ts @@ -92,9 +92,9 @@ export const allDashboardPanels = [ 'webcam', ] -export const thumbnailSmallMin = 32 +export const thumbnailSmallMin = 30 export const thumbnailSmallMax = 64 -export const thumbnailBigMin = 256 +export const thumbnailBigMin = 128 export const navigationWidth = 220 export const navigationItemHeight = 48