-
Notifications
You must be signed in to change notification settings - Fork 37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Document Plejd BLE #163
Comments
Some random thoughts since you pinged me.. Some data in the plejd API is little endian, for example the dim level is 16 bits little endian. command types: I can probably have other thoughts, but this is as structured as they are right now. One other interesting revelation I had was that it's possible to query current state on the light_level uuid, I implemented that at klali/ha-plejd@de13334 @emilohman realised that this can be triggered as reads on one output at a time as well to get only specific device states. |
Thanks for that @klali! I actually looked just the other day at that specific commit you referenced, and realized that is something not implemented in this code-base. Haven't had time to look into what it actually does though. I tried my best based on just looking at your code to write down what it writes/decodes, might not be accurate. The dim level is interesting that you mention. Is what you're saying Plejd actually have 2 byte dim level? So not 0-255 but rather 0-65535? We recently switched to parsing byte 8 (index 7) rather than byte 7 (index 6) but maybe we're then just decoding the most significant byte and discarding the rest? |
Yes, dim is two bytes, little-endian. If you let the bytes swap places and decode it it will make sense. This isn't very useful from home-assistant since dim is only one byte there, but to reach highest dim levels you need to set it to ffff. Yes, I didn't completely decode the lightlevel data, but it's reported one or two outputs at a time, with 10 bytes per output: |
I see. I realize now that we actually do set the full two bytes when setting dim level ( |
And as I look at what you wrote about time, remember that it's unix time, so 32 bits (little-endian) since 1970-01-01 00:00, so: Several of the commands seem to have a trailing byte, I have no idea what that means. |
Thanks, clarified in the text! |
Have been doiing some testing. Interestingly enough it seems you can broadcast light commands to device id Btw - thanks to the discussion here this repo now has a PR for time reading/updates as well as a better handle on dim levels and little-endian encoding, so thanks for that! (btw 2: Makes me think the command are actually |
General format of incoming messages
BLE device Id Command/request Command Data
|
Thanks, added in first post. Left to find out: Rotation of RTR-01 rotary encoder and what BLE commands that sends. |
RTR-01 is just another input physically/electrically attached to a Plejd Device like DIM-01, etc. When using RTR-01 towards another device than the host it must be configured towards that other device, just like any other input. WPH-01 and WTR-01 are different from RTR-01 by being battery powered Bluetooth devices without loads. Sadly the WRT-01 does not broadcast on rotation. Just like RTR-01 it will only send targeted commands/rotation/dimming after having been configured to a target device. |
Oh, I didn't realize that was the the case, shame. So - if no device is set as output it sends nothing? And if a device is connected it sends dim command as per usual? |
Color temperatureCommand
I have tested this on one DWN-01, but it should work with DWN-02 and probably LED-75 too. |
Much appreciated, thanks! Looking at my site json response I don't have any @thomasloven could you possibly post a (scrubbed of course) version of yours in some way? |
No, that's right. Quite annoying, and it honestly seems like Pljed are just making up things as they go. As for example in the color temperature being BIG endian while the dim value is LITTLE... Here's the site details for my test setup: https://gist.github.com/thomasloven/b53ae38ea2971c319618a848e02c0234 |
Perfect, thanks for that!
|
DWN-X are not guaranteed to be tunable, by the way. They can be set up to follow the astrotable for the color temperature in which case I believe they will reject any manual settings. See the lines below what I linked above. |
@thomasloven Looking through your site JSON a bit more carefully and comparing it to our code I note that for the DWN-01 there is a new We (in this repo) use
I added the binary equivalents above, which seem to be reasonable.
I've added this as a test to fix that DWN are currently not dimmable in the https://github.com/icanos/hassio-plejd/tree/feature/DWN-dimmable-fix branch. Thoughts? We would really need some more examples to know for sure, but I'm feeling lucky today 😄 |
Seems to make sense. I have site JSON from a user with some DWN-2 also, and they have traits either 15 or 9. I'm not sure how it works, but I guess those can be grouped in some way. Unfortunately they only had one in stock at elbutik.se when I ordered mine for testing, so I can't test the grouping... {
"deviceId": "C3E245730751",
"siteId": "e6f7cddb-6582-4c39-b485-6982803b5f0f",
"title": "Downlights",
"traits": 15,
"hiddenFromRoomList": false,
"roomId": "fb9f0653-3ceb-45f2-bca8-50321c704cc8",
"createdAt": "2023-09-09T23:20:52.033Z",
"updatedAt": "2023-09-10T19:55:12.605Z",
"hiddenFromIntegrations": false,
"outputType": "LIGHT",
"ACL": {},
"objectId": "NJxc5qbS8B",
"__type": "Object",
"className": "Device"
},
{
"deviceId": "D2B437D3D6C3",
"siteId": "e6f7cddb-6582-4c39-b485-6982803b5f0f",
"title": "Downlights",
"traits": 9,
"hiddenFromRoomList": false,
"roomId": "fb9f0653-3ceb-45f2-bca8-50321c704cc8",
"createdAt": "2023-09-09T23:20:53.286Z",
"updatedAt": "2023-09-09T23:20:53.286Z",
"ACL": {},
"objectId": "63ggVxw5aC",
"__type": "Object",
"className": "Device"
}, {
"deviceId": "C3E245730751",
"siteId": ...,
"installer": {
...
},
"dirtyInstall": false,
"dirtyUpdate": false,
"dirtyClock": false,
"dirtySettings": false,
"hardwareId": "199",
"faceplateId": "0",
"faceplateUpdatedAt": "2023-09-09T23:20:52.029Z",
"firmware": {
...
},
"createdAt": "2023-09-09T23:20:52.033Z",
"updatedAt": "2023-09-10T19:53:43.192Z",
"isFellowshipFollower": false,
"coordinates": {
"__type": "GeoPoint",
"latitude": 68.6974329,
"longitude": 15.1949525
},
"predefinedLoad": {
"loadType": "DWN",
"descriptionKey": "DWNDescription",
"titleKey": "DWNTitle",
"predefinedLoadData": "{\n \"Order\":1,\n \"Min\":0.5,\n \"Max\":100,\n \"Start\":0.5,\n \"OutputSpeed\":0.25,\n \"ColorTemperature\":{\n \"behavior\":\"dimToWarm\",\n \"logFactor\":105,\n \"slewRate\":6554,\n \"minDimLevel\":25,\n \"maxDimLevel\":255,\n \"minTemperatureLimit\":2200,\n \"maxTemperatureLimit\":4000,\n \"minTemperature\":2200,\n \"maxTemperature\":3200\n },\n \"MinDimLevelMapping\":{\n \"0%\":15,\n \"0.1%\":19,\n \"0.2%\":23,\n \"0.3%\":29,\n \"0.4%\":35,\n \"0.5%\":44,\n \"0.6%\":76,\n \"0.7%\":130,\n \"0.8%\":222,\n \"0.9%\":382\n },\n \"OutputType\":\"LIGHT\",\n \"BootState\":\"UseLast\",\n \"UserDefined\":[\n \"ColorTemperature\"\n ],\n \"Settings\":[\n \"SimpleStart\",\n \"Max\",\n \"ColorTemperature\"\n ]\n}",
"createdAt": "2023-05-16T14:37:27.700Z",
"updatedAt": "2023-06-22T13:01:16.366Z",
"defaultDimCurve": {
"__type": "Pointer",
"className": "DimCurve",
"objectId": "xGBw2qRHoE"
},
"allowedDimCurves": {
"__type": "Relation",
"className": "DimCurve"
},
"ACL": {},
"objectId": "G9rgAQ8X6B",
"__type": "Object",
"className": "PredefinedLoad"
},
"diagnostics": "0000170000003200000000000000",
"ACL": {},
"objectId": "wpjCzRm0xz",
"__type": "Object",
"className": "PlejdDevice"
},
{
"deviceId": "D2B437D3D6C3",
"siteId": ...,
"installer": {
...
},
"dirtyInstall": true,
"dirtyUpdate": false,
"dirtyClock": false,
"dirtySettings": false,
"hardwareId": "199",
"faceplateId": "0",
"faceplateUpdatedAt": "2023-09-09T23:20:53.225Z",
"isFellowshipFollower": true,
"firmware": {
...
},
"createdAt": "2023-09-09T23:20:53.286Z",
"updatedAt": "2023-09-10T19:59:37.014Z",
"diagnostics": "0000150000003400000000000000",
"ACL": {},
"objectId": "D3HEfE6djd",
"__type": "Object",
"className": "PlejdDevice"
}, |
I got a WMS-01 motion sensor.
There are no events sent when no more motion is detected. The sensitivity can be set in the app. I've been playing around with it a little bit, but can't see much difference in either behavior or in the siteData.
{
"deviceId": "EE2FE8EBFE52",
"siteId": "<REDACTED>",
"title": "H\u00f6rn",
"traits": 0,
"hiddenFromRoomList": false,
"roomId": "40e2a007-9445-4e5b-821a-4e922ba8fd47",
"createdAt": "2024-02-20T19:52:25.976Z",
"updatedAt": "2024-02-20T19:52:25.976Z",
"ACL": {},
"objectId": "poSqxqgd8X",
"__type": "Object",
"className": "Device"
}
{
"deviceId": "EE2FE8EBFE52",
"siteId": "<REDACTED>",
"installer": "<REDACTED>",
"dirtyInstall": false,
"dirtyUpdate": false,
"dirtyClock": false,
"dirtySettings": false,
"hardwareId": "70",
"faceplateId": "0",
"faceplateUpdatedAt": "2024-02-20T19:52:25.967Z",
"firmware": {
"notes": "WMS-01",
"data": {
"__type": "File",
"name": "e6bde80da922879ee5cf7d6d47960593_application.bin",
"url": "https://cloud.plejd.com/parse/files/zHtVqXt8k4yFyk2QGmgp48D9xZr2G94xWYnF4dak/e6bde80da922879ee5cf7d6d47960593_application.bin"
},
"metaData": {
"__type": "File",
"name": "9082ea4691359bee99f15aad763a4020_application.dat",
"url": "https://cloud.plejd.com/parse/files/zHtVqXt8k4yFyk2QGmgp48D9xZr2G94xWYnF4dak/9082ea4691359bee99f15aad763a4020_application.dat"
},
"version": "1.4.4",
"buildTime": 20231122114870,
"firmwareApi": "12",
"createdAt": "2023-11-24T09:17:18.850Z",
"updatedAt": "2023-11-24T09:17:18.850Z",
"ACL": {},
"objectId": "YP9uedNKVw",
"__type": "Object",
"className": "Firmware"
},
"createdAt": "2024-02-20T19:52:25.976Z",
"updatedAt": "2024-02-20T19:52:38.388Z",
"ACL": {},
"objectId": "C3xCAWEZTr",
"__type": "Object",
"className": "PlejdDevice"
}
{
"motionSensorData": {
"threshold": 50,
"blindTime": 15,
"windowTime": 0,
"pulseCounter": 0,
"requireZeroCrossing": true,
"useHpf04": false
},
"deviceId": "EE2FE8EBFE52",
"siteId": "<REDACTED>",
"input": 0,
"buttonType": "WirelessMotionSensor",
"dimSpeed": -1,
"doubleSidedDirectionButton": false,
"createdAt": "2024-02-20T19:52:26.120Z",
"updatedAt": "2024-02-20T19:58:49.184Z",
"ACL": {},
"objectId": "ud53ef9U0b",
"__type": "Object",
"className": "PlejdDeviceInputSetting"
}
{
"siteId": "<REDACTED>",
"deviceId": "EE2FE8EBFE52",
"input": 0,
"deviceParseId": "poSqxqgd8X",
"dirty": false,
"dirtyRemove": false,
"active": true,
"createdAt": "2024-02-20T19:53:04.706Z",
"updatedAt": "2024-02-20T19:53:04.706Z",
"ACL": {},
"objectId": "yXpj4rivza",
"__type": "Object",
"className": "MotionSensor"
} It's also listed in |
I got a JAL-01 controller for testing. First of all, it has two new Traits.
It reports position through the normal state/dim update with the dim level being the position of the cover from 0 to 0xFFFF (little-endian). The movement command looks like:
And movement can be stopped with
I'm not sure the third byte of Now... remember how I said it seems like the Plejd engineers are just making things up as they go? When reporting position, the tilt angle is sent after the dim data as two bytes. |
Broken out of #130
Thought it could be a good idea to compile all known BLE commands and their structure. From this projects code base, mentioned PR and some light looking @klali's great work in https://github.com/klali/ha-plejd
API has been documented in typings
.d.ts
files bound for the v0.8.0 release.Below are my best initial guesses/compilations. Please write any mistakes or improvements in the comments!
BLE characteristics
UUID:s for light level, data, last data, auth and ping below. Used to listen to incoming messages and write messages
Outgoing messages
Request light level update
Posted to
light level
characteristic. Value0x01
(hex). Response sent back on same characteristic. Response format:General format of incoming messages
List of fields below
BLE device Id
B82B1730526F
Command/request
0110
: Command (no response)0102
: Read (request response)0103
: Read?Command
Commands are 2 bytes, so 00 should be included.
Is the00
prefix actually part of the command? So: Is the command001b
or1b
? Does it matter which we parse?0021
: Scene trigger0097
: State update0098
: Dim+state update ("DIM2" in this code)0016
: (Wireless) button pressed001b
: Time broadcast00c8
: Dim+state update ("DIM" in this code)Data
Depending on command
Commands
Scene trigger
Command
0021
02
always in my installationState update
Command
0097
State/dim update
Command
0098
/00c8
00
so it can probably be discarded(Wireless) button pressed
Command
0016
button_1
button_2
button_3
button_4
button_1
Time
Command
001b
Using @emilohman's great explanation:
(btw, the above code is actually picked up by the lastest code restructure, but only logged with
Command 001b seems to be some kind of often repeating ping/mesh data
- now I know better, thanks @emilohman!)The text was updated successfully, but these errors were encountered: