Merge branch 'feature/websocket-api' into develop

This commit is contained in:
Erwin Boskma 2022-04-07 21:24:21 +02:00
commit 1878c99482
Signed by: erwin
GPG key ID: 270B20D17394F7E5
6 changed files with 800 additions and 118 deletions

563
Cargo.lock generated
View file

@ -28,9 +28,25 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.52"
version = "1.0.56"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84450d0b4a8bd1ba4144ce8ce718fbc5d071358b1e5384bace6536b3d1f2d5b3"
checksum = "4361135be9122e0870de935d7c439aef945b9f9ddd4199a553b5270b49c82a27"
[[package]]
name = "async-tungstenite"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7922abeade7dd8948c20dfa1f85dc48cc952d2e0791f7c42b8b1cbb07a57129d"
dependencies = [
"futures-io",
"futures-util",
"log",
"pin-project-lite",
"rustls-native-certs",
"tokio",
"tokio-rustls",
"tungstenite",
]
[[package]]
name = "atty"
@ -76,12 +92,27 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
dependencies = [
"generic-array",
]
[[package]]
name = "bumpalo"
version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]]
name = "bytes"
version = "1.1.0"
@ -102,9 +133,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clap"
version = "3.0.0-beta.5"
version = "3.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feff3878564edb93745d58cf63e17b63f24142506e7a20c87a5521ed7bfb1d63"
checksum = "d8c93436c21e4698bacadf42917db28b23017027a4deccb35dbe47a7e7840123"
dependencies = [
"atty",
"bitflags",
@ -120,9 +151,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "3.0.0-beta.5"
version = "3.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b15c6b4f786ffb6192ffe65a36855bc1fc2444bcd0945ae16748dcd6ed7d0d3"
checksum = "da95d038ede1a964ce99f49cbe27a7fb538d1da595e4b4f70b8c8f338d17bf16"
dependencies = [
"heck",
"proc-macro-error",
@ -133,9 +164,9 @@ dependencies = [
[[package]]
name = "color-eyre"
version = "0.6.0"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d6ec7641ff3474b7593009c809db602c414cd97c7d47a78ed004162b74ff96c"
checksum = "8ebf286c900a6d5867aeff75cfee3192857bb7f24b547d4f0df2ed6baa812c90"
dependencies = [
"backtrace",
"color-spantrace",
@ -174,6 +205,35 @@ version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "cpufeatures"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b"
dependencies = [
"libc",
]
[[package]]
name = "crypto-common"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
dependencies = [
"block-buffer",
"crypto-common",
]
[[package]]
name = "encoding_rs"
version = "0.8.29"
@ -225,46 +285,87 @@ dependencies = [
]
[[package]]
name = "futures-channel"
version = "0.3.18"
name = "futures"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27"
checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.18"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445"
checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
[[package]]
name = "futures-executor"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.18"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11"
checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
[[package]]
name = "futures-macro"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.18"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af"
checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
[[package]]
name = "futures-task"
version = "0.3.18"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12"
checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
[[package]]
name = "futures-util"
version = "0.3.18"
version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e"
checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
dependencies = [
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
@ -272,6 +373,16 @@ dependencies = [
"slab",
]
[[package]]
name = "generic-array"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "getrandom"
version = "0.2.3"
@ -280,7 +391,7 @@ checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if",
"libc",
"wasi",
"wasi 0.10.2+wasi-snapshot-preview1",
]
[[package]]
@ -291,9 +402,9 @@ checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4"
[[package]]
name = "h2"
version = "0.3.7"
version = "0.3.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fd819562fcebdac5afc5c113c3ec36f902840b70fd4fc458799c8ce4607ae55"
checksum = "62eeb471aa3e3c9197aa4bfeabfe02982f6dc96f750486c0bb0009ac58b26d2b"
dependencies = [
"bytes",
"fnv",
@ -310,17 +421,22 @@ dependencies = [
[[package]]
name = "ha-now-playing"
version = "0.3.2"
version = "0.4.0"
dependencies = [
"anyhow",
"async-tungstenite",
"clap",
"color-eyre",
"futures",
"html-escape",
"reqwest",
"serde",
"serde_json",
"tokio",
"tracing",
"tracing-error",
"tracing-subscriber",
"tracing-tree",
]
[[package]]
@ -331,12 +447,9 @@ checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "heck"
version = "0.3.3"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c"
dependencies = [
"unicode-segmentation",
]
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "hermit-abi"
@ -349,9 +462,9 @@ dependencies = [
[[package]]
name = "html-escape"
version = "0.2.9"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "816ea801a95538fc5f53c836697b3f8b64a9d664c4f0b91efe1fe7c92e4dbcb7"
checksum = "b8e7479fa1ef38eb49fb6a42c426be515df2d063f06cb8efd3e50af073dbc26c"
dependencies = [
"utf8-width",
]
@ -364,7 +477,7 @@ checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b"
dependencies = [
"bytes",
"fnv",
"itoa",
"itoa 0.4.8",
]
[[package]]
@ -405,7 +518,7 @@ dependencies = [
"http-body",
"httparse",
"httpdate",
"itoa",
"itoa 0.4.8",
"pin-project-lite",
"socket2",
"tokio",
@ -466,6 +579,12 @@ version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "itoa"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
[[package]]
name = "js-sys"
version = "0.3.55"
@ -483,9 +602,18 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.108"
version = "0.2.121"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119"
checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f"
[[package]]
name = "lock_api"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
@ -535,14 +663,15 @@ dependencies = [
[[package]]
name = "mio"
version = "0.7.14"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
checksum = "52da4364ffb0e4fe33a9841a98a3f3014fb964045ce4f7a45a398243c8d6b0c9"
dependencies = [
"libc",
"log",
"miow",
"ntapi",
"wasi 0.11.0+wasi-snapshot-preview1",
"winapi",
]
@ -642,9 +771,9 @@ dependencies = [
[[package]]
name = "os_str_bytes"
version = "4.2.0"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "addaa943333a514159c80c97ff4a93306530d965d27e139188283cd13e06a799"
checksum = "8e22443d1643a904602595ba1cd8f7d896afe56d26712531c5ff73a15b2fbf64"
dependencies = [
"memchr",
]
@ -655,6 +784,29 @@ version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20448fd678ec04e6ea15bbe0476874af65e98a01515d667aa49f1434dc44ebf4"
[[package]]
name = "parking_lot"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-sys",
]
[[package]]
name = "percent-encoding"
version = "2.1.0"
@ -811,15 +963,16 @@ dependencies = [
[[package]]
name = "reqwest"
version = "0.11.6"
version = "0.11.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66d2927ca2f685faf0fc620ac4834690d29e7abb153add10f5812eef20b5e280"
checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb"
dependencies = [
"base64",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"hyper",
@ -844,12 +997,60 @@ 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 = "rustc-demangle"
version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342"
[[package]]
name = "rustls"
version = "0.20.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fbfeb8d0ddb84706bc597a5574ab8912817c52a397f819e5b614e2265206921"
dependencies = [
"log",
"ring",
"sct",
"webpki",
]
[[package]]
name = "rustls-native-certs"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ca9ebdfa27d3fc180e42879037b5338ab1c040c06affd00d8338598e7800943"
dependencies = [
"openssl-probe",
"rustls-pemfile",
"schannel",
"security-framework",
]
[[package]]
name = "rustls-pemfile"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5eebeaeb360c87bfb72e84abdb3447159c0eaececf1bef2aecd65a8be949d1c9"
dependencies = [
"base64",
]
[[package]]
name = "ryu"
version = "1.0.5"
@ -866,6 +1067,22 @@ dependencies = [
"winapi",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sct"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
dependencies = [
"ring",
"untrusted",
]
[[package]]
name = "security-framework"
version = "2.4.2"
@ -891,18 +1108,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.130"
version = "1.0.136"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.130"
version = "1.0.136"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
dependencies = [
"proc-macro2",
"quote",
@ -911,27 +1128,38 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.72"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527"
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
dependencies = [
"itoa",
"itoa 1.0.1",
"ryu",
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.0"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa",
"itoa 1.0.1",
"ryu",
"serde",
]
[[package]]
name = "sha-1"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sharded-slab"
version = "0.1.4"
@ -941,6 +1169,15 @@ dependencies = [
"lazy_static",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
]
[[package]]
name = "slab"
version = "0.4.5"
@ -955,14 +1192,20 @@ checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
[[package]]
name = "socket2"
version = "0.4.2"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516"
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
name = "strsim"
version = "0.10.0"
@ -1005,18 +1248,38 @@ dependencies = [
[[package]]
name = "textwrap"
version = "0.14.2"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
dependencies = [
"unicode-width",
]
[[package]]
name = "thread_local"
version = "1.1.3"
name = "thiserror"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd"
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "thread_local"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
dependencies = [
"once_cell",
]
@ -1038,20 +1301,35 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
version = "1.14.0"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144"
checksum = "2af73ac49756f3f7c01172e34a23e5d0216f6c32333757c2c61feb2bbff5a5ee"
dependencies = [
"autocfg",
"bytes",
"libc",
"memchr",
"mio",
"num_cpus",
"once_cell",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"winapi",
]
[[package]]
name = "tokio-macros"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio-native-tls"
version = "0.3.0"
@ -1062,6 +1340,17 @@ dependencies = [
"tokio",
]
[[package]]
name = "tokio-rustls"
version = "0.23.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4151fda0cf2798550ad0b34bcfc9b9dcc2a9d2471c895c68f3a8818e54f2389e"
dependencies = [
"rustls",
"tokio",
"webpki",
]
[[package]]
name = "tokio-util"
version = "0.6.9"
@ -1084,9 +1373,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]]
name = "tracing"
version = "0.1.29"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
dependencies = [
"cfg-if",
"pin-project-lite",
@ -1096,9 +1385,9 @@ dependencies = [
[[package]]
name = "tracing-attributes"
version = "0.1.18"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f480b8f81512e825f337ad51e94c1eb5d3bbdf2b363dcd01e2b19a9ffe3f8e"
checksum = "2e65ce065b4b5c53e73bb28912318cb8c9e9ad3921f1d669eb0e68b4c8143a2b"
dependencies = [
"proc-macro2",
"quote",
@ -1107,11 +1396,12 @@ dependencies = [
[[package]]
name = "tracing-core"
version = "0.1.21"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
checksum = "aa31669fa42c09c34d94d8165dd2012e8ff3c66aca50f3bb226b68f216f2706c"
dependencies = [
"lazy_static",
"valuable",
]
[[package]]
@ -1137,9 +1427,9 @@ dependencies = [
[[package]]
name = "tracing-subscriber"
version = "0.3.5"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d81bfa81424cc98cb034b837c985b7a290f592e5b4322f353f94a0ab0f9f594"
checksum = "9e0ab7bdc962035a87fba73f3acca9b8a8d0034c2e6f60b84aeaaddddc155dce"
dependencies = [
"ansi_term",
"lazy_static",
@ -1153,12 +1443,52 @@ dependencies = [
"tracing-log",
]
[[package]]
name = "tracing-tree"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ce989c9962c7f61fe084dd4a230eec784649dfc2392467c790007c3a6e134e7"
dependencies = [
"ansi_term",
"atty",
"tracing-core",
"tracing-log",
"tracing-subscriber",
]
[[package]]
name = "try-lock"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "tungstenite"
version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d96a2dea40e7570482f28eb57afbe42d97551905da6a9400acc5c328d24004f5"
dependencies = [
"base64",
"byteorder",
"bytes",
"http",
"httparse",
"log",
"rand",
"rustls",
"sha-1",
"thiserror",
"url",
"utf-8",
"webpki",
]
[[package]]
name = "typenum"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
[[package]]
name = "unicase"
version = "2.6.0"
@ -1183,12 +1513,6 @@ dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-width"
version = "0.1.9"
@ -1201,6 +1525,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]]
name = "url"
version = "2.2.2"
@ -1213,12 +1543,24 @@ dependencies = [
"percent-encoding",
]
[[package]]
name = "utf-8"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "utf8-width"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cf7d77f457ef8dfa11e4cd5933c5ddb5dc52a94664071951219a97710f0a32b"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "vcpkg"
version = "0.2.15"
@ -1227,9 +1569,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version_check"
version = "0.9.3"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "want"
@ -1247,6 +1589,12 @@ version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.78"
@ -1323,6 +1671,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"
@ -1355,10 +1713,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "winreg"
version = "0.7.0"
name = "windows-sys"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69"
checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6"
dependencies = [
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5"
[[package]]
name = "windows_i686_gnu"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615"
[[package]]
name = "windows_i686_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172"
[[package]]
name = "windows_x86_64_gnu"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.32.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"
[[package]]
name = "winreg"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d"
dependencies = [
"winapi",
]

View file

@ -1,20 +1,25 @@
[package]
name = "ha-now-playing"
description = "Retrieves the state of a media_player entity from Home Assistant"
version = "0.3.2"
version = "0.4.0"
authors = ["Erwin Boskma <erwin@datarift.nl>"]
edition = "2021"
[dependencies]
anyhow = "1.0.52"
clap = "3.0.0-beta.2"
color-eyre = "0.6.0"
html-escape = "0.2.9"
reqwest = { version = "0.11.4", features = ["blocking", "json"] }
serde = { version = "1.0.126", features = ["derive"] }
serde_json = "1.0.64"
tracing = "0.1.29"
tracing-subscriber = { version = "0.3.5", features = ["env-filter"] }
anyhow = "1.0.56"
async-tungstenite = { version = "0.17.1", features = ["tokio-rustls-native-certs"] }
clap = { version = "3.1.6", features = ["cargo", "unicode", "derive", "env"] }
color-eyre = "0.6.1"
futures = "0.3.21"
html-escape = "0.2.11"
reqwest = { version = "0.11.10", features = ["blocking", "json"] }
serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0.79"
tokio = { version = "1.17.0", features = ["full"] }
tracing = "0.1.32"
tracing-error = "0.2.0"
tracing-subscriber = { version = "0.3.9", features = ["env-filter", "registry"] }
tracing-tree = "0.2.0"
[profile.release]
opt-level = "z"

View file

@ -7,11 +7,11 @@
]
},
"locked": {
"lastModified": 1639947939,
"narHash": "sha256-pGsM8haJadVP80GFq4xhnSpNitYNQpaXk4cnA796Cso=",
"lastModified": 1649096192,
"narHash": "sha256-7O8e+eZEYeU+ET98u/zW5epuoN/xYx9G+CIh4DjZVzY=",
"owner": "nmattia",
"repo": "naersk",
"rev": "2fc8ce9d3c025d59fee349c1f80be9785049d653",
"rev": "d626f73332a8f587b613b0afe7293dd0777be07d",
"type": "github"
},
"original": {
@ -23,11 +23,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1647350163,
"narHash": "sha256-OcMI+PFEHTONthXuEQNddt16Ml7qGvanL3x8QOl2Aao=",
"lastModified": 1648219316,
"narHash": "sha256-Ctij+dOi0ZZIfX5eMhgwugfvB+WZSrvVNAyAuANOsnQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "3eb07eeafb52bcbf02ce800f032f18d666a9498d",
"rev": "30d3d79b7d3607d56546dd2a6b49e156ba0ec634",
"type": "github"
},
"original": {
@ -55,11 +55,11 @@
]
},
"locked": {
"lastModified": 1647829973,
"narHash": "sha256-z3gJX54DX6v4nQS1OgggtnZ4qRcqknoS3/WpX5ksceA=",
"lastModified": 1649298784,
"narHash": "sha256-rUwQKjBOZiRpzgkG3h9OM5pUyxRYIV45ohgqZJtSZtE=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "458f4fcd4450b8bfd2e2c8ca4f7673809bfe344c",
"rev": "c6fe2a14f10cb85659b8848bac87e4ff29a00f9a",
"type": "github"
},
"original": {
@ -70,11 +70,11 @@
},
"utils": {
"locked": {
"lastModified": 1644229661,
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
"lastModified": 1648297722,
"narHash": "sha256-W+qlPsiZd8F3XkzXOzAoR+mpFqzm3ekQkJNa+PIh1BQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
"rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade",
"type": "github"
},
"original": {

View file

@ -42,18 +42,18 @@
root = ./.;
};
defaultPackage = packages.ha-now-playing;
packages.default = packages.ha-now-playing;
apps.ha-now-playing = utils.lib.mkApp {
drv = self.defaultPackage."${system}";
};
defaultApp = apps.ha-now-playing;
apps.default = apps.ha-now-playing;
overlays = final: prev: {
ha-now-playing = packages.ha-now-playing;
};
devShell = with pkgs; mkShell {
devShells.default = with pkgs; mkShell {
inherit buildInputs;
nativeBuildInputs = [ cargo-edit cargo-expand cargo-diet cargo-feature cargo-outdated rust-analyzer pre-commit jq gitflow ] ++ nativeBuildInputs;
};

250
src/homeassistant.rs Normal file
View file

@ -0,0 +1,250 @@
use async_tungstenite::{tokio::connect_async, tungstenite};
use color_eyre::{eyre::eyre, Result};
use futures::{SinkExt, StreamExt};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use tracing::{debug, error, trace};
pub(crate) struct HomeAssistant {
token: String,
entity: String,
insecure: bool,
host: String,
id: u64,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
struct Message {
#[serde(rename = "type")]
message_type: MessageType,
#[serde(skip_serializing_if = "Option::is_none")]
ha_version: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
access_token: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
message: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
event_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
success: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
id: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
event: Option<Event>,
#[serde(skip_serializing_if = "Option::is_none")]
result: Option<Value>,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
struct Event {
data: EventData,
time_fired: String,
origin: String,
context: EventContext,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
struct EventData {
new_state: EntityState,
old_state: EntityState,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
struct EventContext {
id: String,
parent_id: Option<String>,
user_id: Option<String>,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
struct EntityState {
entity_id: String,
last_changed: String,
state: String,
attributes: Value,
last_updated: String,
context: EventContext,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
enum MessageType {
AuthRequired,
Auth,
AuthOk,
AuthInvalid,
Result,
SubscribeEvents,
Event,
SubscribeTrigger,
UnsubscribeEvents,
FireEvent,
CallService,
GetStates,
GetConfig,
GetServices,
GetPanels,
CameraThumbnail,
MediaPlayerThumbnail,
Ping,
Pong,
ValidateConfig,
}
impl Default for MessageType {
fn default() -> Self {
MessageType::Pong
}
}
impl Message {
fn auth() -> Self {
let mut msg = Self::default();
msg.message_type = MessageType::Auth;
msg
}
fn subscribe_events() -> Self {
let mut msg = Self::default();
msg.message_type = MessageType::SubscribeEvents;
msg
}
fn get_states() -> Self {
let mut msg = Self::default();
msg.message_type = MessageType::GetStates;
msg
}
fn to_json(self) -> String {
serde_json::to_string(&self).unwrap()
}
fn to_message(self) -> tungstenite::Message {
tungstenite::Message::from(self.to_json())
}
}
impl HomeAssistant {
pub(crate) fn new(host: String, entity: String, insecure: bool, token: String) -> Self {
Self {
token,
entity,
insecure,
host,
id: 1,
}
}
fn incrementing_id(&mut self) -> u64 {
let id = self.id;
self.id = self.id.wrapping_add(1);
id
}
pub(crate) async fn open_connection(mut self) -> Result<()> {
let api_url = format!(
"{}://{}/api/websocket",
if self.insecure { "ws" } else { "wss" },
self.host
);
debug!("Connecting to URL {api_url}");
let (mut ws_stream, _) = connect_async(&api_url).await?;
while let Some(msg) = ws_stream.next().await {
let msg = msg?;
match self.handle_message(msg).await {
Ok(response_messages) => {
for response in response_messages {
ws_stream.send(response).await?
}
}
Err(e) => {
error!("{e}");
}
}
}
Err(eyre!(
"TODO: Connect to {} and subscribe to {}",
api_url,
self.entity
))
}
async fn handle_message(
&mut self,
msg: tungstenite::Message,
) -> Result<Vec<tungstenite::Message>> {
trace!("{}", msg.clone().into_text()?);
let message: Message = serde_json::from_slice(&msg.into_data())?;
trace!("Received: {message:?}");
let response = match message.message_type {
MessageType::AuthRequired => {
debug!("Sending Authentication Data");
let mut auth = Message::auth();
auth.access_token = Some(self.token.clone());
vec![auth.to_message()]
}
MessageType::AuthOk => {
let mut subscribe = Message::subscribe_events();
subscribe.event_type = Some("state_changed".into());
subscribe.id = Some(self.incrementing_id());
let mut get_states = Message::get_states();
get_states.id = Some(self.incrementing_id());
vec![subscribe.to_message(), get_states.to_message()]
}
MessageType::Event => {
let event = message.event.unwrap();
if event.data.new_state.entity_id == self.entity {
Self::print_state(event.data.new_state.state, event.data.new_state.attributes);
}
vec![]
}
MessageType::Result => {
debug!("{}", message.to_json());
vec![]
}
_ => return Err(eyre!("TODO: Handle {:?}", message.message_type)),
};
Ok(response)
}
fn print_state(state: String, attributes: Value) {
if state == "playing" {
let maybe_channel = attributes["media_channel"].as_str();
let artist = attributes["media_artist"].as_str().unwrap_or("No artist");
let title = attributes["media_title"].as_str().unwrap_or("No title");
let volume_raw = attributes["volume_level"].as_f64().unwrap_or(-1.);
let is_muted = attributes["is_volume_muted"].as_bool().unwrap_or(false);
let volume = if is_muted {
String::from("[ ﱝ ]")
} else if volume_raw >= 0. {
format!("[{:3.0}%] ", volume_raw * 100.)
} else {
String::new()
};
let now_playing = if let Some(channel) = maybe_channel {
format!("{volume}[{channel}] {artist} - {title}")
} else {
format!("{volume}{artist} - {title}")
};
println!("{}", html_escape::encode_text(&now_playing));
} else {
println!("Sonos {state}");
}
}
}

View file

@ -5,8 +5,12 @@ use clap::Parser;
use color_eyre::{eyre::WrapErr, Result};
use serde_json::json;
use std::fmt::Display;
use tracing::debug;
use tracing_subscriber::EnvFilter;
use tracing::{debug, trace};
use tracing_error::ErrorLayer;
use tracing_subscriber::{prelude::*, EnvFilter, Registry};
use tracing_tree::HierarchicalLayer;
mod homeassistant;
/// Bert
#[derive(Parser, Debug)]
@ -21,11 +25,11 @@ struct Opts {
entity: String,
/// API token
#[clap(short, long)]
#[clap(short, long, env)]
token: Option<String>,
/// File with the API token
#[clap(long)]
#[clap(long, env)]
token_file: Option<PathBuf>,
/// Use HTTP instead of HTTPS
@ -47,6 +51,8 @@ enum Command {
VolumeUp,
/// Lower volume
VolumeDown,
/// Set volume to value
Volume { volume: u8 },
}
impl Display for Command {
@ -55,11 +61,13 @@ impl Display for Command {
Command::PlayPause => write!(f, "Play/Pause"),
Command::VolumeUp => write!(f, "Volume Up"),
Command::VolumeDown => write!(f, "Volume Down"),
Command::Volume { volume } => write!(f, "Volume {volume}"),
}
}
}
fn main() -> Result<()> {
#[tokio::main]
async fn main() -> Result<()> {
let opts = Opts::parse();
let Opts {
@ -91,11 +99,15 @@ fn main() -> Result<()> {
if let Some(token) = token {
if let Some(cmd) = cmd {
debug!("Calling service '{cmd}' on entity '{entity}'");
call_service(cmd, host, entity, insecure, token)
.wrap_err_with(|| format!("Unable to execute command {cmd}"))?;
} else {
get_now_playing(host, entity, insecure, token)
.wrap_err("Unable to retrieve now playing info")?;
debug!("Retrieving state of '{entity}' on '{host}'");
// get_now_playing(host, entity, insecure, token)
// .wrap_err("Unable to retrieve now playing info")?;
let ha = homeassistant::HomeAssistant::new(host, entity, insecure, token);
ha.open_connection().await.unwrap();
}
}
Ok(())
@ -107,13 +119,19 @@ fn setup(debug: bool) -> Result<()> {
}
color_eyre::install()?;
tracing_subscriber::fmt::fmt()
.with_env_filter(EnvFilter::from_default_env())
.with_writer(std::io::stderr)
Registry::default()
.with(EnvFilter::from_default_env())
.with(
HierarchicalLayer::new(2)
.with_targets(true)
.with_bracketed_fields(true),
)
.with(ErrorLayer::default())
.init();
Ok(())
}
#[tracing::instrument]
fn get_now_playing(host: String, entity: String, insecure: bool, token: String) -> Result<()> {
let url = format!(
"{}://{}/api/states/{}",
@ -131,7 +149,7 @@ fn get_now_playing(host: String, entity: String, insecure: bool, token: String)
.send()?
.json::<serde_json::Value>()?;
debug!("Response: {:#?}", response);
trace!("Response: {:#?}", response);
if response["state"] == "playing" {
let attributes = &response["attributes"];
@ -169,6 +187,7 @@ fn get_now_playing(host: String, entity: String, insecure: bool, token: String)
Ok(())
}
#[tracing::instrument]
fn call_service(
command: Command,
host: String,
@ -180,6 +199,7 @@ fn call_service(
Command::PlayPause => "media_play_pause",
Command::VolumeUp => "volume_up",
Command::VolumeDown => "volume_down",
Command::Volume { .. } => "volume_set",
};
let url = format!(
@ -189,7 +209,13 @@ fn call_service(
cmd
);
let body = json!({ "entity_id": entity }).to_string();
let body = match command {
Command::Volume { volume } => {
json!({ "entity_id": entity, "volume_level": volume.clamp(0, 100) as f32 / 100. })
.to_string()
}
_ => json!({ "entity_id": entity }).to_string(),
};
let client = reqwest::blocking::Client::new();
let response = client