mirror of
https://github.com/Sea-Haven-Industries/seahaven-door-unlock-api.git
synced 2026-09-30 04:53:10 +00:00
feat(phones): add T57W door-unlock-with-sp template (#87)
* feat(phones): add T57W door-unlock-with-sp template * feat: add firmware dir and add latest 3cx supported yealink firmware
This commit is contained in:
parent
b43335b4a7
commit
c23f990c6f
6 changed files with 22162 additions and 3 deletions
|
|
@ -7,7 +7,7 @@
|
|||
AWS Lambda middleware that allows Yealink desk phones to unlock the front door and manage lockdown profiles via LenelS2 Elements. Target account is **seahaven-prod** (`011934824531`) under HCP Terraform workspace `seahaven-door-unlock-api-prod`.
|
||||
|
||||
```
|
||||
Yealink T54W/T58W → HTTPS GET (?token=) → API Gateway (token authorizer) → Lambda → LenelS2 Elements API
|
||||
Yealink T54W/T57W/T58W → HTTPS GET (?token=) → API Gateway (token authorizer) → Lambda → LenelS2 Elements API
|
||||
```
|
||||
|
||||
Phones keep `https://doorunlock.seahaven.com`. Cutover is a Route 53 A-record flip in the mgmt zone (`Z06652411XKH89KTZD3XA`). DNS is not managed in this Terraform.
|
||||
|
|
@ -97,7 +97,7 @@ Do not run `cdk deploy` against prod. The GitHub CDK deploy workflow is frozen.
|
|||
|
||||
## Phone Configuration
|
||||
|
||||
Configure DSS keys on the Yealink T54W/T58W (via phone web UI or 3CX):
|
||||
Configure DSS keys on the Yealink T54W/T57W/T58W (via phone web UI or 3CX):
|
||||
|
||||
- **Key 2 — Unlock Door**
|
||||
- Type: URL
|
||||
|
|
@ -115,14 +115,16 @@ Custom 3CX templates are included with door unlock and lockdown URLs hardcoded.
|
|||
|----------|-------|-------|----------|---------|
|
||||
| `yealinkT54W-door-unlock.ph.xml` | T54W | Unlock Door | Managed by 3CX BLF | Dim after 5 min, never sleep |
|
||||
| `yealinkT54W-door-unlock-with-sp.ph.xml` | T54W | Unlock Door | SP1-3 via BLF sync | Dim after 5 min, never sleep |
|
||||
| `yealinkT57W-door-unlock-with-sp.ph.xml` | T57W | Unlock Door | SP1-3 via BLF sync | Dim after 5 min, never sleep |
|
||||
| `yealinkT58W-door-unlock.ph.xml` | T58W | Unlock Door | Lockdown Toggle (Bohemia/Ronkonkoma) | Default T58W display settings |
|
||||
|
||||
Department colleague BLFs are not encoded in these templates. A scheduled Lambda (`door-unlock-api-blf-sync`) writes each Yealink user's 3CX BLF list from that user's first non-DEFAULT 3CX department, excluding the phone's own extension. Extension 100 is always included, even when the XAPI Users list omits it. Unlock and lockdown URL keys stay hardcoded in the template. Shared parking on the T54W+SP template is written by the sync job as 3CX SharedParking BLFs.
|
||||
Department colleague BLFs are not encoded in these templates. A scheduled Lambda (`door-unlock-api-blf-sync`) writes each Yealink user's 3CX BLF list from that user's first non-DEFAULT 3CX department, excluding the phone's own extension. Extension 100 is always included, even when the XAPI Users list omits it. Unlock and lockdown URL keys stay hardcoded in the template. Shared parking on the T54W+SP and T57W+SP templates is written by the sync job as 3CX SharedParking BLFs.
|
||||
|
||||
| Template | Reserved (never write) | Sync-owned parking | Own line | Managed department BLFs | Personal |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| `yealinkT54W-door-unlock.ph.xml` | `blf2` | none | `blf1` | `blf3`–`blf12` | `blf13+` |
|
||||
| `yealinkT54W-door-unlock-with-sp.ph.xml` | `blf2` | `blf3`–`blf5` (SP1–SP3) | `blf1` | `blf6`–`blf15` | `blf16+` |
|
||||
| `yealinkT57W-door-unlock-with-sp.ph.xml` | `blf2` | `blf3`–`blf5` (SP1–SP3) | `blf1` | `blf6`–`blf15` | `blf16+` |
|
||||
| `yealinkT58W-door-unlock.ph.xml` | `blf2`–`blf4` | none | `blf1` | `blf5`–`blf14` | `blf15+` |
|
||||
|
||||
The job authenticates to 3CX XAPI with the existing `afterhours-shift-manager/3cx-*` Secrets Manager values. Invoke `door-unlock-api-blf-sync` with `DRY_RUN=true` for a proposed-XML log and no writes. Set `SMOKE_EXTENSION` to PATCH a single extension. The daily EventBridge rule runs at `09:00 UTC` (05:00 ET during EDT).
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ plaintext, in both the `/unlock` and `/lockdown` query strings, across:
|
|||
- `yealinkT58W-door-unlock.ph.xml`
|
||||
- `yealinkT54W-door-unlock.ph.xml`
|
||||
- `yealinkT54W-door-unlock-with-sp.ph.xml`
|
||||
- `yealinkT57W-door-unlock-with-sp.ph.xml`
|
||||
|
||||
The token is the exact secret the API Gateway authorizer (`lambda/authorizer/authorizer-handler.ts`)
|
||||
validates against SSM SecureString `/seahaven/door-unlock/auth-token` via `timingSafeEqual`.
|
||||
|
|
|
|||
BIN
firmware/T5XW-96.87.0.22.rom
Normal file
BIN
firmware/T5XW-96.87.0.22.rom
Normal file
Binary file not shown.
|
|
@ -19,9 +19,21 @@ test("resolveTemplateId matches longest Sea Haven template first", () => {
|
|||
resolveTemplateId("yealinkT54W-door-unlock-with-sp.ph.xml"),
|
||||
"t54w-door-unlock-with-sp"
|
||||
);
|
||||
assert.equal(
|
||||
resolveTemplateId("yealinkT57W-door-unlock-with-sp.ph.xml"),
|
||||
"t57w-door-unlock-with-sp"
|
||||
);
|
||||
assert.equal(resolveTemplateId("yealinkT54W-door-unlock.ph.xml"), "t54w-door-unlock");
|
||||
assert.equal(resolveTemplateId("yealinkT58W-door-unlock.ph.xml"), "t58w-door-unlock");
|
||||
assert.equal(resolveTemplateId("yealinkT54W.ph.xml"), undefined);
|
||||
assert.equal(resolveTemplateId("yealinkT57W.ph.xml"), undefined);
|
||||
});
|
||||
|
||||
test("T57W+SP slot contract matches T54W+SP", () => {
|
||||
assert.deepEqual(
|
||||
SLOT_CONTRACT["t57w-door-unlock-with-sp"],
|
||||
SLOT_CONTRACT["t54w-door-unlock-with-sp"]
|
||||
);
|
||||
});
|
||||
|
||||
test("parseBlfs reads Line self-close and extension BLFs", () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
export type TemplateId =
|
||||
| "t54w-door-unlock"
|
||||
| "t54w-door-unlock-with-sp"
|
||||
| "t57w-door-unlock-with-sp"
|
||||
| "t58w-door-unlock";
|
||||
|
||||
export interface SharedParkingSlot {
|
||||
|
|
@ -35,6 +36,17 @@ export const SLOT_CONTRACT: Record<TemplateId, SlotContract> = {
|
|||
managedStart: 6,
|
||||
managedEnd: 15,
|
||||
},
|
||||
"t57w-door-unlock-with-sp": {
|
||||
reserved: [2],
|
||||
sharedParking: [
|
||||
{ blfNo: 3, value: "SP1" },
|
||||
{ blfNo: 4, value: "SP2" },
|
||||
{ blfNo: 5, value: "SP3" },
|
||||
],
|
||||
ownLine: 1,
|
||||
managedStart: 6,
|
||||
managedEnd: 15,
|
||||
},
|
||||
"t58w-door-unlock": {
|
||||
reserved: [2, 3, 4],
|
||||
sharedParking: [],
|
||||
|
|
@ -45,6 +57,7 @@ export const SLOT_CONTRACT: Record<TemplateId, SlotContract> = {
|
|||
};
|
||||
|
||||
const TEMPLATE_MATCHERS: { id: TemplateId; needle: string }[] = [
|
||||
{ id: "t57w-door-unlock-with-sp", needle: "yealinkT57W-door-unlock-with-sp" },
|
||||
{ id: "t54w-door-unlock-with-sp", needle: "yealinkT54W-door-unlock-with-sp" },
|
||||
{ id: "t54w-door-unlock", needle: "yealinkT54W-door-unlock" },
|
||||
{ id: "t58w-door-unlock", needle: "yealinkT58W-door-unlock" },
|
||||
|
|
|
|||
22131
yealinkT57W-door-unlock-with-sp.ph.xml
Normal file
22131
yealinkT57W-door-unlock-with-sp.ph.xml
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue