Skip to content

Commit 17f470e

Browse files
committed
Document CLI syntax and expand camera tests
1 parent 6457ad0 commit 17f470e

5 files changed

Lines changed: 239 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Repository guidance for agents
2+
3+
- When command syntax is changed or extended, update the documentation in
4+
`docs/` and, when relevant, `README.md` in the same change.
5+
- Keep simulated/example command output in the documentation up to date whenever
6+
the corresponding command output changes.
7+
- Always create GitHub issues in English.

README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
11
# PTZControl
22

3+
## About this fork
4+
5+
This fork builds on Martin Richter's original PTZControl project for Logitech
6+
PTZ cameras and keeps the original Windows GUI application available. The fork
7+
adds a stronger focus on automation, command-line operation, release packaging,
8+
and future Bitfocus Companion integration.
9+
10+
Important additions in this fork include:
11+
12+
- A .NET-based `PTZControlConsole` command-line application.
13+
- Cross-platform console support for Windows and experimental Linux builds, with
14+
macOS support planned for the same backend architecture.
15+
- Modern CLI verbs for device discovery, camera information, zoom, pan/tilt,
16+
presets, home/default restore, and preset/camera friendly names.
17+
- Explicit `--camera`, `--device-path`, and `--slot` selection concepts for
18+
automation scenarios.
19+
- Percent and raw value modes for camera movement commands.
20+
- Cross-platform metadata handling: Windows stays compatible with the original
21+
registry storage, while Linux/macOS use JSON metadata files.
22+
- Config export/import commands for moving preset names and camera slot aliases
23+
between systems.
24+
- GitHub Actions release packaging for the Windows GUI, Windows console builds,
25+
and experimental Linux console builds.
26+
- Guided Windows/Linux camera test scripts to collect reproducible feedback from
27+
real PTZ Pro 2 camera tests.
28+
29+
The original project remains the upstream reference for the classic PTZControl
30+
application. Fork-specific feature work and test feedback are tracked in this
31+
repository's issues.
32+
33+
## Documentation
34+
35+
- [Command syntax](docs/syntax.md)
36+
- [Linux installation](install-linux.md)
37+
338
## History
439
This small program is designed to control a Logitech PTZ 2 Pro. The camera was purchased to stream our church services.
540
Unfortunately, it quickly turned out that the operation with the remote control is possible but cumbersome and inaccurate. The camera was installed directly behind and above the video technician and always pointing back with the remote control was not comfortable.

docs/syntax.md

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
# PTZControlConsole command syntax
2+
3+
`PTZControlConsole` is the automation-oriented command-line interface in this
4+
fork. It is intended for direct shell usage, scripts, and future Bitfocus
5+
Companion integration.
6+
7+
## Device and information commands
8+
9+
```text
10+
PTZControlConsole list-devices
11+
PTZControlConsole cam-device-info [--camera "NamePart" | --device-path "DevicePath"]
12+
PTZControlConsole list-presets [--camera "NamePart" | --device-path "DevicePath"]
13+
```
14+
15+
Example `list-devices` output:
16+
17+
```text
18+
PTZ Pro 2 @device:pnp:\\?\usb#vid_046d&pid_085f&mi_00#...
19+
OBS Virtual Camera @device:sw:{860BB310-5D01-11D0-BD3B-00A0C911CE86}\...
20+
```
21+
22+
Example `cam-device-info` output:
23+
24+
```text
25+
Camera:
26+
Device Name: PTZ Pro 2
27+
Device Path: @device:pnp:\\?\usb#vid_046d&pid_085f&mi_00#...
28+
PTZControl Slot: 1
29+
Camera Slot Alias: Saal links
30+
31+
Zoom:
32+
Percent range: 0..100
33+
Raw min: 0
34+
Raw max: 500
35+
Raw default: 0
36+
Raw step size: 1
37+
Raw current: 120
38+
39+
Move X axis:
40+
Percent range: 0..100
41+
Raw min: -36000
42+
Raw max: 36000
43+
Raw default: 0
44+
Raw step size: 1
45+
Raw current: 0
46+
47+
Move Y axis:
48+
Percent range: 0..100
49+
Raw min: -36000
50+
Raw max: 36000
51+
Raw default: 0
52+
Raw step size: 1
53+
Raw current: 0
54+
55+
Available restore targets:
56+
Home: zoom, move, all
57+
Default: zoom, move, move-x, move-y, all
58+
59+
Presets:
60+
Restore range: 1..8
61+
Save range: 1..8
62+
```
63+
64+
Example `list-presets` output:
65+
66+
```text
67+
Camera Device Name: PTZ Pro 2
68+
PTZControl app camera slot: 1
69+
Camera Slot Alias: Saal links
70+
Preset storage: camera Logitech extension unit
71+
* Preset 1: name=Predigt; values=not readable
72+
* Preset 2: name=Musik; values=not readable
73+
* Preset 3: name=(none); values=not readable
74+
```
75+
76+
## Preset and camera friendly names
77+
78+
```text
79+
PTZControlConsole get-preset-name 1..8 [--camera "NamePart" | --device-path "DevicePath" | --slot 1..3]
80+
PTZControlConsole set-preset-name 1..8 --friendlyname "Title" [--camera "NamePart" | --device-path "DevicePath" | --slot 1..3]
81+
PTZControlConsole clear-preset-name 1..8 [--camera "NamePart" | --device-path "DevicePath" | --slot 1..3]
82+
PTZControlConsole get-camera-name --slot 1..3
83+
PTZControlConsole set-camera-name --friendlyname "Title" --slot 1..3
84+
PTZControlConsole clear-camera-name --slot 1..3
85+
PTZControlConsole swap-preset-names --slot-a 1..3 --slot-b 1..3
86+
```
87+
88+
Friendly names are metadata used by PTZControl and automation tools. They do
89+
not rename the physical camera device.
90+
91+
## Metadata config transport
92+
93+
```text
94+
PTZControlConsole config --export [json-path]
95+
PTZControlConsole config --import json-path
96+
```
97+
98+
Without `json-path`, `config --export` writes the JSON document to stdout.
99+
100+
Windows reads and writes the original PTZControl registry values for
101+
compatibility. Linux and macOS use JSON metadata files.
102+
103+
## Restore commands
104+
105+
```text
106+
PTZControlConsole restore-home --target zoom|move|all [--camera "NamePart" | --device-path "DevicePath"]
107+
PTZControlConsole restore-default --target zoom|move|move-x|move-y|all [--camera "NamePart" | --device-path "DevicePath"]
108+
PTZControlConsole restore-preset 1..8 [--camera "NamePart" | --device-path "DevicePath"]
109+
PTZControlConsole save-preset 1..8 [--camera "NamePart" | --device-path "DevicePath"] [--friendlyname "Title"]
110+
```
111+
112+
## Zoom commands
113+
114+
```text
115+
PTZControlConsole zoom-absolute VALUE --mode percent|raw [--camera "NamePart" | --device-path "DevicePath"]
116+
PTZControlConsole zoom-relative VALUE_DELTA --mode percent|raw [--camera "NamePart" | --device-path "DevicePath"]
117+
```
118+
119+
`--mode percent` uses values relative to the CLI percent range. `--mode raw`
120+
uses device/driver raw values.
121+
122+
## Move commands
123+
124+
```text
125+
PTZControlConsole move-absolute --mode percent|raw [--x VALUE] [--y VALUE] [--camera "NamePart" | --device-path "DevicePath"]
126+
PTZControlConsole move-relative --mode percent|raw [--x VALUE_DELTA] [--y VALUE_DELTA] [--camera "NamePart" | --device-path "DevicePath"]
127+
```
128+
129+
`--x` controls pan. `--y` controls tilt.
130+
131+
## Selection options
132+
133+
```text
134+
--camera "NamePart"
135+
--device-path "DevicePath"
136+
--slot 1..3
137+
```
138+
139+
`--camera` selects by camera device name fragment. `--device-path` selects by a
140+
concrete device path. `--slot` selects PTZControl metadata slot 1, 2, or 3 and
141+
is used for friendly names.

scripts/test-console-camera-linux.sh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ set -u
44
EXE_PATH="./PTZControlConsole"
55
CAMERA=""
66
DEVICE_PATH=""
7+
RAW_ZOOM_DELTA=100
8+
RAW_MOVE_DELTA=3000
9+
RAW_MOVE_ABSOLUTE=9000
710
LOG_PATH="./PTZControlConsole-camera-test-linux.log"
811

912
while [ $# -gt 0 ]; do
@@ -20,6 +23,18 @@ while [ $# -gt 0 ]; do
2023
DEVICE_PATH="$2"
2124
shift 2
2225
;;
26+
--raw-zoom-delta)
27+
RAW_ZOOM_DELTA="$2"
28+
shift 2
29+
;;
30+
--raw-move-delta)
31+
RAW_MOVE_DELTA="$2"
32+
shift 2
33+
;;
34+
--raw-move-absolute)
35+
RAW_MOVE_ABSOLUTE="$2"
36+
shift 2
37+
;;
2338
--log)
2439
LOG_PATH="$2"
2540
shift 2
@@ -87,17 +102,36 @@ fi
87102
log_line "PTZControlConsole guided Linux camera test"
88103
log_line "Executable: $EXE_PATH"
89104
log_line "Selector: ${selector[*]}"
105+
log_line "RawZoomDelta: $RAW_ZOOM_DELTA"
106+
log_line "RawMoveDelta: $RAW_MOVE_DELTA"
107+
log_line "RawMoveAbsolute: $RAW_MOVE_ABSOLUTE"
90108

91109
run_camera_command "List devices" list-devices
92110
run_camera_command "Camera device info" cam-device-info "${selector[@]}"
93111
run_camera_command "Zoom absolute percent 0" zoom-absolute 0 --mode percent "${selector[@]}"
94112
run_camera_command "Zoom absolute percent 50" zoom-absolute 50 --mode percent "${selector[@]}"
113+
run_camera_command "Zoom absolute percent 100" zoom-absolute 100 --mode percent "${selector[@]}"
95114
run_camera_command "Zoom relative percent +10" zoom-relative 10 --mode percent "${selector[@]}"
96115
run_camera_command "Zoom relative percent -10" zoom-relative -10 --mode percent "${selector[@]}"
116+
run_camera_command "Zoom absolute raw 0" zoom-absolute 0 --mode raw "${selector[@]}"
117+
run_camera_command "Zoom relative raw +$RAW_ZOOM_DELTA" zoom-relative "$RAW_ZOOM_DELTA" --mode raw "${selector[@]}"
118+
run_camera_command "Zoom relative raw -$RAW_ZOOM_DELTA" zoom-relative "-$RAW_ZOOM_DELTA" --mode raw "${selector[@]}"
119+
run_camera_command "Move absolute percent center" move-absolute --mode percent --x 50 --y 50 "${selector[@]}"
120+
run_camera_command "Move absolute percent X 40" move-absolute --mode percent --x 40 "${selector[@]}"
121+
run_camera_command "Move absolute percent Y 60" move-absolute --mode percent --y 60 "${selector[@]}"
97122
run_camera_command "Move relative percent X +10" move-relative --mode percent --x 10 "${selector[@]}"
98123
run_camera_command "Move relative percent X -10" move-relative --mode percent --x -10 "${selector[@]}"
99124
run_camera_command "Move relative percent Y +10" move-relative --mode percent --y 10 "${selector[@]}"
100125
run_camera_command "Move relative percent Y -10" move-relative --mode percent --y -10 "${selector[@]}"
126+
run_camera_command "Move absolute raw center" move-absolute --mode raw --x 0 --y 0 "${selector[@]}"
127+
run_camera_command "Move absolute raw X +$RAW_MOVE_ABSOLUTE" move-absolute --mode raw --x "$RAW_MOVE_ABSOLUTE" "${selector[@]}"
128+
run_camera_command "Move absolute raw X -$RAW_MOVE_ABSOLUTE" move-absolute --mode raw --x "-$RAW_MOVE_ABSOLUTE" "${selector[@]}"
129+
run_camera_command "Move absolute raw Y +$RAW_MOVE_ABSOLUTE" move-absolute --mode raw --y "$RAW_MOVE_ABSOLUTE" "${selector[@]}"
130+
run_camera_command "Move absolute raw Y -$RAW_MOVE_ABSOLUTE" move-absolute --mode raw --y "-$RAW_MOVE_ABSOLUTE" "${selector[@]}"
131+
run_camera_command "Move relative raw X +$RAW_MOVE_DELTA" move-relative --mode raw --x "$RAW_MOVE_DELTA" "${selector[@]}"
132+
run_camera_command "Move relative raw X -$RAW_MOVE_DELTA" move-relative --mode raw --x "-$RAW_MOVE_DELTA" "${selector[@]}"
133+
run_camera_command "Move relative raw Y +$RAW_MOVE_DELTA" move-relative --mode raw --y "$RAW_MOVE_DELTA" "${selector[@]}"
134+
run_camera_command "Move relative raw Y -$RAW_MOVE_DELTA" move-relative --mode raw --y "-$RAW_MOVE_DELTA" "${selector[@]}"
101135
run_camera_command "Restore home move" restore-home --target move "${selector[@]}"
102136
run_camera_command "Restore default zoom" restore-default --target zoom "${selector[@]}"
103137
run_camera_command "Restore preset 1" restore-preset 1 "${selector[@]}"

scripts/test-console-camera-windows.ps1

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ param(
22
[string]$ExePath = ".\PTZControlConsole.exe",
33
[string]$Camera,
44
[string]$DevicePath,
5+
[int]$RawZoomDelta = 100,
6+
[int]$RawMoveDelta = 3000,
7+
[int]$RawMoveAbsolute = 9000,
58
[string]$LogPath = ".\PTZControlConsole-camera-test-windows.log"
69
)
710

@@ -59,17 +62,36 @@ elseif ($DevicePath) {
5962
Write-Log "PTZControlConsole guided Windows camera test"
6063
Write-Log "Executable: $ExePath"
6164
Write-Log "Selector: $($selector -join ' ')"
65+
Write-Log "RawZoomDelta: $RawZoomDelta"
66+
Write-Log "RawMoveDelta: $RawMoveDelta"
67+
Write-Log "RawMoveAbsolute: $RawMoveAbsolute"
6268

6369
Invoke-CameraCommand "List devices" @("list-devices")
6470
Invoke-CameraCommand "Camera device info" (@("cam-device-info") + $selector)
6571
Invoke-CameraCommand "Zoom absolute percent 0" (@("zoom-absolute", "0", "--mode", "percent") + $selector)
6672
Invoke-CameraCommand "Zoom absolute percent 50" (@("zoom-absolute", "50", "--mode", "percent") + $selector)
73+
Invoke-CameraCommand "Zoom absolute percent 100" (@("zoom-absolute", "100", "--mode", "percent") + $selector)
6774
Invoke-CameraCommand "Zoom relative percent +10" (@("zoom-relative", "10", "--mode", "percent") + $selector)
6875
Invoke-CameraCommand "Zoom relative percent -10" (@("zoom-relative", "-10", "--mode", "percent") + $selector)
76+
Invoke-CameraCommand "Zoom absolute raw 0" (@("zoom-absolute", "0", "--mode", "raw") + $selector)
77+
Invoke-CameraCommand "Zoom relative raw +$RawZoomDelta" (@("zoom-relative", "$RawZoomDelta", "--mode", "raw") + $selector)
78+
Invoke-CameraCommand "Zoom relative raw -$RawZoomDelta" (@("zoom-relative", "$(-1 * $RawZoomDelta)", "--mode", "raw") + $selector)
79+
Invoke-CameraCommand "Move absolute percent center" (@("move-absolute", "--mode", "percent", "--x", "50", "--y", "50") + $selector)
80+
Invoke-CameraCommand "Move absolute percent X 40" (@("move-absolute", "--mode", "percent", "--x", "40") + $selector)
81+
Invoke-CameraCommand "Move absolute percent Y 60" (@("move-absolute", "--mode", "percent", "--y", "60") + $selector)
6982
Invoke-CameraCommand "Move relative percent X +10" (@("move-relative", "--mode", "percent", "--x", "10") + $selector)
7083
Invoke-CameraCommand "Move relative percent X -10" (@("move-relative", "--mode", "percent", "--x", "-10") + $selector)
7184
Invoke-CameraCommand "Move relative percent Y +10" (@("move-relative", "--mode", "percent", "--y", "10") + $selector)
7285
Invoke-CameraCommand "Move relative percent Y -10" (@("move-relative", "--mode", "percent", "--y", "-10") + $selector)
86+
Invoke-CameraCommand "Move absolute raw center" (@("move-absolute", "--mode", "raw", "--x", "0", "--y", "0") + $selector)
87+
Invoke-CameraCommand "Move absolute raw X +$RawMoveAbsolute" (@("move-absolute", "--mode", "raw", "--x", "$RawMoveAbsolute") + $selector)
88+
Invoke-CameraCommand "Move absolute raw X -$RawMoveAbsolute" (@("move-absolute", "--mode", "raw", "--x", "$(-1 * $RawMoveAbsolute)") + $selector)
89+
Invoke-CameraCommand "Move absolute raw Y +$RawMoveAbsolute" (@("move-absolute", "--mode", "raw", "--y", "$RawMoveAbsolute") + $selector)
90+
Invoke-CameraCommand "Move absolute raw Y -$RawMoveAbsolute" (@("move-absolute", "--mode", "raw", "--y", "$(-1 * $RawMoveAbsolute)") + $selector)
91+
Invoke-CameraCommand "Move relative raw X +$RawMoveDelta" (@("move-relative", "--mode", "raw", "--x", "$RawMoveDelta") + $selector)
92+
Invoke-CameraCommand "Move relative raw X -$RawMoveDelta" (@("move-relative", "--mode", "raw", "--x", "$(-1 * $RawMoveDelta)") + $selector)
93+
Invoke-CameraCommand "Move relative raw Y +$RawMoveDelta" (@("move-relative", "--mode", "raw", "--y", "$RawMoveDelta") + $selector)
94+
Invoke-CameraCommand "Move relative raw Y -$RawMoveDelta" (@("move-relative", "--mode", "raw", "--y", "$(-1 * $RawMoveDelta)") + $selector)
7395
Invoke-CameraCommand "Restore home move" (@("restore-home", "--target", "move") + $selector)
7496
Invoke-CameraCommand "Restore default zoom" (@("restore-default", "--target", "zoom") + $selector)
7597
Invoke-CameraCommand "Restore preset 1" (@("restore-preset", "1") + $selector)

0 commit comments

Comments
 (0)