File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 33from pqnstack .app .api .routes import chsh
44from pqnstack .app .api .routes import qkd
55from pqnstack .app .api .routes import rng
6+ from pqnstack .app .api .routes import serial
67from pqnstack .app .api .routes import timetagger
78
89api_router = APIRouter ()
910api_router .include_router (chsh .router )
1011api_router .include_router (qkd .router )
1112api_router .include_router (timetagger .router )
1213api_router .include_router (rng .router )
14+ api_router .include_router (serial .router )
Original file line number Diff line number Diff line change 1+ import logging
2+ from typing import Annotated
3+
4+ from fastapi import APIRouter
5+ from fastapi import Depends
6+ from pydantic import BaseModel
7+
8+ from pqnstack .app .core .config import settings
9+ from pqnstack .pqn .drivers .rotaryencoder import SerialRotaryEncoder
10+
11+ logger = logging .getLogger (__name__ )
12+ router = APIRouter (prefix = "/serial" , tags = ["measure" ])
13+
14+
15+ def get_rotary_encoder () -> SerialRotaryEncoder :
16+ return settings .rotary_encoder
17+
18+
19+ SERDep = Annotated [SerialRotaryEncoder , Depends (get_rotary_encoder )]
20+
21+
22+ class AngleResponse (BaseModel ):
23+ theta : float
24+
25+
26+ @router .get ("/" )
27+ async def read_angle (rotary_encoder : SERDep ) -> AngleResponse :
28+ return AngleResponse (theta = rotary_encoder .read ())
Original file line number Diff line number Diff line change 1010
1111from pqnstack .constants import BellState
1212from pqnstack .constants import QKDEncodingBasis
13+ from pqnstack .pqn .drivers .rotaryencoder import SerialRotaryEncoder
1314from pqnstack .pqn .protocols .measurement import MeasurementConfig
1415
1516logger = logging .getLogger (__name__ )
@@ -39,6 +40,10 @@ class Settings(BaseSettings):
3940 bell_state : BellState = BellState .Phi_plus
4041 timetagger : tuple [str , str ] | None = None # Name of the timetagger to use for the CHSH experiment.
4142
43+ rotary_encoder : SerialRotaryEncoder = SerialRotaryEncoder (
44+ label = "rotary_encoder" , address = "/dev/ttyACM0" , offset_degrees = 0.0
45+ )
46+
4247 model_config = SettingsConfigDict (toml_file = "./config.toml" , env_file = ".env" , env_file_encoding = "utf-8" )
4348
4449 @classmethod
Original file line number Diff line number Diff line change 1+ import atexit
2+ from dataclasses import dataclass
3+ from dataclasses import field
4+
5+ import serial
6+
7+
8+ @dataclass (slots = True )
9+ class SerialRotaryEncoder :
10+ label : str
11+ address : str
12+ offset_degrees : float = 0.0
13+ _conn : serial .Serial = field (init = False , repr = False )
14+
15+ def __post_init__ (self ) -> None :
16+ self ._conn = serial .Serial (self .address , baudrate = 115200 , timeout = 1 )
17+ self ._conn .write (b"open_channel" )
18+ self ._conn .read (100 )
19+ self ._conn .write (b"ready" )
20+ self ._conn .read (100 )
21+
22+ atexit .register (self .close )
23+
24+ def close (self ) -> None :
25+ self ._conn .close ()
26+
27+ def read (self ) -> float :
28+ self ._conn .write (b"ANGLE?\n " )
29+ angle = self ._conn .readline ().decode ().strip ()
30+ return float (angle ) + self .offset_degrees
You can’t perform that action at this time.
0 commit comments