From 5c1e3d3fac3094503ee2dc9bc2f1f737399ffade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Ben=C3=AD=C4=8Dek?= Date: Sat, 7 Dec 2024 07:01:52 +0100 Subject: [PATCH] Added support for 8RTD card --- .env.sample | 1 + .pdm-python | 2 +- pdm.lock | 41 ++++++++++++++++++++++++-- pyproject.toml | 1 + src/main.py | 4 ++- src/modules/RTD8/readme.md | 1 + src/modules/RTD8/router.py | 35 ++++++++++++++++++++++ src/modules/RTD8/service.py | 58 +++++++++++++++++++++++++++++++++++++ src/modules/router.py | 11 +++++++ 9 files changed, 150 insertions(+), 4 deletions(-) create mode 100644 .env.sample create mode 100644 src/modules/RTD8/readme.md create mode 100644 src/modules/RTD8/router.py create mode 100644 src/modules/RTD8/service.py create mode 100644 src/modules/router.py diff --git a/.env.sample b/.env.sample new file mode 100644 index 0000000..5fd9784 --- /dev/null +++ b/.env.sample @@ -0,0 +1 @@ +MODULE_RTD8_LEVELS=01234567 #number of stack level (0-7) not separated \ No newline at end of file diff --git a/.pdm-python b/.pdm-python index b8128fa..9965068 100644 --- a/.pdm-python +++ b/.pdm-python @@ -1 +1 @@ -C:/Users/jan00/Documents/Programovani/MyProjects/SequentMicrosystems_API/.venv/Scripts/python.exe \ No newline at end of file +/home/jbenicek/Programovani/SequentMicrosystems_API/.venv/bin/python \ No newline at end of file diff --git a/pdm.lock b/pdm.lock index e2c21d2..237ec1e 100644 --- a/pdm.lock +++ b/pdm.lock @@ -4,8 +4,11 @@ [metadata] groups = ["default"] strategy = ["cross_platform", "inherit_metadata"] -lock_version = "4.4.1" -content_hash = "sha256:f1937df1c5cdc07e0f42993da0c629a6322e5f5ec15a7ddf5012135f4ce53009" +lock_version = "4.5.0" +content_hash = "sha256:f4f1e2189c6ffd6d794a2407d788e6716784556dfe8717566ece8e4c48e157e7" + +[[metadata.targets]] +requires_python = ">=3.12" [[package]] name = "annotated-types" @@ -13,6 +16,9 @@ version = "0.7.0" requires_python = ">=3.8" summary = "Reusable constraint types to use with typing.Annotated" groups = ["default"] +dependencies = [ + "typing-extensions>=4.0.0; python_version < \"3.9\"", +] 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"}, @@ -25,8 +31,10 @@ requires_python = ">=3.9" summary = "High level compatibility layer for multiple asynchronous event loop implementations" groups = ["default"] dependencies = [ + "exceptiongroup>=1.0.2; python_version < \"3.11\"", "idna>=2.8", "sniffio>=1.1", + "typing-extensions>=4.1; python_version < \"3.11\"", ] files = [ {file = "anyio-4.6.2.post1-py3-none-any.whl", hash = "sha256:6d170c36fba3bdd840c73d3868c1e777e33676a69c3a72cf0a0d5d6d8009b61d"}, @@ -41,6 +49,7 @@ summary = "Composable command line interface toolkit" groups = ["default"] dependencies = [ "colorama; platform_system == \"Windows\"", + "importlib-metadata; python_version < \"3.8\"", ] files = [ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, @@ -90,6 +99,9 @@ version = "0.14.0" requires_python = ">=3.7" summary = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" groups = ["default"] +dependencies = [ + "typing-extensions; python_version < \"3.8\"", +] files = [ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, @@ -181,6 +193,29 @@ files = [ {file = "pydantic_core-2.27.0.tar.gz", hash = "sha256:f57783fbaf648205ac50ae7d646f27582fc706be3977e87c3c124e7a92407b10"}, ] +[[package]] +name = "smbus2" +version = "0.5.0" +summary = "smbus2 is a drop-in replacement for smbus-cffi/smbus-python in pure Python" +groups = ["default"] +files = [ + {file = "smbus2-0.5.0-py2.py3-none-any.whl", hash = "sha256:1a15c3b9fa69357beb038cc0b5d37939702f8bfde1ddc89ca9f17d8461dbe949"}, + {file = "smbus2-0.5.0.tar.gz", hash = "sha256:4a5946fd82277870c2878befdb1a29bb28d15cda14ea4d8d2d54cf3d4bdcb035"}, +] + +[[package]] +name = "smrtd" +version = "1.0.1" +summary = "Library to control Sequent Microsystems rtd Card" +groups = ["default"] +dependencies = [ + "smbus2", +] +files = [ + {file = "SMrtd-1.0.1-py2.py3-none-any.whl", hash = "sha256:0c6c1708f2240b8e283445f9cd5d00be7e7405fc79cf3d96b8c3488d7fc4b3a7"}, + {file = "smrtd-1.0.1.tar.gz", hash = "sha256:b9b1275f80a4f84091a10ae0cd41ad85ce39968f3f7ba989f2db07f732505fcc"}, +] + [[package]] name = "sniffio" version = "1.3.1" @@ -200,6 +235,7 @@ summary = "The little ASGI library that shines." groups = ["default"] dependencies = [ "anyio<5,>=3.4.0", + "typing-extensions>=3.10.0; python_version < \"3.10\"", ] files = [ {file = "starlette-0.41.3-py3-none-any.whl", hash = "sha256:44cedb2b7c77a9de33a8b74b2b90e9f50d11fcf25d8270ea525ad71a25374ff7"}, @@ -226,6 +262,7 @@ groups = ["default"] dependencies = [ "click>=7.0", "h11>=0.8", + "typing-extensions>=4.0; python_version < \"3.11\"", ] files = [ {file = "uvicorn-0.32.1-py3-none-any.whl", hash = "sha256:82ad92fd58da0d12af7482ecdb5f2470a04c9c9a53ced65b9bbb4a205377602e"}, diff --git a/pyproject.toml b/pyproject.toml index df52975..4381439 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ dependencies = [ "fastapi>=0.115.5", "uvicorn>=0.32.1", "dotenv>=0.0.5", + "SMrtd>=1.0.1", ] requires-python = ">=3.12" readme = "README.md" diff --git a/src/main.py b/src/main.py index 7f5899b..5e0298a 100644 --- a/src/main.py +++ b/src/main.py @@ -1,5 +1,7 @@ from fastapi import FastAPI +from src.modules.router import router as modulesrouter +app = FastAPI(root_path="/api") -app = FastAPI() \ No newline at end of file +app.include_router(router=modulesrouter) diff --git a/src/modules/RTD8/readme.md b/src/modules/RTD8/readme.md new file mode 100644 index 0000000..3b6ee7d --- /dev/null +++ b/src/modules/RTD8/readme.md @@ -0,0 +1 @@ +Card: RTD Data Acquisition 8-Layer Stackable HAT for Raspberry Pi - https://sequentmicrosystems.com/products/rtd-data-acquisition-card-for-rpi diff --git a/src/modules/RTD8/router.py b/src/modules/RTD8/router.py new file mode 100644 index 0000000..c946aff --- /dev/null +++ b/src/modules/RTD8/router.py @@ -0,0 +1,35 @@ +import src.modules.RTD8.service as service +from fastapi import APIRouter +from typing import Dict + + + +router = APIRouter(prefix="/RTD8", tags=["Modules --> RTD8 card"]) + + + +@router.get("/all", summary="Read all RTD8 cards values in Celsius", response_model=Dict[int, Dict[int, float]]) +def get_all_celsius(): + return service.read_temp_all() + +@router.get("/{stack}", summary="Read specified RTD8 card values in Celsius", response_model=Dict[int, float]) +def get_stack_celsius(stack: int): + return service.read_temp_stack(stack) + +@router.get("/{stack}/{channel}", summary="Read specified RTD8 card value of specified channel in Celsius", response_model=float) +def get_channel_celsius(stack: int, channel: int): + return service.read_temp(stack, channel) + + + +@router.get("/all/resistance", summary="Read all RTD8 cards values in Ohm", response_model=Dict[int, Dict[int, float]]) +def get_all_celsius(): + return service.read_resistance_all() + +@router.get("/{stack}/resistance", summary="Read specified RTD8 card values in Ohm", response_model=Dict[int, float]) +def get_stack_celsius(stack: int): + return service.read_resistance_stack(stack) + +@router.get("/{stack}/{channel}/resistance", summary="Read specified RTD8 card value of specified channel in Ohm", response_model=float) +def get_channel_celsius(stack: int, channel: int): + return service.read_resistance(stack, channel) \ No newline at end of file diff --git a/src/modules/RTD8/service.py b/src/modules/RTD8/service.py new file mode 100644 index 0000000..00b1d96 --- /dev/null +++ b/src/modules/RTD8/service.py @@ -0,0 +1,58 @@ +import librtd, os + + +stacks = [int(h) for h in os.getenv("MODULE_RTD8_LEVELS", "")] +if not stacks: + print("MODULE_RTD8_LEVELS is not set or invalid") + + + +def read_temp(stack: int, channel: int) -> float | str: + """ + Read specified channel in Celsius + """ + if stack in stacks and 1 <= channel <= 8: + try: + return librtd.get(stack, channel) + except Exception as e: + raise ValueError(f"Error read data from card {stack} on channel {channel} by error: {e}") + + return -512 + +def read_temp_stack(stack: int) -> dict: + """ + Read all inputs data in Celsius + """ + return {ch: read_temp(stack=stack, channel=ch) for ch in range(1, 9)} + +def read_temp_all() -> dict: + """ + Read all RTD8 cards inputs in Celsius + """ + return {stack: read_resistance_stack(stack=stack) for stack in stacks} + + + +def read_resistance(stack: int, channel: int) -> float | str: + """ + Read specified channel in Ohm + """ + if stack in stacks and 1 <= channel <= 8: + try: + return librtd.getRes(stack, channel) + except Exception as e: + raise ValueError(f"Error read data from card {stack} on channel {channel} by error: {e}") + + return -512 + +def read_resistance_stack(stack: int) -> dict: + """ + Read all inputs data in Ohm + """ + return {ch: read_resistance(stack=stack, channel=ch) for ch in range(1, 9)} + +def read_resistance_all() -> dict: + """ + Read all RTD8 cards inputs in Ohm + """ + return {stack: read_resistance_stack(stack=stack) for stack in stacks} \ No newline at end of file diff --git a/src/modules/router.py b/src/modules/router.py new file mode 100644 index 0000000..83a6ad6 --- /dev/null +++ b/src/modules/router.py @@ -0,0 +1,11 @@ +from fastapi import APIRouter + +from src.modules.RTD8.router import router as RTD8Router + + + + + +router = APIRouter(prefix="/modules") + +router.include_router(router=RTD8Router) \ No newline at end of file