-
-
Save andrey-yantsen/0e1e18748f5e2f4c0a21a847c6cb38f6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
meta: | |
id: timeguard | |
file-extension: tg | |
endian: le | |
bit-endian: le | |
doc: | | |
The device (in my case — NTT WIFI) communicates with a binary API located at | |
www.cloudwarm.net:9997. The device tries to establish a TCP-connection, and | |
when it fails — goes with UDP. At the time of writing the TCP port was | |
not available. I tried forcing the device to use TCP by opening the port in | |
socat and forwarding it to the UDP on the Cloudwarm server, this seemed to be | |
working just fine. | |
Legal Disclaimer | |
This information is un-official and is not endorsed or associated with | |
Timeguard Limited in any way shape or form. | |
This information has been gathered legally using the Supplymaster iOS | |
application, NTT WIFI timeswitch and tcpdump/socat. | |
This information has been captured to aid my own personal efforts to automate | |
scheduling of my NTTWIFI device. | |
The information is provided “as is”, without warranty of any kind, express or | |
implied, including but not limited to the warranties of merchantability, | |
fitness for a particular purpose and noninfringement. in no event shall the | |
authors or copyright holders be liable for any claim, damages or other | |
liability, whether in an action of contract, tort or otherwise, arising from, | |
out of or in connection with the informations or the use or mis-used or other | |
dealings in the information. | |
seq: | |
- id: hdr | |
type: header | |
- id: total_payload_size | |
type: u2 | |
- id: message_id | |
type: u4 | |
doc: | | |
Incrementing counter. Device always sends something here, starting with 1. | |
Server always sends 0xFFFFFFFF. | |
- id: payload | |
type: payload | |
- id: checksum | |
doc: | | |
CRC16 XMODEM of the payload | |
type: u2 | |
- id: ftr | |
type: footer | |
enums: | |
work_mode: | |
0: auto | |
1: always_off | |
2: always_on | |
3: holiday | |
types: | |
header: | |
seq: | |
- id: magic | |
contents: [0xfa, 0xd4] | |
payload: | |
seq: | |
- id: message_type | |
type: b4 | |
enum: message_type | |
- id: reserved1 | |
type: b4 | |
- id: is_success | |
type: b1 | |
- id: is_update_request | |
type: b1 | |
- id: unknown1 | |
type: b1 | |
doc: | | |
Almost always this bit is set to 1, except for a few rare exceptions | |
- id: is_from_server | |
type: b1 | |
- id: reserved2 | |
type: b4 | |
- id: params_size | |
type: u2 | |
- id: seq | |
type: u1 | |
- id: unknown2 | |
size: 3 | |
- id: device_mac | |
type: u4 | |
- id: params | |
type: | |
switch-on: "message_type.as<u1> + (is_from_server.as<u1> << 4) + (is_update_request.as<u1> << 5)" | |
cases: | |
32: ping_device | |
48: ping_server | |
5: schedule # response from device to schedule read requests | |
37: schedule # response from device to schedule update requests | |
53: schedule # schedule update request from server | |
21: schedule_server_read | |
29: boost_server | |
45: boost_device | |
40: work_mode_change | |
56: work_mode_change | |
11: schedule_id # response to "get current schedule" | |
27: empty # "get current schedule" command from server | |
43: schedule_id # response to "set current schedule" | |
59: schedule_id # "set current schedule" command from server | |
9: holiday # device response to "get holiday" | |
25: empty # "get holiday" command from server | |
41: holiday # "set holiday" response from device | |
57: holiday # "set holiday" command from server | |
44: advance # device response to "set advance mode" | |
60: advance # "set advance mode" command from server | |
42: schedule_id # device response to "update schedule name" | |
58: schedule_name | |
34: init # first message from the device to server with "initialization sequence" | |
50: init # server response to the first message | |
18: empty # server asks device to repeat "initialization sequence" | |
2: init # device repeats the "initialization sequence" to the server | |
size: params_size | |
instances: | |
params_object_type_id: | |
value: "message_type.as<u1> + (is_from_server.as<u1> << 4) + (is_update_request.as<u1> << 5)" | |
enums: | |
message_type: | |
0: ping | |
2: init # details are unknown | |
4: unknown | |
5: schedule | |
8: work_mode | |
9: holiday | |
10: update_schedule_name | |
11: active_schedule | |
12: advance | |
13: boost | |
empty: {} | |
init: | |
seq: | |
- id: unknown | |
size: 13 | |
advance: | |
seq: | |
- id: is_enabled | |
type: b1 | |
- id: reserved | |
type: b7 | |
schedule_name: | |
seq: | |
- id: schedule_id | |
type: u1 | |
- id: schedule_name | |
type: str | |
size: 50 | |
doc: | | |
The name is limited to 40 symbols in the app, so the size could be | |
just 40-41 bytes here, and not 50 | |
encoding: ASCII | |
schedule_id: | |
seq: | |
- id: schedule_id | |
type: u1 | |
holiday: | |
seq: | |
- id: is_active | |
type: b1 | |
- id: reserved | |
type: b7 | |
- id: unknown1 | |
size: 3 | |
- id: ts_end | |
type: u4 | |
- id: ts_start | |
type: u4 | |
boost: | |
doc: | | |
There're 2 types of Boosts: 1-hour and 2-hours. Minutes are calculated | |
starting from the midnight of the last Sunday, e.g. 7155 means Thursday | |
23:15 — 7155 div 1440 == 4, 7155 % 1440 == 1395 minutes. | |
seq: | |
- id: minutes_from_sunday | |
type: b14 | |
- id: is_1h_boost | |
type: b1 | |
- id: is_2h_boost | |
type: b1 | |
boost_server: | |
seq: | |
- id: boost_type | |
type: u1 | |
enum: boost_type | |
enums: | |
boost_type: | |
0: off | |
1: on_1_hour | |
2: on_2_hours | |
boost_device: | |
seq: | |
- id: expected_finish_time | |
type: boost | |
doc: | | |
Could be other message, but so far I seen only the following values: | |
is_2h_boost=1 | |
is_1h_boost=1 | |
while the resulting time seems to be correct. | |
- id: boost | |
type: boost | |
ping_device: | |
doc: | | |
The device sends PING-requests every ≈41 seconds (sometimes less, | |
sometimes more). The "is_update_request" is always set. If the server | |
doesn't respond device continues as normal, without retries. | |
seq: | |
- id: status | |
type: b2 | |
enum: device_status | |
- id: unknown1 # could be just reserved, seems to be always 0 | |
type: b1 | |
- id: load_detected | |
type: b1 | |
- id: advance_mode_enabled | |
type: b1 | |
- id: load_was_detected | |
type: b1 | |
doc: | | |
Indicates whether load was detected during current (if power is on | |
right now), or the previous "session". | |
- id: reserved1 | |
type: b2 | |
- id: unknown2 | |
size: 2 | |
- id: work_mode | |
type: u1 | |
enum: work_mode | |
- id: unknown3 | |
size: 4 | |
- id: device_uptime | |
type: u4 | |
- id: boost | |
type: boost | |
- id: unknown4 | |
size: 2 | |
enums: | |
device_status: | |
1: off | |
2: on | |
ping_server: | |
seq: | |
- id: timestamp | |
type: u4 | |
schedule_server_read: | |
seq: | |
- id: schedule_id | |
type: u1 | |
repeat_weekdays: | |
seq: | |
- id: monday | |
type: b1 | |
- id: tuesday | |
type: b1 | |
- id: wednesday | |
type: b1 | |
- id: thursday | |
type: b1 | |
- id: friday | |
type: b1 | |
- id: saturday | |
type: b1 | |
- id: sunday | |
type: b1 | |
- id: reserved | |
type: b1 | |
schedule_time: | |
seq: | |
- id: minutes | |
type: b12 | |
- id: is_enabled | |
type: b1 | |
- id: reserved | |
type: b3 | |
single_schedule_item: | |
seq: | |
- id: start | |
type: schedule_time | |
- id: end | |
type: schedule_time | |
- id: repeat | |
type: repeat_weekdays | |
- id: reserved | |
type: u1 | |
schedule: | |
doc: | | |
Schedule with an empty name == deleted schedule | |
seq: | |
- id: schedule_id | |
type: u1 | |
- id: schedule1 | |
type: single_schedule_item | |
- id: schedule2 | |
type: single_schedule_item | |
- id: schedule3 | |
type: single_schedule_item | |
- id: schedule4 | |
type: single_schedule_item | |
- id: schedule5 | |
type: single_schedule_item | |
- id: schedule6 | |
type: single_schedule_item | |
- id: schedule_name | |
type: str | |
size: 50 | |
doc: | | |
The name is limited to 40 symbols in the app, so the size could be | |
just 40-41 bytes here, and not 50 | |
encoding: ASCII | |
work_mode_change: | |
seq: | |
- id: mode | |
type: u1 | |
enum: work_mode | |
footer: | |
seq: | |
- id: magic | |
contents: [0x2d, 0xdf] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment