feat: unified Logging for frontend and backend

This commit is contained in:
AkiChase 2025-03-25 15:24:37 +08:00
parent 5ebe1ba587
commit 0d847cba4d
21 changed files with 436 additions and 77 deletions

View File

@ -15,6 +15,7 @@
"@tauri-apps/cli": "^2.3.1", "@tauri-apps/cli": "^2.3.1",
"@tauri-apps/plugin-clipboard-manager": "~2.2.1", "@tauri-apps/plugin-clipboard-manager": "~2.2.1",
"@tauri-apps/plugin-http": "~2", "@tauri-apps/plugin-http": "~2",
"@tauri-apps/plugin-log": "~2",
"@tauri-apps/plugin-os": "~2", "@tauri-apps/plugin-os": "~2",
"@tauri-apps/plugin-process": "~2", "@tauri-apps/plugin-process": "~2",
"@tauri-apps/plugin-shell": "~2", "@tauri-apps/plugin-shell": "~2",

View File

@ -20,6 +20,9 @@ importers:
'@tauri-apps/plugin-http': '@tauri-apps/plugin-http':
specifier: ~2 specifier: ~2
version: 2.3.0 version: 2.3.0
'@tauri-apps/plugin-log':
specifier: ~2
version: 2.3.1
'@tauri-apps/plugin-os': '@tauri-apps/plugin-os':
specifier: ~2 specifier: ~2
version: 2.2.0 version: 2.2.0
@ -702,6 +705,9 @@ packages:
'@tauri-apps/plugin-http@2.3.0': '@tauri-apps/plugin-http@2.3.0':
resolution: {integrity: sha512-pigTvz+zzAqbIhCzRiR1GE98Jw7A03j2V+Eiexr9thBI8VfMiwFQMcbgON51xlwnVaI72LdbYKNajU84im8tlg==} resolution: {integrity: sha512-pigTvz+zzAqbIhCzRiR1GE98Jw7A03j2V+Eiexr9thBI8VfMiwFQMcbgON51xlwnVaI72LdbYKNajU84im8tlg==}
'@tauri-apps/plugin-log@2.3.1':
resolution: {integrity: sha512-nnKGHENWt7teqvUlIKxd6bp2wCUrrLvCvajN6CWbyrHBNKPi/pyKELzD511siEMDEdndbiZ/GEhiK0xBtZopRg==}
'@tauri-apps/plugin-os@2.2.0': '@tauri-apps/plugin-os@2.2.0':
resolution: {integrity: sha512-HszbCdbisMlu5QhCNAN8YIWyz2v33abAWha6+uvV2CKX8P5VSct/y+kEe22JeyqrxCnWlQ3DRx7s49Byg7/0EA==} resolution: {integrity: sha512-HszbCdbisMlu5QhCNAN8YIWyz2v33abAWha6+uvV2CKX8P5VSct/y+kEe22JeyqrxCnWlQ3DRx7s49Byg7/0EA==}
@ -1969,6 +1975,10 @@ snapshots:
dependencies: dependencies:
'@tauri-apps/api': 2.1.1 '@tauri-apps/api': 2.1.1
'@tauri-apps/plugin-log@2.3.1':
dependencies:
'@tauri-apps/api': 2.1.1
'@tauri-apps/plugin-os@2.2.0': '@tauri-apps/plugin-os@2.2.0':
dependencies: dependencies:
'@tauri-apps/api': 2.1.1 '@tauri-apps/api': 2.1.1

290
src-tauri/Cargo.lock generated
View File

@ -17,6 +17,17 @@ version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "ahash"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
dependencies = [
"getrandom 0.2.15",
"once_cell",
"version_check",
]
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "1.1.3" version = "1.1.3"
@ -47,6 +58,23 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_log-sys"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d"
[[package]]
name = "android_logger"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f39be698127218cca460cb624878c9aa4e2b47dba3b277963d2bf00bad263b"
dependencies = [
"android_log-sys",
"env_filter",
"log",
]
[[package]] [[package]]
name = "android_system_properties" name = "android_system_properties"
version = "0.1.5" version = "0.1.5"
@ -80,6 +108,12 @@ dependencies = [
"x11rb", "x11rb",
] ]
[[package]]
name = "arrayvec"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
[[package]] [[package]]
name = "atk" name = "atk"
version = "0.18.2" version = "0.18.2"
@ -157,6 +191,18 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "bitvec"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]] [[package]]
name = "block-buffer" name = "block-buffer"
version = "0.10.4" version = "0.10.4"
@ -184,6 +230,29 @@ dependencies = [
"objc2 0.6.0", "objc2 0.6.0",
] ]
[[package]]
name = "borsh"
version = "1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2b74d67a0fc0af8e9823b79fd1c43a0900e5a8f0e0f4cc9210796bf3a820126"
dependencies = [
"borsh-derive",
"cfg_aliases",
]
[[package]]
name = "borsh-derive"
version = "1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d37ed1b2c9b78421218a0b4f6d8349132d6ec2cfeba1cfb0118b0a8e268df9e"
dependencies = [
"once_cell",
"proc-macro-crate 3.3.0",
"proc-macro2",
"quote",
"syn 2.0.99",
]
[[package]] [[package]]
name = "brotli" name = "brotli"
version = "7.0.0" version = "7.0.0"
@ -211,6 +280,39 @@ version = "3.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
[[package]]
name = "byte-unit"
version = "5.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1cd29c3c585209b0cbc7309bfe3ed7efd8c84c21b7af29c8bfae908f8777174"
dependencies = [
"rust_decimal",
"serde",
"utf8-width",
]
[[package]]
name = "bytecheck"
version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2"
dependencies = [
"bytecheck_derive",
"ptr_meta",
"simdutf8",
]
[[package]]
name = "bytecheck_derive"
version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.22.0" version = "1.22.0"
@ -361,8 +463,10 @@ checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
dependencies = [ dependencies = [
"android-tzdata", "android-tzdata",
"iana-time-zone", "iana-time-zone",
"js-sys",
"num-traits", "num-traits",
"serde", "serde",
"wasm-bindgen",
"windows-link", "windows-link",
] ]
@ -783,6 +887,16 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "env_filter"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
dependencies = [
"log",
"regex",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.2" version = "1.0.2"
@ -824,6 +938,15 @@ dependencies = [
"simd-adler32", "simd-adler32",
] ]
[[package]]
name = "fern"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29"
dependencies = [
"log",
]
[[package]] [[package]]
name = "field-offset" name = "field-offset"
version = "0.3.6" version = "0.3.6"
@ -886,6 +1009,12 @@ dependencies = [
"percent-encoding", "percent-encoding",
] ]
[[package]]
name = "funty"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]] [[package]]
name = "futf" name = "futf"
version = "0.1.5" version = "0.1.5"
@ -1320,6 +1449,9 @@ name = "hashbrown"
version = "0.12.3" version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
"ahash",
]
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
@ -1911,6 +2043,9 @@ name = "log"
version = "0.4.26" version = "0.4.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
dependencies = [
"value-bag",
]
[[package]] [[package]]
name = "mac" name = "mac"
@ -2079,6 +2214,15 @@ dependencies = [
"syn 2.0.99", "syn 2.0.99",
] ]
[[package]]
name = "num_threads"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "objc-sys" name = "objc-sys"
version = "0.3.5" version = "0.3.5"
@ -2717,6 +2861,26 @@ version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac"
[[package]]
name = "ptr_meta"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
dependencies = [
"ptr_meta_derive",
]
[[package]]
name = "ptr_meta_derive"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "publicsuffix" name = "publicsuffix"
version = "2.3.0" version = "2.3.0"
@ -2797,6 +2961,12 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "radium"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]] [[package]]
name = "rand" name = "rand"
version = "0.7.3" version = "0.7.3"
@ -2933,6 +3103,15 @@ version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rend"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c"
dependencies = [
"bytecheck",
]
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.12.12" version = "0.12.12"
@ -2997,6 +3176,51 @@ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.52.0",
] ]
[[package]]
name = "rkyv"
version = "0.7.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b"
dependencies = [
"bitvec",
"bytecheck",
"bytes",
"hashbrown 0.12.3",
"ptr_meta",
"rend",
"rkyv_derive",
"seahash",
"tinyvec",
"uuid",
]
[[package]]
name = "rkyv_derive"
version = "0.7.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "rust_decimal"
version = "1.37.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faa7de2ba56ac291bd90c6b9bece784a52ae1411f9506544b3eae36dd2356d50"
dependencies = [
"arrayvec",
"borsh",
"bytes",
"num-traits",
"rand 0.8.5",
"rkyv",
"serde",
"serde_json",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.24" version = "0.1.24"
@ -3133,13 +3357,16 @@ name = "scrcpy-mask"
version = "0.6.0" version = "0.6.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono",
"lazy_static", "lazy_static",
"log",
"serde", "serde",
"serde_json", "serde_json",
"tauri", "tauri",
"tauri-build", "tauri-build",
"tauri-plugin-clipboard-manager", "tauri-plugin-clipboard-manager",
"tauri-plugin-http", "tauri-plugin-http",
"tauri-plugin-log",
"tauri-plugin-os", "tauri-plugin-os",
"tauri-plugin-process", "tauri-plugin-process",
"tauri-plugin-shell", "tauri-plugin-shell",
@ -3147,6 +3374,12 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "seahash"
version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
[[package]] [[package]]
name = "selectors" name = "selectors"
version = "0.22.0" version = "0.22.0"
@ -3357,6 +3590,12 @@ version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
[[package]]
name = "simdutf8"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
[[package]] [[package]]
name = "siphasher" name = "siphasher"
version = "0.3.11" version = "0.3.11"
@ -3631,6 +3870,12 @@ dependencies = [
"syn 2.0.99", "syn 2.0.99",
] ]
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]] [[package]]
name = "target-lexicon" name = "target-lexicon"
version = "0.12.16" version = "0.12.16"
@ -3827,6 +4072,28 @@ dependencies = [
"urlpattern", "urlpattern",
] ]
[[package]]
name = "tauri-plugin-log"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2341d5b9bc5318c8e34f35a569140c78337241aa9c14091550b424c49f0314e0"
dependencies = [
"android_logger",
"byte-unit",
"fern",
"log",
"objc2 0.6.0",
"objc2-foundation 0.3.0",
"serde",
"serde_json",
"serde_repr",
"swift-rs",
"tauri",
"tauri-plugin",
"thiserror 2.0.12",
"time",
]
[[package]] [[package]]
name = "tauri-plugin-os" name = "tauri-plugin-os"
version = "2.2.0" version = "2.2.0"
@ -4061,7 +4328,9 @@ checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8"
dependencies = [ dependencies = [
"deranged", "deranged",
"itoa 1.0.15", "itoa 1.0.15",
"libc",
"num-conv", "num-conv",
"num_threads",
"powerfmt", "powerfmt",
"serde", "serde",
"time-core", "time-core",
@ -4408,6 +4677,12 @@ version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
[[package]]
name = "utf8-width"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
[[package]] [[package]]
name = "utf8_iter" name = "utf8_iter"
version = "1.0.4" version = "1.0.4"
@ -4424,6 +4699,12 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "value-bag"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2"
[[package]] [[package]]
name = "version-compare" name = "version-compare"
version = "0.2.0" version = "0.2.0"
@ -5197,6 +5478,15 @@ dependencies = [
"x11-dl", "x11-dl",
] ]
[[package]]
name = "wyz"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
dependencies = [
"tap",
]
[[package]] [[package]]
name = "x11" name = "x11"
version = "2.21.0" version = "2.21.0"

View File

@ -16,6 +16,8 @@ serde = { version = "1", features = ["derive"] }
serde_json = "1" serde_json = "1"
anyhow = "1" anyhow = "1"
lazy_static = "1" lazy_static = "1"
log = "0.4"
chrono = "0.4"
tokio = { version = "1", features = ["rt-multi-thread", "net", "macros", "io-util", "time", "sync"] } tokio = { version = "1", features = ["rt-multi-thread", "net", "macros", "io-util", "time", "sync"] }
tauri-plugin-store = "2" tauri-plugin-store = "2"
tauri-plugin-process = "2" tauri-plugin-process = "2"
@ -23,3 +25,4 @@ tauri-plugin-shell = "2"
tauri-plugin-http = "2" tauri-plugin-http = "2"
tauri-plugin-clipboard-manager = "2" tauri-plugin-clipboard-manager = "2"
tauri-plugin-os = "2" tauri-plugin-os = "2"
tauri-plugin-log = "2"

View File

@ -49,6 +49,7 @@
"clipboard-manager:default", "clipboard-manager:default",
"clipboard-manager:allow-read-text", "clipboard-manager:allow-read-text",
"clipboard-manager:allow-write-text", "clipboard-manager:allow-write-text",
"os:default" "os:default",
"log:default"
] ]
} }

View File

@ -24,7 +24,15 @@ impl Device {
.args(&["-s", id, "push", src, des]) .args(&["-s", id, "push", src, des])
.output() .output()
.with_context(|| format!("Failed to execute 'adb push {} {}'", src, des))?; .with_context(|| format!("Failed to execute 'adb push {} {}'", src, des))?;
Ok(String::from_utf8(res.stdout).unwrap())
let output = [
String::from_utf8(res.stdout)?,
String::from_utf8(res.stderr)?,
]
.join("\n")
.trim()
.to_string();
Ok(output)
} }
/// execute "adb reverse" to reverse the device port to local port /// execute "adb reverse" to reverse the device port to local port

View File

@ -54,7 +54,7 @@ impl ScrcpyClient {
"/data/local/tmp/scrcpy-server.jar", "/data/local/tmp/scrcpy-server.jar",
)?; )?;
println!("{}\nSuccessfully push server files", info); log::info!("Successfully push server files: {}", info);
Ok(()) Ok(())
} }
@ -65,7 +65,7 @@ impl ScrcpyClient {
&format!("tcp:{}", port), &format!("tcp:{}", port),
&format!("localabstract:scrcpy_{}", scid), &format!("localabstract:scrcpy_{}", scid),
)?; )?;
println!("Successfully forward port"); log::info!("Successfully forward port");
Ok(()) Ok(())
} }
@ -76,7 +76,7 @@ impl ScrcpyClient {
&format!("localabstract:scrcpy_{}", scid), &format!("localabstract:scrcpy_{}", scid),
&format!("tcp:{}", port), &format!("tcp:{}", port),
)?; )?;
println!("Successfully reverse port"); log::info!("Successfully reverse port");
Ok(()) Ok(())
} }
@ -97,7 +97,7 @@ impl ScrcpyClient {
], ],
)?; )?;
println!("Starting scrcpy server..."); log::info!("Starting scrcpy server...");
let out = child.stdout.take().unwrap(); let out = child.stdout.take().unwrap();
let mut out = std::io::BufReader::new(out); let mut out = std::io::BufReader::new(out);
let mut s = String::new(); let mut s = String::new();
@ -107,13 +107,13 @@ impl ScrcpyClient {
if let core::result::Result::Ok(Some(_)) = child.try_wait() { if let core::result::Result::Ok(Some(_)) = child.try_wait() {
break; break;
} }
print!("{}", s); log::info!("{}", s.trim());
// clear string to store new line only // clear string to store new line only
s.clear(); s.clear();
} }
*share::CLIENT_INFO.lock().unwrap() = None; *share::CLIENT_INFO.lock().unwrap() = None;
println!("Scrcpy server closed"); log::info!("Scrcpy server closed");
Ok(()) Ok(())
} }
} }

View File

@ -84,12 +84,12 @@ pub fn start_scrcpy_server(
let share_app = app.clone(); let share_app = app.clone();
let (device_reply_sender, mut device_reply_receiver) = let (device_reply_sender, mut device_reply_receiver) =
tokio::sync::mpsc::channel::<String>(16); tokio::sync::mpsc::channel::<String>(16);
println!("device reply channel created"); log::info!("Device reply channel created");
tokio::spawn(async move { tokio::spawn(async move {
while let Some(reply) = device_reply_receiver.recv().await { while let Some(reply) = device_reply_receiver.recv().await {
share_app.emit("device-reply", reply).unwrap(); share_app.emit("device-reply", reply).unwrap();
} }
println!("device reply channel closed"); log::info!("Device reply channel closed");
}); });
// create channel to transmit front msg to TcpStream handler // create channel to transmit front msg to TcpStream handler
@ -97,10 +97,10 @@ pub fn start_scrcpy_server(
let share_app = app.clone(); let share_app = app.clone();
let listen_handler = share_app.listen("front-command", move |event| { let listen_handler = share_app.listen("front-command", move |event| {
let sender = front_msg_sender.clone(); let sender = front_msg_sender.clone();
// println!("收到front-command: {}", event.payload()); // log::debug!("Received front-command: {}", event.payload());
tokio::spawn(async move { tokio::spawn(async move {
if let Err(_) = sender.send(event.payload().into()).await { if let Err(_) = sender.send(event.payload().into()).await {
println!("front-command forwarding failure, please restart the program !"); log::error!("Forwarding front command failed, please restart the program!");
}; };
}); });
}); });

View File

@ -3,10 +3,24 @@
use scrcpy_mask::{command, resource::ResHelper}; use scrcpy_mask::{command, resource::ResHelper};
use tauri::Manager; use tauri::Manager;
use tauri_plugin_log::{Target, TargetKind};
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
tauri::Builder::default() tauri::Builder::default()
.plugin(
tauri_plugin_log::Builder::new()
.clear_targets()
.targets([
Target::new(TargetKind::Webview)
.filter(|metadata| metadata.target().starts_with("scrcpy_mask")),
Target::new(TargetKind::LogDir {
file_name: Some(chrono::Local::now().format("%Y-%m-%d_%H-%M-%S").to_string()),
})
.filter(|metadata| metadata.target().starts_with("scrcpy_mask")),
])
.build(),
)
.plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_os::init())
.plugin(tauri_plugin_clipboard_manager::init()) .plugin(tauri_plugin_clipboard_manager::init())
.plugin(tauri_plugin_http::init()) .plugin(tauri_plugin_http::init())

View File

@ -28,7 +28,7 @@ pub async fn connect_socket(
.await .await
.context("Socket connect failed")?; .context("Socket connect failed")?;
println!("connect to scrcpy-server:{:?}", client.local_addr()); log::info!("Connected to scrcpy server: {}", client.local_addr().unwrap());
let (read_half, write_half) = client.into_split(); let (read_half, write_half) = client.into_split();
@ -44,7 +44,7 @@ pub async fn connect_socket(
anyhow::Ok(()) anyhow::Ok(())
} }
// 从客户端读取 // read from scrcpy server
async fn read_socket( async fn read_socket(
mut reader: OwnedReadHalf, mut reader: OwnedReadHalf,
device_reply_sender: tokio::sync::mpsc::Sender<String>, device_reply_sender: tokio::sync::mpsc::Sender<String>,
@ -52,7 +52,7 @@ async fn read_socket(
// read dummy byte // read dummy byte
let mut buf: [u8; 1] = [0; 1]; let mut buf: [u8; 1] = [0; 1];
if let Err(_e) = reader.read_exact(&mut buf).await { if let Err(_e) = reader.read_exact(&mut buf).await {
eprintln!("failed to read dummy byte"); log::error!("Failed to read dummy byte");
return; return;
} }
@ -60,11 +60,11 @@ async fn read_socket(
let mut buf: [u8; 64] = [0; 64]; let mut buf: [u8; 64] = [0; 64];
match reader.read(&mut buf).await { match reader.read(&mut buf).await {
Err(_e) => { Err(_e) => {
eprintln!("failed to read metadata"); log::error!("Failed to read metadata");
return; return;
} }
Ok(0) => { Ok(0) => {
eprintln!("failed to read metadata"); log::error!("Failed to read metadata");
return; return;
} }
Ok(n) => { Ok(n) => {
@ -93,11 +93,11 @@ async fn read_socket(
loop { loop {
match reader.read_u8().await { match reader.read_u8().await {
Err(e) => { Err(e) => {
eprintln!( log::error!(
"Failed to read from scrcpy server, maybe it was closed. Error:{}", "Failed to read from scrcpy server, maybe it was closed: {}",
e e
); );
println!("Drop TcpStream reader"); log::info!("Drop TcpStream reader");
drop(reader); drop(reader);
return; return;
} }
@ -105,14 +105,14 @@ async fn read_socket(
let message_type = match DeviceMsgType::from_u8(message_type) { let message_type = match DeviceMsgType::from_u8(message_type) {
Some(t) => t, Some(t) => t,
None => { None => {
println!("Ignore unkonw message type: {}", message_type); log::warn!("Ignore unkonw message type: {}", message_type);
continue; continue;
} }
}; };
if let Err(e) = if let Err(e) =
handle_device_message(message_type, &mut reader, &device_reply_sender).await handle_device_message(message_type, &mut reader, &device_reply_sender).await
{ {
eprintln!("Failed to handle device message: {}", e); log::warn!("Failed to handle device message: {}", e);
} }
} }
} }
@ -125,7 +125,7 @@ async fn handle_device_message(
device_reply_sender: &tokio::sync::mpsc::Sender<String>, device_reply_sender: &tokio::sync::mpsc::Sender<String>,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
match message_type { match message_type {
// 设备剪切板变动 // Clipboard changed
DeviceMsgType::DeviceMsgTypeClipboard => { DeviceMsgType::DeviceMsgTypeClipboard => {
let text_length = reader.read_u32().await?; let text_length = reader.read_u32().await?;
let mut buf: Vec<u8> = vec![0; text_length as usize]; let mut buf: Vec<u8> = vec![0; text_length as usize];
@ -138,7 +138,7 @@ async fn handle_device_message(
.to_string(); .to_string();
device_reply_sender.send(msg).await?; device_reply_sender.send(msg).await?;
} }
// 设备剪切板设置成功的回复 // Clipboard set ACK
DeviceMsgType::DeviceMsgTypeAckClipboard => { DeviceMsgType::DeviceMsgTypeAckClipboard => {
let sequence = reader.read_u64().await?; let sequence = reader.read_u64().await?;
let msg = json!({ let msg = json!({
@ -148,14 +148,14 @@ async fn handle_device_message(
.to_string(); .to_string();
device_reply_sender.send(msg).await?; device_reply_sender.send(msg).await?;
} }
// 虚拟设备输出,仅读取但不做进一步处理 // Virtual device output(read only but not further processing)
DeviceMsgType::DeviceMsgTypeUhidOutput => { DeviceMsgType::DeviceMsgTypeUhidOutput => {
let _id = reader.read_u16().await?; let _id = reader.read_u16().await?;
let size = reader.read_u16().await?; let size = reader.read_u16().await?;
let mut buf: Vec<u8> = vec![0; size as usize]; let mut buf: Vec<u8> = vec![0; size as usize];
reader.read_exact(&mut buf).await?; reader.read_exact(&mut buf).await?;
} }
// 设备旋转 // Device rotation
DeviceMsgType::DeviceMsgTypeRotation => { DeviceMsgType::DeviceMsgTypeRotation => {
let rotation = reader.read_u16().await?; let rotation = reader.read_u16().await?;
let width = reader.read_i32().await?; let width = reader.read_i32().await?;
@ -179,7 +179,7 @@ async fn handle_device_message(
anyhow::Ok(()) anyhow::Ok(())
} }
// 接收前端发送的消息,执行相关操作 // Receive messages sent by the front-end and perform related operations
async fn recv_front_msg( async fn recv_front_msg(
mut write_half: OwnedWriteHalf, mut write_half: OwnedWriteHalf,
mut front_msg_receiver: tokio::sync::mpsc::Receiver<String>, mut front_msg_receiver: tokio::sync::mpsc::Receiver<String>,
@ -189,12 +189,12 @@ async fn recv_front_msg(
while let Some(msg) = front_msg_receiver.recv().await { while let Some(msg) = front_msg_receiver.recv().await {
match serde_json::from_str::<serde_json::Value>(&msg) { match serde_json::from_str::<serde_json::Value>(&msg) {
Err(_e) => { Err(_e) => {
println!("无法解析的Json数据: {}", msg); log::warn!("Failed to parse front msg as json: {}", msg);
} }
Ok(payload) => { Ok(payload) => {
if let Some(front_msg_type) = payload["msgType"].as_i64() { if let Some(front_msg_type) = payload["msgType"].as_i64() {
// 发送原始控制信息
if front_msg_type >= 0 && front_msg_type <= 14 { if front_msg_type >= 0 && front_msg_type <= 14 {
// Processing Control commands
let ctrl_msg_type = ControlMsgType::from_i64(front_msg_type).unwrap(); let ctrl_msg_type = ControlMsgType::from_i64(front_msg_type).unwrap();
control_msg::send_ctrl_msg( control_msg::send_ctrl_msg(
ctrl_msg_type, ctrl_msg_type,
@ -204,15 +204,15 @@ async fn recv_front_msg(
.await; .await;
continue; continue;
} else { } else {
// 处理Scrcpy Mask命令 // Processing Scrcpy Mask commands
if let Some(cmd_type) = ScrcpyMaskCmdType::from_i64(front_msg_type) { if let Some(cmd_type) = ScrcpyMaskCmdType::from_i64(front_msg_type) {
if let ScrcpyMaskCmdType::Shutdown = cmd_type { if let ScrcpyMaskCmdType::Shutdown = cmd_type {
*share::CLIENT_INFO.lock().unwrap() = None; *share::CLIENT_INFO.lock().unwrap() = None;
drop(write_half); drop(write_half);
println!("Drop TcpStream writer"); log::info!("Drop TcpStream writer");
app.unlisten(listen_handler); app.unlisten(listen_handler);
println!("front msg channel closed"); log::info!("Front msg channel closed");
return; return;
} }
@ -225,14 +225,13 @@ async fn recv_front_msg(
} }
} }
} else { } else {
eprintln!("fc-command invalid!"); log::warn!("Invalid font command!: {:?}", payload);
eprintln!("{:?}", payload);
} }
} }
}; };
} }
println!("font msg channel closed"); log::info!("Font msg channel closed");
} }
#[derive(Debug)] #[derive(Debug)]

View File

@ -52,6 +52,7 @@ import ButtonWithTip from "./common/ButtonWithTip.vue";
import { NonReactiveStore } from "../store/noneReactiveStore"; import { NonReactiveStore } from "../store/noneReactiveStore";
import { useRoute } from "vue-router"; import { useRoute } from "vue-router";
import { useHorRotation } from "../tools/hooks"; import { useHorRotation } from "../tools/hooks";
import { error, warn } from "@tauri-apps/plugin-log";
const { t } = useI18n(); const { t } = useI18n();
const dialog = useDialog(); const dialog = useDialog();
@ -124,11 +125,12 @@ onMounted(async () => {
} }
break; break;
default: default:
console.warn("Unknown reply", payload); warn("Unknown device reply: " + event.payload);
break; break;
} }
} catch (e) { } catch (e) {
console.error(e); error(("Failed to handle device reply: " + event.payload) as string);
console.error(event.payload, e);
} }
}); });
}); });
@ -367,6 +369,7 @@ async function refreshDevices() {
devices.value = await adbDevices(); devices.value = await adbDevices();
} catch (e) { } catch (e) {
message.error(t("pages.Device.adbDeviceError")); message.error(t("pages.Device.adbDeviceError"));
error("Failed to get devices, " + e);
console.error(e); console.error(e);
} }
store.hideLoading(); store.hideLoading();
@ -382,6 +385,7 @@ async function restartAdb() {
await adbRestartServer(); await adbRestartServer();
} catch (e) { } catch (e) {
message.error(t("pages.Device.adbRestartError")); message.error(t("pages.Device.adbRestartError"));
error("Failed to restart adb server, " + e);
console.error(e); console.error(e);
} }
store.hideLoading(); store.hideLoading();
@ -399,6 +403,7 @@ async function connectDevice() {
await refreshDevices(); await refreshDevices();
} catch (e) { } catch (e) {
message.error("t('pages.Device.adbConnectError')"); message.error("t('pages.Device.adbConnectError')");
error("Failed to connect device wirelessly, " + e);
console.error(e); console.error(e);
} }
} }

View File

@ -22,6 +22,7 @@ import {
import { useKeyboardStore } from "../../store/keyboard"; import { useKeyboardStore } from "../../store/keyboard";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { configKeyCommon } from "./config"; import { configKeyCommon } from "./config";
import { error } from "@tauri-apps/plugin-log";
const props = defineProps<{ const props = defineProps<{
index: number; index: number;
@ -148,8 +149,9 @@ function saveMacro() {
keyboardStore.edited = true; keyboardStore.edited = true;
message.success(t("pages.KeyBoard.KeyCommon.macroParseSuccess")); message.success(t("pages.KeyBoard.KeyCommon.macroParseSuccess"));
} catch (e) { } catch (e) {
console.error(e);
message.error(t("pages.KeyBoard.KeyCommon.macroParseFailed")); message.error(t("pages.KeyBoard.KeyCommon.macroParseFailed"));
error("Failed to save macro, " + e);
console.error(e);
} }
} }

View File

@ -21,6 +21,7 @@ import { useI18n } from "vue-i18n";
import { writeText } from "@tauri-apps/plugin-clipboard-manager"; import { writeText } from "@tauri-apps/plugin-clipboard-manager";
import { LocalStore } from "../../store/localStore"; import { LocalStore } from "../../store/localStore";
import { NonReactiveStore } from "../../store/noneReactiveStore"; import { NonReactiveStore } from "../../store/noneReactiveStore";
import { error } from "@tauri-apps/plugin-log";
const { t } = useI18n(); const { t } = useI18n();
const store = useGlobalStore(); const store = useGlobalStore();
@ -150,8 +151,9 @@ function importKeyMappingConfig() {
try { try {
keyMappingConfig = JSON.parse(importModalInputValue.value); keyMappingConfig = JSON.parse(importModalInputValue.value);
} catch (e) { } catch (e) {
console.error(e);
message.error(t("pages.KeyBoard.KeySetting.importFailed")); message.error(t("pages.KeyBoard.KeySetting.importFailed"));
error("Failed to import key mapping config, " + e);
console.error(e);
return; return;
} }
store.keyMappingConfigList.push(keyMappingConfig); store.keyMappingConfigList.push(keyMappingConfig);
@ -172,8 +174,9 @@ async function importDefaultKeyMappingConfig() {
count++; count++;
} }
} catch (e) { } catch (e) {
console.error(e);
message.error(t("pages.KeyBoard.KeySetting.importDefaultFailed")); message.error(t("pages.KeyBoard.KeySetting.importDefaultFailed"));
error("Failed to import default key mapping config, " + e);
console.error(e);
return; return;
} }
@ -266,8 +269,9 @@ function exportKeyMappingConfig() {
message.success(t("pages.KeyBoard.KeySetting.exportSuccess")); message.success(t("pages.KeyBoard.KeySetting.exportSuccess"));
}) })
.catch((e) => { .catch((e) => {
console.error(e);
message.error(t("pages.KeyBoard.KeySetting.exportFailed")); message.error(t("pages.KeyBoard.KeySetting.exportFailed"));
error("Failed to export key mapping config, " + e);
console.error(e);
}); });
} }

View File

@ -77,6 +77,14 @@ function delLocalStore(key?: string) {
<template> <template>
<div> <div>
<NH4 prefix="bar">{{ $t("pages.Setting.Data.logs") }}</NH4>
<NButton
text
@click="open(LocalStore.logDir)"
style="margin-bottom: 32px"
>{{ LocalStore.logDir }}</NButton
>
<NFlex justify="space-between"> <NFlex justify="space-between">
<NH4 prefix="bar">{{ $t("pages.Setting.Data.localStore") }}</NH4> <NH4 prefix="bar">{{ $t("pages.Setting.Data.localStore") }}</NH4>
<NFlex> <NFlex>
@ -110,27 +118,27 @@ function delLocalStore(key?: string) {
</div> </div>
</NListItem> </NListItem>
</NList> </NList>
<NModal v-model:show="showDataModal">
<NCard
style="width: 50%; height: 80%"
:title="localStoreEntries[curDataIndex][0]"
>
<NFlex vertical style="height: 100%">
<NInput
type="textarea"
style="flex-grow: 1"
:value="dataModalInputVal"
round
readonly
/>
<NButton
type="success"
round
@click="delLocalStore(localStoreEntries[curDataIndex][0])"
>{{ $t("pages.Setting.Data.delCurData") }}</NButton
>
</NFlex>
</NCard>
</NModal>
</div> </div>
<NModal v-model:show="showDataModal">
<NCard
style="width: 50%; height: 80%"
:title="localStoreEntries[curDataIndex][0]"
>
<NFlex vertical style="height: 100%">
<NInput
type="textarea"
style="flex-grow: 1"
:value="dataModalInputVal"
round
readonly
/>
<NButton
type="success"
round
@click="delLocalStore(localStoreEntries[curDataIndex][0])"
>{{ $t("pages.Setting.Data.delCurData") }}</NButton
>
</NFlex>
</NCard>
</NModal>
</template> </template>

View File

@ -136,7 +136,8 @@
"localStore": "Local data", "localStore": "Local data",
"delCurData": "Delete current data", "delCurData": "Delete current data",
"btnRefresh": "Refresh", "btnRefresh": "Refresh",
"btnDelAll": "Clear local data" "btnDelAll": "Clear local data",
"logs": "Log dir"
}, },
"About": { "About": {
"introduction": "A Scrcpy client in Rust & Tarui aimed at providing mouse and key mapping to control Android device.", "introduction": "A Scrcpy client in Rust & Tarui aimed at providing mouse and key mapping to control Android device.",

View File

@ -136,7 +136,8 @@
"localStore": "本地数据", "localStore": "本地数据",
"delCurData": "删除当前数据", "delCurData": "删除当前数据",
"btnDelAll": "清空本地数据", "btnDelAll": "清空本地数据",
"btnRefresh": "刷新" "btnRefresh": "刷新",
"logs": "日志目录"
}, },
"About": { "About": {
"about": "关于", "about": "关于",

View File

@ -4,6 +4,9 @@ import "./css/global.scss";
import App from "./App.vue"; import App from "./App.vue";
import router from "./router"; import router from "./router";
import i18n from "./i18n"; import i18n from "./i18n";
import { attachConsole } from "@tauri-apps/plugin-log";
attachConsole()
const pinia = createPinia(); const pinia = createPinia();

View File

@ -12,16 +12,18 @@ import {
LogicalSize, LogicalSize,
primaryMonitor, primaryMonitor,
} from "@tauri-apps/api/window"; } from "@tauri-apps/api/window";
import { appDataDir, join } from "@tauri-apps/api/path"; import { appDataDir, appLogDir, join } from "@tauri-apps/api/path";
export class LocalStore { export class LocalStore {
public static store: Store; public static store: Store;
public static vueStore: ReturnType<typeof useGlobalStore>; public static vueStore: ReturnType<typeof useGlobalStore>;
public static path: string; public static path: string;
public static dir: string; public static dir: string;
public static logDir: string;
static async init() { static async init() {
this.dir = await appDataDir(); this.dir = await appDataDir();
this.logDir = await appLogDir();
this.path = await join(this.dir, "store.bin"); this.path = await join(this.dir, "store.bin");
this.store = await load("store.bin", { autoSave: true }); this.store = await load("store.bin", { autoSave: true });
this.vueStore = useGlobalStore(); this.vueStore = useGlobalStore();

View File

@ -10,6 +10,7 @@ import { useGlobalStore } from "../store/global";
import { h } from "vue"; import { h } from "vue";
import { marked } from "marked"; import { marked } from "marked";
import { open } from "@tauri-apps/plugin-shell"; import { open } from "@tauri-apps/plugin-shell";
import { error } from "@tauri-apps/plugin-log";
const render = new marked.Renderer(); const render = new marked.Renderer();
marked.setOptions({ marked.setOptions({
@ -59,8 +60,9 @@ export function useCheckUpdate() {
}); });
} }
} catch (e) { } catch (e) {
console.error(e);
message.error(t("pages.Mask.checkUpdate.failed")); message.error(t("pages.Mask.checkUpdate.failed"));
error("Failed to check for update, " + e);
console.error(e);
} }
}; };
} }

View File

@ -38,6 +38,7 @@ import {
} from "../frontcommand/controlMsg"; } from "../frontcommand/controlMsg";
import { NonReactiveStore } from "../store/noneReactiveStore"; import { NonReactiveStore } from "../store/noneReactiveStore";
import { asType } from "./tools"; import { asType } from "./tools";
import { error } from "@tauri-apps/plugin-log";
function clientxToPosx(clientx: number) { function clientxToPosx(clientx: number) {
return clientx < 70 return clientx < 70
@ -1289,7 +1290,7 @@ async function execMacro(
if (macro === null) return; if (macro === null) return;
for (const cmd of macro) { for (const cmd of macro) {
if (!cmd.hasOwnProperty("type") || !cmd.hasOwnProperty("args")) { if (!cmd.hasOwnProperty("type") || !cmd.hasOwnProperty("args")) {
console.error("Invalid command: ", cmd); error("Invalid command: " + cmd);
return; return;
} }
try { try {
@ -1313,7 +1314,7 @@ async function execMacro(
touchAction = TouchAction.Move; touchAction = TouchAction.Move;
break; break;
default: default:
console.error("Invalid touch action: ", cmd.args[0]); error("Invalid touch action: " + cmd.args[0]);
return; return;
} }
await touchX( await touchX(
@ -1337,7 +1338,7 @@ async function execMacro(
swipeAction = SwipeAction.NoDown; swipeAction = SwipeAction.NoDown;
break; break;
default: default:
console.error("Invalid swipe action: ", cmd.args[0]); error("Invalid swipe action: " + cmd.args[0]);
return; return;
} }
await swipe({ await swipe({
@ -1365,11 +1366,12 @@ async function execMacro(
} }
break; break;
default: default:
console.error("Invalid command: ", cmd); error("Invalid command: " + cmd);
return; return;
} }
} catch (e) { } catch (e) {
console.error("Invalid command: ", cmd, e); error(`Invalid command: ${cmd}, ${e}`);
console.error(e);
return; return;
} }
} }
@ -1528,13 +1530,14 @@ function applyKeyMappingConfigShortcuts(
case "Fire": case "Fire":
break; break;
default: default:
console.error("Invalid item type: ", item); error("Invalid item type: " + item);
break; break;
} }
} }
return true; return true;
} catch (e) { } catch (e) {
console.error("Invalid keyMappingConfig: ", keyMappingConfig, e); error("Invalid keyMappingConfig, " + e);
console.error(keyMappingConfig, e);
clearShortcuts(); clearShortcuts();
return false; return false;
} }

View File

@ -2,6 +2,7 @@ import { useMessage } from "naive-ui";
import { useGlobalStore } from "../store/global"; import { useGlobalStore } from "../store/global";
import { sendKey, shutdown, swipe, touch } from "../frontcommand/scrcpyMaskCmd"; import { sendKey, shutdown, swipe, touch } from "../frontcommand/scrcpyMaskCmd";
import { useI18n } from "vue-i18n"; import { useI18n } from "vue-i18n";
import { error } from "@tauri-apps/plugin-log";
let ws: WebSocket; let ws: WebSocket;
let sharedMessage: ReturnType<typeof useMessage>; let sharedMessage: ReturnType<typeof useMessage>;
@ -58,10 +59,11 @@ async function handleMessage(event: MessageEvent) {
await shutdown(); await shutdown();
sharedStore.controledDevice = null; sharedStore.controledDevice = null;
} else { } else {
console.error("Invalid message received", msg); error("Invalid message received: " + msg);
} }
} catch (error) { } catch (e) {
console.error("Message received failed", error); error("Message received failed, " + e);
console.error(e);
} }
} }