{"id":50719033,"url":"https://github.com/pcs-electronics/stmax-config","last_synced_at":"2026-06-09T22:01:09.420Z","repository":{"id":349158492,"uuid":"1197244673","full_name":"pcs-electronics/stmax-config","owner":"pcs-electronics","description":"Configure PCS Electronix STMAX FM transmitter boards over a serial port via CLI","archived":false,"fork":false,"pushed_at":"2026-04-04T13:12:55.000Z","size":13,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-04T15:52:44.041Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pcs-electronics.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-31T12:41:09.000Z","updated_at":"2026-04-04T13:13:30.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pcs-electronics/stmax-config","commit_stats":null,"previous_names":["pcs-electronics/stmax-config"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/pcs-electronics/stmax-config","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcs-electronics%2Fstmax-config","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcs-electronics%2Fstmax-config/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcs-electronics%2Fstmax-config/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcs-electronics%2Fstmax-config/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pcs-electronics","download_url":"https://codeload.github.com/pcs-electronics/stmax-config/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pcs-electronics%2Fstmax-config/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34127345,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-09T22:01:08.599Z","updated_at":"2026-06-09T22:01:09.411Z","avatar_url":"https://github.com/pcs-electronics.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# stmax-config\n\n`stmax-config.py` configures PCS Electronix STMAX FM transmitter boards (like STMAX9100) over a serial port using the command set implemented in [`Firmware/Firmware.ino`](../Firmware/Firmware.ino).\n\n\u003e Notice: `stmax-config.py` was designed by the GPT-5.4 AI model.\n\n## Features\n\n- Opens one serial port session and sends one or more configuration commands.\n- Uses normalized command names such as `power 50`, `fq 99.5`, and `rds-pi 1234`.\n- Validates values before anything is sent to the board.\n- Prints a local command reference when run without a port or without commands.\n- Supports `info`, which sends `?` and prints the board's `output_help()` response.\n\n## Requirements\n\n- Python 3.9+\n- `pyserial`\n\nInstall the runtime dependency with:\n\n```bash\npython3 -m pip install pyserial\n```\n\n## Usage\n\n```bash\npython3 stmax-config.py [OPTIONS] [SERIAL_PORT] [COMMAND ...]\n```\n\nThe first positional argument is the serial port name. All following arguments are parsed as one or more board commands. The script validates each command locally, opens the serial port once, sends newline-terminated firmware commands, and prints the board replies to standard output.\n\nIf you run the script without a serial port, or with a serial port but no commands, it prints a local command reference and exits without opening the port.\n\nRun the built-in CLI help for the full argument list:\n\n```bash\npython3 stmax-config.py --help\n```\n\nSupported options:\n\n- `-h`, `--help` prints the command reference and exits.\n- `--baud` sets the serial baud rate. Default: `115200`\n- `--timeout` sets the per-read serial timeout in seconds. Default: `0.10`\n- `--quiet-timeout` defines how long the line must stay quiet before a response is considered complete. Default: `0.35`\n- `--startup-delay` waits briefly after opening the port before flushing startup text. Default: `0.20`\n\nExamples:\n\n```bash\npython3 stmax-config.py /dev/ttyUSB0 info\npython3 stmax-config.py /dev/ttyUSB0 power 50 fq 99.5 save\npython3 stmax-config.py /dev/ttyUSB0 audio-stereo 1 audio-input 0 audio-gain 2 audio-pre 1\npython3 stmax-config.py /dev/ttyUSB0 rds-ps STMAX rds-rt \"Studio link active\"\npython3 stmax-config.py /dev/ttyUSB0 rds-afs 99.5 101.2 104.7\npython3 stmax-config.py /dev/ttyUSB0 rds-pi 1234 rds 1 save\n```\n\nNotes:\n\n- Quote multi-word `rds-ps` and `rds-rt` values.\n- `rds-afs:` with an empty value clears the AF list, for example: `python3 stmax-config.py /dev/ttyUSB0 rds-afs:`\n- The script prints the board responses directly. Most configuration commands return `OK` or `ERR`. `info` prints the full firmware help and current settings block.\n- `info` is a convenience alias for the firmware `?` command.\n- The script exits with status `0` on success, `1` on board or serial errors, and `2` on local argument validation errors.\n\n## AI Agent Integration\n\nA `SKILL.md` file is included in the `skills/stmax-control/` folder. This file provides a structured skill definition that can be integrated into AI agents (such as OpenClaw, ZeroClaw, PicoClaw, etc.).\n\nTo use this skill with your AI agent:\n\n1. Copy the `skills/stmax-control/SKILL.md` file to your agent's skills folder.\n2. Configure your agent to recognize the skill by placing it in the appropriate path according to your agent framework's conventions.\n3. Your agent can then:\n   - Understand the `stmax-config.py` command set and validation rules\n   - Help you construct valid configuration sequences\n   - Suggest optimal settings for frequency, power, and RDS parameters\n   - Guide complex workflows such as saving configurations and rebooting\n\nThe skill includes command categories, validation ranges, common patterns, and full workflow guidance.\n\n## How Commands Are Parsed\n\nThis README uses the normalized command names that match the original firmware commands with the `config-` prefix removed.\n\nExamples:\n\n```bash\npython3 stmax-config.py /dev/ttyUSB0 power 50 fq 99.5 save\npython3 stmax-config.py /dev/ttyUSB0 rds 1 rds-pi 1234 rds-ps STMAX rds-rt \"Studio link active\"\n```\n\nParsing rules:\n\n- Commands are sent in the same order they are given on the command line.\n- Commands such as `save`, `reboot`, `defaults`, and `info` do not take a value.\n- Commands such as `power 50`, `fq 99.5`, and `rds-pi 1234` may also be written inline as `power:50`, `fq:99.5`, and `rds-pi:1234`.\n- `rds-ps` and `rds-rt` accept the next argument as text, so wrap multi-word values in quotes.\n- `rds-afs` accepts multiple following frequency values until the next recognized command token.\n\n## Script Behavior\n\nThe script is intentionally thin. It does not try to interpret or reformat the board response. Instead it:\n\n- validates the requested values against the current firmware ranges\n- opens the selected serial port\n- sends each translated command followed by a newline\n- reads until the board stops replying for the configured quiet timeout\n- prints the received text as-is\n\nThis is especially useful for `info`, because the output is the board's own `output_help()` text rather than a copy embedded in the Python script.\n\n## Helper Scripts\n\nThe folder also contains small helper wrappers that always use `/dev/ttyUSB0` as the serial port.\n\n| Script | Action |\n| --- | --- |\n| `info.sh` | Runs `info` and prints the board help and current settings. |\n| `save.sh` | Saves the current board state to non-volatile memory. |\n| `set875.sh` | Sets the frequency to `87.5` MHz. |\n| `set108.sh` | Sets the frequency to `108` MHz. |\n| `power10percent.sh` | Sets the output power to `10` percent. |\n| `power100percent.sh` | Sets the output power to `100` percent. |\n\nExamples:\n\n```bash\n./info.sh\n./save.sh\n./set875.sh\n./set108.sh\n./power10percent.sh\n./power100percent.sh\n```\n\nEach helper forwards any extra arguments to `stmax-config.py`, so you can append commands such as `save`:\n\n```bash\n./set875.sh save\n./power10percent.sh save\n```\n\n## Supported Commands\n\nThe descriptions below mirror the current firmware help text from `output_help()` in [`../Firmware/Firmware.ino`](../Firmware/Firmware.ino).\n\n| Command | Firmware description | Validation |\n| --- | --- | --- |\n| `info` | Show firmware help and current settings. | No value |\n| `save` | Save settings to non-volatile memory. | No value |\n| `reboot` | Reboot the exciter board. | No value |\n| `defaults` | Set factory defaults. | No value |\n| `power N` | Set power percentage to `n` (`0` to `100`). | `0` to `100` |\n| `fq N` | Set frequency to `n` MHz (example: `87.5`). | `87.5` to `108.0` MHz |\n| `audio-stereo N` | Set stereo mode to `0` (mono) or `1` (stereo). | `0` or `1` |\n| `audio-input N` | Set audio input to `0` (analog) or `1` (digital). | `0` or `1` |\n| `audio-gain N` | Set audio gain to `0` (low) to `2` (high). | `0` to `2` |\n| `audio-pre N` | Set preemphasis `0` (75 uS) or `1` (50 uS). | `0` or `1` |\n| `alarm-temp N` | Set alarm temperature to `n` degrees C (`40` to `100`). | `40` to `100` C |\n| `rds N` | Turn RDS on (`n=1`) or off (`n=0`). | `0` or `1` |\n| `rds-pi HEX` | Set PI to `nnnn` (hex). | 1 to 4 hex digits |\n| `rds-ecc N` | Set ECC to `n`. | `0` to `255` |\n| `rds-ps TEXT` | Set PS to `n` (up to 8 characters). | Up to 8 bytes |\n| `rds-rt TEXT` | Set Radio Text to `n` (up to 64 characters). | Up to 64 bytes |\n| `rds-tp N` | Set TP bit (`0` or `1`). | `0` or `1` |\n| `rds-ta N` | Set TA bit (`0` or `1`). | `0` or `1` |\n| `rds-ms N` | Set MS bit (`0` or `1`). | `0` or `1` |\n| `rds-di N` | Set DI (`0` to `15`). | `0` to `15` |\n| `rds-pty N` | Set PTY (`0` to `31`). | `0` to `31` |\n| `rds-afs F1 F2 ...` | Set up to 25 alternative frequencies in MHz. | Up to 25 entries, `87.6` to `107.9` MHz in `0.1` MHz steps |\n\n## Firmware Mapping\n\nThe tool validates against the ranges exposed by the current firmware:\n\n- `power`, `alarm-temp`, `fq`, and `rds-afs` use explicit numeric range checks before sending.\n- `rds-ps` and `rds-rt` reject embedded newlines and enforce the firmware byte-length limits.\n- `info` maps to `?`, which causes the board to respond with `answer_ok()` followed by `output_help()`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpcs-electronics%2Fstmax-config","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpcs-electronics%2Fstmax-config","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpcs-electronics%2Fstmax-config/lists"}