Compare commits
No commits in common. "a94a9b4ec47e52f64d6bff16b8f51642b0ed93be" and "638440feff3fd548a1605011e547793ada54b86a" have entirely different histories.
a94a9b4ec4
...
638440feff
@ -4,7 +4,9 @@ version = "0.1.0"
|
|||||||
description = "Use Wi-Fi Channel State Information to locate human presence"
|
description = "Use Wi-Fi Channel State Information to locate human presence"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"flask",
|
||||||
"numpy>=2.0.0",
|
"numpy>=2.0.0",
|
||||||
|
"flask-sock",
|
||||||
"pytest",
|
"pytest",
|
||||||
"matplotlib",
|
"matplotlib",
|
||||||
"scipy",
|
"scipy",
|
||||||
@ -13,15 +15,9 @@ dependencies = [
|
|||||||
"h5py>=3.12.1",
|
"h5py>=3.12.1",
|
||||||
"pyyaml>=6.0.2",
|
"pyyaml>=6.0.2",
|
||||||
"pydantic>=2.10.6",
|
"pydantic>=2.10.6",
|
||||||
"torch",
|
"torch"
|
||||||
"grpcio>=1.70.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[build-system]
|
|
||||||
requires = ["setuptools", "wheel", "grpcio-tools"]
|
|
||||||
build-backend = "setuptools.build_meta"
|
|
||||||
|
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
where-fi = "where_fi.cli:app"
|
where-fi = "where_fi.cli:app"
|
||||||
|
|
||||||
@ -47,9 +43,3 @@ package = true
|
|||||||
|
|
||||||
[tool.setuptools]
|
[tool.setuptools]
|
||||||
packages = ["where_fi"]
|
packages = ["where_fi"]
|
||||||
|
|
||||||
[dependency-groups]
|
|
||||||
dev = [
|
|
||||||
"grpcio-tools>=1.70.0",
|
|
||||||
"protoletariat>=3.3.9",
|
|
||||||
]
|
|
||||||
|
|||||||
199
uv.lock
199
uv.lock
@ -1,5 +1,4 @@
|
|||||||
version = 1
|
version = 1
|
||||||
revision = 1
|
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
resolution-markers = [
|
resolution-markers = [
|
||||||
"python_full_version >= '3.12'",
|
"python_full_version >= '3.12'",
|
||||||
@ -15,6 +14,15 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 },
|
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blinker"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "click"
|
name = "click"
|
||||||
version = "8.1.8"
|
version = "8.1.8"
|
||||||
@ -105,6 +113,35 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/89/ec/00d68c4ddfedfe64159999e5f8a98fb8442729a63e2077eb9dcd89623d27/filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338", size = 16164 },
|
{ url = "https://files.pythonhosted.org/packages/89/ec/00d68c4ddfedfe64159999e5f8a98fb8442729a63e2077eb9dcd89623d27/filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338", size = 16164 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flask"
|
||||||
|
version = "3.1.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "blinker" },
|
||||||
|
{ name = "click" },
|
||||||
|
{ name = "itsdangerous" },
|
||||||
|
{ name = "jinja2" },
|
||||||
|
{ name = "werkzeug" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/89/50/dff6380f1c7f84135484e176e0cac8690af72fa90e932ad2a0a60e28c69b/flask-3.1.0.tar.gz", hash = "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac", size = 680824 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/af/47/93213ee66ef8fae3b93b3e29206f6b251e65c97bd91d8e1c5596ef15af0a/flask-3.1.0-py3-none-any.whl", hash = "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136", size = 102979 },
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flask-sock"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "flask" },
|
||||||
|
{ name = "simple-websocket" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/8d/8f/c6ab717dc90f4e46d1430335cd4ab13e3629410bb760c0ead6de476760fb/flask-sock-0.7.0.tar.gz", hash = "sha256:e023b578284195a443b8d8bdb4469e6a6acf694b89aeb51315b1a34fcf427b7d", size = 4334 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/d8/98/107728ce3f430b5481eb426ccc5e1f7c8ab0bd01eaf231c62a8d528ff721/flask_sock-0.7.0-py3-none-any.whl", hash = "sha256:caac4d679392aaf010d02fabcf73d52019f5bdaf1c9c131ec5a428cb3491204a", size = 3982 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fonttools"
|
name = "fonttools"
|
||||||
version = "4.55.6"
|
version = "4.55.6"
|
||||||
@ -148,78 +185,12 @@ wheels = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "grpcio"
|
name = "h11"
|
||||||
version = "1.70.0"
|
version = "0.14.0"
|
||||||
source = { registry = "https://pypi.org/simple" }
|
source = { registry = "https://pypi.org/simple" }
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/69/e1/4b21b5017c33f3600dcc32b802bb48fe44a4d36d6c066f52650c7c2690fa/grpcio-1.70.0.tar.gz", hash = "sha256:8d1584a68d5922330025881e63a6c1b54cc8117291d382e4fa69339b6d914c56", size = 12788932 }
|
sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 }
|
||||||
wheels = [
|
wheels = [
|
||||||
{ url = "https://files.pythonhosted.org/packages/65/c4/1f67d23d6bcadd2fd61fb460e5969c52b3390b4a4e254b5e04a6d1009e5e/grpcio-1.70.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:17325b0be0c068f35770f944124e8839ea3185d6d54862800fc28cc2ffad205a", size = 5229017 },
|
{ url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 },
|
||||||
{ url = "https://files.pythonhosted.org/packages/e4/bd/cc36811c582d663a740fb45edf9f99ddbd99a10b6ba38267dc925e1e193a/grpcio-1.70.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:dbe41ad140df911e796d4463168e33ef80a24f5d21ef4d1e310553fcd2c4a386", size = 11472027 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/7e/32/8538bb2ace5cd72da7126d1c9804bf80b4fe3be70e53e2d55675c24961a8/grpcio-1.70.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:5ea67c72101d687d44d9c56068328da39c9ccba634cabb336075fae2eab0d04b", size = 5707785 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ce/5c/a45f85f2a0dfe4a6429dee98717e0e8bd7bd3f604315493c39d9679ca065/grpcio-1.70.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb5277db254ab7586769e490b7b22f4ddab3876c490da0a1a9d7c695ccf0bf77", size = 6331599 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9f/e5/5316b239380b8b2ad30373eb5bb25d9fd36c0375e94a98a0a60ea357d254/grpcio-1.70.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7831a0fc1beeeb7759f737f5acd9fdcda520e955049512d68fda03d91186eea", size = 5940834 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/05/33/dbf035bc6d167068b4a9f2929dfe0b03fb763f0f861ecb3bb1709a14cb65/grpcio-1.70.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:27cc75e22c5dba1fbaf5a66c778e36ca9b8ce850bf58a9db887754593080d839", size = 6641191 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/4c/c4/684d877517e5bfd6232d79107e5a1151b835e9f99051faef51fed3359ec4/grpcio-1.70.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d63764963412e22f0491d0d32833d71087288f4e24cbcddbae82476bfa1d81fd", size = 6198744 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e9/43/92fe5eeaf340650a7020cfb037402c7b9209e7a0f3011ea1626402219034/grpcio-1.70.0-cp311-cp311-win32.whl", hash = "sha256:bb491125103c800ec209d84c9b51f1c60ea456038e4734688004f377cfacc113", size = 3617111 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/55/15/b6cf2c9515c028aff9da6984761a3ab484a472b0dc6435fcd07ced42127d/grpcio-1.70.0-cp311-cp311-win_amd64.whl", hash = "sha256:d24035d49e026353eb042bf7b058fb831db3e06d52bee75c5f2f3ab453e71aca", size = 4304604 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/4c/a4/ddbda79dd176211b518f0f3795af78b38727a31ad32bc149d6a7b910a731/grpcio-1.70.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:ef4c14508299b1406c32bdbb9fb7b47612ab979b04cf2b27686ea31882387cff", size = 5198135 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/30/5c/60eb8a063ea4cb8d7670af8fac3f2033230fc4b75f62669d67c66ac4e4b0/grpcio-1.70.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:aa47688a65643afd8b166928a1da6247d3f46a2784d301e48ca1cc394d2ffb40", size = 11447529 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fb/b9/1bf8ab66729f13b44e8f42c9de56417d3ee6ab2929591cfee78dce749b57/grpcio-1.70.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:880bfb43b1bb8905701b926274eafce5c70a105bc6b99e25f62e98ad59cb278e", size = 5664484 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/d1/06/2f377d6906289bee066d96e9bdb91e5e96d605d173df9bb9856095cccb57/grpcio-1.70.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e654c4b17d07eab259d392e12b149c3a134ec52b11ecdc6a515b39aceeec898", size = 6303739 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ae/50/64c94cfc4db8d9ed07da71427a936b5a2bd2b27c66269b42fbda82c7c7a4/grpcio-1.70.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2394e3381071045a706ee2eeb6e08962dd87e8999b90ac15c55f56fa5a8c9597", size = 5910417 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/53/89/8795dfc3db4389c15554eb1765e14cba8b4c88cc80ff828d02f5572965af/grpcio-1.70.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:b3c76701428d2df01964bc6479422f20e62fcbc0a37d82ebd58050b86926ef8c", size = 6626797 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/9c/b2/6a97ac91042a2c59d18244c479ee3894e7fb6f8c3a90619bb5a7757fa30c/grpcio-1.70.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ac073fe1c4cd856ebcf49e9ed6240f4f84d7a4e6ee95baa5d66ea05d3dd0df7f", size = 6190055 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/86/2b/28db55c8c4d156053a8c6f4683e559cd0a6636f55a860f87afba1ac49a51/grpcio-1.70.0-cp312-cp312-win32.whl", hash = "sha256:cd24d2d9d380fbbee7a5ac86afe9787813f285e684b0271599f95a51bce33528", size = 3600214 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/17/c3/a7a225645a965029ed432e5b5e9ed959a574e62100afab553eef58be0e37/grpcio-1.70.0-cp312-cp312-win_amd64.whl", hash = "sha256:0495c86a55a04a874c7627fd33e5beaee771917d92c0e6d9d797628ac40e7655", size = 4292538 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/68/38/66d0f32f88feaf7d83f8559cd87d899c970f91b1b8a8819b58226de0a496/grpcio-1.70.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:aa573896aeb7d7ce10b1fa425ba263e8dddd83d71530d1322fd3a16f31257b4a", size = 5199218 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/c1/96/947df763a0b18efb5cc6c2ae348e56d97ca520dc5300c01617b234410173/grpcio-1.70.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:d405b005018fd516c9ac529f4b4122342f60ec1cee181788249372524e6db429", size = 11445983 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fd/5b/f3d4b063e51b2454bedb828e41f3485800889a3609c49e60f2296cc8b8e5/grpcio-1.70.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:f32090238b720eb585248654db8e3afc87b48d26ac423c8dde8334a232ff53c9", size = 5663954 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/bd/0b/dab54365fcedf63e9f358c1431885478e77d6f190d65668936b12dd38057/grpcio-1.70.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dfa089a734f24ee5f6880c83d043e4f46bf812fcea5181dcb3a572db1e79e01c", size = 6304323 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/76/a8/8f965a7171ddd336ce32946e22954aa1bbc6f23f095e15dadaa70604ba20/grpcio-1.70.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f19375f0300b96c0117aca118d400e76fede6db6e91f3c34b7b035822e06c35f", size = 5910939 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/1b/05/0bbf68be8b17d1ed6f178435a3c0c12e665a1e6054470a64ce3cb7896596/grpcio-1.70.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:7c73c42102e4a5ec76608d9b60227d917cea46dff4d11d372f64cbeb56d259d0", size = 6631405 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/79/6a/5df64b6df405a1ed1482cb6c10044b06ec47fd28e87c2232dbcf435ecb33/grpcio-1.70.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:0a5c78d5198a1f0aa60006cd6eb1c912b4a1520b6a3968e677dbcba215fabb40", size = 6190982 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/42/aa/aeaac87737e6d25d1048c53b8ec408c056d3ed0c922e7c5efad65384250c/grpcio-1.70.0-cp313-cp313-win32.whl", hash = "sha256:fe9dbd916df3b60e865258a8c72ac98f3ac9e2a9542dcb72b7a34d236242a5ce", size = 3598359 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/1f/79/8edd2442d2de1431b4a3de84ef91c37002f12de0f9b577fb07b452989dbc/grpcio-1.70.0-cp313-cp313-win_amd64.whl", hash = "sha256:4119fed8abb7ff6c32e3d2255301e59c316c22d31ab812b3fbcbaf3d0d87cc68", size = 4293938 },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "grpcio-tools"
|
|
||||||
version = "1.70.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "grpcio" },
|
|
||||||
{ name = "protobuf" },
|
|
||||||
{ name = "setuptools" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/c1/fe/3adf1035c1f9e9243516530beae67e197f2acc17562ec75f03a0ba77fc55/grpcio_tools-1.70.0.tar.gz", hash = "sha256:e578fee7c1c213c8e471750d92631d00f178a15479fb2cb3b939a07fc125ccd3", size = 5323149 }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ab/2b/446a63000acab303bbc1b84fa7dbfa4857d96e95ab53e85083ba16c60d4a/grpcio_tools-1.70.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:5f5aba12d98d25c7ab2dd983939e2c21556a7d15f903b286f24d88d2c6e30c0a", size = 2380860 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/0c/d2/48e82de83bf34f9a5207ea808a1c6e074bf657720664eb6c9f0bab38dbf2/grpcio_tools-1.70.0-cp311-cp311-macosx_10_14_universal2.whl", hash = "sha256:d47a6c6cfc526b290b7b53a37dd7e6932983f7a168b56aab760b4b597c47f30f", size = 5957716 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fa/f7/a735faa8fc96778aa54e321ac6820bab03ee4eea305cc1209b095dfdffee/grpcio_tools-1.70.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:b5a9beadd1e24772ffa2c70f07d72f73330d356b78b246e424f4f2ed6c6713f3", size = 2336501 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/47/ed/4bed599c061b65149b32569347a857098819d75c2419c4202f9de1e06250/grpcio_tools-1.70.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bb8135eef160a62505f074bf7a3d62f3b13911c3c14037c5392bf877114213b5", size = 2729638 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/4f/43/d8850889a2041cf94e882712df0e323cd6bbf24f8f4c50e2f0d80c68da7d/grpcio_tools-1.70.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7ac9b3e13ace8467a586c53580ee22f9732c355583f3c344ef8c6c0666219cc", size = 2463251 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a8/2e/2407641c70ca0afe03a04c3c29f0b51e1582759e3d5c995217b4ed0ce2bd/grpcio_tools-1.70.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:63f367363a4a1489a0046b19f9d561216ea0d206c40a6f1bf07a58ccfb7be480", size = 3340968 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/de/bb/591799e6b0445028d74552964e47d7b0b23ff5ce9c377688b318de331f12/grpcio_tools-1.70.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:54ceffef59a059d2c7304554a8bbb20eedb05a3f937159ab1c332c1b28e12c9f", size = 2944466 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/3f/90/b73293fff616574cbdf70437efb3b2ee6af3705c6b2cc19dd02dfb01708f/grpcio_tools-1.70.0-cp311-cp311-win32.whl", hash = "sha256:7a90a66a46821140a2a2b0be787dfabe42e22e9a5ba9cc70726b3e5c71a3b785", size = 947335 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/88/cc/12ad066dc722285ee3f7d398d4272dc43857de6b7e6fa509a385ca4a857f/grpcio_tools-1.70.0-cp311-cp311-win_amd64.whl", hash = "sha256:4ebf09733545a69c166b02caa14c34451e38855544820dab7fdde5c28e2dbffe", size = 1119053 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/58/8d/21f3f0c6e8ddc7ffd82873a6ff767a568a3384043adc034c49fd72020884/grpcio_tools-1.70.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:ec5d6932c3173d7618267b3b3fd77b9243949c5ec04302b7338386d4f8544e0b", size = 2380552 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e1/10/def56ecb8e139a96aae9d408d891f32f24a066c57179ce5f78e7edf70a35/grpcio_tools-1.70.0-cp312-cp312-macosx_10_14_universal2.whl", hash = "sha256:f22852da12f53b02a3bdb29d0c32fcabab9c7c8f901389acffec8461083f110d", size = 5956826 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/63/5e/f10375b90b7dc14d1b5095797d4f79b34e584fbc9bda06e093ad316a96dd/grpcio_tools-1.70.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:7d45067e6efd20881e98a0e1d7edd7f207b1625ad7113321becbfe0a6ebee46c", size = 2335835 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/ec/33/d770fbdf824edfc0f9297be046d4d48fbc81b2dbf802827ade65110f0a47/grpcio_tools-1.70.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3020c97f03b30eee3c26aa2a55fbe003f1729c6f879a378507c2c78524db7c12", size = 2729501 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/e2/fb/8442f386fa71056abe7ebbc153eaac8cbe32875ed659a641ca526ab9f341/grpcio_tools-1.70.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7fd472fce3b33bdf7fbc24d40da7ab10d7a088bcaf59c37433c2c57330fbcb6", size = 2462824 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/46/4e/1703d2586663078613baed553de052e029b3d7fe311e90d3f023c85e612a/grpcio_tools-1.70.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3875543d74ce1a698a11f498f83795216ce929cb29afa5fac15672c7ba1d6dd2", size = 3340759 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/59/d9/f61e427b0e1d7305396dacea65d1e0612eb2bc66b02328ef6bde117624fb/grpcio_tools-1.70.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a130c24d617a3a57369da784080dfa8848444d41b7ae1250abc06e72e706a8d9", size = 2944463 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8d/8f/8f6f511ad90e12d7c2f396ad9efe46019c0a77a5f5f69e46998c834405e4/grpcio_tools-1.70.0-cp312-cp312-win32.whl", hash = "sha256:8eae17c920d14e2e451dbb18f5d8148f884e10228061941b33faa8fceee86e73", size = 946776 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/83/0f/aff5d01ce9ae94ed02b79e033b0c469e560221340c09120270109de4986a/grpcio_tools-1.70.0-cp312-cp312-win_amd64.whl", hash = "sha256:99caa530242a0a832d8b6a6ab94b190c9b449d3e237f953911b4d56207569436", size = 1118594 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/49/2a/bf442acb748b2a53281e5e7cc3fa36c25ae99436cd2f2cfe684096d4c39f/grpcio_tools-1.70.0-cp313-cp313-linux_armv7l.whl", hash = "sha256:f024688d04e7a9429489ed695b85628075c3c6d655198ba3c6ccbd1d8b7c333b", size = 2380142 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/dc/a2/984dabaf1cdc41e267acdd37232026ede28f55bc6f9e932907bcbbb46773/grpcio_tools-1.70.0-cp313-cp313-macosx_10_14_universal2.whl", hash = "sha256:1fa9a81621d7178498dedcf94eb8f276a7594327faf3dd5fd1935ce2819a2bdb", size = 5955907 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/cd/78/ebefc32418be93828b46eca5952ef1cb0400b33883bc20c22b1fc2a51f61/grpcio_tools-1.70.0-cp313-cp313-manylinux_2_17_aarch64.whl", hash = "sha256:c6da2585c0950cdb650df1ff6d85b3fe31e22f8370b9ee11f8fe641d5b4bf096", size = 2335428 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a0/f8/5d4b58dc846bf28b8b9abf07f5d091eb078fc4f01184adb3b374cf5119a4/grpcio_tools-1.70.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70234b592af17050ec30cf35894790cef52aeae87639efe6db854a7fa783cc8c", size = 2728481 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b0/28/46833d415b2c2e3e0f36763c528da48785c94580240684e56410abd08aa0/grpcio_tools-1.70.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9c021b040d0a9f5bb96a725c4d2b95008aad127d6bed124a7bbe854973014f5b", size = 2462401 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fa/8a/c771a09aea58275106e08e7dd37470c6e8555dfcea9a7b44d1c5adc80370/grpcio_tools-1.70.0-cp313-cp313-musllinux_1_1_i686.whl", hash = "sha256:114a42e566e5b16a47e98f7910a6c0074b37e2d1faacaae13222e463d0d0d43c", size = 3340068 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/3a/be/e3dfa73435c633859c4a045c299105e99a6c6a41cda524148bf9c8d4dc99/grpcio_tools-1.70.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:4cae365d7e3ba297256216a9a256458b286f75c64603f017972b3ad1ee374437", size = 2944317 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/b6/bd/e30fb2b0ce2c0c48caf994b1ebedb56fc7103e26062dd31a41ad1e528eb7/grpcio_tools-1.70.0-cp313-cp313-win32.whl", hash = "sha256:ae139a8d3ddd8353f62af3af018e99ebcd2f4a237bd319cb4b6f58dd608aaa54", size = 946136 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/0f/8a/92aba852bbe2ddf3e44c354b4162b3cf350b810523ffb2d0e5937bd3f249/grpcio_tools-1.70.0-cp313-cp313-win_amd64.whl", hash = "sha256:04bf30c0eb2741defe3ab6e0a6102b022d69cfd39d68fab9b954993ceca8d346", size = 1118147 },
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -257,6 +228,15 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 },
|
{ url = "https://files.pythonhosted.org/packages/ef/a6/62565a6e1cf69e10f5727360368e451d4b7f58beeac6173dc9db836a5b46/iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374", size = 5892 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itsdangerous"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jinja2"
|
name = "jinja2"
|
||||||
version = "3.1.5"
|
version = "3.1.5"
|
||||||
@ -702,33 +682,6 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 },
|
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556 },
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "protobuf"
|
|
||||||
version = "5.29.3"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/f7/d1/e0a911544ca9993e0f17ce6d3cc0932752356c1b0a834397f28e63479344/protobuf-5.29.3.tar.gz", hash = "sha256:5da0f41edaf117bde316404bad1a486cb4ededf8e4a54891296f648e8e076620", size = 424945 }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/dc/7a/1e38f3cafa022f477ca0f57a1f49962f21ad25850c3ca0acd3b9d0091518/protobuf-5.29.3-cp310-abi3-win32.whl", hash = "sha256:3ea51771449e1035f26069c4c7fd51fba990d07bc55ba80701c78f886bf9c888", size = 422708 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/61/fa/aae8e10512b83de633f2646506a6d835b151edf4b30d18d73afd01447253/protobuf-5.29.3-cp310-abi3-win_amd64.whl", hash = "sha256:a4fa6f80816a9a0678429e84973f2f98cbc218cca434abe8db2ad0bffc98503a", size = 434508 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/dd/04/3eaedc2ba17a088961d0e3bd396eac764450f431621b58a04ce898acd126/protobuf-5.29.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a8434404bbf139aa9e1300dbf989667a83d42ddda9153d8ab76e0d5dcaca484e", size = 417825 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/4f/06/7c467744d23c3979ce250397e26d8ad8eeb2bea7b18ca12ad58313c1b8d5/protobuf-5.29.3-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:daaf63f70f25e8689c072cfad4334ca0ac1d1e05a92fc15c54eb9cf23c3efd84", size = 319573 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/a8/45/2ebbde52ad2be18d3675b6bee50e68cd73c9e0654de77d595540b5129df8/protobuf-5.29.3-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:c027e08a08be10b67c06bf2370b99c811c466398c357e615ca88c91c07f0910f", size = 319672 },
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fd/b2/ab07b09e0f6d143dfb839693aa05765257bceaa13d03bf1a696b78323e7a/protobuf-5.29.3-py3-none-any.whl", hash = "sha256:0a18ed4a24198528f2333802eb075e59dea9d679ab7a6c5efb017a59004d849f", size = 172550 },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "protoletariat"
|
|
||||||
version = "3.3.9"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "click" },
|
|
||||||
{ name = "protobuf" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/09/cd/f8c0b9d113a1d551b7a014339c4da85c71c2ba9ac889855eb45744d89459/protoletariat-3.3.9.tar.gz", hash = "sha256:db209b7058a0b700c5855b79c4151216205a93298b052c227774cba59f213831", size = 20678 }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/8b/59/bf79f403c358d1dd4a9cfa2bbfea8734bfa1a1181aecf3a8945ab6f6e7fc/protoletariat-3.3.9-py3-none-any.whl", hash = "sha256:a876a600691005c7d229a149f9639c994a087c4a66bc054717f243f0f353ae66", size = 20718 },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pydantic"
|
name = "pydantic"
|
||||||
version = "2.10.6"
|
version = "2.10.6"
|
||||||
@ -961,6 +914,18 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 },
|
{ url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simple-websocket"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "wsproto" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/b0/d4/bfa032f961103eba93de583b161f0e6a5b63cebb8f2c7d0c6e6efe1e3d2e/simple_websocket-1.1.0.tar.gz", hash = "sha256:7939234e7aa067c534abdab3a9ed933ec9ce4691b0713c78acb195560aa52ae4", size = 17300 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/52/59/0782e51887ac6b07ffd1570e0364cf901ebc36345fea669969d2084baebb/simple_websocket-1.1.0-py3-none-any.whl", hash = "sha256:4af6069630a38ed6c561010f0e11a5bc0d4ca569b36306eb257cd9a192497c8c", size = 13842 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "six"
|
name = "six"
|
||||||
version = "1.17.0"
|
version = "1.17.0"
|
||||||
@ -1056,12 +1021,25 @@ wheels = [
|
|||||||
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
|
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "werkzeug"
|
||||||
|
version = "3.1.3"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "markupsafe" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/9f/69/83029f1f6300c5fb2471d621ab06f6ec6b3324685a2ce0f9777fd4a8b71e/werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746", size = 806925 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/52/24/ab44c871b0f07f491e5d2ad12c9bd7358e527510618cb1b803a88e986db1/werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e", size = 224498 },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "where-fi"
|
name = "where-fi"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "grpcio" },
|
{ name = "flask" },
|
||||||
|
{ name = "flask-sock" },
|
||||||
{ name = "h5py" },
|
{ name = "h5py" },
|
||||||
{ name = "matplotlib" },
|
{ name = "matplotlib" },
|
||||||
{ name = "numpy" },
|
{ name = "numpy" },
|
||||||
@ -1074,15 +1052,10 @@ dependencies = [
|
|||||||
{ name = "typer" },
|
{ name = "typer" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dev-dependencies]
|
|
||||||
dev = [
|
|
||||||
{ name = "grpcio-tools" },
|
|
||||||
{ name = "protoletariat" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.metadata]
|
[package.metadata]
|
||||||
requires-dist = [
|
requires-dist = [
|
||||||
{ name = "grpcio", specifier = ">=1.70.0" },
|
{ name = "flask" },
|
||||||
|
{ name = "flask-sock" },
|
||||||
{ name = "h5py", specifier = ">=3.12.1" },
|
{ name = "h5py", specifier = ">=3.12.1" },
|
||||||
{ name = "matplotlib" },
|
{ name = "matplotlib" },
|
||||||
{ name = "numpy", specifier = ">=2.0.0" },
|
{ name = "numpy", specifier = ">=2.0.0" },
|
||||||
@ -1095,8 +1068,14 @@ requires-dist = [
|
|||||||
{ name = "typer" },
|
{ name = "typer" },
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.metadata.requires-dev]
|
[[package]]
|
||||||
dev = [
|
name = "wsproto"
|
||||||
{ name = "grpcio-tools", specifier = ">=1.70.0" },
|
version = "1.2.0"
|
||||||
{ name = "protoletariat", specifier = ">=3.3.9" },
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "h11" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/c9/4a/44d3c295350d776427904d73c189e10aeae66d7f555bb2feee16d1e4ba5a/wsproto-1.2.0.tar.gz", hash = "sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065", size = 53425 }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/78/58/e860788190eba3bcce367f74d29c4675466ce8dddfba85f7827588416f01/wsproto-1.2.0-py3-none-any.whl", hash = "sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736", size = 24226 },
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,16 +1,15 @@
|
|||||||
import logging
|
import logging
|
||||||
import multiprocessing as mp
|
import multiprocessing as mp
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import numpy.typing as npt
|
import numpy.typing as npt
|
||||||
import torch
|
import torch
|
||||||
import typer
|
import typer
|
||||||
|
|
||||||
|
from .. import visualise
|
||||||
from ..config import config
|
from ..config import config
|
||||||
from ..processing.aoa import AoA
|
from ..processing.aoa import AoA
|
||||||
from ..processing.preprocess import Preprocessor
|
from ..processing.preprocess import Preprocessor
|
||||||
from ..visualise import server as visualise
|
|
||||||
from . import file, globals
|
from . import file, globals
|
||||||
|
|
||||||
app = typer.Typer(callback=globals.main)
|
app = typer.Typer(callback=globals.main)
|
||||||
@ -41,24 +40,23 @@ def heatmap() -> None:
|
|||||||
aoa = AoA()
|
aoa = AoA()
|
||||||
|
|
||||||
# Start webapp in background process
|
# Start webapp in background process
|
||||||
webapp_queue: "mp.Queue[visualise.VisualiserData]" = mp.Queue(config.sample_rate)
|
manager = mp.Manager()
|
||||||
|
webapp_queue: "mp.Queue[npt.NDArray[np.float32]]" = manager.Queue(
|
||||||
|
config.sample_rate
|
||||||
|
)
|
||||||
webapp = mp.Process(target=visualise.start, args=(webapp_queue,))
|
webapp = mp.Process(target=visualise.start, args=(webapp_queue,))
|
||||||
webapp.start()
|
webapp.start()
|
||||||
|
|
||||||
def visualise_data(data: npt.NDArray[Any], dtype: visualise.DataType) -> None:
|
|
||||||
if not webapp_queue.full():
|
|
||||||
webapp_queue.put(visualise.VisualiserData(data, dtype))
|
|
||||||
|
|
||||||
def callback(antenna_data: npt.NDArray[np.complex64]) -> None:
|
def callback(antenna_data: npt.NDArray[np.complex64]) -> None:
|
||||||
logger.info(f"Got final CSI data with shape {antenna_data.shape}")
|
logger.info(f"Got final CSI data with shape {antenna_data.shape}")
|
||||||
visualise_data(antenna_data, visualise.DataType.RAW_CSI)
|
|
||||||
processed = preprocessor.preprocess(antenna_data)
|
processed = preprocessor.preprocess(antenna_data)
|
||||||
visualise_data(processed, visualise.DataType.PROCESSED_CSI)
|
|
||||||
logger.info(f"Processed CSI data with shape {processed.shape}")
|
logger.info(f"Processed CSI data with shape {processed.shape}")
|
||||||
processed_tensor = torch.tensor(processed, device=device)
|
processed_tensor = torch.tensor(processed, device=device)
|
||||||
aoa.update(processed_tensor)
|
aoa.update(processed_tensor)
|
||||||
heatmap = aoa.heatmap()
|
|
||||||
visualise_data(heatmap, visualise.DataType.HEATMAP)
|
if not webapp_queue.full():
|
||||||
|
heatmap = aoa.heatmap()
|
||||||
|
webapp_queue.put(heatmap)
|
||||||
|
|
||||||
globals.csi_producer(csi_callback=callback)
|
globals.csi_producer(csi_callback=callback)
|
||||||
logger.info("Finished processing CSI data")
|
logger.info("Finished processing CSI data")
|
||||||
|
|||||||
@ -17,7 +17,6 @@ class Preprocessing(BaseModel):
|
|||||||
return (self.lowcut, self.highcut)
|
return (self.lowcut, self.highcut)
|
||||||
|
|
||||||
bandpass: Bandpass
|
bandpass: Bandpass
|
||||||
subcarrier_step: int
|
|
||||||
|
|
||||||
|
|
||||||
class MUSIC(BaseModel):
|
class MUSIC(BaseModel):
|
||||||
@ -68,8 +67,8 @@ class Config(BaseModel):
|
|||||||
@property
|
@property
|
||||||
def delta_f(self) -> int:
|
def delta_f(self) -> int:
|
||||||
if self.frame_format == "HESU":
|
if self.frame_format == "HESU":
|
||||||
return 78_125 * self.preprocessing.subcarrier_step
|
return 78_125
|
||||||
return 312_500 * self.preprocessing.subcarrier_step
|
return 312_500
|
||||||
|
|
||||||
@model_validator(mode="after")
|
@model_validator(mode="after")
|
||||||
def channels(self) -> Self:
|
def channels(self) -> Self:
|
||||||
|
|||||||
@ -34,8 +34,8 @@ class Preprocessor:
|
|||||||
h,
|
h,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Skip subcarrierss per config
|
# Skip every other subcarrier
|
||||||
h_hat = h_hat[:: config.preprocessing.subcarrier_step, :, :]
|
# h_hat = h_hat[::2, :, :]
|
||||||
# logger.info(f"CSI shape: {h_hat.shape}")
|
# logger.info(f"CSI shape: {h_hat.shape}")
|
||||||
|
|
||||||
h_hat = np.multiply(h_hat, h_hat.conj() / abs(h_hat.conj()))
|
h_hat = np.multiply(h_hat, h_hat.conj() / abs(h_hat.conj()))
|
||||||
|
|||||||
2
where_fi/visualise/.gitignore
vendored
2
where_fi/visualise/.gitignore
vendored
@ -1,2 +0,0 @@
|
|||||||
server/generated
|
|
||||||
frontend/src/grpc
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
all: server/generated frontend/src/grpc
|
|
||||||
|
|
||||||
server/generated: protos/*.proto
|
|
||||||
mkdir -p server/generated
|
|
||||||
find protos/ -type f -name "*.proto" | xargs uv run python -m grpc_tools.protoc -Iprotos --python_out=server/generated --pyi_out=server/generated --grpc_python_out=server/generated
|
|
||||||
find protos/ -type f -name "*.proto" | xargs uv run protol --create-package --in-place --python-out server/generated/ protoc --proto-path=protos/
|
|
||||||
|
|
||||||
frontend/src/grpc: protos/*.proto
|
|
||||||
find protos/ -name "*.proto" | xargs npm exec --prefix frontend/ protoc --ts_out frontend/src/grpc -I protos/
|
|
||||||
@ -0,0 +1,136 @@
|
|||||||
|
import io
|
||||||
|
import logging
|
||||||
|
import multiprocessing as mp
|
||||||
|
import time
|
||||||
|
from datetime import datetime
|
||||||
|
from typing import Generator
|
||||||
|
|
||||||
|
import matplotlib
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
import numpy.typing as npt
|
||||||
|
from flask import Flask, Response, render_template, request
|
||||||
|
from flask_sock import Sock
|
||||||
|
from simple_websocket import Server
|
||||||
|
|
||||||
|
from ..config import config
|
||||||
|
from ..processing.aoa import AoA
|
||||||
|
|
||||||
|
matplotlib.use("agg")
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
sock = Sock(app)
|
||||||
|
aoa_queue = None
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
data: npt.NDArray[np.complex128] = np.array([], dtype=complex)
|
||||||
|
aoa: AoA = AoA()
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/preprocessed")
|
||||||
|
def preprocessed() -> str:
|
||||||
|
return render_template("preprocessed.html")
|
||||||
|
|
||||||
|
|
||||||
|
Subscriber = Server
|
||||||
|
subscriber_settings: dict[Subscriber, tuple[int, int, int]] = {}
|
||||||
|
|
||||||
|
|
||||||
|
@sock.route("/data")
|
||||||
|
def get_data(sock: Subscriber) -> None:
|
||||||
|
while True:
|
||||||
|
msg = sock.receive()
|
||||||
|
if len(msg.split()) != 3:
|
||||||
|
break
|
||||||
|
subcarrier, rx, tx = map(int, msg.split())
|
||||||
|
subscriber_settings[sock] = (subcarrier, rx, tx)
|
||||||
|
|
||||||
|
|
||||||
|
def add_data(
|
||||||
|
raw_data: npt.NDArray[np.complex128], new_data: npt.NDArray[np.complex128]
|
||||||
|
) -> None:
|
||||||
|
if config.VISUALISE_RAW:
|
||||||
|
magn = np.abs(raw_data)
|
||||||
|
phase = np.angle(raw_data)
|
||||||
|
|
||||||
|
new_mag = np.abs(new_data)
|
||||||
|
new_phase = np.angle(new_data)
|
||||||
|
|
||||||
|
fig, axs = plt.subplots(2, 2)
|
||||||
|
axs[0, 0].plot(magn[:, 0, 0], c="b")
|
||||||
|
axs[0, 0].plot(magn[:, 1, 0], c="orange")
|
||||||
|
axs[1, 0].plot(new_mag[:, 0, 0], c="b")
|
||||||
|
axs[1, 0].plot(new_mag[:, 1, 0], c="orange")
|
||||||
|
axs[0, 1].plot(phase[:, 0, 0], c="b")
|
||||||
|
axs[0, 1].plot(phase[:, 1, 0], c="orange")
|
||||||
|
axs[1, 1].plot(new_phase[:, 0, 0], c="b")
|
||||||
|
axs[1, 1].plot(new_phase[:, 1, 0], c="orange")
|
||||||
|
fig.savefig("/tmp/plot.png")
|
||||||
|
plt.close(fig)
|
||||||
|
|
||||||
|
global data
|
||||||
|
if data.size == 0:
|
||||||
|
data = np.expand_dims(new_data, axis=0)
|
||||||
|
else:
|
||||||
|
data = np.concat([data, np.expand_dims(new_data, axis=0)], axis=0)
|
||||||
|
|
||||||
|
# Only keep latest 100 entries
|
||||||
|
if data.shape[0] > 100:
|
||||||
|
data = data[-100:]
|
||||||
|
to_remove: list[Subscriber] = []
|
||||||
|
for subscriber in subscriber_settings:
|
||||||
|
try:
|
||||||
|
subcarrier, rx, tx = subscriber_settings[subscriber]
|
||||||
|
subscriber.send(new_data.real[subcarrier, rx, tx])
|
||||||
|
except Exception as e:
|
||||||
|
to_remove.append(subscriber)
|
||||||
|
print(e)
|
||||||
|
|
||||||
|
for subscriber in to_remove:
|
||||||
|
del subscriber_settings[subscriber]
|
||||||
|
|
||||||
|
|
||||||
|
def plot_heatmap(heatmap: npt.NDArray[np.float32]) -> io.BytesIO:
|
||||||
|
logger.info(f"Making heatmap with aoa of {aoa.timestamp}")
|
||||||
|
fig = plt.figure()
|
||||||
|
ax = fig.add_axes([0.1, 0.1, 0.9, 0.9]) # , polar=True)
|
||||||
|
r = np.linspace(
|
||||||
|
0, config.music.heatmap.tof_max, config.music.heatmap.tof_resolution
|
||||||
|
)
|
||||||
|
theta = np.linspace(0, np.pi, config.music.heatmap.theta_resolution) # Angle values
|
||||||
|
|
||||||
|
mesh = ax.pcolormesh(theta, r, heatmap, edgecolors="face", vmin=0, vmax=50)
|
||||||
|
|
||||||
|
fig.colorbar(mesh, ax=ax)
|
||||||
|
buf = io.BytesIO()
|
||||||
|
fig.savefig(buf, format="jpeg")
|
||||||
|
plt.close(fig)
|
||||||
|
|
||||||
|
buf.seek(0)
|
||||||
|
return buf
|
||||||
|
|
||||||
|
|
||||||
|
def gather_aoa() -> Generator[bytes, None, None]:
|
||||||
|
assert aoa_queue is not None
|
||||||
|
|
||||||
|
while True:
|
||||||
|
logger.debug("Receiving from aoa pipe")
|
||||||
|
heatmap = aoa_queue.get()
|
||||||
|
buf = plot_heatmap(heatmap)
|
||||||
|
yield (b"--frame\r\nContent-Type: image/jpeg\r\n\r\n" + buf.read() + b"\r\n")
|
||||||
|
buf.close()
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/aoa_tof")
|
||||||
|
def aoa_tof() -> Response:
|
||||||
|
return Response(gather_aoa(), mimetype="multipart/x-mixed-replace; boundary=frame")
|
||||||
|
|
||||||
|
|
||||||
|
def start(conn: "mp.Queue[npt.NDArray[np.float32]]") -> None:
|
||||||
|
global app, aoa_queue
|
||||||
|
|
||||||
|
aoa_queue = conn
|
||||||
|
app.run(debug=True, use_reloader=False, host="0.0.0.0")
|
||||||
|
logger.info("Visualisation server shut down")
|
||||||
@ -1,66 +0,0 @@
|
|||||||
admin:
|
|
||||||
access_log_path: /tmp/admin_access.log
|
|
||||||
address:
|
|
||||||
socket_address: { address: 0.0.0.0, port_value: 9901 }
|
|
||||||
|
|
||||||
static_resources:
|
|
||||||
listeners:
|
|
||||||
- name: listener_0
|
|
||||||
address:
|
|
||||||
socket_address: { address: 0.0.0.0, port_value: 8080 }
|
|
||||||
filter_chains:
|
|
||||||
- filters:
|
|
||||||
- name: envoy.filters.network.http_connection_manager
|
|
||||||
typed_config:
|
|
||||||
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
|
|
||||||
codec_type: auto
|
|
||||||
stat_prefix: ingress_http
|
|
||||||
route_config:
|
|
||||||
name: local_route
|
|
||||||
virtual_hosts:
|
|
||||||
- name: local_service
|
|
||||||
domains: ["*"]
|
|
||||||
routes:
|
|
||||||
- match: { prefix: "/" }
|
|
||||||
route:
|
|
||||||
cluster: echo_service
|
|
||||||
timeout: 0s
|
|
||||||
max_stream_duration:
|
|
||||||
grpc_timeout_header_max: 0s
|
|
||||||
cors:
|
|
||||||
allow_origin_string_match:
|
|
||||||
- prefix: "*"
|
|
||||||
allow_methods: GET, PUT, DELETE, POST, OPTIONS
|
|
||||||
allow_headers: keep-alive,user-agent,cache-control,content-type,content-transfer-encoding,custom-header-1,x-accept-content-transfer-encoding,x-accept-response-streaming,x-user-agent,x-grpc-web,grpc-timeout
|
|
||||||
max_age: "1728000"
|
|
||||||
expose_headers: custom-header-1,grpc-status,grpc-message
|
|
||||||
http_filters:
|
|
||||||
- name: envoy.filters.http.grpc_web
|
|
||||||
typed_config:
|
|
||||||
"@type": type.googleapis.com/envoy.extensions.filters.http.grpc_web.v3.GrpcWeb
|
|
||||||
- name: envoy.filters.http.cors
|
|
||||||
typed_config:
|
|
||||||
"@type": type.googleapis.com/envoy.extensions.filters.http.cors.v3.Cors
|
|
||||||
- name: envoy.filters.http.router
|
|
||||||
typed_config:
|
|
||||||
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
|
|
||||||
clusters:
|
|
||||||
- name: echo_service
|
|
||||||
connect_timeout: 0.25s
|
|
||||||
type: logical_dns
|
|
||||||
# HTTP/2 support
|
|
||||||
typed_extension_protocol_options:
|
|
||||||
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
|
|
||||||
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
|
|
||||||
explicit_http_config:
|
|
||||||
http2_protocol_options: {}
|
|
||||||
lb_policy: round_robin
|
|
||||||
load_assignment:
|
|
||||||
cluster_name: cluster_0
|
|
||||||
endpoints:
|
|
||||||
- lb_endpoints:
|
|
||||||
- endpoint:
|
|
||||||
address:
|
|
||||||
socket_address:
|
|
||||||
address: 127.0.0.1
|
|
||||||
port_value: 50051
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue}]
|
|
||||||
charset = utf-8
|
|
||||||
indent_size = 2
|
|
||||||
indent_style = space
|
|
||||||
insert_final_newline = true
|
|
||||||
trim_trailing_whitespace = true
|
|
||||||
|
|
||||||
end_of_line = lf
|
|
||||||
max_line_length = 100
|
|
||||||
1
where_fi/visualise/frontend/.gitattributes
vendored
1
where_fi/visualise/frontend/.gitattributes
vendored
@ -1 +0,0 @@
|
|||||||
* text=auto eol=lf
|
|
||||||
30
where_fi/visualise/frontend/.gitignore
vendored
30
where_fi/visualise/frontend/.gitignore
vendored
@ -1,30 +0,0 @@
|
|||||||
# Logs
|
|
||||||
logs
|
|
||||||
*.log
|
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
|
|
||||||
node_modules
|
|
||||||
.DS_Store
|
|
||||||
dist
|
|
||||||
dist-ssr
|
|
||||||
coverage
|
|
||||||
*.local
|
|
||||||
|
|
||||||
/cypress/videos/
|
|
||||||
/cypress/screenshots/
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.idea
|
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.sw?
|
|
||||||
|
|
||||||
*.tsbuildinfo
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
|
|
||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/prettierrc",
|
|
||||||
"semi": false,
|
|
||||||
"singleQuote": true,
|
|
||||||
"printWidth": 100
|
|
||||||
}
|
|
||||||
1
where_fi/visualise/frontend/env.d.ts
vendored
1
where_fi/visualise/frontend/env.d.ts
vendored
@ -1 +0,0 @@
|
|||||||
/// <reference types="vite/client" />
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
import pluginVue from 'eslint-plugin-vue'
|
|
||||||
import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript'
|
|
||||||
import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'
|
|
||||||
|
|
||||||
// To allow more languages other than `ts` in `.vue` files, uncomment the following lines:
|
|
||||||
// import { configureVueProject } from '@vue/eslint-config-typescript'
|
|
||||||
// configureVueProject({ scriptLangs: ['ts', 'tsx'] })
|
|
||||||
// More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup
|
|
||||||
|
|
||||||
export default defineConfigWithVueTs(
|
|
||||||
{
|
|
||||||
name: 'app/files-to-lint',
|
|
||||||
files: ['**/*.{ts,mts,tsx,vue}'],
|
|
||||||
},
|
|
||||||
|
|
||||||
{
|
|
||||||
name: 'app/files-to-ignore',
|
|
||||||
ignores: ['**/dist/**', '**/dist-ssr/**', '**/coverage/**'],
|
|
||||||
},
|
|
||||||
|
|
||||||
pluginVue.configs['flat/essential'],
|
|
||||||
vueTsConfigs.recommended,
|
|
||||||
skipFormatting,
|
|
||||||
)
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Where-Fi Visualizer</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app"></div>
|
|
||||||
<script type="module" src="/src/main.ts"></script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
5326
where_fi/visualise/frontend/package-lock.json
generated
5326
where_fi/visualise/frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "visualise",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"private": true,
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "vite",
|
|
||||||
"build": "run-p type-check \"build-only {@}\" --",
|
|
||||||
"preview": "vite preview",
|
|
||||||
"build-only": "vite build",
|
|
||||||
"type-check": "vue-tsc --build",
|
|
||||||
"lint": "eslint . --fix",
|
|
||||||
"format": "prettier --write src/"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@mdi/font": "^7.4.47",
|
|
||||||
"@protobuf-ts/grpcweb-transport": "^2.9.4",
|
|
||||||
"buffer": "^6.0.3",
|
|
||||||
"google-protobuf": "^3.21.4",
|
|
||||||
"grpc-web": "^1.5.0",
|
|
||||||
"plotly.js-dist": "^3.0.1",
|
|
||||||
"plotly.js-dist-min": "^3.0.1",
|
|
||||||
"vue": "^3.5.13",
|
|
||||||
"vuetify": "^3.7.12"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@protobuf-ts/plugin": "^2.9.4",
|
|
||||||
"@tsconfig/node22": "^22.0.0",
|
|
||||||
"@types/node": "^22.13.1",
|
|
||||||
"@types/plotly.js": "^2.35.2",
|
|
||||||
"@types/plotly.js-dist-min": "^2.3.4",
|
|
||||||
"@vitejs/plugin-vue": "^5.2.1",
|
|
||||||
"@vue/eslint-config-prettier": "^10.1.0",
|
|
||||||
"@vue/eslint-config-typescript": "^14.3.0",
|
|
||||||
"@vue/tsconfig": "^0.7.0",
|
|
||||||
"eslint": "^9.18.0",
|
|
||||||
"eslint-plugin-vue": "^9.32.0",
|
|
||||||
"jiti": "^2.4.2",
|
|
||||||
"npm-run-all2": "^7.0.2",
|
|
||||||
"prettier": "^3.4.2",
|
|
||||||
"typescript": "~5.7.3",
|
|
||||||
"vite": "^6.0.11",
|
|
||||||
"vite-plugin-vue-devtools": "^7.7.1",
|
|
||||||
"vue-tsc": "^2.2.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,42 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import PlotList from './components/PlotList.vue'
|
|
||||||
import Figure from './components/Figure.vue'
|
|
||||||
import { Figure as FigureType } from './grpc/figure'
|
|
||||||
|
|
||||||
var plots = ref<FigureType[]>([])
|
|
||||||
var paused = ref(false)
|
|
||||||
|
|
||||||
function addPlot(fig: FigureType) {
|
|
||||||
console.log('Plot added', fig)
|
|
||||||
plots.value.push(fig)
|
|
||||||
console.log(plots)
|
|
||||||
}
|
|
||||||
function removePlot(fig: FigureType) {
|
|
||||||
console.log('Plot removed', fig)
|
|
||||||
plots.value = plots.value.filter((x) => x.uuid !== fig.uuid)
|
|
||||||
console.log(plots)
|
|
||||||
}
|
|
||||||
declare module '@vue/runtime-core' {
|
|
||||||
interface ComponentCustomProperties {
|
|
||||||
$props: {
|
|
||||||
onClick?: (e: MouseEvent) => void
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<v-app>
|
|
||||||
<PlotList @figure-selected="addPlot" @figure-deselected="removePlot" />
|
|
||||||
|
|
||||||
<v-main>
|
|
||||||
<v-container fluid>
|
|
||||||
<Figure v-for="plot in plots" :key="plot.uuid" :figure="plot" :paused="paused" />
|
|
||||||
</v-container>
|
|
||||||
<v-fab location="right bottom" color="secondary" @click="paused = !paused" icon app>
|
|
||||||
<v-icon :icon="paused ? 'mdi-play' : 'mdi-pause'"></v-icon>
|
|
||||||
</v-fab>
|
|
||||||
</v-main>
|
|
||||||
</v-app>
|
|
||||||
</template>
|
|
||||||
@ -1,86 +0,0 @@
|
|||||||
/* color palette from <https://github.com/vuejs/theme> */
|
|
||||||
:root {
|
|
||||||
--vt-c-white: #ffffff;
|
|
||||||
--vt-c-white-soft: #f8f8f8;
|
|
||||||
--vt-c-white-mute: #f2f2f2;
|
|
||||||
|
|
||||||
--vt-c-black: #181818;
|
|
||||||
--vt-c-black-soft: #222222;
|
|
||||||
--vt-c-black-mute: #282828;
|
|
||||||
|
|
||||||
--vt-c-indigo: #2c3e50;
|
|
||||||
|
|
||||||
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
|
|
||||||
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
|
|
||||||
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
|
|
||||||
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
|
|
||||||
|
|
||||||
--vt-c-text-light-1: var(--vt-c-indigo);
|
|
||||||
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
|
|
||||||
--vt-c-text-dark-1: var(--vt-c-white);
|
|
||||||
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* semantic color variables for this project */
|
|
||||||
:root {
|
|
||||||
--color-background: var(--vt-c-white);
|
|
||||||
--color-background-soft: var(--vt-c-white-soft);
|
|
||||||
--color-background-mute: var(--vt-c-white-mute);
|
|
||||||
|
|
||||||
--color-border: var(--vt-c-divider-light-2);
|
|
||||||
--color-border-hover: var(--vt-c-divider-light-1);
|
|
||||||
|
|
||||||
--color-heading: var(--vt-c-text-light-1);
|
|
||||||
--color-text: var(--vt-c-text-light-1);
|
|
||||||
|
|
||||||
--section-gap: 160px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--color-background: var(--vt-c-black);
|
|
||||||
--color-background-soft: var(--vt-c-black-soft);
|
|
||||||
--color-background-mute: var(--vt-c-black-mute);
|
|
||||||
|
|
||||||
--color-border: var(--vt-c-divider-dark-2);
|
|
||||||
--color-border-hover: var(--vt-c-divider-dark-1);
|
|
||||||
|
|
||||||
--color-heading: var(--vt-c-text-dark-1);
|
|
||||||
--color-text: var(--vt-c-text-dark-2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*,
|
|
||||||
*::before,
|
|
||||||
*::after {
|
|
||||||
box-sizing: border-box;
|
|
||||||
margin: 0;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
min-height: 100vh;
|
|
||||||
color: var(--color-text);
|
|
||||||
background: var(--color-background);
|
|
||||||
transition:
|
|
||||||
color 0.5s,
|
|
||||||
background-color 0.5s;
|
|
||||||
line-height: 1.6;
|
|
||||||
font-family:
|
|
||||||
Inter,
|
|
||||||
-apple-system,
|
|
||||||
BlinkMacSystemFont,
|
|
||||||
'Segoe UI',
|
|
||||||
Roboto,
|
|
||||||
Oxygen,
|
|
||||||
Ubuntu,
|
|
||||||
Cantarell,
|
|
||||||
'Fira Sans',
|
|
||||||
'Droid Sans',
|
|
||||||
'Helvetica Neue',
|
|
||||||
sans-serif;
|
|
||||||
font-size: 15px;
|
|
||||||
text-rendering: optimizeLegibility;
|
|
||||||
-webkit-font-smoothing: antialiased;
|
|
||||||
-moz-osx-font-smoothing: grayscale;
|
|
||||||
}
|
|
||||||
@ -1,92 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import * as Plotly from 'plotly.js-dist-min'
|
|
||||||
import { Figure, FigureData } from '../grpc/figure'
|
|
||||||
import { FigureServiceClient } from '../grpc/figure.client'
|
|
||||||
import { GrpcWebFetchTransport } from '@protobuf-ts/grpcweb-transport'
|
|
||||||
import { host } from '../connect'
|
|
||||||
import { onMounted, ref } from 'vue'
|
|
||||||
import { onBeforeUnmount } from 'vue'
|
|
||||||
import { computed } from 'vue'
|
|
||||||
|
|
||||||
const { figure, paused = false } = defineProps<{ figure: Figure; paused?: boolean }>()
|
|
||||||
const cancel = ref<boolean>(false)
|
|
||||||
|
|
||||||
const data = ref<FigureData | null>(null)
|
|
||||||
const plotData = computed(() => {
|
|
||||||
if (data.value) {
|
|
||||||
switch (data.value.figure.oneofKind) {
|
|
||||||
case 'line':
|
|
||||||
return data.value.figure.line.lines.map((line) => ({
|
|
||||||
x: line.x.length == 0 ? undefined : line.x,
|
|
||||||
y: line.y,
|
|
||||||
type: 'scatter' as const,
|
|
||||||
name: line.label,
|
|
||||||
color: line.color ? line.color : undefined,
|
|
||||||
}))
|
|
||||||
case 'heatmap':
|
|
||||||
return []
|
|
||||||
/* data.value.figure.heatmap.lines.map((line) => {
|
|
||||||
return {
|
|
||||||
x: line.x,
|
|
||||||
y: line.y,
|
|
||||||
type: 'scatter',
|
|
||||||
name: line.label,
|
|
||||||
color: line.color,
|
|
||||||
}
|
|
||||||
})*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return []
|
|
||||||
})
|
|
||||||
|
|
||||||
const layout = {
|
|
||||||
title: { text: figure.title },
|
|
||||||
xaxis: { title: { text: figure.xLabel } },
|
|
||||||
yaxis: { title: { text: figure.yLabel } },
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateGraph() {
|
|
||||||
console.log('Updating graph with', plotData.value)
|
|
||||||
Plotly.newPlot(figure.uuid, plotData.value, layout, { responsive: true })
|
|
||||||
}
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
console.log('Mounted')
|
|
||||||
|
|
||||||
updateGraph()
|
|
||||||
|
|
||||||
const transport = new GrpcWebFetchTransport({ baseUrl: host })
|
|
||||||
const figureService = new FigureServiceClient(transport)
|
|
||||||
const stream = figureService.getFigureUpdate({ uuid: figure.uuid })
|
|
||||||
for await (const response of stream.responses) {
|
|
||||||
if (cancel.value) {
|
|
||||||
console.log('Stopping stream...')
|
|
||||||
break
|
|
||||||
}
|
|
||||||
console.log(`Got new value for ${figure.uuid}:`, response)
|
|
||||||
|
|
||||||
if (!paused) {
|
|
||||||
data.value = response
|
|
||||||
updateGraph()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
console.log('Component is about to unmount, stopping stream...')
|
|
||||||
cancel.value = true
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<v-row class="w-100">
|
|
||||||
<v-col cols="12">
|
|
||||||
<v-card class="w-100">
|
|
||||||
<v-card-title>{{ figure.title }}</v-card-title>
|
|
||||||
<v-card-text>
|
|
||||||
<div :id="figure.uuid" class="w-100" />
|
|
||||||
</v-card-text>
|
|
||||||
</v-card>
|
|
||||||
</v-col>
|
|
||||||
</v-row>
|
|
||||||
</template>
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { defineComponent, ref } from 'vue'
|
|
||||||
import { Figure } from '../grpc/figure'
|
|
||||||
import { FigureServiceClient } from '../grpc/figure.client'
|
|
||||||
import { GrpcWebFetchTransport } from '@protobuf-ts/grpcweb-transport'
|
|
||||||
import { host } from '../connect'
|
|
||||||
|
|
||||||
const plots = ref<Figure[]>([])
|
|
||||||
const loading = ref(true)
|
|
||||||
const error = ref<string | null>(null)
|
|
||||||
var emit = (_: any, ...args: any[]) => {
|
|
||||||
console.log('No emit function set', args)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
emits: ['figure-selected', 'figure-deselected'],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
selected: [],
|
|
||||||
loading: loading,
|
|
||||||
plots: plots,
|
|
||||||
error,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setup(_, ctx) {
|
|
||||||
console.log('Setup')
|
|
||||||
emit = ctx.emit
|
|
||||||
},
|
|
||||||
async mounted() {
|
|
||||||
const transport = new GrpcWebFetchTransport({ baseUrl: host })
|
|
||||||
const figureService = new FigureServiceClient(transport)
|
|
||||||
const stream = figureService.getFigure({})
|
|
||||||
for await (const response of stream.responses) {
|
|
||||||
console.log('Got new figure', response)
|
|
||||||
plots.value.push(response)
|
|
||||||
}
|
|
||||||
console.log('Done fetching figures')
|
|
||||||
loading.value = false
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
selected(newVal: string[], oldVal: string[]) {
|
|
||||||
const added = newVal.filter((x) => !oldVal.includes(x))
|
|
||||||
const removed = oldVal.filter((x) => !newVal.includes(x))
|
|
||||||
|
|
||||||
for (const uuid of added) {
|
|
||||||
console.log('Selected', uuid)
|
|
||||||
const plot = plots.value.find((x) => x.uuid === uuid)
|
|
||||||
emit('figure-selected', plot)
|
|
||||||
}
|
|
||||||
for (const uuid of removed) {
|
|
||||||
console.log('Deselected', uuid)
|
|
||||||
const plot = plots.value.find((x) => x.uuid === uuid)
|
|
||||||
emit('figure-deselected', plot)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<v-navigation-drawer permanent width="250">
|
|
||||||
<v-list>
|
|
||||||
<v-list-item title="Available figures" subtitle="Choose some of the figures below" />
|
|
||||||
</v-list>
|
|
||||||
<v-divider />
|
|
||||||
<v-list v-model:selected="selected" select-strategy="leaf" nav>
|
|
||||||
<v-list-item v-for="plot in plots" :key="plot.uuid" :value="plot.uuid">
|
|
||||||
<v-list-item-title>{{ plot.title }}</v-list-item-title>
|
|
||||||
<v-list-item-subtitle class="text-high-emphasis"
|
|
||||||
>{{ plot.xLabel }} w/ {{ plot.yLabel }}</v-list-item-subtitle
|
|
||||||
>
|
|
||||||
</v-list-item>
|
|
||||||
<v-skeleton-loader
|
|
||||||
type="list-item-two-line"
|
|
||||||
v-for="n in 3"
|
|
||||||
:key="n"
|
|
||||||
v-if="loading"
|
|
||||||
></v-skeleton-loader>
|
|
||||||
</v-list>
|
|
||||||
</v-navigation-drawer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped></style>
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export const host = 'http://localhost:8080'
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
import App from './App.vue'
|
|
||||||
|
|
||||||
import { createApp } from 'vue'
|
|
||||||
import 'vuetify/styles'
|
|
||||||
import { createVuetify } from 'vuetify'
|
|
||||||
import * as components from 'vuetify/components'
|
|
||||||
import * as directives from 'vuetify/directives'
|
|
||||||
import { aliases, mdi } from 'vuetify/iconsets/mdi'
|
|
||||||
import '@mdi/font/css/materialdesignicons.css'
|
|
||||||
|
|
||||||
const vuetify = createVuetify({
|
|
||||||
components,
|
|
||||||
directives,
|
|
||||||
theme: { defaultTheme: 'dark' },
|
|
||||||
icons: {
|
|
||||||
defaultSet: 'mdi',
|
|
||||||
aliases,
|
|
||||||
sets: {
|
|
||||||
mdi,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
createApp(App).use(vuetify).mount('#app')
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "@vue/tsconfig/tsconfig.dom.json",
|
|
||||||
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
|
|
||||||
"exclude": ["src/**/__tests__/*"],
|
|
||||||
"compilerOptions": {
|
|
||||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
||||||
|
|
||||||
"paths": {
|
|
||||||
"@/*": ["./src/*"]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"vueCompilerOptions": {
|
|
||||||
"fallthroughAttributes": true,
|
|
||||||
"strictTemplates": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"files": [],
|
|
||||||
"references": [
|
|
||||||
{
|
|
||||||
"path": "./tsconfig.node.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"path": "./tsconfig.app.json"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "@tsconfig/node22/tsconfig.json",
|
|
||||||
"include": [
|
|
||||||
"vite.config.*",
|
|
||||||
"vitest.config.*",
|
|
||||||
"cypress.config.*",
|
|
||||||
"nightwatch.conf.*",
|
|
||||||
"playwright.config.*",
|
|
||||||
"eslint.config.*"
|
|
||||||
],
|
|
||||||
"compilerOptions": {
|
|
||||||
"noEmit": true,
|
|
||||||
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
||||||
|
|
||||||
"module": "ESNext",
|
|
||||||
"moduleResolution": "Bundler",
|
|
||||||
"types": ["node"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
import { fileURLToPath, URL } from 'node:url'
|
|
||||||
|
|
||||||
import { defineConfig } from 'vite'
|
|
||||||
import vue from '@vitejs/plugin-vue'
|
|
||||||
import vueDevTools from 'vite-plugin-vue-devtools'
|
|
||||||
|
|
||||||
// https://vite.dev/config/
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [vue(), vueDevTools()],
|
|
||||||
resolve: {
|
|
||||||
alias: {
|
|
||||||
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
import "figure_type/line.proto";
|
|
||||||
import "figure_type/heatmap.proto";
|
|
||||||
|
|
||||||
message Figure {
|
|
||||||
string uuid = 1;
|
|
||||||
string title = 2;
|
|
||||||
string x_label = 3;
|
|
||||||
string y_label = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
message FigureData {
|
|
||||||
string uuid = 1;
|
|
||||||
oneof figure {
|
|
||||||
LineChartData line = 2;
|
|
||||||
HeatmapData heatmap = 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
message FigureRequest {}
|
|
||||||
message FigureDataRequest { string uuid = 1; }
|
|
||||||
|
|
||||||
service FigureService {
|
|
||||||
rpc GetFigure(FigureRequest) returns (stream Figure) {}
|
|
||||||
rpc GetFigureUpdate(FigureDataRequest) returns (stream FigureData) {}
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
message HeatmapData {
|
|
||||||
string uuid = 1;
|
|
||||||
repeated float x = 2;
|
|
||||||
repeated float y = 3;
|
|
||||||
uint32 width = 4;
|
|
||||||
uint32 height = 5;
|
|
||||||
string cmap = 6;
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
message LineChartData {
|
|
||||||
message Line {
|
|
||||||
string uuid = 1;
|
|
||||||
repeated float x = 2;
|
|
||||||
repeated float y = 3;
|
|
||||||
string label = 4;
|
|
||||||
string color = 5;
|
|
||||||
}
|
|
||||||
repeated Line lines = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message LineChartPoint {
|
|
||||||
string uuid = 1;
|
|
||||||
float x = 2;
|
|
||||||
float y = 3;
|
|
||||||
}
|
|
||||||
@ -1,127 +0,0 @@
|
|||||||
import logging
|
|
||||||
import multiprocessing as mp
|
|
||||||
import queue
|
|
||||||
import threading
|
|
||||||
import uuid
|
|
||||||
from concurrent import futures
|
|
||||||
from dataclasses import dataclass
|
|
||||||
from enum import Enum
|
|
||||||
from typing import Any, Generator
|
|
||||||
|
|
||||||
import grpc
|
|
||||||
import numpy as np
|
|
||||||
import numpy.typing as npt
|
|
||||||
|
|
||||||
from .generated import figure_pb2, figure_pb2_grpc
|
|
||||||
from .generated.figure_type import heatmap_pb2, line_pb2
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
clients: dict[str, list[queue.Queue[figure_pb2.FigureData]]] = {}
|
|
||||||
clients_lock = threading.Lock()
|
|
||||||
|
|
||||||
|
|
||||||
class DataType(Enum):
|
|
||||||
RAW_CSI = 1
|
|
||||||
PROCESSED_CSI = 2
|
|
||||||
HEATMAP = 3
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class VisualiserData:
|
|
||||||
data: npt.NDArray[Any]
|
|
||||||
dtype: DataType
|
|
||||||
|
|
||||||
|
|
||||||
figures = {
|
|
||||||
"raw_phase": figure_pb2.Figure(
|
|
||||||
uuid=str(uuid.uuid4()),
|
|
||||||
title="Raw CSI Phase",
|
|
||||||
x_label="Subcarrier",
|
|
||||||
y_label="Phase",
|
|
||||||
),
|
|
||||||
"processed_phase": figure_pb2.Figure(
|
|
||||||
uuid=str(uuid.uuid4()),
|
|
||||||
title="Preprocessed CSI Phase",
|
|
||||||
x_label="Subcarrier",
|
|
||||||
y_label="Phase",
|
|
||||||
),
|
|
||||||
"aoa_heatmap": figure_pb2.Figure(
|
|
||||||
uuid=str(uuid.uuid4()),
|
|
||||||
title="Preprocessed CSI Phase",
|
|
||||||
x_label="Subcarrier",
|
|
||||||
y_label="Phase",
|
|
||||||
),
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class FigureServer(figure_pb2_grpc.FigureServiceServicer):
|
|
||||||
def GetFigure(
|
|
||||||
self, request: figure_pb2.FigureRequest, context: grpc.ServicerContext
|
|
||||||
) -> Generator[figure_pb2.Figure, None, None]:
|
|
||||||
for figure in figures.values():
|
|
||||||
yield figure
|
|
||||||
|
|
||||||
def GetFigureUpdate(
|
|
||||||
self, request: figure_pb2.FigureDataRequest, context: grpc.ServicerContext
|
|
||||||
) -> Generator[figure_pb2.FigureData, None, None]:
|
|
||||||
logger.info(
|
|
||||||
f"Received request for figure data stream for figure {request.uuid}"
|
|
||||||
)
|
|
||||||
|
|
||||||
with clients_lock:
|
|
||||||
q: queue.Queue[figure_pb2.FigureData] = queue.Queue()
|
|
||||||
if request.uuid not in clients:
|
|
||||||
clients[request.uuid] = []
|
|
||||||
clients[request.uuid].append(q)
|
|
||||||
|
|
||||||
try:
|
|
||||||
while context.is_active():
|
|
||||||
try:
|
|
||||||
yield q.get(timeout=1)
|
|
||||||
except queue.Empty:
|
|
||||||
pass
|
|
||||||
finally:
|
|
||||||
with clients_lock:
|
|
||||||
clients[request.uuid].remove(q)
|
|
||||||
|
|
||||||
|
|
||||||
def add_data(dtype: DataType, new_data: npt.NDArray[np.complex128]) -> None:
|
|
||||||
match dtype:
|
|
||||||
case DataType.RAW_CSI | DataType.PROCESSED_CSI:
|
|
||||||
uuid = (
|
|
||||||
figures["raw_phase"].uuid
|
|
||||||
if dtype == DataType.RAW_CSI
|
|
||||||
else figures["processed_phase"].uuid
|
|
||||||
)
|
|
||||||
lines = [
|
|
||||||
line_pb2.LineChartData.Line(
|
|
||||||
y=np.angle(new_data)[:, i, 0], label=f"Antenna {i}"
|
|
||||||
)
|
|
||||||
for i in range(new_data.shape[1])
|
|
||||||
]
|
|
||||||
linechart = line_pb2.LineChartData(lines=lines)
|
|
||||||
for q in clients.get(uuid, []):
|
|
||||||
q.put(figure_pb2.FigureData(uuid=uuid, line=linechart))
|
|
||||||
case DataType.HEATMAP:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def listen_for_data(data_queue: "mp.Queue[VisualiserData]") -> None:
|
|
||||||
while True:
|
|
||||||
data = data_queue.get()
|
|
||||||
add_data(data.dtype, data.data)
|
|
||||||
|
|
||||||
|
|
||||||
def start(data_queue: "mp.Queue[VisualiserData]") -> None:
|
|
||||||
logger.info("Visualisation server shut down")
|
|
||||||
|
|
||||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
|
|
||||||
figure_pb2_grpc.add_FigureServiceServicer_to_server(FigureServer(), server)
|
|
||||||
server.add_insecure_port("[::]:50051")
|
|
||||||
server.add_insecure_port("0.0.0.0:50051")
|
|
||||||
logger.info("Starting server on port 50051")
|
|
||||||
server.start()
|
|
||||||
logger.info("Server started")
|
|
||||||
threading.Thread(target=listen_for_data, args=(data_queue,), daemon=True).start()
|
|
||||||
server.wait_for_termination()
|
|
||||||
42
where_fi/visualise/static/plot.js
Normal file
42
where_fi/visualise/static/plot.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
const plotElement = document.getElementById("plot");
|
||||||
|
|
||||||
|
const layout = {
|
||||||
|
title: "Real-Time Complex Data Visualization",
|
||||||
|
xaxis: { title: "Time (ms)" },
|
||||||
|
yaxis: { title: "Value" },
|
||||||
|
};
|
||||||
|
|
||||||
|
Plotly.newPlot(
|
||||||
|
plotElement,
|
||||||
|
[
|
||||||
|
{
|
||||||
|
x: [],
|
||||||
|
y: [],
|
||||||
|
type: "scatter",
|
||||||
|
mode: "lines+markers", // Line + markers
|
||||||
|
},
|
||||||
|
],
|
||||||
|
layout,
|
||||||
|
);
|
||||||
|
|
||||||
|
const socket = new WebSocket("ws://" + location.host + "/data");
|
||||||
|
socket.onopen = function () {
|
||||||
|
console.log("Connected to the server");
|
||||||
|
socket.send("0 0 0");
|
||||||
|
};
|
||||||
|
socket.addEventListener("message", function (msg) {
|
||||||
|
Plotly.extendTraces(
|
||||||
|
plotElement,
|
||||||
|
{
|
||||||
|
x: [[msg.timeStamp]],
|
||||||
|
y: [[msg.data]],
|
||||||
|
},
|
||||||
|
[0],
|
||||||
|
300,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
function changeSubcarrier() {
|
||||||
|
const subcarrier = document.getElementById("subcarrier").value;
|
||||||
|
socket.send(subcarrier + " 0 0");
|
||||||
|
}
|
||||||
15
where_fi/visualise/templates/preprocessed.html
Normal file
15
where_fi/visualise/templates/preprocessed.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||||
|
<script src="https://cdn.plot.ly/plotly-2.35.2.min.js" charset="utf-8"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<h1>Preprocessing</h1>
|
||||||
|
<div id="plot"></div>
|
||||||
|
<script src="{{url_for('static', filename='plot.js')}}"></script>
|
||||||
|
<input type="number" id="subcarrier" class="form-control" placeholder="Choose subcarrier" onchange="changeSubcarrier()" value="0">
|
||||||
|
</div>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
|
</body>
|
||||||
Loading…
Reference in New Issue
Block a user