niceboygithub / AqaraGateway

Aqara Gateway/Hub integration for Home Assistant
489 stars 64 forks source link

Aqara Hub G3 #63

Closed Wh1terat closed 2 years ago

Wh1terat commented 2 years ago

Hi,

I've worked out root access for the G3 hub:

https://github.com/Wh1terat/aQRootG3

Would you be willing to look to add support?

Thanks

niceboygithub commented 2 years ago

Sure. I wait for soft hack on G3 for long time

thanks for your great work

Wh1terat commented 2 years ago

Thank you for the kind words πŸ˜ƒ

It was a fun challenge, had to think a little out of the box for the solution!

I mainly did it for rtsp support for the camera so I could integrate into Hass without p2p crap πŸ˜… but of course telnet access will help in your project too!

niceboygithub commented 2 years ago

lumi did not remove rtsp app. I think the next step to find the way to control camera head(ptz)

niceboygithub commented 2 years ago

360p: rtsp:/10.0.1.69:8554/360p 720p":"rtsp://10.0.1.69:8554/720p 1080p":"rtsp://10.0.1.69:8554/1080p

Wh1terat commented 2 years ago

Indeed. But rtsp daemon either does not start or starts with auth required.

Unless I'm missing something obvious

niceboygithub commented 2 years ago

it doesn’t start as default

but it can be added to post_init.sh if user want to rtsp

BTW, you python script also works on FW 3.2.7_0019.004

Wh1terat commented 2 years ago

I worked that out πŸ˜ƒ

Great! Thanks, is it Chinese version?

niceboygithub commented 2 years ago

I worked that out πŸ˜ƒ

Great! Thanks, is it Chinese version?

G3 is China version.

rtsp binary does not exist in fw 3.2.7 but exists in fw 3.3.2.

Wh1terat commented 2 years ago

Thanks! I've updated Readme :) Just had to unbrick my G3 via uart 🀦 I really should pay more attention. (Damn "!" expansion)

You got me thinking about rtsp and you're right, it is usually started - but looks like the post init generated by fw_manager doesn't include it.

So was thinking this payload is closer to factory:

        "d": ";".join(
            [
                domain,
                'x="fw_""manager.sh"',
                "$x -t -k",
                "$x -t -f",
                'echo -e "#\x21/bin/sh\\n$x -r\\n$x -t -k">/data/scripts/post_init.sh',
            ]

Which just fits. (129/132)

(The first fw_manager call isn't really needed but there was room, just means you can telnet to it before bind fails.)

So new post_init we're calling fw_manager runner and then enabling tty & telnet, like the original init script(ish):

CUSTOM_POST_INIT=/data/scripts/post_init.sh
if [ -x ${CUSTOM_POST_INIT} ]; then
    ${CUSTOM_POST_INIT} &
else
    asetprop sys.camera_ptz_moving true
    fw_manager.sh -r
fi

It does miss out:

asetprop sys.camera_ptz_moving true

But I'm not entirely sure what this is used for since the ptz function works fine without it?

Also figured no need to chmod as nothing should be overwriting it and it's already got execute bit.

niceboygithub commented 2 years ago

Thanks! I've updated Readme :) Just had to unbrick my G3 via uart 🀦 I really should pay more attention. (Damn "!" expansion)

The hacking is high risk. I also did the stupid think on post_init.sh before. XD

So was thinking this payload is closer to factory:

I found G3 is not easy to connect if using "fw_manager.sh -t -f" to generate post_init.sh.

I will recommand to use "fw_manager.sh -r" in post_init.sh

The better post_init.sh shall be like

#!/bin/sh

asetprop sys.camera_ptz_moving true
fw_manager.sh -r &
fw_manager.sh -t -k

So I suggest that let user use your script to enable telnet. After enabled telnet, ask user to have another post_init.sh

likes

wget -O /tmp/post_init.sh "http://somewhere.dl.sourceforge.net/project/aqrootg3/bin/post_init.sh?viasf=1"
chmod a+x /tmp/post_init.sh
[ "$(md5sum /tmp/post_init.sh)" != "bbc7e1da0fd531a48a9c29eeaec97e4b /tmp/post_init.sh" ] && cp -f /tmp/post_init.sh /data/scripts/post_init.sh
chattr +i /data/scripts/post_init.sh

Anyway, that is my little suggestion. You may have better solution.

Wh1terat commented 2 years ago

Thankfully it is well built and not too difficult to disassemble, plus uart pins are marked on the board which is a huge help!

echo enable > /sys/class/tty/tty/enable
telnetd &

are both achieved by "fw_manager.sh -t -k":

test_user_behavior()
{
    # Enable Uart.
    echo enable > /sys/class/tty/tty/enable

    # Start telnet.
    local running=`pgrep telnetd`
    if [ "$running" = "" ]; then telnetd; fi
}

and no need to push telnetd to background, it backgrounds by default.

But even then, your payload would be too long.

I rely upon "fw_manager.sh -t -f" in my example above because it creates dir if not exist and sets executable flag and then I overwrite the file anyway. It is shorter.

Oh the sky is the limit once telnet is enabled, but can leave to that others to implement πŸ˜„

niceboygithub commented 2 years ago

You are right.

Another question. How do you open G3. It is not easy to open it.

Wh1terat commented 2 years ago

Ah you edited just before I posted πŸ˜„

Even with:

#!/bin/sh

asetprop sys.camera_ptz_moving true
fw_manager.sh -r &
fw_manager.sh -t -k

In it's shortest form becomes: nsloolup aiot-coap.aqara.cn;x="fw_""manager.sh";$x -t -f;echo -e "#\x26/bin/sh\nasetprop sys.camera_ptz_moving true\n$x -r\n$x -t -k">/data/scripts/post_init.sh

Which is 29 bytes over the buffer and will not be executed.

I tried every which way I could to fit it all in one go. πŸ€·β€β™‚οΈ

Wh1terat commented 2 years ago

Brain dump:

Remove 2x rubber bungs on back of top section and remove 2x screws behind. Remove rubber ring from base, 4x more screws. Remove plastic cover from base Remove 1x screw holding rotating base and remove (keep cable attached). Remove 2x screws holding lower case together - now the case will separate, remove front not back. Remove 1x screw top right next to camera lens and pull camera to right. Disconnect ribbon cable between middle board and camera "head". Remove tilt motor (2 screws) Remove 2 remaining screws from heatsink plate Done. You can see tx/rx/gnd marked next to SoC.

niceboygithub commented 2 years ago

Brain dump:

Remove 2x rubber bungs on back of top section and remove 2x screws behind. Remove rubber ring from base, 4x more screws. Remove plastic cover from base Remove 1x screw holding rotating base and remove (keep cable attached). Remove 2x screws holding lower case together - now the case will separate, remove front not back. Remove 1x screw top right next to camera lens and pull camera to right. Disconnect ribbon cable between middle board and camera "head". Remove tilt motor (2 screws) Remove 2 remaining screws from heatsink plate Done. You can see tx/rx/gnd marked next to SoC.

Thanks

I bricked my G3 after few tests too. >_<

niceboygithub commented 2 years ago

Even with: In it's shortest form becomes: nsloolup aiot-coap.aqara.cn;x="fw_""manager.sh";$x -t -f;echo -e "#\x26/bin/sh\nasetprop sys.camera_ptz_moving true\n$x -r\n$x -t -k">/data/scripts/post_init.sh

Which is 29 bytes over the buffer and will not be executed.

"$x -t -f;" can be removed. but it is still over 10 chars

"asetprop sys.camera_ptz_moving true" is too long.

Wh1terat commented 2 years ago

Nope. If you remove "$x -t -f;" what will create /data/scripts directory and how to set execute bit on script? mkdir -f /data/scripts and chmod +x /data/scripts/post_init.sh is much longer

yeah prop is too long.

My sed is too rusty to work out shorter way to do "tail -n3 /e/i/S9* | head -n 2" which would give us:

    asetprop sys.camera_ptz_moving true
    fw_manager.sh -r

Might be enough πŸ€·β€β™‚οΈ

niceboygithub commented 2 years ago

Nope. If you remove "$x -t -f;" what will create /data/scripts directory and how to set execute bit on script? mkdir -f /data/scripts and chmod +x /data/scripts/post_init.sh is much longer

yeah prop is too long.

My sed is too rusty to work out shorter way to do "tail -n3 /e/i/S9* | head -n 2" which would give us:

    asetprop sys.camera_ptz_moving true
    fw_manager.sh -r

Might be enough πŸ€·β€β™‚οΈ

You are right again. if remove "$x -t -f" , need chmod a+x.. so "$x -t -f" is better

niceboygithub commented 2 years ago

Brain dump:

Remove 2x rubber bungs on back of top section and remove 2x screws behind. Remove rubber ring from base, 4x more screws. Remove plastic cover from base Remove 1x screw holding rotating base and remove (keep cable attached). Remove 2x screws holding lower case together - now the case will separate, remove front not back. Remove 1x screw top right next to camera lens and pull camera to right. Disconnect ribbon cable between middle board and camera "head". Remove tilt motor (2 screws) Remove 2 remaining screws from heatsink plate Done. You can see tx/rx/gnd marked next to SoC.

Thanks for your instructions I unbricked my G3..

8319765C-526A-415A-A72A-95B632ACFE89

Wh1terat commented 2 years ago

Good work @niceboygithub πŸ‘

rezmus commented 2 years ago

@Wh1terat global g3 has 100% same fw.

Wh1terat commented 2 years ago

Thanks @rezmus, I wondered if it did. I suspect the only difference is properties - would be interesting to compare differences from a global / european agetprop dump.

rezmus commented 2 years ago

@Wh1terat it is just the model on factory mtd from which prop.dat is recreated during factory reset (persist.sys.model in db). global is lumi.camera.gwpgl1, cn lumi.camera.gwpagl01. global also should have more voices.

btw: when your bug is used on d (coap server address) camera should be able to connect to wifi, but not cloud (wrong server address because on added payload). how it behave in this case? does it spawn pairing mode again by itself or you have to reboot/reset it again? for how long you can access telnetd temporarily spawned by fw_manager.sh -t -k? i know there is permanent in post_init.sh, but i mean temp one.

Wh1terat commented 2 years ago

Ah didn't realise model was different, but did suspect it was just a prop setting. prop.dat format is based on https://github.com/peterGraf/pbl/ (obscure choice from Aqara there)

If you submit a valid bind_key it would actually root and pair in one go, but the work involved to get a valid bind_key was excessive vs a 2 step play.

Domain is largely irrelevant to be honest. I did use a single letter at times to try to get more space for the payload and seemed fine in that it'll just fail binding still.

It'll disconnect from wifi as soon as binding has failed - but you could just put a long sleep or infinite loop in the payload to keep wifi connected and telnet open, it's what I was doing during testing. Then when you kill the nslookup process it'll continue and tell you bind failed.

Once binding has failed it should go back to waiting for another qrcode or you can hold button for 10 secs to start pairing again without reboot/reset.

rezmus commented 2 years ago

@Wh1terat tx for info. i always thought coap server is cloud server device should connect to

[persist.app.prior_domain]: [coap-ger.aqara.com]
[persist.app.country_domain]: [coap-ger.aqara.com]

so if you tamper it (add payload) it should fail to connect anyway.

Wh1terat commented 2 years ago

@rezmus Thanks for the idea, I set persist.sys.model to lumi.camera.gwpgl1 and it allowed me to pair to EU server and all working. πŸ˜„

Wh1terat commented 2 years ago

@rezmus Spoke too soon. somehow there is something different with ptz control between gwpgl1 and gwpagl01 from the app. I guess gwpgl1 is not G3 ? or maybe EU model changed something subtle with PTZ control.

If you have EU model could you share your ro.sys props or better still, copy of mtd10 ?

Scrap that. Think my stepper motor is busted.

niceboygithub commented 2 years ago

@rezmus Spoke too soon. somehow there is something different with ptz control between gwpgl1 and gwpagl01 from the app. I guess gwpgl1 is not G3 ? or maybe EU model changed something subtle with PTZ control.

If you have EU model could you share your ro.sys props or better still, copy of mtd10 ?

Scrap that. Think my stepper motor is busted.

Are you still using the post_init.sh that created by "-t -f". if yes, you may need to use rewrite the post_init.sh to run "fw_manger.sh -r" user program.

rezmus commented 2 years ago

@Wh1terat i dont have any g3. both models are g3 for different markets. firmware ota is exactly same so all ro. props will be same, however there might be some differences in factory props, res and/or data. in past i did convert both cn g2h and e1 hub to global versions by just change of model and had no issues so far.

niceboygithub commented 2 years ago

Ah you edited just before I posted πŸ˜„

Even with:

#!/bin/sh

asetprop sys.camera_ptz_moving true
fw_manager.sh -r &
fw_manager.sh -t -k

In it's shortest form becomes: nsloolup aiot-coap.aqara.cn;x="fw_""manager.sh";$x -t -f;echo -e "#\x26/bin/sh\nasetprop sys.camera_ptz_moving true\n$x -r\n$x -t -k">/data/scripts/post_init.sh

Which is 29 bytes over the buffer and will not be executed.

I tried every which way I could to fit it all in one go. πŸ€·β€β™‚οΈ

After few tests sys.camera_ptz_moving in post_init.sh can be ignore.

Wh1terat commented 2 years ago

@rezmus I don't think OTA is exactly the same.

From fw_unpack:

    iVar4 = strncmp("lumi.camera.gwpagl01",model_id,0x14);
    if ((iVar4 != 0) && (iVar4 = strncmp("lumi.camera.gwpgl1",model_id,0x12), iVar4 != 0)) {
      puts("modle_id is not match!!!");
      exit(1);
    }

Although rootfs may well be identical and I'm sure zb/ir firmware will be too.

It would seem somehow my stepper motor has for the 360 rotation has failed - bizarrely at exactly the same time as testing EU server πŸ˜• ordered replacement motor but from Ali so will be a few weeks.

If it was more popular device I'd maybe ask for donations and then keep this one as test device πŸ˜‡

@niceboygithub : I came to the same conclusion, sys.camera_ptz_moving appears to just change when ptz is in motion, not like some key to say it supports ptz.

I was using:

        "d": ";".join(
            [
                domain,
                'x="fw_man""ager.sh"',
                '$x -t -f',
                'echo -e "#\\x21/bin/sh\\n$x -r\\n$x -t -k">/data/scripts/post_init.sh',

            ]
        ),

But interestingly despite being within buffer size, ha_master crashes so have to hold down button after to pair with legit qrcode afterwards.

rezmus commented 2 years ago

@Wh1terat it is 100% same ota file (same md5). they always send lumi.camera.gwpagl01 in ota header for both models and fw_unpack will fail only if model in ota header is different than lumi.camera.gwpagl01 or lumi.camera.gwpgl1.

Wh1terat commented 2 years ago

@rezmus Ah that makes sense. You seem very familiar with this πŸ˜…

niceboygithub commented 2 years ago

He is expert of experts.

rezmus commented 2 years ago

nah, my knowledge of aqara/lumi devices is just a piece of puzzle.