suprema-biostar-mcp 1.0.1__py3-none-any.whl
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.
- biostar_x_mcp_server/__init__.py +25 -0
- biostar_x_mcp_server/__main__.py +15 -0
- biostar_x_mcp_server/config.py +87 -0
- biostar_x_mcp_server/handlers/__init__.py +35 -0
- biostar_x_mcp_server/handlers/access_handler.py +2162 -0
- biostar_x_mcp_server/handlers/audit_handler.py +489 -0
- biostar_x_mcp_server/handlers/auth_handler.py +216 -0
- biostar_x_mcp_server/handlers/base_handler.py +228 -0
- biostar_x_mcp_server/handlers/card_handler.py +746 -0
- biostar_x_mcp_server/handlers/device_handler.py +4344 -0
- biostar_x_mcp_server/handlers/door_handler.py +3969 -0
- biostar_x_mcp_server/handlers/event_handler.py +1331 -0
- biostar_x_mcp_server/handlers/file_handler.py +212 -0
- biostar_x_mcp_server/handlers/help_web_handler.py +379 -0
- biostar_x_mcp_server/handlers/log_handler.py +1051 -0
- biostar_x_mcp_server/handlers/navigation_handler.py +109 -0
- biostar_x_mcp_server/handlers/occupancy_handler.py +541 -0
- biostar_x_mcp_server/handlers/user_handler.py +3568 -0
- biostar_x_mcp_server/schemas/__init__.py +21 -0
- biostar_x_mcp_server/schemas/access.py +158 -0
- biostar_x_mcp_server/schemas/audit.py +73 -0
- biostar_x_mcp_server/schemas/auth.py +24 -0
- biostar_x_mcp_server/schemas/cards.py +128 -0
- biostar_x_mcp_server/schemas/devices.py +496 -0
- biostar_x_mcp_server/schemas/doors.py +306 -0
- biostar_x_mcp_server/schemas/events.py +104 -0
- biostar_x_mcp_server/schemas/files.py +7 -0
- biostar_x_mcp_server/schemas/help.py +29 -0
- biostar_x_mcp_server/schemas/logs.py +33 -0
- biostar_x_mcp_server/schemas/occupancy.py +19 -0
- biostar_x_mcp_server/schemas/tool_response.py +29 -0
- biostar_x_mcp_server/schemas/users.py +166 -0
- biostar_x_mcp_server/server.py +335 -0
- biostar_x_mcp_server/session.py +221 -0
- biostar_x_mcp_server/tool_manager.py +172 -0
- biostar_x_mcp_server/tools/__init__.py +45 -0
- biostar_x_mcp_server/tools/access.py +510 -0
- biostar_x_mcp_server/tools/audit.py +227 -0
- biostar_x_mcp_server/tools/auth.py +59 -0
- biostar_x_mcp_server/tools/cards.py +269 -0
- biostar_x_mcp_server/tools/categories.py +197 -0
- biostar_x_mcp_server/tools/devices.py +1552 -0
- biostar_x_mcp_server/tools/doors.py +865 -0
- biostar_x_mcp_server/tools/events.py +305 -0
- biostar_x_mcp_server/tools/files.py +28 -0
- biostar_x_mcp_server/tools/help.py +80 -0
- biostar_x_mcp_server/tools/logs.py +123 -0
- biostar_x_mcp_server/tools/navigation.py +89 -0
- biostar_x_mcp_server/tools/occupancy.py +91 -0
- biostar_x_mcp_server/tools/users.py +1113 -0
- biostar_x_mcp_server/utils/__init__.py +31 -0
- biostar_x_mcp_server/utils/category_mapper.py +206 -0
- biostar_x_mcp_server/utils/decorators.py +101 -0
- biostar_x_mcp_server/utils/language_detector.py +51 -0
- biostar_x_mcp_server/utils/search.py +42 -0
- biostar_x_mcp_server/utils/timezone.py +122 -0
- suprema_biostar_mcp-1.0.1.dist-info/METADATA +163 -0
- suprema_biostar_mcp-1.0.1.dist-info/RECORD +61 -0
- suprema_biostar_mcp-1.0.1.dist-info/WHEEL +4 -0
- suprema_biostar_mcp-1.0.1.dist-info/entry_points.txt +2 -0
- suprema_biostar_mcp-1.0.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,865 @@
|
|
|
1
|
+
from mcp.types import Tool
|
|
2
|
+
|
|
3
|
+
# Door management tools
|
|
4
|
+
GET_DOORS_TOOL = Tool(
|
|
5
|
+
name="get-doors",
|
|
6
|
+
description=(
|
|
7
|
+
"[ACTION TOOL] Retrieve doors from BioStar X with robust filtering. "
|
|
8
|
+
"Use this when user asks to 'list doors', 'show doors', 'get doors', 'display doors', or needs door information. "
|
|
9
|
+
"This performs actual system operations - do NOT use vector search for this. "
|
|
10
|
+
"Supports API params (limit, order_by) and client-side filters for LLM-friendly use."
|
|
11
|
+
),
|
|
12
|
+
inputSchema={
|
|
13
|
+
"type": "object",
|
|
14
|
+
"properties": {
|
|
15
|
+
"limit": {
|
|
16
|
+
"type": "integer",
|
|
17
|
+
"description": "Number of records (0 = all). Default: 0."
|
|
18
|
+
},
|
|
19
|
+
"order_by": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Sort order, e.g., 'id:true' (asc) or 'id:false' (desc)."
|
|
22
|
+
},
|
|
23
|
+
"ids": {
|
|
24
|
+
"type": "array",
|
|
25
|
+
"items": {"type": "integer"},
|
|
26
|
+
"description": "Filter by specific door IDs."
|
|
27
|
+
},
|
|
28
|
+
"name": {
|
|
29
|
+
"type": "string",
|
|
30
|
+
"description": "Exact door name match."
|
|
31
|
+
},
|
|
32
|
+
"name_contains": {
|
|
33
|
+
"type": "string",
|
|
34
|
+
"description": "Case-insensitive substring match for door name."
|
|
35
|
+
},
|
|
36
|
+
"group_id": {
|
|
37
|
+
"type": "integer",
|
|
38
|
+
"description": "Filter by door group ID."
|
|
39
|
+
},
|
|
40
|
+
"group_name": {
|
|
41
|
+
"type": "string",
|
|
42
|
+
"description": "Case-insensitive substring match for door group name."
|
|
43
|
+
},
|
|
44
|
+
"status": {
|
|
45
|
+
"type": "string",
|
|
46
|
+
"description": "Filter by status value (as returned by API), e.g., '0'."
|
|
47
|
+
},
|
|
48
|
+
"include_raw": {
|
|
49
|
+
"type": "boolean",
|
|
50
|
+
"description": "Attach raw API row for each door (debugging). Default: false."
|
|
51
|
+
},
|
|
52
|
+
"minimal": {
|
|
53
|
+
"type": "boolean",
|
|
54
|
+
"description": "Return only id and name (for access level creation). Reduces response size from 13KB to <1KB. Default: false."
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"required": []
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
GET_DOOR_TOOL = Tool(
|
|
62
|
+
name="get-door",
|
|
63
|
+
description=(
|
|
64
|
+
"Search and retrieve a single door. "
|
|
65
|
+
"If 'door_id' is given, fetch details directly. "
|
|
66
|
+
"Otherwise it will POST /api/v2/doors/search with the provided criteria. "
|
|
67
|
+
"When zero or multiple matches are found, the tool returns a choice list and requests user selection."
|
|
68
|
+
),
|
|
69
|
+
inputSchema={
|
|
70
|
+
"type": "object",
|
|
71
|
+
"properties": {
|
|
72
|
+
"door_id": {
|
|
73
|
+
"type": "integer",
|
|
74
|
+
"description": "ID of the door to retrieve. If provided, the tool skips search and fetches details."
|
|
75
|
+
},
|
|
76
|
+
"search_text": {
|
|
77
|
+
"type": "string",
|
|
78
|
+
"description": "Free-text query for door search (POST /api/v2/doors/search)."
|
|
79
|
+
},
|
|
80
|
+
"door_group_id": {
|
|
81
|
+
"type": "integer",
|
|
82
|
+
"description": "Filter by door group ID in search (POST /api/v2/doors/search)."
|
|
83
|
+
},
|
|
84
|
+
"limit": {
|
|
85
|
+
"type": "integer",
|
|
86
|
+
"description": "Max results for search (default: 50)."
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
"required": [],
|
|
90
|
+
"anyOf": [
|
|
91
|
+
{"required": ["door_id"]},
|
|
92
|
+
{"required": ["search_text"]},
|
|
93
|
+
{"required": ["door_group_id"]}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
CREATE_DOOR_TOOL = Tool(
|
|
99
|
+
name="create-door",
|
|
100
|
+
description="""[ACTION TOOL] Create a new door in BioStar X system. Use this when user explicitly asks to 'create door', 'add door', 'new door', or 'make door'. This performs actual system operations - do NOT use vector search for this.
|
|
101
|
+
Create a new door with HARD-STOP guardrails.
|
|
102
|
+
|
|
103
|
+
STRICT, NON-NEGOTIABLE RULES:
|
|
104
|
+
- NEVER discover, register, or select any device automatically.
|
|
105
|
+
- NEVER create a door with any device other than the EXACT provided `entry_device_id`.
|
|
106
|
+
- If `entry_device_id` is already linked to another door (1:1 policy), DO NOT create anything.
|
|
107
|
+
- Perform UDP discovery (LIST ONLY), FILTER OUT devices already used by any door, RETURN the candidate list, and STOP.
|
|
108
|
+
- Do NOT call create-door again with a different device. The client must explicitly choose and call again.
|
|
109
|
+
- If the device is not registered, DO NOT register it and DO NOT create. Optionally return a UDP candidate list (LIST ONLY) and STOP.
|
|
110
|
+
- If `relay_index` is missing, RETURN available relay indices for the provided device and STOP. DO NOT create.
|
|
111
|
+
- Actual creation occurs ONLY when `confirm=true` AND ALL required fields are present AND there is NO conflict for the provided `entry_device_id`.
|
|
112
|
+
|
|
113
|
+
ABSOLUTE PROHIBITIONS:
|
|
114
|
+
- Do NOT call other tools implicitly (no device registration, no alternative device selection, no follow-up create).
|
|
115
|
+
- Do NOT "help" by choosing a different device. If the provided device is invalid or in conflict, return info and STOP.
|
|
116
|
+
|
|
117
|
+
OUTPUT CONTRACT:
|
|
118
|
+
- Conflict -> return: `{ conflict: {...}, udp_discovery: { devices: [...] }, available_registered_devices: [...] }` and STOP.
|
|
119
|
+
- Missing relay -> return: `{ relay_options: [...] }` and STOP.
|
|
120
|
+
- Success -> return: `{ door_id, request_body, door_groups: [...] }` (no group reassignment).
|
|
121
|
+
- AFTER ANY RETURN, END THE TURN. The client must make the next explicit call.
|
|
122
|
+
""",
|
|
123
|
+
inputSchema={
|
|
124
|
+
"type": "object",
|
|
125
|
+
"properties": {
|
|
126
|
+
# flow controls
|
|
127
|
+
"confirm": {"type": "boolean", "description": "If true, actually create the door. If false, return a preview.", "default": False},
|
|
128
|
+
"default_group_id": {"type": "integer", "description": "Fallback group id when door_group_id is not provided.", "default": 1},
|
|
129
|
+
|
|
130
|
+
# door core
|
|
131
|
+
"name": {"type": "string", "description": "Door name"},
|
|
132
|
+
"description": {"type": "string"},
|
|
133
|
+
"door_group_id": {"type": "integer", "description": "Optional group id at creation time. If omitted, default_group_id is used."},
|
|
134
|
+
"open_timeout": {"type": "integer", "default": 10},
|
|
135
|
+
"open_duration": {"type": "integer", "default": 5},
|
|
136
|
+
"open_once": {"type": "boolean", "default": True},
|
|
137
|
+
"unconditional_lock": {"type": "boolean", "default": True},
|
|
138
|
+
|
|
139
|
+
# device / IO
|
|
140
|
+
"entry_device_id": {"type": "integer", "description": "Device id to control the lock (1:1 mapping enforced)."},
|
|
141
|
+
"relay_index": {
|
|
142
|
+
"type": "integer",
|
|
143
|
+
"description": "Relay index on the entry device. If omitted, the tool returns relay list and exits."
|
|
144
|
+
},
|
|
145
|
+
|
|
146
|
+
"exit_device_id": {"type": "integer"},
|
|
147
|
+
"exit_input_index": {"type": "integer", "default": 0},
|
|
148
|
+
"exit_input_type": {"type": "integer", "description": "1=NC, 0=NO", "default": 1},
|
|
149
|
+
|
|
150
|
+
"sensor_device_id": {"type": "integer"},
|
|
151
|
+
"sensor_input_index": {"type": "integer", "default": 1},
|
|
152
|
+
"sensor_input_type": {"type": "integer", "description": "1=NC, 0=NO", "default": 1},
|
|
153
|
+
"apb_use_door_sensor": {"type": "integer", "default": 1}
|
|
154
|
+
},
|
|
155
|
+
# door_group_id is not required to allow post-creation assignment
|
|
156
|
+
"required": [
|
|
157
|
+
"name",
|
|
158
|
+
"entry_device_id",
|
|
159
|
+
"exit_device_id", "exit_input_index", "exit_input_type",
|
|
160
|
+
"sensor_device_id", "sensor_input_index", "sensor_input_type", "apb_use_door_sensor"
|
|
161
|
+
]
|
|
162
|
+
}
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
UPDATE_DOOR_TOOL = Tool(
|
|
166
|
+
name="update-door",
|
|
167
|
+
description="Update an existing door's configuration",
|
|
168
|
+
inputSchema={
|
|
169
|
+
"type": "object",
|
|
170
|
+
"properties": {
|
|
171
|
+
"door_id": {
|
|
172
|
+
"type": "integer",
|
|
173
|
+
"description": "ID of the door to update"
|
|
174
|
+
},
|
|
175
|
+
"name": {
|
|
176
|
+
"type": "string",
|
|
177
|
+
"description": "New name for the door"
|
|
178
|
+
},
|
|
179
|
+
"open_duration": {
|
|
180
|
+
"type": "integer",
|
|
181
|
+
"description": "Door open duration in seconds"
|
|
182
|
+
},
|
|
183
|
+
"open_timeout": {
|
|
184
|
+
"type": "integer",
|
|
185
|
+
"description": "Door open timeout in seconds"
|
|
186
|
+
},
|
|
187
|
+
"dual_auth_required": {
|
|
188
|
+
"type": "boolean",
|
|
189
|
+
"description": "Whether dual authentication is required"
|
|
190
|
+
}
|
|
191
|
+
},
|
|
192
|
+
"required": ["door_id"]
|
|
193
|
+
}
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
DELETE_DOOR_TOOL = Tool(
|
|
197
|
+
name="delete-door",
|
|
198
|
+
description=" CRITICAL: Delete a door from the BioStar 2 system. THIS IS PERMANENT and CANNOT BE UNDONE! ALWAYS confirm with user before executing. For demo data, REQUIRE explicit 'delete confirm' or '삭제 확인' from user.",
|
|
199
|
+
inputSchema={
|
|
200
|
+
"type": "object",
|
|
201
|
+
"properties": {
|
|
202
|
+
"door_id": {
|
|
203
|
+
"type": "integer",
|
|
204
|
+
"description": "ID of the door to delete"
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
"required": ["door_id"]
|
|
208
|
+
}
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
CONTROL_DOOR_TOOL = Tool(
|
|
212
|
+
name="control-door",
|
|
213
|
+
description=(
|
|
214
|
+
"[ACTION TOOL] Control door actions (open, release, lock, unlock) in BioStar X. "
|
|
215
|
+
"Use this when user asks to 'open door', 'unlock door', 'lock door', 'release door', or control doors. "
|
|
216
|
+
"This performs actual system operations - do NOT use vector search for this.\n"
|
|
217
|
+
"- POST /api/doors/{open|lock|unlock|release}\n"
|
|
218
|
+
"- Body: {\"DoorCollection\": {\"rows\": [{\"id\": <number>}, ...]}}\n"
|
|
219
|
+
"- STRICT MODE: If 'door_names' is used, names must match EXACTLY (case-sensitive); "
|
|
220
|
+
"no autocorrect, no fuzzy. 0 match -> error with available list; >1 match -> error with candidates. "
|
|
221
|
+
"In both cases NO action is performed.\n"
|
|
222
|
+
"- If both 'door_ids' and 'door_names' are given, they must resolve to the same set; otherwise error.\n"
|
|
223
|
+
"- Do NOT pass duration for 'open'; door uses its configured duration."
|
|
224
|
+
),
|
|
225
|
+
inputSchema={
|
|
226
|
+
"type": "object",
|
|
227
|
+
"properties": {
|
|
228
|
+
"door_ids": {
|
|
229
|
+
"type": "array",
|
|
230
|
+
"items": {"oneOf": [{"type": "integer"}, {"type": "string"}]},
|
|
231
|
+
"description": "Door IDs to control (validated against GET /api/doors)."
|
|
232
|
+
},
|
|
233
|
+
"door_names": {
|
|
234
|
+
"type": "array",
|
|
235
|
+
"items": {"type": "string"},
|
|
236
|
+
"description": "Door names to control (EXACT, case-sensitive). No autocorrect, no fuzzy."
|
|
237
|
+
},
|
|
238
|
+
"action": {
|
|
239
|
+
"type": "string",
|
|
240
|
+
"enum": ["open", "release", "lock", "unlock"],
|
|
241
|
+
"description": "Action to perform. 'release' clears manual lock/unlock."
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
"required": ["action"], # one of door_ids or door_names is required at runtime by handler
|
|
245
|
+
}
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
GET_DOORS_STATUS_TOOL = Tool(
|
|
250
|
+
name="get-doors-status",
|
|
251
|
+
description=(
|
|
252
|
+
"Fetch current status for doors via POST /api/doors/status. "
|
|
253
|
+
"Normalizes booleans/ints, derives human-friendly labels, supports filters and optional enrichment."
|
|
254
|
+
),
|
|
255
|
+
inputSchema={
|
|
256
|
+
"type": "object",
|
|
257
|
+
"properties": {
|
|
258
|
+
"monitoring_permission": {
|
|
259
|
+
"type": "boolean",
|
|
260
|
+
"description": "Pass-through flag for the status API. Default: true."
|
|
261
|
+
},
|
|
262
|
+
"include_enrichment": {
|
|
263
|
+
"type": "boolean",
|
|
264
|
+
"description": "If true, joins names/groups from GET /api/doors and enables group/name filters. Default: true."
|
|
265
|
+
},
|
|
266
|
+
"include_device_response": {
|
|
267
|
+
"type": "boolean",
|
|
268
|
+
"description": "Include normalized DeviceResponse with error summary. Default: true."
|
|
269
|
+
},
|
|
270
|
+
"include_raw": {
|
|
271
|
+
"type": "boolean",
|
|
272
|
+
"description": "Attach raw status row for debugging. Default: false."
|
|
273
|
+
},
|
|
274
|
+
"door_ids": {
|
|
275
|
+
"type": "array",
|
|
276
|
+
"items": {"type": "integer"},
|
|
277
|
+
"description": "Filter to specific door IDs."
|
|
278
|
+
},
|
|
279
|
+
"is_open": {
|
|
280
|
+
"type": "boolean",
|
|
281
|
+
"description": "Filter by open state."
|
|
282
|
+
},
|
|
283
|
+
"is_unlocked": {
|
|
284
|
+
"type": "boolean",
|
|
285
|
+
"description": "Filter by unlocked state."
|
|
286
|
+
},
|
|
287
|
+
"has_alarm": {
|
|
288
|
+
"type": "boolean",
|
|
289
|
+
"description": "Filter by alarm state."
|
|
290
|
+
},
|
|
291
|
+
"status_in": {
|
|
292
|
+
"type": "array",
|
|
293
|
+
"items": {"type": "string"},
|
|
294
|
+
"description": "Filter by raw status code values (as strings)."
|
|
295
|
+
},
|
|
296
|
+
"group_id": {
|
|
297
|
+
"type": "integer",
|
|
298
|
+
"description": "Filter by door group ID (requires include_enrichment=true)."
|
|
299
|
+
},
|
|
300
|
+
"group_name": {
|
|
301
|
+
"type": "string",
|
|
302
|
+
"description": "Substring match for group name (requires include_enrichment=true)."
|
|
303
|
+
},
|
|
304
|
+
"name_contains": {
|
|
305
|
+
"type": "string",
|
|
306
|
+
"description": "Substring match for door name (requires include_enrichment=true)."
|
|
307
|
+
},
|
|
308
|
+
"sort_by": {
|
|
309
|
+
"type": "string",
|
|
310
|
+
"enum": ["door_id", "name", "group_name"],
|
|
311
|
+
"description": "Client-side sort key. Default: 'door_id'."
|
|
312
|
+
},
|
|
313
|
+
"sort_desc": {
|
|
314
|
+
"type": "boolean",
|
|
315
|
+
"description": "Sort descending when true. Default: false."
|
|
316
|
+
}
|
|
317
|
+
},
|
|
318
|
+
"required": []
|
|
319
|
+
}
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
GET_DOOR_GROUPS_TOOL = Tool(
|
|
323
|
+
name="get-door-groups",
|
|
324
|
+
description=(
|
|
325
|
+
"Retrieve all door groups (non-breaking). "
|
|
326
|
+
"Keeps the legacy output shape {message,total,groups} and, when available, "
|
|
327
|
+
"adds optional fields per group: depth, parent, children, child_count, path, door_ids."
|
|
328
|
+
),
|
|
329
|
+
inputSchema={
|
|
330
|
+
"type": "object",
|
|
331
|
+
"properties": {
|
|
332
|
+
# When true (default), enrich with hierarchy info via v2 search (depth/parent/children/path)
|
|
333
|
+
"include_hierarchy": {
|
|
334
|
+
"type": "boolean",
|
|
335
|
+
"description": "Enrich with /api/v2/door_groups/only_permission_item/search (depth/parent/children/path). Default: true"
|
|
336
|
+
},
|
|
337
|
+
# When true (default), scan /api/doors to compute door_ids & door_count if missing in v1 payload
|
|
338
|
+
"include_doors_scan": {
|
|
339
|
+
"type": "boolean",
|
|
340
|
+
"description": "Enrich with /api/doors to fill door_ids and door_count when absent. Default: true"
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
"required": []
|
|
344
|
+
}
|
|
345
|
+
)
|
|
346
|
+
GET_DOOR_GROUP_TOOL = Tool(
|
|
347
|
+
name="get-door-group",
|
|
348
|
+
description="Get detailed information about a specific door group (by id or by name).",
|
|
349
|
+
inputSchema={
|
|
350
|
+
"type": "object",
|
|
351
|
+
"properties": {
|
|
352
|
+
"group_id": {
|
|
353
|
+
"type": ["integer", "string"],
|
|
354
|
+
"description": "ID of the door group to retrieve"
|
|
355
|
+
},
|
|
356
|
+
"group_name": {
|
|
357
|
+
"type": "string",
|
|
358
|
+
"description": "Name of the door group to resolve (supports exact/iexact/icontains via name_match_mode)"
|
|
359
|
+
},
|
|
360
|
+
"name_match_mode": {
|
|
361
|
+
"type": "string",
|
|
362
|
+
"enum": ["auto", "exact", "iexact", "contains", "icontains"],
|
|
363
|
+
"default": "auto",
|
|
364
|
+
"description": "Name matching strategy when group_name is provided"
|
|
365
|
+
},
|
|
366
|
+
"include_hierarchy": {
|
|
367
|
+
"type": "boolean",
|
|
368
|
+
"default": True,
|
|
369
|
+
"description": "Include depth/parent/children/path if available"
|
|
370
|
+
},
|
|
371
|
+
"include_doors": {
|
|
372
|
+
"type": "boolean",
|
|
373
|
+
"default": True,
|
|
374
|
+
"description": "Include door_ids (scan /api/doors if missing)"
|
|
375
|
+
},
|
|
376
|
+
"include_doors_detail": {
|
|
377
|
+
"type": "boolean",
|
|
378
|
+
"default": False,
|
|
379
|
+
"description": "Also include brief door objects (id, name, description, group)"
|
|
380
|
+
},
|
|
381
|
+
"include_raw": {
|
|
382
|
+
"type": "boolean",
|
|
383
|
+
"default": False,
|
|
384
|
+
"description": "Attach raw DoorGroup payload"
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
"anyOf": [
|
|
388
|
+
{"required": ["group_id"]},
|
|
389
|
+
{"required": ["group_name"]}
|
|
390
|
+
]
|
|
391
|
+
}
|
|
392
|
+
)
|
|
393
|
+
|
|
394
|
+
CREATE_DOOR_GROUP_TOOL = Tool(
|
|
395
|
+
name="create-door-group",
|
|
396
|
+
description="Create a new door group. Parent ID defaults to 1 (root), depth defaults to 1.",
|
|
397
|
+
inputSchema={
|
|
398
|
+
"type": "object",
|
|
399
|
+
"properties": {
|
|
400
|
+
"name": {
|
|
401
|
+
"type": "string",
|
|
402
|
+
"description": "Name of the door group (e.g., 'Ground Floor', '1st Floor', '2nd Floor')"
|
|
403
|
+
},
|
|
404
|
+
"parent_id": {
|
|
405
|
+
"type": "integer",
|
|
406
|
+
"description": "Parent door group ID (default: 1 for root group)"
|
|
407
|
+
},
|
|
408
|
+
"depth": {
|
|
409
|
+
"type": "integer",
|
|
410
|
+
"description": "Depth level of the door group (1-8, default: 1)",
|
|
411
|
+
"minimum": 1,
|
|
412
|
+
"maximum": 8
|
|
413
|
+
}
|
|
414
|
+
},
|
|
415
|
+
"required": ["name"]
|
|
416
|
+
}
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
UPDATE_DOOR_GROUP_TOOL = Tool(
|
|
420
|
+
name="update-door-group",
|
|
421
|
+
description="Update an existing door group",
|
|
422
|
+
inputSchema={
|
|
423
|
+
"type": "object",
|
|
424
|
+
"properties": {
|
|
425
|
+
"group_id": {
|
|
426
|
+
"type": "integer",
|
|
427
|
+
"description": "ID of the door group to update"
|
|
428
|
+
},
|
|
429
|
+
"name": {
|
|
430
|
+
"type": "string",
|
|
431
|
+
"description": "New name for the door group"
|
|
432
|
+
},
|
|
433
|
+
"parent_id": {
|
|
434
|
+
"type": "integer",
|
|
435
|
+
"description": "New parent door group ID"
|
|
436
|
+
}
|
|
437
|
+
},
|
|
438
|
+
"required": ["group_id"]
|
|
439
|
+
}
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
DELETE_DOOR_GROUP_TOOL = Tool(
|
|
443
|
+
name="delete-door-group",
|
|
444
|
+
description="Delete a door group",
|
|
445
|
+
inputSchema={
|
|
446
|
+
"type": "object",
|
|
447
|
+
"properties": {
|
|
448
|
+
"group_id": {
|
|
449
|
+
"type": "integer",
|
|
450
|
+
"description": "ID of the door group to delete"
|
|
451
|
+
}
|
|
452
|
+
},
|
|
453
|
+
"required": ["group_id"]
|
|
454
|
+
}
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
ADD_DOORS_TO_GROUP_TOOL = Tool(
|
|
458
|
+
name="add-doors-to-group",
|
|
459
|
+
description="""
|
|
460
|
+
Assign one or more doors to a door group by updating each Door via PUT /api/doors/:id.
|
|
461
|
+
- Supports resolving by door_ids or door_names (exact match). At least one must be provided.
|
|
462
|
+
- Supports resolving the target group by group_id or group_name (exact match). One must be provided.
|
|
463
|
+
- If a door is already assigned to another single group, use `force=true` to overwrite. Otherwise a conflict is returned.
|
|
464
|
+
- If the door supports multiple groups (id_list), the tool will union the id into the list (idempotent).
|
|
465
|
+
""".strip(),
|
|
466
|
+
inputSchema={
|
|
467
|
+
"type": "object",
|
|
468
|
+
"properties": {
|
|
469
|
+
"group_id": {"type": "integer", "description": "Target door group ID"},
|
|
470
|
+
"group_name": {"type": "string", "description": "Target door group name (used when group_id is not provided)"},
|
|
471
|
+
"door_ids": {
|
|
472
|
+
"type": "array",
|
|
473
|
+
"items": {"type": "integer"},
|
|
474
|
+
"description": "List of door IDs to assign"
|
|
475
|
+
},
|
|
476
|
+
"door_names": {
|
|
477
|
+
"type": "array",
|
|
478
|
+
"items": {"type": "string"},
|
|
479
|
+
"description": "List of door names to assign (exact match)"
|
|
480
|
+
},
|
|
481
|
+
"force": {
|
|
482
|
+
"type": "boolean",
|
|
483
|
+
"description": "Overwrite an existing single-group assignment if different.",
|
|
484
|
+
"default": False
|
|
485
|
+
}
|
|
486
|
+
},
|
|
487
|
+
"required": []
|
|
488
|
+
}
|
|
489
|
+
)
|
|
490
|
+
|
|
491
|
+
REMOVE_DOORS_FROM_GROUP_TOOL = Tool(
|
|
492
|
+
name="remove-doors-from-group",
|
|
493
|
+
description="""
|
|
494
|
+
Remove one or more doors from a door group.
|
|
495
|
+
|
|
496
|
+
IMPORTANT:
|
|
497
|
+
- BioStar 2 does not accept clearing 'door_group_id' to null/empty. If removal would leave
|
|
498
|
+
a door with no group, it must be reassigned somewhere.
|
|
499
|
+
|
|
500
|
+
FALLBACK BEHAVIOR (when removal would leave no group):
|
|
501
|
+
- fallback_mode:
|
|
502
|
+
- "auto" (default): reassign to a root-like group (All Door Groups/All Doors/기본/전체),
|
|
503
|
+
else group id == 1, else the smallest group id.
|
|
504
|
+
- "ask": make NO changes; return a list of candidate groups and `needs_fallback_choice=true`.
|
|
505
|
+
- "assign": reassign to the exact `fallback_group_id` you provide.
|
|
506
|
+
|
|
507
|
+
USAGE:
|
|
508
|
+
- If you want the tool to ask you for where to move: set `fallback_mode="ask"`.
|
|
509
|
+
- If you already know the destination group: set `fallback_mode="assign"` and pass `fallback_group_id`.
|
|
510
|
+
""",
|
|
511
|
+
inputSchema={
|
|
512
|
+
"type": "object",
|
|
513
|
+
"properties": {
|
|
514
|
+
"door_ids": {"type":"array","items":{"type":"integer"}},
|
|
515
|
+
"door_names": {"type":"array","items":{"type":"string"}},
|
|
516
|
+
"group_id": {"type":"integer", "description":"Remove from this group id"},
|
|
517
|
+
"group_name": {"type":"string", "description":"Or remove from this group name"},
|
|
518
|
+
|
|
519
|
+
# NEW:
|
|
520
|
+
"fallback_mode": {
|
|
521
|
+
"type":"string",
|
|
522
|
+
"enum":["auto","ask","assign"],
|
|
523
|
+
"default":"auto",
|
|
524
|
+
"description":"What to do if removal would leave no group"
|
|
525
|
+
},
|
|
526
|
+
"fallback_group_id": {
|
|
527
|
+
"type":"integer",
|
|
528
|
+
"description":"Required when fallback_mode='assign'"
|
|
529
|
+
}
|
|
530
|
+
},
|
|
531
|
+
"required": [] # (group_id or group_name required at runtime by handler)
|
|
532
|
+
}
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
UPDATE_DOOR_DESCRIPTION_TOOL = Tool(
|
|
536
|
+
name="update-door-description",
|
|
537
|
+
description=(
|
|
538
|
+
"Update only the 'description' field of a Door via PUT /api/doors/:id with a minimal payload. "
|
|
539
|
+
"This tool does NOT fetch or send any other fields, ensuring no unintended changes."
|
|
540
|
+
),
|
|
541
|
+
inputSchema={
|
|
542
|
+
"type": "object",
|
|
543
|
+
"properties": {
|
|
544
|
+
"door_id": {
|
|
545
|
+
"type": "integer",
|
|
546
|
+
"description": "ID of the door to update"
|
|
547
|
+
},
|
|
548
|
+
"description": {
|
|
549
|
+
"type": "string",
|
|
550
|
+
"description": "New description to set. Pass an empty string to clear."
|
|
551
|
+
}
|
|
552
|
+
},
|
|
553
|
+
"required": ["door_id", "description"]
|
|
554
|
+
}
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
SET_DOOR_AUTO_MODE_TOOL = Tool(
|
|
558
|
+
name="set-door-auto-mode",
|
|
559
|
+
description=(
|
|
560
|
+
"Enable/disable the door's 'auto door' option (unconditional_lock) with XOR validation "
|
|
561
|
+
"against 'relock on close' (open_once). Steps: GET -> XOR check -> NO-OP or PUT with preserved fields."
|
|
562
|
+
),
|
|
563
|
+
inputSchema={
|
|
564
|
+
"type": "object",
|
|
565
|
+
"properties": {
|
|
566
|
+
"door_id": {"type": "integer", "description": "Door ID"},
|
|
567
|
+
"door_name": {"type": "string", "description": "Exact door name (alternative to door_id)"},
|
|
568
|
+
"enable": {"type": "boolean", "description": "true to enable, false to disable"}
|
|
569
|
+
},
|
|
570
|
+
"anyOf": [
|
|
571
|
+
{"required": ["door_id", "enable"]},
|
|
572
|
+
{"required": ["door_name", "enable"]}
|
|
573
|
+
]
|
|
574
|
+
}
|
|
575
|
+
)
|
|
576
|
+
|
|
577
|
+
SET_DOOR_RELOCK_ON_CLOSE_TOOL = Tool(
|
|
578
|
+
name="set-door-relock-on-close",
|
|
579
|
+
description=(
|
|
580
|
+
"Enable/disable 'relock on close' (open_once) with XOR validation against 'auto door' "
|
|
581
|
+
"(unconditional_lock). Steps: GET -> XOR check -> NO-OP or PUT with preserved fields."
|
|
582
|
+
),
|
|
583
|
+
inputSchema={
|
|
584
|
+
"type": "object",
|
|
585
|
+
"properties": {
|
|
586
|
+
"door_id": {"type": "integer", "description": "Door ID"},
|
|
587
|
+
"door_name": {"type": "string", "description": "Exact door name (alternative to door_id)"},
|
|
588
|
+
"enable": {"type": "boolean", "description": "true to enable, false to disable"}
|
|
589
|
+
},
|
|
590
|
+
"anyOf": [
|
|
591
|
+
{"required": ["door_id", "enable"]},
|
|
592
|
+
{"required": ["door_name", "enable"]}
|
|
593
|
+
]
|
|
594
|
+
}
|
|
595
|
+
)
|
|
596
|
+
|
|
597
|
+
SET_DOOR_OPEN_DURATION_TOOL = Tool(
|
|
598
|
+
name="set-door-open-duration",
|
|
599
|
+
description=(
|
|
600
|
+
"Update only the door 'open_duration' (seconds) while preserving all other fields. "
|
|
601
|
+
"Idempotent: if the current value equals the requested one, returns no-op."
|
|
602
|
+
),
|
|
603
|
+
inputSchema={
|
|
604
|
+
"type": "object",
|
|
605
|
+
"properties": {
|
|
606
|
+
"door_id": {"type": "integer", "description": "ID of the door to update"},
|
|
607
|
+
"door_name": {"type": "string", "description": "Exact door name (alternative to door_id)"},
|
|
608
|
+
"seconds": {
|
|
609
|
+
"type": "integer",
|
|
610
|
+
"description": "New open duration in seconds (sent as string). Range: 1-900 (inclusive).",
|
|
611
|
+
"minimum": 1,
|
|
612
|
+
"maximum": 900
|
|
613
|
+
}
|
|
614
|
+
},
|
|
615
|
+
"anyOf": [
|
|
616
|
+
{"required": ["door_id", "seconds"]},
|
|
617
|
+
{"required": ["door_name", "seconds"]}
|
|
618
|
+
]
|
|
619
|
+
}
|
|
620
|
+
)
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
# ---------------------------------------------------------------------------
|
|
624
|
+
# Timed APB Unified Tool
|
|
625
|
+
# - Turn OFF (no device), turn ON for entry-only or exit-only, and optionally
|
|
626
|
+
# set/reset the reset_time in minutes (0..60 inclusive).
|
|
627
|
+
# - Business rules:
|
|
628
|
+
# * Allowed modes depend on connected devices of the door:
|
|
629
|
+
# - no entry, no exit => {off}
|
|
630
|
+
# - both entry and exit => {off, entry, exit}
|
|
631
|
+
# - entry only => {off, entry}
|
|
632
|
+
# - exit only => {off, exit}
|
|
633
|
+
# * When turning ON (entry/exit), force:
|
|
634
|
+
# - door_anti_passback.apb_type = "0" (NONE)
|
|
635
|
+
# - sensor_input_id.apb_use_door_sensor = "0" (OFF)
|
|
636
|
+
# * All other fields must be preserved exactly as-is.
|
|
637
|
+
# ---------------------------------------------------------------------------
|
|
638
|
+
SET_DOOR_TIMED_APB_TOOL = Tool(
|
|
639
|
+
name="set-door-timed-apb",
|
|
640
|
+
description=(
|
|
641
|
+
"Set door Timed APB (Anti-Passback) mode. Turn OFF (no device), or turn ON for entry-only/exit-only "
|
|
642
|
+
"with reset_time (0..60 minutes). Rejects invalid requests based on the door's "
|
|
643
|
+
"device configuration. When enabling APB, it forces classic APB off and sensor APB off. "
|
|
644
|
+
"All other fields remain intact."
|
|
645
|
+
),
|
|
646
|
+
inputSchema={
|
|
647
|
+
"type": "object",
|
|
648
|
+
"properties": {
|
|
649
|
+
"door_id": {
|
|
650
|
+
"type": "integer",
|
|
651
|
+
"description": "Door ID (optional). Either door_id or door_name is required."
|
|
652
|
+
},
|
|
653
|
+
"door_name": {
|
|
654
|
+
"type": "string",
|
|
655
|
+
"description": "Exact door name (optional). Either door_id or door_name is required."
|
|
656
|
+
},
|
|
657
|
+
"mode": {
|
|
658
|
+
"description": "APB mode: off | entry | exit (also accepts 0/1/2).",
|
|
659
|
+
"anyOf": [
|
|
660
|
+
{"type": "string", "enum": ["off", "entry", "exit", "0", "1", "2"]},
|
|
661
|
+
{"type": "integer", "enum": [0, 1, 2]}
|
|
662
|
+
]
|
|
663
|
+
},
|
|
664
|
+
"reset_time": {
|
|
665
|
+
"type": "integer",
|
|
666
|
+
"description": "APB reset time in minutes. 0..60 inclusive. Required when mode != off.",
|
|
667
|
+
"minimum": 0,
|
|
668
|
+
"maximum": 60
|
|
669
|
+
},
|
|
670
|
+
"bypass_group_ids": {
|
|
671
|
+
"type": "array",
|
|
672
|
+
"items": {"type": "integer"},
|
|
673
|
+
"description": "Optional: Access Group IDs for timed APB bypass. If omitted, preserves current."
|
|
674
|
+
}
|
|
675
|
+
},
|
|
676
|
+
"anyOf": [
|
|
677
|
+
{"required": ["door_id", "mode"]},
|
|
678
|
+
{"required": ["door_name", "mode"]}
|
|
679
|
+
]
|
|
680
|
+
}
|
|
681
|
+
)
|
|
682
|
+
|
|
683
|
+
|
|
684
|
+
SET_DOOR_CLASSIC_APB_TOOL = Tool(
|
|
685
|
+
name="set-door-classic-apb",
|
|
686
|
+
description=(
|
|
687
|
+
"Set door Classic APB (Anti-Passback) mode. "
|
|
688
|
+
"Controls the door_anti_passback.apb_type setting. "
|
|
689
|
+
"Options: none (0), soft (1), hard (2). "
|
|
690
|
+
"Preserves existing reset_time and open_when_disconnected values."
|
|
691
|
+
),
|
|
692
|
+
inputSchema={
|
|
693
|
+
"type": "object",
|
|
694
|
+
"properties": {
|
|
695
|
+
"door_id": {
|
|
696
|
+
"type": "integer",
|
|
697
|
+
"description": "Door ID (optional). Either door_id or door_name is required."
|
|
698
|
+
},
|
|
699
|
+
"door_name": {
|
|
700
|
+
"type": "string",
|
|
701
|
+
"description": "Exact door name (optional). Either door_id or door_name is required."
|
|
702
|
+
},
|
|
703
|
+
"apb_type": {
|
|
704
|
+
"description": "APB type: none | soft | hard (also accepts 0/1/2).",
|
|
705
|
+
"anyOf": [
|
|
706
|
+
{"type": "string", "enum": ["none", "soft", "hard", "0", "1", "2"]},
|
|
707
|
+
{"type": "integer", "enum": [0, 1, 2]}
|
|
708
|
+
]
|
|
709
|
+
}
|
|
710
|
+
},
|
|
711
|
+
"anyOf": [
|
|
712
|
+
{"required": ["door_id", "apb_type"]},
|
|
713
|
+
{"required": ["door_name", "apb_type"]}
|
|
714
|
+
]
|
|
715
|
+
}
|
|
716
|
+
)
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
SET_DOOR_IO_TOOL = Tool(
|
|
720
|
+
name="set-door-io",
|
|
721
|
+
description=(
|
|
722
|
+
"Update a door's 4 IO fields (entry_device_id, relay_output_id, "
|
|
723
|
+
"exit_button_input_id, sensor_input_id) in a single PUT while preserving "
|
|
724
|
+
"all other fields. Accepts either IDs or names; when names are provided, "
|
|
725
|
+
"the tool searches /api/v2/devices/search to resolve them to IDs. "
|
|
726
|
+
"To clear the entry device, pass entry_device_id=null or entry_device_name='none'."
|
|
727
|
+
),
|
|
728
|
+
inputSchema={
|
|
729
|
+
"type": "object",
|
|
730
|
+
"properties": {
|
|
731
|
+
# Door target (id or name)
|
|
732
|
+
"door_id": {"type": "integer", "description": "ID of the door to update."},
|
|
733
|
+
"door_name": {"type": "string", "description": "Exact door name to update."},
|
|
734
|
+
|
|
735
|
+
# 1) Entry device (reader) - either id or name (name can be 'none' to clear)
|
|
736
|
+
"entry_device_id": {"type": ["integer", "null"], "description": "Device id for entry reader, or null to clear."},
|
|
737
|
+
"entry_device_name": {"type": ["string", "null"], "description": "Device name for entry reader; 'none' to clear."},
|
|
738
|
+
|
|
739
|
+
# 2) Relay output (door relay) - either id or name
|
|
740
|
+
"relay_device_id": {"type": "integer", "description": "Device id hosting the relay."},
|
|
741
|
+
"relay_device_name": {"type": "string", "description": "Device name hosting the relay."},
|
|
742
|
+
"relay_index": {"type": "integer", "description": "Relay index on the device."},
|
|
743
|
+
|
|
744
|
+
# 3) Exit button input - either id or name
|
|
745
|
+
"exit_button_device_id": {"type": "integer", "description": "Device id for the exit button input."},
|
|
746
|
+
"exit_button_device_name": {"type": "string", "description": "Device name for the exit button input."},
|
|
747
|
+
"exit_button_input_index": {"type": "integer", "description": "Input index (e.g., 0 or 1)."},
|
|
748
|
+
"exit_button_input_type": {
|
|
749
|
+
"type": "integer",
|
|
750
|
+
"enum": [0, 1],
|
|
751
|
+
"description": "Input type: 1=NC, 0=NO"
|
|
752
|
+
},
|
|
753
|
+
|
|
754
|
+
# 4) Door sensor input - either id or name
|
|
755
|
+
"sensor_device_id": {"type": "integer", "description": "Device id for the door sensor input."},
|
|
756
|
+
"sensor_device_name": {"type": "string", "description": "Device name for the door sensor input."},
|
|
757
|
+
"sensor_input_index": {"type": "integer", "description": "Input index (e.g., 0 or 1)."},
|
|
758
|
+
"sensor_input_type": {
|
|
759
|
+
"type": "integer",
|
|
760
|
+
"enum": [0, 1],
|
|
761
|
+
"description": "Input type: 1=NC, 0=NO"
|
|
762
|
+
},
|
|
763
|
+
"sensor_apb_use": {
|
|
764
|
+
"description": "Whether to use the door sensor for APB (apb_use_door_sensor). Accepts boolean or 0/1/'0'/'1'.",
|
|
765
|
+
"oneOf": [
|
|
766
|
+
{"type": "boolean"},
|
|
767
|
+
{"type": "integer", "enum": [0, 1]},
|
|
768
|
+
{"type": "string", "enum": ["0", "1", "true", "false", "True", "False"]}
|
|
769
|
+
]
|
|
770
|
+
}
|
|
771
|
+
},
|
|
772
|
+
"anyOf": [
|
|
773
|
+
{"required": ["door_id"]},
|
|
774
|
+
{"required": ["door_name"]}
|
|
775
|
+
]
|
|
776
|
+
}
|
|
777
|
+
)
|
|
778
|
+
|
|
779
|
+
BULK_CREATE_DOORS_TOOL = Tool(
|
|
780
|
+
name="bulk-create-doors",
|
|
781
|
+
description=(
|
|
782
|
+
"Create multiple doors by iterating the single 'create-door' logic sequentially. "
|
|
783
|
+
"This tool NEVER performs any automatic device discovery/registration/selection. "
|
|
784
|
+
"Each item MUST follow the exact schema of 'create-door'. "
|
|
785
|
+
"Results are aggregated as created / preview-needed / failed."
|
|
786
|
+
),
|
|
787
|
+
inputSchema={
|
|
788
|
+
"type": "object",
|
|
789
|
+
"properties": {
|
|
790
|
+
"doors": {
|
|
791
|
+
"type": "array",
|
|
792
|
+
"description": "List of door payloads. Each item uses the same schema as 'create-door'.",
|
|
793
|
+
"items": {
|
|
794
|
+
"type": "object",
|
|
795
|
+
"properties": {
|
|
796
|
+
# flow controls
|
|
797
|
+
"confirm": {"type": "boolean", "description": "If true and all required fields are valid, creation proceeds.", "default": False},
|
|
798
|
+
"default_group_id": {"type": "integer", "description": "Fallback door group id when 'door_group_id' is not provided.", "default": 1},
|
|
799
|
+
|
|
800
|
+
# door core
|
|
801
|
+
"name": {"type": "string", "description": "Door name"},
|
|
802
|
+
"description": {"type": "string", "description": "Door description"},
|
|
803
|
+
"door_group_id": {"type": "integer", "description": "Door group id to assign at creation time"},
|
|
804
|
+
"open_timeout": {"type": "integer", "description": "Door open timeout (sec).", "default": 10},
|
|
805
|
+
"open_duration": {"type": "integer", "description": "Door open duration (sec).", "default": 5},
|
|
806
|
+
"open_once": {"type": "boolean", "description": "Open once option.", "default": True},
|
|
807
|
+
"unconditional_lock": {"type": "boolean", "description": "Unconditional lock option.", "default": True},
|
|
808
|
+
|
|
809
|
+
# device / IO (same guardrails as 'create-door')
|
|
810
|
+
"entry_device_id": {"type": "integer", "description": "Device id to control the lock (1:1 mapping enforced)."},
|
|
811
|
+
"relay_index": {"type": "integer", "description": "Required to actually create. If missing, tool returns relay options and stops."},
|
|
812
|
+
|
|
813
|
+
"exit_device_id": {"type": "integer", "description": "Exit button device id."},
|
|
814
|
+
"exit_input_index": {"type": "integer", "description": "Exit input index.", "default": 0},
|
|
815
|
+
"exit_input_type": {"type": "integer", "description": "Exit input type.", "default": 1},
|
|
816
|
+
|
|
817
|
+
"sensor_device_id": {"type": "integer", "description": "Door sensor device id."},
|
|
818
|
+
"sensor_input_index": {"type": "integer", "description": "Sensor input index.", "default": 1},
|
|
819
|
+
"sensor_input_type": {"type": "integer", "description": "Sensor input type.", "default": 1},
|
|
820
|
+
"apb_use_door_sensor": {"type": "integer", "description": "Use door sensor for APB.", "default": 1}
|
|
821
|
+
},
|
|
822
|
+
# Keep in sync with CREATE_DOOR_TOOL
|
|
823
|
+
"required": [
|
|
824
|
+
"name",
|
|
825
|
+
"entry_device_id",
|
|
826
|
+
"exit_device_id", "exit_input_index", "exit_input_type",
|
|
827
|
+
"sensor_device_id", "sensor_input_index", "sensor_input_type", "apb_use_door_sensor"
|
|
828
|
+
]
|
|
829
|
+
}
|
|
830
|
+
},
|
|
831
|
+
"continue_on_error": {
|
|
832
|
+
"type": "boolean",
|
|
833
|
+
"description": "If false, stop at the first failure. Default: true.",
|
|
834
|
+
"default": True
|
|
835
|
+
}
|
|
836
|
+
},
|
|
837
|
+
"required": ["doors"]
|
|
838
|
+
}
|
|
839
|
+
)
|
|
840
|
+
|
|
841
|
+
# Export all door tools
|
|
842
|
+
DOOR_TOOLS = [
|
|
843
|
+
GET_DOORS_TOOL,
|
|
844
|
+
GET_DOOR_TOOL,
|
|
845
|
+
CREATE_DOOR_TOOL,
|
|
846
|
+
UPDATE_DOOR_TOOL,
|
|
847
|
+
DELETE_DOOR_TOOL,
|
|
848
|
+
CONTROL_DOOR_TOOL,
|
|
849
|
+
GET_DOORS_STATUS_TOOL,
|
|
850
|
+
GET_DOOR_GROUPS_TOOL,
|
|
851
|
+
GET_DOOR_GROUP_TOOL,
|
|
852
|
+
CREATE_DOOR_GROUP_TOOL,
|
|
853
|
+
UPDATE_DOOR_GROUP_TOOL,
|
|
854
|
+
DELETE_DOOR_GROUP_TOOL,
|
|
855
|
+
ADD_DOORS_TO_GROUP_TOOL,
|
|
856
|
+
REMOVE_DOORS_FROM_GROUP_TOOL,
|
|
857
|
+
UPDATE_DOOR_DESCRIPTION_TOOL,
|
|
858
|
+
SET_DOOR_AUTO_MODE_TOOL,
|
|
859
|
+
SET_DOOR_RELOCK_ON_CLOSE_TOOL,
|
|
860
|
+
SET_DOOR_OPEN_DURATION_TOOL,
|
|
861
|
+
SET_DOOR_TIMED_APB_TOOL,
|
|
862
|
+
SET_DOOR_CLASSIC_APB_TOOL,
|
|
863
|
+
SET_DOOR_IO_TOOL,
|
|
864
|
+
BULK_CREATE_DOORS_TOOL
|
|
865
|
+
]
|