een-api-toolkit 0.3.85 → 0.3.91
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/een-devices-agent.md +21 -0
- package/.claude/agents/een-ptz-agent.md +235 -0
- package/CHANGELOG.md +51 -22
- package/dist/index.cjs +3 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +400 -0
- package/dist/index.js +1079 -951
- package/dist/index.js.map +1 -1
- package/docs/AI-CONTEXT.md +3 -1
- package/docs/ai-reference/AI-AUTH.md +1 -1
- package/docs/ai-reference/AI-AUTOMATIONS.md +1 -1
- package/docs/ai-reference/AI-DEVICES.md +1 -1
- package/docs/ai-reference/AI-EVENT-DATA-SCHEMAS.md +1 -1
- package/docs/ai-reference/AI-EVENTS.md +1 -1
- package/docs/ai-reference/AI-GROUPING.md +1 -1
- package/docs/ai-reference/AI-JOBS.md +1 -1
- package/docs/ai-reference/AI-MEDIA.md +1 -1
- package/docs/ai-reference/AI-PTZ.md +158 -0
- package/docs/ai-reference/AI-SETUP.md +1 -1
- package/docs/ai-reference/AI-USERS.md +1 -1
- package/examples/vue-ptz/.env.example +4 -0
- package/examples/vue-ptz/README.md +221 -0
- package/examples/vue-ptz/e2e/app.spec.ts +58 -0
- package/examples/vue-ptz/e2e/auth.spec.ts +296 -0
- package/examples/vue-ptz/index.html +13 -0
- package/examples/vue-ptz/package-lock.json +1729 -0
- package/examples/vue-ptz/package.json +29 -0
- package/examples/vue-ptz/playwright.config.ts +49 -0
- package/examples/vue-ptz/screenshot-ptz.png +0 -0
- package/examples/vue-ptz/src/App.vue +154 -0
- package/examples/vue-ptz/src/components/ApiLog.vue +387 -0
- package/examples/vue-ptz/src/components/CameraSelector.vue +155 -0
- package/examples/vue-ptz/src/components/DirectionPad.vue +350 -0
- package/examples/vue-ptz/src/components/LiveVideoPlayer.vue +248 -0
- package/examples/vue-ptz/src/components/PositionDisplay.vue +206 -0
- package/examples/vue-ptz/src/components/PositionInput.vue +190 -0
- package/examples/vue-ptz/src/components/PresetManager.vue +538 -0
- package/examples/vue-ptz/src/composables/useApiLog.ts +89 -0
- package/examples/vue-ptz/src/main.ts +22 -0
- package/examples/vue-ptz/src/router/index.ts +61 -0
- package/examples/vue-ptz/src/views/Callback.vue +76 -0
- package/examples/vue-ptz/src/views/Home.vue +199 -0
- package/examples/vue-ptz/src/views/Login.vue +32 -0
- package/examples/vue-ptz/src/views/Logout.vue +59 -0
- package/examples/vue-ptz/src/views/PtzControl.vue +173 -0
- package/examples/vue-ptz/src/vite-env.d.ts +12 -0
- package/examples/vue-ptz/tsconfig.json +21 -0
- package/examples/vue-ptz/tsconfig.node.json +11 -0
- package/examples/vue-ptz/vite.config.ts +12 -0
- package/package.json +1 -1
|
@@ -403,6 +403,27 @@ if (isCameraOnline(camera.status)) {
|
|
|
403
403
|
}
|
|
404
404
|
```
|
|
405
405
|
|
|
406
|
+
## PTZ Camera Support
|
|
407
|
+
|
|
408
|
+
When the user asks about PTZ (Pan/Tilt/Zoom) camera controls, presets, or camera movement,
|
|
409
|
+
**delegate to the `een-ptz-agent`** which has specialized knowledge of:
|
|
410
|
+
- `getPtzPosition()`, `movePtz()`, `getPtzSettings()`, `updatePtzSettings()`
|
|
411
|
+
- Direction pad controls, click-to-center, preset management
|
|
412
|
+
- PTZ automation modes (homeReturn, tour, manualOnly)
|
|
413
|
+
|
|
414
|
+
To check if a camera supports PTZ, use `getCamera(id, { include: ['capabilities'] })` and check
|
|
415
|
+
the nested `capabilities.ptz.capable` field:
|
|
416
|
+
|
|
417
|
+
```typescript
|
|
418
|
+
const result = await getCamera(cameraId, { include: ['capabilities'] })
|
|
419
|
+
const capabilities = result.data?.capabilities as { ptz?: { capable?: boolean } } | undefined
|
|
420
|
+
if (capabilities?.ptz?.capable) {
|
|
421
|
+
// This camera supports PTZ - use een-ptz-agent for PTZ-specific tasks
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
**IMPORTANT:** The capability is at `capabilities.ptz.capable` (nested object), NOT `capabilities.ptzCapable`.
|
|
426
|
+
|
|
406
427
|
## Constraints
|
|
407
428
|
- Always check authentication before API calls
|
|
408
429
|
- Use appropriate status filters to reduce payload
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: een-ptz-agent
|
|
3
|
+
description: |
|
|
4
|
+
Use this agent when working with PTZ camera controls: getting position,
|
|
5
|
+
moving cameras, managing presets, or implementing PTZ control UI
|
|
6
|
+
with the een-api-toolkit.
|
|
7
|
+
model: inherit
|
|
8
|
+
color: orange
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
You are an expert in PTZ (Pan/Tilt/Zoom) camera control with the een-api-toolkit.
|
|
12
|
+
|
|
13
|
+
## Examples
|
|
14
|
+
|
|
15
|
+
<example>
|
|
16
|
+
Context: User wants to add PTZ controls to their app.
|
|
17
|
+
user: "How do I add PTZ controls to my camera view?"
|
|
18
|
+
assistant: "I'll use the een-ptz-agent to help implement PTZ controls using movePtz() and getPtzPosition()."
|
|
19
|
+
<Task tool call to launch een-ptz-agent>
|
|
20
|
+
</example>
|
|
21
|
+
|
|
22
|
+
<example>
|
|
23
|
+
Context: User wants to manage PTZ presets.
|
|
24
|
+
user: "How do I save and load PTZ presets?"
|
|
25
|
+
assistant: "I'll use the een-ptz-agent to implement preset management with getPtzSettings() and updatePtzSettings()."
|
|
26
|
+
<Task tool call to launch een-ptz-agent>
|
|
27
|
+
</example>
|
|
28
|
+
|
|
29
|
+
<example>
|
|
30
|
+
Context: User wants click-to-center functionality.
|
|
31
|
+
user: "How do I make the camera center on where I click in the video?"
|
|
32
|
+
assistant: "I'll use the een-ptz-agent to implement click-to-center using movePtz() with the centerOn move type."
|
|
33
|
+
<Task tool call to launch een-ptz-agent>
|
|
34
|
+
</example>
|
|
35
|
+
|
|
36
|
+
## Context Files
|
|
37
|
+
- docs/AI-CONTEXT.md (overview)
|
|
38
|
+
- docs/ai-reference/AI-AUTH.md (auth is required)
|
|
39
|
+
- docs/ai-reference/AI-DEVICES.md (camera selection)
|
|
40
|
+
- docs/ai-reference/AI-PTZ.md (primary reference)
|
|
41
|
+
- docs/ai-reference/AI-MEDIA.md (live video integration)
|
|
42
|
+
|
|
43
|
+
## Reference Examples
|
|
44
|
+
- examples/vue-ptz/ (complete PTZ control app with live video)
|
|
45
|
+
|
|
46
|
+
## Your Capabilities
|
|
47
|
+
1. Get current PTZ position with getPtzPosition()
|
|
48
|
+
2. Move cameras with movePtz() (position, direction, centerOn)
|
|
49
|
+
3. Get PTZ settings and presets with getPtzSettings()
|
|
50
|
+
4. Update settings, presets, and mode with updatePtzSettings()
|
|
51
|
+
5. Implement direction pad controls
|
|
52
|
+
6. Implement click-to-center on live video
|
|
53
|
+
7. Manage PTZ presets (save, load, delete)
|
|
54
|
+
8. Configure automation modes (homeReturn, tour, manualOnly)
|
|
55
|
+
|
|
56
|
+
## Key Types
|
|
57
|
+
|
|
58
|
+
### PtzPosition
|
|
59
|
+
```typescript
|
|
60
|
+
interface PtzPosition {
|
|
61
|
+
x?: number // Pan (horizontal)
|
|
62
|
+
y?: number // Tilt (vertical)
|
|
63
|
+
z?: number // Zoom level
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### PtzMove (discriminated union)
|
|
68
|
+
```typescript
|
|
69
|
+
// Absolute position
|
|
70
|
+
{ moveType: 'position', x?: number, y?: number, z?: number }
|
|
71
|
+
|
|
72
|
+
// Relative direction
|
|
73
|
+
{ moveType: 'direction', direction: PtzDirection[], stepSize?: PtzStepSize }
|
|
74
|
+
|
|
75
|
+
// Center on point in frame
|
|
76
|
+
{ moveType: 'centerOn', relativeX: number, relativeY: number }
|
|
77
|
+
|
|
78
|
+
type PtzDirection = 'up' | 'down' | 'left' | 'right' | 'in' | 'out'
|
|
79
|
+
type PtzStepSize = 'small' | 'medium' | 'large'
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### PtzSettings
|
|
83
|
+
```typescript
|
|
84
|
+
interface PtzSettings {
|
|
85
|
+
presets: PtzPreset[]
|
|
86
|
+
homePreset: string | null
|
|
87
|
+
mode: PtzMode // 'homeReturn' | 'tour' | 'manualOnly'
|
|
88
|
+
autoStartDelay: number // seconds
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
interface PtzPreset {
|
|
92
|
+
name: string
|
|
93
|
+
position: PtzPosition
|
|
94
|
+
timeAtPreset: number // seconds at preset during tour
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### PtzSettingsUpdate
|
|
99
|
+
```typescript
|
|
100
|
+
interface PtzSettingsUpdate {
|
|
101
|
+
presets?: PtzPreset[]
|
|
102
|
+
homePreset?: string | null
|
|
103
|
+
mode?: PtzMode
|
|
104
|
+
autoStartDelay?: number
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Key Functions
|
|
109
|
+
|
|
110
|
+
### getPtzPosition(cameraId)
|
|
111
|
+
Get current camera position:
|
|
112
|
+
```typescript
|
|
113
|
+
import { getPtzPosition } from 'een-api-toolkit'
|
|
114
|
+
|
|
115
|
+
const { data, error } = await getPtzPosition('camera-123')
|
|
116
|
+
if (data) {
|
|
117
|
+
console.log(`Pan: ${data.x}, Tilt: ${data.y}, Zoom: ${data.z}`)
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### movePtz(cameraId, move)
|
|
122
|
+
Move camera with three move types:
|
|
123
|
+
```typescript
|
|
124
|
+
import { movePtz } from 'een-api-toolkit'
|
|
125
|
+
|
|
126
|
+
// Absolute position
|
|
127
|
+
await movePtz('camera-123', { moveType: 'position', x: 0.5, y: -0.3, z: 2.0 })
|
|
128
|
+
|
|
129
|
+
// Direction with step size
|
|
130
|
+
await movePtz('camera-123', {
|
|
131
|
+
moveType: 'direction',
|
|
132
|
+
direction: ['up', 'left'],
|
|
133
|
+
stepSize: 'medium'
|
|
134
|
+
})
|
|
135
|
+
|
|
136
|
+
// Center on point in video frame (0.0 to 1.0)
|
|
137
|
+
await movePtz('camera-123', {
|
|
138
|
+
moveType: 'centerOn',
|
|
139
|
+
relativeX: 0.75,
|
|
140
|
+
relativeY: 0.5
|
|
141
|
+
})
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### getPtzSettings(cameraId)
|
|
145
|
+
Get presets and automation settings:
|
|
146
|
+
```typescript
|
|
147
|
+
import { getPtzSettings } from 'een-api-toolkit'
|
|
148
|
+
|
|
149
|
+
const { data, error } = await getPtzSettings('camera-123')
|
|
150
|
+
if (data) {
|
|
151
|
+
console.log('Mode:', data.mode)
|
|
152
|
+
console.log('Presets:', data.presets.map(p => p.name))
|
|
153
|
+
console.log('Home:', data.homePreset)
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### updatePtzSettings(cameraId, settings)
|
|
158
|
+
Update settings (partial update - only provided fields change):
|
|
159
|
+
```typescript
|
|
160
|
+
import { updatePtzSettings } from 'een-api-toolkit'
|
|
161
|
+
|
|
162
|
+
// Change mode
|
|
163
|
+
await updatePtzSettings('camera-123', { mode: 'tour' })
|
|
164
|
+
|
|
165
|
+
// To add a preset, first fetch existing presets and append the new one
|
|
166
|
+
const { data: settings } = await getPtzSettings('camera-123')
|
|
167
|
+
const newPreset = { name: 'Entrance', position: { x: 0, y: 0, z: 1 }, timeAtPreset: 10 }
|
|
168
|
+
await updatePtzSettings('camera-123', {
|
|
169
|
+
presets: [...(settings?.presets ?? []), newPreset],
|
|
170
|
+
homePreset: 'Entrance'
|
|
171
|
+
})
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Click-to-Center Pattern
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
function handleVideoClick(event: MouseEvent) {
|
|
178
|
+
const video = event.currentTarget as HTMLVideoElement
|
|
179
|
+
const rect = video.getBoundingClientRect()
|
|
180
|
+
const relativeX = (event.clientX - rect.left) / rect.width
|
|
181
|
+
const relativeY = (event.clientY - rect.top) / rect.height
|
|
182
|
+
|
|
183
|
+
movePtz(cameraId, {
|
|
184
|
+
moveType: 'centerOn',
|
|
185
|
+
relativeX,
|
|
186
|
+
relativeY
|
|
187
|
+
})
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Error Handling
|
|
192
|
+
|
|
193
|
+
| Error Code | Meaning | Action |
|
|
194
|
+
|------------|---------|--------|
|
|
195
|
+
| AUTH_REQUIRED | Not authenticated | Redirect to login |
|
|
196
|
+
| NOT_FOUND | Camera not found or no PTZ support | Show "not found" message |
|
|
197
|
+
| FORBIDDEN | No permission | Show access denied message |
|
|
198
|
+
| VALIDATION_ERROR | Empty camera ID | Fix input |
|
|
199
|
+
| API_ERROR | Server error | Show error, allow retry |
|
|
200
|
+
|
|
201
|
+
## Detecting PTZ-Capable Cameras
|
|
202
|
+
|
|
203
|
+
To check if a camera supports PTZ, fetch it with `include: ['capabilities']` and check the
|
|
204
|
+
nested `capabilities.ptz.capable` field. The structure is:
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
// Response from getCamera(id, { include: ['capabilities'] })
|
|
208
|
+
{
|
|
209
|
+
capabilities: {
|
|
210
|
+
ptz: {
|
|
211
|
+
capable: true, // Camera supports PTZ
|
|
212
|
+
panTilt: true, // Supports pan/tilt
|
|
213
|
+
zoom: true, // Supports zoom
|
|
214
|
+
positionMove: true, // Supports absolute position moves
|
|
215
|
+
directionMove: true, // Supports directional moves
|
|
216
|
+
centerOnMove: true, // Supports center-on moves
|
|
217
|
+
fisheye: false // Whether camera is fisheye
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
**IMPORTANT:** The PTZ capability is at `capabilities.ptz.capable` (nested under a `ptz` object),
|
|
224
|
+
NOT at `capabilities.ptzCapable` (flat). Always use `capabilities?.ptz?.capable` to check.
|
|
225
|
+
|
|
226
|
+
Also check `effectivePermissions.controlPTZ` to verify the user has permission to move the camera,
|
|
227
|
+
and `effectivePermissions.editPTZStations` for managing presets.
|
|
228
|
+
|
|
229
|
+
## Constraints
|
|
230
|
+
- Always check authentication before API calls
|
|
231
|
+
- Verify camera has PTZ capability (`capabilities.ptz.capable`) before showing controls
|
|
232
|
+
- Check user permissions (`effectivePermissions.controlPTZ`) before enabling movement
|
|
233
|
+
- Poll position periodically (every 5s) for position display
|
|
234
|
+
- Handle 204 responses for PUT/PATCH (no response body)
|
|
235
|
+
- Use encodeURIComponent for camera IDs in URLs
|
package/CHANGELOG.md
CHANGED
|
@@ -2,24 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
## [0.3.
|
|
5
|
+
## [0.3.91] - 2026-02-21
|
|
6
6
|
|
|
7
7
|
### Release Summary
|
|
8
8
|
|
|
9
|
-
#### PR #113: fix: address three security review findings
|
|
10
|
-
## Summary
|
|
11
|
-
- **HIGH**: Validate hostname before persisting OAuth token — `setBaseUrl()` now returns boolean; `handleAuthCallback()` checks it before calling `setToken()`, preventing token persistence when hostname is rejected
|
|
12
|
-
- **MEDIUM**: Pin external proxy repo clone in CI workflows (`validate-pr`, `test-release`) to commit SHA `4e8f45f` to prevent supply chain attacks
|
|
13
|
-
- **LOW**: Remove unnecessary `id-token: write` permission from `claude-code-review` workflow
|
|
14
|
-
|
|
15
|
-
## Test plan
|
|
16
|
-
- [x] 644/644 unit tests pass
|
|
17
|
-
- [x] 225/225 E2E tests pass across all 11 example apps
|
|
18
|
-
- [x] Lint clean, build succeeds
|
|
19
|
-
- [ ] Validate-PR workflow passes on this PR
|
|
20
|
-
|
|
21
|
-
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
|
22
|
-
|
|
23
9
|
#### PR #118: Release v0.3.85 - API coverage docs and workflow security fix
|
|
24
10
|
## Summary
|
|
25
11
|
|
|
@@ -51,23 +37,66 @@ v0.3.85
|
|
|
51
37
|
|
|
52
38
|
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
|
53
39
|
|
|
40
|
+
#### PR #128: Release v0.3.89: PTZ camera control API and vue-ptz example
|
|
41
|
+
## Summary
|
|
42
|
+
|
|
43
|
+
This release adds PTZ (Pan/Tilt/Zoom) camera control support to the toolkit:
|
|
44
|
+
|
|
45
|
+
- **PTZ API functions**: `getPtzPosition()`, `movePtz()`, `getPtzSettings()`, `updatePtzSettings()` with full TypeScript types
|
|
46
|
+
- **PTZ types**: `PtzPosition`, `PtzMove` (discriminated union: position/direction/centerOn), `PtzSettings`, `PtzPreset`, `PtzSettingsUpdate`
|
|
47
|
+
- **vue-ptz example app**: Complete PTZ control application with live video, direction pad, click-to-center, position display, preset management, and API call logging
|
|
48
|
+
- **Camera capabilities**: Added `capabilities` field to `Camera` type for PTZ detection via `include: ['capabilities']`
|
|
49
|
+
- **Documentation**: AI-PTZ.md reference doc, een-ptz-agent, updated AI-CONTEXT.md and CLAUDE.md
|
|
50
|
+
- **E2E tests**: Conditional PTZ API tests that exercise position read, direction move, and preset loading when a PTZ camera is available
|
|
51
|
+
|
|
52
|
+
### Additional changes
|
|
53
|
+
- Dependabot: CodeQL action bump to 4.32.3
|
|
54
|
+
- CI: Use floating v1 tag for claude-code-action instead of SHA pin
|
|
55
|
+
|
|
56
|
+
## Commits
|
|
57
|
+
|
|
58
|
+
- `c552fd0` feat: add PTZ camera control API and vue-ptz example app
|
|
59
|
+
- `6a12649` fix: use single getCameras call with include and pagination for PTZ discovery
|
|
60
|
+
- `2b04b26` fix: address review findings in vue-ptz example app
|
|
61
|
+
- `92a18e4` fix: address remaining review findings
|
|
62
|
+
- `4d01c2c` fix: use floating v1 tag for claude-code-action instead of SHA pin
|
|
63
|
+
- `3f197ba` chore(deps): bump github/codeql-action from 4.32.2 to 4.32.3
|
|
64
|
+
|
|
65
|
+
## Test Results
|
|
66
|
+
|
|
67
|
+
| Check | Result |
|
|
68
|
+
|-------|--------|
|
|
69
|
+
| Lint | Pass (0 errors) |
|
|
70
|
+
| Unit tests | 681 passed (24 suites) |
|
|
71
|
+
| Build | Pass |
|
|
72
|
+
| E2E (12 apps) | All passed |
|
|
73
|
+
| Security review | No vulnerabilities found |
|
|
74
|
+
| Confidential data scan | Clean |
|
|
75
|
+
|
|
76
|
+
**Version**: 0.3.89
|
|
77
|
+
|
|
78
|
+
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
|
79
|
+
|
|
54
80
|
|
|
55
81
|
### Detailed Changes
|
|
56
82
|
|
|
57
83
|
#### Features
|
|
58
|
-
- feat: add
|
|
84
|
+
- feat: add PTZ camera control API and vue-ptz example app
|
|
59
85
|
|
|
60
86
|
#### Bug Fixes
|
|
61
|
-
- fix:
|
|
62
|
-
- fix:
|
|
87
|
+
- fix: address remaining PR #128 review findings
|
|
88
|
+
- fix: address PR #128 review findings
|
|
89
|
+
- fix: address remaining review findings
|
|
90
|
+
- fix: address review findings in vue-ptz example app
|
|
91
|
+
- fix: use single getCameras call with include and pagination for PTZ discovery
|
|
92
|
+
- fix: use floating v1 tag for claude-code-action instead of SHA pin
|
|
63
93
|
|
|
64
94
|
#### Other Changes
|
|
65
|
-
-
|
|
66
|
-
- docs: add missing agents to README agent list
|
|
95
|
+
- chore(deps): bump github/codeql-action from 4.32.2 to 4.32.3
|
|
67
96
|
|
|
68
97
|
### Links
|
|
69
98
|
- [npm package](https://www.npmjs.com/package/een-api-toolkit)
|
|
70
|
-
- [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.3.
|
|
99
|
+
- [Full Changelog](https://github.com/klaushofrichter/een-api-toolkit/compare/v0.3.85...v0.3.91)
|
|
71
100
|
|
|
72
101
|
---
|
|
73
|
-
*Released: 2026-02-17
|
|
102
|
+
*Released: 2026-02-21 17:41:30 CST*
|