mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 09:56:31 +00:00
make python app load a bit eariler, making startup a bit faster
This commit is contained in:
@@ -148,13 +148,13 @@
|
||||
Grid.Column="0"
|
||||
Name="LvFiles"
|
||||
Background="Black"
|
||||
SelectedItem="{Binding Path=SelectedVideo}" Foreground="#FFA4AFCC"
|
||||
SelectedItem="{Binding Path=SelectedVideo}" Foreground="#FFEEEEEE"
|
||||
>
|
||||
<ListView.Resources>
|
||||
<Style TargetType="{x:Type ListViewItem}">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasAnnotations}" Value="true">
|
||||
<Setter Property="Background" Value="Gray"/>
|
||||
<Setter Property="Background" Value="#FF505050"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
<EventSetter Event="ContextMenuOpening" Handler="LvFilesContextOpening"></EventSetter>
|
||||
|
||||
@@ -41,7 +41,6 @@ public partial class Annotator
|
||||
private readonly AnnotationService _annotationService;
|
||||
private readonly IDbFactory _dbFactory;
|
||||
private readonly IInferenceService _inferenceService;
|
||||
private readonly IResourceLoader _resourceLoader;
|
||||
|
||||
private ObservableCollection<DetectionClass> AnnotationClasses { get; set; } = new();
|
||||
private bool _suspendLayout;
|
||||
@@ -71,8 +70,7 @@ public partial class Annotator
|
||||
ILogger<Annotator> logger,
|
||||
AnnotationService annotationService,
|
||||
IDbFactory dbFactory,
|
||||
IInferenceService inferenceService,
|
||||
IResourceLoader resourceLoader)
|
||||
IInferenceService inferenceService)
|
||||
{
|
||||
InitializeComponent();
|
||||
_appConfig = appConfig.Value;
|
||||
@@ -86,7 +84,6 @@ public partial class Annotator
|
||||
_annotationService = annotationService;
|
||||
_dbFactory = dbFactory;
|
||||
_inferenceService = inferenceService;
|
||||
_resourceLoader = resourceLoader;
|
||||
|
||||
Loaded += OnLoaded;
|
||||
Closed += OnFormClosed;
|
||||
@@ -401,7 +398,6 @@ public partial class Annotator
|
||||
|
||||
private void OnFormClosed(object? sender, EventArgs e)
|
||||
{
|
||||
_resourceLoader.StopPython();
|
||||
MainCancellationSource.Cancel();
|
||||
DetectionCancellationSource.Cancel();
|
||||
_mediaPlayer.Stop();
|
||||
@@ -454,6 +450,7 @@ public partial class Annotator
|
||||
|
||||
_appConfig.DirectoriesConfig.VideosDirectory = dlg.FileName;
|
||||
TbFolder.Text = dlg.FileName;
|
||||
await Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void TbFilter_OnTextChanged(object sender, TextChangedEventArgs e)
|
||||
@@ -497,8 +494,6 @@ public partial class Annotator
|
||||
LvFilesContextMenu.DataContext = listItem!.DataContext;
|
||||
}
|
||||
|
||||
private (TimeSpan Time, List<Detection> Detections)? _previousDetection;
|
||||
|
||||
public void AutoDetect(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (IsInferenceNow)
|
||||
@@ -560,7 +555,7 @@ public partial class Annotator
|
||||
try
|
||||
{
|
||||
var annotation = await _annotationService.SaveAnnotation(annotationImage);
|
||||
if (annotation.OriginalMediaName != _formState.CurrentMedia.FName)
|
||||
if (annotation.OriginalMediaName != _formState.CurrentMedia?.FName)
|
||||
return;
|
||||
AddAnnotation(annotation);
|
||||
|
||||
|
||||
@@ -14,4 +14,5 @@ public class AIRecognitionConfig
|
||||
[Key(nameof(TrackingIntersectionThreshold))] public double TrackingIntersectionThreshold { get; set; }
|
||||
|
||||
[Key(nameof(Data))] public byte[] Data { get; set; }
|
||||
[Key(nameof(Paths))] public List<string> Paths { get; set; }
|
||||
}
|
||||
@@ -26,9 +26,9 @@ public class PythonInferenceService(ILogger<PythonInferenceService> logger, IOpt
|
||||
dealer.Options.Identity = Encoding.UTF8.GetBytes(clientId.ToString("N"));
|
||||
dealer.Connect($"tcp://{SecurityConstants.ZMQ_HOST}:{SecurityConstants.ZMQ_PORT}");
|
||||
|
||||
var data = MessagePackSerializer.Serialize(aiConfigOptions.Value);
|
||||
var filename = JsonConvert.SerializeObject(mediaPaths);
|
||||
dealer.SendFrame(MessagePackSerializer.Serialize(new RemoteCommand(CommandType.Inference, filename, data)));
|
||||
var aiConfig = aiConfigOptions.Value;
|
||||
aiConfig.Paths = mediaPaths;
|
||||
dealer.SendFrame(RemoteCommand.Serialize(CommandType.Inference, aiConfig));
|
||||
|
||||
while (!ct.IsCancellationRequested)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,16 @@
|
||||
namespace Azaion.CommonSecurity.DTO;
|
||||
using MessagePack;
|
||||
|
||||
namespace Azaion.CommonSecurity.DTO;
|
||||
|
||||
[MessagePackObject]
|
||||
public class ApiCredentials(string email, string password) : EventArgs
|
||||
{
|
||||
[Key(nameof(Email))]
|
||||
public string Email { get; set; } = email;
|
||||
|
||||
[Key(nameof(Password))]
|
||||
public string Password { get; set; } = password;
|
||||
|
||||
[Key(nameof(Folder))]
|
||||
public string Folder { get; set; } = null!;
|
||||
}
|
||||
@@ -3,22 +3,36 @@
|
||||
namespace Azaion.CommonSecurity.DTO.Commands;
|
||||
|
||||
[MessagePackObject]
|
||||
public class RemoteCommand(CommandType commandType, string? filename = null, byte[]? data = null)
|
||||
public class RemoteCommand(CommandType commandType, byte[]? data = null)
|
||||
{
|
||||
[Key("CommandType")]
|
||||
public CommandType CommandType { get; set; } = commandType;
|
||||
|
||||
[Key("Filename")]
|
||||
public string? Filename { get; set; } = filename;
|
||||
|
||||
[Key("Data")]
|
||||
public byte[]? Data { get; set; } = data;
|
||||
|
||||
public static byte[] Serialize<T>(CommandType commandType, T data) where T : class
|
||||
{
|
||||
var dataBytes = MessagePackSerializer.Serialize(data);
|
||||
return MessagePackSerializer.Serialize(new RemoteCommand(commandType, dataBytes ));
|
||||
}
|
||||
}
|
||||
|
||||
[MessagePackObject]
|
||||
public class LoadFileData(string filename, string? folder = null )
|
||||
{
|
||||
[Key(nameof(Folder))]
|
||||
public string? Folder { get; set; } = folder;
|
||||
|
||||
[Key(nameof(Filename))]
|
||||
public string Filename { get; set; } = filename;
|
||||
}
|
||||
|
||||
|
||||
public enum CommandType
|
||||
{
|
||||
None = 0,
|
||||
GetUser = 10,
|
||||
Login = 10,
|
||||
Load = 20,
|
||||
Inference = 30,
|
||||
StopInference = 40,
|
||||
|
||||
@@ -6,8 +6,8 @@ namespace Azaion.CommonSecurity.DTO;
|
||||
[MessagePackObject]
|
||||
public class User
|
||||
{
|
||||
[Key("i")]public string Id { get; set; }
|
||||
[Key("e")]public string Email { get; set; }
|
||||
[Key("i")] public string Id { get; set; } = "";
|
||||
[Key("e")] public string Email { get; set; } = "";
|
||||
[Key("r")]public RoleEnum Role { get; set; }
|
||||
|
||||
//For deserializing
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Azaion.CommonSecurity.Services;
|
||||
|
||||
public interface IResourceLoader
|
||||
{
|
||||
MemoryStream LoadFileFromPython(string fileName);
|
||||
MemoryStream LoadFileFromPython(string fileName, string? folder = null);
|
||||
void StopPython();
|
||||
}
|
||||
|
||||
@@ -25,29 +25,22 @@ public class PythonResourceLoader : IResourceLoader, IAuthProvider
|
||||
private readonly DealerSocket _dealer = new();
|
||||
private readonly Guid _clientId = Guid.NewGuid();
|
||||
|
||||
public User CurrentUser { get; }
|
||||
public User CurrentUser { get; set; }
|
||||
|
||||
public PythonResourceLoader(ApiConfig apiConfig, ApiCredentials credentials, AzaionApiClient api)
|
||||
public PythonResourceLoader()
|
||||
{
|
||||
StartPython(apiConfig, credentials);
|
||||
StartPython();
|
||||
_dealer.Options.Identity = Encoding.UTF8.GetBytes(_clientId.ToString("N"));
|
||||
_dealer.Connect($"tcp://{SecurityConstants.ZMQ_HOST}:{SecurityConstants.ZMQ_PORT}");
|
||||
|
||||
_dealer.SendFrame(MessagePackSerializer.Serialize(new RemoteCommand(CommandType.GetUser)));
|
||||
var user = _dealer.Get<User>();
|
||||
if (user == null)
|
||||
throw new Exception("Can't get user from Auth provider");
|
||||
|
||||
CurrentUser = user;
|
||||
}
|
||||
|
||||
private void StartPython( ApiConfig apiConfig, ApiCredentials credentials)
|
||||
private void StartPython()
|
||||
{
|
||||
using var process = new Process();
|
||||
process.StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = SecurityConstants.AZAION_INFERENCE_PATH,
|
||||
Arguments = $"-e {credentials.Email} -p {credentials.Password} -f {apiConfig.ResourcesFolder}",
|
||||
//Arguments = $"-e {credentials.Email} -p {credentials.Password} -f {apiConfig.ResourcesFolder}",
|
||||
//UseShellExecute = false,
|
||||
//RedirectStandardOutput = true,
|
||||
// RedirectStandardError = true,
|
||||
@@ -59,17 +52,27 @@ public class PythonResourceLoader : IResourceLoader, IAuthProvider
|
||||
process.Start();
|
||||
}
|
||||
|
||||
public void Login(ApiCredentials credentials)
|
||||
{
|
||||
_dealer.SendFrame(RemoteCommand.Serialize(CommandType.Login, credentials));
|
||||
var user = _dealer.Get<User>();
|
||||
if (user == null)
|
||||
throw new Exception("Can't get user from Auth provider");
|
||||
|
||||
CurrentUser = user;
|
||||
}
|
||||
|
||||
public void StopPython()
|
||||
{
|
||||
_dealer.SendFrame(MessagePackSerializer.Serialize(new RemoteCommand(CommandType.Exit)));
|
||||
_dealer?.Close();
|
||||
_dealer.Close();
|
||||
}
|
||||
|
||||
public MemoryStream LoadFileFromPython(string fileName)
|
||||
public MemoryStream LoadFileFromPython(string fileName, string? folder = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_dealer.SendFrame(MessagePackSerializer.Serialize(new RemoteCommand(CommandType.Load, fileName)));
|
||||
_dealer.SendFrame(RemoteCommand.Serialize(CommandType.Load, new LoadFileData(fileName, folder)));
|
||||
|
||||
if (!_dealer.TryReceiveFrameBytes(TimeSpan.FromSeconds(3), out var bytes))
|
||||
throw new Exception($"Unable to receive {fileName}");
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
from user cimport User
|
||||
from credentials cimport Credentials
|
||||
from file_data cimport FileData
|
||||
|
||||
cdef class ApiClient:
|
||||
cdef str email, password, token, folder, token_file, api_url
|
||||
cdef public Credentials credentials
|
||||
cdef str token, folder, api_url
|
||||
cdef User user
|
||||
|
||||
cdef get_encryption_key(self, str hardware_hash)
|
||||
@@ -9,7 +12,7 @@ cdef class ApiClient:
|
||||
cdef set_token(self, str token)
|
||||
cdef get_user(self)
|
||||
|
||||
cdef load_bytes(self, str filename)
|
||||
cdef load_bytes(self, FileData file_data)
|
||||
cdef load_ai_model(self)
|
||||
cdef load_queue_config(self)
|
||||
|
||||
|
||||
@@ -9,33 +9,25 @@ from hardware_service cimport HardwareService, HardwareInfo
|
||||
from security cimport Security
|
||||
from io import BytesIO
|
||||
from user cimport User, RoleEnum
|
||||
from file_data cimport FileData
|
||||
|
||||
cdef class ApiClient:
|
||||
"""Handles API authentication and downloading of the AI model."""
|
||||
def __init__(self, str email, str password, str folder):
|
||||
self.email = email
|
||||
self.password = password
|
||||
self.folder = folder
|
||||
def __init__(self):
|
||||
self.credentials = None
|
||||
self.user = None
|
||||
|
||||
if os.path.exists(<str>constants.TOKEN_FILE):
|
||||
with open(<str>constants.TOKEN_FILE, "r") as file:
|
||||
self.set_token(<str>file.read().strip())
|
||||
else:
|
||||
self.token = None
|
||||
|
||||
cdef get_encryption_key(self, str hardware_hash):
|
||||
cdef str key = f'{self.email}-{self.password}-{hardware_hash}-#%@AzaionKey@%#---'
|
||||
cdef str key = f'{self.credentials.email}-{self.credentials.password}-{hardware_hash}-#%@AzaionKey@%#---'
|
||||
return Security.calc_hash(key)
|
||||
|
||||
cdef login(self):
|
||||
response = requests.post(f"{constants.API_URL}/login",
|
||||
json={"email": self.email, "password": self.password})
|
||||
json={"email": self.credentials.email, "password": self.credentials.password})
|
||||
response.raise_for_status()
|
||||
token = response.json()["token"]
|
||||
self.set_token(token)
|
||||
with open(<str>constants.TOKEN_FILE, 'w') as file:
|
||||
file.write(token)
|
||||
|
||||
cdef set_token(self, str token):
|
||||
self.token = token
|
||||
@@ -68,14 +60,15 @@ cdef class ApiClient:
|
||||
self.login()
|
||||
return self.user
|
||||
|
||||
cdef load_bytes(self, str filename):
|
||||
cdef load_bytes(self, FileData file_data):
|
||||
folder = file_data.folder or self.credentials.folder
|
||||
hardware_service = HardwareService()
|
||||
cdef HardwareInfo hardware = hardware_service.get_hardware_info()
|
||||
|
||||
if self.token is None:
|
||||
self.login()
|
||||
|
||||
url = f"{constants.API_URL}/resources/get/{self.folder}"
|
||||
url = f"{constants.API_URL}/resources/get/{folder}"
|
||||
headers = {
|
||||
"Authorization": f"Bearer {self.token}",
|
||||
"Content-Type": "application/json"
|
||||
@@ -83,9 +76,9 @@ cdef class ApiClient:
|
||||
|
||||
payload = json.dumps(
|
||||
{
|
||||
"password": self.password,
|
||||
"password": self.credentials.password,
|
||||
"hardware": hardware.to_json_object(),
|
||||
"fileName": filename
|
||||
"fileName": file_data.filename
|
||||
}, indent=4)
|
||||
response = requests.post(url, data=payload, headers=headers, stream=True)
|
||||
|
||||
@@ -104,7 +97,7 @@ cdef class ApiClient:
|
||||
|
||||
stream = BytesIO(response.raw.read())
|
||||
data = Security.decrypt_to(stream, key)
|
||||
print(f'loaded file: {filename}, {len(data)} bytes')
|
||||
print(f'loaded file: {file_data.filename}, {len(data)} bytes')
|
||||
return data
|
||||
|
||||
cdef load_ai_model(self):
|
||||
|
||||
@@ -7,13 +7,15 @@ pyinstaller --onefile ^
|
||||
--collect-all cryptography ^
|
||||
--collect-all cv2 ^
|
||||
--collect-all onnxruntime ^
|
||||
--hidden-import constants ^
|
||||
--hidden-import annotation ^
|
||||
--hidden-import credentials ^
|
||||
--hidden-import file_data ^
|
||||
--hidden-import user ^
|
||||
--hidden-import security ^
|
||||
--hidden-import secure_model ^
|
||||
--hidden-import api_client ^
|
||||
--hidden-import hardware_service ^
|
||||
--hidden-import constants ^
|
||||
--hidden-import annotation ^
|
||||
--hidden-import remote_command ^
|
||||
--hidden-import ai_config ^
|
||||
--hidden-import inference ^
|
||||
|
||||
@@ -5,7 +5,6 @@ cdef str COMMANDS_QUEUE # Name of the commands queue in rabbit
|
||||
cdef str ANNOTATIONS_QUEUE # Name of the annotations queue in rabbit
|
||||
|
||||
cdef str API_URL # Base URL for the external API
|
||||
cdef str TOKEN_FILE # Name of the token file where temporary token would be stored
|
||||
cdef str QUEUE_CONFIG_FILENAME # queue config filename to load from api
|
||||
cdef str AI_MODEL_FILE # AI Model file
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ cdef str COMMANDS_QUEUE = "azaion-commands"
|
||||
cdef str ANNOTATIONS_QUEUE = "azaion-annotations"
|
||||
|
||||
cdef str API_URL = "https://api.azaion.com" # Base URL for the external API
|
||||
cdef str TOKEN_FILE = "token"
|
||||
cdef str QUEUE_CONFIG_FILENAME = "secured-config.json"
|
||||
cdef str AI_MODEL_FILE = "azaion.onnx"
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
cdef class Credentials:
|
||||
cdef public str email
|
||||
cdef public str password
|
||||
cdef public str folder
|
||||
|
||||
@staticmethod
|
||||
cdef from_msgpack(bytes data)
|
||||
@@ -0,0 +1,17 @@
|
||||
from msgpack import unpackb
|
||||
|
||||
cdef class Credentials:
|
||||
|
||||
def __init__(self, str email, str password, str folder):
|
||||
self.email = email
|
||||
self.password = password
|
||||
self.folder = folder
|
||||
|
||||
@staticmethod
|
||||
cdef from_msgpack(bytes data):
|
||||
unpacked = unpackb(data, strict_map_key=False)
|
||||
return Credentials(
|
||||
unpacked.get("Email"),
|
||||
unpacked.get("Password"),
|
||||
unpacked.get("Folder"))
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
cdef class FileData:
|
||||
cdef public str folder
|
||||
cdef public str filename
|
||||
|
||||
@staticmethod
|
||||
cdef from_msgpack(bytes data)
|
||||
@@ -0,0 +1,14 @@
|
||||
from msgpack import unpackb
|
||||
|
||||
cdef class FileData:
|
||||
|
||||
def __init__(self, str folder, str filename):
|
||||
self.folder = folder
|
||||
self.filename = filename
|
||||
|
||||
@staticmethod
|
||||
cdef from_msgpack(bytes data):
|
||||
unpacked = unpackb(data, strict_map_key=False)
|
||||
return FileData(
|
||||
unpacked.get("Folder"),
|
||||
unpacked.get("Filename"))
|
||||
+15
-15
@@ -9,16 +9,10 @@ from annotation cimport Annotation
|
||||
from inference cimport Inference
|
||||
from remote_command cimport RemoteCommand, CommandType
|
||||
from remote_command_handler cimport RemoteCommandHandler
|
||||
from credentials cimport Credentials
|
||||
from file_data cimport FileData
|
||||
from user cimport User
|
||||
|
||||
cdef class ParsedArguments:
|
||||
cdef str email, password, folder;
|
||||
|
||||
def __init__(self, str email, str password, str folder):
|
||||
self.email = email
|
||||
self.password = password
|
||||
self.folder = folder
|
||||
|
||||
cdef class CommandProcessor:
|
||||
cdef ApiClient api_client
|
||||
cdef RemoteCommandHandler remote_handler
|
||||
@@ -26,8 +20,8 @@ cdef class CommandProcessor:
|
||||
cdef bint running
|
||||
cdef Inference inference
|
||||
|
||||
def __init__(self, args: ParsedArguments):
|
||||
self.api_client = ApiClient(args.email, args.password, args.folder)
|
||||
def __init__(self):
|
||||
self.api_client = ApiClient()
|
||||
self.remote_handler = RemoteCommandHandler(self.on_command)
|
||||
self.inference_queue = Queue(maxsize=constants.QUEUE_MAXSIZE)
|
||||
self.remote_handler.start()
|
||||
@@ -49,11 +43,10 @@ cdef class CommandProcessor:
|
||||
|
||||
cdef on_command(self, RemoteCommand command):
|
||||
try:
|
||||
if command.command_type == CommandType.GET_USER:
|
||||
self.get_user(command, self.api_client.get_user())
|
||||
if command.command_type == CommandType.LOGIN:
|
||||
self.login(command)
|
||||
elif command.command_type == CommandType.LOAD:
|
||||
response = self.api_client.load_bytes(command.filename)
|
||||
self.remote_handler.send(command.client_id, response)
|
||||
self.load_file(command)
|
||||
elif command.command_type == CommandType.INFERENCE:
|
||||
self.inference_queue.put(command)
|
||||
elif command.command_type == CommandType.STOP_INFERENCE:
|
||||
@@ -66,9 +59,16 @@ cdef class CommandProcessor:
|
||||
except Exception as e:
|
||||
print(f"Error handling client: {e}")
|
||||
|
||||
cdef get_user(self, RemoteCommand command, User user):
|
||||
cdef login(self, RemoteCommand command):
|
||||
cdef User user
|
||||
self.api_client.credentials = Credentials.from_msgpack(command.data)
|
||||
user = self.api_client.get_user()
|
||||
self.remote_handler.send(command.client_id, user.serialize())
|
||||
|
||||
cdef load_file(self, RemoteCommand command):
|
||||
response = self.api_client.load_bytes(FileData.from_msgpack(command.data))
|
||||
self.remote_handler.send(command.client_id, response)
|
||||
|
||||
cdef on_annotation(self, RemoteCommand cmd, Annotation annotation):
|
||||
data = annotation.serialize()
|
||||
self.remote_handler.send(cmd.client_id, data)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
cdef enum CommandType:
|
||||
GET_USER = 10
|
||||
LOGIN = 10
|
||||
LOAD = 20
|
||||
INFERENCE = 30
|
||||
STOP_INFERENCE = 40
|
||||
@@ -8,7 +8,6 @@ cdef enum CommandType:
|
||||
cdef class RemoteCommand:
|
||||
cdef public bytes client_id
|
||||
cdef CommandType command_type
|
||||
cdef str filename
|
||||
cdef bytes data
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -1,23 +1,22 @@
|
||||
import msgpack
|
||||
|
||||
cdef class RemoteCommand:
|
||||
def __init__(self, CommandType command_type, str filename, bytes data):
|
||||
def __init__(self, CommandType command_type, bytes data):
|
||||
self.command_type = command_type
|
||||
self.filename = filename
|
||||
self.data = data
|
||||
|
||||
def __str__(self):
|
||||
command_type_names = {
|
||||
10: "GET_USER",
|
||||
10: "LOGIN",
|
||||
20: "LOAD",
|
||||
30: "INFERENCE",
|
||||
40: "STOP_INFERENCE",
|
||||
100: "EXIT"
|
||||
}
|
||||
data_str = f'. Data: {len(self.data)} bytes' if self.data else ''
|
||||
return f'{command_type_names[self.command_type]}: {self.filename}{data_str}'
|
||||
return f'{command_type_names[self.command_type]}: {data_str}'
|
||||
|
||||
@staticmethod
|
||||
cdef from_msgpack(bytes data):
|
||||
unpacked = msgpack.unpackb(data, strict_map_key=False)
|
||||
return RemoteCommand(unpacked.get("CommandType"), unpacked.get("Filename"), unpacked.get("Data"))
|
||||
return RemoteCommand(unpacked.get("CommandType"), unpacked.get("Data"))
|
||||
|
||||
@@ -5,6 +5,8 @@ import numpy as np
|
||||
extensions = [
|
||||
Extension('constants', ['constants.pyx']),
|
||||
Extension('annotation', ['annotation.pyx']),
|
||||
Extension('credentials', ['credentials.pyx']),
|
||||
Extension('file_data', ['file_data.pyx']),
|
||||
Extension('security', ['security.pyx']),
|
||||
Extension('hardware_service', ['hardware_service.pyx'], extra_compile_args=["-g"], extra_link_args=["-g"]),
|
||||
Extension('remote_command', ['remote_command.pyx']),
|
||||
|
||||
@@ -1,22 +1,13 @@
|
||||
import argparse
|
||||
from main import ParsedArguments, CommandProcessor
|
||||
from main import CommandProcessor
|
||||
|
||||
|
||||
def parse_arguments():
|
||||
parser = argparse.ArgumentParser(description="Command Processor")
|
||||
parser.add_argument("-e", "--email", type=str, default="", help="Email")
|
||||
parser.add_argument("-p", "--pw", type=str, default="", help="Password")
|
||||
parser.add_argument("-f", "--folder", type=str, default="", help="Folder to API inner folder to download file from")
|
||||
args = parser.parse_args()
|
||||
|
||||
return ParsedArguments(args.email, args.pw, args.folder)
|
||||
|
||||
def start(args: ParsedArguments):
|
||||
processor = CommandProcessor(args)
|
||||
def start():
|
||||
processor = CommandProcessor()
|
||||
try:
|
||||
processor.start()
|
||||
except KeyboardInterrupt:
|
||||
processor.stop()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
start(parse_arguments())
|
||||
start()
|
||||
|
||||
@@ -3,7 +3,7 @@ from PyInstaller.utils.hooks import collect_all
|
||||
|
||||
datas = []
|
||||
binaries = []
|
||||
hiddenimports = ['user', 'security', 'secure_model', 'api_client', 'hardware_service', 'constants', 'annotation', 'remote_command', 'ai_config', 'inference', 'remote_command_handler']
|
||||
hiddenimports = ['constants', 'annotation', 'credentials', 'file_data', 'user', 'security', 'secure_model', 'api_client', 'hardware_service', 'remote_command', 'ai_config', 'inference', 'remote_command_handler']
|
||||
tmp_ret = collect_all('jwt')
|
||||
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
||||
tmp_ret = collect_all('requests')
|
||||
|
||||
@@ -32,22 +32,27 @@ Global
|
||||
{8E0809AF-2920-4267-B14D-84BAB334A46F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8E0809AF-2920-4267-B14D-84BAB334A46F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8E0809AF-2920-4267-B14D-84BAB334A46F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8E0809AF-2920-4267-B14D-84BAB334A46F}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{85359558-FB59-4542-A597-FD9E1B04C8E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{85359558-FB59-4542-A597-FD9E1B04C8E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{85359558-FB59-4542-A597-FD9E1B04C8E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{85359558-FB59-4542-A597-FD9E1B04C8E7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{85359558-FB59-4542-A597-FD9E1B04C8E7}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{BA77500E-8B66-4F31-81B0-E831FC12EDFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{BA77500E-8B66-4F31-81B0-E831FC12EDFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{BA77500E-8B66-4F31-81B0-E831FC12EDFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{BA77500E-8B66-4F31-81B0-E831FC12EDFB}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{BA77500E-8B66-4F31-81B0-E831FC12EDFB}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{1D8E6F44-C64E-4DBE-8665-2101EC5BE36E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1D8E6F44-C64E-4DBE-8665-2101EC5BE36E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1D8E6F44-C64E-4DBE-8665-2101EC5BE36E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1D8E6F44-C64E-4DBE-8665-2101EC5BE36E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1D8E6F44-C64E-4DBE-8665-2101EC5BE36E}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{01A5CA37-A62E-4EF3-8678-D72CD9525677}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{01A5CA37-A62E-4EF3-8678-D72CD9525677}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{01A5CA37-A62E-4EF3-8678-D72CD9525677}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{01A5CA37-A62E-4EF3-8678-D72CD9525677}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{01A5CA37-A62E-4EF3-8678-D72CD9525677}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
{32C4747F-F700-44FD-B4ED-21B4A66B5FAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{32C4747F-F700-44FD-B4ED-21B4A66B5FAB}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{32C4747F-F700-44FD-B4ED-21B4A66B5FAB}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -60,6 +65,7 @@ Global
|
||||
{E0C7176D-2E91-4928-B3C1-55CC91C8F77D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E0C7176D-2E91-4928-B3C1-55CC91C8F77D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E0C7176D-2E91-4928-B3C1-55CC91C8F77D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E0C7176D-2E91-4928-B3C1-55CC91C8F77D}.Release|Any CPU.Deploy.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{32C4747F-F700-44FD-B4ED-21B4A66B5FAB} = {C307BE2E-FFCC-4BD7-AD89-C82D40B65D03}
|
||||
|
||||
@@ -33,7 +33,7 @@ public partial class App
|
||||
private IMediator _mediator = null!;
|
||||
private FormState _formState = null!;
|
||||
|
||||
private PythonResourceLoader _resourceLoader = null!;
|
||||
private readonly PythonResourceLoader _resourceLoader = new();
|
||||
private Stream _securedConfig = null!;
|
||||
|
||||
private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
|
||||
@@ -54,7 +54,7 @@ public partial class App
|
||||
"Azaion.Dataset"
|
||||
];
|
||||
|
||||
private ApiConfig ReadConfig()
|
||||
private static ApiConfig ReadConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -69,8 +69,9 @@ public partial class App
|
||||
return new ApiConfig
|
||||
{
|
||||
Url = SecurityConstants.DEFAULT_API_URL,
|
||||
RetryCount = SecurityConstants.DEFAULT_API_RETRY_COUNT ,
|
||||
TimeoutSeconds = SecurityConstants.DEFAULT_API_TIMEOUT_SECONDS
|
||||
RetryCount = SecurityConstants.DEFAULT_API_RETRY_COUNT,
|
||||
TimeoutSeconds = SecurityConstants.DEFAULT_API_TIMEOUT_SECONDS,
|
||||
ResourcesFolder = ""
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -81,10 +82,9 @@ public partial class App
|
||||
var login = new Login();
|
||||
login.CredentialsEntered += (_, credentials) =>
|
||||
{
|
||||
var apiConfig = ReadConfig();
|
||||
var api = AzaionApiClient.Create(credentials, apiConfig);
|
||||
|
||||
_resourceLoader = new PythonResourceLoader(apiConfig, credentials, api);
|
||||
var config = ReadConfig();
|
||||
credentials.Folder = config.ResourcesFolder;
|
||||
_resourceLoader.Login(credentials);
|
||||
_securedConfig = _resourceLoader.LoadFileFromPython("secured-config.json");
|
||||
|
||||
AppDomain.CurrentDomain.AssemblyResolve += (_, a) =>
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Azaion.Annotator\Azaion.Annotator.csproj" />
|
||||
<ProjectReference Include="..\Azaion.Common\Azaion.Common.csproj" />
|
||||
<ProjectReference Include="..\Azaion.Dataset\Azaion.Dataset.csproj" />
|
||||
<ProjectReference Include="..\Dummy\Azaion.Annotator\Azaion.Annotator.csproj" />
|
||||
<ProjectReference Include="..\Dummy\Azaion.Dataset\Azaion.Dataset.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -54,9 +54,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="Build">
|
||||
<MakeDir Directories="$(TargetDir)secure" />
|
||||
<Move SourceFiles="$(TargetDir)Azaion.Annotator.dll" DestinationFolder="$(TargetDir)secure" />
|
||||
<Move SourceFiles="$(TargetDir)Azaion.Dataset.dll" DestinationFolder="$(TargetDir)secure" />
|
||||
<MakeDir Directories="$(TargetDir)dummy" />
|
||||
<Move SourceFiles="$(TargetDir)Azaion.Annotator.dll" DestinationFolder="$(TargetDir)dummy" />
|
||||
<Move SourceFiles="$(TargetDir)Azaion.Dataset.dll" DestinationFolder="$(TargetDir)dummy" />
|
||||
<Exec Command="upload.cmd $(ConfigurationName)" />
|
||||
</Target>
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using Azaion.Common.DTO;
|
||||
using Azaion.Common.DTO.Config;
|
||||
using Azaion.Common.Extensions;
|
||||
using Azaion.Common.Services;
|
||||
using Azaion.CommonSecurity.Services;
|
||||
using Azaion.Dataset;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Options;
|
||||
@@ -24,20 +25,22 @@ public partial class MainSuite
|
||||
private readonly IGalleryService _galleryService;
|
||||
private readonly IDbFactory _dbFactory;
|
||||
private readonly Dictionary<WindowEnum, Window> _openedWindows = new();
|
||||
private readonly IResourceLoader _resourceLoader;
|
||||
|
||||
public MainSuite(IOptions<AppConfig> appConfig,
|
||||
IConfigUpdater configUpdater,
|
||||
IEnumerable<IAzaionModule> modules,
|
||||
IServiceProvider sp,
|
||||
IGalleryService galleryService,
|
||||
IDbFactory dbFactory
|
||||
)
|
||||
IDbFactory dbFactory,
|
||||
IResourceLoader resourceLoader)
|
||||
{
|
||||
_configUpdater = configUpdater;
|
||||
_modules = modules;
|
||||
_sp = sp;
|
||||
_galleryService = galleryService;
|
||||
_dbFactory = dbFactory;
|
||||
_resourceLoader = resourceLoader;
|
||||
_appConfig = appConfig.Value;
|
||||
InitializeComponent();
|
||||
Loaded += OnLoaded;
|
||||
@@ -107,6 +110,7 @@ public partial class MainSuite
|
||||
_openedWindows[module.WindowEnum] = window;
|
||||
window.Closed += (_, _) =>
|
||||
{
|
||||
_resourceLoader.StopPython();
|
||||
_openedWindows.Remove(module.WindowEnum);
|
||||
if (!_openedWindows.Any())
|
||||
Close();
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
{
|
||||
"ApiConfig": {
|
||||
"Url": "https://api.azaion.com/",
|
||||
"RetryCount": 3,
|
||||
"TimeoutSeconds": 40.0,
|
||||
"ResourcesFolder": "stage",
|
||||
"TokenFile": "token.txt"
|
||||
"TimeoutSeconds": 20.0,
|
||||
"ResourcesFolder": "stage"
|
||||
},
|
||||
"DirectoriesConfig": {
|
||||
"VideosDirectory": "E:\\Azaion6",
|
||||
|
||||
@@ -7,11 +7,12 @@ set RESOURCES_FOLDER=stage
|
||||
|
||||
set EMAIL=uploader@azaion.com
|
||||
set PASSWORD=Az@1on_10Upl0@der
|
||||
echo %cd%
|
||||
|
||||
set FILE1_TO_UPLOAD=%cd%\bin\%CONFIG%\net8.0-windows\secure\Azaion.Annotator.dll
|
||||
set FILE1_TO_UPLOAD=%cd%\..\Azaion.Annotator\bin\%CONFIG%\net8.0-windows\Azaion.Annotator.dll
|
||||
set "FILE1_TO_UPLOAD=%FILE1_TO_UPLOAD:\=/%"
|
||||
|
||||
set FILE2_TO_UPLOAD=%cd%\bin\%CONFIG%\net8.0-windows\secure\Azaion.Dataset.dll
|
||||
set FILE2_TO_UPLOAD=%cd%\..\Azaion.Dataset\bin\%CONFIG%\net8.0-windows\Azaion.Dataset.dll
|
||||
set "FILE2_TO_UPLOAD=%FILE2_TO_UPLOAD:\=/%"
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ public class DictTest
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(null, 0)]
|
||||
[InlineData(new int[]{}, 0)]
|
||||
[InlineData(new int[]{1, 2, 5}, 1)]
|
||||
[InlineData(new int[]{3, -2, 5}, -2)]
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
<PackageReference Include="SkiaSharp" Version="2.88.9" />
|
||||
<PackageReference Include="VideoLAN.LibVLC.Windows" Version="3.0.21" />
|
||||
<PackageReference Include="WindowsAPICodePack" Version="7.0.4" />
|
||||
<PackageReference Include="YoloV8.Gpu" Version="5.0.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
Reference in New Issue
Block a user