diff --git a/.env.sample b/.env.sample index 5fd9784..bb5c8bc 100644 --- a/.env.sample +++ b/.env.sample @@ -1 +1,2 @@ -MODULE_RTD8_LEVELS=01234567 #number of stack level (0-7) not separated \ No newline at end of file +MODULE_RTD8_LEVELS=01234567 #number of stack level (0-7) not separated +MODULE_REL4HVI4_LEVELS=01234567 #number of stack level (0-7) not separated \ No newline at end of file diff --git a/README.md b/README.md index aa47fe6..6fa4d02 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,20 @@ # SequentMicrosystems_API -API for sequent microsystems boards running on RaspberryPI \ No newline at end of file +API for sequent microsystems boards running on RaspberryPI + + + + + + + + + + + + + + + + + diff --git a/pdm.lock b/pdm.lock index 237ec1e..01f9752 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default"] strategy = ["cross_platform", "inherit_metadata"] lock_version = "4.5.0" -content_hash = "sha256:f4f1e2189c6ffd6d794a2407d788e6716784556dfe8717566ece8e4c48e157e7" +content_hash = "sha256:a386b1448f475cfd997f505d3dc55da73a888f9be06306adbabb701440ec7aa3" [[metadata.targets]] requires_python = ">=3.12" @@ -68,15 +68,6 @@ files = [ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] -[[package]] -name = "dotenv" -version = "0.0.5" -summary = "Handle .env files" -groups = ["default"] -files = [ - {file = "dotenv-0.0.5.tar.gz", hash = "sha256:b58d2ab3f83dbd4f8a362b21158a606bee87317a9444485566b3c8f0af847091"}, -] - [[package]] name = "fastapi" version = "0.115.5" @@ -193,6 +184,30 @@ files = [ {file = "pydantic_core-2.27.0.tar.gz", hash = "sha256:f57783fbaf648205ac50ae7d646f27582fc706be3977e87c3c124e7a92407b10"}, ] +[[package]] +name = "python-dotenv" +version = "1.0.1" +requires_python = ">=3.8" +summary = "Read key-value pairs from a .env file and set them as environment variables" +groups = ["default"] +files = [ + {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, + {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, +] + +[[package]] +name = "sm4relind" +version = "1.0.3" +summary = "A set of functions to control Sequent Microsystems 4-Relay board" +groups = ["default"] +dependencies = [ + "smbus2", +] +files = [ + {file = "SM4relind-1.0.3-py2.py3-none-any.whl", hash = "sha256:1308f580d05893f481b79c055dfb5572bbce992777edeee6292c91c707a73a55"}, + {file = "sm4relind-1.0.3.tar.gz", hash = "sha256:aa1c464f6344be63f8a84fb7e51d9c683f73f696cb8fd43cb0f1171b851f7d6b"}, +] + [[package]] name = "smbus2" version = "0.5.0" diff --git a/pyproject.toml b/pyproject.toml index 4381439..de5bf9c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,8 +8,9 @@ authors = [ dependencies = [ "fastapi>=0.115.5", "uvicorn>=0.32.1", - "dotenv>=0.0.5", "SMrtd>=1.0.1", + "SM4relind>=1.0.3", + "python-dotenv>=1.0.1", ] requires-python = ">=3.12" readme = "README.md" diff --git a/src/main.py b/src/main.py index 5e0298a..f2a6911 100644 --- a/src/main.py +++ b/src/main.py @@ -1,7 +1,14 @@ +import os +from dotenv import load_dotenv + +load_dotenv() + from fastapi import FastAPI from src.modules.router import router as modulesrouter + app = FastAPI(root_path="/api") app.include_router(router=modulesrouter) + diff --git a/src/modules/RTD8/service.py b/src/modules/RTD8/service.py index 00b1d96..c947d5a 100644 --- a/src/modules/RTD8/service.py +++ b/src/modules/RTD8/service.py @@ -5,6 +5,9 @@ stacks = [int(h) for h in os.getenv("MODULE_RTD8_LEVELS", "")] if not stacks: print("MODULE_RTD8_LEVELS is not set or invalid") +for i in stacks: + print(f"Configured RTD8 card: {i}") + def read_temp(stack: int, channel: int) -> float | str: @@ -15,7 +18,7 @@ def read_temp(stack: int, channel: int) -> float | str: 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 return -512 @@ -41,7 +44,7 @@ def read_resistance(stack: int, channel: int) -> float | str: 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 return -512 diff --git a/src/modules/Rel4HVI4/readme.md b/src/modules/Rel4HVI4/readme.md new file mode 100644 index 0000000..91308ad --- /dev/null +++ b/src/modules/Rel4HVI4/readme.md @@ -0,0 +1 @@ +Card: Four Relays four HV Inputs 8-Layer Stackable HAT for Raspberry Pi - https://sequentmicrosystems.com/collections/industrial-automation/products/four-relays-four-inputs-for-raspberry-pi \ No newline at end of file diff --git a/src/modules/Rel4HVI4/router.py b/src/modules/Rel4HVI4/router.py new file mode 100644 index 0000000..2ed2822 --- /dev/null +++ b/src/modules/Rel4HVI4/router.py @@ -0,0 +1,48 @@ +from fastapi import APIRouter +import src.modules.Rel4HVI4.service as service +from typing import Dict + + + +router = APIRouter(prefix="/rel4hvi4", tags=["Modules --> Rel4HVI4"]) + + + +@router.post("/relay/all/{state}", description="Set all relays to required state (1/0)") +def post_relay_all(state: bool): + service.set_relay_all(value=state) + +@router.post("/relay/{stack}/{state}", description="Set all relays on specified card to required state (1/0)") +def post_relay_stack(stack: int, state: bool): + service.set_relay_stack(stack=stack, value=state) + +@router.post("/relay/{stack}/{channel}/{state}", description="Set all relays on specified card to required state (1/0)") +def post_relay_stack(stack: int, channel, state: bool): + service.set_relay(stack=stack, relay=channel, value=state) + + +@router.get("/relay/all", description="Get state of all relays", response_model=Dict[int, Dict[int, bool]]) +def get_relay_all(): + return service.read_relay_all() + +@router.get("/relay/{stack}", description="Get all relays state of specified card", response_model=Dict[int, bool]) +def get_relay_stack(stack: int): + return service.read_relay_stack(stack=stack) + +@router.get("/relay/{stack}/{channel}", description="Get state of selected relay", response_model=bool) +def get_relay(stack: int, channel: int): + return service.read_relay(stack=stack, relay=channel) + + + +@router.get("/opto/all", description="Get input state of all opto inputs", response_model=Dict[int, Dict[int, bool]]) +def get_opto_all(): + return service.read_opto_all() + +@router.get("/opto/{stack}", description="Get input state all opto inputs on selected card", response_model=Dict[int, bool]) +def get_opto_stack(stack: int): + return service.read_opto_stack(stack=stack) + +@router.get("/opto/{stack}/{channel}", description="Get state of selected input", response_model=bool) +def get_opto(stack: int, channel: int): + return service.read_opto(stack=stack, opto=channel) \ No newline at end of file diff --git a/src/modules/Rel4HVI4/service.py b/src/modules/Rel4HVI4/service.py new file mode 100644 index 0000000..4f61e62 --- /dev/null +++ b/src/modules/Rel4HVI4/service.py @@ -0,0 +1,86 @@ +import lib4relind, os +from typing import Dict + + +stacks = [int(h) for h in os.getenv("MODULE_REL4HVI4_LEVELS", "")] +if not stacks: + print("MODULE_Rel4HVI4_LEVELS is not set or invalid") + +for i in stacks: + print(f"Configured Rel4HVI4 card: {i}") + + +def set_relay(stack: int, relay: int, value: bool): + """ + Set specified relay to requested state + """ + if stack in stacks and 1 <= relay <= 4: + lib4relind.set_relay(stack=stack, relay=relay, value=int(value)) + +def set_relay_stack(stack: int, value: bool): + """ + Set all relays to requested state on specified stack/card + """ + (set_relay(stack=stack, relay=ch, value=value) for ch in range(1, 5)) + +def set_relay_all(value: bool): + """ + Set all relays to requested state + """ + (set_relay_stack(stack=stack, value=value) for stack in stacks) + + +def read_relay(stack: int, relay: int): + """ + Read specified relay state + """ + if stack in stacks and 1 <= relay <= 4: + try: + if lib4relind.get_relay(stack=stack, relay=relay) == 1: + return True + else: + return False + except: + return False + return False + +def read_relay_stack(stack: int): + """ + Read all relays state on specified stack/card + """ + return {relay: read_relay(stack=stack, relay=relay) for relay in range(1, 5)} + +def read_relay_all(): + """ + Read all relays state + """ + return {stack: read_relay_stack(stack=stack) for stack in stacks} + + + +def read_opto(stack: int, opto: int): + """ + Read specified opto input state + """ + if stack in stacks and 1 <= opto <= 4: + try: + if lib4relind.get_opto(stack=stack, channel=opto) == 1: + return True + else: + return False + except: + return False + return False + +def read_opto_stack(stack: int): + """ + Read all opto inputs state on specified stack/card + """ + return {opto: read_opto(stack=stack, opto=opto) for opto in range(1, 5)} + +def read_opto_all(): + """ + Read all opto inputs state + """ + return {stack: read_opto_stack(stack=stack) for stack in stacks} + diff --git a/src/modules/router.py b/src/modules/router.py index 83a6ad6..e14577a 100644 --- a/src/modules/router.py +++ b/src/modules/router.py @@ -1,6 +1,7 @@ from fastapi import APIRouter from src.modules.RTD8.router import router as RTD8Router +from src.modules.Rel4HVI4.router import router as Rel4HVI4Router @@ -8,4 +9,5 @@ from src.modules.RTD8.router import router as RTD8Router router = APIRouter(prefix="/modules") -router.include_router(router=RTD8Router) \ No newline at end of file +router.include_router(router=RTD8Router) +router.include_router(router=Rel4HVI4Router) \ No newline at end of file