Files
Administrator 14893e62a5 feat: Geutebruck GeViScope/GeViSoft Action Mapping System - MVP
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>
2025-12-31 18:10:54 +01:00

337 lines
18 KiB
HTML

<!DOCTYPE html>
<html class="left-layout" data-mc-runtime-file-type="Default">
<!-- saved from url=(0014)about:internet -->
<head>
<meta charset="UTF-8" /><title></title>
<link rel="Stylesheet" href="Skins/Default/Stylesheets/Styles.css" />
<link rel="Stylesheet" href="Skins/Default/Stylesheets/TextEffects.css" />
<script type="text/javascript" src="Resources/Scripts/jquery.min.js">
</script>
<script type="text/javascript" src="Resources/Scripts/plugins.min.js">
</script>
<script type="text/javascript" src="Resources/Scripts/require.min.js">
</script>
<script type="text/javascript" src="Resources/Scripts/require.config.js">
</script>
<script type="text/javascript" src="Resources/Scripts/MadCapAll.js">
</script>
<style>/*&lt;meta /&gt;*/
.print-button
{
-pie-background: url('Skins/Default/Stylesheets/Images/printer.png') no-repeat center center, linear-gradient(#ffffff, #ececec);
}
.expand-all-button
{
-pie-background: url('Skins/Default/Stylesheets/Images/expand.png') no-repeat center center, linear-gradient(#ffffff, #ececec);
}
.remove-highlight-button
{
-pie-background: url('Skins/Default/Stylesheets/Images/highlight.png') no-repeat center center, linear-gradient(#ffffff, #ececec);
}
.separator-button
{
-pie-background: linear-gradient(#ffffff, #ececec);
}
.topic-ratings-button
{
}
.separator-button
{
-pie-background: linear-gradient(#ffffff, #ececec);
}
.edit-user-profile-button
{
-pie-background: url('Skins/Default/Stylesheets/Images/edit-profile.png') no-repeat center center, linear-gradient(#ffffff, #ececec);
}
.filler-button
{
-pie-background: linear-gradient(#ffffff, #ececec);
}
.previous-topic-button
{
-pie-background: url('Skins/Default/Stylesheets/Images/navigate-previous.png') no-repeat center center, linear-gradient(#ffffff, #ececec);
}
.current-topic-index-button
{
}
.next-topic-button
{
-pie-background: url('Skins/Default/Stylesheets/Images/navigate-next.png') no-repeat center center, linear-gradient(#ffffff, #ececec);
}
.login-button
{
-pie-background: url('Skins/Default/Stylesheets/Images/login.png') no-repeat center center, linear-gradient(#ffffff, #ececec);
}
.tabs-nav li
{
-pie-background: linear-gradient(#707070, #555555);
}
.tabs-nav li.tabs-nav-active
{
-pie-background: linear-gradient(#ffffff, #f7f7f7);
}
.login-dialog-header
{
-pie-background: url('Skins/Default/Stylesheets/Images/login-dialog-icon.png') no-repeat 18px center, linear-gradient(#5a5a5a, #4a4a4a);
}
.login-dialog button
{
-pie-background: linear-gradient(#595959, #4a4a4a);
}
#search-field
{
}
.search-filter
{
-pie-background: linear-gradient(#6F6F6F, #555555);
}
.search-submit-wrapper
{
-pie-background: url('Skins/Default/Stylesheets/Images/magnifying_glass.png') no-repeat center center, linear-gradient(#626262, #373737);
}
</style>
</head>
<body>
<div id="DEBUG_Log">
<div class="MCDebugLogHeader">
Log Console</div>
<div class="MCDebugLogBody">
</div>
<div class="MCDebugLogFooter">
</div>
</div>
<div id="header"><a href="index.htm"><h1 class="logo"></h1></a>
<div class="search-bar needs-pie">
<input id="search-field" class="needs-pie" type="text" placeholder="Search" />
<div class="search-filter-wrapper">
<div class="search-filter"><span>All Files</span>
<div class="search-filter-content">
<ul>
<li>All Files</li>
</ul>
</div>
</div>
</div>
<div class="search-submit-wrapper" dir="ltr">
<div class="search-submit" title="Search">
</div>
</div>
</div>
</div>
<div id="body">
<div id="navigation">
<div class="tabs">
<ul class="tabs-nav clearfix image-then-text tab-icon">
<li id="TocTab" class="needs-pie tabs-nav-active">
<div><span class="tabs-nav-icon active" title="Contents"></span><span class="tabs-nav-text">Contents</span>
</div>
</li>
</ul>
<div class="tabs-panels">
<div class="tabs-panel tabs-panel-active">
<div id="toc" class="tabs-panel-content needs-pie">
<!--
<ul class="tree">
<li class="tree-node tree-node-inner tree-node-expanded">
<div>
<span>Book A</span>
</div>
<ul class="tree inner">
<li class="tree-node tree-node-inner tree-node-expanded">
<div>
<span class="label">Book A-A</span>
</div>
<ul class="tree inner">
<li class="tree-node tree-node-leaf">
<div>
<span><a href="#TopicA.htm">Topic A-A</a></span>
</div>
</li>
<li class="tree-node tree-node-leaf">
<div>
<span class="new-indicator"></span>
<span><a href="#TopicB.htm">Topic A-B</a></span>
</div>
</li>
</ul>
</li>
<li class="tree-node tree-node-inner">
<div>
<span class="tree-node-leaf">Topic B</span>
</div>
</li>
</ul>
</li>
<li class="tree-node tree-node-inner tree-node-collapsed">
<div>
<span>Book B</span>
</div>
<ul class="tree inner">
<li class="tree-node tree-node-leaf">
<div>
<span>Topic B-A</span>
</div>
</li>
<li class="tree-node tree-node-leaf">
<div>
<span>Topic B-B</span>
</div>
</li>
</ul>
</li>
</ul>
-->
</div>
</div>
</div>
</div>
</div>
<div id="navigationResizeBar">
<div id="show-hide-navigation" class="needs-pie" dir="ltr">
</div>
</div>
<div id="contentBody" class="needs-pie">
<div class="buttons">
<div class="button-group-container-left">
<div class="button-group">
<button class="button needs-pie print-button" title="Print">
</button>
<button class="button needs-pie expand-all-button" data-state1-class="expand-all-button" data-state2-class="collapse-all-button" data-state2-title="Collapse all" title="Expand all" data-state1-title="Expand all">
</button>
<button class="button needs-pie remove-highlight-button" title="Remove Highlights">
</button>
</div>
<div class="button-group">
<div class="star-buttons loading feedback-topic-required">
<div class="button star-button topic-ratings-empty-button" data-state1-class="topic-ratings-empty-button" data-state2-class="topic-ratings-button" title="Click a star to rate this topic" data-state1-title="Click a star to rate this topic" data-state2-title="Click a star to rate this topic">
</div>
<div class="button star-button topic-ratings-empty-button" data-state1-class="topic-ratings-empty-button" data-state2-class="topic-ratings-button" title="Click a star to rate this topic" data-state1-title="Click a star to rate this topic" data-state2-title="Click a star to rate this topic">
</div>
<div class="button star-button topic-ratings-empty-button" data-state1-class="topic-ratings-empty-button" data-state2-class="topic-ratings-button" title="Click a star to rate this topic" data-state1-title="Click a star to rate this topic" data-state2-title="Click a star to rate this topic">
</div>
<div class="button star-button topic-ratings-empty-button" data-state1-class="topic-ratings-empty-button" data-state2-class="topic-ratings-button" title="Click a star to rate this topic" data-state1-title="Click a star to rate this topic" data-state2-title="Click a star to rate this topic">
</div>
<div class="button star-button topic-ratings-empty-button" data-state1-class="topic-ratings-empty-button" data-state2-class="topic-ratings-button" title="Click a star to rate this topic" data-state1-title="Click a star to rate this topic" data-state2-title="Click a star to rate this topic">
</div>
</div>
</div>
<div class="button-group">
<button class="button feedback-required login-button" data-state1-class="login-button" data-state2-class="edit-user-profile-button" data-state2-title="Edit user profile" title="Login" data-state1-title="Login">
</button>
</div>
</div>
<div class="button-group-container-right">
<div class="button-group">
<button class="button needs-pie previous-topic-button" title="Navigate previous">
</button>
<div class="button current-topic-index-button disabled"><span class="sequence-index"></span> of <span class="sequence-total"></span></div>
<button class="button needs-pie next-topic-button" title="Navigate next">
</button>
</div>
</div>
</div>
<div id="contentBodyInner">
<!-- frameBorder="0" is for IE 8 and below --><iframe id="topic" class="content" name="topic" frameBorder="0"></iframe><iframe id="pulse" class="content" name="pulse" frameBorder="0"></iframe>
<div id="searchPane">
<h1 id="results-heading">Your search for <span class="query"></span> returned <span class="total-results"></span> result(s).</h1>
<!--
<ul id="resultList">
<li>
<h3 class="title"><a href="#TopicA.htm">Topic A</a></h3>
<span class="ratingStarsContainer">
<div class="ratingStar ratingStarFilled">&#160;</div>
<div class="ratingStar ratingStarFilled">&#160;</div>
<div class="ratingStar ratingStarFilled">&#160;</div>
<div class="ratingStar ratingStarFilled">&#160;</div>
<div class="ratingStar ratingStarEmpty">&#160;</div>
17 reviews
</span>
<div class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a dictum dolor. Suspendisse potenti. Donec commodo, mi et pulvinar lobortis, velit magna sodales lectus, sit amet interdum magna urna eget leo. Pellentesque risus eros, vehicula non tempus at, bibendum in neque. In mollis malesuada facilisis.</div>
<div class="url"><cite>TopicA.htm</cite></div>
</li>
<li>
<h3 class="title"><a href="#TopicB.htm">Topic B</a></h3>
<span class="ratingStarsContainer">
<div class="ratingStar ratingStarFilled">&#160;</div>
<div class="ratingStar ratingStarFilled">&#160;</div>
<div class="ratingStar ratingStarFilled">&#160;</div>
<div class="ratingStar ratingStarEmpty">&#160;</div>
<div class="ratingStar ratingStarEmpty">&#160;</div>
5 reviews
</span>
<div class="description">Duis nec massa est, id hendrerit neque. Sed ornare adipiscing turpis eu luctus. Phasellus eu viverra lectus. Nunc purus risus, scelerisque non porttitor vitae, fringilla luctus augue.</div>
<div class="url"><cite>TopicB.htm</cite></div>
</li>
<li>
<h3 class="title"><a href="#TopicA.htm">Topic A</a></h3>
<div class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a dictum dolor. Suspendisse potenti. Donec commodo, mi et pulvinar lobortis, velit magna sodales lectus, sit amet interdum magna urna eget leo. Pellentesque risus eros, vehicula non tempus at, bibendum in neque. In mollis malesuada facilisis.</div>
<div class="url"><cite>TopicA.htm</cite></div>
</li>
</ul>
-->
</div>
</div>
</div>
</div>
<div class="login-dialog needs-pie">
<div class="login-dialog-header needs-pie">
Create Profile
</div>
<div class="login-dialog-content needs-pie">
<div class="profile-item-wrapper clearfix">
<div class="label-wrapper">
<label>Username *</label>
</div>
<div class="input-wrapper">
<input class="needs-pie" type="text" name="Username" data-required="true" />
</div>
</div>
<div class="profile-item-wrapper clearfix">
<div class="label-wrapper">
<label>Email Address *</label>
</div>
<div class="input-wrapper">
<input class="needs-pie" type="text" name="EmailAddress" data-required="true" />
</div>
</div>
<div class="profile-item-wrapper email-notifications-wrapper">
<div class="label-wrapper">
Email Notifications
</div>
<div class="email-notifications-group needs-pie">
I want to receive an email when...
<div><label><input type="checkbox" name="CommentReplyNotification" />a reply is left to one of my comments</label></div><div><label><input type="checkbox" name="CommentSameTopicNotification" />a comment is left on a topic that I commented on</label></div><div><label><input type="checkbox" name="CommentSameHelpSystemNotification" />a comment is left on any topic in the Help system</label></div></div>
</div>
<div class="login-dialog-buttons">
<button class="submit-button needs-pie" type="submit">Submit</button>
<button class="cancel-button needs-pie">Cancel</button>
</div>
<div class="status-message-box"><span class="message verification-email-sent-message">An email has been sent to verify your new profile.</span><span class="message required-fields-missing-message">Please fill out all required fields before submitting your information.</span>
</div>
</div>
</div>
</body>
</html>