tesmartctl 0.0.7.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tesmartctl-0.0.7.2/LICENSE +21 -0
- tesmartctl-0.0.7.2/PKG-INFO +399 -0
- tesmartctl-0.0.7.2/README.md +387 -0
- tesmartctl-0.0.7.2/pyproject.toml +24 -0
- tesmartctl-0.0.7.2/setup.cfg +4 -0
- tesmartctl-0.0.7.2/tesmart/__init__.py +19 -0
- tesmartctl-0.0.7.2/tesmart/__main__.py +3 -0
- tesmartctl-0.0.7.2/tesmart/cli.py +706 -0
- tesmartctl-0.0.7.2/tesmart/config.py +359 -0
- tesmartctl-0.0.7.2/tesmart/examples.py +198 -0
- tesmartctl-0.0.7.2/tesmart/listener.py +336 -0
- tesmartctl-0.0.7.2/tesmart/notices.py +27 -0
- tesmartctl-0.0.7.2/tesmart/panel.py +447 -0
- tesmartctl-0.0.7.2/tesmart/peek.py +241 -0
- tesmartctl-0.0.7.2/tesmart/protocol.py +201 -0
- tesmartctl-0.0.7.2/tesmart/static/panel.css +110 -0
- tesmartctl-0.0.7.2/tesmart/static/panel.html +327 -0
- tesmartctl-0.0.7.2/tesmart/static/panel.js +949 -0
- tesmartctl-0.0.7.2/tesmart/switch.py +388 -0
- tesmartctl-0.0.7.2/tesmart/transport.py +128 -0
- tesmartctl-0.0.7.2/tesmart/web.py +379 -0
- tesmartctl-0.0.7.2/tesmartctl.egg-info/PKG-INFO +399 -0
- tesmartctl-0.0.7.2/tesmartctl.egg-info/SOURCES.txt +25 -0
- tesmartctl-0.0.7.2/tesmartctl.egg-info/dependency_links.txt +1 -0
- tesmartctl-0.0.7.2/tesmartctl.egg-info/entry_points.txt +2 -0
- tesmartctl-0.0.7.2/tesmartctl.egg-info/requires.txt +3 -0
- tesmartctl-0.0.7.2/tesmartctl.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 WBEVAN
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tesmartctl
|
|
3
|
+
Version: 0.0.7.2
|
|
4
|
+
Summary: Command-line control for TESmart 8x1 / 16x1 HDMI switches over LAN or RS232
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Provides-Extra: serial
|
|
10
|
+
Requires-Dist: pyserial>=3.5; extra == "serial"
|
|
11
|
+
Dynamic: license-file
|
|
12
|
+
|
|
13
|
+
# tesmartctl
|
|
14
|
+
|
|
15
|
+
Command-line, HTTP, and browser control for TESmart 8×1 and 16×1 HDMI switches (HSW0801, HKS0801, HSW1601, HKS1601 and the same protocol family). It talks to the switch over its LAN port or the 3-pin RS232 port.
|
|
16
|
+
|
|
17
|
+
This is an independent project. It is not published by, or affiliated with, TESmart.
|
|
18
|
+
|
|
19
|
+
LAN control uses only the Python standard library. RS232 needs `pyserial`. Python 3.10 or newer. Licensed under the [MIT License](LICENSE).
|
|
20
|
+
|
|
21
|
+
## What it does
|
|
22
|
+
|
|
23
|
+
| | |
|
|
24
|
+
| --- | --- |
|
|
25
|
+
| Read | Active input, and the IP, port, gateway, and mask stored in the switch |
|
|
26
|
+
| Switch | Select an input by number or by a local name, or step next and previous through a list you choose |
|
|
27
|
+
| Peek | Show another input for a few seconds, then return. Not a cycle |
|
|
28
|
+
| Cycle | Walk a chosen list by hand (`next` / `previous`) or on a timer (`cycle run`) |
|
|
29
|
+
| Settings | Buzzer, front-panel display timeout, auto input detection. The switch cannot report these back |
|
|
30
|
+
| Address | Change the switch's IP, port, gateway, and mask, with two warnings and a read-back. Applied only after a power cycle |
|
|
31
|
+
| Listen | Keep one connection open: a line protocol on stdin or TCP, or HTTP URLs for Stream Deck, Companion, Home Assistant, and similar |
|
|
32
|
+
| Panel | Optional browser page at `/panel` (`listen --http PORT --panel`), including an API explorer |
|
|
33
|
+
|
|
34
|
+
The switch cannot say which HDMI inputs have a signal. A cycle is the list you configure, stored on this computer, not in the switch. Local input names are stored the same way.
|
|
35
|
+
|
|
36
|
+
| Document | What it covers |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| This file | Install, configuration, every command |
|
|
39
|
+
| [`Docs/protocol.md`](Docs/protocol.md) | Byte protocol the switch speaks |
|
|
40
|
+
| [`Docs/listener.md`](Docs/listener.md) | Long-running line protocol and HTTP URLs |
|
|
41
|
+
| [`Docs/panel.md`](Docs/panel.md) | Browser control panel at `/panel` |
|
|
42
|
+
| [`Docs/embed.md`](Docs/embed.md) | Input buttons on a page you already have |
|
|
43
|
+
|
|
44
|
+
## Install
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
git clone https://github.com/WBEVAN/TESmartController.git
|
|
48
|
+
cd TESmartController
|
|
49
|
+
pip install . # adds the tesmartctl command
|
|
50
|
+
pip install '.[serial]' # also installs pyserial, for the RS232 port
|
|
51
|
+
pip install -e . # editable: edits in this tree take effect immediately
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Without installing, run from the repository directory:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
python3 -m tesmart status
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
If the shell cannot find `tesmartctl` after install, open a new shell, or rehash your version manager. Requires Python 3.10 or newer.
|
|
61
|
+
|
|
62
|
+
## Help and examples
|
|
63
|
+
|
|
64
|
+
Every command prints worked examples at the end of its `--help`:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
tesmartctl --help # command list plus the most common invocations
|
|
68
|
+
tesmartctl input --help # flags and examples for one command
|
|
69
|
+
tesmartctl net set --help
|
|
70
|
+
tesmartctl examples # every example for every command, in one listing
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
The same examples appear in this README. They are generated from one table (`tesmart/examples.py`), so the terminal and the docs agree.
|
|
74
|
+
|
|
75
|
+
## Quick start: change inputs
|
|
76
|
+
|
|
77
|
+
From the command line:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
tesmartctl input 3 # switch to HDMI 3
|
|
81
|
+
tesmartctl input Office # switch by a local name (see `tesmartctl name`)
|
|
82
|
+
tesmartctl next # next input in the saved cycle
|
|
83
|
+
tesmartctl peek 2 # look at HDMI 2 for 5 seconds, then come back
|
|
84
|
+
tesmartctl input # which input is active now
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
From a URL, after starting the HTTP listener once (for example as a login item or a service):
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
tesmartctl listen --http 0.0.0.0:8080 # add --panel for the browser control panel
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```text
|
|
94
|
+
http://<host>:8080/input/3 switch to HDMI 3
|
|
95
|
+
http://<host>:8080/input/Office switch by local name
|
|
96
|
+
http://<host>:8080/next next input in the saved cycle
|
|
97
|
+
http://<host>:8080/previous previous input
|
|
98
|
+
http://<host>:8080/peek/2?seconds=8 look at HDMI 2 for 8 seconds, then come back
|
|
99
|
+
http://<host>:8080/input read the active input, {"active_input": 3}
|
|
100
|
+
http://<host>:8080/input?format=text same, as a bare number
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
`<host>` is the machine running `tesmartctl`, not the switch. Use `127.0.0.1` with a port-only `--http 8080` when the controller runs on the same computer. Use `0.0.0.0:8080` to accept other devices on your network. The listener has no authentication, so only expose it to a network you trust.
|
|
104
|
+
|
|
105
|
+
### Stream Deck, macro pads, and home control
|
|
106
|
+
|
|
107
|
+
Each input change is one URL or one command, so anything that can open a URL or run a shell command can drive the switch:
|
|
108
|
+
|
|
109
|
+
| Controller | How to wire one button |
|
|
110
|
+
| --- | --- |
|
|
111
|
+
| Elgato Stream Deck | **Website** action with `http://127.0.0.1:8080/input/3` and "GET request in background" ticked, or a **System > Open** action running `tesmartctl input 3`. |
|
|
112
|
+
| Bitfocus Companion | **Generic HTTP**, GET `http://<host>:8080/input/3`. |
|
|
113
|
+
| Home Assistant | A `rest_command` (`url: http://<host>:8080/input/{{ input }}`) called from a button, script, or automation. A `rest` sensor on `/input?format=text` shows the active input. |
|
|
114
|
+
| Homebridge / HomeKit | An HTTP switch or button plugin pointed at `/input/N`, one accessory per input. |
|
|
115
|
+
| Node-RED | An **http request** node, GET `/input/3`. |
|
|
116
|
+
| Apple Shortcuts | **Get Contents of URL** with `http://<host>:8080/input/3`. |
|
|
117
|
+
| Keyboard Maestro, Hammerspoon, cron | Run `tesmartctl input 3`, or `curl -s http://127.0.0.1:8080/input/3`. |
|
|
118
|
+
|
|
119
|
+
Home Assistant example (`configuration.yaml`):
|
|
120
|
+
|
|
121
|
+
```yaml
|
|
122
|
+
rest_command:
|
|
123
|
+
tesmart_input:
|
|
124
|
+
url: "http://192.168.1.20:8080/input/{{ input }}"
|
|
125
|
+
tesmart_peek:
|
|
126
|
+
url: "http://192.168.1.20:8080/peek/{{ input }}?seconds={{ seconds | default(5) }}"
|
|
127
|
+
|
|
128
|
+
sensor:
|
|
129
|
+
- platform: rest
|
|
130
|
+
name: TESmart active input
|
|
131
|
+
resource: "http://192.168.1.20:8080/input?format=text"
|
|
132
|
+
scan_interval: 10
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Here `192.168.1.20` stands for the computer running the listener. Every response says which input the switch actually reports (`active_input`), so a controller can show the real state rather than assuming the switch obeyed. See [Listener](#listener) for every route.
|
|
136
|
+
|
|
137
|
+
## Connection
|
|
138
|
+
|
|
139
|
+
The switch's factory address is `192.168.1.10`, TCP port `5000`. You can move it to another address on your network with `tesmartctl net set`. After that, save the new address as the CLI default so later commands do not need `--host`.
|
|
140
|
+
|
|
141
|
+
Each setting (`host`, `port`, `serial`, `inputs`) is resolved in this order:
|
|
142
|
+
|
|
143
|
+
1. Command-line flag (`--host`, `--port`, `--serial`, `--inputs`)
|
|
144
|
+
2. Env file `~/.config/tesmartctl/env` (override the path with `--env-file` or `TESMART_ENV_FILE`)
|
|
145
|
+
3. Environment variable, only when it is set (`TESMART_HOST`, `TESMART_PORT`, `TESMART_SERIAL`, `TESMART_INPUTS`)
|
|
146
|
+
4. Built-in default (`192.168.1.10`, `5000`, no serial device, `8` inputs)
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
tesmartctl config show # effective values and where each came from
|
|
150
|
+
tesmartctl config set host 192.168.1.50 # also: port, serial, inputs
|
|
151
|
+
tesmartctl config unset host
|
|
152
|
+
tesmartctl config path
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Input names are local. The switch cannot store them. They are written to the same env file as `TESMART_NAME_1=Office` and appear in `status`, `input`, and `rotate`.
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
tesmartctl name set 2 Office
|
|
159
|
+
tesmartctl name set 1 "Living room"
|
|
160
|
+
tesmartctl name list
|
|
161
|
+
tesmartctl name unset 1
|
|
162
|
+
tesmartctl input Office # select by the local name
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The env file is plain `KEY=VALUE` lines (`TESMART_HOST=192.168.1.50`) and can be edited by hand. `--serial /dev/tty.usbserial-xxx` uses RS232 at 9600 8N1 instead of LAN. `--inputs 16` is for a 16×1. `--timeout 1.5` is how long a reply is awaited. `--json` prints JSON from the one-shot commands.
|
|
166
|
+
|
|
167
|
+
Global flags go before the subcommand: `tesmartctl --host 192.168.1.50 status`.
|
|
168
|
+
|
|
169
|
+
## What the switch will report
|
|
170
|
+
|
|
171
|
+
| Setting | Read | Write |
|
|
172
|
+
| --- | --- | --- |
|
|
173
|
+
| Active input (1–8, or 1–16) | yes | yes, and the switch reports the input it actually selected |
|
|
174
|
+
| LAN IP, TCP port, gateway, mask | yes | yes, applied only after a power cycle |
|
|
175
|
+
| Buzzer | no | yes |
|
|
176
|
+
| Front-panel LED timeout (never, 10s, 30s) | no | yes |
|
|
177
|
+
| Auto input detection | no | yes |
|
|
178
|
+
|
|
179
|
+
Buzzer, LED timeout, and auto-detect accept a set command and send nothing back. A successful command means the bytes were sent, not that the value was read back.
|
|
180
|
+
|
|
181
|
+
The switch drops or garbles commands sent faster than about once a second. `tesmartctl` waits that long between writes on one connection.
|
|
182
|
+
|
|
183
|
+
This is an 8-input, 1-output switch. The protocol can read the selected input and cannot read which inputs have a signal, so it cannot calculate which sources are connected. The front-panel LEDs show that locally. `rotate` therefore walks every input from 1 to 8, or an explicit list you pass with `--only`.
|
|
184
|
+
|
|
185
|
+
## Commands
|
|
186
|
+
|
|
187
|
+
### Read
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
tesmartctl status # active input plus saved LAN settings
|
|
191
|
+
tesmartctl status --json
|
|
192
|
+
tesmartctl status --no-network # skip the four LAN queries
|
|
193
|
+
tesmartctl input # active input only
|
|
194
|
+
tesmartctl net show # IP, port, gateway, mask
|
|
195
|
+
tesmartctl monitor # print the input whenever it changes
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
`status` looks like:
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
Endpoint: tcp://192.168.1.50:5000
|
|
202
|
+
Active input: 2 (Office) of 8
|
|
203
|
+
Input names (stored locally, not on the switch):
|
|
204
|
+
1 Living room
|
|
205
|
+
2 Office
|
|
206
|
+
Network (persisted; applied after power cycle):
|
|
207
|
+
IP: 192.168.1.50
|
|
208
|
+
Port: 5000
|
|
209
|
+
Gateway: 192.168.1.1
|
|
210
|
+
Mask: 255.255.255.0
|
|
211
|
+
Cycle: manual (next/previous); 1, 2, 4 (chosen inputs)
|
|
212
|
+
Peek: 5s on another input, then back (`peek N`)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
The cycle is stored on this machine. `manual` moves only when you ask for `next` or `previous`. `automatic` is the same list on a timer, and it starts only while `cycle run` is running. With no saved list the cycle is every input.
|
|
216
|
+
|
|
217
|
+
Peek is not a cycle. `peek 3` shows input 3 for a few seconds and then returns to the input that was active. The duration is stored on this machine.
|
|
218
|
+
|
|
219
|
+
`monitor` stays running and prints a new line when the front panel, the remote, auto-detect, or another client changes the input. Ctrl-C stops it.
|
|
220
|
+
|
|
221
|
+
### Change the input
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
tesmartctl input 3 # switch to HDMI 3 and read it back
|
|
225
|
+
tesmartctl input 3 --no-verify # send the command and do not read it back
|
|
226
|
+
tesmartctl cycle inputs 1,2,4 # save the inputs to walk
|
|
227
|
+
tesmartctl cycle mode manual # next and previous only
|
|
228
|
+
tesmartctl next # Office -> next chosen input
|
|
229
|
+
tesmartctl previous
|
|
230
|
+
tesmartctl cycle mode automatic --every 15 # then start the timer:
|
|
231
|
+
tesmartctl cycle run
|
|
232
|
+
tesmartctl --json input 3
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
Inputs are 1-based. The command exits non-zero when the switch reports a different input than the one requested. `input 9` is rejected locally and is not sent.
|
|
236
|
+
|
|
237
|
+
### Peek at another input
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
tesmartctl peek 3 # show input 3 for 5 seconds, then come back
|
|
241
|
+
tesmartctl peek Office --seconds 10
|
|
242
|
+
tesmartctl peek 3 --seconds 8 --save # and make 8 seconds the default
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
`peek` flips to the input, waits, and flips back to the one that was active. Ctrl-C comes back at once. If the input is changed by something else during the peek (front panel, remote, another client), `peek` leaves that choice alone, reports it, and exits non-zero. The default duration is `5` seconds, stored as `TESMART_PEEK_SECONDS` in the env file.
|
|
246
|
+
|
|
247
|
+
The listener can also make the *next* ordinary input change a peek, so a button that calls `/input/3` peeks instead of sticking. `GET /peek/once` arms a single change. `GET /peek/always` keeps doing it until `GET /peek/off`. Detail is in [`Docs/listener.md`](Docs/listener.md).
|
|
248
|
+
|
|
249
|
+
### Write-only settings
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
tesmartctl buzzer off # on | off
|
|
253
|
+
tesmartctl led 10 # never | 10 | 30 (seconds)
|
|
254
|
+
tesmartctl autodetect on # on | off
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Accepted words for on/off also include `1`/`0`, `true`/`false`, `enable`/`disable`, `unmute`/`mute`.
|
|
258
|
+
|
|
259
|
+
### LAN address
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
tesmartctl net set \
|
|
263
|
+
--ip 192.168.1.50 --gateway 192.168.1.1 --mask 255.255.255.0 --yes
|
|
264
|
+
tesmartctl net show # read the stored values back before rebooting
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
`--tcp-port` sets the switch's own listen port (factory `5000`). Each value is stored immediately and used only after the switch is power-cycled. There is no factory reset for these settings.
|
|
268
|
+
|
|
269
|
+
**Risk notice.** A wrong IP address, port, gateway, or mask makes the switch unreachable over the network, and recovery is only possible with a serial (RS232) cable. This software sends the values exactly as entered; it cannot check that they are valid for your network, cannot undo the change, and cannot recover a switch that is no longer reachable. You change these settings at your own risk. This software and its authors accept no liability for any loss, damage, downtime, or cost that results from doing so.
|
|
270
|
+
|
|
271
|
+
`net set` warns twice: without `--yes` it prints the notice and refuses; with `--yes` it prints the notice again, writes, then reads every value back from the switch and reports whether each one is `stored` or a `MISMATCH`. The exit code is `0` only when every value reads back as requested. Until the switch is power-cycled it keeps answering on its current address, so a mismatch can still be corrected.
|
|
272
|
+
|
|
273
|
+
`--save-default` writes the new `--ip` and `--tcp-port` into the CLI env file after the read-back confirms them, so later commands follow the switch to the new address.
|
|
274
|
+
|
|
275
|
+
### Raw bytes
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
tesmartctl raw AA BB 03 10 00 EE
|
|
279
|
+
# Sent: AA BB 03 10 00 EE
|
|
280
|
+
# Received: AA BB 03 11 01 EE
|
|
281
|
+
# frame cmd=0x11 value=0x01 term=0xEE -> input 2
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
`--listen 3` waits longer for the reply. See [`Docs/protocol.md`](Docs/protocol.md) for the frame layout. The input query value is 0-based in the reply (`0x01` is input 2).
|
|
285
|
+
|
|
286
|
+
## Listener
|
|
287
|
+
|
|
288
|
+
`listen` keeps one connection open. Use it when something else (a script, `nc`, a browser, a home-automation "open URL" action) needs to change inputs without starting a new process each time. Full detail is in [`Docs/listener.md`](Docs/listener.md).
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
tesmartctl listen # one command per line on stdin
|
|
292
|
+
printf 'get\nset 3\nquit\n' | tesmartctl listen
|
|
293
|
+
|
|
294
|
+
tesmartctl listen --bind 9753 # raw TCP on this computer only, 127.0.0.1:9753
|
|
295
|
+
tesmartctl listen --bind 0.0.0.0:9753 # raw TCP on every interface
|
|
296
|
+
echo set 4 | nc 127.0.0.1 9753 # prints the input the switch reports
|
|
297
|
+
|
|
298
|
+
tesmartctl listen --http 8080 # HTTP on this computer only, http://127.0.0.1:8080/
|
|
299
|
+
tesmartctl listen --http 0.0.0.0:8080 # HTTP on every interface; other devices use this computer's address
|
|
300
|
+
tesmartctl listen --http 0.0.0.0:8080 --panel
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
`--bind` and `--http` cannot be combined. Run two processes if you want both. A port number alone binds `127.0.0.1`, so only this computer can connect. `0.0.0.0` accepts every network interface. Other devices then use the address of the computer running `tesmartctl`, for example `http://192.168.1.20:8080/input/3`. There is no authentication, so only do this on a network you trust.
|
|
304
|
+
|
|
305
|
+
`--panel` is off unless you add it. It serves a browser page for selecting inputs, stepping the cycle, peeking, and the switch settings the vendor Windows controller exposes (buzzer, front-panel display timeout, auto input detection, LAN address). Detail is in [`Docs/panel.md`](Docs/panel.md).
|
|
306
|
+
|
|
307
|
+

|
|
308
|
+
|
|
309
|
+
The **API** button in the top bar opens an explorer that lists every `/api` route, sends it, and shows the raw status and body the listener returned.
|
|
310
|
+
|
|
311
|
+

|
|
312
|
+
|
|
313
|
+
Line commands: `get` (also `port`, `status`, `?`) prints the active input; `set 3`, `set Office`, or just `3` switches and prints the input the switch reports; `next` or `rotate 1,2,4` moves to the next input; `peek 3` or `peek 3 10` shows an input briefly and replies once back; `quit` closes the session. `--json` makes each reply one JSON object. The line command `status` is only the active input. The full readable status is the HTTP route and `tesmartctl status`.
|
|
314
|
+
|
|
315
|
+
A full session on stdin:
|
|
316
|
+
|
|
317
|
+
```text
|
|
318
|
+
$ tesmartctl listen
|
|
319
|
+
Command listener on stdin for tcp://192.168.1.50:5000 (Ctrl-C or 'quit' to stop).
|
|
320
|
+
commands: get | set <n> | <n> | next | previous | rotate [1,2,4] | peek <n> [seconds] | quit
|
|
321
|
+
get
|
|
322
|
+
2
|
|
323
|
+
set 3
|
|
324
|
+
3
|
|
325
|
+
Office
|
|
326
|
+
2
|
|
327
|
+
next
|
|
328
|
+
3
|
|
329
|
+
quit
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
HTTP routes, GET or POST:
|
|
333
|
+
|
|
334
|
+
```text
|
|
335
|
+
http://127.0.0.1:8080/ list of routes
|
|
336
|
+
http://127.0.0.1:8080/input {"active_input": 2}
|
|
337
|
+
http://127.0.0.1:8080/status input plus saved IP, port, gateway, mask
|
|
338
|
+
http://127.0.0.1:8080/status?network=0 input only, skips the LAN queries
|
|
339
|
+
http://127.0.0.1:8080/status?format=text same fields as plain lines
|
|
340
|
+
http://127.0.0.1:8080/rotate next input; {"previous": 2, "active_input": 3}
|
|
341
|
+
http://127.0.0.1:8080/rotate?only=1,2,4 next input within that list
|
|
342
|
+
http://127.0.0.1:8080/input?rotate=1 same as /rotate
|
|
343
|
+
http://127.0.0.1:8080/peek/3 show 3 for the saved seconds, then back; replies once back
|
|
344
|
+
http://127.0.0.1:8080/peek?input=3&seconds=8 same with an explicit duration
|
|
345
|
+
http://127.0.0.1:8080/peek/once the next input change peeks, then later changes stick
|
|
346
|
+
http://127.0.0.1:8080/peek/always every plain input change peeks until /peek/off
|
|
347
|
+
http://127.0.0.1:8080/peek/off plain input changes stick again
|
|
348
|
+
http://127.0.0.1:8080/input?set=3 {"active_input": 3, "requested": 3}
|
|
349
|
+
http://127.0.0.1:8080/input/3 same as /input?set=3
|
|
350
|
+
http://127.0.0.1:8080/input/Office switch by a local name
|
|
351
|
+
http://127.0.0.1:8080/set?input=3 same as /input?set=3
|
|
352
|
+
http://127.0.0.1:8080/get same as /input
|
|
353
|
+
http://127.0.0.1:8080/input/3?format=text 3
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
`active_input` is what the switch reports after the change. Compare it with `requested` when they might differ. `400` is a bad number or a switch rejection, `404` is an unknown route, `502` means the switch connection failed. `/status` takes a few seconds because each LAN query is paced.
|
|
357
|
+
|
|
358
|
+
## Library
|
|
359
|
+
|
|
360
|
+
```python
|
|
361
|
+
from tesmart import TcpTransport, TesmartSwitch, LedTimeout
|
|
362
|
+
|
|
363
|
+
with TesmartSwitch(TcpTransport("192.168.1.50")) as sw:
|
|
364
|
+
print(sw.get_active_input())
|
|
365
|
+
sw.set_input(4)
|
|
366
|
+
sw.set_buzzer(False)
|
|
367
|
+
sw.set_led_timeout(LedTimeout.SECONDS_30)
|
|
368
|
+
sw.set_auto_detect(True)
|
|
369
|
+
print(sw.read_status())
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
`SerialTransport("/dev/tty.usbserial-xxx")` is the RS232 equivalent and imports `pyserial`.
|
|
373
|
+
|
|
374
|
+
## Layout
|
|
375
|
+
|
|
376
|
+
| Path | Responsibility |
|
|
377
|
+
| --- | --- |
|
|
378
|
+
| `tesmart/protocol.py` | Hex and ASCII encode/decode, no I/O |
|
|
379
|
+
| `tesmart/transport.py` | TCP and serial transports |
|
|
380
|
+
| `tesmart/switch.py` | Device operations, receive buffer, command pacing |
|
|
381
|
+
| `tesmart/config.py` | Flag, env file, environment variable, default |
|
|
382
|
+
| `tesmart/peek.py` | Peek: flip to an input, wait, flip back |
|
|
383
|
+
| `tesmart/listener.py` | Stdin and raw-TCP command listener |
|
|
384
|
+
| `tesmart/web.py` | HTTP routes |
|
|
385
|
+
| `tesmart/panel.py` | `/panel` and its `/api` routes, only with `--panel` |
|
|
386
|
+
| `tesmart/static/` | Panel HTML, CSS, and JS |
|
|
387
|
+
| `tesmart/cli.py` | `tesmartctl` argument parsing and output |
|
|
388
|
+
| `tesmart/examples.py` | Worked examples shown by `--help` and `tesmartctl examples` |
|
|
389
|
+
| `Docs/protocol.md` | Wire protocol |
|
|
390
|
+
| `Docs/listener.md` | Line protocol and HTTP routes |
|
|
391
|
+
| `Docs/panel.md` | Browser control panel |
|
|
392
|
+
| `Docs/embed.md` | Input buttons on another page |
|
|
393
|
+
| `examples/buttons/` | Sample page of input links, no script or framework |
|
|
394
|
+
| `Docs/images/` | Screenshots used in the documentation |
|
|
395
|
+
| `LICENSE` | MIT License |
|
|
396
|
+
|
|
397
|
+
## License
|
|
398
|
+
|
|
399
|
+
[MIT](LICENSE). This software is provided as is, without warranty. Changing the switch's network address can make it unreachable over the LAN; that risk, and the absence of any liability for it, is spelled out in [LAN address](#lan-address) and in the panel before a write is accepted.
|