Add chrony SOCK refclock and initial UCCM source

This commit is contained in:
Keenan Tims 2022-11-22 12:12:09 -08:00
parent 116f9b1cec
commit 90958a4046
Signed by: ktims
GPG Key ID: 11230674D69038D4
9 changed files with 808 additions and 289 deletions

463
Cargo.lock generated
View File

@ -3,10 +3,31 @@
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.19"
name = "CoreFoundation-sys"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
checksum = "d0e9889e6db118d49d88d84728d0e964d973a5680befb5f85f55141beea5c20b"
dependencies = [
"libc",
"mach 0.1.2",
]
[[package]]
name = "IOKit-sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99696c398cbaf669d2368076bdb3d627fb0ce51a26899d7c61228c5c0af3bf4a"
dependencies = [
"CoreFoundation-sys",
"libc",
"mach 0.1.2",
]
[[package]]
name = "aho-corasick"
version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
dependencies = [
"memchr",
]
@ -121,16 +142,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
[[package]]
name = "bytes"
version = "1.2.1"
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
[[package]]
name = "cc"
version = "1.0.74"
version = "1.0.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574"
checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
[[package]]
name = "cfg-if"
@ -143,6 +170,10 @@ name = "chimemon"
version = "0.1.0"
dependencies = [
"async-trait",
"bitflags",
"byteorder",
"bytes",
"chrono",
"chrony-candm",
"clap",
"env_logger",
@ -150,18 +181,20 @@ dependencies = [
"futures",
"gethostname",
"influxdb2",
"libc",
"log",
"serde",
"serde_derive",
"tokio",
"tokio-serial",
"tokio-stream",
]
[[package]]
name = "chrono"
version = "0.4.22"
version = "0.4.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
dependencies = [
"iana-time-zone",
"js-sys",
@ -203,9 +236,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.0.18"
version = "4.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "335867764ed2de42325fafe6d18b8af74ba97ee0c590fa016f157535b42ab04b"
checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e"
dependencies = [
"atty",
"bitflags",
@ -218,9 +251,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.0.18"
version = "4.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16a1b0f6422af32d5da0c58e2703320f379216ee70198241c84173a8c5ac28f3"
checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
dependencies = [
"heck",
"proc-macro-error",
@ -248,16 +281,6 @@ dependencies = [
"unicode-width",
]
[[package]]
name = "core-foundation"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
@ -288,9 +311,9 @@ dependencies = [
[[package]]
name = "cxx"
version = "1.0.80"
version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a"
checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453"
dependencies = [
"cc",
"cxxbridge-flags",
@ -300,9 +323,9 @@ dependencies = [
[[package]]
name = "cxx-build"
version = "1.0.80"
version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827"
checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0"
dependencies = [
"cc",
"codespan-reporting",
@ -315,15 +338,15 @@ dependencies = [
[[package]]
name = "cxxbridge-flags"
version = "1.0.80"
version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a"
checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71"
[[package]]
name = "cxxbridge-macro"
version = "1.0.80"
version = "1.0.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7"
checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470"
dependencies = [
"proc-macro2",
"quote",
@ -369,9 +392,9 @@ dependencies = [
[[package]]
name = "env_logger"
version = "0.9.1"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272"
checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
dependencies = [
"atty",
"humantime",
@ -414,21 +437,6 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "form_urlencoded"
version = "1.1.0"
@ -648,9 +656,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyper"
version = "0.14.22"
version = "0.14.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abfba89e19b959ca163c7752ba59d737c1ceea53a5d31a149c805446fc958064"
checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c"
dependencies = [
"bytes",
"futures-channel",
@ -670,19 +678,6 @@ dependencies = [
"want",
]
[[package]]
name = "hyper-tls"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905"
dependencies = [
"bytes",
"hyper",
"native-tls",
"tokio",
"tokio-native-tls",
]
[[package]]
name = "iana-time-zone"
version = "0.1.53"
@ -719,9 +714,9 @@ dependencies = [
[[package]]
name = "indexmap"
version = "1.9.1"
version = "1.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
dependencies = [
"autocfg",
"hashbrown",
@ -794,9 +789,9 @@ dependencies = [
[[package]]
name = "ipnet"
version = "2.5.0"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b"
checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745"
[[package]]
name = "itertools"
@ -881,6 +876,24 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "mach"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd13ee2dd61cc82833ba05ade5a30bb3d63f7ced605ef827063c63078302de9"
dependencies = [
"libc",
]
[[package]]
name = "mach"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
dependencies = [
"libc",
]
[[package]]
name = "matchers"
version = "0.0.1"
@ -896,6 +909,15 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "mime"
version = "0.3.16"
@ -911,25 +933,45 @@ dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.42.0",
"windows-sys",
]
[[package]]
name = "native-tls"
version = "0.2.10"
name = "mio-serial"
version = "5.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9"
checksum = "dff736ea7e2501db099ae3f82aabc14db416a01958c8354b3f353dd961a18773"
dependencies = [
"lazy_static",
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
"mio",
"nix 0.25.0",
"serialport",
"winapi",
]
[[package]]
name = "nix"
version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc"
dependencies = [
"bitflags",
"cfg-if",
"libc",
]
[[package]]
name = "nix"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e322c04a9e3440c327fca7b6c8a63e6890a32fa2ad689db972425f07e0d22abb"
dependencies = [
"autocfg",
"bitflags",
"cfg-if",
"libc",
"memoffset",
"pin-utils",
]
[[package]]
@ -966,9 +1008,9 @@ dependencies = [
[[package]]
name = "num_cpus"
version = "1.13.1"
version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
dependencies = [
"hermit-abi",
"libc",
@ -1001,51 +1043,6 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
[[package]]
name = "openssl"
version = "0.10.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12fc0523e3bd51a692c8850d075d74dc062ccf251c0110668cbd921917118a13"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "openssl-probe"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
name = "openssl-sys"
version = "0.9.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b03b84c3b2d099b81f0953422b4d4ad58761589d0229b5506356afca05a3670a"
dependencies = [
"autocfg",
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "opentelemetry"
version = "0.13.0"
@ -1068,18 +1065,18 @@ dependencies = [
[[package]]
name = "ordered-float"
version = "3.3.0"
version = "3.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f74e330193f90ec45e2b257fa3ef6df087784157ac1ad2c1e71c62837b03aa7"
checksum = "d84eb1409416d254e4a9c8fa56cc24701755025b458f0fcd8e59e1f5f40c23bf"
dependencies = [
"num-traits",
]
[[package]]
name = "os_str_bytes"
version = "6.3.1"
version = "6.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3baf96e39c5359d2eb0dd6ccb42c62b91d9678aa68160d261b9e0ccbf9e9dea9"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
[[package]]
name = "parking_lot"
@ -1144,17 +1141,11 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "ppv-lite86"
version = "0.2.16"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro-crate"
@ -1256,9 +1247,9 @@ dependencies = [
[[package]]
name = "regex"
version = "1.6.0"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
dependencies = [
"aho-corasick",
"memchr",
@ -1276,9 +1267,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.6.27"
version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "remove_dir_all"
@ -1291,9 +1282,9 @@ dependencies = [
[[package]]
name = "reqwest"
version = "0.11.12"
version = "0.11.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc"
checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c"
dependencies = [
"base64",
"bytes",
@ -1304,20 +1295,18 @@ dependencies = [
"http",
"http-body",
"hyper",
"hyper-tls",
"ipnet",
"js-sys",
"log",
"mime",
"native-tls",
"once_cell",
"percent-encoding",
"pin-project-lite",
"rustls",
"serde",
"serde_json",
"serde_urlencoded",
"tokio",
"tokio-native-tls",
"tokio-util",
"tower-service",
"url",
@ -1327,22 +1316,39 @@ dependencies = [
"winreg",
]
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin",
"untrusted",
"web-sys",
"winapi",
]
[[package]]
name = "rustls"
version = "0.20.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c"
dependencies = [
"log",
"ring",
"sct",
"webpki",
]
[[package]]
name = "ryu"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "schannel"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2"
dependencies = [
"lazy_static",
"windows-sys 0.36.1",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
@ -1356,26 +1362,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898"
[[package]]
name = "security-framework"
version = "2.7.0"
name = "sct"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c"
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
dependencies = [
"bitflags",
"core-foundation",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
dependencies = [
"core-foundation-sys",
"libc",
"ring",
"untrusted",
]
[[package]]
@ -1400,9 +1393,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.87"
version = "1.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45"
checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
dependencies = [
"itoa 1.0.4",
"ryu",
@ -1432,6 +1425,22 @@ dependencies = [
"serde",
]
[[package]]
name = "serialport"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aab92efb5cf60ad310548bc3f16fa6b0d950019cb7ed8ff41968c3d03721cf12"
dependencies = [
"CoreFoundation-sys",
"IOKit-sys",
"bitflags",
"cfg-if",
"mach 0.3.2",
"nix 0.24.2",
"regex",
"winapi",
]
[[package]]
name = "sharded-slab"
version = "0.1.4"
@ -1493,6 +1502,12 @@ dependencies = [
"winapi",
]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "static_assertions"
version = "1.1.0"
@ -1602,9 +1617,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
version = "1.21.2"
version = "1.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099"
checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3"
dependencies = [
"autocfg",
"bytes",
@ -1629,12 +1644,15 @@ dependencies = [
]
[[package]]
name = "tokio-native-tls"
version = "0.3.0"
name = "tokio-serial"
version = "5.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b"
checksum = "aa6e2e4cf0520a99c5f87d5abb24172b5bd220de57c3181baaaa5440540c64aa"
dependencies = [
"native-tls",
"cfg-if",
"futures",
"log",
"mio-serial",
"tokio",
]
@ -1786,6 +1804,12 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "url"
version = "2.3.1"
@ -1803,12 +1827,6 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version_check"
version = "0.9.4"
@ -1913,6 +1931,16 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "webpki"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "winapi"
version = "0.3.9"
@ -1944,19 +1972,6 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
"windows_aarch64_msvc 0.36.1",
"windows_i686_gnu 0.36.1",
"windows_i686_msvc 0.36.1",
"windows_x86_64_gnu 0.36.1",
"windows_x86_64_msvc 0.36.1",
]
[[package]]
name = "windows-sys"
version = "0.42.0"
@ -1964,12 +1979,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc 0.42.0",
"windows_i686_gnu 0.42.0",
"windows_i686_msvc 0.42.0",
"windows_x86_64_gnu 0.42.0",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc 0.42.0",
"windows_x86_64_msvc",
]
[[package]]
@ -1978,48 +1993,24 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_aarch64_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_gnu"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_i686_msvc"
version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_gnu"
version = "0.42.0"
@ -2032,12 +2023,6 @@ version = "0.42.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]]
name = "windows_x86_64_msvc"
version = "0.42.0"

View File

@ -6,8 +6,10 @@ edition = "2021"
[dependencies]
serde = "1.0"
serde_derive = "1.0"
influxdb2 = "0.3.3"
tokio = { version = "1", features = ["rt"] }
influxdb2 = { version = "0.3.3", features = [
"rustls",
], default-features = false }
tokio = { version = "1", features = ["rt", "io-util"] }
clap = { version = "4.0", features = ["derive"] }
log = "0.4"
figment = { version = "0.10", features = ["toml"] }
@ -16,6 +18,12 @@ env_logger = "0.9.1"
futures = "0.3.24"
async-trait = "0.1.58"
tokio-stream = { version = "0.1.11", features = ["sync"] }
bitflags = "1.3.2"
byteorder = "1.4.3"
tokio-serial = "5.4.4"
bytes = "1.2.1"
chrono = "0.4.23"
libc = "0.2.137"
[dependencies.chrony-candm]
git = "https://github.com/aws/chrony-candm"

View File

@ -18,6 +18,11 @@
name = "hwmon0"
sensor = "temp1_input"
[targets]
[targets.chrony]
enabled = true
sock = "/tmp/uccm.sock"
[influxdb]
url = "http://localhost:8086"
org = "default"

View File

@ -3,7 +3,7 @@ use chimemon::{ChimemonSource, ChimemonSourceChannel, Config};
use chrony_candm::reply::{self, ReplyBody, SourceMode};
use chrony_candm::request::{self, RequestBody};
use influxdb2::models::DataPoint;
use log::{info, warn};
use log::{debug, info, warn};
use std::net::{SocketAddr, ToSocketAddrs};
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use tokio::runtime::Handle;
@ -77,8 +77,8 @@ pub fn datapoint_from_sourcedata(
reply::SourceState::NonSelectable => String::from("unusable"),
reply::SourceState::Falseticker => String::from("falseticker"),
reply::SourceState::Jittery => String::from("jittery"),
reply::SourceState::Unselected => String::from("unused"),
reply::SourceState::Selectable => String::from("combined"),
reply::SourceState::Unselected => String::from("combined"),
reply::SourceState::Selectable => String::from("unused"),
},
)
.field("poll", d.poll as i64)
@ -208,9 +208,9 @@ impl ChronyClient {
let tracking_data = datapoint_from_tracking(&tracking, &self.config)?;
info!("Writing tracking data: {:?}", tracking_data);
info!("Sending tracking data");
chan.send(tracking_data)
chan.send(tracking_data.into())
.expect("Unable to send tracking data to targets");
Ok(())
@ -221,19 +221,21 @@ impl ChronyClient {
chan: &ChimemonSourceChannel,
) -> Result<(), Box<dyn std::error::Error>> {
let sources = self.get_sources().await?;
let mut dps = Vec::with_capacity(sources.len());
for ds in sources {
let source_data = datapoint_from_sourcedata(&ds, &self.config)?;
info!("Writing source data: {:?}", source_data);
chan.send(source_data)
.expect("Unable to send source data to targets");
dps.push(source_data);
}
info!("Sending source data");
chan.send(dps.into())
.expect("Unable to send source data to targets");
Ok(())
}
}
#[async_trait]
impl ChimemonSource for ChronyClient {
async fn run(self, chan: tokio::sync::broadcast::Sender<DataPoint>) {
async fn run(self, chan: ChimemonSourceChannel) {
info!("Chrony task started");
let mut t_interval = tokio::time::interval(Duration::from_secs(

76
src/chrony_refclock.rs Normal file
View File

@ -0,0 +1,76 @@
use async_trait::async_trait;
use chimemon::{ChimemonMessage, ChimemonTarget, ChimemonTargetChannel, ChronySockConfig};
use libc::{c_double, c_int, timeval};
use log::debug;
use std::io::prelude::*;
use std::mem;
use std::os::unix::net::UnixDatagram;
use std::path::Path;
const CHRONY_MAGIC: c_int = 0x534f434b;
pub struct ChronySockServer {
sock: UnixDatagram,
}
#[repr(C)]
#[derive(Debug)]
pub struct ChronyTimeReport {
tv: timeval,
offset: c_double,
pulse: c_int,
leap: c_int,
_pad: c_int,
magic: c_int,
}
impl ChronySockServer {
pub fn new(config: ChronySockConfig) -> Self {
debug!(
"Size of chrony refclock report: {}",
mem::size_of::<ChronyTimeReport>()
);
let sock = UnixDatagram::unbound().unwrap();
// TODO: Don't connect to the socket or we break when chrony restarts
// use sock.send_to instead and fail gracefully
sock.connect(&config.sock).expect("Unable to open socket");
ChronySockServer { sock }
}
}
#[async_trait]
impl ChimemonTarget for ChronySockServer {
async fn run(mut self, mut chan: ChimemonTargetChannel) {
loop {
let msg = chan.recv().await.unwrap();
match msg {
ChimemonMessage::TimeReport(tr) => {
if tr.valid {
{
let frame = ChronyTimeReport {
tv: timeval {
tv_sec: tr.system_time.timestamp().try_into().unwrap_or_default(),
tv_usec: tr.system_time.timestamp_subsec_micros().try_into().unwrap_or_default(),
},
offset: tr.offset.num_nanoseconds().unwrap() as f64 / 1e9,
leap: if tr.leap_flag { 1 } else { 0 },
pulse: 0,
_pad: 0,
magic: CHRONY_MAGIC,
};
unsafe {
let bs = std::slice::from_raw_parts(
(&frame as *const ChronyTimeReport) as *const u8,
mem::size_of::<ChronyTimeReport>(),
);
debug!("Sending to chrony sock {:#?}", frame);
self.sock.send(bs).unwrap();
};
}
}
}
_ => continue,
}
}
}
}

View File

@ -4,7 +4,7 @@ use futures::{stream, StreamExt};
use influxdb2::models::DataPoint;
use log::{debug, info};
use std::{
path::{Path, PathBuf},
path::PathBuf,
time::{Duration, SystemTime, UNIX_EPOCH},
};
@ -47,37 +47,35 @@ impl HwmonSource {
#[async_trait]
impl ChimemonSource for HwmonSource {
async fn run(self, chan: tokio::sync::broadcast::Sender<DataPoint>) {
async fn run(self, chan: ChimemonSourceChannel) {
info!("hwmon task started");
let mut interval =
tokio::time::interval(Duration::from_secs(self.config.sources.hwmon.interval));
loop {
interval.tick().await;
stream::iter(&self.sensors)
.for_each_concurrent(None, |s| async {
let sensor_val = HwmonSource::get_raw_value(s)
.await
.expect("Unable to read sensor");
debug!(
"hwmon {} raw value {}",
s.path.to_string_lossy(),
sensor_val
);
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let mut builder =
DataPoint::builder(&s.device).timestamp(now.as_nanos().try_into().unwrap());
for (key, value) in &self.config.influxdb.tags {
builder = builder.tag(key, value)
}
builder = builder
.tag("sensor", &s.name)
.field("value", sensor_val.trim().parse::<i64>().unwrap());
let dp = builder.build().unwrap();
info!("Writing hwmon data: {:?}", dp);
chan.send(dp).unwrap();
})
.await;
let s = stream::iter(&self.sensors).then(|s| async {
let sensor_val = HwmonSource::get_raw_value(s)
.await
.expect("Unable to read sensor");
debug!(
"hwmon {} raw value {}",
s.path.to_string_lossy(),
sensor_val
);
let now = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
let mut builder =
DataPoint::builder(&s.device).timestamp(now.as_nanos().try_into().unwrap());
for (key, value) in &self.config.influxdb.tags {
builder = builder.tag(key, value)
}
builder = builder
.tag("sensor", &s.name)
.field("value", sensor_val.trim().parse::<i64>().unwrap());
builder.build().unwrap()
});
info!("Writing hwmon data");
chan.send(s.collect::<Vec<DataPoint>>().await.into())
.unwrap();
}
}
}

View File

@ -1,6 +1,7 @@
use async_trait::async_trait;
use chrono::NaiveDateTime;
use figment::{
providers::{Format, Serialized, Toml},
providers::{Data, Format, Serialized, Toml},
util::map,
value::Map,
Figment,
@ -8,7 +9,7 @@ use figment::{
use gethostname::gethostname;
use influxdb2::models::DataPoint;
use serde_derive::{Deserialize, Serialize};
use std::path::Path;
use std::{path::Path, time::Duration};
use tokio::sync::broadcast::*;
#[derive(Serialize, Deserialize, Clone)]
@ -60,6 +61,21 @@ impl Default for ChronyConfig {
}
}
#[derive(Serialize, Deserialize, Clone)]
pub struct ChronySockConfig {
pub enabled: bool,
pub sock: String,
}
impl Default for ChronySockConfig {
fn default() -> Self {
ChronySockConfig {
enabled: false,
sock: "".into(),
}
}
}
#[derive(Serialize, Deserialize, Clone)]
pub struct HwmonSensorConfig {
pub name: String,
@ -84,25 +100,85 @@ impl Default for HwmonConfig {
}
}
}
#[derive(Clone, Debug)]
pub struct TimeReport {
pub system_time: NaiveDateTime,
pub offset: chrono::Duration,
pub leaps: isize,
pub leap_flag: bool,
pub valid: bool,
}
#[derive(Serialize, Deserialize, Clone)]
pub struct UCCMConfig {
pub enabled: bool,
pub port: String,
pub baud: u32,
pub status_interval: std::time::Duration,
pub timeout: std::time::Duration,
}
impl Default for UCCMConfig {
fn default() -> Self {
UCCMConfig {
enabled: false,
port: "/dev/ttyS0".into(),
baud: 57600,
status_interval: std::time::Duration::from_secs(10),
timeout: std::time::Duration::from_secs(1),
}
}
}
#[derive(Serialize, Deserialize, Clone, Default)]
pub struct SourcesConfig {
pub chrony: ChronyConfig,
pub hwmon: HwmonConfig,
pub uccm: UCCMConfig,
}
#[derive(Serialize, Deserialize, Clone, Default)]
pub struct TargetsConfig {
pub chrony: ChronySockConfig,
}
#[derive(Serialize, Deserialize, Clone, Default)]
pub struct Config {
pub influxdb: InfluxConfig,
pub sources: SourcesConfig,
pub targets: TargetsConfig,
}
pub fn load_config(filename: &Path) -> Figment {
Figment::from(Serialized::defaults(Config::default())).merge(Toml::file(filename))
}
pub type ChimemonSourceChannel = Sender<DataPoint>;
pub type ChimemonTargetChannel = Receiver<DataPoint>;
#[derive(Clone, Debug)]
pub enum ChimemonMessage {
DataPoint(DataPoint),
DataPoints(Vec<DataPoint>),
TimeReport(TimeReport),
}
impl From<DataPoint> for ChimemonMessage {
fn from(dp: DataPoint) -> Self {
ChimemonMessage::DataPoint(dp)
}
}
impl From<Vec<DataPoint>> for ChimemonMessage {
fn from(dps: Vec<DataPoint>) -> Self {
ChimemonMessage::DataPoints(dps)
}
}
impl From<TimeReport> for ChimemonMessage {
fn from(tr: TimeReport) -> Self {
ChimemonMessage::TimeReport(tr)
}
}
pub type ChimemonSourceChannel = Sender<ChimemonMessage>;
pub type ChimemonTargetChannel = Receiver<ChimemonMessage>;
#[async_trait]
pub trait ChimemonSource {

View File

@ -1,14 +1,16 @@
mod chrony;
mod chrony_refclock;
mod hwmon;
mod uccm;
use clap::{Parser, ValueEnum};
use env_logger::{self, Env};
use futures::{future::join_all, prelude::*};
use log::{error, info, warn};
use log::{debug, error, info, warn};
use std::path::Path;
use tokio::sync::broadcast;
use crate::{chrony::*, hwmon::HwmonSource};
use crate::{chrony::*, chrony_refclock::ChronySockServer, hwmon::HwmonSource, uccm::UCCMMonitor};
use chimemon::*;
const PROGRAM_NAME: &str = "chimemon";
@ -79,20 +81,59 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
None
};
match hwmon {
Some(hwmon) => {
Some(hwmon) => {
tasks.push(tokio::spawn(hwmon.run(sourcechan.clone())));
}
None => (),
};
let uccm = if config.sources.uccm.enabled {
Some(UCCMMonitor::new(config.to_owned()))
} else {
None
};
match uccm {
Some(uccm) => {
tasks.push(tokio::spawn(uccm.run(sourcechan.clone())));
}
None => (),
};
let chrony_refclock = if config.targets.chrony.enabled {
Some(ChronySockServer::new(config.targets.chrony.to_owned()))
} else {
None
};
match chrony_refclock {
Some(chrony_refclock) => {
tasks.push(tokio::spawn(chrony_refclock.run(sourcechan.subscribe())));
}
None => (),
};
let mut influxrx = sourcechan.subscribe();
tasks.push(tokio::spawn(async move {
loop {
let dp = influxrx.recv().await.unwrap();
influx
.write(&config.influxdb.bucket, stream::iter([dp]))
.await
.expect("Error writing to influxdb");
let msg = influxrx.recv().await.unwrap();
match msg {
ChimemonMessage::DataPoint(dp) => {
debug!("Writing datapoint to influx: {:?}", dp);
influx
.write(&config.influxdb.bucket, stream::iter([dp]))
.await
.expect("Error writing to influxdb");
}
ChimemonMessage::DataPoints(dps) => {
debug!("Writing datapoints to influx: {:?}", dps);
influx
.write(&config.influxdb.bucket, stream::iter(dps))
.await
.expect("Error writing to influxdb");
}
ChimemonMessage::TimeReport(tr) => {
debug!("GPS TOD: {:?}", tr);
}
}
}
}));

328
src/uccm.rs Normal file
View File

@ -0,0 +1,328 @@
use async_trait::async_trait;
use bitflags::bitflags;
use byteorder::{BigEndian, ReadBytesExt};
use bytes::{Buf, BytesMut};
use chimemon::{
ChimemonMessage, ChimemonSource, ChimemonSourceChannel, Config, TimeReport, UCCMConfig,
};
use chrono::{Duration, NaiveDateTime, Utc};
use log::{debug, info, warn};
use std::io::Cursor;
use std::str;
use std::sync::Arc;
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader, ReadHalf, WriteHalf};
use tokio::join;
use tokio::sync::Mutex;
use tokio::time::{interval, sleep, Interval};
use tokio_serial::{SerialPort, SerialStream};
pub const GPS_EPOCH: i64 = 315964800; // Doesn't seem possible to have a const DateTime object
pub type UccmEndian = BigEndian;
pub enum UCCMMonitorParseState {
Idle,
ReadStatus,
ReadLoopDiag,
ReadTOD,
}
pub struct UCCMMonitor {
// pub port: SerialStream,
rx: ReadHalf<SerialStream>,
tx: WriteHalf<SerialStream>,
pub info: Option<UCCMInfo>,
config: UCCMConfig,
}
#[derive(Debug)]
pub struct UCCMTODReport {
pub time: NaiveDateTime, // TAI timestamp
pub leaps: i8,
pub flags: UCCMFlags,
}
bitflags! {
pub struct UCCMFlags: u32 {
const OSC_LOCK = (1<<29);
const LEAP_FLAG = (1<<25);
const INIT_UNLOCK = (1<<24);
const INIT_NO_SATS = (1<<19);
const HAVE_GPS_TIME = (1<<18);
const POWER_FAIL = (1<<17);
const MODEL_SYMMETRICOM = (1<<15);
const MODEL_TRIMBLE = (1<<14);
const NO_GPS_SYNC = (1<<11);
const NO_GPS_SYNC2 = (1<<9);
const MODEL_SYMMETRICOM2 = (1<<7);
const MODEL_TRIMBLE2 = (1<<6);
const NO_ANT = (1<<5);
const GPS_LOS = (1<<4);
}
}
/* FLAGS:
MSB 31 x
30 ALWAYS 1
29 oscillator locked
28..26 x
25 leap flag
24 initial unlock
23..20 x
19 initialized no sats (trimble)
18 have gps time flag
17 power fail
16 x
15..14 model/protocol ( 01 = trimble 10 = symmetricom )
13..12 x
11 no gps sync
10 always 1
9 no gps sync
8 always 1
7..6 model/protocol ( 01 = trimble 10 = symmetricom )
5 no ant
4 gps los
LSB 3..0 x
*/
#[derive(Debug)]
pub struct GPSSVInfo {
pub tracked: bool,
pub in_view: bool,
pub prn: u8,
pub elevation: usize,
pub azimuth: usize,
pub cn0: usize,
}
#[derive(Debug)]
pub struct UCCMStatusReport {
pub tfom: u8,
pub ffom: u8,
pub gpsPhase: f32,
pub gpsPPSValid: bool,
pub gpsSVs: [GPSSVInfo; 32],
pub gpsTime: NaiveDateTime,
pub antVoltage: f32,
pub antCurrent: f32,
pub temp: f32,
pub efcDac: u32,
pub freqError: f32,
}
pub struct UCCMInfo {
pub vendor: String,
pub model: String,
pub serial: String,
pub version: String,
}
impl TryFrom<&[u8]> for UCCMTODReport {
type Error = String;
fn try_from(strbuf: &[u8]) -> Result<Self, Self::Error> {
debug!("TOD buffer: `{:#?}`", String::from_utf8(strbuf.to_vec()));
let resp: Vec<u8> = strbuf
.split(|c| *c == ' ' as u8)
.map(|x| u8::from_str_radix(str::from_utf8(x).unwrap(), 16).unwrap())
.collect();
let mut rdr = Cursor::new(resp);
// Sync flag
let c = rdr.read_u16::<UccmEndian>().unwrap();
if c != 0xc500 {
return Err(format!("Missing start delimter (got: `{}`)", c));
}
// Consume 25 unknown bytes
rdr.advance(25);
let time = rdr.read_u32::<UccmEndian>().unwrap();
rdr.advance(1); // consume padding
let leaps = rdr.read_i8().unwrap();
let flags = rdr.read_u32::<UccmEndian>().unwrap();
debug!("Flags: {}", flags);
rdr.advance(6); // Consume padding and checksum, don't check it
let c = rdr.read_u8().unwrap();
if c != 0xca {
return Err(format!("Missing end delimiter (got: `{}`)", c));
}
debug!("TOD time: {} leaps: {} flags: {}", time, leaps, flags);
Ok(UCCMTODReport {
time: NaiveDateTime::from_timestamp_opt(GPS_EPOCH + time as i64, 0).unwrap(),
leaps,
flags: UCCMFlags::from_bits_truncate(flags),
})
}
}
impl UCCMMonitor {
pub fn new(config: Config) -> Self {
let builder = tokio_serial::new(&config.sources.uccm.port, config.sources.uccm.baud)
.timeout(config.sources.uccm.timeout)
.data_bits(tokio_serial::DataBits::Eight)
.parity(tokio_serial::Parity::None)
.stop_bits(tokio_serial::StopBits::One)
.flow_control(tokio_serial::FlowControl::None);
let mut port = SerialStream::open(&builder).expect("Must be able to open serial port");
port.set_exclusive(true).expect("Can't lock serial port");
info!(
"Opened serial port {}@{}",
port.name().unwrap(),
port.baud_rate().unwrap()
);
let (rx, tx) = tokio::io::split(port);
UCCMMonitor {
// port,
rx,
tx,
info: None,
config: config.sources.uccm,
}
}
pub async fn send_cmd(&mut self, cmd: &[u8]) -> Result<String, std::io::Error> {
debug!("cmd: `{:?}`", String::from_utf8_lossy(cmd));
self.tx.write_all(cmd).await;
self.tx.write(&[b'\n']).await;
let mut reader = BufReader::new(&mut self.rx);
let mut resp = String::new();
while !resp.contains("UCCM>") {
let mut buf = Vec::new();
reader.read_until(b'>', &mut buf).await;
resp.push_str(&String::from_utf8_lossy(&buf));
}
// Remove the command we sent from the response
resp.replace_range(0..resp.find('\n').unwrap_or(0) + 1, "");
resp = resp.replace("\r", "");
debug!("cmd response: `{:?}`", resp);
Ok(resp)
}
pub async fn get_info(&mut self) -> Result<(), std::io::Error> {
self.send_cmd(b"SCPI").await.unwrap_or_default();
self.send_cmd(b"TOD DI").await.unwrap_or_default();
sleep(tokio::time::Duration::from_secs(1)).await;
let resp = self.send_cmd(b"*IDN?").await.unwrap_or_default();
let info: Vec<&str> = resp.lines().next().unwrap().split(',').collect();
debug!("Response length: {}", info.len());
if info.len() != 4 {
return Err(std::io::Error::new(
std::io::ErrorKind::Unsupported,
"Unexpected *IDN? response",
));
}
self.info = Some(UCCMInfo {
vendor: info[0].into(),
model: info[1].into(),
serial: info[2].into(),
version: info[3].into(),
});
info!(
"Found {} {} s/n: {} version: {}",
self.info.as_ref().unwrap().vendor,
self.info.as_ref().unwrap().model,
self.info.as_ref().unwrap().serial,
self.info.as_ref().unwrap().version
);
Ok(())
}
}
async fn rx_loop(
mut rx: ReadHalf<SerialStream>,
chan: ChimemonSourceChannel,
state: Arc<Mutex<UCCMMonitorParseState>>,
) {
let mut rdbuf = BytesMut::with_capacity(1024);
loop {
match tokio::io::AsyncReadExt::read_buf(&mut rx, &mut rdbuf).await {
Ok(n) => {
if n == 0 {
continue;
}
}
Err(_) => continue,
}
match *state.lock().await {
UCCMMonitorParseState::Idle => {
while !rdbuf.starts_with(b"c5 00") && rdbuf.remaining() > 0 {
rdbuf.advance(1);
}
if rdbuf.len() < (44 * 2 + 43) {
// TOD frame is 44 bytes, plus 43 spaces
continue;
};
let frame = rdbuf.split_to(44 * 2 + 43);
match UCCMTODReport::try_from(&frame[..]) {
Ok(tod) => {
let sysnow = Utc::now().naive_utc();
let offset = tod.time - Duration::seconds(tod.leaps as i64) - sysnow;
debug!("System time: {:#?} GPS time: {:#?} Leaps: {:#?}", sysnow, tod.time, tod.leaps);
debug!("TOD offset: {}ms", offset.num_milliseconds());
info!("{:#?}", tod);
let valid = tod.leaps > 0
&& tod
.flags
.contains(UCCMFlags::OSC_LOCK | UCCMFlags::HAVE_GPS_TIME);
chan.send(ChimemonMessage::TimeReport(TimeReport {
system_time: sysnow,
offset,
leaps: tod.leaps as isize,
leap_flag: if tod.flags.contains(UCCMFlags::LEAP_FLAG) {
true
} else {
false
},
valid,
}))
.expect("Unable to send to channel");
}
Err(e) => {
warn!("Unable to parse TOD frame: {}", e);
rdbuf.clear();
}
}
}
UCCMMonitorParseState::ReadStatus => todo!(),
UCCMMonitorParseState::ReadLoopDiag => todo!(),
UCCMMonitorParseState::ReadTOD => todo!(),
}
}
}
#[async_trait]
impl ChimemonSource for UCCMMonitor {
async fn run(mut self, chan: ChimemonSourceChannel) {
info!("UCCM task starting");
if self.get_info().await.is_err() {
warn!("Error starting UCCM");
return;
}
self.send_cmd(b"SCPI").await.unwrap();
self.send_cmd(b"SYSTem:PRESet").await.unwrap();
self.send_cmd(b"OUTPut:TP:SELection PP1S").await.unwrap();
self.send_cmd(b"TESTMODE EN").await.unwrap();
self.send_cmd(b"TOD EN").await.unwrap();
let state = Arc::new(Mutex::<UCCMMonitorParseState>::new(
UCCMMonitorParseState::Idle,
));
let rx_handle = tokio::spawn(rx_loop(self.rx, chan.clone(), state.clone()));
// let tx_handle = tokio::spawn(async move {
// let mut interval = interval(self.config.status_interval);
// loop {
// interval.tick().await;
// let wfut = self.tx.write_all(b"SYST:STAT?\n");
// *state.lock().await = UCCMMonitorParseState::ReadStatus;
// wfut.await;
// }
// });
join!(rx_handle);
}
}