at 24.11-pre 7.0 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8with lib; 9 10let 11 cfg = config.services.mqtt2influxdb; 12 filterNull = filterAttrsRecursive (n: v: v != null); 13 configFile = (pkgs.formats.yaml {}).generate "mqtt2influxdb.config.yaml" ( 14 filterNull { 15 inherit (cfg) mqtt influxdb; 16 points = map filterNull cfg.points; 17 } 18 ); 19 20 pointType = types.submodule { 21 options = { 22 measurement = mkOption { 23 type = types.str; 24 description = "Name of the measurement"; 25 }; 26 topic = mkOption { 27 type = types.str; 28 description = "MQTT topic to subscribe to."; 29 }; 30 fields = mkOption { 31 type = types.submodule { 32 options = { 33 value = mkOption { 34 type = types.str; 35 default = "$.payload"; 36 description = "Value to be picked up"; 37 }; 38 type = mkOption { 39 type = with types; nullOr str; 40 default = null; 41 description = "Type to be picked up"; 42 }; 43 }; 44 }; 45 description = "Field selector."; 46 }; 47 tags = mkOption { 48 type = with types; attrsOf str; 49 default = {}; 50 description = "Tags applied"; 51 }; 52 }; 53 }; 54 55 defaultPoints = [ 56 { 57 measurement = "temperature"; 58 topic = "node/+/thermometer/+/temperature"; 59 fields.value = "$.payload"; 60 tags = { 61 id = "$.topic[1]"; 62 channel = "$.topic[3]"; 63 }; 64 } 65 { 66 measurement = "relative-humidity"; 67 topic = "node/+/hygrometer/+/relative-humidity"; 68 fields.value = "$.payload"; 69 tags = { 70 id = "$.topic[1]"; 71 channel = "$.topic[3]"; 72 }; 73 } 74 { 75 measurement = "illuminance"; 76 topic = "node/+/lux-meter/0:0/illuminance"; 77 fields.value = "$.payload"; 78 tags = { 79 id = "$.topic[1]"; 80 }; 81 } 82 { 83 measurement = "pressure"; 84 topic = "node/+/barometer/0:0/pressure"; 85 fields.value = "$.payload"; 86 tags = { 87 id = "$.topic[1]"; 88 }; 89 } 90 { 91 measurement = "co2"; 92 topic = "node/+/co2-meter/-/concentration"; 93 fields.value = "$.payload"; 94 tags = { 95 id = "$.topic[1]"; 96 }; 97 } 98 { 99 measurement = "voltage"; 100 topic = "node/+/battery/+/voltage"; 101 fields.value = "$.payload"; 102 tags = { 103 id = "$.topic[1]"; 104 }; 105 } 106 { 107 measurement = "button"; 108 topic = "node/+/push-button/+/event-count"; 109 fields.value = "$.payload"; 110 tags = { 111 id = "$.topic[1]"; 112 channel = "$.topic[3]"; 113 }; 114 } 115 { 116 measurement = "tvoc"; 117 topic = "node/+/voc-lp-sensor/0:0/tvoc"; 118 fields.value = "$.payload"; 119 tags = { 120 id = "$.topic[1]"; 121 }; 122 } 123 ]; 124in { 125 options = { 126 services.mqtt2influxdb = { 127 enable = mkEnableOption "BigClown MQTT to InfluxDB bridge."; 128 environmentFiles = mkOption { 129 type = types.listOf types.path; 130 default = []; 131 example = [ "/run/keys/mqtt2influxdb.env" ]; 132 description = '' 133 File to load as environment file. Environment variables from this file 134 will be interpolated into the config file using envsubst with this 135 syntax: `$ENVIRONMENT` or `''${VARIABLE}`. 136 This is useful to avoid putting secrets into the nix store. 137 ''; 138 }; 139 mqtt = { 140 host = mkOption { 141 type = types.str; 142 default = "127.0.0.1"; 143 description = "Host where MQTT server is running."; 144 }; 145 port = mkOption { 146 type = types.port; 147 default = 1883; 148 description = "MQTT server port."; 149 }; 150 username = mkOption { 151 type = with types; nullOr str; 152 default = null; 153 description = "Username used to connect to the MQTT server."; 154 }; 155 password = mkOption { 156 type = with types; nullOr str; 157 default = null; 158 description = '' 159 MQTT password. 160 161 It is highly suggested to use here replacement through 162 environmentFiles as otherwise the password is put world readable to 163 the store. 164 ''; 165 }; 166 cafile = mkOption { 167 type = with types; nullOr path; 168 default = null; 169 description = "Certification Authority file for MQTT"; 170 }; 171 certfile = mkOption { 172 type = with types; nullOr path; 173 default = null; 174 description = "Certificate file for MQTT"; 175 }; 176 keyfile = mkOption { 177 type = with types; nullOr path; 178 default = null; 179 description = "Key file for MQTT"; 180 }; 181 }; 182 influxdb = { 183 host = mkOption { 184 type = types.str; 185 default = "127.0.0.1"; 186 description = "Host where InfluxDB server is running."; 187 }; 188 port = mkOption { 189 type = types.port; 190 default = 8086; 191 description = "InfluxDB server port"; 192 }; 193 database = mkOption { 194 type = types.str; 195 description = "Name of the InfluxDB database."; 196 }; 197 username = mkOption { 198 type = with types; nullOr str; 199 default = null; 200 description = "Username for InfluxDB login."; 201 }; 202 password = mkOption { 203 type = with types; nullOr str; 204 default = null; 205 description = '' 206 Password for InfluxDB login. 207 208 It is highly suggested to use here replacement through 209 environmentFiles as otherwise the password is put world readable to 210 the store. 211 ''; 212 }; 213 ssl = mkOption { 214 type = types.bool; 215 default = false; 216 description = "Use SSL to connect to the InfluxDB server."; 217 }; 218 verify_ssl = mkOption { 219 type = types.bool; 220 default = true; 221 description = "Verify SSL certificate when connecting to the InfluxDB server."; 222 }; 223 }; 224 points = mkOption { 225 type = types.listOf pointType; 226 default = defaultPoints; 227 description = "Points to bridge from MQTT to InfluxDB."; 228 }; 229 }; 230 }; 231 232 config = mkIf cfg.enable { 233 systemd.services.bigclown-mqtt2influxdb = let 234 envConfig = cfg.environmentFiles != []; 235 finalConfig = if envConfig 236 then "$RUNTIME_DIRECTORY/mqtt2influxdb.config.yaml" 237 else configFile; 238 in { 239 description = "BigClown MQTT to InfluxDB bridge"; 240 wantedBy = ["multi-user.target"]; 241 wants = mkIf config.services.mosquitto.enable ["mosquitto.service"]; 242 preStart = '' 243 umask 077 244 ${pkgs.envsubst}/bin/envsubst -i "${configFile}" -o "${finalConfig}" 245 ''; 246 serviceConfig = { 247 EnvironmentFile = cfg.environmentFiles; 248 ExecStart = "${cfg.package}/bin/mqtt2influxdb -dc ${finalConfig}"; 249 RuntimeDirectory = "mqtt2influxdb"; 250 }; 251 }; 252 }; 253}