at 24.11-pre 3.8 kB view raw
1{ config, lib, pkgs, utils, ... }: 2 3with lib; 4 5let 6 7 uid = config.ids.uids.gpsd; 8 gid = config.ids.gids.gpsd; 9 cfg = config.services.gpsd; 10 11in { 12 13 ###### interface 14 15 imports = [ 16 (lib.mkRemovedOptionModule [ "services" "gpsd" "device" ] 17 "Use `services.gpsd.devices` instead.") 18 ]; 19 20 options = { 21 22 services.gpsd = { 23 24 enable = mkOption { 25 type = types.bool; 26 default = false; 27 description = '' 28 Whether to enable `gpsd`, a GPS service daemon. 29 ''; 30 }; 31 32 devices = mkOption { 33 type = types.listOf types.str; 34 default = [ "/dev/ttyUSB0" ]; 35 description = '' 36 List of devices that `gpsd` should subscribe to. 37 38 A device may be a local serial device for GPS input, or a 39 URL of the form: 40 `[{dgpsip|ntrip}://][user:passwd@]host[:port][/stream]` in 41 which case it specifies an input source for DGPS or ntrip 42 data. 43 ''; 44 }; 45 46 readonly = mkOption { 47 type = types.bool; 48 default = true; 49 description = '' 50 Whether to enable the broken-device-safety, otherwise 51 known as read-only mode. Some popular bluetooth and USB 52 receivers lock up or become totally inaccessible when 53 probed or reconfigured. This switch prevents gpsd from 54 writing to a receiver. This means that gpsd cannot 55 configure the receiver for optimal performance, but it 56 also means that gpsd cannot break the receiver. A better 57 solution would be for Bluetooth to not be so fragile. A 58 platform independent method to identify 59 serial-over-Bluetooth devices would also be nice. 60 ''; 61 }; 62 63 nowait = mkOption { 64 type = types.bool; 65 default = false; 66 description = '' 67 don't wait for client connects to poll GPS 68 ''; 69 }; 70 71 port = mkOption { 72 type = types.port; 73 default = 2947; 74 description = '' 75 The port where to listen for TCP connections. 76 ''; 77 }; 78 79 debugLevel = mkOption { 80 type = types.int; 81 default = 0; 82 description = '' 83 The debugging level. 84 ''; 85 }; 86 87 listenany = mkOption { 88 type = types.bool; 89 default = false; 90 description = '' 91 Listen on all addresses rather than just loopback. 92 ''; 93 }; 94 95 extraArgs = mkOption { 96 type = types.listOf types.str; 97 default = [ ]; 98 example = [ "-r" "-s" "19200" ]; 99 description = '' 100 A list of extra command line arguments to pass to gpsd. 101 Check gpsd(8) mangpage for possible arguments. 102 ''; 103 }; 104 105 }; 106 107 }; 108 109 ###### implementation 110 111 config = mkIf cfg.enable { 112 113 users.users.gpsd = { 114 inherit uid; 115 group = "gpsd"; 116 description = "gpsd daemon user"; 117 home = "/var/empty"; 118 }; 119 120 users.groups.gpsd = { inherit gid; }; 121 122 systemd.services.gpsd = { 123 description = "GPSD daemon"; 124 wantedBy = [ "multi-user.target" ]; 125 after = [ "network.target" ]; 126 serviceConfig = { 127 Type = "forking"; 128 ExecStart = let 129 devices = utils.escapeSystemdExecArgs cfg.devices; 130 extraArgs = utils.escapeSystemdExecArgs cfg.extraArgs; 131 in '' 132 ${pkgs.gpsd}/sbin/gpsd -D "${toString cfg.debugLevel}" \ 133 -S "${toString cfg.port}" \ 134 ${optionalString cfg.readonly "-b"} \ 135 ${optionalString cfg.nowait "-n"} \ 136 ${optionalString cfg.listenany "-G"} \ 137 ${extraArgs} \ 138 ${devices} 139 ''; 140 }; 141 }; 142 143 }; 144 145}