-
Notifications
You must be signed in to change notification settings - Fork 49
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
DPG1C Support #32
Comments
I only have a Idasen desk and I think the other Linak controllers use different commands so the scope of this tool was just for the Linak desk. If you were able to find out what commands work on the DPG1C then it's possible that I could include them in the script. |
If you want to do this you can run this script using the Bleak python library https://github.com/hbldh/bleak/blob/develop/examples/service_explorer.py If you were able to post the output here then we could try to work out what the correct characteristics or commands are for the DPG1C |
@linusbierhoff another option (if you have a Mac) would be Bluetillity. |
I also remembered that someone else apparently got the DPG1C working and claimed it used the same commands: #3 |
I'm having trouble wit this as well. After reading #3, I reset the controller per the manual and re-paired it. But it only seems to be reading the status and not settings it:
|
Here's the output from the serviceexplorer script linked above: https://gist.github.com/dmitrym0/7394da30f2e543b5d4ac825a604d989b |
I can confirm, that getting the status is working, but not setting a position |
@dmitrym0 thank you for getting that. It's odd, it looks like it has all the right characteristics. The only thing I can think of is that for some reason that notifications on the height characteristic aren't working on the DPG1C. If you are comfortable running this as a python script then some things that would be useful to try are:
I am currently away so limited to what I can try. One thing I will add when I am back at my desk is some better logging so you don't have to fiddle with the script if you don't want to. |
I tried running locally with the following values:
No change. I also instrumented the code with some
So If |
If you run the script with |
Yup:
|
Aha, that must means that the movement commands are wrong then. Apologies for the trial and error style approach but could you try replacing If that doesn't work then it might be that we have the right characteristic but we are sending the wrong data. In which case I'll probably have to get the android app and decompile it again to have a look. |
I had a small success. I opened the iOS App and allowed the app to allow movement in both directions. After that the movement works but just for a few steps |
Ah that is interesting because in the decompiled app there is some code for sending a I think the command could be defined as:
And then send it just before we send the first movement command:
(The app also sends a stop command immediately after wakeup so 🤷♂️ ) |
I got the same/a similar problem. The program is able to read all the values from the desk, but not able to trigger a movement. I added a Log (ignore my strange log output in between if necessary)
Nothing happens; I move the desk up manually
(If you look closely at the speed, you can see that the I also tried this
with and without the following My `service_explorer.py` for completeness
|
I thought maybe the async def move_up(client):
print('raw send up with loop:', UUID_COMMAND)
for i in range(270):
print(i)
await client.write_gatt_char(UUID_COMMAND, bytearray(struct.pack("<H", i)))
time.sleep(1)
print('up loop finsihed', UUID_COMMAND) but nothing happened 😄. |
So one thing I realised was that maybe the wake up command is being sent to the "reference input" characterisitc rather than the "command" characteristic. Perhaps someone could try:
|
Made changes above, and tried a "move-to" followed by a "sit". Height: 733mm Target: 730mm Speed: -34mm/s |
Probably better if I add the command definition for WAKEUP 🤦♂️ Note that I have some bleak errors, so the previous fix is not fully working: |
Sadly after 4h, the controller went to sleep, and I tried again. No result. My question would be how confident are you with the exact WAKEUP command? |
Played with the WAKEUP command:
But also interestingly, tried just launching the app (no desk movement) and killing it (to close the bluetooth connection) instantly. The wakeup is at app opening, not when sending up/down instructions (maybe also there) |
I've just pushed a change which may help with this if anyone is willing to test. I was inspired by this repo to use a different characteristic to perform the height commands. As mentioned in that repo its essentially a "move to" command rather than a "move up/down" command which means that the desk now stops dead on the target height. This works for me perfectly but I found I needed to add the wake up command, even on the Linak desk, and as it works on my desk I think that means I have got the wakeup command working. Maybe this will work on the DPC1C? Change is only on github, not on pip yet. |
If somebody gets it to work with the DPC1C now, please report back! I'd love to add this to my homebridge plugin. |
Nothing has changed with the initial connection so it shouldn't be different 😓 Have you tried increasing the connection timeout? And maybe unpair and repair? |
@AhmedKamal that is because our desks require additional command after the device goes to sleep. It seems that any accepted write to settings or desk rename does the job (tested with the linak app) but so far I was not able to reverse engineer the actual command |
Yea, I tried to connect from the phone and then back and then it worked again. I'm not sure how to capture the Bluetooth communication. It has a macos app as well. |
@AhmedKamal unfortunately for me it's mac and I'm linux. I have the BLE communication of the original app from the android phone as well as I was able to decompile the android app but the complexity of the update code makes it hard for me to figure out :( |
@mensfeld I have donwloaded the nordic nrf connect (any other ble scanner would work) and with that it's easy to get all the services for bluetooth. Maybe that is something that we can use? |
@LuisDiazUgena I have no idea how that works. I tried understanding the dumps from wireshark and I know, that there is an update that needs to be sent to the desk once in a while to "wake it" or unlock etc. At the moment I gave up but I would love to have it working. It drives me crazy that I cannot automate desk journey through the day. |
connecting to the desk in linux also output the whole list of characteristics. Those are here: https://pastebin.com/mYWYu0ub Also, I;m trying to make a workaround trying to reset the docker container every half hour or something like that. Maybe that works. will keep this updated as I found out things. |
@LuisDiazUgena For me, the problem was not the characteristics but the usage of some of them. I mean one that is responsible for writing a name update/anything else that would just "wake" it up. The rest of the commands are pretty well-defined. |
I had another scan through the decompiled app to see if I could find anything to do with initialisation. I found this function in /* access modifiers changed from: private */
public final Completable setUpDevice(Device device, RxBleConnection rxBleConnection, DpgClient dpgClient) {
Iterable<DpgCommand.ControlCommand> listOf = CollectionsKt.listOf(DpgCommand.ControlCommand.GET_CAPABILITIES,
DpgCommand.ControlCommand.USER_ID, DpgCommand.ControlCommand.DESK_OFFSET,
DpgCommand.ControlCommand.REMINDER_SETTING, DpgCommand.ControlCommand.GET_SET_MEMORY_POSITION_1,
DpgCommand.ControlCommand.GET_SET_MEMORY_POSITION_2,
DpgCommand.ControlCommand.GET_SET_MEMORY_POSITION_3,
DpgCommand.ControlCommand.GET_SET_MEMORY_POSITION_4);
Collection arrayList = new ArrayList(CollectionsKt.collectionSizeOrDefault(listOf, 10));
for (DpgCommand.ControlCommand readCommand : listOf) {
arrayList.add(DpgCommand.readCommand(readCommand));
}
List list = (List) arrayList;
Completable doOnComplete = Completable
.mergeArray(Observable.fromIterable(list)
.flatMapSingle(new RxConnectionManager$setUpDevice$dpgSetupCompletable$1(dpgClient))
.take((long) list.size()).ignoreElements()
.doOnComplete(RxConnectionManager$setUpDevice$dpgSetupCompletable$2.INSTANCE),
rxBleConnection
.readCharacteristic(LinakServices.Characteristic.GenericAccess.DEVICE_NAME.uuid())
.doOnSuccess(new RxConnectionManager$setUpDevice$nameReadCompletable$1(device))
.ignoreElement().retry(3),
rxBleConnection.readCharacteristic(LinakServices.Characteristic.ReferenceOutput.ONE.uuid())
.doOnSuccess(new RxConnectionManager$setUpDevice$referenceZeroReadCompletable$1(device))
.ignoreElement().retry(3).onErrorComplete())
.doOnComplete(new RxConnectionManager$setUpDevice$1(device));
Intrinsics.checkExpressionValueIsNotNull(doOnComplete, "Completable.mergeArray(d…anged()\n }");
return doOnComplete;
} which I guess is taking the list of commands and running them:
This matches with what I found from that other repo earlier in the thread. Another guess is that then the response is picked up in So it really seems like the only thing that the android app does is send that list of commands. Perhaps we just haven't found the correct byte encoding or something like that? Trying to follow the code above it seems like it takes each command constant and runs:
This looks like it simply wraps the command constant in some other bytes:
It looks like So for examples
(Python seems to want 128 and not -128). This matches the command I asked someone to send earlier. Long winded way to say I think the commands are correct BUT looking at this now I think they should be sent to
And try again? Note that |
@rhyst nope :( still does not wake up with the suggested wakeup |
Hi guys, I have been working on a different via to be able to use the desk with HA. Basically I have used a existing project that wraps the idasen controller on a docker enviroment in nodejs and added some logic and new mqtt topics in order to be able to control it using HA. I have created a PR to original repo and the code is in my fork meanwhile. Basically I have been able to run flawleslly the server for a few days now without any issue. Moving the desk from HA works, but for me it feel weird. I always move from stored heigth 1 to stored heigth 2 and viceversa, so I double tap the controller and I'm ready. Also, triggering the movement from the HA buttons have always been weird, because the movement has stopped several times before reaching the desired heigth. |
Maybe this is something we should pursue here. |
Hi all, Please check if this will work for you:
|
Yes! That works for me. Thank you for sharing! |
That's great! Thank you @kaml123 , do you have an explanation for what it's doing? I will confirm it works with idasen desk and add it in (unless you want to make a PR 🙂) |
Hi @rhyst,
Please look at |
@kaml123 works for me as well so far. Amazing! 🙏 |
I have published Can someone let me know if this version works on their DPG1C? |
Hi,
when running |
@voruti ah because of the relative imports you need to run it like:
I also know Python too little to know why this is needed 😆 |
It looks like Python 3.8 isn't supported: https://peps.python.org/pep-0604/ in line https://github.com/rhyst/idasen-controller/blob/master/idasen_controller/gatt.py#L80 which you wrote in the https://github.com/rhyst/idasen-controller/blob/master/CHANGELOG.md?plain=1#L13. I switched to Python 3.10 |
Fixed by #69 |
As I stated above #32 (comment) I have the DPG1M. It's working for me quite well now. |
Released 2.1.0 with these changes so closing this issue 🥳 |
Works like a charm! :) |
Hi! I am not able to move my desk. When I try to run e.g.
idasen-controller --sit
my raspberry pi connects and gets the right height but nothing happens:Is there anything I need to be aware of when using the script on a raspberry pi or with a linak desk?
The text was updated successfully, but these errors were encountered: