# Hikvision NVR RTSP Playback Compatibility Fix Implementation Plan > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. **Goal:** Make the playback-search endpoint return an RTSP URL that the target Hikvision NVR can actually play while retaining SDK channel `33` for recording lookup. **Architecture:** Extend the existing Hikvision login cache value with immutable device channel metadata read from `NET_DVR_DEVICEINFO_V40`. The playback service uses that metadata to map SDK channel numbers to RTSP display-channel numbers, then passes the resolved RTSP channel to a pure URL builder. RTSP query timestamps keep Beijing clock digits because the target firmware was verified to interpret them as device-local time. **Tech Stack:** Java 8, Spring Boot 2.3.4, HCNetSDK/JNA, Caffeine, JUnit 4, Mockito, Maven. **Execution constraint:** Modify the local `master` worktree only. Do not stage or commit any file. --- ## File map - Create `src/main/java/com/inspect/nvr/service/HikLoginSession.java` — immutable login handle and channel-layout mapping. - Modify `src/main/java/com/inspect/nvr/service/HikLoginService.java` — cache `HikLoginSession` and capture login device metadata while preserving existing `login(NvrInfo)` callers. - Modify `src/main/java/com/inspect/nvr/hik/service/HikNvrPlaybackService.java` — use the login session for the SDK handle and resolved RTSP channel. - Modify `src/main/java/com/inspect/nvr/hik/service/HikPlaybackUrlBuilder.java` — accept an RTSP channel explicitly and retain Beijing clock digits. - Create `src/test/java/com/inspect/nvr/service/HikLoginSessionTest.java` — pure channel mapping coverage. - Create `src/test/java/com/inspect/nvr/service/HikLoginServiceTest.java` — verify SDK device metadata is captured into the cached session. - Modify `src/test/java/com/inspect/nvr/hik/service/HikPlaybackUrlBuilderTest.java` — reproduce `3301` and UTC-conversion regressions. - Modify `src/test/java/com/inspect/nvr/hik/service/HikNvrPlaybackServiceTest.java` — prove SDK search still uses `33` while the URL uses `101`. ## Task 1: Lock down corrected RTSP behavior - [x] Add a URL-builder test that calls `build(request, 1, start, end)` for SDK channel `33` and expects `/Streaming/tracks/101?starttime=20260713T120000Z&endtime=20260713T130000Z`. - [x] Add mapping tests asserting pure-NVR `33 -> 1`, pure-NVR `34 -> 2`, hybrid-DVR `33 -> 17`, and analog-channel ordinal mapping. - [x] Add a login-service test whose mocked `NET_DVR_Login_V40` returns `byChanNum=0`, `byIPChanNum=8`, and `byStartDChan=33`, then assert the returned session maps `33 -> 1`. - [x] Add a playback-service test asserting `NET_DVR_FILECOND_V40.lChannel == 33` while the response URL contains `/Streaming/tracks/101?`. - [x] Run `mvn -Dtest=HikPlaybackUrlBuilderTest,HikLoginSessionTest,HikLoginServiceTest,HikNvrPlaybackServiceTest test` and confirm RED failures are caused by the missing session API, explicit RTSP-channel builder signature, and old UTC behavior. ## Task 2: Implement the minimal production fix - [x] Implement `HikLoginSession` with the existing user ID plus unsigned analog/digital channel counts and starts. Map a covered digital SDK channel after the analog channel count; map a covered analog SDK channel to its ordinal; otherwise return the original channel as a compatibility fallback. - [x] Change `HikLoginService` to cache `HikLoginSession`, add `loginSession(NvrInfo)`, and keep `login(NvrInfo)` delegating to it so existing callers retain the same API. - [x] Change `HikNvrPlaybackService` to use `loginSession`, keep the original request channel in `NET_DVR_FILECOND_V40`, resolve the RTSP channel once, and pass it into every generated record URL. - [x] Change `HikPlaybackUrlBuilder` to calculate `trackId` from the explicit RTSP channel and format the supplied `LocalDateTime` directly as `yyyyMMdd'T'HHmmss'Z'` without converting to UTC. - [x] Re-run the four focused test classes and confirm all are GREEN. ## Task 3: Verify regression safety and the real device - [x] Run `mvn test -DskipTests=false` and confirm zero failures/errors. - [x] Restart only the user-controlled application if explicitly permitted; otherwise use a temporary port to validate the endpoint without stopping the existing 8080 process. - [x] POST the known `channel=33` query and verify the response URL contains track `101` and Beijing digits `120000Z` to `130000Z`, with credentials redacted from diagnostic output. - [x] Probe that returned URL with VLC using the default RTSP transport and require `PLAY 200 OK` plus decoded H.264 NAL units. - [x] Run scoped `git diff --check`, inspect `git status --short`, and confirm no new staging or commit occurred.