mirror of
https://github.com/gensokyo-zone/infrastructure.git
synced 2026-02-09 12:29:19 -08:00
feat(octoprint): motion and notifs
This commit is contained in:
parent
6bf729ffe9
commit
7fe6d48ff0
11 changed files with 263 additions and 47 deletions
34
nixos/cameras/kitchen.nix
Normal file
34
nixos/cameras/kitchen.nix
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
gensokyo-zone,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (gensokyo-zone.lib) mapDefaults;
|
||||||
|
inherit (config.services) motion;
|
||||||
|
in {
|
||||||
|
services.motion.cameras.kitchencam.settings = mapDefaults {
|
||||||
|
videodevice = "/dev/kitchencam";
|
||||||
|
v4l2_palette = 8;
|
||||||
|
width = 640;
|
||||||
|
height = 480;
|
||||||
|
framerate = 5;
|
||||||
|
camera_id = 1;
|
||||||
|
text_left = "kitchen";
|
||||||
|
};
|
||||||
|
services.udev.extraRules = let
|
||||||
|
inherit (lib.strings) concatStringsSep;
|
||||||
|
rules = [
|
||||||
|
''SUBSYSTEM=="video4linux"''
|
||||||
|
''ACTION=="add"''
|
||||||
|
''ATTR{index}=="0"''
|
||||||
|
''ATTRS{idProduct}=="2a25"''
|
||||||
|
''ATTRS{idVendor}=="1224"''
|
||||||
|
''SYMLINK+="kitchencam"''
|
||||||
|
''OWNER="${motion.user}"''
|
||||||
|
''TAG+="systemd"''
|
||||||
|
''ENV{SYSTEMD_WANTS}="motion.service"''
|
||||||
|
];
|
||||||
|
rulesLine = concatStringsSep ", " rules;
|
||||||
|
in rulesLine;
|
||||||
|
}
|
||||||
12
nixos/cameras/logistics-webcam.nix
Normal file
12
nixos/cameras/logistics-webcam.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
gensokyo-zone,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (gensokyo-zone.lib) mapDefaults;
|
||||||
|
in {
|
||||||
|
services.motion.cameras.webcam.settings = mapDefaults {
|
||||||
|
videodevice = "/dev/video0";
|
||||||
|
camera_id = 3;
|
||||||
|
text_left = "logistics";
|
||||||
|
};
|
||||||
|
}
|
||||||
34
nixos/cameras/printer.nix
Normal file
34
nixos/cameras/printer.nix
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
gensokyo-zone,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (gensokyo-zone.lib) mapDefaults;
|
||||||
|
inherit (config.services) motion;
|
||||||
|
in {
|
||||||
|
services.motion.cameras.printercam.settings = mapDefaults {
|
||||||
|
videodevice = "/dev/printercam";
|
||||||
|
width = 640;
|
||||||
|
height = 480;
|
||||||
|
framerate = 5;
|
||||||
|
camera_id = 2;
|
||||||
|
text_left = "";
|
||||||
|
#text_right = "";
|
||||||
|
};
|
||||||
|
services.udev.extraRules = let
|
||||||
|
inherit (lib.strings) concatStringsSep;
|
||||||
|
rules = [
|
||||||
|
''SUBSYSTEM=="video4linux"''
|
||||||
|
''ACTION=="add"''
|
||||||
|
''ATTR{index}=="0"''
|
||||||
|
''ATTRS{idProduct}=="6366"''
|
||||||
|
''ATTRS{idVendor}=="0c45"''
|
||||||
|
''SYMLINK+="printercam"''
|
||||||
|
''OWNER="${motion.user}"''
|
||||||
|
''TAG+="systemd"''
|
||||||
|
''ENV{SYSTEMD_WANTS}="motion.service"''
|
||||||
|
];
|
||||||
|
rulesLine = concatStringsSep ", " rules;
|
||||||
|
in rulesLine;
|
||||||
|
}
|
||||||
|
|
@ -33,32 +33,7 @@ in {
|
||||||
webcontrol_port = webPort;
|
webcontrol_port = webPort;
|
||||||
stream_port = streamPort;
|
stream_port = streamPort;
|
||||||
};
|
};
|
||||||
cameras.kitchencam.settings = mapDefaults {
|
|
||||||
videodevice = "/dev/kitchencam";
|
|
||||||
v4l2_palette = 8;
|
|
||||||
width = 640;
|
|
||||||
height = 480;
|
|
||||||
framerate = 5;
|
|
||||||
camera_id = 1;
|
|
||||||
text_left = "kitchen";
|
|
||||||
};
|
};
|
||||||
};
|
|
||||||
services.udev.extraRules = let
|
|
||||||
inherit (lib.strings) concatStringsSep;
|
|
||||||
rules = [
|
|
||||||
''SUBSYSTEM=="video4linux"''
|
|
||||||
''ACTION=="add"''
|
|
||||||
''ATTR{index}=="0"''
|
|
||||||
''ATTRS{idProduct}=="2a25"''
|
|
||||||
''ATTRS{idVendor}=="1224"''
|
|
||||||
''SYMLINK+="kitchencam"''
|
|
||||||
''OWNER="${cfg.user}"''
|
|
||||||
''TAG+="systemd"''
|
|
||||||
''ENV{SYSTEMD_WANTS}="motion.service"''
|
|
||||||
];
|
|
||||||
rulesLine = concatStringsSep ", " rules;
|
|
||||||
in
|
|
||||||
mkIf cfg.enable rulesLine;
|
|
||||||
networking.firewall.interfaces.local = mkIf cfg.enable {
|
networking.firewall.interfaces.local = mkIf cfg.enable {
|
||||||
allowedTCPPorts = [cfg.settings.stream_port cfg.settings.webcontrol_port];
|
allowedTCPPorts = [cfg.settings.stream_port cfg.settings.webcontrol_port];
|
||||||
};
|
};
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
{
|
{
|
||||||
pkgs,
|
|
||||||
config,
|
config,
|
||||||
access,
|
access,
|
||||||
|
gensokyo-zone,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
|
inherit (gensokyo-zone.lib) domain;
|
||||||
inherit (lib.modules) mkIf mkMerge mkDefault;
|
inherit (lib.modules) mkIf mkMerge mkDefault;
|
||||||
inherit (config.services) motion;
|
inherit (config.services) motion;
|
||||||
cfg = config.services.octoprint;
|
cfg = config.services.octoprint;
|
||||||
behindVouch = false;
|
vouchHeader = null;
|
||||||
|
#vouchHeader = "X-Vouch-User";
|
||||||
in {
|
in {
|
||||||
services.octoprint = {
|
services.octoprint = {
|
||||||
enable = mkDefault true;
|
enable = mkDefault true;
|
||||||
|
|
@ -16,6 +18,7 @@ in {
|
||||||
plugins = python3Packages: with python3Packages; [
|
plugins = python3Packages: with python3Packages; [
|
||||||
prometheus-exporter
|
prometheus-exporter
|
||||||
octorant
|
octorant
|
||||||
|
queue
|
||||||
abl-expert
|
abl-expert
|
||||||
bedlevelvisualizer
|
bedlevelvisualizer
|
||||||
#displayprogress / displaylayerprogress?
|
#displayprogress / displaylayerprogress?
|
||||||
|
|
@ -66,27 +69,113 @@ in {
|
||||||
serial = {
|
serial = {
|
||||||
port = "/dev/ttyUSB0";
|
port = "/dev/ttyUSB0";
|
||||||
baudrate = 115200;
|
baudrate = 115200;
|
||||||
#autoconnect = true;
|
autoconnect = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
plugins.octorant = let
|
||||||
|
media = {
|
||||||
|
none = "none";
|
||||||
|
webcam = "snapshot";
|
||||||
|
#timelapse = ?;
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
_config_version = 2;
|
||||||
|
events = {
|
||||||
|
printer_state_error.media = media.none;
|
||||||
|
printer_state_operational = {
|
||||||
|
enabled = false;
|
||||||
|
media = media.none;
|
||||||
|
};
|
||||||
|
printer_state_unknown.media = media.none;
|
||||||
|
printing_started = {
|
||||||
|
message = "New print started: **{name}**";
|
||||||
|
};
|
||||||
|
printing_cancelled = {
|
||||||
|
message = "Print cancelled after {time_formatted}";
|
||||||
|
};
|
||||||
|
printing_paused = {
|
||||||
|
message = "Print paused";
|
||||||
|
media = media.none;
|
||||||
|
};
|
||||||
|
printing_failed.message = "Print failed! :<";
|
||||||
|
printing_progress.message = "Printed **{progress}%** with {remaining_formatted} remaining";
|
||||||
|
printing_resumed = {
|
||||||
|
message = "Print resumed";
|
||||||
|
media = media.none;
|
||||||
|
};
|
||||||
|
shutdown = {
|
||||||
|
#enabled = false;
|
||||||
|
media = media.none;
|
||||||
|
};
|
||||||
|
startup = {
|
||||||
|
#enabled = false;
|
||||||
|
media = media.none;
|
||||||
|
};
|
||||||
|
timelapse_done = {
|
||||||
|
enabled = true;
|
||||||
|
# TODO: movie_basename needs uri encoding if it contains spaces .-.
|
||||||
|
message = "Timelapse for {gcode}: https://print.${domain}/downloads/timelapse/{movie_basename}";
|
||||||
|
media = media.none;
|
||||||
|
};
|
||||||
|
timelapse_failed.media = media.none;
|
||||||
|
transfer_done.media = media.none;
|
||||||
|
transfer_failed.media = media.none;
|
||||||
|
transfer_progress.media = media.none;
|
||||||
|
progress = {
|
||||||
|
#percentage_enabled = false;
|
||||||
|
percentage_step = "14";
|
||||||
|
throttle_enabled = true;
|
||||||
|
time_enabled = true;
|
||||||
|
throttle_step = "540";
|
||||||
|
time_step = "600";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# TODO: url = "https://discord.com/api/webhooks/etc";
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
(mkIf motion.enable {
|
(mkIf motion.enable {
|
||||||
webcam = {
|
webcam = {
|
||||||
# TODO
|
bitrate = "6000k";
|
||||||
|
ffmpegThreads = 2;
|
||||||
|
timelapse = {
|
||||||
|
fps = 25;
|
||||||
|
options.interval = 3;
|
||||||
|
postRoll = 0;
|
||||||
|
type = "timed";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
plugins = {
|
||||||
|
classicwebcam = let
|
||||||
|
inherit (motion.cameras) printercam;
|
||||||
|
inherit (printercam.settings) camera_id;
|
||||||
|
in {
|
||||||
|
_config_version = 1;
|
||||||
|
snapshot = "https://kitchen.local.${domain}/${toString camera_id}/current";
|
||||||
|
stream = "https://kitchen.local.${domain}/${toString camera_id}/stream";
|
||||||
|
streamRatio = "4:3";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
(mkIf (!behindVouch) {
|
(mkIf (vouchHeader == null) {
|
||||||
accessControl = {
|
accessControl = {
|
||||||
autologinLocal = true;
|
autologinLocal = true;
|
||||||
|
autologinHeadsupAcknowledged = true;
|
||||||
#autologinAs = "guest";
|
#autologinAs = "guest";
|
||||||
autologinAs = "admin";
|
autologinAs = "admin";
|
||||||
localNetworks = access.cidrForNetwork.allLocal.all;
|
localNetworks = access.cidrForNetwork.allLocal.all
|
||||||
|
++ [
|
||||||
|
# vouch protects it from the outside world so...
|
||||||
|
"0.0.0.0/0"
|
||||||
|
"::/0"
|
||||||
|
];
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
(mkIf behindVouch {
|
(mkIf (vouchHeader != null) {
|
||||||
accessControl = {
|
accessControl = {
|
||||||
trustRemoteUser = true;
|
trustRemoteUser = true;
|
||||||
addRemoteUsers = true;
|
addRemoteUsers = true;
|
||||||
remoteUserHeader = "X-Vouch-User";
|
remoteUserHeader = vouchHeader;
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ in {
|
||||||
inherit (python3Packages) buildPlugin;
|
inherit (python3Packages) buildPlugin;
|
||||||
};
|
};
|
||||||
packageOverrides = python3Packages: python3Packages'prev: lib.mapAttrs (mapPlugin python3Packages) {
|
packageOverrides = python3Packages: python3Packages'prev: lib.mapAttrs (mapPlugin python3Packages) {
|
||||||
inherit (final.octoprintPlugins) prometheus-exporter octorant;
|
inherit (final.octoprintPlugins) prometheus-exporter octorant queue printtimegenius;
|
||||||
};
|
};
|
||||||
octoprint = prev.octoprint.override (old: {
|
octoprint = prev.octoprint.override (old: {
|
||||||
packageOverrides = lib.composeExtensions old.packageOverrides or (_: _: {}) packageOverrides;
|
packageOverrides = lib.composeExtensions old.packageOverrides or (_: _: {}) packageOverrides;
|
||||||
|
|
@ -31,8 +31,20 @@ in {
|
||||||
|
|
||||||
prometheus-exporter = callPackage ../packages/octoprint/prometheus-exporter.nix { };
|
prometheus-exporter = callPackage ../packages/octoprint/prometheus-exporter.nix { };
|
||||||
octorant = callPackage ../packages/octoprint/octorant.nix { };
|
octorant = callPackage ../packages/octoprint/octorant.nix { };
|
||||||
|
queue = callPackage ../packages/octoprint/queue.nix { };
|
||||||
|
printtimegenius = let
|
||||||
|
printtimegenius = { fetchFromGitHub, python3Packages, buildPlugin }: octoprintPlugins.printtimegenius.overrideAttrs (old: rec {
|
||||||
|
version = lib.warnIf (lib.versionAtLeast old.version "2.3.2") "printtimegenius updated upstream" "2.3.3";
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
inherit (old.src) owner repo;
|
||||||
|
rev = version;
|
||||||
|
sha256 = "sha256-hqm8RShCNpsVbrVXquat5VXqcVc7q5tn5+7Ipqmaw4U=";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
in callPackage printtimegenius { };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
# XXX: build broken upstream ugh...
|
||||||
curaengine = prev.curaengine.override {
|
curaengine = prev.curaengine.override {
|
||||||
inherit (final.python311Packages) libarcus;
|
inherit (final.python311Packages) libarcus;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,14 @@
|
||||||
, python3Packages
|
, python3Packages
|
||||||
, fetchFromGitHub
|
, fetchFromGitHub
|
||||||
}: let
|
}: let
|
||||||
|
pname = "OctoPrint-Octorant";
|
||||||
version = "1.3.4";
|
version = "1.3.4";
|
||||||
in buildPlugin {
|
in buildPlugin {
|
||||||
pname = "OctoPrint-Octorant";
|
inherit pname version;
|
||||||
inherit version;
|
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "bchanudet";
|
owner = "bchanudet";
|
||||||
repo = "OctoPrint-Octorant";
|
repo = pname;
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "sha256-gP79zlJ8gdtpddXOJIMhouSbwXnrSf+c1bURkN/7jvw=";
|
sha256 = "sha256-gP79zlJ8gdtpddXOJIMhouSbwXnrSf+c1bURkN/7jvw=";
|
||||||
};
|
};
|
||||||
|
|
|
||||||
39
packages/octoprint/prometheus-exporter-deregister.patch
Normal file
39
packages/octoprint/prometheus-exporter-deregister.patch
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
diff --git a/octoprint_prometheus_exporter/__init__.py b/octoprint_prometheus_exporter/__init__.py
|
||||||
|
--- a/octoprint_prometheus_exporter/__init__.py
|
||||||
|
+++ b/octoprint_prometheus_exporter/__init__.py
|
||||||
|
@@ -53,15 +53,22 @@ class PrometheusExporterPlugin(octoprint.plugin.BlueprintPlugin,
|
||||||
|
self.print_completion_timer = None
|
||||||
|
|
||||||
|
def print_deregister_callback(self, label):
|
||||||
|
- if label != '':
|
||||||
|
+ self.print_progress_label = ''
|
||||||
|
+ if label == '':
|
||||||
|
+ return
|
||||||
|
+ try:
|
||||||
|
self.metrics.print_progress.remove(label)
|
||||||
|
self.metrics.print_time_elapsed.remove(label)
|
||||||
|
self.metrics.print_time_est.remove(label)
|
||||||
|
self.metrics.print_time_left_est.remove(label)
|
||||||
|
- self.print_progress_label = ''
|
||||||
|
+ except Exception as err:
|
||||||
|
+ self._logger.warning(err)
|
||||||
|
|
||||||
|
def slice_deregister_callback(self, label):
|
||||||
|
- self.metrics.slice_progress.remove(label)
|
||||||
|
+ try:
|
||||||
|
+ self.metrics.slice_progress.remove(label)
|
||||||
|
+ except Exception as err:
|
||||||
|
+ self._logger.warning(err)
|
||||||
|
|
||||||
|
def print_complete(self):
|
||||||
|
self.metrics.printing_time_total.inc(time.time() - self.print_time_start)
|
||||||
|
@@ -74,7 +81,8 @@ class PrometheusExporterPlugin(octoprint.plugin.BlueprintPlugin,
|
||||||
|
|
||||||
|
self.print_completion_timer = Timer(30, self.print_complete_callback)
|
||||||
|
self.print_completion_timer.start()
|
||||||
|
- Timer(30, lambda: self.print_deregister_callback(self.print_progress_label)).start()
|
||||||
|
+ print_progress_label = self.print_progress_label
|
||||||
|
+ Timer(30, lambda: self.print_deregister_callback(print_progress_label)).start()
|
||||||
|
|
||||||
|
def deactivateMetricsIfOffline(self, payload):
|
||||||
|
if payload['state_id'] == 'OFFLINE':
|
||||||
|
|
@ -18,6 +18,10 @@ in buildPlugin {
|
||||||
prometheus-client
|
prometheus-client
|
||||||
];
|
];
|
||||||
|
|
||||||
|
patches = [
|
||||||
|
./prometheus-exporter-deregister.patch
|
||||||
|
];
|
||||||
|
|
||||||
meta = {
|
meta = {
|
||||||
homepage = "https://github.com/tg44/OctoPrint-Prometheus-Exporter";
|
homepage = "https://github.com/tg44/OctoPrint-Prometheus-Exporter";
|
||||||
};
|
};
|
||||||
|
|
|
||||||
23
packages/octoprint/queue.nix
Normal file
23
packages/octoprint/queue.nix
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
{ buildPlugin
|
||||||
|
, python3Packages
|
||||||
|
, fetchFromGitHub
|
||||||
|
}: let
|
||||||
|
version = "2.0.0";
|
||||||
|
pname = "OctoPrint-Queue";
|
||||||
|
in buildPlugin {
|
||||||
|
inherit pname version;
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "chennes";
|
||||||
|
repo = pname;
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "sha256-uAG6GrUKXUdUTtzmjKWPiHxMa3ekvoLpSIvFMiJI+/8=";
|
||||||
|
};
|
||||||
|
|
||||||
|
propagatedBuildInputs = with python3Packages; [
|
||||||
|
];
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
homepage = "https://github.com/chennes/OctoPrint-Queue";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -13,7 +13,10 @@ in {
|
||||||
nixos.sops
|
nixos.sops
|
||||||
nixos.base
|
nixos.base
|
||||||
nixos.barcodebuddy-scanner
|
nixos.barcodebuddy-scanner
|
||||||
nixos.kitchencam
|
nixos.motion
|
||||||
|
nixos.cameras.kitchen
|
||||||
|
nixos.cameras.printer
|
||||||
|
nixos.cameras.logistics-webcam
|
||||||
nixos.octoprint
|
nixos.octoprint
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
];
|
];
|
||||||
|
|
@ -49,15 +52,6 @@ in {
|
||||||
#jack.enable = true;
|
#jack.enable = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
services.motion.cameras.webcam = {
|
|
||||||
#enable = false;
|
|
||||||
settings = {
|
|
||||||
videodevice = "/dev/video0";
|
|
||||||
camera_id = 2;
|
|
||||||
text_left = "logistics";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.systemPackages = [ pkgs.cura-octoprint ];
|
environment.systemPackages = [ pkgs.cura-octoprint ];
|
||||||
|
|
||||||
users.users.logistics = {
|
users.users.logistics = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue