1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7
8with lib;
9
10let
11 cfg = config.services.bcg;
12 configFile = (pkgs.formats.yaml {}).generate "bcg.conf.yaml" (
13 filterAttrsRecursive (n: v: v != null) {
14 inherit (cfg) device name mqtt;
15 retain_node_messages = cfg.retainNodeMessages;
16 qos_node_messages = cfg.qosNodeMessages;
17 base_topic_prefix = cfg.baseTopicPrefix;
18 automatic_remove_kit_from_names = cfg.automaticRemoveKitFromNames;
19 automatic_rename_kit_nodes = cfg.automaticRenameKitNodes;
20 automatic_rename_generic_nodes = cfg.automaticRenameGenericNodes;
21 automatic_rename_nodes = cfg.automaticRenameNodes;
22 }
23 );
24in
25{
26 options = {
27 services.bcg = {
28 enable = mkEnableOption (mdDoc "BigClown gateway");
29 package = mkOption {
30 default = pkgs.python3Packages.bcg;
31 defaultText = literalExpression "pkgs.python3Packages.bcg";
32 description = mdDoc "Which bcg derivation to use.";
33 type = types.package;
34 };
35 environmentFiles = mkOption {
36 type = types.listOf types.path;
37 default = [];
38 example = [ "/run/keys/bcg.env" ];
39 description = mdDoc ''
40 File to load as environment file. Environment variables from this file
41 will be interpolated into the config file using envsubst with this
42 syntax: `$ENVIRONMENT` or `''${VARIABLE}`.
43 This is useful to avoid putting secrets into the nix store.
44 '';
45 };
46 verbose = mkOption {
47 type = types.enum ["CRITICAL" "ERROR" "WARNING" "INFO" "DEBUG"];
48 default = "WARNING";
49 description = mdDoc "Verbosity level.";
50 };
51 device = mkOption {
52 type = types.str;
53 description = mdDoc "Device name to configure gateway to use.";
54 };
55 name = mkOption {
56 type = with types; nullOr str;
57 default = null;
58 description = mdDoc ''
59 Name for the device.
60
61 Supported variables:
62 * `{ip}` IP address
63 * `{id}` The ID of the connected usb-dongle or core-module
64
65 `null` can be used for automatic detection from gateway firmware.
66 '';
67 };
68 mqtt = {
69 host = mkOption {
70 type = types.str;
71 default = "127.0.0.1";
72 description = mdDoc "Host where MQTT server is running.";
73 };
74 port = mkOption {
75 type = types.port;
76 default = 1883;
77 description = mdDoc "Port of MQTT server.";
78 };
79 username = mkOption {
80 type = with types; nullOr str;
81 default = null;
82 description = mdDoc "MQTT server access username.";
83 };
84 password = mkOption {
85 type = with types; nullOr str;
86 default = null;
87 description = mdDoc "MQTT server access password.";
88 };
89 cafile = mkOption {
90 type = with types; nullOr str;
91 default = null;
92 description = mdDoc "Certificate Authority file for MQTT server access.";
93 };
94 certfile = mkOption {
95 type = with types; nullOr str;
96 default = null;
97 description = mdDoc "Certificate file for MQTT server access.";
98 };
99 keyfile = mkOption {
100 type = with types; nullOr str;
101 default = null;
102 description = mdDoc "Key file for MQTT server access.";
103 };
104 };
105 retainNodeMessages = mkOption {
106 type = types.bool;
107 default = false;
108 description = mdDoc "Specify that node messages should be retaied in MQTT broker.";
109 };
110 qosNodeMessages = mkOption {
111 type = types.int;
112 default = 1;
113 description = mdDoc "Set the guarantee of MQTT message delivery.";
114 };
115 baseTopicPrefix = mkOption {
116 type = types.str;
117 default = "";
118 description = mdDoc "Topic prefix added to all MQTT messages.";
119 };
120 automaticRemoveKitFromNames = mkOption {
121 type = types.bool;
122 default = true;
123 description = mdDoc "Automatically remove kits.";
124 };
125 automaticRenameKitNodes = mkOption {
126 type = types.bool;
127 default = true;
128 description = mdDoc "Automatically rename kit's nodes.";
129 };
130 automaticRenameGenericNodes = mkOption {
131 type = types.bool;
132 default = true;
133 description = mdDoc "Automatically rename generic nodes.";
134 };
135 automaticRenameNodes = mkOption {
136 type = types.bool;
137 default = true;
138 description = mdDoc "Automatically rename all nodes.";
139 };
140 rename = mkOption {
141 type = with types; attrsOf str;
142 default = {};
143 description = mdDoc "Rename nodes to different name.";
144 };
145 };
146 };
147
148 config = mkIf cfg.enable {
149 environment.systemPackages = with pkgs; [
150 python3Packages.bcg
151 python3Packages.bch
152 ];
153
154 systemd.services.bcg = let
155 envConfig = cfg.environmentFiles != [];
156 finalConfig = if envConfig
157 then "$RUNTIME_DIRECTORY/bcg.config.yaml"
158 else configFile;
159 in {
160 description = "BigClown Gateway";
161 wantedBy = [ "multi-user.target" ];
162 wants = mkIf config.services.mosquitto.enable [ "mosquitto.service" ];
163 after = [ "network-online.target" ];
164 preStart = ''
165 umask 077
166 ${pkgs.envsubst}/bin/envsubst -i "${configFile}" -o "${finalConfig}"
167 '';
168 serviceConfig = {
169 EnvironmentFile = cfg.environmentFiles;
170 ExecStart="${cfg.package}/bin/bcg -c ${finalConfig} -v ${cfg.verbose}";
171 RuntimeDirectory = "bcg";
172 };
173 };
174 };
175}