Dahua adapter: support shallow folder layout (MM.SS filenames) #135

Closed
opened 2026-08-12 02:30:29 +00:00 by agent-pi · 1 comment
Collaborator

Some Dahua cameras use a shallower folder structure than what the adapter currently handles.

Deep format (currently supported):

{serial}/{date}/{channel}/jpg/{HH}/{MM}/{SS}[flags].jpg

Example: AL096ADPAGE8458/2026-08-12/001/jpg/12/24/33[R][0@0][0].jpg

Shallow format (new cameras):

{serial}/{date}/{channel}/jpg/{HH}/{MM}.{SS}[flags].jpg

Example: AF007D8PAG5B66F/2026-08-12/001/jpg/12/16.36[M][0@0][0].jpg

Two differences:

  1. No MM/ subdirectory — .jpg files sit directly in jpg/{HH}/
  2. Filename encodes both minutes and seconds: MM.SS[flags] instead of just SS[flags]

The adapter must handle both layouts.

Some Dahua cameras use a shallower folder structure than what the adapter currently handles. **Deep format (currently supported):** ``` {serial}/{date}/{channel}/jpg/{HH}/{MM}/{SS}[flags].jpg ``` Example: `AL096ADPAGE8458/2026-08-12/001/jpg/12/24/33[R][0@0][0].jpg` **Shallow format (new cameras):** ``` {serial}/{date}/{channel}/jpg/{HH}/{MM}.{SS}[flags].jpg ``` Example: `AF007D8PAG5B66F/2026-08-12/001/jpg/12/16.36[M][0@0][0].jpg` Two differences: 1. No `MM/` subdirectory — `.jpg` files sit directly in `jpg/{HH}/` 2. Filename encodes both minutes and seconds: `MM.SS[flags]` instead of just `SS[flags]` The adapter must handle both layouts.
Author
Collaborator

Plan

Root cause: The adapter's _all_snapshots_in_channel() iterates jpg_root → hh_dir → mm_dir → *.jpg. The new camera has no mm_dir — its .jpg files live directly in hh_dir. Similarly, _parse_snapshot_time() assumes the filename stem is SS[flags], but the new camera produces MM.SS[flags].

Changes (all in src/cang/adapters/dahua.py):

  1. _parse_snapshot_time() — accept a new parameter or detect the format. If the filename stem contains a ., parse it as MM.SS with minutes from the filename and the hour still from the parent directory. Otherwise fall back to the existing SS-only parse with minutes from the grandparent directory.

  2. _snapshots_in_minute_dir() — when called for the shallow format, the jpg's parent is the HH directory (not an MM directory), so we need the filename to supply the minutes.

  3. _all_snapshots_in_channel() — after iterating MM directories (deep format), also check for .jpg files directly in each hh_dir (shallow format). Pass an indicator so the parse function knows which format to use.

Approach: The cleanest path is to modify _parse_snapshot_time() to accept an optional mm_from_dir parameter. In the shallow format the filename carries minutes, so we don't read the parent dir for minutes. In _all_snapshots_in_channel(), add a fallback that checks for .jpg files in the hh_dir itself when no mm_dir subdirectories are found.

Branch: fix/issue-135-shallow-dahua-layout

Commits:

  • 🧪 Add failing test for shallow Dahua layout
  • 🐛 Support shallow Dahua folder layout in adapter

PR: fj pr create targeting main

**Plan** **Root cause:** The adapter's `_all_snapshots_in_channel()` iterates `jpg_root → hh_dir → mm_dir → *.jpg`. The new camera has no `mm_dir` — its `.jpg` files live directly in `hh_dir`. Similarly, `_parse_snapshot_time()` assumes the filename stem is `SS[flags]`, but the new camera produces `MM.SS[flags]`. **Changes (all in `src/cang/adapters/dahua.py`):** 1. **`_parse_snapshot_time()`** — accept a new parameter or detect the format. If the filename stem contains a `.`, parse it as `MM.SS` with minutes from the filename and the hour still from the parent directory. Otherwise fall back to the existing `SS`-only parse with minutes from the grandparent directory. 2. **`_snapshots_in_minute_dir()`** — when called for the shallow format, the jpg's parent *is* the HH directory (not an MM directory), so we need the filename to supply the minutes. 3. **`_all_snapshots_in_channel()`** — after iterating MM directories (deep format), also check for `.jpg` files directly in each `hh_dir` (shallow format). Pass an indicator so the parse function knows which format to use. **Approach:** The cleanest path is to modify `_parse_snapshot_time()` to accept an optional `mm_from_dir` parameter. In the shallow format the filename carries minutes, so we don't read the parent dir for minutes. In `_all_snapshots_in_channel()`, add a fallback that checks for `.jpg` files in the `hh_dir` itself when no `mm_dir` subdirectories are found. **Branch:** `fix/issue-135-shallow-dahua-layout` **Commits:** - :test_tube: Add failing test for shallow Dahua layout - :bug: Support shallow Dahua folder layout in adapter **PR:** `fj pr create` targeting `main`
Sign in to join this conversation.
No labels
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
marvin8/cang#135
No description provided.