feat(setup): generate the camera's Alarm Server settings to paste

When a camera has Alarm Server push enabled, the setup form now shows the
camera's Alarm Settings (Destination IP / URL / Protocol / Port) ready to copy,
so the operator never hunts the deviceId or memorises the endpoint.

CRUCIAL: host/port come from the BACKEND address on the camera's subnet
(backendIpForDevice + the server's listen port — the same probe the push-IP
picker uses), NOT window.location.origin (the SPA's dev/proxy origin, which
would wrongly say localhost:5173). Verified live: matches the on-camera config
field-for-field (10.0.10.203 / …/event / HTTP / 3000). Shows a "save first"
(needs a deviceId) then "test first" (needs the resolved backend IP) hint.
i18n keys added to sq + en (parity enforced).

Claude-Session: https://claude.ai/code/session_01Xcm6ikLgGoCxxHrxtjkk5V
This commit is contained in:
2026-06-26 16:47:02 +02:00
parent f0fd15bb88
commit 40de8a7467
3 changed files with 98 additions and 3 deletions
+13
View File
@@ -406,6 +406,19 @@ export const en: Catalog = {
"anprFail.vision-disabled": "Vision service is disabled — enable it (VISION_ENABLED) to test ANPR.",
"anprFail.snapshot-failed": "Couldn't take a snapshot from the camera (offline or unreachable).",
"anprFail.no-plate": "No plate found in the snapshot.",
alarmUrlTitle: "Alarm Server settings (enter these in the camera)",
alarmUrlHint:
"Enter these in the camera at Configuration → Event → … → Alarm Settings (or Notify Surveillance Center). The camera POSTs every event here — no polling.",
alarmUrlCopy: "Copy all",
alarmUrlCopied: "Copied ✓",
alarmUrlSaveFirst:
"Save the camera first — the address is generated once the device has an ID. Re-open it for editing to see it.",
alarmUrlTestFirst:
"Click “Test connection” first — that resolves this host's IP on the camera's network (so the camera can reach it).",
alarmFieldHost: "Destination IP / Host",
alarmFieldUrl: "URL",
alarmFieldProtocol: "Protocol",
alarmFieldPort: "Port",
whichBarrier: "Which barrier does this device serve?",
controller: "Controller",
choose: "Choose…",
+14
View File
@@ -416,6 +416,20 @@ export const sq = {
"anprFail.vision-disabled": "Shërbimi i vizionit është çaktivizuar — aktivizoje (VISION_ENABLED) për ta testuar ANPR.",
"anprFail.snapshot-failed": "Nuk u mor dot pamje nga kamera (jashtë linje ose e paarritshme).",
"anprFail.no-plate": "Nuk u gjet asnjë targë në pamje.",
// Alarm Server push settings — generated for the camera's Event → Alarm Server form.
alarmUrlTitle: "Cilësimet e Alarm Server (vendosi te kamera)",
alarmUrlHint:
"Vendosi këto te kamera: Configuration → Event → … → Alarm Settings (ose Notify Surveillance Center). Kamera do të dërgojë çdo ngjarje këtu — pa polling.",
alarmUrlCopy: "Kopjo të gjitha",
alarmUrlCopied: "U kopjua ✓",
alarmUrlSaveFirst:
"Ruaje kamerën më parë — adresa gjenerohet pasi pajisja të marrë një ID. Hape sërish për editim që ta shohësh.",
alarmUrlTestFirst:
"Kliko “Testo lidhjen” më parë — kështu përcaktohet IP-ja e këtij hosti në rrjetin e kamerës (që kamera ta thërrasë).",
alarmFieldHost: "Destination IP / Host",
alarmFieldUrl: "URL",
alarmFieldProtocol: "Protokolli",
alarmFieldPort: "Porta",
// Binding picker.
whichBarrier: "Cilën barrierë shërben kjo pajisje?",
controller: "Kontrolluesi",