een-api-toolkit 0.3.97 → 0.3.103

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.
@@ -1,6 +1,6 @@
1
1
  # EEN API Toolkit - AI Reference
2
2
 
3
- > **Version:** 0.3.97
3
+ > **Version:** 0.3.103
4
4
  >
5
5
  > This documentation is optimized for AI assistants. It provides focused, domain-specific
6
6
  > references to help you understand and use the een-api-toolkit efficiently.
@@ -1,6 +1,6 @@
1
1
  # Authentication - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.97
3
+ > **Version:** 0.3.103
4
4
  >
5
5
  > OAuth flow implementation, token management, and session handling.
6
6
  > Load this document when implementing login, logout, or auth guards.
@@ -1,6 +1,6 @@
1
1
  # Automations API - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.97
3
+ > **Version:** 0.3.103
4
4
  >
5
5
  > Complete reference for automation rules and alert actions.
6
6
  > Load this document when working with automated alert workflows.
@@ -1,6 +1,6 @@
1
1
  # Cameras & Bridges API - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.97
3
+ > **Version:** 0.3.103
4
4
  >
5
5
  > Complete reference for camera and bridge management.
6
6
  > Load this document when working with devices.
@@ -1,6 +1,6 @@
1
1
  # Event Type to Data Schemas Mapping - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.97
3
+ > **Version:** 0.3.103
4
4
  >
5
5
  > Complete reference for event type to data schema mappings.
6
6
  > Load this document when building dynamic event queries with the `include` parameter.
@@ -152,6 +152,7 @@ const schemas = EVENT_TYPE_DATA_SCHEMAS['een.personDetectionEvent.v1']
152
152
  | `een.objectRemovalEvent.v1` | monitoredArea, objectDetection, fullFrameImageUrl, croppedFrameImageUrl, displayOverlay.boundingBox, fullFrameImageUrlWithOverlay |
153
153
  | `een.personTailgateEvent.v1` | objectDetection, fullFrameImageUrl, croppedFrameImageUrl, displayOverlay.boundingBox, fullFrameImageUrlWithOverlay |
154
154
  | `een.edgeReportedDeviceStatusEvent.v1` | deviceCommonStatusUpdate, deviceErrorStatusUpdate |
155
+ | `een.accessActivationEvent.v1` | credentialAccessActivation, creatorDetails, userAccessActivation |
155
156
 
156
157
  ### Camera Analytics Events
157
158
 
@@ -1,6 +1,6 @@
1
1
  # Events, Alerts & Real-Time Streaming - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.97
3
+ > **Version:** 0.3.103
4
4
  >
5
5
  > Complete reference for events, alerts, metrics, and SSE subscriptions.
6
6
  > Load this document when implementing event-driven features.
@@ -1,6 +1,6 @@
1
1
  # Layouts API - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.97
3
+ > **Version:** 0.3.103
4
4
  >
5
5
  > Complete reference for layout management (camera grouping).
6
6
  > Load this document when working with layouts.
@@ -1,6 +1,6 @@
1
1
  # Jobs, Exports, Files & Downloads - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.97
3
+ > **Version:** 0.3.103
4
4
  >
5
5
  > Complete reference for async jobs, video exports, and file management.
6
6
  > Load this document when implementing export workflows or file downloads.
@@ -1,6 +1,6 @@
1
1
  # Media & Live Video - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.97
3
+ > **Version:** 0.3.103
4
4
  >
5
5
  > Complete reference for media retrieval, live streaming, and video playback.
6
6
  > Load this document when implementing video features.
@@ -1,6 +1,6 @@
1
1
  # PTZ Camera Controls
2
2
 
3
- > **Version:** 0.3.97
3
+ > **Version:** 0.3.103
4
4
  >
5
5
  > Pan/Tilt/Zoom camera control: position, movement, presets, and automation.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # Vue 3 Application Setup - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.97
3
+ > **Version:** 0.3.103
4
4
  >
5
5
  > Complete guide for setting up a Vue 3 application with the een-api-toolkit.
6
6
  > Load this document when creating a new project or troubleshooting setup issues.
@@ -1,6 +1,6 @@
1
1
  # Users API - EEN API Toolkit
2
2
 
3
- > **Version:** 0.3.97
3
+ > **Version:** 0.3.103
4
4
  >
5
5
  > Complete reference for user management.
6
6
  > Load this document when working with user data.
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { ref, watch } from 'vue'
3
3
  import { movePtz } from 'een-api-toolkit'
4
- import type { PtzPositionResponse } from 'een-api-toolkit'
4
+ import type { PtzPositionResponse, PtzDirection, PtzStepSize, PtzMoveType, PtzMove } from 'een-api-toolkit'
5
5
  import { useApiLog } from '../composables/useApiLog'
6
6
 
7
7
  const props = defineProps<{
@@ -14,45 +14,97 @@ const emit = defineEmits<{
14
14
  }>()
15
15
 
16
16
  const { log: apiLog } = useApiLog()
17
+
18
+ // Move type selection
19
+ const moveType = ref<PtzMoveType>('position')
20
+
21
+ // Position fields
17
22
  const x = ref<string>('0')
18
23
  const y = ref<string>('0')
19
24
  const z = ref<string>('0')
25
+
26
+ // Direction fields
27
+ const directions = ref<PtzDirection[]>([])
28
+ const stepSize = ref<PtzStepSize>('medium')
29
+ const allDirections: PtzDirection[] = ['up', 'down', 'left', 'right', 'in', 'out']
30
+
31
+ // CenterOn fields
32
+ const relativeX = ref<string>('0.5')
33
+ const relativeY = ref<string>('0.5')
34
+
20
35
  const applying = ref(false)
21
36
  const error = ref<string | null>(null)
22
37
 
23
- watch(() => props.currentPosition, (pos) => {
24
- if (pos) {
25
- x.value = pos.x?.toFixed(3) ?? '0'
26
- y.value = pos.y?.toFixed(3) ?? '0'
27
- z.value = pos.z?.toFixed(3) ?? '0'
38
+ watch(moveType, () => {
39
+ error.value = null
40
+ })
41
+
42
+ function importPosition() {
43
+ if (props.currentPosition) {
44
+ x.value = props.currentPosition.x?.toFixed(3) ?? '0'
45
+ y.value = props.currentPosition.y?.toFixed(3) ?? '0'
46
+ z.value = props.currentPosition.z?.toFixed(3) ?? '0'
28
47
  }
29
- }, { immediate: true })
48
+ }
30
49
 
31
- async function apply() {
32
- if (!props.cameraId || applying.value) return
50
+ function buildMove(): PtzMove | null {
51
+ if (moveType.value === 'position') {
52
+ const xVal = parseFloat(x.value)
53
+ const yVal = parseFloat(y.value)
54
+ const zVal = parseFloat(z.value)
55
+
56
+ if (isNaN(xVal) || isNaN(yVal) || isNaN(zVal)) {
57
+ error.value = 'Invalid numeric values'
58
+ return null
59
+ }
60
+
61
+ // Position coordinates are camera-specific absolute values (not normalised to 0-1)
62
+ return { moveType: 'position', x: xVal, y: yVal, z: zVal }
63
+ } else if (moveType.value === 'direction') {
64
+ if (directions.value.length === 0) {
65
+ error.value = 'Select at least one direction'
66
+ return null
67
+ }
33
68
 
34
- const xVal = parseFloat(x.value)
35
- const yVal = parseFloat(y.value)
36
- const zVal = parseFloat(z.value)
69
+ return { moveType: 'direction', direction: [...directions.value], stepSize: stepSize.value }
70
+ } else {
71
+ const rxVal = parseFloat(relativeX.value)
72
+ const ryVal = parseFloat(relativeY.value)
73
+
74
+ if (isNaN(rxVal) || isNaN(ryVal)) {
75
+ error.value = 'Invalid numeric values'
76
+ return null
77
+ }
37
78
 
38
- if (isNaN(xVal) || isNaN(yVal) || isNaN(zVal)) {
39
- error.value = 'Invalid numeric values'
40
- return
79
+ if (rxVal < 0 || rxVal > 1 || ryVal < 0 || ryVal > 1) {
80
+ error.value = 'Values must be between 0 and 1'
81
+ return null
82
+ }
83
+
84
+ return { moveType: 'centerOn', relativeX: rxVal, relativeY: ryVal }
41
85
  }
86
+ }
87
+
88
+ async function apply() {
89
+ if (!props.cameraId || applying.value) return
42
90
 
43
- applying.value = true
44
91
  error.value = null
45
92
 
46
- const move = { moveType: 'position' as const, x: xVal, y: yVal, z: zVal }
47
- const result = await movePtz(props.cameraId, move)
48
- apiLog('movePtz', { cameraId: props.cameraId, move }, result.error ?? result.data, !!result.error)
93
+ const move = buildMove()
94
+ if (!move) return
49
95
 
50
- applying.value = false
96
+ applying.value = true
97
+ try {
98
+ const result = await movePtz(props.cameraId, move)
99
+ apiLog('movePtz', { cameraId: props.cameraId, move }, result.error ?? result.data, !!result.error)
51
100
 
52
- if (result.error) {
53
- error.value = result.error.message
54
- } else {
55
- emit('move-complete')
101
+ if (result.error) {
102
+ error.value = result.error.message
103
+ } else {
104
+ emit('move-complete')
105
+ }
106
+ } finally {
107
+ applying.value = false
56
108
  }
57
109
  }
58
110
  </script>
@@ -60,39 +112,114 @@ async function apply() {
60
112
  <template>
61
113
  <div class="position-input" data-testid="position-input">
62
114
  <div class="input-row">
63
- <label>X</label>
64
- <input
65
- v-model="x"
66
- type="number"
67
- step="0.01"
68
- :disabled="!cameraId || applying"
69
- data-testid="input-x"
70
- @keyup.enter="apply"
71
- />
72
- </div>
73
- <div class="input-row">
74
- <label>Y</label>
75
- <input
76
- v-model="y"
77
- type="number"
78
- step="0.01"
79
- :disabled="!cameraId || applying"
80
- data-testid="input-y"
81
- @keyup.enter="apply"
82
- />
83
- </div>
84
- <div class="input-row">
85
- <label>Z</label>
86
- <input
87
- v-model="z"
88
- type="number"
89
- step="0.1"
90
- min="0"
91
- :disabled="!cameraId || applying"
92
- data-testid="input-z"
93
- @keyup.enter="apply"
94
- />
115
+ <label>Move</label>
116
+ <select v-model="moveType" :disabled="!cameraId || applying" data-testid="move-type-select">
117
+ <option value="position">Position</option>
118
+ <option value="direction">Direction</option>
119
+ <option value="centerOn">Center On</option>
120
+ </select>
95
121
  </div>
122
+
123
+ <!-- Position fields -->
124
+ <template v-if="moveType === 'position'">
125
+ <div class="input-row">
126
+ <label>X</label>
127
+ <input
128
+ v-model="x"
129
+ type="number"
130
+ step="0.01"
131
+ :disabled="!cameraId || applying"
132
+ data-testid="input-x"
133
+ @keyup.enter="apply"
134
+ />
135
+ </div>
136
+ <div class="input-row">
137
+ <label>Y</label>
138
+ <input
139
+ v-model="y"
140
+ type="number"
141
+ step="0.01"
142
+ :disabled="!cameraId || applying"
143
+ data-testid="input-y"
144
+ @keyup.enter="apply"
145
+ />
146
+ </div>
147
+ <div class="input-row">
148
+ <label>Z</label>
149
+ <input
150
+ v-model="z"
151
+ type="number"
152
+ step="0.1"
153
+ min="0"
154
+ :disabled="!cameraId || applying"
155
+ data-testid="input-z"
156
+ @keyup.enter="apply"
157
+ />
158
+ </div>
159
+ <button
160
+ class="import-btn"
161
+ :disabled="!cameraId || !currentPosition || applying"
162
+ @click="importPosition"
163
+ data-testid="import-position"
164
+ >
165
+ Import Current Position
166
+ </button>
167
+ </template>
168
+
169
+ <!-- Direction fields -->
170
+ <template v-else-if="moveType === 'direction'">
171
+ <div class="direction-checkboxes">
172
+ <label v-for="dir in allDirections" :key="dir" class="checkbox-label">
173
+ <input
174
+ type="checkbox"
175
+ :value="dir"
176
+ v-model="directions"
177
+ :disabled="!cameraId || applying"
178
+ :data-testid="'dir-' + dir"
179
+ />
180
+ {{ dir }}
181
+ </label>
182
+ </div>
183
+ <div class="input-row">
184
+ <label>Step</label>
185
+ <select v-model="stepSize" :disabled="!cameraId || applying" data-testid="step-size-select">
186
+ <option value="small">Small</option>
187
+ <option value="medium">Medium</option>
188
+ <option value="large">Large</option>
189
+ </select>
190
+ </div>
191
+ </template>
192
+
193
+ <!-- CenterOn fields -->
194
+ <template v-else>
195
+ <div class="input-row">
196
+ <label>rX</label>
197
+ <input
198
+ v-model="relativeX"
199
+ type="number"
200
+ step="0.01"
201
+ min="0"
202
+ max="1"
203
+ :disabled="!cameraId || applying"
204
+ data-testid="input-relative-x"
205
+ @keyup.enter="apply"
206
+ />
207
+ </div>
208
+ <div class="input-row">
209
+ <label>rY</label>
210
+ <input
211
+ v-model="relativeY"
212
+ type="number"
213
+ step="0.01"
214
+ min="0"
215
+ max="1"
216
+ :disabled="!cameraId || applying"
217
+ data-testid="input-relative-y"
218
+ @keyup.enter="apply"
219
+ />
220
+ </div>
221
+ </template>
222
+
96
223
  <button
97
224
  class="apply-btn"
98
225
  :disabled="!cameraId || applying"
@@ -127,7 +254,7 @@ async function apply() {
127
254
  font-size: 13px;
128
255
  font-weight: 600;
129
256
  color: #555;
130
- min-width: 20px;
257
+ min-width: 32px;
131
258
  text-align: right;
132
259
  }
133
260
 
@@ -140,10 +267,61 @@ async function apply() {
140
267
  font-family: monospace;
141
268
  }
142
269
 
143
- .input-row input:disabled {
270
+ .input-row select {
271
+ flex: 1;
272
+ padding: 5px 8px;
273
+ border: 1px solid #ddd;
274
+ border-radius: 4px;
275
+ font-size: 13px;
276
+ }
277
+
278
+ .input-row input:disabled,
279
+ .input-row select:disabled {
144
280
  opacity: 0.5;
145
281
  }
146
282
 
283
+ .direction-checkboxes {
284
+ display: grid;
285
+ grid-template-columns: 1fr 1fr;
286
+ gap: 4px 12px;
287
+ margin-bottom: 8px;
288
+ }
289
+
290
+ .checkbox-label {
291
+ display: flex;
292
+ align-items: center;
293
+ gap: 6px;
294
+ font-size: 13px;
295
+ color: #555;
296
+ cursor: pointer;
297
+ text-transform: capitalize;
298
+ }
299
+
300
+ .checkbox-label input[type="checkbox"] {
301
+ margin: 0;
302
+ }
303
+
304
+ .import-btn {
305
+ width: 100%;
306
+ padding: 6px;
307
+ font-size: 11px;
308
+ background: #6c757d;
309
+ color: white;
310
+ border: none;
311
+ border-radius: 4px;
312
+ cursor: pointer;
313
+ margin-bottom: 4px;
314
+ }
315
+
316
+ .import-btn:hover:not(:disabled) {
317
+ background: #5a6268;
318
+ }
319
+
320
+ .import-btn:disabled {
321
+ opacity: 0.4;
322
+ cursor: not-allowed;
323
+ }
324
+
147
325
  .apply-btn {
148
326
  width: 100%;
149
327
  padding: 8px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "een-api-toolkit",
3
- "version": "0.3.97",
3
+ "version": "0.3.103",
4
4
  "description": "EEN Video platform API v3.0 library for Vue 3",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",