Compare commits
No commits in common. "96bbb3602a3545c4b5f77842e236fb1cea071e57" and "58c98b01192841eba79cae5669a56b0a0bc3594a" have entirely different histories.
96bbb3602a
...
58c98b0119
5 changed files with 5 additions and 452 deletions
181
poetry.lock
generated
181
poetry.lock
generated
|
|
@ -24,17 +24,6 @@ dev = ["duckdb (>=1.0)", "geopandas", "hatch (>=1.13.0)", "ipython[kernel]", "mi
|
||||||
doc = ["docutils", "jinja2", "myst-parser", "numpydoc", "pillow (>=9,<10)", "pydata-sphinx-theme (>=0.14.1)", "scipy", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinxext-altair"]
|
doc = ["docutils", "jinja2", "myst-parser", "numpydoc", "pillow (>=9,<10)", "pydata-sphinx-theme (>=0.14.1)", "scipy", "sphinx", "sphinx-copybutton", "sphinx-design", "sphinxext-altair"]
|
||||||
save = ["vl-convert-python (>=1.7.0)"]
|
save = ["vl-convert-python (>=1.7.0)"]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "annotated-types"
|
|
||||||
version = "0.7.0"
|
|
||||||
description = "Reusable constraint types to use with typing.Annotated"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.8"
|
|
||||||
files = [
|
|
||||||
{file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"},
|
|
||||||
{file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyio"
|
name = "anyio"
|
||||||
version = "4.11.0"
|
version = "4.11.0"
|
||||||
|
|
@ -2580,160 +2569,6 @@ files = [
|
||||||
{file = "pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2"},
|
{file = "pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pydantic"
|
|
||||||
version = "2.12.4"
|
|
||||||
description = "Data validation using Python type hints"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.9"
|
|
||||||
files = [
|
|
||||||
{file = "pydantic-2.12.4-py3-none-any.whl", hash = "sha256:92d3d202a745d46f9be6df459ac5a064fdaa3c1c4cd8adcfa332ccf3c05f871e"},
|
|
||||||
{file = "pydantic-2.12.4.tar.gz", hash = "sha256:0f8cb9555000a4b5b617f66bfd2566264c4984b27589d3b845685983e8ea85ac"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
annotated-types = ">=0.6.0"
|
|
||||||
pydantic-core = "2.41.5"
|
|
||||||
typing-extensions = ">=4.14.1"
|
|
||||||
typing-inspection = ">=0.4.2"
|
|
||||||
|
|
||||||
[package.extras]
|
|
||||||
email = ["email-validator (>=2.0.0)"]
|
|
||||||
timezone = ["tzdata"]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pydantic-core"
|
|
||||||
version = "2.41.5"
|
|
||||||
description = "Core functionality for Pydantic validation and serialization"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.9"
|
|
||||||
files = [
|
|
||||||
{file = "pydantic_core-2.41.5-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:77b63866ca88d804225eaa4af3e664c5faf3568cea95360d21f4725ab6e07146"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:dfa8a0c812ac681395907e71e1274819dec685fec28273a28905df579ef137e2"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5921a4d3ca3aee735d9fd163808f5e8dd6c6972101e4adbda9a4667908849b97"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25c479382d26a2a41b7ebea1043564a937db462816ea07afa8a44c0866d52f9"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f547144f2966e1e16ae626d8ce72b4cfa0caedc7fa28052001c94fb2fcaa1c52"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f52298fbd394f9ed112d56f3d11aabd0d5bd27beb3084cc3d8ad069483b8941"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:100baa204bb412b74fe285fb0f3a385256dad1d1879f0a5cb1499ed2e83d132a"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:05a2c8852530ad2812cb7914dc61a1125dc4e06252ee98e5638a12da6cc6fb6c"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:29452c56df2ed968d18d7e21f4ab0ac55e71dc59524872f6fc57dcf4a3249ed2"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:d5160812ea7a8a2ffbe233d8da666880cad0cbaf5d4de74ae15c313213d62556"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:df3959765b553b9440adfd3c795617c352154e497a4eaf3752555cfb5da8fc49"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp310-cp310-win32.whl", hash = "sha256:1f8d33a7f4d5a7889e60dc39856d76d09333d8a6ed0f5f1190635cbec70ec4ba"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp310-cp310-win_amd64.whl", hash = "sha256:62de39db01b8d593e45871af2af9e497295db8d73b085f6bfd0b18c83c70a8f9"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:a3a52f6156e73e7ccb0f8cced536adccb7042be67cb45f9562e12b319c119da6"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7f3bf998340c6d4b0c9a2f02d6a400e51f123b59565d74dc60d252ce888c260b"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:378bec5c66998815d224c9ca994f1e14c0c21cb95d2f52b6021cc0b2a58f2a5a"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7b576130c69225432866fe2f4a469a85a54ade141d96fd396dffcf607b558f8"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6cb58b9c66f7e4179a2d5e0f849c48eff5c1fca560994d6eb6543abf955a149e"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88942d3a3dff3afc8288c21e565e476fc278902ae4d6d134f1eeda118cc830b1"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f31d95a179f8d64d90f6831d71fa93290893a33148d890ba15de25642c5d075b"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c1df3d34aced70add6f867a8cf413e299177e0c22660cc767218373d0779487b"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:4009935984bd36bd2c774e13f9a09563ce8de4abaa7226f5108262fa3e637284"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:34a64bc3441dc1213096a20fe27e8e128bd3ff89921706e83c0b1ac971276594"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:c9e19dd6e28fdcaa5a1de679aec4141f691023916427ef9bae8584f9c2fb3b0e"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-win32.whl", hash = "sha256:2c010c6ded393148374c0f6f0bf89d206bf3217f201faa0635dcd56bd1520f6b"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-win_amd64.whl", hash = "sha256:76ee27c6e9c7f16f47db7a94157112a2f3a00e958bc626e2f4ee8bec5c328fbe"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp311-cp311-win_arm64.whl", hash = "sha256:4bc36bbc0b7584de96561184ad7f012478987882ebf9f9c389b23f432ea3d90f"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:8bfeaf8735be79f225f3fefab7f941c712aaca36f1128c9d7e2352ee1aa87bdf"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:346285d28e4c8017da95144c7f3acd42740d637ff41946af5ce6e5e420502dd5"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a75dafbf87d6276ddc5b2bf6fae5254e3d0876b626eb24969a574fff9149ee5d"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7b93a4d08587e2b7e7882de461e82b6ed76d9026ce91ca7915e740ecc7855f60"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e8465ab91a4bd96d36dde3263f06caa6a8a6019e4113f24dc753d79a8b3a3f82"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:299e0a22e7ae2b85c1a57f104538b2656e8ab1873511fd718a1c1c6f149b77b5"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:707625ef0983fcfb461acfaf14de2067c5942c6bb0f3b4c99158bed6fedd3cf3"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f41eb9797986d6ebac5e8edff36d5cef9de40def462311b3eb3eeded1431e425"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0384e2e1021894b1ff5a786dbf94771e2986ebe2869533874d7e43bc79c6f504"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:f0cd744688278965817fd0839c4a4116add48d23890d468bc436f78beb28abf5"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:753e230374206729bf0a807954bcc6c150d3743928a73faffee51ac6557a03c3"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp39-cp39-win32.whl", hash = "sha256:873e0d5b4fb9b89ef7c2d2a963ea7d02879d9da0da8d9d4933dee8ee86a8b460"},
|
|
||||||
{file = "pydantic_core-2.41.5-cp39-cp39-win_amd64.whl", hash = "sha256:e4f4a984405e91527a0d62649ee21138f8e3d0ef103be488c1dc11a80d7f184b"},
|
|
||||||
{file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:b96d5f26b05d03cc60f11a7761a5ded1741da411e7fe0909e27a5e6a0cb7b034"},
|
|
||||||
{file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:634e8609e89ceecea15e2d61bc9ac3718caaaa71963717bf3c8f38bfde64242c"},
|
|
||||||
{file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:93e8740d7503eb008aa2df04d3b9735f845d43ae845e6dcd2be0b55a2da43cd2"},
|
|
||||||
{file = "pydantic_core-2.41.5-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f15489ba13d61f670dcc96772e733aad1a6f9c429cc27574c6cdaed82d0146ad"},
|
|
||||||
{file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd"},
|
|
||||||
{file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc"},
|
|
||||||
{file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56"},
|
|
||||||
{file = "pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b5819cd790dbf0c5eb9f82c73c16b39a65dd6dd4d1439dcdea7816ec9adddab8"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5a4e67afbc95fa5c34cf27d9089bca7fcab4e51e57278d710320a70b956d1b9a"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ece5c59f0ce7d001e017643d8d24da587ea1f74f6993467d85ae8a5ef9d4f42b"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:16f80f7abe3351f8ea6858914ddc8c77e02578544a0ebc15b4c2e1a0e813b0b2"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:33cb885e759a705b426baada1fe68cbb0a2e68e34c5d0d0289a364cf01709093"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:c8d8b4eb992936023be7dee581270af5c6e0697a8559895f527f5b7105ecd36a"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:242a206cd0318f95cd21bdacff3fcc3aab23e79bba5cac3db5a841c9ef9c6963"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d3a978c4f57a597908b7e697229d996d77a6d3c94901e9edee593adada95ce1a"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b2379fa7ed44ddecb5bfe4e48577d752db9fc10be00a6b7446e9663ba143de26"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:266fb4cbf5e3cbd0b53669a6d1b039c45e3ce651fd5442eff4d07c2cc8d66808"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58133647260ea01e4d0500089a8c4f07bd7aa6ce109682b1426394988d8aaacc"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:287dad91cfb551c363dc62899a80e9e14da1f0e2b6ebde82c806612ca2a13ef1"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:03b77d184b9eb40240ae9fd676ca364ce1085f203e1b1256f8ab9984dca80a84"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:a668ce24de96165bb239160b3d854943128f4334822900534f2fe947930e5770"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f14f8f046c14563f8eb3f45f499cc658ab8d10072961e07225e507adb700e93f"},
|
|
||||||
{file = "pydantic_core-2.41.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:56121965f7a4dc965bff783d70b907ddf3d57f6eba29b6d2e5dabfaf07799c51"},
|
|
||||||
{file = "pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
typing-extensions = ">=4.14.1"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pygments"
|
name = "pygments"
|
||||||
version = "2.19.2"
|
version = "2.19.2"
|
||||||
|
|
@ -3587,20 +3422,6 @@ files = [
|
||||||
{file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"},
|
{file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "typing-inspection"
|
|
||||||
version = "0.4.2"
|
|
||||||
description = "Runtime typing introspection tools"
|
|
||||||
optional = false
|
|
||||||
python-versions = ">=3.9"
|
|
||||||
files = [
|
|
||||||
{file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"},
|
|
||||||
{file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"},
|
|
||||||
]
|
|
||||||
|
|
||||||
[package.dependencies]
|
|
||||||
typing-extensions = ">=4.12.0"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tzdata"
|
name = "tzdata"
|
||||||
version = "2025.2"
|
version = "2025.2"
|
||||||
|
|
@ -3919,4 +3740,4 @@ files = [
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.12"
|
python-versions = "^3.12"
|
||||||
content-hash = "8f3d473f12e66f997137dab2288517897944a71f63adfb47c4c9104af1a2e7ff"
|
content-hash = "8d54f76b3dea166d41dc33c774985c4e0039808fb038f23cec959089d724ea29"
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,6 @@ watchfiles = "^1.1.1"
|
||||||
jupyterlab = "^4.4.10"
|
jupyterlab = "^4.4.10"
|
||||||
pandas-stubs = "^2.3.2.250926"
|
pandas-stubs = "^2.3.2.250926"
|
||||||
websockets = "^15.0.1"
|
websockets = "^15.0.1"
|
||||||
pydantic = "^2.12.4"
|
|
||||||
httpx = "^0.28.1"
|
|
||||||
[tool.poetry.group.dev.dependencies]
|
[tool.poetry.group.dev.dependencies]
|
||||||
pytest = "^8.3.3"
|
pytest = "^8.3.3"
|
||||||
pytest-cov = "^5.0.0"
|
pytest-cov = "^5.0.0"
|
||||||
|
|
|
||||||
54
sample.py
54
sample.py
|
|
@ -1,7 +1,5 @@
|
||||||
import json
|
import json
|
||||||
import panel
|
import panel
|
||||||
from random import randint
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
from watt42_viewlib import attach_w42_state
|
from watt42_viewlib import attach_w42_state
|
||||||
|
|
||||||
|
|
@ -12,58 +10,8 @@ state_as_text = panel.bind(lambda s: f"W42 State:\n\n```\n{json.dumps(s, indent=
|
||||||
|
|
||||||
state_pane = panel.pane.Markdown(state_as_text, sizing_mode='stretch_width')
|
state_pane = panel.pane.Markdown(state_as_text, sizing_mode='stretch_width')
|
||||||
|
|
||||||
value = w42_state.rx.value
|
|
||||||
|
|
||||||
multiplier = panel.widgets.IntSlider(name='Multiplier', start=1, end=10, step=1, value=1)
|
|
||||||
|
|
||||||
def value_display(state: dict[str, Any], multiplier: int) -> str:
|
|
||||||
if state and 'value' in state:
|
|
||||||
return f"Current W42 State Value times multiplier: {state['value'] * multiplier}"
|
|
||||||
return "Current W42 State Value: N/A"
|
|
||||||
|
|
||||||
def value_or_zero(state: dict[str, Any]) -> int:
|
|
||||||
if state and 'value' in state:
|
|
||||||
return state['value']
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def array_from_value(x: int) -> list[int]:
|
|
||||||
return [x * randint(1, 20) for _ in range(25)]
|
|
||||||
|
|
||||||
def times2(x: int) -> int:
|
|
||||||
return x * 2
|
|
||||||
|
|
||||||
times2_rx = panel.rx(times2)(panel.rx(value_or_zero)(w42_state))
|
|
||||||
|
|
||||||
markdown_rx = panel.rx(lambda v: f"## Value times 2 is: {v}, array={array_from_value(v)}")(times2_rx)
|
|
||||||
|
|
||||||
array_rx = panel.rx(array_from_value)(panel.rx(value_or_zero)(w42_state))
|
|
||||||
|
|
||||||
echart_bar_rx = panel.pane.ECharts(
|
|
||||||
panel.rx(lambda arr: {
|
|
||||||
'xAxis': {
|
|
||||||
'type': 'category',
|
|
||||||
'data': [f'Item {i+1}' for i in range(len(arr))]
|
|
||||||
},
|
|
||||||
'yAxis': {
|
|
||||||
'type': 'value'
|
|
||||||
},
|
|
||||||
'series': [{
|
|
||||||
'data': arr,
|
|
||||||
'type': 'bar'
|
|
||||||
}]
|
|
||||||
})(array_rx),
|
|
||||||
sizing_mode='stretch_width',
|
|
||||||
height=400
|
|
||||||
)
|
|
||||||
|
|
||||||
_ = panel.template.FastListTemplate(
|
_ = panel.template.FastListTemplate(
|
||||||
title="Sample W42 View App",
|
title="Sample W42 View App",
|
||||||
sidebar=[panel.pane.Markdown("This is a sample sidebar.")],
|
sidebar=[panel.pane.Markdown("This is a sample sidebar.")],
|
||||||
main=[
|
main=[panel.pane.Markdown("# Welcome to the Main Content Area"), state_pane],
|
||||||
panel.pane.Markdown("# Welcome to the Main Content Area"),
|
|
||||||
echart_bar_rx,
|
|
||||||
# state_pane, panel.pane.Markdown(f"Current W42 State Value: {value}"),
|
|
||||||
panel.ReactiveExpr(panel.rx(value_display)(w42_state, multiplier), widget_location='top'),
|
|
||||||
panel.pane.Markdown(markdown_rx),
|
|
||||||
],
|
|
||||||
).servable()
|
).servable()
|
||||||
|
|
|
||||||
209
sample2.py
209
sample2.py
|
|
@ -1,209 +0,0 @@
|
||||||
import json
|
|
||||||
import panel
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
|
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
from watt42_viewlib import attach_w42_state
|
|
||||||
|
|
||||||
panel.extension('echarts', 'ace', 'jsoneditor')
|
|
||||||
|
|
||||||
SYSTEM_ID = "79476e53-dea6-44fa-976c-eff6260baeb6"
|
|
||||||
API_TOKEN = "d0vA6CsrY69N3JAOGtuZMEb9QpbJWPcoxhxRyBXZn8SIisB3weLKjMZwQRo8c2k9BRDtK0qHYnsvUMnqeO7Xog"
|
|
||||||
|
|
||||||
w42_state = panel.rx(None)
|
|
||||||
|
|
||||||
# TODO: must pass token, otherwise subscription should fail
|
|
||||||
attach_w42_state(rx_var=w42_state, system_id=SYSTEM_ID, token=API_TOKEN)
|
|
||||||
|
|
||||||
state_as_text = panel.bind(lambda s: f"W42 State:\n\n```\n{json.dumps(s, indent=2)}\n```\n\nReplace this with some awesome visuals", w42_state)
|
|
||||||
|
|
||||||
class Output(BaseModel):
|
|
||||||
target_storage: float
|
|
||||||
target_geyser_temperature: float
|
|
||||||
storage: list[float]
|
|
||||||
grid_sell: list[float]
|
|
||||||
grid_buy: list[float]
|
|
||||||
|
|
||||||
|
|
||||||
class PvForecast(BaseModel):
|
|
||||||
at: datetime = datetime.now()
|
|
||||||
slots: list[float] = []
|
|
||||||
|
|
||||||
class LoadForecast(BaseModel):
|
|
||||||
at: datetime = datetime.now()
|
|
||||||
slots: list[float] = []
|
|
||||||
|
|
||||||
class Configuration(BaseModel):
|
|
||||||
inverter_sid: str = ""
|
|
||||||
location_lat: float = 0.0
|
|
||||||
location_lon: float = 0.0
|
|
||||||
|
|
||||||
class Stats(BaseModel):
|
|
||||||
grid_cost_total: float = 0.0
|
|
||||||
|
|
||||||
class SystemState(BaseModel):
|
|
||||||
load_forecast: LoadForecast = LoadForecast()
|
|
||||||
pv_forecast: PvForecast = PvForecast()
|
|
||||||
now: datetime = datetime.now()
|
|
||||||
sell_prices: list[float] = []
|
|
||||||
buy_prices: list[float] = []
|
|
||||||
output: Output | None = None
|
|
||||||
config: Configuration = Configuration()
|
|
||||||
stats: Stats = Stats()
|
|
||||||
|
|
||||||
state: SystemState = panel.rx(lambda s: SystemState.model_validate(s) if s else SystemState())(w42_state)
|
|
||||||
|
|
||||||
state_pane = panel.pane.Markdown(state_as_text, sizing_mode='stretch_width')
|
|
||||||
|
|
||||||
def now_from_state(state: SystemState) -> datetime:
|
|
||||||
return state.load_forecast.at
|
|
||||||
|
|
||||||
# now_from_state_rx = panel.rx(now_from_state)(state)
|
|
||||||
|
|
||||||
def get_label(at: datetime, slot_index: int) -> str:
|
|
||||||
slot_time = at + timedelta(minutes=15 * slot_index)
|
|
||||||
return slot_time.strftime('%H:%M')
|
|
||||||
|
|
||||||
def load_fc_chart(state: SystemState) -> dict:
|
|
||||||
slots = state.load_forecast.slots
|
|
||||||
at = state.load_forecast.at
|
|
||||||
storage = state.output.storage if state.output else [0] * len(slots)
|
|
||||||
battery = [storage[ix] - storage[ix-1] if ix > 0 else 0 for ix in range(len(slots))] if state.output else [0] * len(slots)
|
|
||||||
grid = [state.output.grid_buy[ix] - state.output.grid_sell[ix] if state.output else 0 for ix in range(len(slots))]
|
|
||||||
return {
|
|
||||||
'title': {
|
|
||||||
'text': '24hr Forecast'
|
|
||||||
},
|
|
||||||
'legend': {
|
|
||||||
'data': ['Load Forecast', 'Battery Storage', 'Battery in/out', 'PV Forecast', 'Grid in/out']
|
|
||||||
},
|
|
||||||
'tooltip': {
|
|
||||||
'trigger': 'axis'
|
|
||||||
},
|
|
||||||
'xAxis': {
|
|
||||||
'type': 'category',
|
|
||||||
'data': [get_label(at, i) for i in range(len(slots))]
|
|
||||||
},
|
|
||||||
'yAxis': {
|
|
||||||
'type': 'value'
|
|
||||||
},
|
|
||||||
'series': [
|
|
||||||
{
|
|
||||||
'name': 'Load Forecast',
|
|
||||||
'data': slots,
|
|
||||||
'type': 'line'
|
|
||||||
}, {
|
|
||||||
'name': 'Battery Storage',
|
|
||||||
'data': storage,
|
|
||||||
'type': 'line',
|
|
||||||
'color': 'orange'
|
|
||||||
}, {
|
|
||||||
'name': 'Battery in/out',
|
|
||||||
'data': battery,
|
|
||||||
'type': 'line',
|
|
||||||
'color': 'lightblue'
|
|
||||||
}, {
|
|
||||||
'name': 'PV Forecast',
|
|
||||||
'data': state.pv_forecast.slots,
|
|
||||||
'type': 'line',
|
|
||||||
'color': 'green'
|
|
||||||
}, {
|
|
||||||
'name': 'Grid in/out',
|
|
||||||
'data': grid,
|
|
||||||
'type': 'line',
|
|
||||||
'color': 'red'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
load_fc_chart_rx = panel.rx(load_fc_chart)(state)
|
|
||||||
|
|
||||||
def prices_chart(state: SystemState) -> dict:
|
|
||||||
return {
|
|
||||||
'title': {
|
|
||||||
'text': 'Electricity Prices'
|
|
||||||
},
|
|
||||||
'legend': {
|
|
||||||
'data': ['Sell Prices', 'Buy Prices']
|
|
||||||
},
|
|
||||||
'tooltip': {
|
|
||||||
'trigger': 'axis'
|
|
||||||
},
|
|
||||||
'xAxis': {
|
|
||||||
'type': 'category',
|
|
||||||
'data': [get_label(state.now, i) for i in range(len(state.sell_prices))]
|
|
||||||
},
|
|
||||||
'yAxis': {
|
|
||||||
'type': 'value'
|
|
||||||
},
|
|
||||||
'series': [
|
|
||||||
{
|
|
||||||
'name': 'Sell Prices',
|
|
||||||
'data': state.sell_prices,
|
|
||||||
'type': 'line',
|
|
||||||
'color': 'green'
|
|
||||||
}, {
|
|
||||||
'name': 'Buy Prices',
|
|
||||||
'data': state.buy_prices,
|
|
||||||
'type': 'line',
|
|
||||||
'color': 'red'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
prices_chart_rx = panel.rx(prices_chart)(state)
|
|
||||||
|
|
||||||
datetime_fmt = "%Y-%m-%d %H:%M:%S"
|
|
||||||
|
|
||||||
config_editor = panel.widgets.JSONEditor(value=state.config.model_dump(), mode='form', height=200, width=400, menu=False)
|
|
||||||
|
|
||||||
SCRIPT_ID = "23a6d15a-f7e3-4ff1-b3c1-94d297c972c9"
|
|
||||||
|
|
||||||
async def process_config_change(_btn):
|
|
||||||
from httpx import AsyncClient
|
|
||||||
async with AsyncClient() as client:
|
|
||||||
response = await client.post(
|
|
||||||
f"http://localhost:8000/api/scripts/{SCRIPT_ID}/execute?system_guid={SYSTEM_ID}",
|
|
||||||
json={
|
|
||||||
'signal': 'update_config',
|
|
||||||
'request_body': config_editor.value,
|
|
||||||
},
|
|
||||||
headers={
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"x-api-token": API_TOKEN
|
|
||||||
}
|
|
||||||
)
|
|
||||||
print(f"Config update response: {response.status_code} - {response.text}")
|
|
||||||
|
|
||||||
|
|
||||||
# _ = panel.rx(process_config_change)(config_editor.value)
|
|
||||||
|
|
||||||
config_submit = panel.widgets.Button(name="Update Configuration", button_type="primary", width=200)
|
|
||||||
config_submit.on_click(process_config_change)
|
|
||||||
|
|
||||||
def summary(state: SystemState) -> str:
|
|
||||||
total_cost = state.stats.grid_cost_total
|
|
||||||
return f"## Summary\n\nGrid {'cost' if total_cost > 0 else 'income'} total: {abs(state.stats.grid_cost_total):.2f} ZAR"
|
|
||||||
|
|
||||||
_ = panel.template.FastListTemplate(
|
|
||||||
title="Sample W42 App",
|
|
||||||
sidebar=[panel.pane.Markdown("This is a sample sidebar.")],
|
|
||||||
main=[
|
|
||||||
# panel.pane.Markdown(state_as_text, sizing_mode='stretch_width'),
|
|
||||||
panel.pane.Markdown(panel.rx(summary)(state), sizing_mode='stretch_width'),
|
|
||||||
panel.pane.ECharts(
|
|
||||||
load_fc_chart_rx,
|
|
||||||
sizing_mode='stretch_width',
|
|
||||||
height=400
|
|
||||||
),
|
|
||||||
panel.pane.ECharts(
|
|
||||||
prices_chart_rx,
|
|
||||||
sizing_mode='stretch_width',
|
|
||||||
height=300
|
|
||||||
),
|
|
||||||
w42_state,
|
|
||||||
panel.Column(config_editor, config_submit, sizing_mode='stretch_width'),
|
|
||||||
panel.pane.Markdown(panel.bind(lambda s: f"State at {s.now.strftime(datetime_fmt)}, Load Forecast Time: {s.load_forecast.at}", state), sizing_mode='stretch_width'),
|
|
||||||
],
|
|
||||||
).servable()
|
|
||||||
|
|
@ -8,7 +8,7 @@ from websockets.asyncio.client import connect
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
def attach_w42_state(rx_var: panel.rx, system_id: str, token: str):
|
def attach_w42_state(rx_var: panel.rx, system_id: str):
|
||||||
|
|
||||||
WS_URL = "ws://localhost:8000/ws/systems" # TODO: make configurable
|
WS_URL = "ws://localhost:8000/ws/systems" # TODO: make configurable
|
||||||
|
|
||||||
|
|
@ -23,17 +23,12 @@ def attach_w42_state(rx_var: panel.rx, system_id: str, token: str):
|
||||||
logger.info(f"Connected to {WS_URL}")
|
logger.info(f"Connected to {WS_URL}")
|
||||||
send_response = await websocket.send(json.dumps({
|
send_response = await websocket.send(json.dumps({
|
||||||
"action": "subscribe",
|
"action": "subscribe",
|
||||||
"system_id": system_id,
|
"system_id": system_id
|
||||||
"token": token
|
|
||||||
}))
|
}))
|
||||||
logger.info(f"Subscribed to system {system_id}, waiting for messages..., send_response={send_response}")
|
logger.info(f"Subscribed to system {system_id}, waiting for messages..., send_response={send_response}")
|
||||||
async for message in websocket:
|
async for message in websocket:
|
||||||
as_json = json.loads(message)
|
as_json = json.loads(message)
|
||||||
if as_json.get('error'):
|
rx_var.rx.value = as_json['change']['state']
|
||||||
logger.error(f"Error from websocket: {as_json['error']}")
|
|
||||||
rx_var.rx.value = as_json
|
|
||||||
else:
|
|
||||||
rx_var.rx.value = as_json['change']['state']
|
|
||||||
except ConnectionClosed:
|
except ConnectionClosed:
|
||||||
if must_reconnect:
|
if must_reconnect:
|
||||||
logger.info("connection closed, retrying...")
|
logger.info("connection closed, retrying...")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue