Skip to content

[DRAFT] Add additional commands to control the camera - #6

Draft
magicus wants to merge 13 commits into
datenstau:masterfrom
magicus:master
Draft

[DRAFT] Add additional commands to control the camera#6
magicus wants to merge 13 commits into
datenstau:masterfrom
magicus:master

Conversation

@magicus

@magicus magicus commented Nov 7, 2023

Copy link
Copy Markdown

Hi @datenstau,

Im very grateful for the work you have done here! I have a camera of unknown model (prefix "DGOD"), that was using the "vi365" app. I have downloaded the APK and started to reverse engineer it. Here are the result of some of my findings, commands to control the white illumination led, pan and tilt ("PTZ") camera motors and a way to query the camera for some information.

This is all still very preliminary, and right now this functionality cannot even be called without hacking run.js, but I thought it was better that I opened up a draft PR to show what I am working on.

@Bluscream

Bluscream commented Jan 15, 2024

Copy link
Copy Markdown

How did you get the needed data? like

    let fixed_data = {
      user: 'admin',
      pwd: '6666',
      devmac:'0000'
    }

I can't control my ptz or lamps for example:

PS C:\Users\blusc\Desktop\PPPP> node .\run.js -b 192.168.169.255
{ port: 3000, broadcastip: '192.168.169.255' }
bind options:[object Object]
socket listening 0.0.0.0:54613
broadcast Message sent.
MSG_PUNCH received
MSG_P2P_RDY received
connected! { address: '192.168.169.100', port: 25186 }
{"pro":"stream","cmd":111,"video":1,"user":"admin","pwd":"6666","devmac":"0000"}
DRW packet sent (len: 96)
CMD sent: {"pro":"stream","cmd":111,"video":1,"user":"admin","pwd":"6666","devmac":"0000"}
CMD Response received
CMD Response: {
        "cmd":  111,
        "result":       0
}
{
[::ffff:127.0.0.1] GET: /params
{"pro":"get_parms","cmd":101,"user":"admin","pwd":"6666","devmac":"0000"}
DRW packet sent (len: 89)
CMD sent: {"pro":"get_parms","cmd":101,"user":"admin","pwd":"6666","devmac":"0000"

Bluscream@398b9e2#diff-f37164ed621e6f1db870a6fa99420258869ae02f4e9d0a3de9e75a5d7910065c

@magicus

magicus commented Jan 15, 2024

Copy link
Copy Markdown
Author

@Bluscream I sniffed the traffic using Wireshark.

@Bluscream

Bluscream commented Jan 15, 2024

Copy link
Copy Markdown

@Bluscream I sniffed the traffic using Wireshark.

from you phone?

EDIT: Hmm, i got a pcap using PCAPAndroid but it seems like the credentials are the same as mine. I'm at a loss why all commands work on the app but none work using your fork :/

((ip.src == 10.215.173.1) && (_ws.col.info contains "MSG_DRW:")) && !(_ws.col.info contains "Len=90 (MSG_DRW:0;0)")

@Bluscream

Bluscream commented Jan 15, 2024

Copy link
Copy Markdown

Okay, i got something to work, but it seems like after some time/when i submit a command that works it just closes the connection:

PS C:\Users\blusc\Desktop\PPPP> node .\run.js -b 192.168.169.255
{ port: 3000, broadcastip: '192.168.169.255' }
bind options:[object Object]
socket listening 0.0.0.0:63605
broadcast Message sent.
MSG_PUNCH received
MSG_P2P_RDY received
connected! { address: '192.168.169.100', port: 24860 }
{"pro":"stream","cmd":111,"video":1,"user":"admin","pwd":"6666"}
DRW packet sent (len: 80)
CMD sent: {"pro":"stream","cmd":111,"video":1,"user":"admin","pwd":"6666"}
CMD Response received
CMD Response: {
        "cmd":  111,
        "result":       0
}
{
[::1] GET: /v.mjpg
[::1] GET: /lightoff
{"pro":"set_whiteLight","cmd":304,"status":0,"user":"admin","pwd":"6666"}
DRW packet sent (len: 89)
CMD sent: {"pro":"set_whiteLight","cmd":304,"status":0,"user":"admin","pwd":"6666"}
        "cmd":  304,
[::1] GET: /iroff
{"pro":"dev_control","cmd":102,"icut":0,"user":"admin","pwd":"6666"}
DRW packet sent (len: 84)
CMD sent: {"pro":"dev_control","cmd":102,"icut":0,"user":"admin","pwd":"6666"}
MSG_CLOSE received

@Bluscream

Copy link
Copy Markdown

I have it up and running now, it's just not very stable xD

@magicus

magicus commented Jan 16, 2024

Copy link
Copy Markdown
Author

Yes, it is not stable. :-( The connection is easily dropped. Restarting the scripts reconnects; so this method can be used as a simple workaround. Since the app is stable, I believe the problem is that some part of the protocol that is responsible for "keep alive" status of the stream is not properly represented in the script.

In the end, it was a bit too much work left for me to actually finish the script, and my camera is just collecting dust right now. If you want to do some more research, have a look at my clone of this repo, and my pppp dissector for Wireshark.

I also got to the point where I did not want to keep extending the javascript code, but wanted a proper rewrite in python (for easier integration with Home Assistant). I created https://github.com/magicus/pypppp for that purpose but never got around more than just adding the basic boilerplate code. :(

@magicus

magicus commented Jan 16, 2024

Copy link
Copy Markdown
Author

I also wrote a specification document here: https://github.com/magicus/pppp-dissector/blob/main/PPPP.md. The parts that are written describes the protocol with a fairly high quality, but it is missing most of the commands.

@Bluscream

Copy link
Copy Markdown

Yes, it is not stable. :-( The connection is easily dropped. Restarting the scripts reconnects; so this method can be used as a simple workaround. Since the app is stable, I believe the problem is that some part of the protocol that is responsible for "keep alive" status of the stream is not properly represented in the script.

I have implemented a /reconnect endpoint, and a auto reconnect but its more of a workaround than an actual fix.

In the end, it was a bit too much work left for me to actually finish the script, and my camera is just collecting dust right now. If you want to do some more research, have a look at my clone of this repo, and my pppp dissector for Wireshark.

I used your pppp dissector to read the pcaps in the first place. Thanks for that

I also got to the point where I did not want to keep extending the javascript code, but wanted a proper rewrite in python (for easier integration with Home Assistant). I created https://github.com/magicus/pypppp for that purpose but never got around more than just adding the basic boilerplate code. :(

this is where the magic will happen i guess? I prefer python over javascript any day lol. The only thing i can't convert are the libraries

@magicus

magicus commented Jan 16, 2024

Copy link
Copy Markdown
Author

I have implemented a /reconnect endpoint, and a auto reconnect but its more of a workaround than an actual fix.

At least it's something. I'll see if I get some time to try running your code. If I can actually get this to work fore more than 5 minutes I might be more interested in picking up this project again. :)

@Bluscream

Bluscream commented Jan 16, 2024

Copy link
Copy Markdown

At least it's something. I'll see if I get some time to try running your code. If I can actually get this to work fore more than 5 minutes I might be more interested in picking up this project again. :)

Neat, i hope we can reuse some of the A9 server hass addon for this and integrate it. My discord is blu#3821

EDIT:

Interesting error i got:

(node:2935817) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 end listeners added to [PassThrough]. Use emitter.setMaxListeners() to increase limit
(Use `node --trace-warnings ...` to show where the warning was created)
(node:2935817) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 data listeners added to [PassThrough]. Use emitter.setMaxListeners() to increase limit

I also started work on a python branch: https://github.com/Bluscream/PPPP/tree/python

Now i also added a rest_command yaml file to my homeassistant to control it via service calls:

pppp_reconnect:
  url: "http://192.168.2.38:2999/reconnect?pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_reboot:
  url: "http://192.168.2.38:2999/func/sendCMDReboot?pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_light_on:
  url: "http://192.168.2.38:2999/func/sendCMDSetWhiteLight?isOn=true&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_light_off:
  url: "http://192.168.2.38:2999/func/sendCMDSetWhiteLight?isOn=false&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_ir_on:
  url: "http://192.168.2.38:2999/func/sendCMDIr?isOn=true&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_ir_off:
  url: "http://192.168.2.38:2999/func/sendCMDIr?isOn=false&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_lamp_on:
  url: "http://192.168.2.38:2999/func/sendCMDLamp?isOn=true&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_lamp_off:
  url: "http://192.168.2.38:2999/func/sendCMDLamp?isOn=false&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_rotate_left_start:
  url: "http://192.168.2.38:2999/func/sendCMDPtzControl?direction=4&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_rotate_left_end:
  url: "http://192.168.2.38:2999/func/sendCMDPtzControl?direction=5&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_rotate_right_start:
  url: "http://192.168.2.38:2999/func/sendCMDPtzControl?direction=6&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_rotate_right_end:
  url: "http://192.168.2.38:2999/func/sendCMDPtzControl?direction=7&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_rotate_up_start:
  url: "http://192.168.2.38:2999/func/sendCMDPtzControl?direction=0&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_rotate_up_end:
  url: "http://192.168.2.38:2999/func/sendCMDPtzControl?direction=1&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_rotate_down_start:
  url: "http://192.168.2.38:2999/func/sendCMDPtzControl?direction=2&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_rotate_down_end:
  url: "http://192.168.2.38:2999/func/sendCMDPtzControl?direction=3&pw=p4%24%24w%C3%B6rd"
  timeout: 5
pppp_rotate_reset:
  url: "http://192.168.2.38:2999/func/sendCMDPtzReset?pw=p4%24%24w%C3%B6rd"
  timeout: 5

@magicus

magicus commented Jan 17, 2024

Copy link
Copy Markdown
Author

My understanding of the "A9 server" is that it is for a completely different protocol, and a product that relies on contacting a cloud server for basic operation (which is faked by the server). Apparently "A9" means nothing more than "small IP camera" in the Chinese sellers' vocabulary. :(

I actually bought a secondary camera to get more data on the protocol described here, but it turned out to be of the "AP server" variant.

So I'm not sure there are much hope of consolidation there, but it would of course be interesting to work with that project to try and get the terminology straight to help users navigate the "A9" jungle.

(But then again, I might have misunderstood this; I did not look too deeply into the "A9 server" code)

@Bluscream

Copy link
Copy Markdown

Interesting... btw have you looked at my changes yet?

@Bluscream

Copy link
Copy Markdown

Yay, https://streamable.com/pqg2nk \o/

@magicus

magicus commented Jan 18, 2024

Copy link
Copy Markdown
Author

btw have you looked at my changes yet?

No, sorry. I'm unlikely to be able to get enough spare time to spend at the PPPP protocol for some time, more than a few minutes per day watching PRs... :( I'd love to, but real world constraints are hard to change.

@Bluscream

Copy link
Copy Markdown

That's really sad, i was making good progress on it. The last commit alone has almost 1000 changed lines. And i also started "classifying" a lot of the requests and responses so they're easier to work with ;)

@magicus

magicus commented Jan 18, 2024

Copy link
Copy Markdown
Author

I've started watching your repo now to track your progress. Feel free to ask me questions, and I'll try to answer. I agree that it is more fun to do reverse engineering and development if you are not alone, so I'll try to shoehorn this into my schedule, if at all possible.

@Bluscream

Copy link
Copy Markdown

Here's a rudimentary automation to give semi 90° coverage:

alias: CCTV Room1 Motion
description: ""
trigger:
  - platform: state
    entity_id:
      - input_boolean.camera_room1_motion
    from: "off"
    to: "on"
    for:
      hours: 0
      minutes: 0
      seconds: 1
  - platform: homeassistant
    event: start
condition:
  - condition: state
    entity_id: input_boolean.camera_room1_motion
    state: "on"
action:
  - service: rest_command.pppp_rotate_reset
    data: {}
  - delay:
      hours: 0
      minutes: 0
      seconds: 5
      milliseconds: 0
  - repeat:
      while:
        - condition: state
          entity_id: input_boolean.camera_room1_motion
          state: "on"
      sequence:
        - delay:
            hours: 0
            minutes: 0
            seconds: 5
            milliseconds: 0
        - service: rest_command.pppp_rotate_left_start
          data: {}
        - delay:
            hours: 0
            minutes: 0
            seconds: 2
            milliseconds: 0
        - service: rest_command.pppp_rotate_left_end
          data: {}
        - delay:
            hours: 0
            minutes: 0
            seconds: 5
            milliseconds: 0
        - service: rest_command.pppp_rotate_reset
          data: {}
        - delay:
            hours: 0
            minutes: 0
            seconds: 5
            milliseconds: 0
        - service: rest_command.pppp_rotate_right_start
          data: {}
        - delay:
            hours: 0
            minutes: 0
            seconds: 2
            milliseconds: 0
        - service: rest_command.pppp_rotate_right_end
          data: {}
        - delay:
            hours: 0
            minutes: 0
            seconds: 5
            milliseconds: 0
        - service: rest_command.pppp_rotate_reset
          data: {}
  - delay:
      hours: 0
      minutes: 0
      seconds: 15
      milliseconds: 0
  - service: rest_command.pppp_rotate_reset
    metadata: {}
    data: {}
mode: restart

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants