@switchbot/openapi-cli 1.0.0 → 1.1.0
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.
- package/LICENSE +21 -21
- package/README.md +376 -278
- package/dist/commands/completion.js +228 -228
- package/dist/commands/devices.js +163 -128
- package/dist/commands/devices.js.map +1 -1
- package/dist/commands/webhook.js +24 -24
- package/dist/devices/cache.d.ts +25 -0
- package/dist/devices/cache.js +74 -0
- package/dist/devices/cache.js.map +1 -0
- package/dist/index.js +38 -38
- package/package.json +62 -62
package/README.md
CHANGED
|
@@ -1,278 +1,376 @@
|
|
|
1
|
-
# switchbot
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
switchbot
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
#
|
|
95
|
-
switchbot devices
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
switchbot
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
`
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
#
|
|
165
|
-
switchbot
|
|
166
|
-
switchbot
|
|
167
|
-
|
|
168
|
-
#
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
#
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
#
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
#
|
|
187
|
-
switchbot
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
```
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
|
206
|
-
|
|
|
207
|
-
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
|
212
|
-
|
|
|
213
|
-
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
#
|
|
239
|
-
switchbot
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
1
|
+
# @switchbot/openapi-cli
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@switchbot/openapi-cli)
|
|
4
|
+
[](https://www.npmjs.com/package/@switchbot/openapi-cli)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
[](https://nodejs.org)
|
|
7
|
+
[](https://github.com/OpenWonderLabs/switchbot-openapi-cli/actions/workflows/ci.yml)
|
|
8
|
+
|
|
9
|
+
Command-line interface for the [SwitchBot API v1.1](https://github.com/OpenWonderLabs/SwitchBotAPI).
|
|
10
|
+
List devices, query live status, send control commands, run scenes, and manage webhooks — all from your terminal or shell scripts.
|
|
11
|
+
|
|
12
|
+
- **npm package:** [`@switchbot/openapi-cli`](https://www.npmjs.com/package/@switchbot/openapi-cli)
|
|
13
|
+
- **Source code:** [github.com/OpenWonderLabs/switchbot-openapi-cli](https://github.com/OpenWonderLabs/switchbot-openapi-cli)
|
|
14
|
+
- **Issues / feature requests:** [GitHub Issues](https://github.com/OpenWonderLabs/switchbot-openapi-cli/issues)
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Table of contents
|
|
19
|
+
|
|
20
|
+
- [Features](#features)
|
|
21
|
+
- [Requirements](#requirements)
|
|
22
|
+
- [Installation](#installation)
|
|
23
|
+
- [Quick start](#quick-start)
|
|
24
|
+
- [Credentials](#credentials)
|
|
25
|
+
- [Global options](#global-options)
|
|
26
|
+
- [Commands](#commands)
|
|
27
|
+
- [`config`](#config--credential-management)
|
|
28
|
+
- [`devices`](#devices--list-status-control)
|
|
29
|
+
- [`scenes`](#scenes--run-manual-scenes)
|
|
30
|
+
- [`webhook`](#webhook--receive-device-events-over-http)
|
|
31
|
+
- [`completion`](#completion--shell-tab-completion)
|
|
32
|
+
- [Output modes](#output-modes)
|
|
33
|
+
- [Exit codes & error codes](#exit-codes--error-codes)
|
|
34
|
+
- [Environment variables](#environment-variables)
|
|
35
|
+
- [Scripting examples](#scripting-examples)
|
|
36
|
+
- [Development](#development)
|
|
37
|
+
- [Contributing](#contributing)
|
|
38
|
+
- [License](#license)
|
|
39
|
+
- [References](#references)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Features
|
|
44
|
+
|
|
45
|
+
- 🔌 **Complete API coverage** — every `/v1.1` endpoint (devices, scenes, webhooks)
|
|
46
|
+
- 📚 **Built-in catalog** — offline reference for every device type's supported commands, parameter formats, and status fields (no API call needed)
|
|
47
|
+
- 🎨 **Dual output modes** — colorized tables by default; `--json` passthrough for `jq` and scripting
|
|
48
|
+
- 🔐 **Secure credentials** — HMAC-SHA256 signed requests; config file written with `0600`; env-var override for CI
|
|
49
|
+
- 🔍 **Dry-run mode** — preview every mutating request before it hits the API
|
|
50
|
+
- 🧪 **Fully tested** — 282 Vitest tests, mocked axios, zero network in CI
|
|
51
|
+
- ⚡ **Shell completion** — Bash / Zsh / Fish / PowerShell
|
|
52
|
+
|
|
53
|
+
## Requirements
|
|
54
|
+
|
|
55
|
+
- **Node.js ≥ 18**
|
|
56
|
+
- A SwitchBot account with **Developer Options** enabled (see [Credentials](#credentials))
|
|
57
|
+
|
|
58
|
+
## Installation
|
|
59
|
+
|
|
60
|
+
### From npm (recommended)
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm install -g @switchbot/openapi-cli
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
This adds the `switchbot` binary to your `$PATH`.
|
|
67
|
+
|
|
68
|
+
### From source
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
git clone https://github.com/OpenWonderLabs/switchbot-openapi-cli.git
|
|
72
|
+
cd switchbot-openapi-cli
|
|
73
|
+
npm install
|
|
74
|
+
npm run build
|
|
75
|
+
npm link # optional — expose `switchbot` globally
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Verify:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
switchbot --version
|
|
82
|
+
switchbot --help
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Quick start
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# 1. Save your credentials (one-time)
|
|
89
|
+
switchbot config set-token <token> <secret>
|
|
90
|
+
|
|
91
|
+
# 2. List every device on your account
|
|
92
|
+
switchbot devices list
|
|
93
|
+
|
|
94
|
+
# 3. Control a device
|
|
95
|
+
switchbot devices command <deviceId> turnOn
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Credentials
|
|
99
|
+
|
|
100
|
+
The CLI reads credentials in this order (first match wins):
|
|
101
|
+
|
|
102
|
+
1. **Environment variables** — `SWITCHBOT_TOKEN` and `SWITCHBOT_SECRET`
|
|
103
|
+
2. **Config file** — `~/.switchbot/config.json` (written by `config set-token`, mode `0600`)
|
|
104
|
+
|
|
105
|
+
Obtain the token and secret from the SwitchBot mobile app:
|
|
106
|
+
**Profile → Preferences → Developer Options → Get Token**.
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# One-time setup (writes ~/.switchbot/config.json)
|
|
110
|
+
switchbot config set-token <token> <secret>
|
|
111
|
+
|
|
112
|
+
# Or export environment variables (e.g. in CI)
|
|
113
|
+
export SWITCHBOT_TOKEN=...
|
|
114
|
+
export SWITCHBOT_SECRET=...
|
|
115
|
+
|
|
116
|
+
# Confirm which source is active and see the masked secret
|
|
117
|
+
switchbot config show
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Global options
|
|
121
|
+
|
|
122
|
+
| Option | Description |
|
|
123
|
+
| ------------------- | ------------------------------------------------------------------------ |
|
|
124
|
+
| `--json` | Print the raw JSON response instead of a formatted table |
|
|
125
|
+
| `-v`, `--verbose` | Log HTTP request/response details to stderr |
|
|
126
|
+
| `--dry-run` | Print mutating requests (POST/PUT/DELETE) without sending them |
|
|
127
|
+
| `--timeout <ms>` | HTTP request timeout in milliseconds (default: `30000`) |
|
|
128
|
+
| `--config <path>` | Override credential file location (default: `~/.switchbot/config.json`) |
|
|
129
|
+
| `-V`, `--version` | Print the CLI version |
|
|
130
|
+
| `-h`, `--help` | Show help for any command or subcommand |
|
|
131
|
+
|
|
132
|
+
Every subcommand supports `--help`, and most include a parameter-format reference and examples.
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
switchbot --help
|
|
136
|
+
switchbot devices command --help
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### `--dry-run`
|
|
140
|
+
|
|
141
|
+
Intercepts every non-GET request: the CLI prints the URL/body it would have
|
|
142
|
+
sent, then exits `0` without contacting the API. `GET` requests (list, status,
|
|
143
|
+
query) are still executed so you can preview the state involved.
|
|
144
|
+
|
|
145
|
+
```bash
|
|
146
|
+
switchbot devices command ABC123 turnOn --dry-run
|
|
147
|
+
# [dry-run] Would POST https://api.switch-bot.com/v1.1/devices/ABC123/commands
|
|
148
|
+
# [dry-run] body: {"command":"turnOn","parameter":"default","commandType":"command"}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## Commands
|
|
152
|
+
|
|
153
|
+
### `config` — credential management
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
switchbot config set-token <token> <secret> # Save to ~/.switchbot/config.json
|
|
157
|
+
switchbot config show # Print current source + masked secret
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### `devices` — list, status, control
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
# List all physical devices and IR remote devices
|
|
164
|
+
# Columns: deviceId, deviceName, type, controlType, family, roomID, room, hub, cloud
|
|
165
|
+
switchbot devices list
|
|
166
|
+
switchbot devices list --json | jq '.deviceList[].deviceId'
|
|
167
|
+
|
|
168
|
+
# Filter by family / room (family & room info requires the 'src: OpenClaw'
|
|
169
|
+
# header, which this CLI sends on every request)
|
|
170
|
+
switchbot devices list --json | jq '.deviceList[] | select(.familyName == "Home")'
|
|
171
|
+
switchbot devices list --json | jq '[.deviceList[], .infraredRemoteList[]] | group_by(.familyName)'
|
|
172
|
+
|
|
173
|
+
# Query real-time status of a physical device
|
|
174
|
+
switchbot devices status <deviceId>
|
|
175
|
+
switchbot devices status <deviceId> --json
|
|
176
|
+
|
|
177
|
+
# Send a control command
|
|
178
|
+
switchbot devices command <deviceId> <cmd> [parameter] [--type command|customize]
|
|
179
|
+
|
|
180
|
+
# Describe a specific device (1 API call): metadata + supported commands + status fields
|
|
181
|
+
switchbot devices describe <deviceId>
|
|
182
|
+
switchbot devices describe <deviceId> --json
|
|
183
|
+
|
|
184
|
+
# Discover what's supported (offline reference, no API call)
|
|
185
|
+
switchbot devices types # List all device types + IR remote types
|
|
186
|
+
switchbot devices commands <type> # Show commands, parameter formats, and status fields
|
|
187
|
+
switchbot devices commands Bot
|
|
188
|
+
switchbot devices commands "Smart Lock"
|
|
189
|
+
switchbot devices commands curtain # Case-insensitive, substring match
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
#### Parameter formats
|
|
193
|
+
|
|
194
|
+
`parameter` is optional — omit it for commands like `turnOn`/`turnOff` (auto-defaults to `"default"`).
|
|
195
|
+
Numeric-only and JSON-object parameters are auto-parsed; strings with colons / commas / semicolons pass through as-is.
|
|
196
|
+
|
|
197
|
+
For the exact commands and parameter formats a specific device supports, query the built-in catalog:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
switchbot devices commands <type> # e.g. Bot, Curtain, "Smart Lock", "Robot Vacuum Cleaner S10"
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Generic parameter shapes (which one applies is decided by the device — see the catalog):
|
|
204
|
+
|
|
205
|
+
| Shape | Example |
|
|
206
|
+
| ------------------- | -------------------------------------------------------- |
|
|
207
|
+
| _(none)_ | `devices command <id> turnOn` |
|
|
208
|
+
| `<integer>` | `devices command <id> setBrightness 75` |
|
|
209
|
+
| `<R:G:B>` | `devices command <id> setColor "255:0:0"` |
|
|
210
|
+
| `<direction;angle>` | `devices command <id> setPosition "up;60"` |
|
|
211
|
+
| `<a,b,c,…>` | `devices command <id> setAll "26,1,3,on"` |
|
|
212
|
+
| `<json object>` | `'{"action":"sweep","param":{"fanLevel":2,"times":1}}'` |
|
|
213
|
+
| Custom IR button | `devices command <id> MyButton --type customize` |
|
|
214
|
+
|
|
215
|
+
For the complete per-device command reference, see the [SwitchBot API docs](https://github.com/OpenWonderLabs/SwitchBotAPI#send-device-control-commands).
|
|
216
|
+
|
|
217
|
+
### `scenes` — run manual scenes
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
switchbot scenes list # Columns: sceneId, sceneName
|
|
221
|
+
switchbot scenes execute <sceneId>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### `webhook` — receive device events over HTTP
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
# Register a receiver URL for events from ALL devices
|
|
228
|
+
switchbot webhook setup https://your.host/hook
|
|
229
|
+
|
|
230
|
+
# Query what is currently configured
|
|
231
|
+
switchbot webhook query
|
|
232
|
+
switchbot webhook query --details https://your.host/hook
|
|
233
|
+
|
|
234
|
+
# Enable / disable / re-submit the registered URL
|
|
235
|
+
switchbot webhook update https://your.host/hook --enable
|
|
236
|
+
switchbot webhook update https://your.host/hook --disable
|
|
237
|
+
|
|
238
|
+
# Remove the configuration
|
|
239
|
+
switchbot webhook delete https://your.host/hook
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
The CLI validates that `<url>` is an absolute `http://` or `https://` URL before calling the API. `--enable` and `--disable` are mutually exclusive.
|
|
243
|
+
|
|
244
|
+
### `completion` — shell tab-completion
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
# Bash: load on every new shell
|
|
248
|
+
echo 'source <(switchbot completion bash)' >> ~/.bashrc
|
|
249
|
+
|
|
250
|
+
# Zsh
|
|
251
|
+
echo 'source <(switchbot completion zsh)' >> ~/.zshrc
|
|
252
|
+
|
|
253
|
+
# Fish
|
|
254
|
+
switchbot completion fish > ~/.config/fish/completions/switchbot.fish
|
|
255
|
+
|
|
256
|
+
# PowerShell (profile)
|
|
257
|
+
switchbot completion powershell >> $PROFILE
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Supported shells: `bash`, `zsh`, `fish`, `powershell` (`pwsh` is accepted as an alias).
|
|
261
|
+
|
|
262
|
+
## Output modes
|
|
263
|
+
|
|
264
|
+
- **Default** — ANSI-colored tables for `list`/`status`, key-value tables for details.
|
|
265
|
+
- **`--json`** — raw JSON passthrough, ideal for `jq` and scripting.
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
switchbot devices list --json | jq '.deviceList[] | {id: .deviceId, name: .deviceName}'
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Exit codes & error codes
|
|
272
|
+
|
|
273
|
+
| Code | Meaning |
|
|
274
|
+
| ---- | ------------------------------------------------------------------------------------------------------------------------- |
|
|
275
|
+
| `0` | Success (including `--dry-run` intercept) |
|
|
276
|
+
| `1` | Runtime error — API error, network failure, missing credentials |
|
|
277
|
+
| `2` | Usage error — bad flag, missing/invalid argument, unknown subcommand, unknown device type, invalid URL, conflicting flags |
|
|
278
|
+
|
|
279
|
+
Typical errors bubble up in the form `Error: <message>` on stderr. The SwitchBot-specific error codes that get mapped to readable English messages:
|
|
280
|
+
|
|
281
|
+
| Code | Meaning |
|
|
282
|
+
| ---- | ------------------------------------------- |
|
|
283
|
+
| 151 | Device type error |
|
|
284
|
+
| 152 | Device not found |
|
|
285
|
+
| 160 | Command not supported by this device |
|
|
286
|
+
| 161 | Device offline (BLE devices need a Hub) |
|
|
287
|
+
| 171 | Hub offline |
|
|
288
|
+
| 190 | Device internal error / server busy |
|
|
289
|
+
| 401 | Authentication failed (check token/secret) |
|
|
290
|
+
| 429 | Request rate too high (10,000 req/day cap) |
|
|
291
|
+
|
|
292
|
+
## Environment variables
|
|
293
|
+
|
|
294
|
+
| Variable | Description |
|
|
295
|
+
| ------------------- | ------------------------------------------------------------------ |
|
|
296
|
+
| `SWITCHBOT_TOKEN` | API token — takes priority over the config file |
|
|
297
|
+
| `SWITCHBOT_SECRET` | API secret — takes priority over the config file |
|
|
298
|
+
| `NO_COLOR` | Disable ANSI colors in all output (automatically respected) |
|
|
299
|
+
|
|
300
|
+
## Scripting examples
|
|
301
|
+
|
|
302
|
+
```bash
|
|
303
|
+
# Turn off every Bot device
|
|
304
|
+
switchbot devices list --json \
|
|
305
|
+
| jq -r '.deviceList[] | select(.deviceType == "Bot") | .deviceId' \
|
|
306
|
+
| while read id; do switchbot devices command "$id" turnOff; done
|
|
307
|
+
|
|
308
|
+
# Dump each scene as `<id> <name>`
|
|
309
|
+
switchbot scenes list --json | jq -r '.[] | "\(.sceneId) \(.sceneName)"'
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
## Development
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
git clone https://github.com/OpenWonderLabs/switchbot-openapi-cli.git
|
|
316
|
+
cd switchbot-openapi-cli
|
|
317
|
+
npm install
|
|
318
|
+
|
|
319
|
+
npm run dev -- <args> # Run from TypeScript sources via tsx
|
|
320
|
+
npm run build # Compile to dist/
|
|
321
|
+
npm test # Run the Vitest suite (282 tests)
|
|
322
|
+
npm run test:watch # Watch mode
|
|
323
|
+
npm run test:coverage # Coverage report (v8, HTML + text)
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Project layout
|
|
327
|
+
|
|
328
|
+
```
|
|
329
|
+
src/
|
|
330
|
+
├── index.ts # Commander entry; mounts all subcommands; global flags
|
|
331
|
+
├── auth.ts # HMAC-SHA256 signature (token + t + nonce → sign)
|
|
332
|
+
├── config.ts # Credential load/save; env > file priority; --config override
|
|
333
|
+
├── api/client.ts # axios instance + request/response interceptors;
|
|
334
|
+
│ # --verbose / --dry-run / --timeout wiring
|
|
335
|
+
├── devices/catalog.ts # Static catalog powering `devices types`/`devices commands`
|
|
336
|
+
├── commands/
|
|
337
|
+
│ ├── config.ts
|
|
338
|
+
│ ├── devices.ts
|
|
339
|
+
│ ├── scenes.ts
|
|
340
|
+
│ ├── webhook.ts
|
|
341
|
+
│ └── completion.ts # `switchbot completion bash|zsh|fish|powershell`
|
|
342
|
+
└── utils/
|
|
343
|
+
├── flags.ts # Global flag readers (isVerbose / isDryRun / getTimeout / getConfigPath)
|
|
344
|
+
└── output.ts # printTable / printKeyValue / printJson / handleError
|
|
345
|
+
tests/ # Vitest suite (282 tests, mocked axios, no network)
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Release flow
|
|
349
|
+
|
|
350
|
+
Releases are cut on tag push and published to npm by GitHub Actions:
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
npm version patch # bump version + create git tag
|
|
354
|
+
git push --follow-tags
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Then on GitHub → **Releases → Draft a new release → select tag → Publish**. The `publish.yml` workflow runs tests, verifies the tag matches `package.json`, and publishes `@switchbot/openapi-cli` to npm with [provenance](https://docs.npmjs.com/generating-provenance-statements).
|
|
358
|
+
|
|
359
|
+
## Contributing
|
|
360
|
+
|
|
361
|
+
Bug reports, feature requests, and PRs are welcome.
|
|
362
|
+
|
|
363
|
+
1. Fork the repo and create a topic branch.
|
|
364
|
+
2. Keep changes small and focused; add or update Vitest cases for any behavior change.
|
|
365
|
+
3. Run `npm test` and `npm run build` locally — both must pass.
|
|
366
|
+
4. Open a pull request against `main`. CI runs on Node 18/20/22; all three must stay green.
|
|
367
|
+
|
|
368
|
+
## License
|
|
369
|
+
|
|
370
|
+
[MIT](./LICENSE) © chenliuyun
|
|
371
|
+
|
|
372
|
+
## References
|
|
373
|
+
|
|
374
|
+
- [SwitchBot API v1.1 documentation](https://github.com/OpenWonderLabs/SwitchBotAPI)
|
|
375
|
+
- Base URL: `https://api.switch-bot.com`
|
|
376
|
+
- Rate limit: 10,000 requests/day per account
|