mirror of
https://github.com/gensokyo-zone/infrastructure.git
synced 2026-02-09 04:19:19 -08:00
feat(motion): kitchencam lives!
This commit is contained in:
parent
fb5ffd50b9
commit
690f86b3bd
6 changed files with 185 additions and 7 deletions
104
modules/nixos/motion.nix
Normal file
104
modules/nixos/motion.nix
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
config,
|
||||||
|
gensokyo-zone,
|
||||||
|
utils,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (gensokyo-zone.lib) mapOptionDefaults;
|
||||||
|
inherit (lib.options) mkOption mkPackageOption mkEnableOption;
|
||||||
|
inherit (lib.modules) mkIf mkMerge mkAfter mkOptionDefault;
|
||||||
|
inherit (lib.attrsets) mapAttrsToList;
|
||||||
|
inherit (lib.meta) getExe;
|
||||||
|
cfg = config.services.motion;
|
||||||
|
mkMotionValue = value:
|
||||||
|
if value == true
|
||||||
|
then "on"
|
||||||
|
else if value == false
|
||||||
|
then "off"
|
||||||
|
else toString value;
|
||||||
|
mkMotionSetting = key: value: "${key} ${mkMotionValue value}";
|
||||||
|
in {
|
||||||
|
options.services.motion = with lib.types; {
|
||||||
|
enable = mkEnableOption "motion";
|
||||||
|
package = mkPackageOption pkgs "motion" {};
|
||||||
|
dataDir = mkOption {
|
||||||
|
type = path;
|
||||||
|
default = "/var/lib/motion";
|
||||||
|
};
|
||||||
|
user = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "motion";
|
||||||
|
};
|
||||||
|
group = mkOption {
|
||||||
|
type = str;
|
||||||
|
default = "motion";
|
||||||
|
};
|
||||||
|
settings = mkOption {
|
||||||
|
type = attrsOf (oneOf [str int bool]);
|
||||||
|
description = "https://linux.die.net/man/1/motion";
|
||||||
|
};
|
||||||
|
extraArgs = mkOption {
|
||||||
|
type = listOf str;
|
||||||
|
default = [];
|
||||||
|
};
|
||||||
|
extraConfig = mkOption {
|
||||||
|
type = lines;
|
||||||
|
default = "";
|
||||||
|
};
|
||||||
|
configText = mkOption {
|
||||||
|
type = lines;
|
||||||
|
internal = true;
|
||||||
|
};
|
||||||
|
configFile = mkOption {
|
||||||
|
type = path;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config.services.motion = let
|
||||||
|
configFile = pkgs.writeText "motion.conf" cfg.configText;
|
||||||
|
in {
|
||||||
|
settings = mapOptionDefaults {
|
||||||
|
target_dir = cfg.dataDir;
|
||||||
|
};
|
||||||
|
configFile = mkOptionDefault "${configFile}";
|
||||||
|
configText = mkMerge (
|
||||||
|
(mapAttrsToList mkMotionSetting cfg.settings)
|
||||||
|
++ [(mkAfter cfg.extraConfig)]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
config.users = mkIf cfg.enable {
|
||||||
|
users.motion = {
|
||||||
|
uid = 916;
|
||||||
|
group = "motion";
|
||||||
|
home = cfg.dataDir;
|
||||||
|
extraGroups = ["video"];
|
||||||
|
};
|
||||||
|
groups.motion = {
|
||||||
|
gid = config.users.users.motion.uid;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config.systemd.services.motion = let
|
||||||
|
cliArgs =
|
||||||
|
[
|
||||||
|
(getExe cfg.package)
|
||||||
|
"-n"
|
||||||
|
"-c"
|
||||||
|
cfg.configFile
|
||||||
|
]
|
||||||
|
++ cfg.extraArgs;
|
||||||
|
in
|
||||||
|
mkIf cfg.enable {
|
||||||
|
wantedBy = ["multi-user.target"];
|
||||||
|
after = ["network.target"];
|
||||||
|
serviceConfig = {
|
||||||
|
Type = mkOptionDefault "exec";
|
||||||
|
Restart = mkOptionDefault "on-failure";
|
||||||
|
User = mkOptionDefault cfg.user;
|
||||||
|
Group = mkOptionDefault cfg.group;
|
||||||
|
ExecStart = [
|
||||||
|
(utils.escapeSystemdExecArgs cliArgs)
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,9 @@
|
||||||
in {
|
in {
|
||||||
config.exports.services.motion = {config, ...}: {
|
config.exports.services.motion = {config, ...}: {
|
||||||
displayName = mkAlmostOptionDefault "Motion";
|
displayName = mkAlmostOptionDefault "Motion";
|
||||||
|
nixos = {
|
||||||
|
serviceAttr = "motion";
|
||||||
|
};
|
||||||
defaults.port.listen = mkAlmostOptionDefault "lan";
|
defaults.port.listen = mkAlmostOptionDefault "lan";
|
||||||
ports = {
|
ports = {
|
||||||
default = {
|
default = {
|
||||||
|
|
@ -15,10 +18,10 @@ in {
|
||||||
status.enable = mkAlmostOptionDefault true;
|
status.enable = mkAlmostOptionDefault true;
|
||||||
};
|
};
|
||||||
stream = {
|
stream = {
|
||||||
port = mkAlmostOptionDefault 8081;
|
port = mkAlmostOptionDefault 41081;
|
||||||
protocol = "http";
|
protocol = "http";
|
||||||
displayName = mkAlmostOptionDefault "Stream";
|
displayName = mkAlmostOptionDefault "Stream";
|
||||||
status.enable = mkAlmostOptionDefault true;
|
#status.enable = mkAlmostOptionDefault true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
66
nixos/kitchencam.nix
Normal file
66
nixos/kitchencam.nix
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib.modules) mkIf mkDefault;
|
||||||
|
cfg = config.services.motion;
|
||||||
|
streamPort = 41081;
|
||||||
|
webPort = 8080;
|
||||||
|
in {
|
||||||
|
services.motion = {
|
||||||
|
enable = mkDefault true;
|
||||||
|
extraConfig = ''
|
||||||
|
videodevice /dev/kitchencam
|
||||||
|
v4l2_palette 8
|
||||||
|
width 640
|
||||||
|
height 480
|
||||||
|
framerate 5
|
||||||
|
|
||||||
|
text_left kitchen
|
||||||
|
text_right %Y-%m-%d\n%T-%q
|
||||||
|
emulate_motion off
|
||||||
|
threshold 1500
|
||||||
|
despeckle_filter EedDl
|
||||||
|
minimum_motion_frames 1
|
||||||
|
event_gap 60
|
||||||
|
pre_capture 3
|
||||||
|
post_capture 0
|
||||||
|
|
||||||
|
picture_output off
|
||||||
|
picture_filename %Y%m%d%H%M%S-%q
|
||||||
|
|
||||||
|
movie_output off
|
||||||
|
movie_max_time 60
|
||||||
|
movie_quality 45
|
||||||
|
movie_codec mkv
|
||||||
|
movie_filename %t-%v-%Y%m%d%H%M%S
|
||||||
|
|
||||||
|
webcontrol_port ${toString webPort}
|
||||||
|
webcontrol_localhost off
|
||||||
|
webcontrol_parms 0
|
||||||
|
stream_port ${toString streamPort}
|
||||||
|
stream_localhost off
|
||||||
|
ipv6_enabled on
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
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 {
|
||||||
|
allowedTCPPorts = [streamPort webPort];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -21,11 +21,6 @@ _: {
|
||||||
enable = true;
|
enable = true;
|
||||||
ports.public.enable = false;
|
ports.public.enable = false;
|
||||||
};
|
};
|
||||||
motion = {
|
|
||||||
id = "kitchen";
|
|
||||||
enable = true;
|
|
||||||
ports.stream.port = 41081;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
# XXX: currently unplugged :<
|
# XXX: currently unplugged :<
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,15 @@ _: {
|
||||||
modules = [
|
modules = [
|
||||||
./nixos.nix
|
./nixos.nix
|
||||||
];
|
];
|
||||||
|
exports = {
|
||||||
|
services = {
|
||||||
|
motion = {
|
||||||
|
id = "kitchen";
|
||||||
|
enable = true;
|
||||||
|
ports.stream.port = 41081;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
network.networks = {
|
network.networks = {
|
||||||
local = {
|
local = {
|
||||||
slaac.postfix = "40c3:23df:e82a:b214";
|
slaac.postfix = "40c3:23df:e82a:b214";
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ in {
|
||||||
nixos.sops
|
nixos.sops
|
||||||
nixos.base
|
nixos.base
|
||||||
nixos.barcodebuddy-scanner
|
nixos.barcodebuddy-scanner
|
||||||
|
nixos.kitchencam
|
||||||
./hardware-configuration.nix
|
./hardware-configuration.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue