A JavaScript interface to a Warema WMS network using a Warema WMS Stick.
import {SerialPort} from "serialport";
import WaremaWMS from "./lib/WaremaWMS.js";
import WaremaWMSFrameHandler from "./lib/WaremaWMSFrameHandler.js";
const port = new SerialPort({
path: '/dev/ttyUSB0',
baudRate: 128000,
})
const wms = new WaremaWMS(port);
console.log(wms.getName());
console.log(wms.getVersion());
console.log(await wms.configureNetwork(11, 'ABCD'));
console.log(await wms.configureEncryptionKey('012345678ABCDEF012345678ABCDEF01'));
wms.frameHandler.on(WaremaWMSFrameHandler.MESSAGE_TYPE_BROADCAST_WEATHER, console.log);
wms.frameHandler.on(WaremaWMSFrameHandler.MESSAGE_TYPE_BROADCAST_NETWORK_PARAMETERS_CHANGE, console.log);
wms.frameHandler.on(WaremaWMSFrameHandler.MESSAGE_TYPE_SCAN_REQUEST, console.log);
wms.frameHandler.on(WaremaWMSFrameHandler.MESSAGE_TYPE_NETWORK_JOIN, console.log);
console.log(await wms.wave('ABCDEF'));
console.log(await wms.getDeviceStatus('ABCDEF'));
console.log(await wms.moveToPosition('ABCDEF', 50, 0));
console.log(await wms.stop('ABCDEF'));
wms.frameHandler.on(WaremaWMSFrameHandler.MESSAGE_TYPE_SCAN_RESPONSE, console.log);
console.log(await wms.scan('ABCD'));
The protocol has been reversed by some kind folks from the IoBroker forum. Additional information is available from the warema-wms-venetian-blinds npm package.
The radio communication is encrypted, the USB stick takes care of all the encryption details, and provides a serial interface that can be easily used to communicate with the WMS network.
Frames are the basic unit of communication with the USB stick. Frames are enclosed in curly braces, and the first character defines the frame type and the direction (uppercase -> host to USB, lowercase -> USB to host).
-> {G}
<- {gWMS USB-Stick}
-> {V}
<- {v12345678 }
-> {R01ABCDEF7021FFFF02}
<- {rABCDEF7080000010FFFFFFFAC8FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF}
Frames, regardless of their direction, might include a payload. The payload might contain information from the USB stick to the host, configuration for the USB stick, or messages to/from the network.
The following frame types are known:
Frame type | Content |
---|---|
G /g |
Stick name request/response |
V /v |
Stick version request/response |
R /r |
Network message request/response |
M |
Stick network parameters configuration |
K |
Stick network encryption key configuration |
a |
Stick ACK |
-> {G}
<- {gWMS USB-Stick}
-> {V}
<- {v XXXXXXXX ___}
XXXXXXXX
is the version reported by the stick. It's not known whether there are multiple versions, or if it's possible to upgrade___
are blank spaces in the response
-> {M X CC PPPP}
<- {a}
X
can be either%
or#
, depending on whether we want to receive network broadcast messages, or not.CC
is the channel number, between11
and26
PPPP
is the PAN ID, between0000
andFFFF
-> {K 401 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}
<- {a}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
32-character, hex encryption key
-> {R TT XXXXXX YYYY ZZZ[...]}
<- {r XXXXXX YYYY ZZZ[...]}
TT
is some kind of type identifier added to outgoing messages onlyXXXXXX
is the source serial numberYYYY
is the message typeZZZ[...]
is the message payload
Messages contain data travelling between devices of the WMS network.
Messages are embedded within R
/r
frames, and can be of different types.
The following message types are known:
Message type | Content |
---|---|
5060 |
Change network parameters broadcast |
50AC |
ACK from device |
7020 /7021 |
Scan request/response |
7050 /7051 |
Wave request/response |
7080 |
Weather station broadcast |
7070 /7071 |
Device move to position request/response |
8010 /8011 |
Device status request/response |
<- {r XXXXXX 7080 YY WW L1 ZZZZZZ L2 xx RR TT yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy}
// the followings are actual message received from 2 different weather stations
r ABCDEF 7080 00 00 10 FFFFFF FA C8 FF FF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
r ABCDEF 7080 00 01 1A FFFFFF FA C8 FF FF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
r ABCDEF 7080 00 00 00 FFFFFF 00 C7 FF FF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
YY
unknownWW
wind speed (hex)L1
illuminance 1, needs processingZZZZZZ
unknownL2
illuminance 2, needs processingxx
unknownRR
rain (00
= no rain,C8
= rain)TT
temperature, needs processingyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
unknown
According to the forum, the following post-processing is needed:
- temperature: convert to dec, divide by 2, and subtract 35
- illuminance
- if
L1
is00
, the illuminance value isL2
, converted to dec, multiplied by 2 - otherwise, convert both
L1
andL2
to dec, multiply them and then multiply by 2
- if
Given the mismatch between the documentation and the sample messages, only wind speed is currently implemented
-> {R06 XXXXXX 7050}
<- {a}
<- {r XXXXXX 50AC YYYY}
// real world examples
r ABCDEF 50AC 88ED
r ABCDEF 50AC CDD6
r ABCDEF 50AC B043
---
<- {r XXXXXX 7050}
XXXXXX
serial number of the source deviceYYYY
unknown - changes with every request
-> {R06 XXXXXX 8010 01000005}
<- {a}
<- {r XXXXXX 8011 010000 TT PP WW V1 V2 MM}
// real world examples
r ABCDEF 8011 010000 05 00 FF FF FF 00
r ABCDEF 8011 010000 05 14 FF FF FF 01
r ABCDEF 8011 010000 05 1D FF FF FF 01
r ABCDEF 8011 010000 05 36 FF FF FF 00
XXXXXX
serial number of the target deviceTT
device type.03
and05
seen in the wild.05
seems to be theWMS Plug receiver
PP
position (hex)WW
inclination (hex)V1
valance 1V2
valance 2MM
status of the device:00
for a stopped device,01
for a device that is moving
Given the lack of test devices, valance
is currently not implemented
The 01000005
string in the request and 010000
in the response has no known meaning.
-> {R06 XXXXXX 7070 CC} (for CC == 01)
-> {R06 XXXXXX 7070 CC PP WW V1 V2} (for CC == 03)
<- {a}
<- {r XXXXXX 7071 0010023F02 pp ww FFFF0C0DFFFF}
// real world examples
r ABCDEF 7071 0010023F02 96 7F FFFF0CFFFFFF
r ABCDEF 7071 0010023F02 C8 7F FFFF0CFFFFFF
r ABCDEF 7071 0010023F02 64 7F FFFF0CFFFFFF
XXXXXX
serial number of the target deviceCC
command01
stop moving03
move to position
PP
position (hex)WW
inclination (hex)V1
valance 1V2
valance 2pp
previous target position (hex)ww
previous target inclination (hex)
This message is sent during device discovery, when linking a remote to a device.
<- {r XXXXXX 5060 PPPP 02 CC 00}
XXXXXX
serial number of the source devicePPPP
PAN IDCC
channel (hex)
<- {r XXXXXX 7020 PPPP 02}
-> {R01 XXXXXX 7021 PPPP 02}
XXXXXX
serial number of the source devicePPPP
PAN ID
-> {R04 XXXXXX 7020 PPPP TT}
<- {a}
<- {r XXXXXX 7021 PPPP TT UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU}
XXXXXX
serial number of the source device (should beFFFFFF
when sending a scan request)PPPP
PAN IDTT
device typeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
unknown
<- {r XXXXXX 5018 PPPP KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK FF CC}
XXXXXX
serial number of the source devicePPPP
PAN IDKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
network encryption key (reversed)CC
channel (hex)
Some of the fields in the messages need to be converted to be properly usable.
- Channel: Convert to base 10
- Inclination: Convert to base 10 and subtract 127
- Network encryption key: Reverse (
ABCDEF
should becomeEFCDAB
) - Position: Convert to base 10 and divide by 2 to have a 0-100 value. 0 means fully retracted
- Wind speed: Convert to base 10