first
This commit is contained in:
commit
d8f9225c34
25 changed files with 2368 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/result*
|
161
feeder.nix
Normal file
161
feeder.nix
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
{ mainConfig, feederConfig, pkgs, self, lib }: {
|
||||||
|
|
||||||
|
config = {
|
||||||
|
users.groups.${feederConfig.name} = { };
|
||||||
|
users.users.${feederConfig.name} = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "${feederConfig.name}";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."${feederConfig.name}-mlat" =
|
||||||
|
let
|
||||||
|
uuidFile = pkgs.writeTextFile {
|
||||||
|
name = "${feederConfig.name}-uuid";
|
||||||
|
text = "${feederConfig.uuid}";
|
||||||
|
};
|
||||||
|
options = [
|
||||||
|
"--input-type"
|
||||||
|
feederConfig.mlat.input.type
|
||||||
|
"--no-udp"
|
||||||
|
"--input-connect"
|
||||||
|
"${feederConfig.mlat.input.host}:${toString feederConfig.mlat.input.port}"
|
||||||
|
"--server"
|
||||||
|
feederConfig.mlat.server
|
||||||
|
"--user"
|
||||||
|
feederConfig.username
|
||||||
|
"--lat"
|
||||||
|
mainConfig.latitude
|
||||||
|
"--lon"
|
||||||
|
mainConfig.longitude
|
||||||
|
"--alt"
|
||||||
|
(toString mainConfig.altitude)
|
||||||
|
"--uuid-file"
|
||||||
|
"${uuidFile}"
|
||||||
|
] ++ (
|
||||||
|
if feederConfig.mlat.privacy
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--privacy"
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
map (result: "--result ${result}") feederConfig.mlat.results
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
enable = feederConfig.mlat.enable;
|
||||||
|
description = "${feederConfig.name} MLAT client.";
|
||||||
|
wants = [ "network.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
unitConfig = {
|
||||||
|
Documentation = "https://github.com/makrsmark/mlat-client/";
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = "${feederConfig.name}";
|
||||||
|
RuntimeDirectory = "${feederConfig.name}-mlat";
|
||||||
|
RuntimeDirectoryMode = "0755";
|
||||||
|
ExecStart = "${self.packages.${pkgs.system}.adsbfi-mlat-client}/bin/mlat-client ${lib.concatStringsSep " " options}";
|
||||||
|
SyslogIdentifier = "${feederConfig.name}-mlat";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 30;
|
||||||
|
Nice = -1;
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."${feederConfig.name}-feed" =
|
||||||
|
let
|
||||||
|
uuidFile = pkgs.writeTextFile {
|
||||||
|
name = "${feederConfig.name}-uuid";
|
||||||
|
text = "${feederConfig.uuid}";
|
||||||
|
};
|
||||||
|
connectors = map
|
||||||
|
(
|
||||||
|
connector: "--net-connector ${connector}"
|
||||||
|
)
|
||||||
|
(
|
||||||
|
map
|
||||||
|
(
|
||||||
|
connector: (
|
||||||
|
lib.concatStringsSep "," (
|
||||||
|
[
|
||||||
|
connector.primary.host
|
||||||
|
(toString connector.primary.port)
|
||||||
|
connector.protocol
|
||||||
|
] ++ (
|
||||||
|
if connector.silentFail
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"silent_fail"
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
if connector.secondary != null
|
||||||
|
then
|
||||||
|
[
|
||||||
|
connector.secondary.host
|
||||||
|
(toString connector.secondary.port)
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
feederConfig.feed.connectors
|
||||||
|
);
|
||||||
|
options = [
|
||||||
|
"--quiet"
|
||||||
|
"--net"
|
||||||
|
"--net-only"
|
||||||
|
"--write-json"
|
||||||
|
"%t/${feederConfig.name}-feed"
|
||||||
|
"--net-beast-reduce-interval 0.5"
|
||||||
|
"--net-heartbeat 60"
|
||||||
|
"--net-ro-size 1280"
|
||||||
|
"--net-ro-interval 0.2"
|
||||||
|
"--net-ro-port 0"
|
||||||
|
"--net-sbs-port 0"
|
||||||
|
"--net-bi-port ${toString feederConfig.feed.beastInputPort}"
|
||||||
|
"--net-bo-port 0"
|
||||||
|
"--net-ri-port 0"
|
||||||
|
"--write-json-every 1"
|
||||||
|
"--lat"
|
||||||
|
mainConfig.latitude
|
||||||
|
"--lon"
|
||||||
|
mainConfig.longitude
|
||||||
|
"--max-range 450"
|
||||||
|
"--json-location-accuracy 2"
|
||||||
|
"--range-outline-hours 24"
|
||||||
|
"--uuid-file"
|
||||||
|
"${uuidFile}"
|
||||||
|
] ++ connectors;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
enable = feederConfig.feed.enable;
|
||||||
|
description = "${feederConfig.name} feeder.";
|
||||||
|
wants = [ "network.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
unitConfig = {
|
||||||
|
Documentation = "https://github.com/widehopf/readsb/";
|
||||||
|
StartLimitIntervalSec = 1;
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = "${feederConfig.name}";
|
||||||
|
RuntimeDirectory = "${feederConfig.name}-feed";
|
||||||
|
RuntimeDirectoryMode = "0755";
|
||||||
|
ExecStart = "${self.packages.${pkgs.system}.adsbfi-readsb}/bin/readsb ${lib.concatStringsSep " " options}";
|
||||||
|
SyslogIdentifier = "${feederConfig.name}-feed";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 30;
|
||||||
|
StartLimitBurst = 100;
|
||||||
|
Nice = -1;
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
60
flake.lock
Normal file
60
flake.lock
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-utils": {
|
||||||
|
"inputs": {
|
||||||
|
"systems": "systems"
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1694529238,
|
||||||
|
"narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "numtide",
|
||||||
|
"repo": "flake-utils",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1697226376,
|
||||||
|
"narHash": "sha256-cumLLb1QOUtWieUnLGqo+ylNt3+fU8Lcv5Zl+tYbRUE=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "898cb2064b6e98b8c5499f37e81adbdf2925f7c5",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"id": "nixpkgs",
|
||||||
|
"ref": "nixos-23.05",
|
||||||
|
"type": "indirect"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-utils": "flake-utils",
|
||||||
|
"nixpkgs": "nixpkgs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
17
flake.nix
Normal file
17
flake.nix
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
description = "piaware";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs = {
|
||||||
|
url = "nixpkgs/nixos-23.05";
|
||||||
|
};
|
||||||
|
flake-utils = {
|
||||||
|
url = "github:numtide/flake-utils";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = { self, nixpkgs, flake-utils }: {
|
||||||
|
packages = (import ./packages { inherit self flake-utils nixpkgs; }).packages;
|
||||||
|
nixosModules = (import ./modules { inherit self; }).nixosModules;
|
||||||
|
};
|
||||||
|
}
|
823
modules/config/default.nix
Normal file
823
modules/config/default.nix
Normal file
|
@ -0,0 +1,823 @@
|
||||||
|
{ self, cfg, pkgs, lib, ... }:
|
||||||
|
let
|
||||||
|
createMlatService =
|
||||||
|
(name: feedConfig:
|
||||||
|
let
|
||||||
|
uuidFile = pkgs.writeTextFile {
|
||||||
|
name = "${name}-uuid";
|
||||||
|
text = "${feedConfig.uuid}";
|
||||||
|
};
|
||||||
|
options = [
|
||||||
|
"--input-type"
|
||||||
|
feedConfig.mlat.input.type
|
||||||
|
"--no-udp"
|
||||||
|
"--input-connect"
|
||||||
|
"${feedConfig.mlat.input.host}:${toString feedConfig.mlat.input.port}"
|
||||||
|
"--server"
|
||||||
|
feedConfig.mlat.server
|
||||||
|
"--user"
|
||||||
|
feedConfig.username
|
||||||
|
"--lat"
|
||||||
|
cfg.latitude
|
||||||
|
"--lon"
|
||||||
|
cfg.longitude
|
||||||
|
"--alt"
|
||||||
|
(toString cfg.altitude)
|
||||||
|
"--uuid-file"
|
||||||
|
"${uuidFile}"
|
||||||
|
] ++ (
|
||||||
|
if feedConfig.mlat.privacy
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--privacy"
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
map (result: "--result ${result}") feedConfig.mlat.results
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
enable = feedConfig.mlat.enable;
|
||||||
|
description = "${name} MLAT client.";
|
||||||
|
wants = [ "network.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
unitConfig = {
|
||||||
|
Documentation = "https://github.com/makrsmark/mlat-client/";
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = "${name}";
|
||||||
|
RuntimeDirectory = "${name}-mlat";
|
||||||
|
RuntimeDirectoryMode = "0755";
|
||||||
|
ExecStart = "${self.packages.${pkgs.system}.adsbfi-mlat-client}/bin/mlat-client ${lib.concatStringsSep " " options}";
|
||||||
|
SyslogIdentifier = "${name}-mlat";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 30;
|
||||||
|
Nice = -1;
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
}
|
||||||
|
|
||||||
|
);
|
||||||
|
createFeedService = (name: feedConfig:
|
||||||
|
let
|
||||||
|
uuidFile = pkgs.writeTextFile {
|
||||||
|
name = "${name}-uuid";
|
||||||
|
text = "${feedConfig.uuid}";
|
||||||
|
};
|
||||||
|
connectors = map
|
||||||
|
(
|
||||||
|
connector: "--net-connector ${connector}"
|
||||||
|
)
|
||||||
|
(
|
||||||
|
map
|
||||||
|
(
|
||||||
|
connector: (
|
||||||
|
lib.concatStringsSep "," (
|
||||||
|
[
|
||||||
|
connector.primary.host
|
||||||
|
(toString connector.primary.port)
|
||||||
|
connector.protocol
|
||||||
|
] ++ (
|
||||||
|
if connector.silentFail
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"silent_fail"
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
if connector.secondary != null
|
||||||
|
then
|
||||||
|
[
|
||||||
|
connector.secondary.host
|
||||||
|
(toString connector.secondary.port)
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
feedConfig.feed.connectors
|
||||||
|
);
|
||||||
|
options = [
|
||||||
|
"--quiet"
|
||||||
|
"--net"
|
||||||
|
"--net-only"
|
||||||
|
"--write-json"
|
||||||
|
"%t/${name}-feed"
|
||||||
|
"--net-beast-reduce-interval 0.5"
|
||||||
|
"--net-heartbeat 60"
|
||||||
|
"--net-ro-size 1280"
|
||||||
|
"--net-ro-interval 0.2"
|
||||||
|
"--net-ro-port 0"
|
||||||
|
"--net-sbs-port 0"
|
||||||
|
"--net-bi-port ${toString feedConfig.feed.beastInputPort}"
|
||||||
|
"--net-bo-port 0"
|
||||||
|
"--net-ri-port 0"
|
||||||
|
"--write-json-every 1"
|
||||||
|
"--lat"
|
||||||
|
cfg.latitude
|
||||||
|
"--lon"
|
||||||
|
cfg.longitude
|
||||||
|
"--max-range 450"
|
||||||
|
"--json-location-accuracy 2"
|
||||||
|
"--range-outline-hours 24"
|
||||||
|
"--uuid-file"
|
||||||
|
"${uuidFile}"
|
||||||
|
] ++ connectors;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
enable = feedConfig.feed.enable;
|
||||||
|
description = "ADSB.fi feeder.";
|
||||||
|
wants = [ "network.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
unitConfig = {
|
||||||
|
Documentation = "https://github.com/widehopf/readsb/";
|
||||||
|
StartLimitIntervalSec = 1;
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = "${name}";
|
||||||
|
RuntimeDirectory = "${name}-feed";
|
||||||
|
RuntimeDirectoryMode = "0755";
|
||||||
|
ExecStart = "${self.packages.${pkgs.system}.adsbfi-readsb}/bin/readsb ${lib.concatStringsSep " " options}";
|
||||||
|
SyslogIdentifier = "${name}-feed";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 30;
|
||||||
|
StartLimitBurst = 100;
|
||||||
|
Nice = -1;
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
}
|
||||||
|
);
|
||||||
|
in
|
||||||
|
lib.mkIf cfg.enable {
|
||||||
|
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = cfg.dump1090.device.type == "rtlsdr";
|
||||||
|
message = "not set up for anything but rtlsdr yet";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = !(cfg.dump1090.device.type == "rtlsdr" && cfg.dump1090.device.rtlsdr.serial != null && cfg.dump1090.device.rtlsdr.index != null);
|
||||||
|
message = "rtlsdr device cannot be selected by both serial and index";
|
||||||
|
}
|
||||||
|
{
|
||||||
|
assertion = !(!cfg.dump978.enable && cfg.skyaware978.enable);
|
||||||
|
message = "The skyaware978 service cannot be enabled if the dump978 service is disabled.";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
boot.blacklistedKernelModules = [
|
||||||
|
"dvb_usb_rtl28xxu"
|
||||||
|
];
|
||||||
|
|
||||||
|
services.udev.packages = [
|
||||||
|
pkgs.rtl-sdr
|
||||||
|
];
|
||||||
|
|
||||||
|
users.groups.plugdev = { };
|
||||||
|
|
||||||
|
users.groups.dump1090 = { };
|
||||||
|
users.users.dump1090 = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "dump1090";
|
||||||
|
extraGroups = [ "plugdev" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.piaware = { };
|
||||||
|
users.users.piaware = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "piaware";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."dump1090-fa" =
|
||||||
|
let
|
||||||
|
rtlsdrOptions =
|
||||||
|
if cfg.dump1090.device.type == "rtlsdr"
|
||||||
|
then
|
||||||
|
(
|
||||||
|
if cfg.dump1090.device.rtlsdr.serial != null
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--device-index"
|
||||||
|
cfg.dump1090.device.rtlsdr.serial
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++
|
||||||
|
(
|
||||||
|
if cfg.dump1090.device.rtlsdr.index != null
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--device-index"
|
||||||
|
(toString cfg.dump1090.device.rtlsdr.index)
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
if cfg.dump1090.device.rtlsdr.enableAgc
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--enable-agc"
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
if cfg.dump1090.device.rtlsdr.frequencyCorrection != null
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--ppm"
|
||||||
|
(toString cfg.dump1090.device.rtlsdr.frequencyCorrection)
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
if cfg.dump1090.device.rtlsdr.directSamplingMode != null
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--direct"
|
||||||
|
(toString cfg.dump1090.device.rtlsdr.directSamplingMode)
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
)
|
||||||
|
else
|
||||||
|
[ ];
|
||||||
|
adaptiveDynamicRangeOptions =
|
||||||
|
if cfg.dump1090.adaptiveDynamicRange.enable
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--adaptive-range"
|
||||||
|
] ++
|
||||||
|
(
|
||||||
|
if cfg.dump1090.adaptiveDynamicRange.target != null
|
||||||
|
then
|
||||||
|
[ "--adaptive-range-target" (toString cfg.dump1090.adaptiveDynamicRange.target) ]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++
|
||||||
|
(
|
||||||
|
if cfg.dump1090.adaptiveDynamicRange.alpha != null
|
||||||
|
then
|
||||||
|
[ "--adaptive-range-alpha" (toString cfg.dump1090.adaptiveDynamicRange.alpha) ]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++
|
||||||
|
(
|
||||||
|
if cfg.dump1090.adaptiveDynamicRange.percentile != null
|
||||||
|
then
|
||||||
|
[ "--adaptive-range-percentile" (toString cfg.dump1090.adaptiveDynamicRange.percentile) ]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++
|
||||||
|
(
|
||||||
|
if cfg.dump1090.adaptiveDynamicRange.changeDelay != null
|
||||||
|
then
|
||||||
|
[ "--adaptive-range-change-delay" (toString cfg.dump1090.adaptiveDynamicRange.changeDelay) ]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++
|
||||||
|
(
|
||||||
|
if cfg.dump1090.adaptiveDynamicRange.scanDelay != null
|
||||||
|
then
|
||||||
|
[ "--adaptive-range-scan-delay" (toString cfg.dump1090.adaptiveDynamicRange.scanDelay) ]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++
|
||||||
|
(
|
||||||
|
if cfg.dump1090.adaptiveDynamicRange.rescanDelay != null
|
||||||
|
then
|
||||||
|
[ "--adaptive-range-rescan-delay" (toString cfg.dump1090.adaptiveDynamicRange.rescanDelay) ]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
)
|
||||||
|
else
|
||||||
|
[ ];
|
||||||
|
options = [
|
||||||
|
"--quiet"
|
||||||
|
"--device-type"
|
||||||
|
cfg.dump1090.device.type
|
||||||
|
] ++ rtlsdrOptions ++ adaptiveDynamicRangeOptions ++ (
|
||||||
|
if cfg.dump1090.device.gain != null
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--gain"
|
||||||
|
(toString cfg.dump1090.device.gain)
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
if cfg.dump1090.errorCorrection
|
||||||
|
then
|
||||||
|
[ "--fix" ]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ [
|
||||||
|
"--lat"
|
||||||
|
cfg.latitude
|
||||||
|
"--lon"
|
||||||
|
cfg.longitude
|
||||||
|
] ++
|
||||||
|
(
|
||||||
|
if cfg.dump1090.maxRange != null
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--max-range"
|
||||||
|
(toString cfg.dump1090.maxRange)
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
if cfg.dump1090.network.raw.input.enable
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--net-ri-port"
|
||||||
|
(lib.concatStringsSep "," (map toString cfg.dump1090.network.raw.input.ports))
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
if cfg.dump1090.network.raw.output.enable
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--net-ro-port"
|
||||||
|
(lib.concatStringsSep "," (map toString cfg.dump1090.network.raw.output.ports))
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
if cfg.dump1090.network.raw.output.size != null
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--net-ro-size"
|
||||||
|
(toString cfg.dump1090.network.raw.output.size)
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
if cfg.dump1090.network.raw.output.interval != null
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--net-ro-interval"
|
||||||
|
(toString cfg.dump1090.network.raw.output.interval)
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++
|
||||||
|
(
|
||||||
|
if cfg.dump1090.network.baseStation.enable
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--net-sbs-port"
|
||||||
|
(lib.concatStringsSep "," (map toString cfg.dump1090.network.baseStation.ports))
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++
|
||||||
|
(
|
||||||
|
if cfg.dump1090.network.beast.input.enable
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--net-bi-port"
|
||||||
|
(lib.concatStringsSep "," (map toString cfg.dump1090.network.beast.input.ports))
|
||||||
|
]
|
||||||
|
else [ ]
|
||||||
|
) ++
|
||||||
|
(
|
||||||
|
if cfg.dump1090.network.beast.output.enable
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--net-bo-port"
|
||||||
|
(lib.concatStringsSep "," (map toString cfg.dump1090.network.beast.output.ports))
|
||||||
|
]
|
||||||
|
else [ ]
|
||||||
|
) ++ [
|
||||||
|
"--json-location-accuracy"
|
||||||
|
(toString cfg.dump1090.jsonLocationAccuracy)
|
||||||
|
"--write-json"
|
||||||
|
"%t/dump1090-fa"
|
||||||
|
] ++ cfg.dump1090.extraOptions;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
enable = cfg.dump1090.enable;
|
||||||
|
description = "dump1090 ADS-B receiver (FlightAware customization)";
|
||||||
|
wants = [ "network.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
unitConfig = {
|
||||||
|
Documentation = "https://flightaware.com/adsb/piaware/";
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = "dump1090";
|
||||||
|
RuntimeDirectory = "dump1090-fa";
|
||||||
|
RuntimeDirectoryMode = "0755";
|
||||||
|
ExecStart = "${self.packages.${pkgs.system}.dump1090-fa}/bin/dump1090 ${lib.concatStringsSep " " options}";
|
||||||
|
SyslogIdentifier = "dump1090-fa";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 30;
|
||||||
|
RestartPreventExitStatus = "64";
|
||||||
|
Nice = -5;
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.skyaware = { };
|
||||||
|
users.users.skyaware = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "skyaware";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."skyaware978" = {
|
||||||
|
enable = cfg.skyaware978.enable;
|
||||||
|
description = "skyaware978 ADS-B UAT web display";
|
||||||
|
wants = [ "network.target" ];
|
||||||
|
after = [ "network.target" "dump978-fa.service" ];
|
||||||
|
unitConfig = {
|
||||||
|
Documentation = "https://flightaware.com/adsb/piaware/";
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = "skyaware";
|
||||||
|
RuntimeDirectory = "skyaware978";
|
||||||
|
RuntimeDirectoryMode = "0755";
|
||||||
|
ExecStart = "${self.packages.${pkgs.system}.dump978-fa}/bin/skyaware978 --lat ${cfg.latitude} --lon ${cfg.longitude} --json-dir %t/skyaware978";
|
||||||
|
SyslogIdentifier = "skyaware978";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 30;
|
||||||
|
RestartPreventExitStatus = "64";
|
||||||
|
};
|
||||||
|
wantedBy = [ "dump978-fa.service" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.adsbexchange = { };
|
||||||
|
users.users.adsbexchange = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "adsbexchange";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."adsbexchange-mlat" =
|
||||||
|
let
|
||||||
|
uuidFile = pkgs.writeTextFile {
|
||||||
|
name = "adsbx-uuid";
|
||||||
|
text = "${cfg.adsbexchange.uuid}";
|
||||||
|
};
|
||||||
|
options = [
|
||||||
|
"--input-type"
|
||||||
|
cfg.adsbexchange.mlat.input.type
|
||||||
|
"--no-udp"
|
||||||
|
"--input-connect"
|
||||||
|
"${cfg.adsbexchange.mlat.input.host}:${toString cfg.adsbexchange.mlat.input.port}"
|
||||||
|
"--server"
|
||||||
|
cfg.adsbexchange.mlat.server
|
||||||
|
"--user"
|
||||||
|
cfg.adsbexchange.username
|
||||||
|
"--lat"
|
||||||
|
cfg.latitude
|
||||||
|
"--lon"
|
||||||
|
cfg.longitude
|
||||||
|
"--alt"
|
||||||
|
(toString cfg.altitude)
|
||||||
|
"--uuid-file"
|
||||||
|
"${uuidFile}"
|
||||||
|
] ++ (
|
||||||
|
if cfg.adsbexchange.mlat.privacy
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--privacy"
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
map (result: "--result ${result}") cfg.adsbexchange.mlat.results
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
enable = cfg.adsbexchange.mlat.enable;
|
||||||
|
description = "ADS-B Exchange MLAT client.";
|
||||||
|
wants = [ "network.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
unitConfig = {
|
||||||
|
Documentation = "https://github.com/makrsmark/mlat-client/";
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = "adsbexchange";
|
||||||
|
RuntimeDirectory = "adsbexchange-mlat";
|
||||||
|
RuntimeDirectoryMode = "0755";
|
||||||
|
ExecStart = "${self.packages.${pkgs.system}.adsbfi-mlat-client}/bin/mlat-client ${lib.concatStringsSep " " options}";
|
||||||
|
SyslogIdentifier = "adsbexchange-mlat";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 30;
|
||||||
|
Nice = -1;
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."adsbexchange-feed" =
|
||||||
|
let
|
||||||
|
uuidFile = pkgs.writeTextFile {
|
||||||
|
name = "adsbx-uuid";
|
||||||
|
text = "${cfg.adsbexchange.uuid}";
|
||||||
|
};
|
||||||
|
options = [
|
||||||
|
"--quiet"
|
||||||
|
"--net"
|
||||||
|
"--net-only"
|
||||||
|
"--write-json"
|
||||||
|
"%t/adsbexchange-feed"
|
||||||
|
"--net-beast-reduce-interval 0.5"
|
||||||
|
"--net-connector feed1.adsbexchange.com,30004,beast_reduce_out,feed2.adsbexchange.com,64004"
|
||||||
|
"--net-heartbeat 60"
|
||||||
|
"--net-ro-size 1280"
|
||||||
|
"--net-ro-interval 0.2"
|
||||||
|
"--net-ro-port 0"
|
||||||
|
"--net-sbs-port 0"
|
||||||
|
"--net-bi-port ${toString cfg.adsbexchange.feed.beastInputPort}"
|
||||||
|
"--net-bo-port 0"
|
||||||
|
"--net-ri-port 0"
|
||||||
|
"--write-json-every 1"
|
||||||
|
"--lat"
|
||||||
|
cfg.latitude
|
||||||
|
"--lon"
|
||||||
|
cfg.longitude
|
||||||
|
"--max-range 450"
|
||||||
|
"--json-location-accuracy 2"
|
||||||
|
"--range-outline-hours 24"
|
||||||
|
"--uuid-file"
|
||||||
|
"${uuidFile}"
|
||||||
|
"--net-connector 127.0.0.1,30978,uat_in,silent_fail"
|
||||||
|
"--net-connector 127.0.0.1,30005,beast_in,silent_fail"
|
||||||
|
];
|
||||||
|
in
|
||||||
|
{
|
||||||
|
enable = cfg.adsbexchange.feed.enable;
|
||||||
|
description = "ADS-B Exchange feeder.";
|
||||||
|
wants = [ "network.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
unitConfig = {
|
||||||
|
Documentation = "https://github.com/wiedehopf/readsb/";
|
||||||
|
StartLimitIntervalSec = 1;
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = "adsbexchange";
|
||||||
|
RuntimeDirectory = "adsbexchange-feed";
|
||||||
|
RuntimeDirectoryMode = "0755";
|
||||||
|
ExecStart = "${self.packages.${pkgs.system}.adsbfi-readsb}/bin/readsb ${lib.concatStringsSep " " options}";
|
||||||
|
SyslogIdentifier = "adsbexchange-feed";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 30;
|
||||||
|
StartLimitBurst = 100;
|
||||||
|
Nice = -1;
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
##
|
||||||
|
## ADSB.fi
|
||||||
|
##
|
||||||
|
|
||||||
|
users.groups.adsbfi = { };
|
||||||
|
users.users.adsbfi = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "adsbexchange";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."adsbfi-mlat" =
|
||||||
|
let
|
||||||
|
uuidFile = pkgs.writeTextFile {
|
||||||
|
name = "adsbfi-uuid";
|
||||||
|
text = "${cfg.adsbfi.uuid}";
|
||||||
|
};
|
||||||
|
options = [
|
||||||
|
"--input-type"
|
||||||
|
cfg.adsbfi.mlat.input.type
|
||||||
|
"--no-udp"
|
||||||
|
"--input-connect"
|
||||||
|
"${cfg.adsbfi.mlat.input.host}:${toString cfg.adsbfi.mlat.input.port}"
|
||||||
|
"--server"
|
||||||
|
cfg.adsbfi.mlat.server
|
||||||
|
"--user"
|
||||||
|
cfg.adsbfi.username
|
||||||
|
"--lat"
|
||||||
|
cfg.latitude
|
||||||
|
"--lon"
|
||||||
|
cfg.longitude
|
||||||
|
"--alt"
|
||||||
|
(toString cfg.altitude)
|
||||||
|
"--uuid-file"
|
||||||
|
"${uuidFile}"
|
||||||
|
] ++ (
|
||||||
|
if cfg.adsbfi.mlat.privacy
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"--privacy"
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
map (result: "--result ${result}") cfg.adsbfi.mlat.results
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
enable = cfg.adsbfi.mlat.enable;
|
||||||
|
description = "ADSB.fi MLAT client.";
|
||||||
|
wants = [ "network.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
unitConfig = {
|
||||||
|
Documentation = "https://github.com/makrsmark/mlat-client/";
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = "adsbfi";
|
||||||
|
RuntimeDirectory = "adsbfi-mlat";
|
||||||
|
RuntimeDirectoryMode = "0755";
|
||||||
|
ExecStart = "${self.packages.${pkgs.system}.adsbfi-mlat-client}/bin/mlat-client ${lib.concatStringsSep " " options}";
|
||||||
|
SyslogIdentifier = "adsbfi-mlat";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 30;
|
||||||
|
Nice = -1;
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."adsbfi-feed" =
|
||||||
|
let
|
||||||
|
uuidFile = pkgs.writeTextFile {
|
||||||
|
name = "adsbfi-uuid";
|
||||||
|
text = "${cfg.adsbfi.uuid}";
|
||||||
|
};
|
||||||
|
connectors = map
|
||||||
|
(
|
||||||
|
connector: "--net-connector ${connector}"
|
||||||
|
)
|
||||||
|
(
|
||||||
|
map
|
||||||
|
(
|
||||||
|
connector: (
|
||||||
|
lib.concatStringsSep "," (
|
||||||
|
[
|
||||||
|
connector.primary.host
|
||||||
|
(toString connector.primary.port)
|
||||||
|
connector.protocol
|
||||||
|
] ++ (
|
||||||
|
if connector.silentFail
|
||||||
|
then
|
||||||
|
[
|
||||||
|
"silent_fail"
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
) ++ (
|
||||||
|
if connector.secondary != null
|
||||||
|
then
|
||||||
|
[
|
||||||
|
connector.secondary.host
|
||||||
|
(toString connector.secondary.port)
|
||||||
|
]
|
||||||
|
else
|
||||||
|
[ ]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
cfg.adsbfi.feed.connectors
|
||||||
|
);
|
||||||
|
options = [
|
||||||
|
"--quiet"
|
||||||
|
"--net"
|
||||||
|
"--net-only"
|
||||||
|
"--write-json"
|
||||||
|
"%t/adsbfi-feed"
|
||||||
|
"--net-beast-reduce-interval 0.5"
|
||||||
|
"--net-heartbeat 60"
|
||||||
|
"--net-ro-size 1280"
|
||||||
|
"--net-ro-interval 0.2"
|
||||||
|
"--net-ro-port 0"
|
||||||
|
"--net-sbs-port 0"
|
||||||
|
"--net-bi-port ${toString cfg.adsbfi.feed.beastInputPort}"
|
||||||
|
"--net-bo-port 0"
|
||||||
|
"--net-ri-port 0"
|
||||||
|
"--write-json-every 1"
|
||||||
|
"--lat"
|
||||||
|
cfg.latitude
|
||||||
|
"--lon"
|
||||||
|
cfg.longitude
|
||||||
|
"--max-range 450"
|
||||||
|
"--json-location-accuracy 2"
|
||||||
|
"--range-outline-hours 24"
|
||||||
|
"--uuid-file"
|
||||||
|
"${uuidFile}"
|
||||||
|
] ++ connectors;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
enable = cfg.adsbfi.feed.enable;
|
||||||
|
description = "ADSB.fi feeder.";
|
||||||
|
wants = [ "network.target" ];
|
||||||
|
after = [ "network.target" ];
|
||||||
|
unitConfig = {
|
||||||
|
Documentation = "https://github.com/widehopf/readsb/";
|
||||||
|
StartLimitIntervalSec = 1;
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = "adsbfi";
|
||||||
|
RuntimeDirectory = "adsbfi-feed";
|
||||||
|
RuntimeDirectoryMode = "0755";
|
||||||
|
ExecStart = "${self.packages.${pkgs.system}.adsbfi-readsb}/bin/readsb ${lib.concatStringsSep " " options}";
|
||||||
|
SyslogIdentifier = "adsbfi-feed";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartSec = 30;
|
||||||
|
StartLimitBurst = 100;
|
||||||
|
Nice = -1;
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
##
|
||||||
|
## theairtraffic.com
|
||||||
|
##
|
||||||
|
|
||||||
|
users.groups.theairtraffic = { };
|
||||||
|
users.users.theairtraffic = {
|
||||||
|
isSystemUser = true;
|
||||||
|
group = "theairtraffic";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services."theairtraffic-mlat" = createMlatService "theairtraffic" cfg.theairtraffic;
|
||||||
|
systemd.services."theairtraffic-feed" = createFeedService "theairtraffic" cfg.theairtraffic;
|
||||||
|
|
||||||
|
systemd.tmpfiles.rules = [
|
||||||
|
"d /var/cache/piaware 0755 piaware piaware - -"
|
||||||
|
];
|
||||||
|
|
||||||
|
systemd.services."piaware" =
|
||||||
|
let
|
||||||
|
config = pkgs.writeTextFile {
|
||||||
|
name = "piaware.conf";
|
||||||
|
text = ''
|
||||||
|
# https://flightaware.com/adsb/piaware/advanced_configuration
|
||||||
|
allow-auto-updates no
|
||||||
|
allow-manual-updates no
|
||||||
|
allow-mlat ${if cfg.piaware.allowMLAT then "yes" else "no"}
|
||||||
|
allow-modeac ${if cfg.piaware.allowModeAC then "yes" else "no"}
|
||||||
|
feeder-id ${cfg.piaware.feederId}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
enable = cfg.piaware.enable;
|
||||||
|
description = "FlightAware ADS-B uploader";
|
||||||
|
wants = [ "network-online.target" ];
|
||||||
|
after = [ "dump1090-fa.service" "network-online.target" "time-sync.target" ];
|
||||||
|
unitConfig = {
|
||||||
|
Documentation = "https://flightaware.com/adsb/piaware/";
|
||||||
|
};
|
||||||
|
serviceConfig = {
|
||||||
|
Type = "simple";
|
||||||
|
User = "piaware";
|
||||||
|
RuntimeDirectory = "piaware";
|
||||||
|
ExecStart = "${self.packages.${pkgs.system}.piaware}/bin/piaware -p %t/piaware/piaware.pid -plainlog -configfile ${config} -statusfile %t/piaware/status.json";
|
||||||
|
ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
|
||||||
|
Restart = "on-failure";
|
||||||
|
RestartPreventExitStatus = "4 6";
|
||||||
|
};
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
reloadTriggers = [
|
||||||
|
"/etc/piaware.conf"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
virtualHosts = {
|
||||||
|
"_" = {
|
||||||
|
root = self.packages.${pkgs.system}.dump1090-fa.html;
|
||||||
|
locations = {
|
||||||
|
"=/status.json" = {
|
||||||
|
alias = "/run/piaware/status.json";
|
||||||
|
extraConfig = ''
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
"/data/" = {
|
||||||
|
alias = "/run/dump1090-fa/";
|
||||||
|
extraConfig = ''
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
"/data-978/" = {
|
||||||
|
root = "/run/skyaware978/";
|
||||||
|
extraConfig = ''
|
||||||
|
add_header Access-Control-Allow-Origin *;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
12
modules/default.nix
Normal file
12
modules/default.nix
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{ self, ... }: {
|
||||||
|
nixosModules = {
|
||||||
|
adsb = { config, lib, pkgs, ... }:
|
||||||
|
let
|
||||||
|
cfg = config.adsb;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = import ./options { inherit self cfg lib; };
|
||||||
|
config = import ./config { inherit self cfg lib pkgs; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
96
modules/options/adsbexchange.nix
Normal file
96
modules/options/adsbexchange.nix
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
{ cfg, lib, netConnector, UUID }:
|
||||||
|
lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
username = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.addCheck lib.types.str (
|
||||||
|
username: (builtins.match ''^[a-zA-Z0-9_-]+$'' username) != null
|
||||||
|
));
|
||||||
|
default = null;
|
||||||
|
example = "'william34-london' or 'william34-jersey'";
|
||||||
|
description = "A unique name to be shown on the ADS-B Exchange MLAT map (map.adsbexchange.com/mlat-map)";
|
||||||
|
};
|
||||||
|
uuid = lib.options.mkOption {
|
||||||
|
type = UUID;
|
||||||
|
};
|
||||||
|
mlat = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable ADS-B Exchange MLAT client.";
|
||||||
|
};
|
||||||
|
input = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
host = lib.options.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "127.0.0.1";
|
||||||
|
example = "127.0.0.1";
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
port = lib.options.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
default = 30005;
|
||||||
|
example = 30005;
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
type = lib.options.mkOption {
|
||||||
|
type = lib.types.enum [ "dump1090" "radarcape_gps" ];
|
||||||
|
default = "dump1090";
|
||||||
|
example = "dump1090";
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
reduceInterval = lib.options.mkOption {
|
||||||
|
type = lib.types.float;
|
||||||
|
default = 0.5;
|
||||||
|
example = "0.5";
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
results = lib.options.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [
|
||||||
|
"beast,connect,127.0.0.1:${toString cfg.adsbexchange.feed.beastInputPort}"
|
||||||
|
];
|
||||||
|
description = "Where to send results of MLAT computations.";
|
||||||
|
};
|
||||||
|
privacy = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Sets the privacy flag for this receiver. Currently, this removes the receiver location pin from the coverage maps.";
|
||||||
|
};
|
||||||
|
server = lib.options.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "feed.adsbexchange.com:31090";
|
||||||
|
example = "feed.adsbexchange.com:31090";
|
||||||
|
description = "Server to feed MLAT data to";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
feed = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable ADS-B Exchange feeder.";
|
||||||
|
};
|
||||||
|
beastInputPort = lib.options.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
default = 30154;
|
||||||
|
description = "Port to accept Beast messages on.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
}
|
144
modules/options/adsbfi.nix
Normal file
144
modules/options/adsbfi.nix
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
##
|
||||||
|
## ADSB.fi configuration options
|
||||||
|
##
|
||||||
|
|
||||||
|
{ cfg, lib, netConnector, UUID }:
|
||||||
|
lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
username = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.addCheck lib.types.str (
|
||||||
|
username: (builtins.match ''^[a-zA-Z0-9_-]+$'' username) != null
|
||||||
|
));
|
||||||
|
default = null;
|
||||||
|
example = "'william34-london' or 'william34-jersey'";
|
||||||
|
description = "A unique name to be shown on the ADSB.fi MLAT map";
|
||||||
|
};
|
||||||
|
|
||||||
|
uuid = lib.options.mkOption {
|
||||||
|
type = UUID;
|
||||||
|
};
|
||||||
|
|
||||||
|
mlat = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable ADSD.fi MLAT client.";
|
||||||
|
};
|
||||||
|
|
||||||
|
input = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
host = lib.options.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "127.0.0.1";
|
||||||
|
example = "127.0.0.1";
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
port = lib.options.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
default = 30005;
|
||||||
|
example = 30005;
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
type = lib.options.mkOption {
|
||||||
|
type = lib.types.enum [
|
||||||
|
"dump1090"
|
||||||
|
"radarcape_gps"
|
||||||
|
];
|
||||||
|
default = "dump1090";
|
||||||
|
example = "dump1090";
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
reduceInterval = lib.options.mkOption {
|
||||||
|
type = lib.types.float;
|
||||||
|
default = 0.5;
|
||||||
|
example = "0.5";
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
results = lib.options.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [
|
||||||
|
"beast,connect,127.0.0.1:${toString cfg.adsbfi.feed.beastInputPort}"
|
||||||
|
];
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
privacy = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Sets the privacy flag for this receiver. Currently, this removes the receiver location pin from the coverage maps.";
|
||||||
|
};
|
||||||
|
|
||||||
|
server = lib.options.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "feed.adsb.fi:31090";
|
||||||
|
example = "feed.adsb.fi:31090";
|
||||||
|
description = "Server to feed MLAT data to";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
feed = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable ADSB.fi feeder.";
|
||||||
|
};
|
||||||
|
|
||||||
|
beastInputPort = lib.options.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
default = 30155;
|
||||||
|
description = "Port to accept Beast messages on.";
|
||||||
|
};
|
||||||
|
|
||||||
|
connectors = lib.options.mkOption {
|
||||||
|
type = lib.types.listOf netConnector;
|
||||||
|
default = [
|
||||||
|
{
|
||||||
|
protocol = "uat_in";
|
||||||
|
primary = {
|
||||||
|
host = "127.0.0.1";
|
||||||
|
port = 30978;
|
||||||
|
};
|
||||||
|
silentFail = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
protocol = "beast_in";
|
||||||
|
primary = {
|
||||||
|
host = "127.0.0.1";
|
||||||
|
port = 30005;
|
||||||
|
};
|
||||||
|
silentFail = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
protocol = "beast_reduce_out";
|
||||||
|
primary = {
|
||||||
|
host = "feed.adsb.fi";
|
||||||
|
port = 30004;
|
||||||
|
};
|
||||||
|
secondary = {
|
||||||
|
host = "feed.adsb.fi";
|
||||||
|
port = 64004;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
95
modules/options/default.nix
Normal file
95
modules/options/default.nix
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
{ cfg, lib, ... }:
|
||||||
|
let
|
||||||
|
hostPort = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
host = lib.options.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
};
|
||||||
|
|
||||||
|
port = lib.options.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
netConnector = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
protocol = lib.options.mkOption {
|
||||||
|
type = lib.types.enum [
|
||||||
|
"beast_in"
|
||||||
|
"beast_out"
|
||||||
|
"beast_reduce_out"
|
||||||
|
"beast_reduce_plus_out"
|
||||||
|
"gpsd_in"
|
||||||
|
"json_out"
|
||||||
|
"raw_in"
|
||||||
|
"raw_out"
|
||||||
|
"sbs_in"
|
||||||
|
"sbs_in_jaero"
|
||||||
|
"sbs_in_mlat"
|
||||||
|
"sbs_out"
|
||||||
|
"sbs_out_jaero"
|
||||||
|
"sbs_out_mlat"
|
||||||
|
"sbs_out_replay"
|
||||||
|
"uat_in"
|
||||||
|
"vrs_out"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
primary = lib.options.mkOption {
|
||||||
|
type = hostPort;
|
||||||
|
};
|
||||||
|
silentFail = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
secondary = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr hostPort;
|
||||||
|
default = null;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
UUID = lib.types.addCheck lib.types.str (
|
||||||
|
uuid: (builtins.match ''^[A-F0-9a-f]{8}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{4}-[A-F0-9a-f]{12}$'' uuid) != null
|
||||||
|
);
|
||||||
|
in
|
||||||
|
{
|
||||||
|
adsb = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkEnableOption "ADS-B";
|
||||||
|
|
||||||
|
latitude = lib.options.mkOption {
|
||||||
|
type = lib.types.addCheck lib.types.str (
|
||||||
|
lat:
|
||||||
|
(builtins.match ''^([+-])?[0-9]+(\.[0-9]{5,})?$'' lat) != null && (builtins.fromJSON lat) >= -90.0 && (builtins.fromJSON lat) <= 90.0
|
||||||
|
);
|
||||||
|
description = "Latitude of the receiver expressed in degrees with at least 5 decimal places. For MLAT the precise location of your antenna is required. A small error of 15m/45ft will cause issues with MLAT!";
|
||||||
|
};
|
||||||
|
|
||||||
|
longitude = lib.options.mkOption {
|
||||||
|
type = lib.types.addCheck lib.types.str (
|
||||||
|
lon:
|
||||||
|
(builtins.match ''^([+-])?[0-9]+(\.[0-9]{5,})?$'' lon) != null && (builtins.fromJSON lon) >= -180.0 && (builtins.fromJSON lon) <= 180.0
|
||||||
|
);
|
||||||
|
description = "Longitude of the receiver expressed in degrees with at least 5 decimal places. For MLAT the precise location of your antenna is required. A small error of 15m/45ft will cause issues with MLAT!";
|
||||||
|
};
|
||||||
|
|
||||||
|
altitude = lib.options.mkOption {
|
||||||
|
type = lib.types.float;
|
||||||
|
description = "The altitude if the receiver above sea level (in meters).";
|
||||||
|
};
|
||||||
|
|
||||||
|
dump1090 = import ./dump1090.nix { inherit lib; };
|
||||||
|
dump978 = import ./dump978.nix { inherit lib; };
|
||||||
|
skyaware978 = import ./skyaware978.nix { inherit lib; };
|
||||||
|
|
||||||
|
adsbexchange = import ./adsbexchange.nix { inherit cfg lib netConnector UUID; };
|
||||||
|
adsbfi = import ./adsbfi.nix { inherit cfg lib netConnector UUID; };
|
||||||
|
piaware = import ./piaware.nix { inherit lib UUID; };
|
||||||
|
theairtraffic = import ./theairtraffic.nix { inherit cfg lib netConnector UUID; };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
293
modules/options/dump1090.nix
Normal file
293
modules/options/dump1090.nix
Normal file
|
@ -0,0 +1,293 @@
|
||||||
|
{ lib }:
|
||||||
|
lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkEnableOption "Dump1090";
|
||||||
|
|
||||||
|
errorCorrection = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
maxRange = lib.options.mkOption {
|
||||||
|
type = lib.types.addCheck lib.types.int (x: x >= 0);
|
||||||
|
default = 360;
|
||||||
|
description = "Absolute maximum range for position decoding (in NM)";
|
||||||
|
};
|
||||||
|
|
||||||
|
jsonLocationAccuracy = lib.options.mkOption {
|
||||||
|
type = lib.types.enum [ 0 1 2 ];
|
||||||
|
default = 2;
|
||||||
|
description = "Accuracy of receiver location in json metadata (0=no location, 1=approximate, 2=exact)";
|
||||||
|
};
|
||||||
|
|
||||||
|
adaptiveDynamicRange = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Adjust gain for target dynamic range";
|
||||||
|
};
|
||||||
|
|
||||||
|
target = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.int;
|
||||||
|
default = null;
|
||||||
|
description = "Set target dynamic range in dB";
|
||||||
|
};
|
||||||
|
|
||||||
|
alpha = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.addCheck lib.types.float (alpha: alpha >= 0.0 && alpha <= 1.0));
|
||||||
|
default = null;
|
||||||
|
description = "Set dynamic range noise smoothing factor (0..1, smaller=more smoothing)";
|
||||||
|
};
|
||||||
|
|
||||||
|
percentile = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.addCheck lib.types.int (x: x >= 0 && x <= 100));
|
||||||
|
default = null;
|
||||||
|
description = "Set dynamic range noise percentile";
|
||||||
|
};
|
||||||
|
|
||||||
|
changeDelay = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.addCheck lib.types.int (x: x >= 0));
|
||||||
|
default = null;
|
||||||
|
description = "Set delay after changing gain before resuming dynamic range control (seconds)";
|
||||||
|
};
|
||||||
|
|
||||||
|
scanDelay = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.addCheck lib.types.int (x: x >= 0));
|
||||||
|
default = null;
|
||||||
|
description = "Set scan interval for dynamic range gain scanning following a gain decrease due to an increase in noise (seconds)";
|
||||||
|
};
|
||||||
|
|
||||||
|
rescanDelay = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.addCheck lib.types.int (x: x >= 0));
|
||||||
|
default = null;
|
||||||
|
description = "Set periodic rescan interval for dynamic range gain scanning (seconds)";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
description = "Configuration options for adaptive dynamic range.";
|
||||||
|
};
|
||||||
|
|
||||||
|
device = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
type = lib.options.mkOption {
|
||||||
|
type = lib.types.enum [ "rtlsdr" "bladerf" "hackrf" "limesdr" ];
|
||||||
|
default = "rtlsdr";
|
||||||
|
};
|
||||||
|
|
||||||
|
rtlsdr = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
serial = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.str;
|
||||||
|
default = null;
|
||||||
|
description = "select device by serial";
|
||||||
|
};
|
||||||
|
|
||||||
|
index = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.int;
|
||||||
|
default = null;
|
||||||
|
description = "select device by index";
|
||||||
|
};
|
||||||
|
|
||||||
|
enableAgc = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "enable digital AGC (not tuner AGC!)";
|
||||||
|
};
|
||||||
|
|
||||||
|
frequencyCorrection = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.int;
|
||||||
|
default = null;
|
||||||
|
description = "set oscillator frequency correction in PPM";
|
||||||
|
};
|
||||||
|
|
||||||
|
directSamplingMode = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.enum [ 0 1 2 ]);
|
||||||
|
default = null;
|
||||||
|
description = "set direct sampling mode";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
gain = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.int;
|
||||||
|
default = null;
|
||||||
|
description = "Set gain in dB (default: varies by SDR type)";
|
||||||
|
};
|
||||||
|
|
||||||
|
frequency = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr lib.types.int;
|
||||||
|
default = null;
|
||||||
|
description = "Set frequency (default: 1090 Mhz)";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
network = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
raw = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
input = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable TCP raw input";
|
||||||
|
};
|
||||||
|
|
||||||
|
ports = lib.options.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.port;
|
||||||
|
default = [ 30001 ];
|
||||||
|
description = "TCP raw input listen ports (default: 30001)";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
output = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Enable TCP raw output";
|
||||||
|
};
|
||||||
|
|
||||||
|
ports = lib.options.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.port;
|
||||||
|
default = [ 30002 ];
|
||||||
|
description = "TCP raw output listen ports (default: 30002)";
|
||||||
|
};
|
||||||
|
|
||||||
|
size = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.addCheck lib.types.int (x: x >= 0));
|
||||||
|
default = null;
|
||||||
|
description = "TCP output minimum size (default: 0)";
|
||||||
|
};
|
||||||
|
|
||||||
|
interval = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.addCheck lib.types.int (x: x >= 0));
|
||||||
|
default = null;
|
||||||
|
description = "TCP output memory flush rate in seconds (default: 0)";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
baseStation = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
ports = lib.options.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.port;
|
||||||
|
default = [ 30003 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
beast = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
input = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
ports = lib.options.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.port;
|
||||||
|
default = [ 30004 30104 ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
output = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
ports = lib.options.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.port;
|
||||||
|
default = [ 30005 ];
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
stratux = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
ports = lib.options.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.port;
|
||||||
|
default = [ ];
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
extraOptions = lib.options.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [ ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
15
modules/options/dump978.nix
Normal file
15
modules/options/dump978.nix
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{ lib }:
|
||||||
|
lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable the dump978 service.";
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
}
|
26
modules/options/piaware.nix
Normal file
26
modules/options/piaware.nix
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
{ lib, UUID }:
|
||||||
|
lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
enable = lib.options.mkEnableOption "PiAware";
|
||||||
|
|
||||||
|
feederId = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr UUID;
|
||||||
|
default = null;
|
||||||
|
description = "PiAware feeder ID";
|
||||||
|
};
|
||||||
|
|
||||||
|
allowMLAT = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Should PiAware enable multilateration where possible? You may need to disable this if multilateration overloads your receiver";
|
||||||
|
};
|
||||||
|
|
||||||
|
allowModeAC = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = true;
|
||||||
|
description = "Should PiAware enable reception of Mode A/C messages when requested? You may need to disable this if processing Mode A/C overloads your receiver.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
15
modules/options/skyaware978.nix
Normal file
15
modules/options/skyaware978.nix
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
{ lib }:
|
||||||
|
lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable the skyaware978 service.";
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
}
|
156
modules/options/theairtraffic.nix
Normal file
156
modules/options/theairtraffic.nix
Normal file
|
@ -0,0 +1,156 @@
|
||||||
|
##
|
||||||
|
## theairtraffic.com
|
||||||
|
##
|
||||||
|
|
||||||
|
{ cfg, lib, netConnector, UUID }: lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
name = lib.options.mkOption {
|
||||||
|
type = lib.types.enum [
|
||||||
|
"adsbexchange"
|
||||||
|
"adsbfi"
|
||||||
|
"theairtraffic"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
username = lib.options.mkOption {
|
||||||
|
type = lib.types.nullOr (lib.types.addCheck lib.types.str (
|
||||||
|
username: (builtins.match ''^[a-zA-Z0-9_-]+$'' username) != null
|
||||||
|
));
|
||||||
|
default = null;
|
||||||
|
example = "'william34-london' or 'william34-jersey'";
|
||||||
|
description = "A unique name to be shown on the MLAT map";
|
||||||
|
};
|
||||||
|
|
||||||
|
uuid = lib.options.mkOption {
|
||||||
|
type = UUID;
|
||||||
|
};
|
||||||
|
|
||||||
|
mlat = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable MLAT client.";
|
||||||
|
};
|
||||||
|
|
||||||
|
input = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
host = lib.options.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "127.0.0.1";
|
||||||
|
example = "127.0.0.1";
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
port = lib.options.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
default = 30005;
|
||||||
|
example = 30005;
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
type = lib.options.mkOption {
|
||||||
|
type = lib.types.enum [
|
||||||
|
"dump1090"
|
||||||
|
"radarcape_gps"
|
||||||
|
];
|
||||||
|
default = "dump1090";
|
||||||
|
example = "dump1090";
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
default = { };
|
||||||
|
};
|
||||||
|
|
||||||
|
reduceInterval = lib.options.mkOption {
|
||||||
|
type = lib.types.float;
|
||||||
|
default = 0.5;
|
||||||
|
example = "0.5";
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
results = lib.options.mkOption {
|
||||||
|
type = lib.types.listOf lib.types.str;
|
||||||
|
default = [
|
||||||
|
"beast,connect,127.0.0.1:${toString cfg.theairtraffic.feed.beastInputPort}"
|
||||||
|
];
|
||||||
|
description = "";
|
||||||
|
};
|
||||||
|
|
||||||
|
privacy = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Sets the privacy flag for this receiver. Currently, this removes the receiver
|
||||||
|
location pin from the coverage maps.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
server = lib.options.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "feed.theairtraffic.com:31090";
|
||||||
|
example = "feed.theairtraffic.com:31090";
|
||||||
|
description = "Server to feed MLAT data to";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
feed = lib.options.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
|
||||||
|
enable = lib.options.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
description = "Enable theairtraffic.com feeder.";
|
||||||
|
};
|
||||||
|
|
||||||
|
beastInputPort = lib.options.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
default = 30156;
|
||||||
|
description = "Port to accept Beast messages on.";
|
||||||
|
};
|
||||||
|
|
||||||
|
connectors = lib.options.mkOption {
|
||||||
|
type = lib.types.listOf netConnector;
|
||||||
|
default = [
|
||||||
|
{
|
||||||
|
protocol = "uat_in";
|
||||||
|
primary = {
|
||||||
|
host = "127.0.0.1";
|
||||||
|
port = 30978;
|
||||||
|
};
|
||||||
|
silentFail = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
protocol = "beast_in";
|
||||||
|
primary = {
|
||||||
|
host = "127.0.0.1";
|
||||||
|
port = 30005;
|
||||||
|
};
|
||||||
|
silentFail = true;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
protocol = "beast_reduce_out";
|
||||||
|
primary = {
|
||||||
|
host = "feed.theairtraffic.com";
|
||||||
|
port = 30004;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
22
packages/adsbexchange-mlat-client.nix
Normal file
22
packages/adsbexchange-mlat-client.nix
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
pname = "adsbexchange-mlat-client";
|
||||||
|
version = "0.4.2";
|
||||||
|
in
|
||||||
|
pkgs.python3.pkgs.buildPythonApplication {
|
||||||
|
inherit pname version;
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "ADSBexchange";
|
||||||
|
repo = "mlat-client";
|
||||||
|
rev = "faf9638fe8c2eafc2abdc45621ff879c7acb882b";
|
||||||
|
sha256 = "sha256-V//LpYmBXtT8haX1aZ4XldzzyUY2YN7x3lTpQ2csTmw=";
|
||||||
|
};
|
||||||
|
meta = with pkgs.lib; {
|
||||||
|
homepage = "https://github.com/adsbexchange/mlat-client";
|
||||||
|
description = "ADS-B Exchange Mode S multilateration client";
|
||||||
|
longDescription = ''
|
||||||
|
This is a client that selectively forwards Mode S messages to a server that resolves the transmitter position by multilateration of the same message received by multiple clients.
|
||||||
|
'';
|
||||||
|
license = licenses.gpl3Plus;
|
||||||
|
};
|
||||||
|
}
|
40
packages/adsbexchange-readsb.nix
Normal file
40
packages/adsbexchange-readsb.nix
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
pname = "adsbexchange-readsb";
|
||||||
|
version = "3.14.1597";
|
||||||
|
in
|
||||||
|
pkgs.stdenv.mkDerivation {
|
||||||
|
inherit pname version;
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "adsbexchange";
|
||||||
|
repo = "readsb";
|
||||||
|
rev = "61c6bb02ae1af04c805e2607bfec5dbfea4c6515";
|
||||||
|
sha256 = "sha256-LXIib8mfgFMINXCYHxfnhdGI5WjJsCNq0LV+i+Kp4r8=";
|
||||||
|
};
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.pkg-config
|
||||||
|
];
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
pkgs.libad9361
|
||||||
|
pkgs.libbladeRF
|
||||||
|
pkgs.libiio
|
||||||
|
pkgs.librtlsdr
|
||||||
|
pkgs.ncurses
|
||||||
|
pkgs.zlib
|
||||||
|
pkgs.zstd
|
||||||
|
];
|
||||||
|
buildFlags = [
|
||||||
|
"READSB_VERSION=v${version}"
|
||||||
|
"RTLSDR=yes"
|
||||||
|
"BLADERF=yes"
|
||||||
|
"PLUTOSDR=yes"
|
||||||
|
];
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p $out/bin
|
||||||
|
install -D readsb $out/bin
|
||||||
|
install -D viewadsb $out/bin
|
||||||
|
ln -s readsb $out/bin/feed-adsbx
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
}
|
22
packages/adsbfi-mlat-client.nix
Normal file
22
packages/adsbfi-mlat-client.nix
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
pname = "adsbfi-mlat-client";
|
||||||
|
version = "0.4.2";
|
||||||
|
in
|
||||||
|
pkgs.python3.pkgs.buildPythonApplication {
|
||||||
|
inherit pname version;
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "makrsmark";
|
||||||
|
repo = "mlat-client";
|
||||||
|
rev = "0e8f9f927339e6bfa8cadaa8fff6cb734de4b60a";
|
||||||
|
sha256 = "sha256-4dWwRBKWkxMjKJmZtAAZjaFqkGubOmKTmzmntcR92II=";
|
||||||
|
};
|
||||||
|
meta = with pkgs.lib; {
|
||||||
|
homepage = "https://github.com/makrsmark/mlat-client";
|
||||||
|
description = "ADSB.fi Mode S multilateration client";
|
||||||
|
longDescription = ''
|
||||||
|
This is a client that selectively forwards Mode S messages to a server that resolves the transmitter position by multilateration of the same message received by multiple clients.
|
||||||
|
'';
|
||||||
|
license = licenses.gpl3Plus;
|
||||||
|
};
|
||||||
|
}
|
40
packages/adsbfi-readsb.nix
Normal file
40
packages/adsbfi-readsb.nix
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
pname = "adsbfi-readsb";
|
||||||
|
version = "3.14.1606";
|
||||||
|
in
|
||||||
|
pkgs.stdenv.mkDerivation {
|
||||||
|
inherit pname version;
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "wiedehopf";
|
||||||
|
repo = "readsb";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "sha256-XjvWpxCYCoNPDPwbvLKk8l23dhHL98HbVK6+Zn+36Wk=";
|
||||||
|
};
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.pkg-config
|
||||||
|
];
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
pkgs.libad9361
|
||||||
|
pkgs.libbladeRF
|
||||||
|
pkgs.libiio
|
||||||
|
pkgs.librtlsdr
|
||||||
|
pkgs.ncurses
|
||||||
|
pkgs.zlib
|
||||||
|
pkgs.zstd
|
||||||
|
];
|
||||||
|
buildFlags = [
|
||||||
|
"READSB_VERSION=v${version}"
|
||||||
|
"RTLSDR=yes"
|
||||||
|
"BLADERF=yes"
|
||||||
|
"PLUTOSDR=yes"
|
||||||
|
"AIRCRAFT_HASH_BITS=12"
|
||||||
|
];
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p $out/bin
|
||||||
|
install -D readsb $out/bin
|
||||||
|
install -D viewadsb $out/bin
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
}
|
28
packages/default.nix
Normal file
28
packages/default.nix
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
{ self, flake-utils, nixpkgs }: flake-utils.lib.eachDefaultSystem (
|
||||||
|
system:
|
||||||
|
let
|
||||||
|
pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
packages = {
|
||||||
|
dump1090-fa = import ./dump1090-fa.nix { inherit pkgs; };
|
||||||
|
dump978-fa = import ./dump978-fa.nix { inherit pkgs; };
|
||||||
|
tcllauncher = import ./tcllauncher.nix { inherit pkgs; };
|
||||||
|
mutability-mlat-client = import ./mutability-mlat-client.nix { inherit pkgs; };
|
||||||
|
piaware = import ./piaware.nix {
|
||||||
|
inherit pkgs;
|
||||||
|
dump1090-fa = self.packages.${system}.dump1090-fa;
|
||||||
|
dump978-fa = self.packages.${system}.dump978-fa;
|
||||||
|
tcllauncher = self.packages.${system}.tcllauncher;
|
||||||
|
mutability-mlat-client = self.packages.${system}.mutability-mlat-client;
|
||||||
|
};
|
||||||
|
adsbexchange-mlat-client = import ./adsbexchange-mlat-client.nix { inherit pkgs; };
|
||||||
|
adsbexchange-readsb = import ./adsbexchange-readsb.nix { inherit pkgs; };
|
||||||
|
adsbfi-mlat-client = import ./adsbfi-mlat-client.nix { inherit pkgs; };
|
||||||
|
adsbfi-readsb = import ./adsbfi-readsb.nix { inherit pkgs; };
|
||||||
|
tar1090 = import ./tar1090.nix { inherit pkgs; };
|
||||||
|
};
|
||||||
|
}
|
||||||
|
)
|
58
packages/dump1090-fa.nix
Normal file
58
packages/dump1090-fa.nix
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
pname = "dump1090-fa";
|
||||||
|
version = "8.2";
|
||||||
|
in
|
||||||
|
pkgs.stdenv.mkDerivation {
|
||||||
|
inherit pname version;
|
||||||
|
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "flightaware";
|
||||||
|
repo = "dump1090";
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-SUvK9XTXIDimEMEnORnp/Af/F030TZTxLI43Jzz31Js=";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = [ "out" "html" ];
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.pkg-config
|
||||||
|
];
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
pkgs.ncurses
|
||||||
|
pkgs.librtlsdr
|
||||||
|
pkgs.libbladeRF
|
||||||
|
pkgs.limesuite
|
||||||
|
pkgs.hackrf
|
||||||
|
];
|
||||||
|
buildFlags = [
|
||||||
|
"DUMP1090_VERSION=v${version}"
|
||||||
|
"CPUFEATURES=yes"
|
||||||
|
"showconfig"
|
||||||
|
"dump1090"
|
||||||
|
"faup1090"
|
||||||
|
"view1090"
|
||||||
|
];
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p $out/bin
|
||||||
|
install -D dump1090 $out/bin
|
||||||
|
install -D faup1090 $out/bin
|
||||||
|
install -D view1090 $out/bin
|
||||||
|
mkdir -p $html
|
||||||
|
cp -a public_html/* $html
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
meta = with pkgs.lib; {
|
||||||
|
homepage = "https://github.com/flightaware/dump1090";
|
||||||
|
description = "A ADS-B, Mode S, and Mode 3A/3C demodulator and decoder.";
|
||||||
|
longDescription = ''
|
||||||
|
dump1090-fa is a ADS-B, Mode S, and Mode 3A/3C demodulator and decoder that will receive and decode aircraft transponder messages received via a directly connected software defined radio, or from data provided over a network connection.
|
||||||
|
|
||||||
|
It is the successor to dump1090-mutability and is maintained by FlightAware.
|
||||||
|
|
||||||
|
It can provide a display of locally received aircraft data in a terminal or via a browser map. Together with PiAware it can be used to contribute crowd-sourced flight tracking data to FlightAware.
|
||||||
|
'';
|
||||||
|
license = licenses.gpl2Plus;
|
||||||
|
};
|
||||||
|
}
|
52
packages/dump978-fa.nix
Normal file
52
packages/dump978-fa.nix
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
pname = "dump978-fa";
|
||||||
|
version = "8.2";
|
||||||
|
in
|
||||||
|
pkgs.stdenv.mkDerivation {
|
||||||
|
inherit pname version;
|
||||||
|
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "flightaware";
|
||||||
|
repo = "dump978";
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-6LPshYbI/lLcjR/xP7DHFza2xVcfiAzh66Y7w95YDjk=";
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs = [ "out" "html" ];
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
# pkgs.autoPatchelfHook
|
||||||
|
pkgs.pkg-config
|
||||||
|
];
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
pkgs.boost
|
||||||
|
pkgs.soapysdr
|
||||||
|
];
|
||||||
|
buildFlags = [
|
||||||
|
"VERSION=v${version}"
|
||||||
|
"dump978-fa"
|
||||||
|
"faup978"
|
||||||
|
"skyaware978"
|
||||||
|
];
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p $out/bin
|
||||||
|
install -D dump978-fa $out/bin
|
||||||
|
install -D faup978 $out/bin
|
||||||
|
install -D skyaware978 $out/bin
|
||||||
|
mkdir -p $html
|
||||||
|
cp -a skyaware/* $html
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
meta = with pkgs.lib; {
|
||||||
|
homepage = "https://github.com/flightaware/dump978";
|
||||||
|
description = "The FlightAware 978MHz UAT decoder..";
|
||||||
|
longDescription = ''
|
||||||
|
This is the FlightAware 978MHz UAT decoder.
|
||||||
|
|
||||||
|
It is a reimplementation in C++, loosely based on the demodulator from https://github.com/mutability/dump978.
|
||||||
|
'';
|
||||||
|
license = licenses.bsd2;
|
||||||
|
};
|
||||||
|
}
|
14
packages/mutability-mlat-client.nix
Normal file
14
packages/mutability-mlat-client.nix
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
pname = "mlat-client";
|
||||||
|
version = "0.2.12";
|
||||||
|
in
|
||||||
|
pkgs.python3.pkgs.buildPythonApplication {
|
||||||
|
inherit pname version;
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "mutability";
|
||||||
|
repo = pname;
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "sha256-kU7DJ6lPwz+mVlp4g7rDz0TTSzsZvd/KxjHbYsDFLPI=";
|
||||||
|
};
|
||||||
|
}
|
91
packages/piaware.nix
Normal file
91
packages/piaware.nix
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
{ pkgs, dump1090-fa, dump978-fa, tcllauncher, mutability-mlat-client, ... }:
|
||||||
|
let
|
||||||
|
pname = "piaware";
|
||||||
|
version = "8.2";
|
||||||
|
in
|
||||||
|
pkgs.stdenv.mkDerivation {
|
||||||
|
inherit pname version;
|
||||||
|
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "flightaware";
|
||||||
|
repo = "piaware";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "sha256-La0J+6Y0cWr6fTr0ppzYV6Vq00GisyDxmSyGzR7nfpg=";
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.makeWrapper
|
||||||
|
pkgs.which
|
||||||
|
];
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
pkgs.coreutils
|
||||||
|
pkgs.iproute2
|
||||||
|
pkgs.openssl
|
||||||
|
pkgs.tcl
|
||||||
|
pkgs.tcltls
|
||||||
|
pkgs.tclx
|
||||||
|
tcllauncher
|
||||||
|
];
|
||||||
|
dontPatch = true;
|
||||||
|
dontConfigure = true;
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
|
||||||
|
substituteInPlace programs/piaware/login.tcl \
|
||||||
|
--replace /bin/uname ${pkgs.coreutils}/bin/uname
|
||||||
|
|
||||||
|
substituteInPlace programs/piaware/helpers.tcl \
|
||||||
|
--replace /bin/uname ${pkgs.coreutils}/bin/uname
|
||||||
|
|
||||||
|
substituteInPlace programs/piaware/update.tcl \
|
||||||
|
--replace /sbin/reboot ${pkgs.systemd}/bin/reboot \
|
||||||
|
--replace /sbin/halt ${pkgs.systemd}/bin/halt
|
||||||
|
|
||||||
|
substituteInPlace programs/piaware/faup1090.tcl \
|
||||||
|
--replace /usr/lib/piaware/helpers/faup1090 ${dump1090-fa}/bin/faup1090
|
||||||
|
|
||||||
|
substituteInPlace programs/piaware/faup978.tcl \
|
||||||
|
--replace /usr/lib/piaware/helpers/faup978 ${dump978-fa}/bin/faup978
|
||||||
|
|
||||||
|
substituteInPlace programs/piaware/mlat.tcl \
|
||||||
|
--replace /usr/lib/piaware/helpers/fa-mutability-mlat-client ${mutability-mlat-client}/bin/fa-mutability-mlat-client
|
||||||
|
|
||||||
|
substituteInPlace package/fa_sysinfo.tcl \
|
||||||
|
--replace /sbin/ip ${pkgs.iproute2}/bin/ip \
|
||||||
|
--replace /bin/df ${pkgs.coreutils}/bin/df
|
||||||
|
|
||||||
|
substituteInPlace package/piaware.tcl \
|
||||||
|
--replace "list netstat --program" "list ${pkgs.nettools}/bin/netstat --program"
|
||||||
|
|
||||||
|
substituteInPlace package/helpers/restart-network \
|
||||||
|
--replace /bin/systemctl ${pkgs.systemd}/bin/systemctl
|
||||||
|
|
||||||
|
substituteInPlace package/helpers/restart-receiver \
|
||||||
|
--replace /bin/systemctl ${pkgs.systemd}/bin/systemctl
|
||||||
|
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
installFlags = [
|
||||||
|
''DESTDIR=''${out}''
|
||||||
|
"PREFIX=/"
|
||||||
|
"INSTALL_SUDOERS=1"
|
||||||
|
];
|
||||||
|
postFixup =
|
||||||
|
let
|
||||||
|
tcllibpath = "$out/lib ${tcllauncher}/lib ${pkgs.tcl}/lib ${pkgs.tclx}/lib ${pkgs.tcltls}/lib ${pkgs.tcllib}/lib";
|
||||||
|
in
|
||||||
|
''
|
||||||
|
for f in piaware piaware-config piaware-status pirehose
|
||||||
|
do
|
||||||
|
ln -sf ${tcllauncher}/bin/tcllauncher $out/bin/$f
|
||||||
|
wrapProgram $out/bin/$f \
|
||||||
|
--set TCLLIBPATH "${tcllibpath}"
|
||||||
|
done
|
||||||
|
'';
|
||||||
|
meta = with pkgs.lib; {
|
||||||
|
homepage = "https://github.com/flightaware/piaware";
|
||||||
|
description = "";
|
||||||
|
longDescription = '' '';
|
||||||
|
license = licenses.gpl2Plus;
|
||||||
|
};
|
||||||
|
}
|
24
packages/tar1090.nix
Normal file
24
packages/tar1090.nix
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
pname = "tar1090";
|
||||||
|
version = "0.0";
|
||||||
|
in
|
||||||
|
pkgs.stdenvNoCC.mkDerivation {
|
||||||
|
inherit pname version;
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "wiedehopf";
|
||||||
|
repo = pname;
|
||||||
|
rev = "3c6a15369c4da2e327d08f7f57373abdf02c6812";
|
||||||
|
sha256 = "sha256-R4K4AxFQdy+Cc9gTVIpmU7r2ghiaDxxpFJcLUTwlhWY=";
|
||||||
|
};
|
||||||
|
dontPatch = true;
|
||||||
|
dontConfigure = true;
|
||||||
|
dontBuild = true;
|
||||||
|
dontFixup = true;
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p $out/html
|
||||||
|
cp -av html/* $out/html
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
}
|
63
packages/tcllauncher.nix
Normal file
63
packages/tcllauncher.nix
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
{ pkgs, ... }:
|
||||||
|
let
|
||||||
|
pname = "tcllauncher";
|
||||||
|
version = "1.10";
|
||||||
|
in
|
||||||
|
pkgs.stdenv.mkDerivation {
|
||||||
|
inherit pname version;
|
||||||
|
|
||||||
|
src = pkgs.fetchFromGitHub {
|
||||||
|
owner = "flightaware";
|
||||||
|
repo = pname;
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "sha256-BVrsoczKeBBoM1Q3v6EJY81QwsX6xbUqFkcBb482WH4=";
|
||||||
|
};
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.autoconf
|
||||||
|
pkgs.makeBinaryWrapper
|
||||||
|
];
|
||||||
|
propagatedBuildInputs = [
|
||||||
|
pkgs.tcl
|
||||||
|
pkgs.tclx
|
||||||
|
pkgs.tcllib
|
||||||
|
];
|
||||||
|
dontPatch = true;
|
||||||
|
preConfigure = ''
|
||||||
|
autoconf
|
||||||
|
'';
|
||||||
|
configureFlags = [
|
||||||
|
"--with-tcl=${pkgs.tcl}/lib"
|
||||||
|
];
|
||||||
|
buildFlags = [
|
||||||
|
''pkglibdir=''${out}/lib''
|
||||||
|
];
|
||||||
|
installFlags = [
|
||||||
|
''DESTDIR=''${out}''
|
||||||
|
"bindir=/bin"
|
||||||
|
"includedir=/include"
|
||||||
|
"mandir=/share/man"
|
||||||
|
"pkglibdir=/lib"
|
||||||
|
];
|
||||||
|
# postFixup = ''
|
||||||
|
# wrapProgram $out/bin/tcllauncher \
|
||||||
|
# --set TCLLIBPATH "${pkgs.tcl}/lib ${pkgs.tclx}/lib"
|
||||||
|
# '';
|
||||||
|
# buildFlags = [
|
||||||
|
# "DUMP1090_VERSION=${version}"
|
||||||
|
# "CPUFEATURES=yes"
|
||||||
|
# ];
|
||||||
|
# installPhase = ''
|
||||||
|
# runHook preInstall
|
||||||
|
# mkdir -p $out
|
||||||
|
# make DESTDIR=$out install
|
||||||
|
# runHook postInstall
|
||||||
|
# '';
|
||||||
|
meta = with pkgs.lib; {
|
||||||
|
homepage = "https://flightaware.github.io/tcllauncher/";
|
||||||
|
description = "Launcher program for Tcl applications.";
|
||||||
|
longDescription = ''
|
||||||
|
tcllauncher is a way to have Tcl programs run out of /usr/local/bin under their own name, be installed in one place with their support files, and provides commands to facilitate server-oriented application execution.
|
||||||
|
'';
|
||||||
|
license = licenses.gpl2Plus;
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue