Latest implementation in v9.97 firmware
There is a HTTP server running on the Tailwind iQ3 Garage Door Opener so we can send HTTP requests to the specific URLs to write or send commands or read the status from the HTTP server.(Currently, local network control is under beta test stage. More security features would be involved in later versions.)
In order to get it work, we need the following steps:
1.Find devices in the local network
2.Read device basic information.(Model ID, FW version )
3. Read device status or send control commands to the device.
In the current solution, we can use mDNS to search for local devices.
We can also find the information about the device.
mDNS TXT Record:
Vendor | tailwind | company name |
---|---|---|
HW ver | V1.3 | Hardware version |
SW ver | 9.97 | Firmware version |
device_id | 30_ae_a4_80_18_80 | Device ID |
HomeKit | 1 | 1: support HomeKit 0: no HomeKit |
Product | iQ3 | Product model type |
dns-sd -Z
_http._tcp PTR TW-WebServer._http._tcp
TW-WebServer._http._tcp SRV 0 0 80 tailwind-30aea4801880.local. ; Replace with unicast FQDN of target host
TW-WebServer._http._tcp TXT "device_id=_30_ae_a4_80_18_80_" "Secure code=1234" "Homekit=0" "SW ver=9.95" "HW ver=V1.0" "vendor=tailwind"
dns-sd -G v4 tailwind-30aea4801880.local
DATE: ---Sat 15 May 2021---
11:35:27.080 ...STARTING...
Timestamp A/R Flags if Hostname Address TTL
11:35:27.294 Add 2 4 tailwind-30aea4801880.local. 192.168.3.7 120
We can find the device IP address and MAC in the Tailwind App, then build the device address like this:
MAC: 30:ae:a4:80:18:80
Device Address in local network: tailwind-30aea4801880.local
IP Address: 192.168.3.7
Examples:
MAC | dev_id | mDNS address |
---|---|---|
AA:BB:CC:DD:EE:FF | _aa_bb_cc_dd_ee_ff_ | tailwind-aabbccddeeff.local |
AA:0B:0C:D0:E0:F0 | _aa_b_c_d0_e0_f0_ | tailwind-aa0b0cd0e0f0.local |
0A:BB:CC:0D:EE:DD | _a_bb_cc_d_ee_dd_ | tailwind-0abbcc0deedd.local |
After this step, we will get the device address in 2 style:
IP Address, e.g. 192.168.3.7 (this might be faster, but the IP address could also change)
Local link domain, e.g. tailwind-xxxxxxxxxxxx.local
In the latest version of device firmware(v9.96 and above), we've added a Token in the local control interface for security reasons.
The TOKEN is a 6-digit string(local control key) generated via the Tailwind server
Steps to find and update Local Control Key:
a.Login on Tailwind Web dashboard (web.gotailwind.com)
b.Find the Local Control Key page and get the code.
c. If the key is leaked, you may create a new one.(make sure device is online when generating a new password)
After getting the KEY, we need to put the key into the HTTP request Header.
Take curl as example,
curl http://tailwind-30aea4801880.local/status -H "TOKEN:869769"
The raw content of the request would be like this, a TOKEN filed will be added into Request Headers.
Brief | Get device status, this is a general command for different types of devices. |
---|---|
HTTP URL | http://tailwind-30aea4801880.local/json |
HTTP Method | POST |
JSON Data | { "version": "0.1", "data": { "type": "get", "name": "dev_st" } } |
Response | iQ3 device response: {"result": "OK","product": "iQ3","dev_id": "30_ae_a4_80_18_80","proto_ver": "0.2","door_num": 3,"night_mode_en": 0,"fw_ver": “10.10","led_brightness": 10, "router_rssi": -31, "server_monitor": false, "data": {"door1": {"index": 0,"status": "open","lockup": 0,"disabled": 0},"door2": {"index": 1,"status": "close","lockup": 0,"disabled": 0},"door3": {"index": 2,"status": "close","lockup": 0,"disabled": 0}}} Light device response: {"result": "OK","product": "light","dev_id": "30_ae_a4_80_18_80","proto_ver": "0.1","pwm_channel": 1,"fw_ver": "9.03","data": {"mode":"auto","light": {"power": 29,"frequency": 5000 },"radar": {"distance": 15,"lux": 1000,"delay": 300}}} Fail: {"result": "Fail","info":"xxxxxx"} |
Device Action | Return current device status in JSON format. |
CURL example | curl http://tailwind-30aea4801880.local/json -d '{"version": "0.1", "data": {"type": "get", "name": "dev_st"}}' -H "TOKEN:869769" |
Key | Value | Example | Brief |
---|---|---|---|
version | string | "0.1" | JSON protocol version number, 0.1 for current version, reserved for future useage |
data | JSON object | ||
type | string | "get" | get: read set: write |
name | string | "dev_st" | Read device status |
When device status changes, it can send a report or notification to an HTTP or UDP server in the local network.(Check 3.1 for the status report data format)
Use this API to set the notification URL.(HTTPS not supported yet.)
Brief | Set Door Status Report Address |
---|---|
HTTP URL | http://tailwind-30aea4801880.local/json |
HTTP Method | POST |
JSON Data | { "product": "iQ3", "version": "0.1" "data": { "type": "set", "name": "notify_url", "value": { "url": "http://192.168.1.1:8888/report”, "proto": "http", "enable": 1, } } } |
Response | {"result": "OK"} {"result": "Fail", "Info": "xxxxxx"} |
Device Action | Set how the device should report door status when door status changed. |
HTTP server and UDP server can either be supported now. | |
CURL example | HTTP: curl http://tailwind-30aea4801880.local/json -d '{"product": "iQ3", "version": "0.1", "data": {"type": "set", "name": "notify_url", "value": {"enable": 1,"proto":"http", "url":"http://192.168.3.61:8888/test"}}}' -H "TOKEN:869769" UDP: curl http://tailwind-30aea4801880.local/json -d '{"product": "iQ3", "version": "0.1", "data": {"type": "set", "name": "notify_url", "value": {"enable": 1,"proto":"udp", "url":"192.168.3.61:8888"}}}' -H "TOKEN:869769" |
Key | Value | Example | Brief |
---|---|---|---|
product | string | "iQ3" | iQ3:Garage door opener device Light: Light Controller device |
version | string | "0.1" | JSON protocol version number, 0.1 for current version, reserved for future useage |
data | JSON object | ||
type | string | "set" | get: read set: write |
name | string | "notify_url" | Set device notification method |
value | JSON object | ||
url | string | HTTP: "http://192.168.1.1:8888/report" or UDP: "192.168.1.1:6888" |
UDP or HTTP URL for device to report its status. The length should be less than 200 bytes. |
proto | string | "http" or "udp" | http: send status report in HTTP udp: send status report in UDP |
enable | integer | 1 | 1: enable status report 0: disable status report |
The payload of a device notification message would like this:
The JSON object with key named 'notify' is the notification event, it indicates with door's status has changed.
Others are the current status of the device
{"result": "OK","product": "iQ3","dev_id": "30_ae_a4_80_18_80","proto_ver": "0.1","door_num": 3,"night_mode_en": 1,"fw_ver": "10.10","led_brightness": 10,"data": {"door1": {"index": 0,"status": "close","lockup": 0,"disabled": 0}
,"door2": {"index": 1,"status": "open","lockup": 0,"disabled": 0}
,"door3": {"index": 2,"status": "close","lockup": 0,"disabled": 0}
},
"notify": {"door_idx": 2,"event": "open"}
}
Currently supported events are:
Event | Description |
---|---|
open | Door opened |
close | Door closed |
lock | Door lockup |
enable | Door enabled |
disable | Door disabled |
reboot | Device rebooted after receiving a reboot command |
Brief | Open / Close Door Command |
---|---|
HTTP URL | http://tailwind-30aea4801880.local/json |
HTTP Method | POST |
JSON Data | { "product": "iQ3", "version": "0.1", "data": { "type": "set", "name": "door_op", "value": { "door_idx": 1, "cmd": "open", } } } |
Response | {"result": "OK"} {"result": "Fail","info":"xxxxxx"} |
Device Action | For open/close door command, if door is currently closed/open, trigger IO pulse to open/close the door. |
CURL example | open door: curl http://tailwind-30aea4801880.local/json -d '{"product": "iQ3", "version": "0.1", "data": {"type": "set", "name": "door_op","value":{"door_idx":1, "cmd":"open"}}}' -H "TOKEN:869769" close door: curl http://tailwind-30aea4801880.local/json -d '{"product": "iQ3", "version": "0.1", "data": {"type": "set", "name": "door_op","value":{"door_idx":1, "cmd":"close"}}}' -H "TOKEN:869769" partial open door: curl http://tailwind-30aea4801880.local/json -d '{"product": "iQ3", "version": "0.1", "data": {"type": "set", "name": "door_op","value":{"door_idx":1, "cmd":"open", "partial_time": 15000}}}' -H "TOKEN:869769" |
Key | Value | Example | Brief |
---|---|---|---|
product | string | "iQ3" | iQ3:Garage door opener device Light: Light Controller device |
version | string | "0.1" | JSON protocol version number, 0.1 for current version, reserved for future useage |
data | JSON object | ||
type | string | "set" | get: read set: write |
name | string | "door_op" | Door Open/Close Operation |
value | JSON object | ||
door_idx | integer | 1 | 0: door 1 1: door 2 2: door 3 |
cmd | string | "open" | "open”: open door "close”: close door |
partial_time | integer | 15000 | optional. Door partial open time (ms). Only work with open door command. |
Note: if door status changed due to the command, a FCM notification will be sent to the phone app with the following format:
Local Network Control opened/closed xxx(Devcie Name) yyy(Door Name) on ddd(Date) at ttt(Time)
Now we can set the brightness of Green status LED that indicates the device is online.
Brief | Set Door Status LED Brightness |
---|---|
HTTP URL | http://tailwind-30aea4801880.local/json |
HTTP Method | POST |
JSON Data | { "product": "iQ3", "version": "0.1" "data": { "type": "set", "name": "status_led", "value": { "brightness": 100 } } } |
Response | {"result": "OK"} {"result": "Fail", "Info": "xxxxxx"} |
Device Action | Device will set the Green LED brightness after it gets online successfully. |
CURL example | curl http://tailwind-30aea4801880.local/json -d '{"product": "iQ3", "version": "0.1", "data": {"type": "set", "name": "status_led", "value": {"brightness": 100}}}' -H "TOKEN:869769" |
Key | Value | Example | Brief |
---|---|---|---|
product | string | "iQ3" | iQ3:Garage door opener device Light: Light Controller device |
version | string | "0.1" | JSON protocol version number, 0.1 for current version, reserved for future useage |
data | JSON object | ||
type | string | "set" | get: read set: write |
name | string | "status_led" | Set status LED brightness |
value | JSON object | ||
brightness | integer | 100 | Brightness of the Green LED.ranges from 0 to 100. |
Use this to set different parameters of a Light Controller device.
Brief | Configure a Light Controller Device |
---|---|
HTTP URL | http://tailwind-30aea4801880.local/json |
HTTP Method | POST |
JSON Data | { "product":"light", "version":"0.1", "data":{ "type":"set", "name":"dev_op", "value":{ "power":50, "delay":300, "lux":1000, "distance":15, "mode":"auto" } } } |
Response | {"result": "OK"} {"result": "Fail", "Info": "xxxxxx"} |
Device Action | Device will parse each give parameters and apply those given parameters. |
CURL example | curl http://tailwind-30aea4801880.local/json -d '{"product":"light","version":"0.1", "data":{"type":"set","name":"dev_op","value":{"power":50,"delay":300,"lux":1000,"distance":15,"mode":"auto"}}}' -H "TOKEN:869769" curl http://tailwind-30aea4801880.local/json -d '{"product":"light","version":"0.1", "data":{"type":"set","name":"dev_op","value":{"power":50, "mode":"manual"}}}' -H "TOKEN:869769" |
Key | Value | Example | Brief |
---|---|---|---|
product | string | "light" | light: Light Controller device |
version | string | "0.1" | JSON protocol version number, 0.1 for current version, reserved for future useage |
data | JSON object | ||
type | string | "set" | get: read set: write |
name | string | "dev_op" | Set Light Controller Parameters |
value | JSON object | ||
power | integer | 50 | Set brightness of the Lightranges from 0 to 100.(optional). |
delay | integer | 300 | when motion detected, how long the light would be kept on, count in seconds.(0-65535)(optional) |
lux | integer | 1000 | when the ambient light is weaker than this level, radar sensor starts to work. ( 0 ~ 65535 Lux)(optional) |
distance | integer | 15 | sensitivity level of the radar sensor, ranges from 0 to 15)(optional) |
mode | string | "auto" | "manual": user sets light brightness, the light stays with the brightness no matter how the radar sensor reads. "auto": user sets radar sensor parameters, the light will be controlled by the radar sensor signal(optional) |
Use this to identify an iQ3 device. The selected device would blink the white light three times.
Brief | To identify a Device |
---|---|
HTTP URL | http://tailwind-30aea4801880.local/json |
HTTP Method | POST |
JSON Data | { "product": "iQ3", "version": "0.2" "data": { "type": "set", "name": “identify" } } |
Response | {"result": "OK"} {"result": "Fail", "Info": "xxxxxx"} |
Device Action | Device will blink the white led thress times. |
CURL example | curl http://tailwind-30aea4801880.local/json -d '{"product": "iQ3", "version": "0.2", "data": {"type": "set", "name": "identify"}}' -H "TOKEN:869769" |
Key | Value | Example | Brief |
---|---|---|---|
product | string | "iQ3" | iQ3:Garage door opener device Light: Light Controller device |
version | string | "0.2" | JSON protocol version number, 0.2 for current version, reserved for future useage |
data | JSON object | ||
type | string | "set" | get: read set: write |
name | string | "identify" | To identify the device |
Use this to reboot an iQ3 device.
Brief | To identify a Device |
---|---|
HTTP URL | http://tailwind-30aea4801880.local/json |
HTTP Method | POST |
JSON Data | { "product": "iQ3", "version": "0.2" "data": { "type": "set", "name": "reboot" } } |
Response | {"result": "OK"} {"result": "Fail", "Info": "xxxxxx"} |
Device Action | Device will reboot in about 2 seconds. |
CURL example | curl http://tailwind-30aea4801880.local/json -d '{"product": "iQ3", "version": "0.2", "data": {"type": "set", "name": "reboot"}}' -H "TOKEN:869769" |
Key | Value | Example | Brief |
---|---|---|---|
product | string | "iQ3" | iQ3:Garage door opener device Light: Light Controller device |
version | string | "0.2" | JSON protocol version number, 0.2 for current version, reserved for future useage |
data | JSON object | ||
type | string | "set" | get: read set: write |
name | string | "reboot" | To reboot the device |
Use this to enable or disable server connection monitoring task on an iQ3 device.
For most cases with internet access, the device would connect to MQTT server to keep remote services available. Sometimes unexpected errors might occur with the internet, which could cause the device lose connection with MQTT server, the device would try to cure the connection by rebooting itself automatically.
If users want to use iQ3 in a local network without internet access, this API can be use to disable the server connection monitoring feature, so the device would never reboot itself even if there is no internet access.
Brief | To identify a Device |
---|---|
HTTP URL | http://tailwind-30aea4801880.local/json |
HTTP Method | POST |
JSON Data | { "product": "iQ3", "version": "0.2" "data": { "type": "set", "name": "server_monitor", "value": { "enable": true } } } |
Response | {"result": "OK"} {"result": "Fail", "Info": "xxxxxx"} |
Device Action | Enable or disable server connection monitoring on device |
CURL example | curl http://tailwind-30aea4801880.local/json -d '{"product": "iQ3", "version": "0.2", "data": {"type": "set", "name": "server_monitor", "value": {"enable": true}}}' -H "TOKEN:869769" |
Key | Value | Example | Brief |
---|---|---|---|
product | string | "iQ3" | iQ3:Garage door opener device Light: Light Controller device |
version | string | "0.2" | JSON protocol version number, 0.2 for current version, reserved for future useage |
data | JSON object | ||
type | string | "set" | get: read set: write |
name | string | "server_monitor" | Enable or disable server connection monitoring |
value | JSON object | ||
enable | bool | true (or flase) | enable (or disable) server connection monitoring. |