feat: GeViScope SDK integration with C# Bridge and Flutter app
- Add GeViScope Bridge (C# .NET 8.0) on port 7720 - Full SDK wrapper for camera control, PTZ, actions/events - 17 REST API endpoints for GeViScope server interaction - Support for MCS (Media Channel Simulator) with 16 test channels - Real-time action/event streaming via PLC callbacks - Add GeViServer Bridge (C# .NET 8.0) on port 7710 - Integration with GeViSoft orchestration layer - Input/output control and event management - Update Python API with new routers - /api/geviscope/* - Proxy to GeViScope Bridge - /api/geviserver/* - Proxy to GeViServer Bridge - /api/excel/* - Excel import functionality - Add Flutter app GeViScope integration - GeViScopeRemoteDataSource with 17 API methods - GeViScopeBloc for state management - GeViScopeScreen with PTZ controls - App drawer navigation to GeViScope - Add SDK documentation (extracted from PDFs) - GeViScope SDK docs (7 parts + action reference) - GeViSoft SDK docs (12 chunks) - Add .mcp.json for Claude Code MCP server config Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
232
geviserver-bridge/GeViServerBridge/Program.cs
Normal file
232
geviserver-bridge/GeViServerBridge/Program.cs
Normal file
@@ -0,0 +1,232 @@
|
||||
using GEUTEBRUECK.GeViSoftSDKNET.ActionsWrapper;
|
||||
using GEUTEBRUECK.GeViSoftSDKNET.ActionsWrapper.ActionDispatcher;
|
||||
using GEUTEBRUECK.GeViSoftSDKNET.ActionsWrapper.SystemActions;
|
||||
using GEUTEBRUECK.GeViSoftSDKNET.ActionsWrapper.SwitchControlActions;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
// GeViServer connection state
|
||||
GeViDatabase? database = null;
|
||||
string? currentAddress = null;
|
||||
string? currentUsername = null;
|
||||
List<string> receivedMessages = new List<string>();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Event handler for received messages
|
||||
void OnDatabaseNotification(object? sender, GeViSoftDatabaseNotificationEventArgs e)
|
||||
{
|
||||
var msg = $"[{DateTime.Now:HH:mm:ss}] Notification: {e.ServerNotificationType}";
|
||||
Console.WriteLine(msg);
|
||||
receivedMessages.Add(msg);
|
||||
}
|
||||
|
||||
void OnReceivedCustomAction(object? sender, GeViAct_CustomActionEventArgs e)
|
||||
{
|
||||
var msg = $"[{DateTime.Now:HH:mm:ss}] CustomAction({e.aCustomInt}, \"{e.aCustomText}\")";
|
||||
Console.WriteLine(msg);
|
||||
receivedMessages.Add(msg);
|
||||
}
|
||||
|
||||
void OnReceivedCrossSwitch(object? sender, GeViAct_CrossSwitchEventArgs e)
|
||||
{
|
||||
var msg = $"[{DateTime.Now:HH:mm:ss}] CrossSwitch({e.aVideoInput}, {e.aVideoOutput}, {e.aSwitchMode})";
|
||||
Console.WriteLine(msg);
|
||||
receivedMessages.Add(msg);
|
||||
}
|
||||
|
||||
// Connection endpoint
|
||||
app.MapPost("/connect", (ConnectRequest request) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
// Create and configure database connection
|
||||
database = new GeViDatabase();
|
||||
database.Create(
|
||||
request.Address,
|
||||
request.Username,
|
||||
request.Password
|
||||
);
|
||||
|
||||
// Register event handlers BEFORE connecting
|
||||
database.DatabaseNotification += OnDatabaseNotification;
|
||||
database.ReceivedCustomAction += OnReceivedCustomAction;
|
||||
database.ReceivedCrossSwitch += OnReceivedCrossSwitch;
|
||||
database.RegisterCallback();
|
||||
|
||||
// Connect to GeViServer
|
||||
var connectResult = database.Connect();
|
||||
|
||||
if (connectResult == GeViConnectResult.connectOk)
|
||||
{
|
||||
currentAddress = request.Address;
|
||||
currentUsername = request.Username;
|
||||
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] Connected to GeViServer at {request.Address}");
|
||||
|
||||
return Results.Ok(new
|
||||
{
|
||||
success = true,
|
||||
message = "Connected to GeViServer",
|
||||
address = request.Address,
|
||||
username = request.Username,
|
||||
connected_at = DateTime.UtcNow
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
return Results.BadRequest(new
|
||||
{
|
||||
error = "Connection failed",
|
||||
message = connectResult.ToString()
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Results.BadRequest(new
|
||||
{
|
||||
error = "Internal Server Error",
|
||||
message = ex.Message,
|
||||
stack_trace = ex.StackTrace
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Disconnect endpoint
|
||||
app.MapPost("/disconnect", () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (database != null)
|
||||
{
|
||||
database.Disconnect();
|
||||
database.Dispose();
|
||||
database = null;
|
||||
}
|
||||
|
||||
currentAddress = null;
|
||||
currentUsername = null;
|
||||
|
||||
return Results.Ok(new
|
||||
{
|
||||
success = true,
|
||||
message = "Disconnected successfully"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Results.BadRequest(new
|
||||
{
|
||||
error = "Internal Server Error",
|
||||
message = ex.Message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Status endpoint
|
||||
app.MapGet("/status", () =>
|
||||
{
|
||||
return Results.Ok(new
|
||||
{
|
||||
is_connected = database != null,
|
||||
address = currentAddress,
|
||||
username = currentUsername
|
||||
});
|
||||
});
|
||||
|
||||
// Ping endpoint
|
||||
app.MapPost("/ping", () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (database == null)
|
||||
{
|
||||
return Results.BadRequest(new { error = "Not connected" });
|
||||
}
|
||||
|
||||
var result = database.SendPing();
|
||||
|
||||
return Results.Ok(new
|
||||
{
|
||||
success = result,
|
||||
message = result ? "Ping successful" : "Ping failed"
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Results.BadRequest(new
|
||||
{
|
||||
error = "Internal Server Error",
|
||||
message = ex.Message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Send message endpoint
|
||||
app.MapPost("/send-message", (SendMessageRequest request) =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (database == null)
|
||||
{
|
||||
return Results.BadRequest(new { error = "Not connected" });
|
||||
}
|
||||
|
||||
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] SENDING: {request.Message}");
|
||||
|
||||
// Send action message
|
||||
database.SendMessage(request.Message);
|
||||
|
||||
var logMsg = $"[{DateTime.Now:HH:mm:ss}] SENT: {request.Message}";
|
||||
receivedMessages.Add(logMsg);
|
||||
|
||||
return Results.Ok(new
|
||||
{
|
||||
success = true,
|
||||
message = "Message sent successfully",
|
||||
sent_message = request.Message
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] ERROR: {ex.Message}");
|
||||
return Results.BadRequest(new
|
||||
{
|
||||
error = "Internal Server Error",
|
||||
message = ex.Message
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Get message log endpoint
|
||||
app.MapGet("/messages", () =>
|
||||
{
|
||||
return Results.Ok(new
|
||||
{
|
||||
count = receivedMessages.Count,
|
||||
messages = receivedMessages.TakeLast(50).ToList()
|
||||
});
|
||||
});
|
||||
|
||||
// Clear message log endpoint
|
||||
app.MapPost("/messages/clear", () =>
|
||||
{
|
||||
receivedMessages.Clear();
|
||||
return Results.Ok(new { message = "Message log cleared" });
|
||||
});
|
||||
|
||||
Console.WriteLine("========================================");
|
||||
Console.WriteLine("GeViServer Bridge starting on port 7710");
|
||||
Console.WriteLine("========================================");
|
||||
|
||||
// Run on port 7710 (avoiding conflict with GeViServer DevicePort 7701)
|
||||
app.Run("http://localhost:7710");
|
||||
|
||||
// Request models
|
||||
record ConnectRequest(
|
||||
string Address,
|
||||
string Username,
|
||||
string Password
|
||||
);
|
||||
|
||||
record SendMessageRequest(string Message);
|
||||
Reference in New Issue
Block a user