Closed Hypfer closed 5 years ago
Some findings:
The static encryption key (RoCKR0B0@BEIJING
) is no longer used.
Instead, a random key is generated for each encrypted file. The key is sourced from /dev/urandom
.
Then, this key is itself encrypted using mbedtls_pk_encrypt
. The first 512 bytes of the file represent the encrypted key.
The remaining file content past the first 512 bytes is the map encrypted with mbedtls_aes_crypt_ecb
and the random key.
That's what I have found so far, but it would be cool if someone else can independently confirm this.
Here's another update.
The encrypted rr.gz
files go through this process:
/dev/urandom/
mbedtls_pk_encrypt
mbedtls_aes_crypt_ecb
and appended to the .rr.gz
fileThis is presumably so that Xiaomi can later decrypt the key using their RSA private key, which will then enable them to decrypt the gzip archive.
Some possible workarounds:
/dev/urandom
and redirect to a custom file. This way, we will always know what the "random" key is.Options 2, and 3 would break the compatibility with the Xiaomi cloud servers, and so they are best used with dummycloud enabled. Option 1 could theoretically still work, but can be easily detected by Xiaomi.
I tried experimenting with Option 1 for a bit, but was unsuccessful. So I decided to just disable encryption, since I do not care about the Xiaomi cloud because my vacuum is not allowed to connect to the internet anyway. Turns out this is the simplest option.
I updated my gen2 vacuum to 001780 and patched rrlogd
. The patched file is attached here.
Then, I updated the regex that I pointed out in an earlier comment: https://github.com/Hypfer/Valetudo/issues/40#issuecomment-443730275
Valetudo now correctly shows the maps on v001780 when the vacuum is docked.
The patched rrlogd for v001780 is attached here. It should be copied to the vacuum and moved to /opt/rockrobo/rrlog/
. Don't forget to give it execution permission, chmod +x /opt/rockrobo/rrlog/rrlogd
Note: it is probably wise to keep a copy of the original rrlogd file first: mv /opt/rockrobo/rrlog/rrlogd /opt/rockrobo/rrlog/rrlogd_
.
Also note: that I did not test this on any other version, and it will probably not work and require different patch offsets.
Final note: You will need to either reboot your vacuum, or kill the running rrlogd
process first so that the robot will re-spawn a process with the patched rrlogd.
Here are the hex patches used:
0001051C: 4B 47
00010746: FF E3
00010747: F7 20
@JohnRev can you patch a rrlog (of course i will privide it) for gen2? i would try this and see how the new persistant pams work out...by the way - what's the setting needed to enable the map storage feature?
This is gen2. I should have clarified. Not sure about the map storage. I was mainly focused on finding means for decrypting the rr.gz file :)
gr8. i'll download 1780 and get myself to work. i guess we should e carefull and stop the automatic update mechanism - xiaomi will most probably close some doors and we might remain stuck with some default stuff...
My vacuum has never connected to the internet, so I'm not too worried about the automatic updates. If you do use the patched rrlogd file, it would probably be wise to use dummycloud too as I'm pretty sure the patched rrlogd breaks compatibility with the xiaomi cloud services.
i was connected to the internet (i got the gadget exactly when it came on the market). now i am on dummycloud and ccrypt is removed (just an empty file). my firewall is also plugging all holes so i should be safe. have you tried to enable the map storage feature? and if yes how did you do it?
No, sorry, I haven't looked into the map storage feature. Tho if you do figure out how to enable it, let me know!
@JohnRev i updated the beast and used your patched rrlogd but i keep getting error 500 from the webserver...
@leonardpitzu, you will have to compile Valetudo with the updated regex from https://github.com/Hypfer/Valetudo/issues/40#issuecomment-443730275
@JohnRev Already done that - I get the correct path to the files and I am trying correctly to open them. That’s where I got with the debugging. I user the rrlogd you provided. Added some more logging to figure out what’s wrong...
Interesting. It works fine for me. How does your /mnt/data/rockrobo/rrlog/
folder look like?
If there are a bunch of subfolders there, i suggest you delete them and try again with a fresh sweep of the vacuum.
Then, after the vacuum is docked, there should be a new subfolder containing a bunch of .gz file. Can you confirm they are unencrypted gzip files?
Oh, and did you reboot your vacuum to make sure it uses the patched rrlogd?
If you dont want to reboot, try killing the running rrlogd process (find process id with ps aux | grep rrlogd
then kill -9 [pid]
). The vacuum will respawn one with the patched rrlogd (assuming it is placed in the right path)
@JohnRev How did you go about patching rrlogd?
@JohnRev i've done some more debugging (i know linux quite well but i'm 250km away from the vacuum so debugging is a bit more tricky :) ). anyway here's what i found (again, using fw 1780 on gen 2, your patched rrlogd and a patched/modified version of valetudo):
and here it stops with the error:
digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
Previousely the log was being encrypted with the standard symmetric key which we all know. So the webserver was decryptiong it using the key, unpacking it and do the rest of it's thing. From your description i figured you disabled the encryption all together so the webserver now failes to decrypt the data. Even more, when i download the encrypted logs locally and try to unpack them it fails - probably the magic number is wrong.
@leonardpitzu :Just to confirm, did you make sure the running rrlogd process is the patched one? Simply replacing the file won't do it. It sounds to me the gz files are still being generated by the unpatched rrlogd
@JohnRev copied the patched rrlogd and rebooted the thing... i'm doing some more testing to see what's going on...
Oh! I think I attached the wrong rrlogd. In the one you're using right now, the first 512 bytes are the encrypted key and the rest of the file is the (unencrypted) gzip. So if you do something like dd if="navmap702931.ppm.0001.rr.gz" of="navmap-unencrypted.gz" bs=1 skip=512
you should get the clean unencrypted gz.
I have updated my initial comment. If you don't mind, please use this rrlogd. It is the same one as I have on my vacuum right now.
md5sum is 93e8df884b4c6162ffa2a11161f47429
Send it to the vacuum, kill the running rrlogd process (or reboot), and try again.
rrlogd_patched_001780_gen2.zip
@dugite-code: I disassembled rrlogd
, looked for the function call that appends the encrypted key to the header, and disabled (NOP
) that call. Then I looked for the call that stores the encrypted gz bytes to the file, and made them store the unencrypted buffer instead. The hex patches posted in my first comment do just that, and you can apply them to your unpatched rrlogd (of version 1780) to get the same patched rrlogd that I posted here.
@JohnRev i looked at the attached rrlogd and it's not the patched one. I patched it and am testing it now. will report back
Thanks! I am waiting. Sorry for attaching the wrong rrlogd
initially ... I got my files mixed up :smile:
@JohnRev sudo "you deserve a beer!" it's working!
Awesome!! And thanks for being willing to testing it :smile:
I discovered there's some 500 errors still showing up after some time, but these are strictly related to the code logic of how the /mnt/data/rockrobo/rrlog
is scanned in FIND_LATEST_MAP_IN_ARCHIVE
function. I will write about them in #40 .
Glad it's working, and hope this helps others too!
@leonardpitzu, I have a question for you. After rebooting the vacuum, does the robot forget the last map when performing a new sweep and generates a new one? Or does it trace correctly over the previously generated map?
@JohnRev mine also has Alzheimer and generates a new map. This is a "feature" i would guess unless we figure out what the "save map" button actually does. If we can set the same flag, by hand, we can keep the map between reboots. I read somewhere that the setting is some new file in /mnt/data/rockrobo. The file has to contain the value 1 in order to enable the map storage feature. Yet i can't seem to find that post nowhere so i am stuck right now...
I think I was able to get the saved map functionality to work. Would you be willing to test it?
pip install python-miio
, then execute the following (replacing with the correct variables, obviously).
export MIROBO_IP=vacuum_ip
export MIROBO_TOKEN=vacuum_token_key
mirobo raw-command set_lab_status 1 mirobo raw-command save_map
4. Reboot the vacuum
5. Do a new sweep
Indeed, the above commands seem to produce a file /mnt/data/rockrobo/lab.cfg
with content 1.
Not sure if just creating that file (echo 1 > /mnt/data/rockrobo/lab.cfg
) would suffice, but the above commands worked well for me, as far as I can tell.
@JohnRev that was the config file + flag. I am not sure though how this should work... Between reboots the maps is lost but i still get to see the track/path of the vacuum (well, at least the last part of it as it's split as o lately on more pieces). I have a persistent gridmap in /dev/shm (around 1MB) but even witht the "preferGridMap":true i only get to see the path...
Note sure I understand. Do you mean in Valetudo you see the path but without a map?
yes
Now that is something I haven't seen yet. It would be interesting to see which path file is being parsed by Valetudo.
Using which method did you enable the persist flag? Manually in lab.cfg
, or with the mirobo set_lab_status
and save_map
commands?
i used lab.cfg manual edit. valetudo is selecting the latest folder and searching for navmap and slam.
Perhaps the mirobo raw-command save_map
command was needed?
I just tried a reboot and my old map was still there, with the last path drawn.
I did a new sweep, and the robot "remembered" the last map and just started tracing over it
@JohnRev somehow my setup was messed up... now it saves the map correctly and it survives reboots. i'll make a diff to see what was screwed up... In between i made a script to have my "own" firmware release - custom apps, scripts, telegram notifications for start-up and status updates (whenever something changes), removed xiaomi stuff and my custom valetudo. This should keep me safe from failures - whenever something goes wrong the vacuum resets itself and i have to start everything from almost scratch.
Nice setup!
So now we have a way to use Valetudo on gen2 v001780 (with patched rrlogd) and a way to keep maps after reboot (with lab.cfg
)!!
So they are still using ppm maps?
How are virtual walls stored?
Yes, ppm is still used.
I haven't been able to figure out where virtual walls are stored (yet), and I don't have the mi app to test it either (my vacuum isn't connected to the internet).
It would be helpful if someone who does use the mi app can provide some insight
Hey @JohnRev could you post this to the https://github.com/marcelrv/XiaomiRobotVacuumProtocol github? I know the miio guys check there for newly discovered commands.
Hopefully someone will figure out the virtual walls soon
On December 14, 2018 11:16:48 AM UTC, JohnRev notifications@github.com wrote:
I think I was able to get the saved map functionality to work. Would you be willing to test it?
- Do a full sweet to generate the map to be saved
- Install python-miio
pip install python-miio
, then execute the following (replacing with the correct variables, obviously).- Execute: {code} export MIROBO_IP=vacuum_ip export MIROBO_TOKEN=vacuum_token_key
mirobo raw-command "set_lab_status" 1 mirobo raw-command "save_map {code}
- Reboot the vacuum
- Do a new sweep
-- You are receiving this because you were mentioned. Reply to this email directly or view it on GitHub: https://github.com/Hypfer/Valetudo/issues/44#issuecomment-447295298
Posted it there https://github.com/marcelrv/XiaomiRobotVacuumProtocol/issues/15#issue-391360556 with some additional info
How are virtual walls stored?
@Hypfer : These are possibly stored in /mnt/data/rockrobo/user_map0
and/or /mnt/data/rockrobo/PersistData*.data
.
Other interesting files: /dev/shm/PersistInfo
, /dev/shm/SharedMapInfo
@JohnRev after the scheduled reboot (every day my vacuum reboots on its own at 3:30am) the maps were not visible any more in valetudo - again only the last part of the track was visible. i removed dummycloud and checked with the official app - the map is saved correctly and all settings are as well correct. I made a full factory reset of the device and made a sweep. Maps were saved (persistent files were generated). After a reboot, boom, maps were gone again in valetudo. I am out of ideas...
Hmm... I haven't faced this issue yet, and I have been rebooting my vacuum daily. Are you getting error 500 in Valetudo? Maybe the issue is from what I described here: https://github.com/Hypfer/Valetudo/issues/40#issuecomment-446504197 ?
Also, would you be willing to try all the steps, including the mirobo commands, from my earlier comment (https://github.com/Hypfer/Valetudo/issues/44#issuecomment-447295298)? I think this was the only difference between what you have done and what I have.
@leonardpitzu & @JohnRev Why do you reboot your device daily if I may ask?
For some reason that I haven't been able to figure out yet, my vacuum loses connection to my wifi overnight (but otherwise remains functional), and so I must reboot it to get it connected to my router again
@JohnRev done that. No change at all. What those commands do is identical to what the original app does. I've done the same settings with both and still the same behaviour. I also encounter #40 but i overcome it by removing the new folder. Still, the map is not visible from the "old" folder - only the track (see attached screenshots - one is valetudo, the other is the original app. both screencaps are after a manual reboot [sudo shutdown -r now]). @herrwusel i'm not rebooting it - it does so on its own at 3:30 every morning. It's some sort of scheduled tasks. I would assume all vacuums do so but you don't see it because either you're not monitoring the network or you don't have startup/shutdown/reboot notifications as i do.
@leonardpitzu Would you be willing to sharing the latest .rr.gz navmaps from the newest folder?
@JohnRev here you go (there are also some new generated folder so you can have an idea what happens @reboot). Archive.zip
# gzip -d /000548.20181215162410931_R0018S81502125_2018101702REL/navmapfirst.ppm.log.rr.gz
gzip: navmapfirst.ppm.log.rr.gz: decompression OK, trailing garbage ignored
After reboot, your navmapfirst.ppm is empty (or corrupt?), and that is why the map is blank and Valetudo can't display it. The official app probably pulls the map from the Mi cloud, and that's why it's displayed (just a guess)
I don't know why your navmapfirst.ppm.log.rr.gz is like that ... My guess is the "saved" persistent map is incorrect, or incomplete somehow? Maybe re-save a new one with the mi app?
Btw, is there a file /mnt/data/rockrobo/user_map0
on your vacuum? What's it size?
@JohnRev user_map0 is 198k. i'll try a fsck... the map is resaved. i made a new one this morning, rebooted and valetudo is what you see it above...
nvmap attached in new rr.gz format
navmapfirst.ppm.log.rr.gz