This MVP release provides a complete full-stack solution for managing action mappings in Geutebruck's GeViScope and GeViSoft video surveillance systems. ## Features ### Flutter Web Application (Port 8081) - Modern, responsive UI for managing action mappings - Action picker dialog with full parameter configuration - Support for both GSC (GeViScope) and G-Core server actions - Consistent UI for input and output actions with edit/delete capabilities - Real-time action mapping creation, editing, and deletion - Server categorization (GSC: prefix for GeViScope, G-Core: prefix for G-Core servers) ### FastAPI REST Backend (Port 8000) - RESTful API for action mapping CRUD operations - Action template service with comprehensive action catalog (247 actions) - Server management (G-Core and GeViScope servers) - Configuration tree reading and writing - JWT authentication with role-based access control - PostgreSQL database integration ### C# SDK Bridge (gRPC, Port 50051) - Native integration with GeViSoft SDK (GeViProcAPINET_4_0.dll) - Action mapping creation with correct binary format - Support for GSC and G-Core action types - Proper Camera parameter inclusion in action strings (fixes CrossSwitch bug) - Action ID lookup table with server-specific action IDs - Configuration reading/writing via SetupClient ## Bug Fixes - **CrossSwitch Bug**: GSC and G-Core actions now correctly display camera/PTZ head parameters in GeViSet - Action strings now include Camera parameter: `@ PanLeft (Comment: "", Camera: 101028)` - Proper filter flags and VideoInput=0 for action mappings - Correct action ID assignment (4198 for GSC, 9294 for G-Core PanLeft) ## Technical Stack - **Frontend**: Flutter Web, Dart, Dio HTTP client - **Backend**: Python FastAPI, PostgreSQL, Redis - **SDK Bridge**: C# .NET 8.0, gRPC, GeViSoft SDK - **Authentication**: JWT tokens - **Configuration**: GeViSoft .set files (binary format) ## Credentials - GeViSoft/GeViScope: username=sysadmin, password=masterkey - Default admin: username=admin, password=admin123 ## Deployment All services run on localhost: - Flutter Web: http://localhost:8081 - FastAPI: http://localhost:8000 - SDK Bridge gRPC: localhost:50051 - GeViServer: localhost (default port) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
22 KiB
GeViSoft .NET SDK Reference - Action Mapping Guide
Generated: 2025-12-11 SDK Version: GeViSoft SDK 6.0.1.5 CHM Files Extracted to: C:\Gevisoft\Documentation\extracted_html\
Table of Contents
- Overview
- GeViSoft Architecture
- Core SDK Components
- Action Mapping Concepts
- API Classes and Methods
- Working with Action Mappings
- State Queries
- Database Queries
- Code Examples
Overview
GeViSoft is a management platform (control layer) that coordinates multiple GeViScope instances (video servers). This SDK allows programmatic control of GeViSoft/GeViScope systems through a .NET API.
Key Concepts:
- GeViSoft: Management platform controlling multiple GeViScope instances
- GeViScope: Video server instances handling cameras, monitors, and video routing
- GeViServer: The GeViSoft server process that clients connect to
- Actions: Commands or notifications in the system
- Action Mapping: Automation rules that trigger output actions in response to input actions
GeViSoft Architecture
┌────────────────────────────────────────────────┐
│ GeViSoft (Management Layer) │
│ GeViServer Process │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ Action Mapping Engine │ │
│ │ Input Action → Output Action(s) │ │
│ └──────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ Activity Database │ │
│ │ - Action logs │ │
│ │ - Alarm events │ │
│ │ - Configuration tables │ │
│ └──────────────────────────────────────────┘ │
└────────────────────────────────────────────────┘
│
┌─────────┴─────────┐
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ GeViScope │ │ GeViScope │
│ Instance 1 │ │ Instance 2 │
│ (GSCServer) │ │ (GSCServer) │
│ │ │ │
│ Cameras │ │ Cameras │
│ Monitors │ │ Monitors │
│ Video Routing │ │ Video Routing │
└─────────────────┘ └─────────────────┘
Core SDK Components
1. GeViAPIClient
Primary SDK wrapper class for communicating with GeViServer.
Header: GeViAPIClient.h
DLL: GeViProcAPI.dll
Key Methods:
Connect()- Establishes connection to GeViServerDisconnect()- Disconnects from GeViServerSendMessage()- Sends action messages to the serverSendStateQuery()- Queries system state (e.g., list of cameras, action mappings)SendDatabaseQuery()- Queries activity databaseSetCBNotification()- Registers callback for receiving server notificationsSendPing()- Heartbeat checkEncodePassword()- Encodes plaintext passwords for authentication
2. CGeViMessage
Base class for all messages (actions, queries, answers).
Types of Messages:
- Actions (CAction): Commands or notifications (e.g.,
CrossSwitch,InputContact) - State Queries (CStateQuery): Request system state information
- State Answers (CStateAnswer): Responses to state queries
- Database Queries (CDataBaseQuery): Query action/alarm logs
- Database Answers (CDataBaseAnswer): Responses to database queries
3. CAction
Base class for action messages.
Properties:
m_ActionKind- Action category (TActionKind)m_ActionCode- Specific action type code (TActionCode)
Methods:
GetActionName()- Returns action name as stringGetActionCodeByName(name)- Converts action name to codeReadASCIIMessage()- Parses action from ASCII stringWriteASCIIMessage()- Serializes action to ASCII string
Action Mapping Concepts
What is Action Mapping?
Action mapping allows you to trigger one or more actions automatically when another action occurs.
Example Use Case:
- Input Action:
InputContact(3, false)- Door contact opened - Output Actions:
AlternateContact(2, 1000, 500)- Flash beacon on digital output 2
Action Mapping Components
┌──────────────────────────────────────────┐
│ Action Mapping Entry │
├──────────────────────────────────────────┤
│ Input Action: │
│ - Action name (e.g., InputContact) │
│ - Parameters (e.g., ContactID=3) │
│ │
│ Output Actions (List): │
│ - Action 1: AlternateContact(...) │
│ - Action 2: SendMail(...) │
│ - Action 3: CrossSwitch(...) │
└──────────────────────────────────────────┘
Action Categories
Actions are organized into logical categories:
- System Actions: System lifecycle, authentication, database operations
- Video Actions: Video control, camera management, VCA (Video Content Analysis)
- Device Actions: Hardware device integration
- Audio Actions: Audio stream management
- Camera Control Actions: PTZ and camera parameter control
- Digital Contacts Actions: Digital I/O operations (e.g.,
InputContact,AlternateContact,CloseContact) - ATM Actions: ATM integration
- POS Actions: Point-of-Sale integration
- Backup Actions: Data backup and export
- Remote Export Actions: Remote video export capabilities
API Classes and Methods
Connection Management
// Constructor
GeViAPIClient::GeViAPIClient(
const char* Aliasname, // Connection alias (can be empty "")
const char* Address, // GeViServer IP or hostname
const char* Username, // Username
const char* Password, // Encrypted password (use EncodePassword)
const char* Username2, // Second username (dual control, optional "")
const char* Password2 // Second password (optional "")
)
// Connect to server
TConnectResult Connect(
TGeViConnectProgress ACallback, // Progress callback
void* AInstance // Pointer to calling instance ("this")
)
// Disconnect
void Disconnect()
// Encode password
static void EncodePassword(
char* Dest, // Output buffer (33 bytes)
const char* Source, // Plaintext password
int DestSize // Size of destination buffer (33)
)
Sending Actions
// Send action message (fire-and-forget, no response)
void SendMessage(CGeViMessage* GeViMessage)
// Example: Send CustomAction
CGeViMessage* gevimessage = new CActCustomAction(123, "Hello GeViSoft!");
m_APIClient->SendMessage(gevimessage);
gevimessage->DeleteObject(); // Always delete objects created in DLL
State Queries (Reading Configuration)
State queries retrieve system configuration and state information.
// Send state query (blocking call, returns answer)
CStateAnswer* SendStateQuery(
CStateQuery* GeViQuery,
const int timeout_ms // Use INFINITE to prevent timeout
)
Common State Queries:
CSQGetFirstVideoInput()- Get first video input (camera)CSQGetNextVideoInput()- Get next video inputCSQGetFirstMonitor()- Get first monitorCSQGetActionMappingTable()- Retrieve action mapping configurationCSQSetActionMappingTable()- Send updated action mapping configuration
Database Queries (Reading Logs)
Database queries retrieve historical action and alarm data.
// Send database query (blocking call, returns answer)
CDataBaseAnswer* SendDatabaseQuery(
CDataBaseQuery* GeViMessage,
const int timeout_ms
)
Database Query Workflow:
- Create query session:
CDBQCreateActionQuery(0) - Extract query handle from answer
- Set filters (optional):
CDBFTypeName,CDBFPK_GrtEqu, etc. - Fetch records:
CDBQGetLast,CDBQGetNext,CDBQGetPrev - Close session when done
Receiving Notifications (Server Push)
// Register notification callback
void SetCBNotification(
TGeViDatabaseNotification ACallback,
void* AInstance
)
// Callback signature
void __stdcall GeViDatabaseNotificationCB(
void* Instance,
TServerNotification Notification,
void* Params
)
Notification Types:
NFServer_NewMessage- New action message receivedNFServer_SetupChanged- Configuration changedNFServer_Shutdown- Server shutting down
Working with Action Mappings
Reading Action Mapping Configuration
To read the current action mapping configuration from GeViServer:
// 1. Create state query to get action mapping table
CStateQuery* getActionMappingQuery = new CSQGetActionMappingTable();
// 2. Send query to server
CStateAnswer* answer = m_APIClient->SendStateQuery(
getActionMappingQuery,
INFINITE // No timeout
);
// 3. Clean up query
getActionMappingQuery->DeleteObject();
// 4. Process answer
if (answer && answer->m_AnswerKind == sak_ActionMappingTable)
{
CSAActionMappingTable* mappingTable =
reinterpret_cast<CSAActionMappingTable*>(answer);
// Work with mappingTable data structure
// ... process action mappings ...
answer->DeleteObject();
}
Modifying Action Mapping Configuration
To send updated action mapping configuration back to GeViServer:
// 1. Read current configuration
CSAActionMappingTable* mappingTable = /* get from server */;
// 2. Modify mappingTable data structure
// ... add/remove/modify action mappings ...
// 3. Create state query to set action mapping table
CStateQuery* setActionMappingQuery =
new CSQSetActionMappingTable(mappingTable);
// 4. Send updated configuration to server
CStateAnswer* answer = m_APIClient->SendStateQuery(
setActionMappingQuery,
INFINITE
);
// 5. Check if successful
if (answer && answer->m_AnswerKind == sak_OK)
{
// Success!
}
else
{
// Handle error
}
// 6. Clean up
setActionMappingQuery->DeleteObject();
answer->DeleteObject();
Action Mapping Table Structure
The CSAActionMappingTable structure contains:
- Mapping Entries: List of input→output action pairs
- Each Entry Contains:
- Input action definition (action name, parameters)
- List of output actions (multiple actions can be triggered)
- Caption/description
- Enable/disable state
State Queries
Video Input Enumeration Example
// Get first video input
CStateQuery* getFirstVideoInputQuery = new CSQGetFirstVideoInput(
true, // Show only active channels
true // Show only enabled channels
);
CStateAnswer* stateAnswer = m_APIClient->SendStateQuery(
getFirstVideoInputQuery,
INFINITE
);
getFirstVideoInputQuery->DeleteObject();
// Iterate through all video inputs
while (stateAnswer && stateAnswer->m_AnswerKind != sak_Nothing)
{
// Get channel info
CSAVideoInputInfo* videoInputInfo =
reinterpret_cast<CSAVideoInputInfo*>(stateAnswer);
// Access properties:
// - videoInputInfo->m_GlobalID
// - videoInputInfo->m_Name
// - videoInputInfo->m_Description
// - videoInputInfo->m_HasPTZHead
// - videoInputInfo->m_HasVideoSensor
// Get next video input
CStateQuery* getNextVideoInputQuery = new CSQGetNextVideoInput(
true, true,
videoInputInfo->m_GlobalID
);
stateAnswer->DeleteObject();
stateAnswer = m_APIClient->SendStateQuery(
getNextVideoInputQuery,
INFINITE
);
getNextVideoInputQuery->DeleteObject();
}
if (stateAnswer)
stateAnswer->DeleteObject();
Database Queries
Querying Action History
// 1. Create action query session
CDataBaseQuery* geviquery = new CDBQCreateActionQuery(0);
CDataBaseAnswer* dbanswer = m_APIClient->SendDatabaseQuery(
geviquery,
INFINITE
);
geviquery->DeleteObject();
// 2. Extract query handle
CDBAQueryHandle* handle = nullptr;
if (dbanswer->m_AnswerCode == dbac_QueryHandle)
{
handle = reinterpret_cast<CDBAQueryHandle*>(dbanswer);
}
// 3. Optional: Set filters
CDataBaseFilter* filter = new CDBFTypeName(
handle->m_Handle,
"CrossSwitch", // Filter for CrossSwitch actions
dbc_LIKE
);
dbanswer = m_APIClient->SendDatabaseQuery(filter, INFINITE);
filter->DeleteObject();
// 4. Get latest action entry
CDataBaseQuery* getEntry = new CDBQGetLast(handle->m_Handle);
dbanswer = m_APIClient->SendDatabaseQuery(getEntry, INFINITE);
getEntry->DeleteObject();
// 5. Process action entry
if (dbanswer->m_AnswerCode == dbac_ActionEntry)
{
CDBAActionEntry* actionEntry =
reinterpret_cast<CDBAActionEntry*>(dbanswer);
// Access:
// - actionEntry->m_PK (primary key)
// - actionEntry->m_TimeStamp
// - actionEntry->m_Action (CAction object)
__int64 primaryKey = actionEntry->m_PK;
}
dbanswer->DeleteObject();
Available Database Filters
CDBFTypeName- Filter by action type nameCDBFPK_GrtEqu- Primary key >= valueCDBFPK_LowEqu- Primary key <= valueCDBFTimestamp_GrtEqu- Timestamp >= valueCDBFTimestamp_LowEqu- Timestamp <= valueCDBFSender- Filter by sender- Many more in DatabaseQueries.h
Code Examples
Complete Connection Example
#include "GeViAPIClient.h"
// Connection progress callback
void __stdcall ConnectProgressCB(
void* Instance,
TConnectProgress Progress
)
{
// Update UI with connection progress
printf("Connection progress: %d\n", Progress);
}
// Database notification callback
void __stdcall GeViDatabaseNotificationCB(
void* Instance,
TServerNotification Notification,
void* Params
)
{
if (Notification == NFServer_NewMessage)
{
TMessageEntry* messageEntry =
reinterpret_cast<TMessageEntry*>(Params);
int noOfBytesRead = 0;
CGeViMessage* gevimessage = CGeViMessage::ReadBinMessage(
messageEntry->Buffer,
messageEntry->Length,
noOfBytesRead
);
if (gevimessage)
{
// Process received message
printf("Received action: %s\n",
static_cast<CAction*>(gevimessage)->GetActionName());
gevimessage->DeleteObject();
}
}
}
// Main application
int main()
{
// Encode password
char encodedPassword[33];
GeViAPIClient::EncodePassword(
encodedPassword,
"myPlaintextPassword",
33
);
// Create client
GeViAPIClient* apiClient = new GeViAPIClient(
"", // Alias
"192.168.1.100", // GeViServer address
"admin", // Username
encodedPassword, // Encrypted password
"", // Username2 (optional)
"" // Password2 (optional)
);
// Connect to server
TConnectResult result = apiClient->Connect(
ConnectProgressCB,
nullptr // or "this" if in class
);
if (result == connectOk)
{
printf("Connected to GeViServer!\n");
// Register notification callback
apiClient->SetCBNotification(
GeViDatabaseNotificationCB,
nullptr
);
// Send a test action
CGeViMessage* testAction = new CActCustomAction(
123,
"Test message"
);
apiClient->SendMessage(testAction);
testAction->DeleteObject();
// Keep connection alive
while (true)
{
if (!apiClient->SendPing())
{
printf("Connection lost!\n");
break;
}
Sleep(5000); // Wait 5 seconds
}
// Disconnect
apiClient->Disconnect();
}
else
{
printf("Connection failed: %d\n", result);
}
delete apiClient;
return 0;
}
Creating Actions from Strings
// Parse action from ASCII string
std::string buffer("CrossSwitch(101038, 1, 0)");
int bytesRead = 0;
CGeViMessage* gevimessage = CGeViMessage::ReadASCIIMessage(
buffer.c_str(),
buffer.size(),
bytesRead
);
if (gevimessage)
{
// Send parsed action
m_APIClient->SendMessage(gevimessage);
gevimessage->DeleteObject();
}
// Convert action to ASCII string
CGeViMessage* action = new CActCrossSwitch(101038, 1, 0);
char buffer[GEVI_MAXACTIONLENGTH];
int numBytesReceived = 0;
action->WriteASCIIMessage(
buffer,
GEVI_MAXACTIONLENGTH,
numBytesReceived
);
printf("Action: %s\n", buffer); // Output: CrossSwitch(101038, 1, 0)
action->DeleteObject();
Working with GeViScope Actions
GeViScope actions can be sent through GeViSoft:
#include "GscActions.h" // GeViScope action constructors
// Create GeViScope action
CGeViMessage* gscAction = new CActGscAction(
"YourGscServerName", // GeViScope server alias from GeViSet
GscAct_CreateCustomAction(1, L"Hello GeViScope!")
);
m_APIClient->SendMessage(gscAction);
gscAction->DeleteObject();
Key Takeaways for Your API Project
Based on your geutebruck-api project specs, here's how to integrate action mapping:
1. Reading Action Mapping Configuration
For your API endpoint GET /api/v1/gevisoft/action-mappings:
// In your GeViSoft SDK bridge
CStateQuery* query = new CSQGetActionMappingTable();
CStateAnswer* answer = m_APIClient->SendStateQuery(query, INFINITE);
query->DeleteObject();
if (answer && answer->m_AnswerKind == sak_ActionMappingTable)
{
CSAActionMappingTable* mappings =
reinterpret_cast<CSAActionMappingTable*>(answer);
// Convert to JSON for your REST API
json result = convertActionMappingsToJson(mappings);
answer->DeleteObject();
return result;
}
2. Modifying Action Mapping Configuration
For your API endpoint PUT /api/v1/gevisoft/action-mappings:
// Receive JSON from REST API
json actionMappingsJson = /* from HTTP request */;
// Convert JSON to CSAActionMappingTable structure
CSAActionMappingTable* mappings =
convertJsonToActionMappings(actionMappingsJson);
// Send to GeViServer
CStateQuery* setQuery = new CSQSetActionMappingTable(mappings);
CStateAnswer* answer = m_APIClient->SendStateQuery(setQuery, INFINITE);
setQuery->DeleteObject();
if (answer && answer->m_AnswerKind == sak_OK)
{
// Success - action mappings updated
answer->DeleteObject();
return {{"success": true}};
}
else
{
// Error handling
answer->DeleteObject();
return {{"success": false, "error": "Failed to update"}};
}
3. Important Implementation Notes
-
Thread Safety: GeViAPIClient operations are blocking. Use a separate thread or async handling in your REST API to avoid blocking HTTP requests.
-
Connection Management: Maintain a persistent GeViAPIClient connection. Don't connect/disconnect for each API request.
-
Memory Management: Always call
DeleteObject()on objects created by the SDK DLL. -
Error Handling: Check answer codes and types before casting pointers.
-
Data Conversion: You'll need helper functions to convert between SDK structures and JSON for your REST API.
Documentation Locations
Extracted CHM Files
All CHM documentation has been extracted to:
C:\Gevisoft\Documentation\extracted_html\
├── GeViSoft_API_Documentation\ # API class reference (Doxygen)
├── GeViSoft_SDK_Documentation\ # SDK usage guide and tutorials
└── GeViSoft_NET_SDK_API\ # .NET specific API docs
Key Files to Reference
- GeViAPIClient Reference:
GeViSoft_API_Documentation/class_ge_vi_a_p_i_client.html - Action Mapping Guide:
GeViSoft_SDK_Documentation/313Action Mapping.htm - State Queries Guide:
GeViSoft_SDK_Documentation/414StateQueries.htm - Database Queries Guide:
GeViSoft_SDK_Documentation/415DatabaseQueries.htm - Action Messages Guide:
GeViSoft_SDK_Documentation/413_4ActionMessages.htm
Headers to Include
#include "GeViAPIClient.h" // Main API client
#include "Actions.h" // GeViSoft action constructors
#include "GscActions.h" // GeViScope action constructors
#include "StateQueries.h" // State query classes
#include "DatabaseQueries.h" // Database query classes
#include "GeViProcAPI.h" // Low-level API types
Next Steps for Your Project
- Set up GeViAPIClient connection in your C++ SDK bridge
- Implement state query wrappers for GetActionMappingTable and SetActionMappingTable
- Create JSON converters for action mapping structures
- Build REST API endpoints that call your SDK bridge functions
- Test with GeViAPI Test Client to verify action mappings work correctly
Good luck with your Geutebruck API implementation!