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>
This commit is contained in:
Administrator
2025-12-31 18:10:54 +01:00
commit 14893e62a5
4189 changed files with 1395076 additions and 0 deletions

View File

@@ -0,0 +1,229 @@
import 'dart:convert';
import 'package:hive/hive.dart';
import '../../domain/entities/action_mapping.dart';
import 'action_mapping_model.dart';
import 'action_output.dart';
part 'action_mapping_hive_model.g.dart';
/// Hive model for local storage of action mappings with sync tracking
@HiveType(typeId: 1)
class ActionMappingHiveModel extends HiveObject {
@HiveField(0)
final String id;
@HiveField(1)
final String name;
@HiveField(2)
final String? description;
@HiveField(3)
final String inputAction;
@HiveField(4)
final List<String> outputActions; // Deprecated - kept for compatibility
@HiveField(5)
final String? geviscopeInstanceScope;
@HiveField(6)
final bool enabled;
@HiveField(7)
final int executionCount;
@HiveField(8)
final DateTime? lastExecuted;
@HiveField(9)
final DateTime createdAt;
@HiveField(10)
final DateTime updatedAt;
@HiveField(11)
final String createdBy;
// Sync tracking fields
@HiveField(12)
final bool isDirty;
@HiveField(13)
final DateTime lastModified;
@HiveField(14)
final String? syncOperation; // 'create', 'update', 'delete'
// New fields for parameters (stored as JSON strings)
@HiveField(15)
final String? inputParametersJson; // JSON-encoded Map<String, dynamic>
@HiveField(16)
final String? outputActionsJson; // JSON-encoded List<ActionOutput>
ActionMappingHiveModel({
required this.id,
required this.name,
this.description,
required this.inputAction,
required this.outputActions,
this.geviscopeInstanceScope,
this.enabled = true,
this.executionCount = 0,
this.lastExecuted,
required this.createdAt,
required this.updatedAt,
required this.createdBy,
this.isDirty = false,
required this.lastModified,
this.syncOperation,
this.inputParametersJson,
this.outputActionsJson,
});
/// Create Hive model from domain entity
factory ActionMappingHiveModel.fromEntity(
ActionMapping mapping, {
bool isDirty = false,
String? syncOperation,
}) {
return ActionMappingHiveModel(
id: mapping.id,
name: mapping.name,
description: mapping.description,
inputAction: mapping.inputAction,
outputActions: mapping.outputActions.map((o) => o.action).toList(), // For compatibility
geviscopeInstanceScope: mapping.geviscopeInstanceScope,
enabled: mapping.enabled,
executionCount: mapping.executionCount,
lastExecuted: mapping.lastExecuted,
createdAt: mapping.createdAt,
updatedAt: mapping.updatedAt,
createdBy: mapping.createdBy,
isDirty: isDirty,
lastModified: DateTime.now(),
syncOperation: syncOperation,
inputParametersJson: jsonEncode(mapping.inputParameters),
outputActionsJson: jsonEncode(mapping.outputActions.map((o) => o.toJson()).toList()),
);
}
/// Create Hive model from API model
factory ActionMappingHiveModel.fromActionMappingModel(
ActionMappingModel model, {
bool isDirty = false,
String? syncOperation,
}) {
return ActionMappingHiveModel(
id: model.id,
name: model.name,
description: model.description,
inputAction: model.inputAction,
outputActions: model.outputActions.map((o) => o.action).toList(), // For compatibility
geviscopeInstanceScope: model.geviscopeInstanceScope,
enabled: model.enabled,
executionCount: model.executionCount,
lastExecuted: model.lastExecuted,
createdAt: model.createdAt,
updatedAt: model.updatedAt,
createdBy: model.createdBy,
isDirty: isDirty,
lastModified: DateTime.now(),
syncOperation: syncOperation,
inputParametersJson: jsonEncode(model.inputParameters),
outputActionsJson: jsonEncode(model.outputActions.map((o) => o.toJson()).toList()),
);
}
/// Convert to API model
ActionMappingModel toActionMappingModel() {
// Decode parameters from JSON
Map<String, dynamic> inputParams = {};
List<ActionOutput> outputs = [];
if (inputParametersJson != null && inputParametersJson!.isNotEmpty) {
try {
inputParams = Map<String, dynamic>.from(jsonDecode(inputParametersJson!));
} catch (e) {
print('Error decoding inputParametersJson: $e');
}
}
if (outputActionsJson != null && outputActionsJson!.isNotEmpty) {
try {
final decoded = jsonDecode(outputActionsJson!) as List<dynamic>;
outputs = decoded.map((e) => ActionOutput.fromJson(e as Map<String, dynamic>)).toList();
} catch (e) {
print('Error decoding outputActionsJson: $e');
// Fallback to legacy outputActions
outputs = outputActions.map((action) => ActionOutput(action: action, parameters: {})).toList();
}
} else {
// Fallback to legacy outputActions
outputs = outputActions.map((action) => ActionOutput(action: action, parameters: {})).toList();
}
return ActionMappingModel(
id: id,
name: name,
description: description,
inputAction: inputAction,
inputParameters: inputParams,
outputActions: outputs,
geviscopeInstanceScope: geviscopeInstanceScope,
enabled: enabled,
executionCount: executionCount,
lastExecuted: lastExecuted,
createdAt: createdAt,
updatedAt: updatedAt,
createdBy: createdBy,
);
}
/// Convert to domain entity
ActionMapping toEntity() {
return toActionMappingModel().toEntity();
}
/// Create a copy with modified fields
ActionMappingHiveModel copyWith({
String? id,
String? name,
String? description,
String? inputAction,
List<String>? outputActions,
String? geviscopeInstanceScope,
bool? enabled,
int? executionCount,
DateTime? lastExecuted,
DateTime? createdAt,
DateTime? updatedAt,
String? createdBy,
bool? isDirty,
DateTime? lastModified,
String? syncOperation,
String? inputParametersJson,
String? outputActionsJson,
}) {
return ActionMappingHiveModel(
id: id ?? this.id,
name: name ?? this.name,
description: description ?? this.description,
inputAction: inputAction ?? this.inputAction,
outputActions: outputActions ?? this.outputActions,
geviscopeInstanceScope: geviscopeInstanceScope ?? this.geviscopeInstanceScope,
enabled: enabled ?? this.enabled,
executionCount: executionCount ?? this.executionCount,
lastExecuted: lastExecuted ?? this.lastExecuted,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
createdBy: createdBy ?? this.createdBy,
isDirty: isDirty ?? this.isDirty,
lastModified: lastModified ?? this.lastModified,
syncOperation: syncOperation ?? this.syncOperation,
inputParametersJson: inputParametersJson ?? this.inputParametersJson,
outputActionsJson: outputActionsJson ?? this.outputActionsJson,
);
}
}

View File

@@ -0,0 +1,90 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'action_mapping_hive_model.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class ActionMappingHiveModelAdapter
extends TypeAdapter<ActionMappingHiveModel> {
@override
final int typeId = 1;
@override
ActionMappingHiveModel read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return ActionMappingHiveModel(
id: fields[0] as String,
name: fields[1] as String,
description: fields[2] as String?,
inputAction: fields[3] as String,
outputActions: (fields[4] as List).cast<String>(),
geviscopeInstanceScope: fields[5] as String?,
enabled: fields[6] as bool,
executionCount: fields[7] as int,
lastExecuted: fields[8] as DateTime?,
createdAt: fields[9] as DateTime,
updatedAt: fields[10] as DateTime,
createdBy: fields[11] as String,
isDirty: fields[12] as bool,
lastModified: fields[13] as DateTime,
syncOperation: fields[14] as String?,
inputParametersJson: fields[15] as String?,
outputActionsJson: fields[16] as String?,
);
}
@override
void write(BinaryWriter writer, ActionMappingHiveModel obj) {
writer
..writeByte(17)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.name)
..writeByte(2)
..write(obj.description)
..writeByte(3)
..write(obj.inputAction)
..writeByte(4)
..write(obj.outputActions)
..writeByte(5)
..write(obj.geviscopeInstanceScope)
..writeByte(6)
..write(obj.enabled)
..writeByte(7)
..write(obj.executionCount)
..writeByte(8)
..write(obj.lastExecuted)
..writeByte(9)
..write(obj.createdAt)
..writeByte(10)
..write(obj.updatedAt)
..writeByte(11)
..write(obj.createdBy)
..writeByte(12)
..write(obj.isDirty)
..writeByte(13)
..write(obj.lastModified)
..writeByte(14)
..write(obj.syncOperation)
..writeByte(15)
..write(obj.inputParametersJson)
..writeByte(16)
..write(obj.outputActionsJson);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ActionMappingHiveModelAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -0,0 +1,145 @@
import '../../domain/entities/action_mapping.dart';
import 'action_output.dart';
/// Data model for action mapping with JSON serialization
/// Handles conversion between API (snake_case) and domain entities
class ActionMappingModel {
final String id;
final String name;
final String? description;
final String inputAction;
final Map<String, dynamic> inputParameters;
final List<ActionOutput> outputActions;
final String? geviscopeInstanceScope;
final bool enabled;
final int executionCount;
final DateTime? lastExecuted;
final DateTime createdAt;
final DateTime updatedAt;
final String createdBy;
const ActionMappingModel({
required this.id,
required this.name,
this.description,
required this.inputAction,
this.inputParameters = const {},
required this.outputActions,
this.geviscopeInstanceScope,
this.enabled = true,
this.executionCount = 0,
this.lastExecuted,
required this.createdAt,
required this.updatedAt,
required this.createdBy,
});
/// Create model from JSON (API response with snake_case keys)
factory ActionMappingModel.fromJson(Map<String, dynamic> json) {
// Convert ID from int to string if needed
final id = json['id'].toString();
// Extract input action and parameters from array of objects
final inputActions = json['input_actions'] as List<dynamic>?;
String inputAction;
Map<String, dynamic> inputParameters;
if (inputActions != null && inputActions.isNotEmpty) {
final firstInput = inputActions[0] as Map<String, dynamic>;
inputAction = firstInput['action'] as String;
inputParameters = Map<String, dynamic>.from(firstInput['parameters'] as Map? ?? {});
} else {
inputAction = json['name'] as String; // Fallback to name
inputParameters = {};
}
// Extract output actions and parameters from array of objects
final outputActionsRaw = json['output_actions'] as List<dynamic>?;
final outputActions = outputActionsRaw != null
? outputActionsRaw.map((e) => ActionOutput.fromJson(e as Map<String, dynamic>)).toList()
: <ActionOutput>[];
return ActionMappingModel(
id: id,
name: json['name'] as String,
description: json['description'] as String?,
inputAction: inputAction,
inputParameters: inputParameters,
outputActions: outputActions,
geviscopeInstanceScope: json['geviscope_instance_scope'] as String?,
enabled: json['enabled'] as bool? ?? true,
executionCount: json['execution_count'] as int? ?? 0,
lastExecuted: json['last_executed'] != null
? DateTime.parse(json['last_executed'] as String)
: null,
createdAt: json['created_at'] != null
? DateTime.parse(json['created_at'] as String)
: DateTime.now(),
updatedAt: json['updated_at'] != null
? DateTime.parse(json['updated_at'] as String)
: DateTime.now(),
createdBy: json['created_by'] as String? ?? 'system',
);
}
/// Convert model to JSON (for API requests with snake_case keys)
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
if (description != null) 'description': description,
// API expects input_actions as array of objects with parameters
'input_actions': [
{'action': inputAction, 'parameters': inputParameters}
],
// API expects output_actions as array of objects with parameters
'output_actions': outputActions.map((output) => output.toJson()).toList(),
if (geviscopeInstanceScope != null)
'geviscope_instance_scope': geviscopeInstanceScope,
'enabled': enabled,
'execution_count': executionCount,
if (lastExecuted != null) 'last_executed': lastExecuted!.toIso8601String(),
'created_at': createdAt.toIso8601String(),
'updated_at': updatedAt.toIso8601String(),
'created_by': createdBy,
};
}
/// Convert to domain entity
ActionMapping toEntity() {
return ActionMapping(
id: id,
name: name,
description: description,
inputAction: inputAction,
inputParameters: inputParameters,
outputActions: outputActions,
geviscopeInstanceScope: geviscopeInstanceScope,
enabled: enabled,
executionCount: executionCount,
lastExecuted: lastExecuted,
createdAt: createdAt,
updatedAt: updatedAt,
createdBy: createdBy,
);
}
/// Create model from domain entity
factory ActionMappingModel.fromEntity(ActionMapping mapping) {
return ActionMappingModel(
id: mapping.id,
name: mapping.name,
description: mapping.description,
inputAction: mapping.inputAction,
inputParameters: mapping.inputParameters,
outputActions: mapping.outputActions,
geviscopeInstanceScope: mapping.geviscopeInstanceScope,
enabled: mapping.enabled,
executionCount: mapping.executionCount,
lastExecuted: mapping.lastExecuted,
createdAt: mapping.createdAt,
updatedAt: mapping.updatedAt,
createdBy: mapping.createdBy,
);
}
}

View File

@@ -0,0 +1,56 @@
/// Represents an output action with its parameters
class ActionOutput {
final String action;
final Map<String, dynamic> parameters;
const ActionOutput({
required this.action,
required this.parameters,
});
/// Create from JSON
factory ActionOutput.fromJson(Map<String, dynamic> json) {
return ActionOutput(
action: json['action'] as String,
parameters: Map<String, dynamic>.from(json['parameters'] as Map? ?? {}),
);
}
/// Convert to JSON
Map<String, dynamic> toJson() {
return {
'action': action,
'parameters': parameters,
};
}
/// Create a copy with updated values
ActionOutput copyWith({
String? action,
Map<String, dynamic>? parameters,
}) {
return ActionOutput(
action: action ?? this.action,
parameters: parameters ?? this.parameters,
);
}
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is ActionOutput &&
other.action == action &&
_mapsEqual(other.parameters, parameters);
}
@override
int get hashCode => action.hashCode ^ parameters.hashCode;
bool _mapsEqual(Map<String, dynamic> a, Map<String, dynamic> b) {
if (a.length != b.length) return false;
for (var key in a.keys) {
if (!b.containsKey(key) || a[key] != b[key]) return false;
}
return true;
}
}

View File

@@ -0,0 +1,174 @@
import 'package:equatable/equatable.dart';
/// Model representing an action template from the API
/// Used for dynamic form generation when selecting action types
class ActionTemplate extends Equatable {
final String actionName;
final List<String> parameters;
final String description;
final String category;
final bool requiredCaption;
final bool supportsDelay;
final Map<String, String>? parameterTypes;
const ActionTemplate({
required this.actionName,
required this.parameters,
required this.description,
required this.category,
this.requiredCaption = true,
this.supportsDelay = true,
this.parameterTypes,
});
factory ActionTemplate.fromJson(Map<String, dynamic> json) {
return ActionTemplate(
actionName: json['action_name'] as String,
parameters: (json['parameters'] as List<dynamic>)
.map((e) => e.toString())
.toList(),
description: json['description'] as String,
category: json['category'] as String,
requiredCaption: json['required_caption'] as bool? ?? true,
supportsDelay: json['supports_delay'] as bool? ?? true,
parameterTypes: json['parameter_types'] != null
? Map<String, String>.from(json['parameter_types'] as Map)
: null,
);
}
Map<String, dynamic> toJson() {
return {
'action_name': actionName,
'parameters': parameters,
'description': description,
'category': category,
'required_caption': requiredCaption,
'supports_delay': supportsDelay,
if (parameterTypes != null) 'parameter_types': parameterTypes,
};
}
@override
List<Object?> get props => [
actionName,
parameters,
description,
category,
requiredCaption,
supportsDelay,
parameterTypes,
];
}
/// Model representing a server (G-Core or GeViScope)
class ServerInfo extends Equatable {
final String id;
final String alias;
final bool enabled;
const ServerInfo({
required this.id,
required this.alias,
required this.enabled,
});
factory ServerInfo.fromJson(Map<String, dynamic> json) {
return ServerInfo(
id: json['id'].toString(),
alias: json['alias'] as String,
enabled: json['enabled'] as bool,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'alias': alias,
'enabled': enabled,
};
}
@override
List<Object?> get props => [id, alias, enabled];
}
/// Model for servers information
class ServersInfo extends Equatable {
final List<ServerInfo> gcoreServers;
final List<ServerInfo> gscServers;
const ServersInfo({
required this.gcoreServers,
required this.gscServers,
});
factory ServersInfo.fromJson(Map<String, dynamic> json) {
return ServersInfo(
gcoreServers: (json['gcore_servers'] as List<dynamic>?)
?.map((e) => ServerInfo.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
gscServers: (json['gsc_servers'] as List<dynamic>?)
?.map((e) => ServerInfo.fromJson(e as Map<String, dynamic>))
.toList() ??
[],
);
}
@override
List<Object?> get props => [gcoreServers, gscServers];
}
/// Model for action categories response
class ActionCategoriesResponse extends Equatable {
final Map<String, List<String>> categories;
final int totalCategories;
final int totalActions;
final ServersInfo servers;
final List<String> gscSpecificCategories;
const ActionCategoriesResponse({
required this.categories,
required this.totalCategories,
required this.totalActions,
required this.servers,
this.gscSpecificCategories = const [],
});
factory ActionCategoriesResponse.fromJson(Map<String, dynamic> json) {
final categoriesMap = json['categories'] as Map<String, dynamic>;
final categories = categoriesMap.map(
(key, value) => MapEntry(
key,
(value as List<dynamic>).map((e) => e.toString()).toList(),
),
);
return ActionCategoriesResponse(
categories: categories,
totalCategories: json['total_categories'] as int,
totalActions: json['total_actions'] as int,
servers: ServersInfo.fromJson(json['servers'] as Map<String, dynamic>? ?? {}),
gscSpecificCategories: (json['gsc_specific_categories'] as List<dynamic>?)
?.map((e) => e.toString())
.toList() ??
[],
);
}
/// Get all action names sorted by category
List<String> getActionsForCategory(String category) {
return categories[category] ?? [];
}
/// Get list of all category names sorted
List<String> get categoryNames {
final names = categories.keys.toList();
names.sort();
return names;
}
@override
List<Object?> get props => [categories, totalCategories, totalActions, servers, gscSpecificCategories];
}

View File

@@ -0,0 +1,43 @@
import '../../domain/entities/user.dart';
class AuthResponseModel {
final String accessToken;
final String refreshToken;
final String username;
final String role;
AuthResponseModel({
required this.accessToken,
required this.refreshToken,
required this.username,
required this.role,
});
factory AuthResponseModel.fromJson(Map<String, dynamic> json) {
final user = json['user'] as Map<String, dynamic>;
return AuthResponseModel(
accessToken: json['access_token'] as String,
refreshToken: json['refresh_token'] as String,
username: user['username'] as String,
role: user['role'] as String,
);
}
Map<String, dynamic> toJson() {
return {
'access_token': accessToken,
'refresh_token': refreshToken,
'username': username,
'role': role,
};
}
User toEntity() {
return User(
username: username,
role: role,
accessToken: accessToken,
refreshToken: refreshToken,
);
}
}

View File

@@ -0,0 +1,154 @@
import 'package:hive/hive.dart';
import '../../domain/entities/server.dart';
import 'server_model.dart';
part 'server_hive_model.g.dart';
@HiveType(typeId: 0)
class ServerHiveModel extends HiveObject {
@HiveField(0)
final String id;
@HiveField(1)
final String alias;
@HiveField(2)
final String host;
@HiveField(3)
final String user;
@HiveField(4)
final String password;
@HiveField(5)
final bool enabled;
@HiveField(6)
final bool deactivateEcho;
@HiveField(7)
final bool deactivateLiveCheck;
@HiveField(8)
final String serverType; // 'gcore' or 'geviscope'
@HiveField(9)
final bool isDirty; // Has unsaved changes
@HiveField(10)
final DateTime lastModified;
@HiveField(11)
final String? syncOperation; // 'create', 'update', 'delete', null
ServerHiveModel({
required this.id,
required this.alias,
required this.host,
required this.user,
required this.password,
required this.enabled,
required this.deactivateEcho,
required this.deactivateLiveCheck,
required this.serverType,
this.isDirty = false,
DateTime? lastModified,
this.syncOperation,
}) : lastModified = lastModified ?? DateTime.now();
// Convert from domain entity to Hive model
factory ServerHiveModel.fromEntity(Server server, {bool isDirty = false, String? syncOperation}) {
return ServerHiveModel(
id: server.id,
alias: server.alias,
host: server.host,
user: server.user,
password: server.password,
enabled: server.enabled,
deactivateEcho: server.deactivateEcho,
deactivateLiveCheck: server.deactivateLiveCheck,
serverType: server.type == ServerType.gcore ? 'gcore' : 'geviscope',
isDirty: isDirty,
syncOperation: syncOperation,
);
}
// Convert from ServerModel (API) to Hive model
factory ServerHiveModel.fromServerModel(ServerModel serverModel) {
return ServerHiveModel(
id: serverModel.id,
alias: serverModel.alias,
host: serverModel.host,
user: serverModel.user,
password: serverModel.password,
enabled: serverModel.enabled,
deactivateEcho: serverModel.deactivateEcho,
deactivateLiveCheck: serverModel.deactivateLiveCheck,
serverType: serverModel.serverType,
isDirty: false,
syncOperation: null,
);
}
// Convert to domain entity
Server toEntity() {
return Server(
id: id,
alias: alias,
host: host,
user: user,
password: password,
enabled: enabled,
deactivateEcho: deactivateEcho,
deactivateLiveCheck: deactivateLiveCheck,
type: serverType == 'gcore' ? ServerType.gcore : ServerType.geviscope,
);
}
// Convert to ServerModel for API calls
ServerModel toServerModel() {
return ServerModel(
id: id,
alias: alias,
host: host,
user: user,
password: password,
enabled: enabled,
deactivateEcho: deactivateEcho,
deactivateLiveCheck: deactivateLiveCheck,
serverType: serverType,
);
}
// Create a copy with modified fields
ServerHiveModel copyWith({
String? id,
String? alias,
String? host,
String? user,
String? password,
bool? enabled,
bool? deactivateEcho,
bool? deactivateLiveCheck,
String? serverType,
bool? isDirty,
DateTime? lastModified,
String? syncOperation,
}) {
return ServerHiveModel(
id: id ?? this.id,
alias: alias ?? this.alias,
host: host ?? this.host,
user: user ?? this.user,
password: password ?? this.password,
enabled: enabled ?? this.enabled,
deactivateEcho: deactivateEcho ?? this.deactivateEcho,
deactivateLiveCheck: deactivateLiveCheck ?? this.deactivateLiveCheck,
serverType: serverType ?? this.serverType,
isDirty: isDirty ?? this.isDirty,
lastModified: lastModified ?? this.lastModified,
syncOperation: syncOperation ?? this.syncOperation,
);
}
}

View File

@@ -0,0 +1,74 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'server_hive_model.dart';
// **************************************************************************
// TypeAdapterGenerator
// **************************************************************************
class ServerHiveModelAdapter extends TypeAdapter<ServerHiveModel> {
@override
final int typeId = 0;
@override
ServerHiveModel read(BinaryReader reader) {
final numOfFields = reader.readByte();
final fields = <int, dynamic>{
for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(),
};
return ServerHiveModel(
id: fields[0] as String,
alias: fields[1] as String,
host: fields[2] as String,
user: fields[3] as String,
password: fields[4] as String,
enabled: fields[5] as bool,
deactivateEcho: fields[6] as bool,
deactivateLiveCheck: fields[7] as bool,
serverType: fields[8] as String,
isDirty: fields[9] as bool,
lastModified: fields[10] as DateTime?,
syncOperation: fields[11] as String?,
);
}
@override
void write(BinaryWriter writer, ServerHiveModel obj) {
writer
..writeByte(12)
..writeByte(0)
..write(obj.id)
..writeByte(1)
..write(obj.alias)
..writeByte(2)
..write(obj.host)
..writeByte(3)
..write(obj.user)
..writeByte(4)
..write(obj.password)
..writeByte(5)
..write(obj.enabled)
..writeByte(6)
..write(obj.deactivateEcho)
..writeByte(7)
..write(obj.deactivateLiveCheck)
..writeByte(8)
..write(obj.serverType)
..writeByte(9)
..write(obj.isDirty)
..writeByte(10)
..write(obj.lastModified)
..writeByte(11)
..write(obj.syncOperation);
}
@override
int get hashCode => typeId.hashCode;
@override
bool operator ==(Object other) =>
identical(this, other) ||
other is ServerHiveModelAdapter &&
runtimeType == other.runtimeType &&
typeId == other.typeId;
}

View File

@@ -0,0 +1,80 @@
import '../../domain/entities/server.dart';
class ServerModel {
final String id;
final String alias;
final String host;
final String user;
final String password;
final bool enabled;
final bool deactivateEcho;
final bool deactivateLiveCheck;
final String serverType; // "gcore" or "geviscope"
ServerModel({
required this.id,
required this.alias,
required this.host,
required this.user,
required this.password,
required this.enabled,
required this.deactivateEcho,
required this.deactivateLiveCheck,
required this.serverType,
});
factory ServerModel.fromJson(Map<String, dynamic> json, String type) {
return ServerModel(
id: json['id'].toString(),
alias: json['alias'] as String,
host: json['host'] as String,
user: json['user'] as String,
password: json['password'] as String,
enabled: json['enabled'] as bool,
deactivateEcho: json['deactivate_echo'] as bool,
deactivateLiveCheck: json['deactivate_live_check'] as bool,
serverType: type,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'alias': alias,
'host': host,
'user': user,
'password': password,
'enabled': enabled,
'deactivate_echo': deactivateEcho,
'deactivate_live_check': deactivateLiveCheck,
};
}
Server toEntity() {
return Server(
id: id,
alias: alias,
host: host,
user: user,
password: password,
enabled: enabled,
deactivateEcho: deactivateEcho,
deactivateLiveCheck: deactivateLiveCheck,
type: serverType == 'gcore' ? ServerType.gcore : ServerType.geviscope,
);
}
factory ServerModel.fromEntity(Server server) {
return ServerModel(
id: server.id,
alias: server.alias,
host: server.host,
user: server.user,
password: server.password,
enabled: server.enabled,
deactivateEcho: server.deactivateEcho,
deactivateLiveCheck: server.deactivateLiveCheck,
serverType: server.type == ServerType.gcore ? 'gcore' : 'geviscope',
);
}
}