1{ pkgs, lib, config, ... }: 2 3with lib; 4let 5 cfg = config.services.gammu-smsd; 6 7 configFile = pkgs.writeText "gammu-smsd.conf" '' 8 [gammu] 9 Device = ${cfg.device.path} 10 Connection = ${cfg.device.connection} 11 SynchronizeTime = ${if cfg.device.synchronizeTime then "yes" else "no"} 12 LogFormat = ${cfg.log.format} 13 ${if (cfg.device.pin != null) then "PIN = ${cfg.device.pin}" else ""} 14 ${cfg.extraConfig.gammu} 15 16 17 [smsd] 18 LogFile = ${cfg.log.file} 19 Service = ${cfg.backend.service} 20 21 ${optionalString (cfg.backend.service == "files") '' 22 InboxPath = ${cfg.backend.files.inboxPath} 23 OutboxPath = ${cfg.backend.files.outboxPath} 24 SentSMSPath = ${cfg.backend.files.sentSMSPath} 25 ErrorSMSPath = ${cfg.backend.files.errorSMSPath} 26 ''} 27 28 ${optionalString (cfg.backend.service == "sql" && cfg.backend.sql.driver == "sqlite") '' 29 Driver = ${cfg.backend.sql.driver} 30 DBDir = ${cfg.backend.sql.database} 31 ''} 32 33 ${optionalString (cfg.backend.service == "sql" && cfg.backend.sql.driver == "native_pgsql") ( 34 with cfg.backend; '' 35 Driver = ${sql.driver} 36 ${if (sql.database!= null) then "Database = ${sql.database}" else ""} 37 ${if (sql.host != null) then "Host = ${sql.host}" else ""} 38 ${if (sql.user != null) then "User = ${sql.user}" else ""} 39 ${if (sql.password != null) then "Password = ${sql.password}" else ""} 40 '')} 41 42 ${cfg.extraConfig.smsd} 43 ''; 44 45 initDBDir = "share/doc/gammu/examples/sql"; 46 47 gammuPackage = with cfg.backend; (pkgs.gammu.override { 48 dbiSupport = (service == "sql" && sql.driver == "sqlite"); 49 postgresSupport = (service == "sql" && sql.driver == "native_pgsql"); 50 }); 51 52in { 53 options = { 54 services.gammu-smsd = { 55 56 enable = mkEnableOption "gammu-smsd daemon"; 57 58 user = mkOption { 59 type = types.str; 60 default = "smsd"; 61 description = "User that has access to the device"; 62 }; 63 64 device = { 65 path = mkOption { 66 type = types.path; 67 description = "Device node or address of the phone"; 68 example = "/dev/ttyUSB2"; 69 }; 70 71 group = mkOption { 72 type = types.str; 73 default = "root"; 74 description = "Owner group of the device"; 75 example = "dialout"; 76 }; 77 78 connection = mkOption { 79 type = types.str; 80 default = "at"; 81 description = "Protocol which will be used to talk to the phone"; 82 }; 83 84 synchronizeTime = mkOption { 85 type = types.bool; 86 default = true; 87 description = "Whether to set time from computer to the phone during starting connection"; 88 }; 89 90 pin = mkOption { 91 type = types.nullOr types.str; 92 default = null; 93 description = "PIN code for the simcard"; 94 }; 95 }; 96 97 98 log = { 99 file = mkOption { 100 type = types.str; 101 default = "syslog"; 102 description = "Path to file where information about communication will be stored"; 103 }; 104 105 format = mkOption { 106 type = types.enum [ "nothing" "text" "textall" "textalldate" "errors" "errorsdate" "binary" ]; 107 default = "errors"; 108 description = "Determines what will be logged to the LogFile"; 109 }; 110 }; 111 112 113 extraConfig = { 114 gammu = mkOption { 115 type = types.lines; 116 default = ""; 117 description = "Extra config lines to be added into [gammu] section"; 118 }; 119 120 121 smsd = mkOption { 122 type = types.lines; 123 default = ""; 124 description = "Extra config lines to be added into [smsd] section"; 125 }; 126 }; 127 128 129 backend = { 130 service = mkOption { 131 type = types.enum [ "null" "files" "sql" ]; 132 default = "null"; 133 description = "Service to use to store sms data."; 134 }; 135 136 files = { 137 inboxPath = mkOption { 138 type = types.path; 139 default = "/var/spool/sms/inbox/"; 140 description = "Where the received SMSes are stored"; 141 }; 142 143 outboxPath = mkOption { 144 type = types.path; 145 default = "/var/spool/sms/outbox/"; 146 description = "Where SMSes to be sent should be placed"; 147 }; 148 149 sentSMSPath = mkOption { 150 type = types.path; 151 default = "/var/spool/sms/sent/"; 152 description = "Where the transmitted SMSes are placed"; 153 }; 154 155 errorSMSPath = mkOption { 156 type = types.path; 157 default = "/var/spool/sms/error/"; 158 description = "Where SMSes with error in transmission is placed"; 159 }; 160 }; 161 162 sql = { 163 driver = mkOption { 164 type = types.enum [ "native_mysql" "native_pgsql" "odbc" "dbi" ]; 165 description = "DB driver to use"; 166 }; 167 168 sqlDialect = mkOption { 169 type = types.nullOr types.str; 170 default = null; 171 description = "SQL dialect to use (odbc driver only)"; 172 }; 173 174 database = mkOption { 175 type = types.str; 176 default = null; 177 description = "Database name to store sms data"; 178 }; 179 180 host = mkOption { 181 type = types.str; 182 default = "localhost"; 183 description = "Database server address"; 184 }; 185 186 user = mkOption { 187 type = types.nullOr types.str; 188 default = null; 189 description = "User name used for connection to the database"; 190 }; 191 192 password = mkOption { 193 type = types.nullOr types.str; 194 default = null; 195 description = "User password used for connetion to the database"; 196 }; 197 }; 198 }; 199 }; 200 }; 201 202 config = mkIf cfg.enable { 203 users.extraUsers.${cfg.user} = { 204 description = "gammu-smsd user"; 205 uid = config.ids.uids.gammu-smsd; 206 extraGroups = [ "${cfg.device.group}" ]; 207 }; 208 209 environment.systemPackages = with cfg.backend; [ gammuPackage ] 210 ++ optionals (service == "sql" && sql.driver == "sqlite") [ pkgs.sqlite ]; 211 212 systemd.services.gammu-smsd = { 213 description = "gammu-smsd daemon"; 214 215 wantedBy = [ "multi-user.target" ]; 216 217 wants = with cfg.backend; [ ] 218 ++ optionals (service == "sql" && sql.driver == "native_pgsql") [ "postgresql.service" ]; 219 220 preStart = with cfg.backend; 221 222 optionalString (service == "files") (with files; '' 223 mkdir -m 755 -p ${inboxPath} ${outboxPath} ${sentSMSPath} ${errorSMSPath} 224 chown ${cfg.user} -R ${inboxPath} 225 chown ${cfg.user} -R ${outboxPath} 226 chown ${cfg.user} -R ${sentSMSPath} 227 chown ${cfg.user} -R ${errorSMSPath} 228 '') 229 + optionalString (service == "sql" && sql.driver == "sqlite") '' 230 cat "${gammuPackage}/${initDBDir}/sqlite.sql" \ 231 | ${pkgs.sqlite}/bin/sqlite3 ${sql.database} 232 '' 233 + (let execPsql = extraArgs: concatStringsSep " " [ 234 (optionalString (sql.password != null) "PGPASSWORD=${sql.password}") 235 "${config.services.postgresql.package}/bin/psql" 236 (optionalString (sql.host != null) "-h ${sql.host}") 237 (optionalString (sql.user != null) "-U ${sql.user}") 238 "$extraArgs" 239 "${sql.database}" 240 ]; in optionalString (service == "sql" && sql.driver == "native_pgsql") '' 241 echo '\i '"${gammuPackage}/${initDBDir}/pgsql.sql" | ${execPsql ""} 242 ''); 243 244 serviceConfig = { 245 User = "${cfg.user}"; 246 Group = "${cfg.device.group}"; 247 PermissionsStartOnly = true; 248 ExecStart = "${gammuPackage}/bin/gammu-smsd -c ${configFile}"; 249 }; 250 251 }; 252 }; 253}