├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE.md ├── README.md ├── src └── main.rs └── systemd └── system-mqtt.service /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | test.yaml -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "aes" 7 | version = "0.7.5" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" 10 | dependencies = [ 11 | "cfg-if", 12 | "cipher", 13 | "cpufeatures", 14 | "opaque-debug", 15 | ] 16 | 17 | [[package]] 18 | name = "aho-corasick" 19 | version = "0.7.20" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" 22 | dependencies = [ 23 | "memchr", 24 | ] 25 | 26 | [[package]] 27 | name = "anyhow" 28 | version = "1.0.69" 29 | source = "registry+https://github.com/rust-lang/crates.io-index" 30 | checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" 31 | 32 | [[package]] 33 | name = "argh" 34 | version = "0.1.10" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "ab257697eb9496bf75526f0217b5ed64636a9cfafa78b8365c71bd283fcef93e" 37 | dependencies = [ 38 | "argh_derive", 39 | "argh_shared", 40 | ] 41 | 42 | [[package]] 43 | name = "argh_derive" 44 | version = "0.1.10" 45 | source = "registry+https://github.com/rust-lang/crates.io-index" 46 | checksum = "b382dbd3288e053331f03399e1db106c9fb0d8562ad62cb04859ae926f324fa6" 47 | dependencies = [ 48 | "argh_shared", 49 | "proc-macro2", 50 | "quote", 51 | "syn", 52 | ] 53 | 54 | [[package]] 55 | name = "argh_shared" 56 | version = "0.1.10" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | checksum = "64cb94155d965e3d37ffbbe7cc5b82c3dd79dd33bd48e536f73d2cfb8d85506f" 59 | 60 | [[package]] 61 | name = "async-broadcast" 62 | version = "0.5.1" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | checksum = "7c48ccdbf6ca6b121e0f586cbc0e73ae440e56c67c30fa0873b4e110d9c26d2b" 65 | dependencies = [ 66 | "event-listener", 67 | "futures-core", 68 | ] 69 | 70 | [[package]] 71 | name = "async-executor" 72 | version = "1.5.0" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "17adb73da160dfb475c183343c8cccd80721ea5a605d3eb57125f0a7b7a92d0b" 75 | dependencies = [ 76 | "async-lock", 77 | "async-task", 78 | "concurrent-queue", 79 | "fastrand", 80 | "futures-lite", 81 | "slab", 82 | ] 83 | 84 | [[package]] 85 | name = "async-io" 86 | version = "1.12.0" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "8c374dda1ed3e7d8f0d9ba58715f924862c63eae6849c92d3a18e7fbde9e2794" 89 | dependencies = [ 90 | "async-lock", 91 | "autocfg", 92 | "concurrent-queue", 93 | "futures-lite", 94 | "libc", 95 | "log", 96 | "parking", 97 | "polling", 98 | "slab", 99 | "socket2", 100 | "waker-fn", 101 | "windows-sys 0.42.0", 102 | ] 103 | 104 | [[package]] 105 | name = "async-lock" 106 | version = "2.6.0" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "c8101efe8695a6c17e02911402145357e718ac92d3ff88ae8419e84b1707b685" 109 | dependencies = [ 110 | "event-listener", 111 | "futures-lite", 112 | ] 113 | 114 | [[package]] 115 | name = "async-recursion" 116 | version = "1.0.2" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | checksum = "3b015a331cc64ebd1774ba119538573603427eaace0a1950c423ab971f903796" 119 | dependencies = [ 120 | "proc-macro2", 121 | "quote", 122 | "syn", 123 | ] 124 | 125 | [[package]] 126 | name = "async-task" 127 | version = "4.3.0" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "7a40729d2133846d9ed0ea60a8b9541bccddab49cd30f0715a1da672fe9a2524" 130 | 131 | [[package]] 132 | name = "async-trait" 133 | version = "0.1.64" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" 136 | dependencies = [ 137 | "proc-macro2", 138 | "quote", 139 | "syn", 140 | ] 141 | 142 | [[package]] 143 | name = "atty" 144 | version = "0.2.14" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 147 | dependencies = [ 148 | "hermit-abi 0.1.19", 149 | "libc", 150 | "winapi", 151 | ] 152 | 153 | [[package]] 154 | name = "autocfg" 155 | version = "1.1.0" 156 | source = "registry+https://github.com/rust-lang/crates.io-index" 157 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 158 | 159 | [[package]] 160 | name = "base64" 161 | version = "0.13.1" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" 164 | 165 | [[package]] 166 | name = "battery" 167 | version = "0.7.8" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "b4b624268937c0e0a3edb7c27843f9e547c320d730c610d3b8e6e8e95b2026e4" 170 | dependencies = [ 171 | "cfg-if", 172 | "core-foundation 0.7.0", 173 | "lazycell", 174 | "libc", 175 | "mach", 176 | "nix 0.19.1", 177 | "num-traits", 178 | "uom", 179 | "winapi", 180 | ] 181 | 182 | [[package]] 183 | name = "bitflags" 184 | version = "1.3.2" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 187 | 188 | [[package]] 189 | name = "block-buffer" 190 | version = "0.10.3" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" 193 | dependencies = [ 194 | "generic-array", 195 | ] 196 | 197 | [[package]] 198 | name = "block-modes" 199 | version = "0.8.1" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "2cb03d1bed155d89dce0f845b7899b18a9a163e148fd004e1c28421a783e2d8e" 202 | dependencies = [ 203 | "block-padding", 204 | "cipher", 205 | ] 206 | 207 | [[package]] 208 | name = "block-padding" 209 | version = "0.2.1" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" 212 | 213 | [[package]] 214 | name = "bumpalo" 215 | version = "3.12.0" 216 | source = "registry+https://github.com/rust-lang/crates.io-index" 217 | checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" 218 | 219 | [[package]] 220 | name = "byteorder" 221 | version = "1.4.3" 222 | source = "registry+https://github.com/rust-lang/crates.io-index" 223 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 224 | 225 | [[package]] 226 | name = "bytes" 227 | version = "0.4.12" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" 230 | dependencies = [ 231 | "byteorder", 232 | "iovec", 233 | ] 234 | 235 | [[package]] 236 | name = "bytes" 237 | version = "1.4.0" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" 240 | 241 | [[package]] 242 | name = "cc" 243 | version = "1.0.79" 244 | source = "registry+https://github.com/rust-lang/crates.io-index" 245 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 246 | 247 | [[package]] 248 | name = "cfg-if" 249 | version = "1.0.0" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 252 | 253 | [[package]] 254 | name = "cipher" 255 | version = "0.3.0" 256 | source = "registry+https://github.com/rust-lang/crates.io-index" 257 | checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" 258 | dependencies = [ 259 | "generic-array", 260 | ] 261 | 262 | [[package]] 263 | name = "colored" 264 | version = "2.0.0" 265 | source = "registry+https://github.com/rust-lang/crates.io-index" 266 | checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" 267 | dependencies = [ 268 | "atty", 269 | "lazy_static", 270 | "winapi", 271 | ] 272 | 273 | [[package]] 274 | name = "concurrent-queue" 275 | version = "2.1.0" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "c278839b831783b70278b14df4d45e1beb1aad306c07bb796637de9a0e323e8e" 278 | dependencies = [ 279 | "crossbeam-utils", 280 | ] 281 | 282 | [[package]] 283 | name = "core-foundation" 284 | version = "0.7.0" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" 287 | dependencies = [ 288 | "core-foundation-sys 0.7.0", 289 | "libc", 290 | ] 291 | 292 | [[package]] 293 | name = "core-foundation" 294 | version = "0.9.3" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" 297 | dependencies = [ 298 | "core-foundation-sys 0.8.3", 299 | "libc", 300 | ] 301 | 302 | [[package]] 303 | name = "core-foundation-sys" 304 | version = "0.7.0" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" 307 | 308 | [[package]] 309 | name = "core-foundation-sys" 310 | version = "0.8.3" 311 | source = "registry+https://github.com/rust-lang/crates.io-index" 312 | checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" 313 | 314 | [[package]] 315 | name = "cpufeatures" 316 | version = "0.2.5" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" 319 | dependencies = [ 320 | "libc", 321 | ] 322 | 323 | [[package]] 324 | name = "crossbeam-channel" 325 | version = "0.5.6" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" 328 | dependencies = [ 329 | "cfg-if", 330 | "crossbeam-utils", 331 | ] 332 | 333 | [[package]] 334 | name = "crossbeam-deque" 335 | version = "0.8.2" 336 | source = "registry+https://github.com/rust-lang/crates.io-index" 337 | checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" 338 | dependencies = [ 339 | "cfg-if", 340 | "crossbeam-epoch", 341 | "crossbeam-utils", 342 | ] 343 | 344 | [[package]] 345 | name = "crossbeam-epoch" 346 | version = "0.9.13" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" 349 | dependencies = [ 350 | "autocfg", 351 | "cfg-if", 352 | "crossbeam-utils", 353 | "memoffset 0.7.1", 354 | "scopeguard", 355 | ] 356 | 357 | [[package]] 358 | name = "crossbeam-utils" 359 | version = "0.8.14" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" 362 | dependencies = [ 363 | "cfg-if", 364 | ] 365 | 366 | [[package]] 367 | name = "crypto-common" 368 | version = "0.1.6" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 371 | dependencies = [ 372 | "generic-array", 373 | "typenum", 374 | ] 375 | 376 | [[package]] 377 | name = "ctor" 378 | version = "0.1.26" 379 | source = "registry+https://github.com/rust-lang/crates.io-index" 380 | checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" 381 | dependencies = [ 382 | "quote", 383 | "syn", 384 | ] 385 | 386 | [[package]] 387 | name = "derivative" 388 | version = "2.2.0" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" 391 | dependencies = [ 392 | "proc-macro2", 393 | "quote", 394 | "syn", 395 | ] 396 | 397 | [[package]] 398 | name = "digest" 399 | version = "0.10.6" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" 402 | dependencies = [ 403 | "block-buffer", 404 | "crypto-common", 405 | "subtle", 406 | ] 407 | 408 | [[package]] 409 | name = "dirs" 410 | version = "4.0.0" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" 413 | dependencies = [ 414 | "dirs-sys", 415 | ] 416 | 417 | [[package]] 418 | name = "dirs-sys" 419 | version = "0.3.7" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" 422 | dependencies = [ 423 | "libc", 424 | "redox_users", 425 | "winapi", 426 | ] 427 | 428 | [[package]] 429 | name = "either" 430 | version = "1.8.1" 431 | source = "registry+https://github.com/rust-lang/crates.io-index" 432 | checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" 433 | 434 | [[package]] 435 | name = "enumflags2" 436 | version = "0.7.5" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "e75d4cd21b95383444831539909fbb14b9dc3fdceb2a6f5d36577329a1f55ccb" 439 | dependencies = [ 440 | "enumflags2_derive", 441 | "serde", 442 | ] 443 | 444 | [[package]] 445 | name = "enumflags2_derive" 446 | version = "0.7.4" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "f58dc3c5e468259f19f2d46304a6b28f1c3d034442e14b322d2b850e36f6d5ae" 449 | dependencies = [ 450 | "proc-macro2", 451 | "quote", 452 | "syn", 453 | ] 454 | 455 | [[package]] 456 | name = "errno" 457 | version = "0.2.8" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" 460 | dependencies = [ 461 | "errno-dragonfly", 462 | "libc", 463 | "winapi", 464 | ] 465 | 466 | [[package]] 467 | name = "errno-dragonfly" 468 | version = "0.1.2" 469 | source = "registry+https://github.com/rust-lang/crates.io-index" 470 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 471 | dependencies = [ 472 | "cc", 473 | "libc", 474 | ] 475 | 476 | [[package]] 477 | name = "event-listener" 478 | version = "2.5.3" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" 481 | 482 | [[package]] 483 | name = "fastrand" 484 | version = "1.9.0" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" 487 | dependencies = [ 488 | "instant", 489 | ] 490 | 491 | [[package]] 492 | name = "form_urlencoded" 493 | version = "1.1.0" 494 | source = "registry+https://github.com/rust-lang/crates.io-index" 495 | checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" 496 | dependencies = [ 497 | "percent-encoding", 498 | ] 499 | 500 | [[package]] 501 | name = "futures-core" 502 | version = "0.3.26" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" 505 | 506 | [[package]] 507 | name = "futures-io" 508 | version = "0.3.26" 509 | source = "registry+https://github.com/rust-lang/crates.io-index" 510 | checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531" 511 | 512 | [[package]] 513 | name = "futures-lite" 514 | version = "1.12.0" 515 | source = "registry+https://github.com/rust-lang/crates.io-index" 516 | checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48" 517 | dependencies = [ 518 | "fastrand", 519 | "futures-core", 520 | "futures-io", 521 | "memchr", 522 | "parking", 523 | "pin-project-lite", 524 | "waker-fn", 525 | ] 526 | 527 | [[package]] 528 | name = "futures-macro" 529 | version = "0.3.26" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" 532 | dependencies = [ 533 | "proc-macro2", 534 | "quote", 535 | "syn", 536 | ] 537 | 538 | [[package]] 539 | name = "futures-sink" 540 | version = "0.3.26" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" 543 | 544 | [[package]] 545 | name = "futures-task" 546 | version = "0.3.26" 547 | source = "registry+https://github.com/rust-lang/crates.io-index" 548 | checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" 549 | 550 | [[package]] 551 | name = "futures-util" 552 | version = "0.3.26" 553 | source = "registry+https://github.com/rust-lang/crates.io-index" 554 | checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" 555 | dependencies = [ 556 | "futures-core", 557 | "futures-macro", 558 | "futures-sink", 559 | "futures-task", 560 | "pin-project-lite", 561 | "pin-utils", 562 | "slab", 563 | ] 564 | 565 | [[package]] 566 | name = "generic-array" 567 | version = "0.14.6" 568 | source = "registry+https://github.com/rust-lang/crates.io-index" 569 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" 570 | dependencies = [ 571 | "typenum", 572 | "version_check", 573 | ] 574 | 575 | [[package]] 576 | name = "getrandom" 577 | version = "0.2.8" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" 580 | dependencies = [ 581 | "cfg-if", 582 | "libc", 583 | "wasi", 584 | ] 585 | 586 | [[package]] 587 | name = "hashbrown" 588 | version = "0.12.3" 589 | source = "registry+https://github.com/rust-lang/crates.io-index" 590 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 591 | 592 | [[package]] 593 | name = "hermit-abi" 594 | version = "0.1.19" 595 | source = "registry+https://github.com/rust-lang/crates.io-index" 596 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 597 | dependencies = [ 598 | "libc", 599 | ] 600 | 601 | [[package]] 602 | name = "hermit-abi" 603 | version = "0.2.6" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" 606 | dependencies = [ 607 | "libc", 608 | ] 609 | 610 | [[package]] 611 | name = "hex" 612 | version = "0.4.3" 613 | source = "registry+https://github.com/rust-lang/crates.io-index" 614 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 615 | 616 | [[package]] 617 | name = "hkdf" 618 | version = "0.12.3" 619 | source = "registry+https://github.com/rust-lang/crates.io-index" 620 | checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" 621 | dependencies = [ 622 | "hmac", 623 | ] 624 | 625 | [[package]] 626 | name = "hmac" 627 | version = "0.12.1" 628 | source = "registry+https://github.com/rust-lang/crates.io-index" 629 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 630 | dependencies = [ 631 | "digest", 632 | ] 633 | 634 | [[package]] 635 | name = "idna" 636 | version = "0.3.0" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" 639 | dependencies = [ 640 | "unicode-bidi", 641 | "unicode-normalization", 642 | ] 643 | 644 | [[package]] 645 | name = "indexmap" 646 | version = "1.9.2" 647 | source = "registry+https://github.com/rust-lang/crates.io-index" 648 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 649 | dependencies = [ 650 | "autocfg", 651 | "hashbrown", 652 | ] 653 | 654 | [[package]] 655 | name = "instant" 656 | version = "0.1.12" 657 | source = "registry+https://github.com/rust-lang/crates.io-index" 658 | checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" 659 | dependencies = [ 660 | "cfg-if", 661 | ] 662 | 663 | [[package]] 664 | name = "io-lifetimes" 665 | version = "1.0.5" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" 668 | dependencies = [ 669 | "libc", 670 | "windows-sys 0.45.0", 671 | ] 672 | 673 | [[package]] 674 | name = "iovec" 675 | version = "0.1.4" 676 | source = "registry+https://github.com/rust-lang/crates.io-index" 677 | checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" 678 | dependencies = [ 679 | "libc", 680 | ] 681 | 682 | [[package]] 683 | name = "itoa" 684 | version = "1.0.5" 685 | source = "registry+https://github.com/rust-lang/crates.io-index" 686 | checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" 687 | 688 | [[package]] 689 | name = "js-sys" 690 | version = "0.3.58" 691 | source = "registry+https://github.com/rust-lang/crates.io-index" 692 | checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" 693 | dependencies = [ 694 | "wasm-bindgen", 695 | ] 696 | 697 | [[package]] 698 | name = "keyring" 699 | version = "2.0.1" 700 | source = "registry+https://github.com/rust-lang/crates.io-index" 701 | checksum = "5bfd6f156b53b48cd89223a27b11f1cddaa5d9bd298b48af3b644c43a8ae5f0f" 702 | dependencies = [ 703 | "byteorder", 704 | "lazy_static", 705 | "linux-keyutils", 706 | "secret-service", 707 | "security-framework", 708 | "winapi", 709 | ] 710 | 711 | [[package]] 712 | name = "lazy_static" 713 | version = "1.4.0" 714 | source = "registry+https://github.com/rust-lang/crates.io-index" 715 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 716 | 717 | [[package]] 718 | name = "lazycell" 719 | version = "1.3.0" 720 | source = "registry+https://github.com/rust-lang/crates.io-index" 721 | checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" 722 | 723 | [[package]] 724 | name = "libc" 725 | version = "0.2.139" 726 | source = "registry+https://github.com/rust-lang/crates.io-index" 727 | checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" 728 | 729 | [[package]] 730 | name = "libsystemd" 731 | version = "0.6.0" 732 | source = "registry+https://github.com/rust-lang/crates.io-index" 733 | checksum = "88b9597a67aa1c81a6624603e6bd0bcefb9e0f94c9c54970ec53771082104b4e" 734 | dependencies = [ 735 | "hmac", 736 | "libc", 737 | "log", 738 | "nix 0.26.2", 739 | "nom", 740 | "once_cell", 741 | "serde", 742 | "sha2", 743 | "thiserror", 744 | "uuid", 745 | ] 746 | 747 | [[package]] 748 | name = "linux-keyutils" 749 | version = "0.2.3" 750 | source = "registry+https://github.com/rust-lang/crates.io-index" 751 | checksum = "3f27bb67f6dd1d0bb5ab582868e4f65052e58da6401188a08f0da09cf512b84b" 752 | dependencies = [ 753 | "bitflags", 754 | "libc", 755 | ] 756 | 757 | [[package]] 758 | name = "linux-raw-sys" 759 | version = "0.1.4" 760 | source = "registry+https://github.com/rust-lang/crates.io-index" 761 | checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" 762 | 763 | [[package]] 764 | name = "lock_api" 765 | version = "0.4.9" 766 | source = "registry+https://github.com/rust-lang/crates.io-index" 767 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 768 | dependencies = [ 769 | "autocfg", 770 | "scopeguard", 771 | ] 772 | 773 | [[package]] 774 | name = "log" 775 | version = "0.4.17" 776 | source = "registry+https://github.com/rust-lang/crates.io-index" 777 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 778 | dependencies = [ 779 | "cfg-if", 780 | "value-bag", 781 | ] 782 | 783 | [[package]] 784 | name = "mach" 785 | version = "0.3.2" 786 | source = "registry+https://github.com/rust-lang/crates.io-index" 787 | checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa" 788 | dependencies = [ 789 | "libc", 790 | ] 791 | 792 | [[package]] 793 | name = "maplit" 794 | version = "1.0.2" 795 | source = "registry+https://github.com/rust-lang/crates.io-index" 796 | checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" 797 | 798 | [[package]] 799 | name = "memchr" 800 | version = "2.5.0" 801 | source = "registry+https://github.com/rust-lang/crates.io-index" 802 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 803 | 804 | [[package]] 805 | name = "memoffset" 806 | version = "0.6.5" 807 | source = "registry+https://github.com/rust-lang/crates.io-index" 808 | checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" 809 | dependencies = [ 810 | "autocfg", 811 | ] 812 | 813 | [[package]] 814 | name = "memoffset" 815 | version = "0.7.1" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" 818 | dependencies = [ 819 | "autocfg", 820 | ] 821 | 822 | [[package]] 823 | name = "minimal-lexical" 824 | version = "0.2.1" 825 | source = "registry+https://github.com/rust-lang/crates.io-index" 826 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 827 | 828 | [[package]] 829 | name = "mio" 830 | version = "0.8.6" 831 | source = "registry+https://github.com/rust-lang/crates.io-index" 832 | checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" 833 | dependencies = [ 834 | "libc", 835 | "log", 836 | "wasi", 837 | "windows-sys 0.45.0", 838 | ] 839 | 840 | [[package]] 841 | name = "mqtt-async-client" 842 | version = "0.3.1" 843 | source = "registry+https://github.com/rust-lang/crates.io-index" 844 | checksum = "4b82b418f370bc4fdba0d38c9588b4ce1546c3026d2aec10f70ac2493a48ab91" 845 | dependencies = [ 846 | "bytes 0.4.12", 847 | "futures-core", 848 | "futures-util", 849 | "log", 850 | "maplit", 851 | "mqttrs", 852 | "rustls", 853 | "tokio", 854 | "tokio-rustls", 855 | "url", 856 | ] 857 | 858 | [[package]] 859 | name = "mqttrs" 860 | version = "0.2.0" 861 | source = "registry+https://github.com/rust-lang/crates.io-index" 862 | checksum = "090163ffd34d1e19613433eb4860a0d69a002db215d5120fb1278daa5a54f978" 863 | dependencies = [ 864 | "bytes 0.4.12", 865 | ] 866 | 867 | [[package]] 868 | name = "nix" 869 | version = "0.19.1" 870 | source = "registry+https://github.com/rust-lang/crates.io-index" 871 | checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2" 872 | dependencies = [ 873 | "bitflags", 874 | "cc", 875 | "cfg-if", 876 | "libc", 877 | ] 878 | 879 | [[package]] 880 | name = "nix" 881 | version = "0.25.1" 882 | source = "registry+https://github.com/rust-lang/crates.io-index" 883 | checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" 884 | dependencies = [ 885 | "autocfg", 886 | "bitflags", 887 | "cfg-if", 888 | "libc", 889 | "memoffset 0.6.5", 890 | "pin-utils", 891 | ] 892 | 893 | [[package]] 894 | name = "nix" 895 | version = "0.26.2" 896 | source = "registry+https://github.com/rust-lang/crates.io-index" 897 | checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" 898 | dependencies = [ 899 | "bitflags", 900 | "cfg-if", 901 | "libc", 902 | "memoffset 0.7.1", 903 | "static_assertions", 904 | ] 905 | 906 | [[package]] 907 | name = "nom" 908 | version = "7.1.3" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 911 | dependencies = [ 912 | "memchr", 913 | "minimal-lexical", 914 | ] 915 | 916 | [[package]] 917 | name = "nom8" 918 | version = "0.2.0" 919 | source = "registry+https://github.com/rust-lang/crates.io-index" 920 | checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8" 921 | dependencies = [ 922 | "memchr", 923 | ] 924 | 925 | [[package]] 926 | name = "ntapi" 927 | version = "0.4.0" 928 | source = "registry+https://github.com/rust-lang/crates.io-index" 929 | checksum = "bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc" 930 | dependencies = [ 931 | "winapi", 932 | ] 933 | 934 | [[package]] 935 | name = "num" 936 | version = "0.4.0" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" 939 | dependencies = [ 940 | "num-bigint", 941 | "num-complex", 942 | "num-integer", 943 | "num-iter", 944 | "num-rational", 945 | "num-traits", 946 | ] 947 | 948 | [[package]] 949 | name = "num-bigint" 950 | version = "0.4.3" 951 | source = "registry+https://github.com/rust-lang/crates.io-index" 952 | checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" 953 | dependencies = [ 954 | "autocfg", 955 | "num-integer", 956 | "num-traits", 957 | ] 958 | 959 | [[package]] 960 | name = "num-complex" 961 | version = "0.4.3" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" 964 | dependencies = [ 965 | "num-traits", 966 | ] 967 | 968 | [[package]] 969 | name = "num-integer" 970 | version = "0.1.45" 971 | source = "registry+https://github.com/rust-lang/crates.io-index" 972 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 973 | dependencies = [ 974 | "autocfg", 975 | "num-traits", 976 | ] 977 | 978 | [[package]] 979 | name = "num-iter" 980 | version = "0.1.43" 981 | source = "registry+https://github.com/rust-lang/crates.io-index" 982 | checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" 983 | dependencies = [ 984 | "autocfg", 985 | "num-integer", 986 | "num-traits", 987 | ] 988 | 989 | [[package]] 990 | name = "num-rational" 991 | version = "0.4.1" 992 | source = "registry+https://github.com/rust-lang/crates.io-index" 993 | checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" 994 | dependencies = [ 995 | "autocfg", 996 | "num-bigint", 997 | "num-integer", 998 | "num-traits", 999 | ] 1000 | 1001 | [[package]] 1002 | name = "num-traits" 1003 | version = "0.2.15" 1004 | source = "registry+https://github.com/rust-lang/crates.io-index" 1005 | checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" 1006 | dependencies = [ 1007 | "autocfg", 1008 | ] 1009 | 1010 | [[package]] 1011 | name = "num_cpus" 1012 | version = "1.15.0" 1013 | source = "registry+https://github.com/rust-lang/crates.io-index" 1014 | checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" 1015 | dependencies = [ 1016 | "hermit-abi 0.2.6", 1017 | "libc", 1018 | ] 1019 | 1020 | [[package]] 1021 | name = "num_threads" 1022 | version = "0.1.6" 1023 | source = "registry+https://github.com/rust-lang/crates.io-index" 1024 | checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" 1025 | dependencies = [ 1026 | "libc", 1027 | ] 1028 | 1029 | [[package]] 1030 | name = "once_cell" 1031 | version = "1.17.1" 1032 | source = "registry+https://github.com/rust-lang/crates.io-index" 1033 | checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" 1034 | 1035 | [[package]] 1036 | name = "opaque-debug" 1037 | version = "0.3.0" 1038 | source = "registry+https://github.com/rust-lang/crates.io-index" 1039 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" 1040 | 1041 | [[package]] 1042 | name = "ordered-stream" 1043 | version = "0.2.0" 1044 | source = "registry+https://github.com/rust-lang/crates.io-index" 1045 | checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" 1046 | dependencies = [ 1047 | "futures-core", 1048 | "pin-project-lite", 1049 | ] 1050 | 1051 | [[package]] 1052 | name = "parking" 1053 | version = "2.0.0" 1054 | source = "registry+https://github.com/rust-lang/crates.io-index" 1055 | checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" 1056 | 1057 | [[package]] 1058 | name = "parking_lot" 1059 | version = "0.12.1" 1060 | source = "registry+https://github.com/rust-lang/crates.io-index" 1061 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 1062 | dependencies = [ 1063 | "lock_api", 1064 | "parking_lot_core", 1065 | ] 1066 | 1067 | [[package]] 1068 | name = "parking_lot_core" 1069 | version = "0.9.7" 1070 | source = "registry+https://github.com/rust-lang/crates.io-index" 1071 | checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" 1072 | dependencies = [ 1073 | "cfg-if", 1074 | "libc", 1075 | "redox_syscall", 1076 | "smallvec", 1077 | "windows-sys 0.45.0", 1078 | ] 1079 | 1080 | [[package]] 1081 | name = "percent-encoding" 1082 | version = "2.2.0" 1083 | source = "registry+https://github.com/rust-lang/crates.io-index" 1084 | checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" 1085 | 1086 | [[package]] 1087 | name = "pin-project-lite" 1088 | version = "0.2.9" 1089 | source = "registry+https://github.com/rust-lang/crates.io-index" 1090 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 1091 | 1092 | [[package]] 1093 | name = "pin-utils" 1094 | version = "0.1.0" 1095 | source = "registry+https://github.com/rust-lang/crates.io-index" 1096 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1097 | 1098 | [[package]] 1099 | name = "polling" 1100 | version = "2.5.2" 1101 | source = "registry+https://github.com/rust-lang/crates.io-index" 1102 | checksum = "22122d5ec4f9fe1b3916419b76be1e80bcb93f618d071d2edf841b137b2a2bd6" 1103 | dependencies = [ 1104 | "autocfg", 1105 | "cfg-if", 1106 | "libc", 1107 | "log", 1108 | "wepoll-ffi", 1109 | "windows-sys 0.42.0", 1110 | ] 1111 | 1112 | [[package]] 1113 | name = "ppv-lite86" 1114 | version = "0.2.17" 1115 | source = "registry+https://github.com/rust-lang/crates.io-index" 1116 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 1117 | 1118 | [[package]] 1119 | name = "proc-macro-crate" 1120 | version = "1.3.0" 1121 | source = "registry+https://github.com/rust-lang/crates.io-index" 1122 | checksum = "66618389e4ec1c7afe67d51a9bf34ff9236480f8d51e7489b7d5ab0303c13f34" 1123 | dependencies = [ 1124 | "once_cell", 1125 | "toml_edit", 1126 | ] 1127 | 1128 | [[package]] 1129 | name = "proc-macro2" 1130 | version = "1.0.51" 1131 | source = "registry+https://github.com/rust-lang/crates.io-index" 1132 | checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" 1133 | dependencies = [ 1134 | "unicode-ident", 1135 | ] 1136 | 1137 | [[package]] 1138 | name = "quote" 1139 | version = "1.0.23" 1140 | source = "registry+https://github.com/rust-lang/crates.io-index" 1141 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" 1142 | dependencies = [ 1143 | "proc-macro2", 1144 | ] 1145 | 1146 | [[package]] 1147 | name = "rand" 1148 | version = "0.8.5" 1149 | source = "registry+https://github.com/rust-lang/crates.io-index" 1150 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1151 | dependencies = [ 1152 | "libc", 1153 | "rand_chacha", 1154 | "rand_core", 1155 | ] 1156 | 1157 | [[package]] 1158 | name = "rand_chacha" 1159 | version = "0.3.1" 1160 | source = "registry+https://github.com/rust-lang/crates.io-index" 1161 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1162 | dependencies = [ 1163 | "ppv-lite86", 1164 | "rand_core", 1165 | ] 1166 | 1167 | [[package]] 1168 | name = "rand_core" 1169 | version = "0.6.4" 1170 | source = "registry+https://github.com/rust-lang/crates.io-index" 1171 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1172 | dependencies = [ 1173 | "getrandom", 1174 | ] 1175 | 1176 | [[package]] 1177 | name = "rayon" 1178 | version = "1.6.1" 1179 | source = "registry+https://github.com/rust-lang/crates.io-index" 1180 | checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" 1181 | dependencies = [ 1182 | "either", 1183 | "rayon-core", 1184 | ] 1185 | 1186 | [[package]] 1187 | name = "rayon-core" 1188 | version = "1.10.2" 1189 | source = "registry+https://github.com/rust-lang/crates.io-index" 1190 | checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" 1191 | dependencies = [ 1192 | "crossbeam-channel", 1193 | "crossbeam-deque", 1194 | "crossbeam-utils", 1195 | "num_cpus", 1196 | ] 1197 | 1198 | [[package]] 1199 | name = "redox_syscall" 1200 | version = "0.2.16" 1201 | source = "registry+https://github.com/rust-lang/crates.io-index" 1202 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 1203 | dependencies = [ 1204 | "bitflags", 1205 | ] 1206 | 1207 | [[package]] 1208 | name = "redox_users" 1209 | version = "0.4.3" 1210 | source = "registry+https://github.com/rust-lang/crates.io-index" 1211 | checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" 1212 | dependencies = [ 1213 | "getrandom", 1214 | "redox_syscall", 1215 | "thiserror", 1216 | ] 1217 | 1218 | [[package]] 1219 | name = "regex" 1220 | version = "1.7.1" 1221 | source = "registry+https://github.com/rust-lang/crates.io-index" 1222 | checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" 1223 | dependencies = [ 1224 | "aho-corasick", 1225 | "memchr", 1226 | "regex-syntax", 1227 | ] 1228 | 1229 | [[package]] 1230 | name = "regex-syntax" 1231 | version = "0.6.28" 1232 | source = "registry+https://github.com/rust-lang/crates.io-index" 1233 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" 1234 | 1235 | [[package]] 1236 | name = "ring" 1237 | version = "0.16.20" 1238 | source = "registry+https://github.com/rust-lang/crates.io-index" 1239 | checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" 1240 | dependencies = [ 1241 | "cc", 1242 | "libc", 1243 | "once_cell", 1244 | "spin", 1245 | "untrusted", 1246 | "web-sys", 1247 | "winapi", 1248 | ] 1249 | 1250 | [[package]] 1251 | name = "rpassword" 1252 | version = "7.2.0" 1253 | source = "registry+https://github.com/rust-lang/crates.io-index" 1254 | checksum = "6678cf63ab3491898c0d021b493c94c9b221d91295294a2a5746eacbe5928322" 1255 | dependencies = [ 1256 | "libc", 1257 | "rtoolbox", 1258 | "winapi", 1259 | ] 1260 | 1261 | [[package]] 1262 | name = "rtoolbox" 1263 | version = "0.0.1" 1264 | source = "registry+https://github.com/rust-lang/crates.io-index" 1265 | checksum = "034e22c514f5c0cb8a10ff341b9b048b5ceb21591f31c8f44c43b960f9b3524a" 1266 | dependencies = [ 1267 | "libc", 1268 | "winapi", 1269 | ] 1270 | 1271 | [[package]] 1272 | name = "rustix" 1273 | version = "0.36.8" 1274 | source = "registry+https://github.com/rust-lang/crates.io-index" 1275 | checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" 1276 | dependencies = [ 1277 | "bitflags", 1278 | "errno", 1279 | "io-lifetimes", 1280 | "libc", 1281 | "linux-raw-sys", 1282 | "windows-sys 0.45.0", 1283 | ] 1284 | 1285 | [[package]] 1286 | name = "rustls" 1287 | version = "0.19.1" 1288 | source = "registry+https://github.com/rust-lang/crates.io-index" 1289 | checksum = "35edb675feee39aec9c99fa5ff985081995a06d594114ae14cbe797ad7b7a6d7" 1290 | dependencies = [ 1291 | "base64", 1292 | "log", 1293 | "ring", 1294 | "sct", 1295 | "webpki", 1296 | ] 1297 | 1298 | [[package]] 1299 | name = "ryu" 1300 | version = "1.0.12" 1301 | source = "registry+https://github.com/rust-lang/crates.io-index" 1302 | checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" 1303 | 1304 | [[package]] 1305 | name = "scopeguard" 1306 | version = "1.1.0" 1307 | source = "registry+https://github.com/rust-lang/crates.io-index" 1308 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1309 | 1310 | [[package]] 1311 | name = "sct" 1312 | version = "0.6.1" 1313 | source = "registry+https://github.com/rust-lang/crates.io-index" 1314 | checksum = "b362b83898e0e69f38515b82ee15aa80636befe47c3b6d3d89a911e78fc228ce" 1315 | dependencies = [ 1316 | "ring", 1317 | "untrusted", 1318 | ] 1319 | 1320 | [[package]] 1321 | name = "secret-service" 1322 | version = "3.0.1" 1323 | source = "registry+https://github.com/rust-lang/crates.io-index" 1324 | checksum = "5da1a5ad4d28c03536f82f77d9f36603f5e37d8869ac98f0a750d5b5686d8d95" 1325 | dependencies = [ 1326 | "aes", 1327 | "block-modes", 1328 | "futures-util", 1329 | "generic-array", 1330 | "hkdf", 1331 | "num", 1332 | "once_cell", 1333 | "rand", 1334 | "serde", 1335 | "sha2", 1336 | "zbus", 1337 | ] 1338 | 1339 | [[package]] 1340 | name = "security-framework" 1341 | version = "2.8.2" 1342 | source = "registry+https://github.com/rust-lang/crates.io-index" 1343 | checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" 1344 | dependencies = [ 1345 | "bitflags", 1346 | "core-foundation 0.9.3", 1347 | "core-foundation-sys 0.8.3", 1348 | "libc", 1349 | "security-framework-sys", 1350 | ] 1351 | 1352 | [[package]] 1353 | name = "security-framework-sys" 1354 | version = "2.8.0" 1355 | source = "registry+https://github.com/rust-lang/crates.io-index" 1356 | checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" 1357 | dependencies = [ 1358 | "core-foundation-sys 0.8.3", 1359 | "libc", 1360 | ] 1361 | 1362 | [[package]] 1363 | name = "serde" 1364 | version = "1.0.152" 1365 | source = "registry+https://github.com/rust-lang/crates.io-index" 1366 | checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" 1367 | dependencies = [ 1368 | "serde_derive", 1369 | ] 1370 | 1371 | [[package]] 1372 | name = "serde_derive" 1373 | version = "1.0.152" 1374 | source = "registry+https://github.com/rust-lang/crates.io-index" 1375 | checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" 1376 | dependencies = [ 1377 | "proc-macro2", 1378 | "quote", 1379 | "syn", 1380 | ] 1381 | 1382 | [[package]] 1383 | name = "serde_json" 1384 | version = "1.0.93" 1385 | source = "registry+https://github.com/rust-lang/crates.io-index" 1386 | checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" 1387 | dependencies = [ 1388 | "itoa", 1389 | "ryu", 1390 | "serde", 1391 | ] 1392 | 1393 | [[package]] 1394 | name = "serde_repr" 1395 | version = "0.1.10" 1396 | source = "registry+https://github.com/rust-lang/crates.io-index" 1397 | checksum = "9a5ec9fa74a20ebbe5d9ac23dac1fc96ba0ecfe9f50f2843b52e537b10fbcb4e" 1398 | dependencies = [ 1399 | "proc-macro2", 1400 | "quote", 1401 | "syn", 1402 | ] 1403 | 1404 | [[package]] 1405 | name = "serde_yaml" 1406 | version = "0.9.17" 1407 | source = "registry+https://github.com/rust-lang/crates.io-index" 1408 | checksum = "8fb06d4b6cdaef0e0c51fa881acb721bed3c924cfaa71d9c94a3b771dfdf6567" 1409 | dependencies = [ 1410 | "indexmap", 1411 | "itoa", 1412 | "ryu", 1413 | "serde", 1414 | "unsafe-libyaml", 1415 | ] 1416 | 1417 | [[package]] 1418 | name = "sha1" 1419 | version = "0.10.5" 1420 | source = "registry+https://github.com/rust-lang/crates.io-index" 1421 | checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" 1422 | dependencies = [ 1423 | "cfg-if", 1424 | "cpufeatures", 1425 | "digest", 1426 | ] 1427 | 1428 | [[package]] 1429 | name = "sha2" 1430 | version = "0.10.6" 1431 | source = "registry+https://github.com/rust-lang/crates.io-index" 1432 | checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" 1433 | dependencies = [ 1434 | "cfg-if", 1435 | "cpufeatures", 1436 | "digest", 1437 | ] 1438 | 1439 | [[package]] 1440 | name = "signal-hook-registry" 1441 | version = "1.4.1" 1442 | source = "registry+https://github.com/rust-lang/crates.io-index" 1443 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 1444 | dependencies = [ 1445 | "libc", 1446 | ] 1447 | 1448 | [[package]] 1449 | name = "simple_logger" 1450 | version = "4.0.0" 1451 | source = "registry+https://github.com/rust-lang/crates.io-index" 1452 | checksum = "e190a521c2044948158666916d9e872cbb9984f755e9bb3b5b75a836205affcd" 1453 | dependencies = [ 1454 | "atty", 1455 | "colored", 1456 | "log", 1457 | "time", 1458 | "windows-sys 0.42.0", 1459 | ] 1460 | 1461 | [[package]] 1462 | name = "slab" 1463 | version = "0.4.8" 1464 | source = "registry+https://github.com/rust-lang/crates.io-index" 1465 | checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" 1466 | dependencies = [ 1467 | "autocfg", 1468 | ] 1469 | 1470 | [[package]] 1471 | name = "smallvec" 1472 | version = "1.10.0" 1473 | source = "registry+https://github.com/rust-lang/crates.io-index" 1474 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 1475 | 1476 | [[package]] 1477 | name = "socket2" 1478 | version = "0.4.7" 1479 | source = "registry+https://github.com/rust-lang/crates.io-index" 1480 | checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" 1481 | dependencies = [ 1482 | "libc", 1483 | "winapi", 1484 | ] 1485 | 1486 | [[package]] 1487 | name = "spin" 1488 | version = "0.5.2" 1489 | source = "registry+https://github.com/rust-lang/crates.io-index" 1490 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" 1491 | 1492 | [[package]] 1493 | name = "static_assertions" 1494 | version = "1.1.0" 1495 | source = "registry+https://github.com/rust-lang/crates.io-index" 1496 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" 1497 | 1498 | [[package]] 1499 | name = "subtle" 1500 | version = "2.4.1" 1501 | source = "registry+https://github.com/rust-lang/crates.io-index" 1502 | checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" 1503 | 1504 | [[package]] 1505 | name = "syn" 1506 | version = "1.0.109" 1507 | source = "registry+https://github.com/rust-lang/crates.io-index" 1508 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1509 | dependencies = [ 1510 | "proc-macro2", 1511 | "quote", 1512 | "unicode-ident", 1513 | ] 1514 | 1515 | [[package]] 1516 | name = "sysinfo" 1517 | version = "0.28.1" 1518 | source = "registry+https://github.com/rust-lang/crates.io-index" 1519 | checksum = "38a81bbc26c485910df47772df6bbcdb417036132caa9e51e29d2e39c4636d4e" 1520 | dependencies = [ 1521 | "cfg-if", 1522 | "core-foundation-sys 0.8.3", 1523 | "libc", 1524 | "ntapi", 1525 | "once_cell", 1526 | "rayon", 1527 | "winapi", 1528 | ] 1529 | 1530 | [[package]] 1531 | name = "system-mqtt" 1532 | version = "0.3.1" 1533 | dependencies = [ 1534 | "anyhow", 1535 | "argh", 1536 | "battery", 1537 | "keyring", 1538 | "log", 1539 | "mqtt-async-client", 1540 | "rpassword", 1541 | "serde", 1542 | "serde_json", 1543 | "serde_yaml", 1544 | "simple_logger", 1545 | "sysinfo", 1546 | "systemd-journal-logger", 1547 | "tokio", 1548 | "url", 1549 | "users", 1550 | ] 1551 | 1552 | [[package]] 1553 | name = "systemd-journal-logger" 1554 | version = "0.7.0" 1555 | source = "registry+https://github.com/rust-lang/crates.io-index" 1556 | checksum = "abee2da0faf67d79baaa095840d6b687e365aa9b7c34560c48a8e90f8e62055e" 1557 | dependencies = [ 1558 | "libsystemd", 1559 | "log", 1560 | ] 1561 | 1562 | [[package]] 1563 | name = "tempfile" 1564 | version = "3.4.0" 1565 | source = "registry+https://github.com/rust-lang/crates.io-index" 1566 | checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95" 1567 | dependencies = [ 1568 | "cfg-if", 1569 | "fastrand", 1570 | "redox_syscall", 1571 | "rustix", 1572 | "windows-sys 0.42.0", 1573 | ] 1574 | 1575 | [[package]] 1576 | name = "thiserror" 1577 | version = "1.0.38" 1578 | source = "registry+https://github.com/rust-lang/crates.io-index" 1579 | checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" 1580 | dependencies = [ 1581 | "thiserror-impl", 1582 | ] 1583 | 1584 | [[package]] 1585 | name = "thiserror-impl" 1586 | version = "1.0.38" 1587 | source = "registry+https://github.com/rust-lang/crates.io-index" 1588 | checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" 1589 | dependencies = [ 1590 | "proc-macro2", 1591 | "quote", 1592 | "syn", 1593 | ] 1594 | 1595 | [[package]] 1596 | name = "time" 1597 | version = "0.3.20" 1598 | source = "registry+https://github.com/rust-lang/crates.io-index" 1599 | checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" 1600 | dependencies = [ 1601 | "itoa", 1602 | "libc", 1603 | "num_threads", 1604 | "serde", 1605 | "time-core", 1606 | "time-macros", 1607 | ] 1608 | 1609 | [[package]] 1610 | name = "time-core" 1611 | version = "0.1.0" 1612 | source = "registry+https://github.com/rust-lang/crates.io-index" 1613 | checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" 1614 | 1615 | [[package]] 1616 | name = "time-macros" 1617 | version = "0.2.8" 1618 | source = "registry+https://github.com/rust-lang/crates.io-index" 1619 | checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" 1620 | dependencies = [ 1621 | "time-core", 1622 | ] 1623 | 1624 | [[package]] 1625 | name = "tinyvec" 1626 | version = "1.6.0" 1627 | source = "registry+https://github.com/rust-lang/crates.io-index" 1628 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1629 | dependencies = [ 1630 | "tinyvec_macros", 1631 | ] 1632 | 1633 | [[package]] 1634 | name = "tinyvec_macros" 1635 | version = "0.1.1" 1636 | source = "registry+https://github.com/rust-lang/crates.io-index" 1637 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1638 | 1639 | [[package]] 1640 | name = "tokio" 1641 | version = "1.25.0" 1642 | source = "registry+https://github.com/rust-lang/crates.io-index" 1643 | checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" 1644 | dependencies = [ 1645 | "autocfg", 1646 | "bytes 1.4.0", 1647 | "libc", 1648 | "memchr", 1649 | "mio", 1650 | "num_cpus", 1651 | "parking_lot", 1652 | "pin-project-lite", 1653 | "signal-hook-registry", 1654 | "socket2", 1655 | "tokio-macros", 1656 | "windows-sys 0.42.0", 1657 | ] 1658 | 1659 | [[package]] 1660 | name = "tokio-macros" 1661 | version = "1.8.2" 1662 | source = "registry+https://github.com/rust-lang/crates.io-index" 1663 | checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" 1664 | dependencies = [ 1665 | "proc-macro2", 1666 | "quote", 1667 | "syn", 1668 | ] 1669 | 1670 | [[package]] 1671 | name = "tokio-rustls" 1672 | version = "0.22.0" 1673 | source = "registry+https://github.com/rust-lang/crates.io-index" 1674 | checksum = "bc6844de72e57df1980054b38be3a9f4702aba4858be64dd700181a8a6d0e1b6" 1675 | dependencies = [ 1676 | "rustls", 1677 | "tokio", 1678 | "webpki", 1679 | ] 1680 | 1681 | [[package]] 1682 | name = "toml_datetime" 1683 | version = "0.5.1" 1684 | source = "registry+https://github.com/rust-lang/crates.io-index" 1685 | checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" 1686 | 1687 | [[package]] 1688 | name = "toml_edit" 1689 | version = "0.18.1" 1690 | source = "registry+https://github.com/rust-lang/crates.io-index" 1691 | checksum = "56c59d8dd7d0dcbc6428bf7aa2f0e823e26e43b3c9aca15bbc9475d23e5fa12b" 1692 | dependencies = [ 1693 | "indexmap", 1694 | "nom8", 1695 | "toml_datetime", 1696 | ] 1697 | 1698 | [[package]] 1699 | name = "tracing" 1700 | version = "0.1.37" 1701 | source = "registry+https://github.com/rust-lang/crates.io-index" 1702 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 1703 | dependencies = [ 1704 | "cfg-if", 1705 | "pin-project-lite", 1706 | "tracing-attributes", 1707 | "tracing-core", 1708 | ] 1709 | 1710 | [[package]] 1711 | name = "tracing-attributes" 1712 | version = "0.1.23" 1713 | source = "registry+https://github.com/rust-lang/crates.io-index" 1714 | checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" 1715 | dependencies = [ 1716 | "proc-macro2", 1717 | "quote", 1718 | "syn", 1719 | ] 1720 | 1721 | [[package]] 1722 | name = "tracing-core" 1723 | version = "0.1.30" 1724 | source = "registry+https://github.com/rust-lang/crates.io-index" 1725 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" 1726 | dependencies = [ 1727 | "once_cell", 1728 | ] 1729 | 1730 | [[package]] 1731 | name = "typenum" 1732 | version = "1.16.0" 1733 | source = "registry+https://github.com/rust-lang/crates.io-index" 1734 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 1735 | 1736 | [[package]] 1737 | name = "uds_windows" 1738 | version = "1.0.2" 1739 | source = "registry+https://github.com/rust-lang/crates.io-index" 1740 | checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" 1741 | dependencies = [ 1742 | "tempfile", 1743 | "winapi", 1744 | ] 1745 | 1746 | [[package]] 1747 | name = "unicode-bidi" 1748 | version = "0.3.10" 1749 | source = "registry+https://github.com/rust-lang/crates.io-index" 1750 | checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" 1751 | 1752 | [[package]] 1753 | name = "unicode-ident" 1754 | version = "1.0.6" 1755 | source = "registry+https://github.com/rust-lang/crates.io-index" 1756 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 1757 | 1758 | [[package]] 1759 | name = "unicode-normalization" 1760 | version = "0.1.22" 1761 | source = "registry+https://github.com/rust-lang/crates.io-index" 1762 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 1763 | dependencies = [ 1764 | "tinyvec", 1765 | ] 1766 | 1767 | [[package]] 1768 | name = "unsafe-libyaml" 1769 | version = "0.2.5" 1770 | source = "registry+https://github.com/rust-lang/crates.io-index" 1771 | checksum = "bc7ed8ba44ca06be78ea1ad2c3682a43349126c8818054231ee6f4748012aed2" 1772 | 1773 | [[package]] 1774 | name = "untrusted" 1775 | version = "0.7.1" 1776 | source = "registry+https://github.com/rust-lang/crates.io-index" 1777 | checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" 1778 | 1779 | [[package]] 1780 | name = "uom" 1781 | version = "0.30.0" 1782 | source = "registry+https://github.com/rust-lang/crates.io-index" 1783 | checksum = "e76503e636584f1e10b9b3b9498538279561adcef5412927ba00c2b32c4ce5ed" 1784 | dependencies = [ 1785 | "num-traits", 1786 | "typenum", 1787 | ] 1788 | 1789 | [[package]] 1790 | name = "url" 1791 | version = "2.3.1" 1792 | source = "registry+https://github.com/rust-lang/crates.io-index" 1793 | checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" 1794 | dependencies = [ 1795 | "form_urlencoded", 1796 | "idna", 1797 | "percent-encoding", 1798 | "serde", 1799 | ] 1800 | 1801 | [[package]] 1802 | name = "users" 1803 | version = "0.11.0" 1804 | source = "registry+https://github.com/rust-lang/crates.io-index" 1805 | checksum = "24cc0f6d6f267b73e5a2cadf007ba8f9bc39c6a6f9666f8cf25ea809a153b032" 1806 | dependencies = [ 1807 | "libc", 1808 | "log", 1809 | ] 1810 | 1811 | [[package]] 1812 | name = "uuid" 1813 | version = "1.3.0" 1814 | source = "registry+https://github.com/rust-lang/crates.io-index" 1815 | checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" 1816 | dependencies = [ 1817 | "serde", 1818 | ] 1819 | 1820 | [[package]] 1821 | name = "value-bag" 1822 | version = "1.0.0-alpha.9" 1823 | source = "registry+https://github.com/rust-lang/crates.io-index" 1824 | checksum = "2209b78d1249f7e6f3293657c9779fe31ced465df091bbd433a1cf88e916ec55" 1825 | dependencies = [ 1826 | "ctor", 1827 | "version_check", 1828 | ] 1829 | 1830 | [[package]] 1831 | name = "version_check" 1832 | version = "0.9.4" 1833 | source = "registry+https://github.com/rust-lang/crates.io-index" 1834 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1835 | 1836 | [[package]] 1837 | name = "waker-fn" 1838 | version = "1.1.0" 1839 | source = "registry+https://github.com/rust-lang/crates.io-index" 1840 | checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" 1841 | 1842 | [[package]] 1843 | name = "wasi" 1844 | version = "0.11.0+wasi-snapshot-preview1" 1845 | source = "registry+https://github.com/rust-lang/crates.io-index" 1846 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1847 | 1848 | [[package]] 1849 | name = "wasm-bindgen" 1850 | version = "0.2.81" 1851 | source = "registry+https://github.com/rust-lang/crates.io-index" 1852 | checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" 1853 | dependencies = [ 1854 | "cfg-if", 1855 | "wasm-bindgen-macro", 1856 | ] 1857 | 1858 | [[package]] 1859 | name = "wasm-bindgen-backend" 1860 | version = "0.2.81" 1861 | source = "registry+https://github.com/rust-lang/crates.io-index" 1862 | checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" 1863 | dependencies = [ 1864 | "bumpalo", 1865 | "lazy_static", 1866 | "log", 1867 | "proc-macro2", 1868 | "quote", 1869 | "syn", 1870 | "wasm-bindgen-shared", 1871 | ] 1872 | 1873 | [[package]] 1874 | name = "wasm-bindgen-macro" 1875 | version = "0.2.81" 1876 | source = "registry+https://github.com/rust-lang/crates.io-index" 1877 | checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" 1878 | dependencies = [ 1879 | "quote", 1880 | "wasm-bindgen-macro-support", 1881 | ] 1882 | 1883 | [[package]] 1884 | name = "wasm-bindgen-macro-support" 1885 | version = "0.2.81" 1886 | source = "registry+https://github.com/rust-lang/crates.io-index" 1887 | checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" 1888 | dependencies = [ 1889 | "proc-macro2", 1890 | "quote", 1891 | "syn", 1892 | "wasm-bindgen-backend", 1893 | "wasm-bindgen-shared", 1894 | ] 1895 | 1896 | [[package]] 1897 | name = "wasm-bindgen-shared" 1898 | version = "0.2.81" 1899 | source = "registry+https://github.com/rust-lang/crates.io-index" 1900 | checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" 1901 | 1902 | [[package]] 1903 | name = "web-sys" 1904 | version = "0.3.58" 1905 | source = "registry+https://github.com/rust-lang/crates.io-index" 1906 | checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" 1907 | dependencies = [ 1908 | "js-sys", 1909 | "wasm-bindgen", 1910 | ] 1911 | 1912 | [[package]] 1913 | name = "webpki" 1914 | version = "0.21.4" 1915 | source = "registry+https://github.com/rust-lang/crates.io-index" 1916 | checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" 1917 | dependencies = [ 1918 | "ring", 1919 | "untrusted", 1920 | ] 1921 | 1922 | [[package]] 1923 | name = "wepoll-ffi" 1924 | version = "0.1.2" 1925 | source = "registry+https://github.com/rust-lang/crates.io-index" 1926 | checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb" 1927 | dependencies = [ 1928 | "cc", 1929 | ] 1930 | 1931 | [[package]] 1932 | name = "winapi" 1933 | version = "0.3.9" 1934 | source = "registry+https://github.com/rust-lang/crates.io-index" 1935 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1936 | dependencies = [ 1937 | "winapi-i686-pc-windows-gnu", 1938 | "winapi-x86_64-pc-windows-gnu", 1939 | ] 1940 | 1941 | [[package]] 1942 | name = "winapi-i686-pc-windows-gnu" 1943 | version = "0.4.0" 1944 | source = "registry+https://github.com/rust-lang/crates.io-index" 1945 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1946 | 1947 | [[package]] 1948 | name = "winapi-x86_64-pc-windows-gnu" 1949 | version = "0.4.0" 1950 | source = "registry+https://github.com/rust-lang/crates.io-index" 1951 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1952 | 1953 | [[package]] 1954 | name = "windows-sys" 1955 | version = "0.42.0" 1956 | source = "registry+https://github.com/rust-lang/crates.io-index" 1957 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 1958 | dependencies = [ 1959 | "windows_aarch64_gnullvm", 1960 | "windows_aarch64_msvc", 1961 | "windows_i686_gnu", 1962 | "windows_i686_msvc", 1963 | "windows_x86_64_gnu", 1964 | "windows_x86_64_gnullvm", 1965 | "windows_x86_64_msvc", 1966 | ] 1967 | 1968 | [[package]] 1969 | name = "windows-sys" 1970 | version = "0.45.0" 1971 | source = "registry+https://github.com/rust-lang/crates.io-index" 1972 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 1973 | dependencies = [ 1974 | "windows-targets", 1975 | ] 1976 | 1977 | [[package]] 1978 | name = "windows-targets" 1979 | version = "0.42.1" 1980 | source = "registry+https://github.com/rust-lang/crates.io-index" 1981 | checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" 1982 | dependencies = [ 1983 | "windows_aarch64_gnullvm", 1984 | "windows_aarch64_msvc", 1985 | "windows_i686_gnu", 1986 | "windows_i686_msvc", 1987 | "windows_x86_64_gnu", 1988 | "windows_x86_64_gnullvm", 1989 | "windows_x86_64_msvc", 1990 | ] 1991 | 1992 | [[package]] 1993 | name = "windows_aarch64_gnullvm" 1994 | version = "0.42.1" 1995 | source = "registry+https://github.com/rust-lang/crates.io-index" 1996 | checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" 1997 | 1998 | [[package]] 1999 | name = "windows_aarch64_msvc" 2000 | version = "0.42.1" 2001 | source = "registry+https://github.com/rust-lang/crates.io-index" 2002 | checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" 2003 | 2004 | [[package]] 2005 | name = "windows_i686_gnu" 2006 | version = "0.42.1" 2007 | source = "registry+https://github.com/rust-lang/crates.io-index" 2008 | checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" 2009 | 2010 | [[package]] 2011 | name = "windows_i686_msvc" 2012 | version = "0.42.1" 2013 | source = "registry+https://github.com/rust-lang/crates.io-index" 2014 | checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" 2015 | 2016 | [[package]] 2017 | name = "windows_x86_64_gnu" 2018 | version = "0.42.1" 2019 | source = "registry+https://github.com/rust-lang/crates.io-index" 2020 | checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" 2021 | 2022 | [[package]] 2023 | name = "windows_x86_64_gnullvm" 2024 | version = "0.42.1" 2025 | source = "registry+https://github.com/rust-lang/crates.io-index" 2026 | checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" 2027 | 2028 | [[package]] 2029 | name = "windows_x86_64_msvc" 2030 | version = "0.42.1" 2031 | source = "registry+https://github.com/rust-lang/crates.io-index" 2032 | checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" 2033 | 2034 | [[package]] 2035 | name = "zbus" 2036 | version = "3.10.0" 2037 | source = "registry+https://github.com/rust-lang/crates.io-index" 2038 | checksum = "f770930448dd412a4a7131dd968a8e6df0064db4d7916fbbd2d6c3f26b566938" 2039 | dependencies = [ 2040 | "async-broadcast", 2041 | "async-executor", 2042 | "async-io", 2043 | "async-lock", 2044 | "async-recursion", 2045 | "async-task", 2046 | "async-trait", 2047 | "byteorder", 2048 | "derivative", 2049 | "dirs", 2050 | "enumflags2", 2051 | "event-listener", 2052 | "futures-core", 2053 | "futures-sink", 2054 | "futures-util", 2055 | "hex", 2056 | "nix 0.25.1", 2057 | "once_cell", 2058 | "ordered-stream", 2059 | "rand", 2060 | "serde", 2061 | "serde_repr", 2062 | "sha1", 2063 | "static_assertions", 2064 | "tracing", 2065 | "uds_windows", 2066 | "winapi", 2067 | "zbus_macros", 2068 | "zbus_names", 2069 | "zvariant", 2070 | ] 2071 | 2072 | [[package]] 2073 | name = "zbus_macros" 2074 | version = "3.10.0" 2075 | source = "registry+https://github.com/rust-lang/crates.io-index" 2076 | checksum = "4832059b438689017db7340580ebabba07f114eab91bf990c6e55052408b40d8" 2077 | dependencies = [ 2078 | "proc-macro-crate", 2079 | "proc-macro2", 2080 | "quote", 2081 | "regex", 2082 | "syn", 2083 | ] 2084 | 2085 | [[package]] 2086 | name = "zbus_names" 2087 | version = "2.5.0" 2088 | source = "registry+https://github.com/rust-lang/crates.io-index" 2089 | checksum = "f34f314916bd89bdb9934154627fab152f4f28acdda03e7c4c68181b214fe7e3" 2090 | dependencies = [ 2091 | "serde", 2092 | "static_assertions", 2093 | "zvariant", 2094 | ] 2095 | 2096 | [[package]] 2097 | name = "zvariant" 2098 | version = "3.11.0" 2099 | source = "registry+https://github.com/rust-lang/crates.io-index" 2100 | checksum = "903169c05b9ab948ee93fefc9127d08930df4ce031d46c980784274439803e51" 2101 | dependencies = [ 2102 | "byteorder", 2103 | "enumflags2", 2104 | "libc", 2105 | "serde", 2106 | "static_assertions", 2107 | "zvariant_derive", 2108 | ] 2109 | 2110 | [[package]] 2111 | name = "zvariant_derive" 2112 | version = "3.11.0" 2113 | source = "registry+https://github.com/rust-lang/crates.io-index" 2114 | checksum = "cce76636e8fab7911be67211cf378c252b115ee7f2bae14b18b84821b39260b5" 2115 | dependencies = [ 2116 | "proc-macro-crate", 2117 | "proc-macro2", 2118 | "quote", 2119 | "syn", 2120 | ] 2121 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "system-mqtt" 3 | authors = ["James Carl"] 4 | version = "0.3.1" 5 | edition = "2018" 6 | license = "MIT" 7 | readme = "README.md" 8 | description = "Broadcasts system statistics to an mqtt server of your choice. Ideal for home assistant!" 9 | repository = "https://github.com/IamTheCarl/system-mqtt" 10 | 11 | [dependencies] 12 | argh = "0.1" 13 | battery = "0.7" 14 | sysinfo = "0.28.1" 15 | keyring = "2.0" 16 | log = "0.4" 17 | systemd-journal-logger = "0.7" 18 | mqtt-async-client = "0.3" 19 | rpassword = "7.2" 20 | serde = { version = "1.0", features = ["derive"] } 21 | serde_json = "1" 22 | serde_yaml = "0.9" 23 | anyhow = "1.0.69" 24 | tokio = { version = "1", features = ["full"] } 25 | url = { version = "2.2", features = ["serde"] } 26 | users = "0.11.0" 27 | simple_logger = "4.0.0" 28 | 29 | [package.metadata.deb] 30 | systemd-units = { unit-name = "system-mqtt", unit-scripts = "systemd", enable = true } 31 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2021-2023 James Carl 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # System MQTT 2 | 3 | Inspired by [system-bridge](https://github.com/timmo001/system-bridge), System MQTT is essentially the same thing but for a different audience. 4 | 5 | System MQTT takes several statistics from the computer it is running on and then reports them to an MQTT broker. With that it also transmits the necessary discovery messages to that broker for Home Assistant to be made aware of the device. 6 | 7 | At this point in time the following information is reported: 8 | 9 | * CPU usage 10 | * Memory usage 11 | * Swap usage 12 | * Filesystem usage 13 | * Battery state 14 | * Battery level 15 | 16 | The advantage of system-mqtt is that it's light weight in comparison to system-bridge. Weighing in at under a Megabyte and a CPU usage so small I can't get it to show up under htop, system-mqtt is light enough to run on your Pi. 17 | 18 | The downside of system-mqtt is that its meant more for power users. There's no system tray icon, no web interface, or really any UI at all. All of the configuration is done using a config folder under `/etc/system-mqtt.yaml`. It's easy enough to work with but not certainly not as pretty as system-bridge. 19 | 20 | # Supported platforms 21 | 22 | My main goal was for this to run on Linux, specifically Debian based distros since that's what I primarily use. In theory a port to Windows should require very minimal effort. Feel free to make a pull request if you wish to add such functionality. If you want some other package format like RPM, again, feel free to make a pull request and add such functionality. 23 | 24 | # Adding more statistics 25 | 26 | Want more statistics to be reported? I'm fine with that. Just make a pull request. My main requirements be that you run `cargo fmt`, avoid use of `unsafe`, keep the memory usage at runtime under a Megabyte, and keep the CPU usage unnoticed. 27 | 28 | If for some reason your feature just can't be fit within those requirement, make the pull request anyway and we'll talk about it. I'm sure we can find a compromise. 29 | 30 | # Dependencies 31 | 32 | * Building `system-mqtt` requires the Rust toolchain including the `cargo` package manager. Default repositories may be out of date and fail to build, so it is recommended to install Rust using the installer at [Rustup](https://rustup.rs/). Remove any existing instances of `rustc` on your system, and install a fresh copy of Rust using the instructions on Rustup.rs. 33 | * The Cargo helper command [cargo-deb](https://crates.io/crates/cargo-deb) is required to allow `cargo` to build a .deb package. Once Rust is installed, add `cargo-deb` with the command `cargo install cargo-deb`. 34 | * `libdbus-1-dev` is required, but not installed by default on many Debian systems. `sudo apt install libdbus-1-dev` will install from the Debian or Ubuntu repositories. 35 | * `libdbus-1-3` or similar is required, but is installed by default on most Debian and Ubuntu systems. 36 | 37 | # Installation 38 | 39 | I brewed this up in less than a day and have less than an hour of runtime with it, so I don't feel ready to publish proper releases or a fancy pre-packaged installer. This means you'll be installing it from source. 40 | 41 | Step 1: [Setup MQTT with Home Assistant](https://www.home-assistant.io/integrations/mqtt/). 42 | 43 | Step 2: Clone this repository. 44 | 45 | Step 3: Verify all dependencies are installed. 46 | 47 | Step 4: Run the command `cargo deb --install` from the cloned directory. 48 | 49 | At this point you've installed `system-mqtt` as a debian package that can easily be removed. It will automatically be registered with systemd, but may require a manual start with `systemctl start system-mqtt`. 50 | 51 | At this point the daemon is installed, but won't run if the mqtt broker is not running on the local system. You'll need to edit the configuration to let it know about the mqtt broker and its credentials. 52 | 53 | # Configuration 54 | 55 | The configuration file lives at `/etc/system-mqtt.yaml`. 56 | 57 | If it does not appear when you first install system-mqtt, it will be created and populated when `system-mqtt` is run with default arguments. 58 | 59 | Here is the default config with comments added explaining the configuration options: 60 | ```yaml 61 | # The URL to the mqtt broker. 62 | mqtt_server: "mqtt://localhost" 63 | 64 | # If no authentication is needed to log into the mqtt broker, leave this be. 65 | # If authentication is needed, set this to the user name. The password will 66 | # be fetched from the OS keyring. 67 | # To set that password, run `system-mqtt set-password` and an interactive 68 | # prompt will ask you for the login password. 69 | username: ~ 70 | 71 | # If unspecified, this will default to `keyring`, where it uses the system keyring for your password. 72 | password_source: keyring 73 | 74 | # Alternatively, you can use a "secret file" for your password. It's an unencrypted plaintext file with the password. You must set the file to be owned by the user running system-mqtt (typically root) and set the permissions so that only the user can access the file. 75 | # This is derived from the security policies used by ssh and OpenPGP. It's a little less ideal than keyring so you should prefer keyring if you can use it. 76 | # Here's an example of how you'd point to where that file is located: 77 | # password_source: !secret_file /path/to/file 78 | 79 | # The amount of time to wait between each report of the system statistics. 80 | update_interval: 81 | secs: 30 82 | nanos: 0 83 | 84 | # You can have multiple filesystem disk usages be reported. 85 | # Each entry here should have its path be set to the root of the filesystem 86 | # you wish to report the usage of, and the name is what name it will 87 | # reported as to mqtt. 88 | drives: 89 | - path: / 90 | name: root 91 | ``` 92 | 93 | Once you have adjusted the configuration as needed, run `systemctl reload system-mqtt` to restart the service with the new configuration. 94 | 95 | Run `systemctl status system-mqtt` after to verify the configuration loaded and the daemon is running correctly. 96 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use anyhow::{bail, Context, Result}; 2 | use argh::FromArgs; 3 | use mqtt_async_client::client::{Client as MqttClient, Publish}; 4 | use serde::{Deserialize, Serialize}; 5 | use std::{ 6 | collections::{HashMap, HashSet}, 7 | os::unix::prelude::MetadataExt, 8 | path::{Path, PathBuf}, 9 | time::Duration, 10 | }; 11 | use sysinfo::{CpuExt, DiskExt, System, SystemExt}; 12 | use tokio::{fs, signal, time}; 13 | use url::Url; 14 | 15 | const KEYRING_SERVICE_NAME: &str = "system-mqtt"; 16 | 17 | #[derive(FromArgs)] 18 | /// Push system statistics to an mqtt server. 19 | struct Arguments { 20 | /// the configuration file we are to use. 21 | #[argh(option, default = "PathBuf::from(\"/etc/system-mqtt.yaml\")")] 22 | config_file: PathBuf, 23 | 24 | #[argh(subcommand)] 25 | command: SubCommand, 26 | } 27 | 28 | #[derive(FromArgs, PartialEq, Debug)] 29 | #[argh(subcommand)] 30 | enum SubCommand { 31 | Run(RunArguments), 32 | SetPassword(SetPasswordArguments), 33 | } 34 | 35 | #[derive(FromArgs, PartialEq, Debug)] 36 | /// Run the daemon. 37 | #[argh(subcommand, name = "run")] 38 | struct RunArguments { 39 | /// log to stderr instead of systemd's journal. 40 | #[argh(switch)] 41 | log_to_stderr: bool, 42 | } 43 | 44 | #[derive(FromArgs, PartialEq, Debug)] 45 | /// Set the password used to log into the mqtt client. 46 | #[argh(subcommand, name = "set-password")] 47 | struct SetPasswordArguments {} 48 | 49 | #[derive(Serialize, Deserialize)] 50 | struct DriveConfig { 51 | path: PathBuf, 52 | name: String, 53 | } 54 | 55 | #[derive(Serialize, Deserialize)] 56 | enum PasswordSource { 57 | #[serde(rename = "keyring")] 58 | Keyring, 59 | 60 | #[serde(rename = "secret_file")] 61 | SecretFile(PathBuf), 62 | } 63 | 64 | impl Default for PasswordSource { 65 | fn default() -> Self { 66 | Self::Keyring 67 | } 68 | } 69 | 70 | #[derive(Serialize, Deserialize)] 71 | struct Config { 72 | /// The URL of the mqtt server. 73 | mqtt_server: Url, 74 | 75 | /// Set the username to connect to the mqtt server, if required. 76 | /// The password will be fetched from the OS keyring. 77 | username: Option, 78 | 79 | /// Where the password for the MQTT server can be found. 80 | /// If a username is not specified, this field is ignored. 81 | /// If not specified, this field defaults to the keyring. 82 | #[serde(default)] 83 | password_source: PasswordSource, 84 | 85 | /// The interval to update at. 86 | update_interval: Duration, 87 | 88 | /// The names of drives, or the paths to where they are mounted. 89 | drives: Vec, 90 | } 91 | 92 | impl Default for Config { 93 | fn default() -> Self { 94 | Self { 95 | mqtt_server: Url::parse("mqtt://localhost").expect("Failed to parse default URL."), 96 | username: None, 97 | password_source: PasswordSource::Keyring, 98 | update_interval: Duration::from_secs(30), 99 | drives: vec![DriveConfig { 100 | path: PathBuf::from("/"), 101 | name: String::from("root"), 102 | }], 103 | } 104 | } 105 | } 106 | 107 | #[tokio::main] 108 | async fn main() { 109 | let arguments: Arguments = argh::from_env(); 110 | 111 | match load_config(&arguments.config_file).await { 112 | Ok(config) => match arguments.command { 113 | SubCommand::Run(arguments) => { 114 | if arguments.log_to_stderr { 115 | simple_logger::SimpleLogger::new() 116 | .env() 117 | .init() 118 | .expect("Failed to setup log."); 119 | } else { 120 | systemd_journal_logger::init().expect("Failed to setup log."); 121 | } 122 | 123 | log::set_max_level(log::LevelFilter::Info); 124 | 125 | while let Err(error) = application_trampoline(&config).await { 126 | log::error!("Fatal error: {}", error); 127 | } 128 | } 129 | SubCommand::SetPassword(_arguments) => { 130 | if let Err(error) = set_password(config).await { 131 | eprintln!("Fatal error: {}", error); 132 | } 133 | } 134 | }, 135 | Err(error) => { 136 | eprintln!("Failed to load config file: {}", error); 137 | } 138 | } 139 | } 140 | 141 | async fn load_config(path: &Path) -> Result { 142 | if path.is_file() { 143 | // It's a readable file we can load. 144 | 145 | let config: Config = serde_yaml::from_str(&fs::read_to_string(path).await?) 146 | .context("Failed to deserialize config file.")?; 147 | 148 | Ok(config) 149 | } else { 150 | log::info!("No config file present. A default one will be written."); 151 | // Doesn't exist yet. We'll create it. 152 | let config = Config::default(); 153 | 154 | // Write it to a file for next time we load. 155 | fs::write(path, serde_yaml::to_string(&config)?).await?; 156 | 157 | Ok(config) 158 | } 159 | } 160 | 161 | async fn set_password(config: Config) -> Result<()> { 162 | if let Some(username) = config.username { 163 | let password = rpassword::prompt_password("Password: ") 164 | .context("Failed to read password from TTY.")?; 165 | 166 | let keyring = keyring::Entry::new(KEYRING_SERVICE_NAME, &username) 167 | .context("Failed to find password entry in keyring.")?; 168 | keyring.set_password(&password).context("Keyring error.")?; 169 | 170 | Ok(()) 171 | } else { 172 | bail!("You must set the username for login with the mqtt server before you can set the user's password") 173 | } 174 | } 175 | 176 | async fn application_trampoline(config: &Config) -> Result<()> { 177 | log::info!("Application start."); 178 | 179 | let mut client_builder = MqttClient::builder(); 180 | client_builder.set_url_string(config.mqtt_server.as_str())?; 181 | 182 | // If credentials are provided, use them. 183 | if let Some(username) = &config.username { 184 | // TODO make TLS mandatory when using a password. 185 | 186 | let password = match &config.password_source { 187 | PasswordSource::Keyring => { 188 | log::info!("Using system keyring for MQTT password source."); 189 | let keyring = keyring::Entry::new(KEYRING_SERVICE_NAME, username) 190 | .context("Failed to find password entry in keyring.")?; 191 | keyring 192 | .get_password() 193 | .context("Failed to get password from keyring. If you have not yet set the password, run `system-mqtt set-password`.")? 194 | } 195 | PasswordSource::SecretFile(file_path) => { 196 | log::info!("Using hidden file for MQTT password source."); 197 | let metadata = file_path 198 | .metadata() 199 | .context("Failed to get password file metadata.")?; 200 | 201 | // It's not even an encrypted file, so we need to keep the permission settings pretty tight. 202 | // The only time I can really enforce that is when reading the password. 203 | if metadata.mode() & 0o777 == 0o600 { 204 | if metadata.uid() == users::get_current_uid() { 205 | if metadata.gid() == users::get_current_gid() { 206 | let pass: String = fs::read_to_string(file_path) 207 | .await 208 | .context("Failed to read password file.")?; 209 | pass.as_str().trim_end().to_string() 210 | } else { 211 | bail!("Password file must be owned by the current group."); 212 | } 213 | } else { 214 | bail!("Password file must be owned by the current user."); 215 | } 216 | } else { 217 | bail!("Permission bits for password file must be set to 0o600 (only owner can read and write)"); 218 | } 219 | } 220 | }; 221 | 222 | client_builder.set_username(Some(username.into())); 223 | client_builder.set_password(Some(password.as_bytes().to_vec())); 224 | } 225 | 226 | let mut client = client_builder.build()?; 227 | client 228 | .connect() 229 | .await 230 | .context("Failed to connect to MQTT server.")?; 231 | 232 | let manager = battery::Manager::new().context("Failed to initalize battery monitoring.")?; 233 | 234 | let mut system = System::new_all(); 235 | 236 | let hostname = system 237 | .host_name() 238 | .context("Could not get system hostname.")?; 239 | 240 | let mut home_assistant = HomeAssistant { 241 | client, 242 | hostname, 243 | registered_topics: HashSet::new(), 244 | }; 245 | 246 | // Register the various sensor topics and include the details about that sensor 247 | 248 | // TODO - create a new register_topic to register binary_sensor so we can make availability a real binary sensor. In the 249 | // meantime, create it as a normal analog sensor with two values, and a template can be used to make it a binary. 250 | 251 | home_assistant 252 | .register_topic( 253 | "sensor", 254 | None, 255 | Some(""), 256 | "available", 257 | None, 258 | Some("mdi:check-network-outline"), 259 | ) 260 | .await 261 | .context("Failed to register availability topic.")?; 262 | home_assistant 263 | .register_topic( 264 | "sensor", 265 | None, 266 | Some(""), 267 | "uptime", 268 | Some("days"), 269 | Some("mdi:timer-sand"), 270 | ) 271 | .await 272 | .context("Failed to register uptime topic.")?; 273 | home_assistant 274 | .register_topic( 275 | "sensor", 276 | None, 277 | Some("measurement"), 278 | "cpu", 279 | Some("%"), 280 | Some("mdi:gauge"), 281 | ) 282 | .await 283 | .context("Failed to register CPU usage topic.")?; 284 | home_assistant 285 | .register_topic( 286 | "sensor", 287 | None, 288 | Some("measurement"), 289 | "memory", 290 | Some("%"), 291 | Some("mdi:gauge"), 292 | ) 293 | .await 294 | .context("Failed to register memory usage topic.")?; 295 | home_assistant 296 | .register_topic( 297 | "sensor", 298 | None, 299 | Some("measurement"), 300 | "swap", 301 | Some("%"), 302 | Some("mdi:gauge"), 303 | ) 304 | .await 305 | .context("Failed to register swap usage topic.")?; 306 | home_assistant 307 | .register_topic( 308 | "sensor", 309 | Some("battery"), 310 | Some("measurement"), 311 | "battery_level", 312 | Some("%"), 313 | Some("mdi:battery"), 314 | ) 315 | .await 316 | .context("Failed to register battery level topic.")?; 317 | home_assistant 318 | .register_topic( 319 | "sensor", 320 | None, 321 | Some(""), 322 | "battery_state", 323 | None, 324 | Some("mdi:battery"), 325 | ) 326 | .await 327 | .context("Failed to register battery state topic.")?; 328 | 329 | // Register the sensors for filesystems 330 | for drive in &config.drives { 331 | home_assistant 332 | .register_topic( 333 | "sensor", 334 | None, 335 | Some("total"), 336 | &drive.name, 337 | Some("%"), 338 | Some("mdi:folder"), 339 | ) 340 | .await 341 | .context("Failed to register a filesystem topic.")?; 342 | } 343 | 344 | home_assistant.set_available(true).await?; 345 | 346 | let result = availability_trampoline(&home_assistant, &mut system, config, manager).await; 347 | 348 | if let Err(error) = home_assistant.set_available(false).await { 349 | // I don't want this error hiding whatever happened in the main loop. 350 | log::error!("Error while disconnecting from home assistant: {:?}", error); 351 | } 352 | 353 | result?; 354 | 355 | home_assistant.disconnect().await?; 356 | 357 | Ok(()) 358 | } 359 | 360 | async fn availability_trampoline( 361 | home_assistant: &HomeAssistant, 362 | system: &mut System, 363 | config: &Config, 364 | manager: battery::Manager, 365 | ) -> Result<()> { 366 | let drive_list: HashMap = config 367 | .drives 368 | .iter() 369 | .map(|drive_config| (drive_config.path.clone(), drive_config.name.clone())) 370 | .collect(); 371 | 372 | system.refresh_disks(); 373 | system.refresh_memory(); 374 | system.refresh_cpu(); 375 | 376 | loop { 377 | tokio::select! { 378 | _ = time::sleep(config.update_interval) => { 379 | system.refresh_disks(); 380 | system.refresh_memory(); 381 | system.refresh_cpu(); 382 | 383 | // Report uptime. 384 | let uptime = system.uptime() as f32 / 60.0 / 60.0 / 24.0; // Convert from seconds to days. 385 | home_assistant.publish("uptime", format!("{}", uptime)).await; 386 | 387 | // Report CPU usage. 388 | let cpu_usage = (system.cpus().iter().map(|cpu| cpu.cpu_usage()).sum::()) / (system.cpus().len() as f32 * 100.0); 389 | home_assistant.publish("cpu", (cpu_usage * 100.0).to_string()).await; 390 | 391 | // Report memory usage. 392 | let memory_percentile = (system.total_memory() - system.available_memory()) as f64 / system.total_memory() as f64; 393 | home_assistant.publish("memory", (memory_percentile.clamp(0.0, 1.0)* 100.0).to_string()).await; 394 | 395 | // Report swap usage. 396 | let swap_percentile = system.used_swap() as f64 / system.free_swap() as f64; 397 | home_assistant.publish("swap", (swap_percentile.clamp(0.0, 1.0) * 100.0).to_string()).await; 398 | 399 | // Report filesystem usage. 400 | for drive in system.disks() { 401 | if let Some(drive_name) = drive_list.get(drive.mount_point()) { 402 | let drive_percentile = (drive.total_space() - drive.available_space()) as f64 / drive.total_space() as f64; 403 | 404 | home_assistant.publish(drive_name, (drive_percentile.clamp(0.0, 1.0) * 100.0).to_string()).await; 405 | } 406 | } 407 | 408 | // TODO we should probably combine the battery charges, but for now we're just going to use the first detected battery. 409 | if let Some(battery) = manager.batteries().context("Failed to read battery info.")?.flatten().next() { 410 | use battery::State; 411 | 412 | let battery_state = match battery.state() { 413 | State::Charging => "charging", 414 | State::Discharging => "discharging", 415 | State::Empty => "empty", 416 | State::Full => "full", 417 | _ => "unknown", 418 | }; 419 | 420 | home_assistant.publish("battery_state", battery_state.to_string()).await; 421 | 422 | let battery_full = battery.energy_full(); 423 | let battery_power = battery.energy(); 424 | let battery_level = battery_power / battery_full; 425 | 426 | home_assistant.publish("battery_level", format!("{:03}", battery_level.value)).await; 427 | } 428 | } 429 | _ = signal::ctrl_c() => { 430 | log::info!("Terminate signal has been received."); 431 | break; 432 | } 433 | } 434 | } 435 | 436 | Ok(()) 437 | } 438 | 439 | pub struct HomeAssistant { 440 | client: MqttClient, 441 | hostname: String, 442 | registered_topics: HashSet, 443 | } 444 | 445 | impl HomeAssistant { 446 | pub async fn set_available(&self, available: bool) -> Result<()> { 447 | self.client 448 | .publish( 449 | Publish::new( 450 | format!("system-mqtt/{}/availability", self.hostname), 451 | if available { "online" } else { "offline" }.into(), 452 | ) 453 | .set_retain(true), 454 | ) 455 | .await 456 | .context("Failed to publish availability topic.") 457 | } 458 | 459 | pub async fn register_topic( 460 | &mut self, 461 | topic_class: &str, 462 | device_class: Option<&str>, 463 | state_class: Option<&str>, 464 | topic_name: &str, 465 | unit_of_measurement: Option<&str>, 466 | icon: Option<&str>, 467 | ) -> Result<()> { 468 | log::info!("Registering topic `{}`.", topic_name); 469 | 470 | #[derive(Serialize)] 471 | struct TopicConfig { 472 | name: String, 473 | 474 | #[serde(skip_serializing_if = "Option::is_none")] 475 | device_class: Option, 476 | state_class: Option, 477 | state_topic: String, 478 | unit_of_measurement: Option, 479 | icon: Option, 480 | } 481 | 482 | let message = serde_json::ser::to_string(&TopicConfig { 483 | name: format!("{}-{}", self.hostname, topic_name), 484 | device_class: device_class.map(str::to_string), 485 | state_class: state_class.map(str::to_string), 486 | state_topic: format!("system-mqtt/{}/{}", self.hostname, topic_name), 487 | unit_of_measurement: unit_of_measurement.map(str::to_string), 488 | icon: icon.map(str::to_string), 489 | }) 490 | .context("Failed to serialize topic information.")?; 491 | let mut publish = Publish::new( 492 | format!( 493 | "homeassistant/{}/system-mqtt-{}/{}/config", 494 | topic_class, self.hostname, topic_name 495 | ), 496 | message.into(), 497 | ); 498 | publish.set_retain(true); 499 | self.client 500 | .publish(&publish) 501 | .await 502 | .context("Failed to publish topic to MQTT server.")?; 503 | 504 | self.registered_topics.insert(topic_name.to_string()); 505 | 506 | Ok(()) 507 | } 508 | 509 | pub async fn publish(&self, topic_name: &str, value: String) { 510 | log::debug!("PUBLISH `{}` TO `{}`", value, topic_name); 511 | 512 | if self.registered_topics.contains(topic_name) { 513 | let mut publish = Publish::new( 514 | format!("system-mqtt/{}/{}", self.hostname, topic_name), 515 | value.into(), 516 | ); 517 | publish.set_retain(false); 518 | 519 | if let Err(error) = self.client.publish(&publish).await { 520 | log::error!("Failed to publish topic `{}`: {:?}", topic_name, error); 521 | } 522 | } else { 523 | log::error!( 524 | "Attempt to publish topic `{}`, which was never registered with Home Assistant.", 525 | topic_name 526 | ); 527 | } 528 | } 529 | 530 | pub async fn disconnect(mut self) -> Result<()> { 531 | self.set_available(false).await?; 532 | self.client.disconnect().await?; 533 | 534 | Ok(()) 535 | } 536 | } 537 | -------------------------------------------------------------------------------- /systemd/system-mqtt.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Broadcasts system statistics to an mqtt server of your choice. 3 | After=network-online.target 4 | 5 | [Service] 6 | User=root 7 | ExecStart=/usr/bin/system-mqtt run 8 | ExecReload=/bin/kill -HUP $MAINPID 9 | Restart=on-failure 10 | 11 | [Install] 12 | WantedBy=multi-user.target --------------------------------------------------------------------------------