Skip to main content

cs2pppp

A small, zero-dependency (stdlib-only) Python client for the CS2 Network PPPP stack used by CS2-style IoT cameras.

cs2pppp is a stdlib Python client for the CS2 PPPP wire protocol and CS2-style app JSON, where directory servers are always supplied by the caller.

It speaks the protocol wire formats:

  • Directory lookup / Online–Offline–InvalidId probe
  • UDP session (HELLO → wake → relay or direct punch → RDY → ALIVE → DRW)
  • CS2 app-channel JSON framing on the DRW command channel
  • High-level device helpers: login, get info, optional snapshot

What it is not

  • Not an A9/iLnk/Yi LAN library — those forks are out of scope.
  • Not an admin/JWT client, IMEI→DID cloud lookup, or DID generator.
  • It ships no directory IPs, InitStrings, cloud domains, or credentials. You always provide the directory servers.

Install

pip install cs2pppp

Python ≥ 3.9. No required dependencies. (Snapshot decoding uses a system ffmpeg if you call it — not needed for probe/session/info.)

Providing directory servers

There are no built-in defaults. Supply servers when constructing the client.

Get them however you like — commonly by decoding an InitString you already have (e.g. from your own app config), or from an environment variable:

import os
from cs2pppp import Cs2Client, decode_init_string

# Option A: from env
servers = os.environ["CS2_SERVERS"].split(",")   # "ip1,ip2,ip3"
client = Cs2Client(servers=servers)

# Option B: decode a user-supplied InitString blob
decoded = decode_init_string(my_init_blob)       # never bundled by this lib
assert decoded.lib_ok
client = Cs2Client(servers=decoded.servers)

Structured config and a custom port are also supported:

from cs2pppp import Cs2Client, DirectoryConfig
client = Cs2Client(directory=DirectoryConfig(servers=("203.0.113.10",), port=32100))

Providing protocol tables

This library ships no byte tables. The InitString decode LUT and the two cipher tables are the caller's responsibility — supply them the same way you supply directory servers. Provide them from your own configuration and inject them once:

import cs2pppp
cs2pppp.configure_tables(
    lut="...",         # 54 bytes, hex or bytes  — used by decode_init_string
    prop_table="...",  # 256 bytes               — session handshake (0xF9)
    crc_table="...",   # 64 bytes                — crc_enc/crc_dec (research)
)

Or via environment variables (hex): CS2PPPP_LUT, CS2PPPP_PROP_TABLE, CS2PPPP_CRC_TABLE. A function that needs a table you did not supply raises ConfigError. You only need prop_table for a live session, lut for decode_init_string, and crc_table for the CRC research helpers.

Probe

status = client.probe("G100000ZKMNP")
print(status)                 # e.g. "online (0x00 via 203.0.113.10)"
print(status.online, status.offline, status.invalid_id, status.raw_code)
Wire Meaning
0x00 Online
0xFE Offline
0xFF InvalidId
0xFD InvalidPrefix

Device session

# High-level device (context manager opens/closes the UDP session)
with client.device("G100000ZKMNP", password="123456") as dev:
    info = dev.get_info()          # dict from GetDevInfo (+ related)
    # dev.login()                  # already done if password given at open
    # dev.snapshot("out.jpg")      # optional; needs ffmpeg on PATH
    # files = dev.list_tf_videos() # TF/SD card recordings
    # dev.download_tf_file(files[0], "clip.mov")
    # dev.reboot()                 # AppointDev state=1; does not wipe Wi‑Fi
    # dev.factory_reset()          # AppointDev state=2; wipes settings / Wi‑Fi
    # dev.set_led(True)            # SetLed ledstatus=1 (IR / night LED on)

# Low-level session
with client.session("G100000ZKMNP") as sess:
    sess.alive()
    replies = sess.request_json({"cmd": "GetDevInfo"})
    sess.send_json({"cmd": "LoginDev", "pwd": "123456"})
    raw = sess.recv(timeout=2.0)
    from cs2pppp import reboot, factory_reset, set_led
    reboot(sess)                   # same as dev.reboot()
    # factory_reset(sess)          # same as dev.factory_reset(); caller confirms
    # set_led(sess, True)          # SetLed ledstatus=1 (IR / night LED)

TF / SD card videos

List and download recordings stored on the camera card (CS2-style app JSON):

from cs2pppp import list_tf_videos, download_tf_file

with client.device("G100000ZKMNP", password="123456") as dev:
    items = dev.list_tf_videos()           # page starts at 1; bare or envelope JSON
    for it in items:
        print(it.name, it.size_bytes, it.patch)
    if items:
        dev.download_tf_file(items[0], f"/tmp/{items[0].name}")

Notes from live RE:

  • List command: GetTfVideoList with page / count (apps often use 1-based pages).
  • Many firmwares stream one bare JSON object per file (name, patch, size, time) — not a single envelope with cmd=GetTfVideoList. Filtering replies by that command name drops all items.
  • Download: DownloadFile on DRW channel 1, file bytes on channel 3.

The relay path is preferred by default (direct hole-punch often fails on CGNAT). Pass prefer="direct" to try the direct punch first.

DID helpers (format only)

from cs2pppp import parse_did, normalize_did, virtual_to_real, real_to_virtual

normalize_did("G100000ZKMNP")     # "GHBB-100000-ZKMNP" (wire/real form)
virtual_to_real("G100000ZKMNP")   # "GHBB-100000-ZKMNP"
parse_did("GHBB-100000-ZKMNP")    # Did(real=..., virtual=..., network="mykj", ...)

The PREFIX_MAP (virtual letter → real prefix, e.g. F→FHBB) is exported as data — it is protocol identity format, not a server list. There is no offline check-digit generator: this library never claims a DID will be accepted by a directory server.

Security notes

  • The PPPP transport "encryption" is weak obfuscation. cs2pppp.crypto exposes research helpers (derive_key, xor_apply, recover_key, crack_key, crc_enc/crc_dec) for analysing captures. They are not required for normal use.
  • The SSD@cs2-network. session key is a universal, hardcoded protocol constant, not a secret.
  • Prefer devices you own. DIDs and passwords are sensitive — treat them like credentials.

Not affiliated

This project is not affiliated with CS2 Network or any device vendor. Names are used only to describe protocol compatibility.

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cs2pppp-0.2.10.tar.gz (53.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cs2pppp-0.2.10-py3-none-any.whl (57.2 kB view details)

Uploaded Python 3

File details

Details for the file cs2pppp-0.2.10.tar.gz.

File metadata

  • Download URL: cs2pppp-0.2.10.tar.gz
  • Upload date:
  • Size: 53.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cs2pppp-0.2.10.tar.gz
Algorithm Hash digest
SHA256 2d4db67506c2dc1d9ccc63bc3ddaf6e0e949e00c5b65258ccf43d38724329b7c
MD5 e03cab013ae9450931242be2297560f0
BLAKE2b-256 ae410044165a39c5691aa828aec73cc616a9596518b984ab992d1aafa4496f49

See more details on using hashes here.

Provenance

The following attestation bundles were made for cs2pppp-0.2.10.tar.gz:

Publisher: publish.yml on wmarquardt/cs2-pppp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cs2pppp-0.2.10-py3-none-any.whl.

File metadata

  • Download URL: cs2pppp-0.2.10-py3-none-any.whl
  • Upload date:
  • Size: 57.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for cs2pppp-0.2.10-py3-none-any.whl
Algorithm Hash digest
SHA256 8a81f1ed91a0347ce1a9aafafc43ef6d3580f1250075fb6c3b0f264fb15d2f8c
MD5 c3ccdd968edb5f50f45c2d62716389da
BLAKE2b-256 c58357118f05b31752ec1c648af8dba89561e2bfa37082e4c5dccebb2ef895c5

See more details on using hashes here.

Provenance

The following attestation bundles were made for cs2pppp-0.2.10-py3-none-any.whl:

Publisher: publish.yml on wmarquardt/cs2-pppp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.2.11

2 files

This release

0.2.10 This release

2 files

0.2.9

2 files

0.2.8

2 files

0.2.7

2 files

0.2.5

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page