1{ config, lib, pkgs, options }:
2
3let
4 cfg = config.services.prometheus.exporters.rtl_433;
5in
6{
7 port = 9550;
8
9 extraOpts = let
10 mkMatcherOptionType = field: description: with lib.types;
11 listOf (submodule {
12 options = {
13 name = lib.mkOption {
14 type = str;
15 description = "Name to match.";
16 };
17 "${field}" = lib.mkOption {
18 type = int;
19 inherit description;
20 };
21 location = lib.mkOption {
22 type = str;
23 description = "Location to match.";
24 };
25 };
26 });
27 in
28 {
29 rtl433Flags = lib.mkOption {
30 type = lib.types.str;
31 default = "-C si";
32 example = "-C si -R 19";
33 description = ''
34 Flags passed verbatim to rtl_433 binary.
35 Having <literal>-C si</literal> (the default) is recommended since only Celsius temperatures are parsed.
36 '';
37 };
38 channels = lib.mkOption {
39 type = mkMatcherOptionType "channel" "Channel to match.";
40 default = [];
41 example = [
42 { name = "Acurite"; channel = 6543; location = "Kitchen"; }
43 ];
44 description = ''
45 List of channel matchers to export.
46 '';
47 };
48 ids = lib.mkOption {
49 type = mkMatcherOptionType "id" "ID to match.";
50 default = [];
51 example = [
52 { name = "Nexus"; id = 1; location = "Bedroom"; }
53 ];
54 description = ''
55 List of ID matchers to export.
56 '';
57 };
58 };
59
60 serviceOpts = {
61 serviceConfig = {
62 # rtl-sdr udev rules make supported USB devices +rw by plugdev.
63 SupplementaryGroups = "plugdev";
64 ExecStart = let
65 matchers = (map (m:
66 "--channel_matcher '${m.name},${toString m.channel},${m.location}'"
67 ) cfg.channels) ++ (map (m:
68 "--id_matcher '${m.name},${toString m.id},${m.location}'"
69 ) cfg.ids); in ''
70 ${pkgs.prometheus-rtl_433-exporter}/bin/rtl_433_prometheus \
71 -listen ${cfg.listenAddress}:${toString cfg.port} \
72 -subprocess "${pkgs.rtl_433}/bin/rtl_433 -F json ${cfg.rtl433Flags}" \
73 ${lib.concatStringsSep " \\\n " matchers} \
74 ${lib.concatStringsSep " \\\n " cfg.extraFlags}
75 '';
76 };
77 };
78}