Commit 0d49e054 authored by Yann Garcia's avatar Yann Garcia
Browse files

Update docs in upper_tester

parent 609d3929
Loading
Loading
Loading
Loading
+6 −0
Changes for upper_tester/.gitignore: 6 added lines, 0 removed lines.
Original line number Diff line number Diff line
# Generated by `doxygen Doxyfile` (see README.md); regenerate, don't commit.
docs/
doxygen-warnings.log

__pycache__/
*.pyc

upper_tester/Doxyfile

0 → 100644
+2614 −0

File added.

Preview size limit exceeded, changes collapsed.

+23 −5
Changes for upper_tester/README.md: 23 added lines, 5 removed lines.
Original line number Diff line number Diff line
@@ -6,11 +6,16 @@ Quectel modem and returns the result. Python 3.13, standard library only.
## Wire protocol (NDJSON over TCP, TITAN is the client)

Request (one line):
`{"id":17,"type":"AT","cmd":"AT+CDU=1,\"tel:123\"<CR>","cnf":"CNF_REQUIRED"}`
`{"id":18,"type":"MMI","cmd":"POWER_ON","params":[{"name":"MCC","value":"001"}],"cnf":"NO_CNF_REQUIRED"}`
```json
{"id":17,"type":"AT","cmd":"AT+CDU=1,\"tel:123\"<CR>","cnf":"CNF_REQUIRED"}
{"id":18,"type":"MMI","cmd":"POWER_ON","params":[{"name":"MCC","value":"001"}],"cnf":"NO_CNF_REQUIRED"}
```
Optional `"timeout"` (seconds) overrides the per-command default.

Reply (one line): `{"id":17,"result":true,"result_string":"+CDU: 1\r\nOK"}`
Reply (one line):
```json
{"id":17,"result":true,"result_string":"+CDU: 1\r\nOK"}
```

- `NO_CNF_REQUIRED`: executed, no reply. `LOCAL_CNF_REQUIRED`: `{"id":..,"result":true}` right after the
  command is written. `CNF_REQUIRED`: reply after the final result code (or `TIMEOUT`, result false).
@@ -18,14 +23,27 @@ Reply (one line): `{"id":17,"result":true,"result_string":"+CDU: 1\r\nOK"}`
- Unsolicited result codes are only logged.

## Run / test
From nas project, execute the following command to validate the installation:
```python
From the nas project root, run the tests to validate the installation:
```sh
$ python3.13 -m unittest upper_tester.tests.test_ut
```
Then run the service itself:
```sh
$ python3.13 -m upper_tester --device /dev/quectel_at --port 12100
```
To try it without a real modem, see dummy_modem.py (`python3.13 -m upper_tester.dummy_modem`).

## Install on the Pi
Copy the `upper_tester/` package to `/opt/upper-tester/`, `deploy/upper-tester.toml` to `/etc/`,
`deploy/upper-tester.service` to `/etc/systemd/system/`, `deploy/99-quectel.rules` to
`/etc/udev/rules.d/`; create user `uttest` (group `dialout`); then
`udevadm control --reload && systemctl enable --now upper-tester`.

## API documentation
Every module, class and function has a Doxygen (`@brief`/`@param`/`@return`/...) docstring.
Generate the browsable HTML docs with:
```sh
$ doxygen Doxyfile
```
then open `docs/html/index.html` (this README is its main page). `docs/` is generated and
git-ignored; regenerate it after editing any docstring. Requires `doxygen` (tested with 1.9.1).
+6 −1
Changes for upper_tester/__init__.py: 6 added lines, 1 removed line.
Original line number Diff line number Diff line
"""Upper Tester service: bridges the TITAN test system (TCP/NDJSON) to an AT modem."""
"""!
@package upper_tester
@brief   Upper Tester service: bridges the TITAN test system (TCP/NDJSON) to an AT modem.
@details See the project overview in README.md for the wire protocol, the module map,
         and how to run and test this package.
"""
+17 −1
Changes for upper_tester/__main__.py: 17 added lines, 1 removed line.
Original line number Diff line number Diff line
"""python3.13 -m upper_tester --device /dev/quectel_at --port 12100"""
"""!
@file
@brief    Command-line entry point: python3.13 -m upper_tester --device /dev/quectel_at --port 12100
@details  Opens the modem, sends `ATE0` once (disable command echo so lines can be told
          apart from responses), and serves the upper-tester TCP protocol (see server.py)
          until interrupted.
"""
import argparse
import asyncio
import logging
@@ -10,6 +16,15 @@ from .server import UtServer


def main() -> None:
    """!
    @brief  Parse arguments/config, open the modem and run the server until Ctrl-C.
    @details Options: `--config` (a TOML file whose keys are option names: `device`, `baud`,
             `host`, `port`, `allow`, `log_level`; overrides the corresponding
             command-line default for any key it sets), `--device` (default
             `/dev/ttyUSB2`), `--baud` (default 115200), `--host` (default `0.0.0.0`),
             `--port` (default 12100), `--allow` (repeatable, an allowed client CIDR
             network; see server.UtServer), `--log-level` (default `INFO`).
    """
    ap = argparse.ArgumentParser(prog="upper_tester")
    ap.add_argument("--config", help="TOML file; keys = option names (device, baud, host, port, allow, log_level)")
    ap.add_argument("--device", default="/dev/ttyUSB2")
@@ -31,6 +46,7 @@ def main() -> None:
    logging.getLogger("ut").info("ATE0 -> %s %r", ok, text)

    async def run() -> None:
        """! @brief Start the TCP server and serve until cancelled. """
        srv = UtServer(Engine(modem), args.host, args.port, args.allow)
        await srv.start()
        await srv.serve_forever()
Loading