# SDK Alarm Query Approach ## Discovery Summary After extracting and analyzing the GeViSoft .NET SDK API documentation (2403 HTML files from CHM), I found the correct approach to read action mappings from the live GeViSoft instance. ## Key Finding **SetupClient functions are NOT exposed in the .NET SDK**. The SDK documentation explicitly states: > "The SetupClient functions are used by GeViSet to change the server setup. They are **usually not of interest for SDK developers**." Instead, the SDK provides **State Query** actions to read alarm configurations. ## The Solution: State Queries Action mappings in GeViSoft are stored as **Alarms**. We can query them using these state query actions: ### Available Query Actions | Action | Description (German → English) | Purpose | |--------|-------------------------------|---------| | `GeViSQ_GetFirstAlarm` | Liefert die Information zu dem ersten Alarm | Get first alarm information | | `GeViSQ_GetNextAlarm` | Liefert die Information zu dem naechsten Alarm | Get next alarm information | | `GeViSQ_GetAlarms` | Liefert die Information zum bestimmten Alarm | Get specific alarm by ID | | `GeViSQ_GetAlarmsByName` | Liefert die Information zum bestimmten Alarm | Get specific alarm by name | | `GeViDBQ_CreateAlarmQuery` | Startet eine Abfrage ueber die Alarmtabelle | Start query over alarm table | ### How to Enumerate All Alarms ```csharp // 1. Create query for first alarm var query = new GeViSQ_GetFirstAlarm( initActiveOnly: false, // false = all alarms (not just active) initEnabledOnly: false // false = both enabled and disabled ); // 2. Send query to GeViServer await geviDatabase.SendMessageAsync(query); // 3. Register callback to receive answer geviDatabase.OnNewGeViSA_FirstAlarm += HandleFirstAlarmAnswer; // 4. Iterate through remaining alarms geviDatabase.OnNewGeViSA_NextAlarm += HandleNextAlarmAnswer; // In handlers, send GeViSQ_GetNextAlarm to get subsequent alarms ``` ## Implementation Plan ### Phase 1: Alarm Query Service (C# SDK Bridge) Create `AlarmQueryService.cs`: ```csharp public class AlarmQueryService { private readonly GeViDatabaseWrapper _database; private readonly List _alarmCache = new(); public async Task> GetAllAlarmsAsync() { _alarmCache.Clear(); // Send first alarm query var query = new GeViSQ_GetFirstAlarm(false, false); await _database.SendMessageAsync(query); // Wait for answers (with timeout) // Answers arrive via callbacks return _alarmCache; } private void HandleFirstAlarmAnswer(GeViSA_FirstAlarmEventArgs e) { // Parse alarm data var alarm = ParseAlarmData(e); _alarmCache.Add(alarm); // Request next alarm var nextQuery = new GeViSQ_GetNextAlarm(); _database.SendMessageAsync(nextQuery); } private void HandleNextAlarmAnswer(GeViSA_NextAlarmEventArgs e) { if (e.HasMoreAlarms) { var alarm = ParseAlarmData(e); _alarmCache.Add(alarm); // Request next var nextQuery = new GeViSQ_GetNextAlarm(); _database.SendMessageAsync(nextQuery); } } } ``` ### Phase 2: Identify Action Mapping Alarms Not all alarms are action mappings. Need to filter by: - Alarm type/category - Input action field presence - Output actions field presence **Example alarm structure** (from GeViDB.mdb): ``` ID: 12345 Name: "Motion Detection Auto-Route" Type: "Action Mapping" (or similar type ID) InputAction: "VMD_Start(101038)" OutputActions: ["CrossSwitch(101038, 1, 0)"] Enabled: true ``` ### Phase 3: Update ActionMappingHandler Modify `ActionMappingHandler.cs`: ```csharp public class ActionMappingHandler { private readonly AlarmQueryService _alarmQuery; public async Task> GetAllActionMappingsAsync() { // Query all alarms from GeViServer var allAlarms = await _alarmQuery.GetAllAlarmsAsync(); // Filter to only action mapping type alarms var actionMappings = allAlarms .Where(IsActionMapping) .Select(MapToActionMappingConfig) .ToList(); return actionMappings; } private bool IsActionMapping(AlarmInfo alarm) { // Filter logic: // - Has input action // - Has output actions // - Type indicates it's an action mapping return !string.IsNullOrEmpty(alarm.InputAction) && alarm.OutputActions?.Any() == true; } } ``` ### Phase 4: Callback Registration Need to investigate: 1. What answer types are returned by these queries 2. How to register callbacks for alarm answers 3. What fields are available in the answer objects ## Next Steps 1. **Find alarm answer event types** - Search for `GeViSA_FirstAlarm`, `GeViSA_NextAlarm` event args 2. **Understand alarm data structure** - What fields are available? 3. **Test query execution** - Send a GetFirstAlarm query and inspect the response 4. **Implement full enumeration** - Iterate through all alarms 5. **Filter for action mappings** - Identify which alarms are action mappings 6. **Map to gRPC model** - Convert alarm data to ActionMappingConfig ## Advantages of This Approach ✅ Uses official SDK API (not direct database access) ✅ Reads LIVE data from GeViServer (not stale database copy) ✅ Same data that GeViSet would see ✅ Respects GeViServer's locking and transaction handling ✅ Can receive real-time updates via alarm events ## Questions to Resolve 1. **Answer event types**: What are the exact event arg types for alarm query answers? 2. **Alarm fields**: What properties are available on alarm answer objects? 3. **Action mapping identification**: How to distinguish action mapping alarms from other alarm types? 4. **Write operations**: How to create/update/delete alarms (action mappings)? 5. **Real-time updates**: Can we subscribe to alarm change notifications? ## Documentation Files Extracted CHM documentation location: ``` C:\DEV\COPILOT\geutebruck-api\docs\chm-extracted\ ``` Key files: - `class_g_e_u_t_e_b_r_u_e_c_k_1_1_ge_vi_soft_s_d_k_n_e_t_1_1_actions_wrapper_1_1_ge_vi_database-members.html` - All GeViDatabase methods - `class_g_e_u_t_e_b_r_u_e_c_k_1_1_ge_vi_soft_s_d_k_n_e_t_1_1_actions_wrapper_1_1_state_queries_1_1_ge_vi_s_q___get_first_alarm.html` - GetFirstAlarm documentation