Die Antwort gab bisher nur die gespeicherte SSID aus. Wurde eine Lampe nie per REST onboardet, ist die leer, und die Lampe laeuft in Wirklichkeit auf den einkompilierten NINLIGHT_WIFI_SSID/-PASSWORD (siehe app_main.c) - GET system/settings suggerierte damit "kein WLAN konfiguriert", obwohl die Lampe zuverlaessig verbunden ist, und widersprach scheinbar system/info. Additiv, ohne die Bedeutung von "ssid" zu aendern: wifi.source ist jetzt "stored" oder "compiled". Spec (§7.2) und bruno/ninlight.yml dokumentieren das Feld, ein neuer Hosttest deckt den compiled-Fall ab. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
413 lines
11 KiB
YAML
413 lines
11 KiB
YAML
opencollection: 1.0.0
|
|
info:
|
|
name: ninlight
|
|
config:
|
|
environments:
|
|
- name: EVK (mDNS)
|
|
variables:
|
|
- name: device_address
|
|
value: ninlight-681f.local
|
|
- name: device_port
|
|
value: '3333'
|
|
- name: device_token
|
|
value: aabbccddeeff0011223344
|
|
- name: ota_url
|
|
value: http://192.168.1.12:8000/ninlight_evk_ota.img
|
|
- name: Onboarding-AP
|
|
variables:
|
|
- name: device_address
|
|
value: 192.168.4.1
|
|
- name: device_port
|
|
value: '3333'
|
|
- name: device_token
|
|
value: aabbccddeeff0011223344
|
|
- name: ota_url
|
|
value: http://192.168.1.12:8000/ninlight_evk_ota.img
|
|
items:
|
|
- info:
|
|
name: Device
|
|
type: folder
|
|
seq: 1
|
|
items:
|
|
- info:
|
|
name: Get State
|
|
type: http
|
|
seq: 1
|
|
http:
|
|
method: GET
|
|
url: '{{device_address}}:{{device_port}}/api/v1/device/state'
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Power On
|
|
type: http
|
|
seq: 2
|
|
http:
|
|
method: POST
|
|
url: '{{device_address}}:{{device_port}}/api/v1/device/state'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"on": true
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Power Off
|
|
type: http
|
|
seq: 3
|
|
http:
|
|
method: POST
|
|
url: '{{device_address}}:{{device_port}}/api/v1/device/state'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"on": false
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Brightness 50
|
|
type: http
|
|
seq: 4
|
|
http:
|
|
method: POST
|
|
url: '{{device_address}}:{{device_port}}/api/v1/device/state'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"brightness": 50
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Color Red
|
|
type: http
|
|
seq: 5
|
|
http:
|
|
method: POST
|
|
url: '{{device_address}}:{{device_port}}/api/v1/device/state'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"color": {
|
|
"r": 255,
|
|
"g": 0,
|
|
"b": 0
|
|
}
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Color Temp 2700
|
|
type: http
|
|
seq: 6
|
|
http:
|
|
method: POST
|
|
url: '{{device_address}}:{{device_port}}/api/v1/device/state'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"color_temp": 2700
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Fade to 100 % in 3 s
|
|
type: http
|
|
seq: 7
|
|
http:
|
|
method: POST
|
|
url: '{{device_address}}:{{device_port}}/api/v1/device/state'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"on": true,
|
|
"brightness": 100,
|
|
"transition": 3000
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Power-On Behaviour
|
|
type: http
|
|
seq: 8
|
|
http:
|
|
method: POST
|
|
url: '{{device_address}}:{{device_port}}/api/v1/device/state'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"power_on_behaviour": "last"
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Fade Times
|
|
type: http
|
|
seq: 9
|
|
http:
|
|
method: POST
|
|
url: '{{device_address}}:{{device_port}}/api/v1/device/state'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"fade_in": 500,
|
|
"fade_out": 800
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: System
|
|
type: folder
|
|
seq: 2
|
|
items:
|
|
- info:
|
|
name: Get System Info
|
|
type: http
|
|
seq: 1
|
|
http:
|
|
method: GET
|
|
url: '{{device_address}}:{{device_port}}/api/v1/system/info'
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
docs: |-
|
|
Enthält `last_ota_error`: `null`, solange kein Update fehlgeschlagen ist, sonst einer von
|
|
`download`, `crc`, `trailer`, `device_mismatch`, `hash`, `busy` (`busy` heißt: es läuft bereits
|
|
ein Update). Kein `reset_reason` mehr im Feld-Satz.
|
|
- info:
|
|
name: Get System Settings
|
|
type: http
|
|
seq: 2
|
|
http:
|
|
method: GET
|
|
url: '{{device_address}}:{{device_port}}/api/v1/system/settings'
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
docs: |-
|
|
`wifi.source` ist `"stored"`, solange ein per PUT onboardetes WLAN gespeichert ist,
|
|
sonst `"compiled"` - dann laeuft die Lampe auf den einkompilierten
|
|
NINLIGHT_WIFI_SSID/-PASSWORD, `wifi.ssid` ist leer, und `GET system/info` kann trotzdem
|
|
eine verbundene SSID zeigen.
|
|
- info:
|
|
name: Set WiFi
|
|
type: http
|
|
seq: 3
|
|
http:
|
|
method: PUT
|
|
url: '{{device_address}}:{{device_port}}/api/v1/system/settings'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"type": "wifi",
|
|
"ssid": "MeinWLAN",
|
|
"password": "geheim123"
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Set Device Name
|
|
type: http
|
|
seq: 4
|
|
http:
|
|
method: PUT
|
|
url: '{{device_address}}:{{device_port}}/api/v1/system/settings'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"type": "device_name",
|
|
"name": "Wohnzimmer"
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Set Token
|
|
type: http
|
|
seq: 5
|
|
http:
|
|
method: PUT
|
|
url: '{{device_address}}:{{device_port}}/api/v1/system/settings'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"type": "token",
|
|
"token": "neues-token-123"
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Require Auth for All
|
|
type: http
|
|
seq: 6
|
|
http:
|
|
method: PUT
|
|
url: '{{device_address}}:{{device_port}}/api/v1/system/settings'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"type": "auth",
|
|
"all": true
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Commands
|
|
type: folder
|
|
seq: 7
|
|
items:
|
|
- info:
|
|
name: Ping
|
|
type: http
|
|
seq: 1
|
|
http:
|
|
method: PUT
|
|
url: '{{device_address}}:{{device_port}}/api/v1/system/command'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"command": {
|
|
"type": "ping"
|
|
}
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Reboot
|
|
type: http
|
|
seq: 2
|
|
http:
|
|
method: PUT
|
|
url: '{{device_address}}:{{device_port}}/api/v1/system/command'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"command": {
|
|
"type": "reboot"
|
|
}
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Factory Reset
|
|
type: http
|
|
seq: 3
|
|
http:
|
|
method: PUT
|
|
url: '{{device_address}}:{{device_port}}/api/v1/system/command'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"command": {
|
|
"type": "factory_reset"
|
|
}
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
- info:
|
|
name: Firmware Update
|
|
type: http
|
|
seq: 4
|
|
http:
|
|
method: PUT
|
|
url: '{{device_address}}:{{device_port}}/api/v1/system/command'
|
|
body:
|
|
type: json
|
|
data: |-
|
|
{
|
|
"command": {
|
|
"type": "fw_update",
|
|
"url": "{{ota_url}}"
|
|
}
|
|
}
|
|
settings:
|
|
encodeUrl: true
|
|
timeout: 0
|
|
followRedirects: true
|
|
maxRedirects: 5
|
|
docs: |-
|
|
Erfolg: `202 {"status":"updating"}`, Download startet im Hintergrund. Ungültige URL (kein
|
|
`http://`-Präfix, zu kurz/lang): `400`. Läuft bereits ein Update oder scheitert der Start
|
|
sonstwie: `409` mit dem Grund im Body (gleicher Wert wie `last_ota_error`, z.B. `"busy"`).
|
|
request:
|
|
headers:
|
|
- name: Authorization
|
|
value: '{{device_token}}'
|
|
bundled: true
|
|
extensions:
|
|
bruno:
|
|
ignore:
|
|
- node_modules
|
|
- .git
|
|
presets:
|
|
requestType: http
|
|
requestUrl: '{{device_address}}:{{device_port}}/api/v1/'
|