diff --git a/Azaion.Annotator/Annotator.xaml.cs b/Azaion.Annotator/Annotator.xaml.cs index 7d86bed..5e88471 100644 --- a/Azaion.Annotator/Annotator.xaml.cs +++ b/Azaion.Annotator/Annotator.xaml.cs @@ -122,7 +122,16 @@ public partial class Annotator { "uploading", "Будь ласка зачекайте, йде зберігання" }, { "enabled", "AI готовий для розпізнавання" } }; - StatusHelp.Text = messagesDict!.GetValueOrDefault(command.Message, aiDisabledText); + + if (command.Message?.StartsWith("Error") ?? false) + { + _logger.LogError(command.Message); + StatusHelp.Text = command.Message; + } + + else + StatusHelp.Text = messagesDict!.GetValueOrDefault(command.Message, aiDisabledText); + if (aiEnabled) StatusHelp.Foreground = aiEnabled ? Brushes.White : Brushes.Red; }); diff --git a/Azaion.Annotator/Azaion.Annotator.csproj b/Azaion.Annotator/Azaion.Annotator.csproj index 0c50406..0e3ecaf 100644 --- a/Azaion.Annotator/Azaion.Annotator.csproj +++ b/Azaion.Annotator/Azaion.Annotator.csproj @@ -7,6 +7,16 @@ net8.0-windows + + $([System.DateTime]::UtcNow.ToString("yyyy.MM.dd")) + $([System.Convert]::ToInt32($([System.DateTime]::UtcNow.TimeOfDay.TotalSeconds))) + + $(VersionDate).$(VersionSeconds) + $(AssemblyVersion) + $(AssemblyVersion) + Copyright @ $([System.DateTime]::UtcNow.ToString("yyyy")) Azaion LLC. All rights reserved. + + diff --git a/Azaion.Common/Services/GpsMatcherClient.cs b/Azaion.Common/Services/GpsMatcherClient.cs index 9676752..81a6211 100644 --- a/Azaion.Common/Services/GpsMatcherClient.cs +++ b/Azaion.Common/Services/GpsMatcherClient.cs @@ -137,6 +137,9 @@ public class GpsMatcherClient : IGpsMatcherClient public void Dispose() { + _poller.Stop(); + _poller.Dispose(); + _requestSocket.SendFrame("EXIT"); _requestSocket.Disconnect(_requestAddress); _requestSocket.Dispose(); diff --git a/Azaion.Common/Services/InferenceClient.cs b/Azaion.Common/Services/InferenceClient.cs index 1e30f6f..a7be69b 100644 --- a/Azaion.Common/Services/InferenceClient.cs +++ b/Azaion.Common/Services/InferenceClient.cs @@ -23,7 +23,7 @@ public interface IInferenceClient : IDisposable void Stop(); } -public class InferenceClient(IOptions inferenceConfig, IOptions loaderConfig) : IInferenceClient +public class InferenceClient : IInferenceClient { public event EventHandler? BytesReceived; public event EventHandler? InferenceDataReceived; @@ -32,8 +32,15 @@ public class InferenceClient(IOptions inferenceConfig, IO private readonly DealerSocket _dealer = new(); private readonly NetMQPoller _poller = new(); private readonly Guid _clientId = Guid.NewGuid(); - private readonly InferenceClientConfig _inferenceClientConfig = inferenceConfig.Value; - private readonly LoaderClientConfig _loaderClientConfig = loaderConfig.Value; + private readonly InferenceClientConfig _inferenceClientConfig; + private readonly LoaderClientConfig _loaderClientConfig; + + public InferenceClient(IOptions inferenceConfig, IOptions loaderConfig) + { + _inferenceClientConfig = inferenceConfig.Value; + _loaderClientConfig = loaderConfig.Value; + Start(); + } private void Start() { @@ -43,7 +50,7 @@ public class InferenceClient(IOptions inferenceConfig, IO process.StartInfo = new ProcessStartInfo { FileName = SecurityConstants.EXTERNAL_INFERENCE_PATH, - Arguments = $"--port {_inferenceClientConfig.ZeroMqPort} --loader-port {_loaderClientConfig.ZeroMqPort} --api {_inferenceClientConfig.ApiUrl}", + Arguments = $"-p {_inferenceClientConfig.ZeroMqPort} -lp {_loaderClientConfig.ZeroMqPort} -a {_inferenceClientConfig.ApiUrl}", //RedirectStandardOutput = true, //RedirectStandardError = true, //CreateNoWindow = true @@ -51,7 +58,7 @@ public class InferenceClient(IOptions inferenceConfig, IO process.OutputDataReceived += (_, e) => { if (e.Data != null) Console.WriteLine(e.Data); }; process.ErrorDataReceived += (_, e) => { if (e.Data != null) Console.WriteLine(e.Data); }; - process.Start(); + // process.Start(); } catch (Exception e) { @@ -101,7 +108,6 @@ public class InferenceClient(IOptions inferenceConfig, IO { _poller.Stop(); _poller.Dispose(); - _dealer.SendFrame(MessagePackSerializer.Serialize(new RemoteCommand(CommandType.Exit))); _dealer.Disconnect($"tcp://{_inferenceClientConfig.ZeroMqHost}:{_inferenceClientConfig.ZeroMqPort}"); _dealer.Close(); diff --git a/Azaion.CommonSecurity/SecurityConstants.cs b/Azaion.CommonSecurity/SecurityConstants.cs index 85deddb..f18a610 100644 --- a/Azaion.CommonSecurity/SecurityConstants.cs +++ b/Azaion.CommonSecurity/SecurityConstants.cs @@ -1,4 +1,5 @@ using Azaion.CommonSecurity.DTO; +using Newtonsoft.Json; namespace Azaion.CommonSecurity; @@ -56,4 +57,22 @@ public class SecurityConstants } }; #endregion ExternalClientsConfig + + public static InitConfig ReadInitConfig() + { + try + { + if (!File.Exists(CONFIG_PATH)) + throw new FileNotFoundException(CONFIG_PATH); + var configStr = File.ReadAllText(CONFIG_PATH); + var config = JsonConvert.DeserializeObject(configStr); + + return config ?? DefaultInitConfig; + } + catch (Exception e) + { + Console.WriteLine(e); + return DefaultInitConfig; + } + } } \ No newline at end of file diff --git a/Azaion.CommonSecurity/Services/LoaderClient.cs b/Azaion.CommonSecurity/Services/LoaderClient.cs index 05f6226..4f0e414 100644 --- a/Azaion.CommonSecurity/Services/LoaderClient.cs +++ b/Azaion.CommonSecurity/Services/LoaderClient.cs @@ -10,7 +10,7 @@ using Exception = System.Exception; namespace Azaion.CommonSecurity.Services; -public class LoaderClient(LoaderClientConfig config, ILogger logger, CancellationToken ct = default) +public class LoaderClient(LoaderClientConfig config, ILogger logger, CancellationToken ct = default) : IDisposable { private readonly DealerSocket _dealer = new(); private readonly Guid _clientId = Guid.NewGuid(); @@ -24,7 +24,7 @@ public class LoaderClient(LoaderClientConfig config, ILogger logger, Cancellatio { FileName = SecurityConstants.EXTERNAL_LOADER_PATH, Arguments = $"--port {config.ZeroMqPort} --api {config.ApiUrl}", - CreateNoWindow = true + //CreateNoWindow = true }; process.OutputDataReceived += (_, e) => @@ -90,4 +90,14 @@ public class LoaderClient(LoaderClientConfig config, ILogger logger, Cancellatio throw; } } + + public void Stop() + { + _dealer.SendFrame(MessagePackSerializer.Serialize(new RemoteCommand(CommandType.Exit))); + } + + public void Dispose() + { + _dealer.Dispose(); + } } \ No newline at end of file diff --git a/Azaion.Dataset/Azaion.Dataset.csproj b/Azaion.Dataset/Azaion.Dataset.csproj index 8ab5bcf..08f525f 100644 --- a/Azaion.Dataset/Azaion.Dataset.csproj +++ b/Azaion.Dataset/Azaion.Dataset.csproj @@ -7,6 +7,16 @@ true + + $([System.DateTime]::UtcNow.ToString("yyyy.MM.dd")) + $([System.Convert]::ToInt32($([System.DateTime]::UtcNow.TimeOfDay.TotalSeconds))) + + $(VersionDate).$(VersionSeconds) + $(AssemblyVersion) + $(AssemblyVersion) + Copyright @ $([System.DateTime]::UtcNow.ToString("yyyy")) Azaion LLC. All rights reserved. + + MSBuild:Compile diff --git a/Azaion.Inference/azaion-inference.spec b/Azaion.Inference/azaion-inference.spec index 1b17195..c10262e 100644 --- a/Azaion.Inference/azaion-inference.spec +++ b/Azaion.Inference/azaion-inference.spec @@ -4,10 +4,8 @@ from PyInstaller.utils.hooks import collect_all datas = [('venv\\Lib\\site-packages\\cv2', 'cv2')] binaries = [] -hiddenimports = ['constants', 'annotation', 'credentials', 'file_data', 'user', 'security', 'secure_model', 'cdn_manager', 'api_client', 'hardware_service', 'remote_command', 'ai_config', 'tensorrt_engine', 'onnx_engine', 'inference_engine', 'inference', 'remote_command_handler'] +hiddenimports = ['constants', 'file_data', 'remote_command', 'remote_command_handler', 'annotation', 'loader_client', 'ai_config', 'tensorrt_engine', 'onnx_engine', 'inference_engine', 'inference', 'main-inf'] hiddenimports += collect_submodules('cv2') -tmp_ret = collect_all('requests') -datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] tmp_ret = collect_all('psutil') datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] tmp_ret = collect_all('msgpack') diff --git a/Azaion.Inference/build_inference.cmd b/Azaion.Inference/build_inference.cmd index 01b08de..6aff820 100644 --- a/Azaion.Inference/build_inference.cmd +++ b/Azaion.Inference/build_inference.cmd @@ -34,23 +34,29 @@ venv\Scripts\pyinstaller --name=azaion-inference ^ --collect-all pynvml ^ --collect-all jwt ^ --hidden-import constants ^ ---hidden-import annotation ^ +--hidden-import file_data ^ --hidden-import remote_command ^ +--hidden-import remote_command_handler ^ +--hidden-import annotation ^ +--hidden-import loader_client ^ --hidden-import ai_config ^ --hidden-import tensorrt_engine ^ --hidden-import onnx_engine ^ --hidden-import inference_engine ^ --hidden-import inference ^ ---hidden-import remote_command_handler ^ +--hidden-import main-inf ^ start.py -robocopy "dist\azaion-inference\_internal" "..\dist-azaion\_internal" "ai_config.cp312-win_amd64.pyd" "annotation.cp312-win_amd64.pyd" "api_client.cp312-win_amd64.pyd" /MOV -robocopy "dist\azaion-inference\_internal" "..\dist-azaion\_internal" "cdn_manager.cp312-win_amd64.pyd" "constants.cp312-win_amd64.pyd" "credentials.cp312-win_amd64.pyd" /MOV -robocopy "dist\azaion-inference\_internal" "..\dist-azaion\_internal" "file_data.cp312-win_amd64.pyd" "hardware_service.cp312-win_amd64.pyd" "inference.cp312-win_amd64.pyd" "inference_engine.cp312-win_amd64.pyd" /MOV -robocopy "dist\azaion-inference\_internal" "..\dist-azaion\_internal" "main.cp312-win_amd64.pyd" "onnx_engine.cp312-win_amd64.pyd" "remote_command.cp312-win_amd64.pyd" "remote_command_handler.cp312-win_amd64.pyd" /MOV -robocopy "dist\azaion-inference\_internal" "..\dist-azaion\_internal" "security.cp312-win_amd64.pyd" "tensorrt_engine.cp312-win_amd64.pyd" "user.cp312-win_amd64.pyd" /MOV +robocopy "dist\azaion-inference\_internal" "..\dist-azaion\_internal" "ai_config.cp312-win_amd64.pyd" "annotation.cp312-win_amd64.pyd" +robocopy "dist\azaion-inference\_internal" "..\dist-azaion\_internal" "constants.cp312-win_amd64.pyd" "file_data.cp312-win_amd64.pyd" +robocopy "dist\azaion-inference\_internal" "..\dist-azaion\_internal" "remote_command.cp312-win_amd64.pyd" "remote_command_handler.cp312-win_amd64.pyd" +robocopy "dist\azaion-inference\_internal" "..\dist-azaion\_internal" "inference.cp312-win_amd64.pyd" "inference_engine.cp312-win_amd64.pyd" +robocopy "dist\azaion-inference\_internal" "..\dist-azaion\_internal" "tensorrt_engine.cp312-win_amd64.pyd" "onnx_engine.cp312-win_amd64.pyd" "main_inference.cp312-win_amd64.pyd" -robocopy "dist\azaion-inference\_internal" "..\dist-dlls\_internal" /E /MOVE -robocopy "dist\azaion-inference" "..\dist-azaion" "azaion-inference.exe" /E /MOVE +robocopy "dist\azaion-inference\_internal" "..\dist-dlls\_internal" /E +robocopy "dist\azaion-inference" "..\dist-azaion" "azaion-inference.exe" /E + +REM copy for local run +robocopy "c:\share\" "dist\azaion-inference\_internal /E cd /d %CURRENT_DIR% diff --git a/Azaion.Inference/inference.pyx b/Azaion.Inference/inference.pyx index acf369d..2908c75 100644 --- a/Azaion.Inference/inference.pyx +++ b/Azaion.Inference/inference.pyx @@ -58,28 +58,39 @@ cdef class Inference: self.is_building_engine = False cdef build_tensor_engine(self, object updater_callback): - if not tensor_gpu_index == -1: + if tensor_gpu_index == -1: return - engine_filename = TensorRTEngine.get_engine_filename(0) - models_dir = constants.MODELS_FOLDER + try: + engine_filename = TensorRTEngine.get_engine_filename(0) + models_dir = constants.MODELS_FOLDER - self.is_building_engine = True - updater_callback('downloading') + self.is_building_engine = True + updater_callback('downloading') - if self.loader_client.load_big_small_resource(engine_filename, models_dir): - print('tensor rt engine is here, no need to build') + res = self.loader_client.load_big_small_resource(engine_filename, models_dir) + if res.err is None: + print('tensor rt engine is here, no need to build') + self.is_building_engine = False + return + + print(res.err) + # time.sleep(8) # prevent simultaneously loading dll and models + updater_callback('converting') + print('try to load onnx') + res = self.loader_client.load_big_small_resource(constants.AI_ONNX_MODEL_FILE, models_dir) + if res.err is not None: + updater_callback(f'Error. {res.err}') + model_bytes = TensorRTEngine.convert_from_onnx(res.data) + updater_callback('uploading') + res = self.loader_client.upload_big_small_resource(model_bytes, engine_filename, models_dir) + if res.err is not None: + updater_callback(f'Error. {res.err}') + print(f'uploaded {engine_filename} to CDN and API') self.is_building_engine = False - return - - # time.sleep(8) # prevent simultaneously loading dll and models - updater_callback('converting') - onnx_model = self.loader_client.load_big_small_resource(constants.AI_ONNX_MODEL_FILE, models_dir) - model_bytes = TensorRTEngine.convert_from_onnx(onnx_model) - updater_callback('uploading') - self.loader_client.upload_big_small_resource(model_bytes, engine_filename, models_dir) - print(f'uploaded {engine_filename} to CDN and API') - self.is_building_engine = False + updater_callback('enabled') + except Exception as e: + updater_callback(f'Error. {str(e)}') cdef init_ai(self): if self.engine is not None: diff --git a/Azaion.Inference/loader_client.pxd b/Azaion.Inference/loader_client.pxd index fe959fa..b5b16dc 100644 --- a/Azaion.Inference/loader_client.pxd +++ b/Azaion.Inference/loader_client.pxd @@ -1,7 +1,12 @@ from remote_command cimport RemoteCommand +cdef class LoadResult: + cdef public str err + cdef public bytes data + + cdef class LoaderClient: - cdef object _context + cdef object _loader_context cdef object _socket cdef RemoteCommand _send_receive_command(self, RemoteCommand command) @@ -10,4 +15,4 @@ cdef class LoaderClient: cdef upload_big_small_resource(self, bytes content, str filename, str directory) - cdef close(self) \ No newline at end of file + cdef stop(self) \ No newline at end of file diff --git a/Azaion.Inference/loader_client.pyx b/Azaion.Inference/loader_client.pyx index df297ea..e3d72a3 100644 --- a/Azaion.Inference/loader_client.pyx +++ b/Azaion.Inference/loader_client.pyx @@ -2,10 +2,15 @@ import zmq from remote_command cimport RemoteCommand, CommandType from file_data cimport FileData, UploadFileData +cdef class LoadResult: + def __init__(self, str err, bytes data=None): + self.err = err + self.data = data + cdef class LoaderClient: def __init__(self, str zmq_host, int zmq_port): - self._context = zmq.Context().instance() - self._socket = self._context.socket(zmq.DEALER) + self._loader_context = zmq.Context() + self._socket = self._loader_context.socket(zmq.DEALER) self._socket.connect(f'tcp://{zmq_host}:{zmq_port}') cdef RemoteCommand _send_receive_command(self, RemoteCommand command): @@ -16,24 +21,24 @@ cdef class LoaderClient: cdef FileData file_data = FileData(folder=directory, filename=filename) cdef RemoteCommand response = self._send_receive_command(RemoteCommand(CommandType.LOAD_BIG_SMALL, data=file_data.serialize())) if response.command_type == CommandType.DATA_BYTES: - return response.data + return LoadResult(None, response.data) elif response.command_type == CommandType.ERROR: - raise Exception(f"Error from server: {response.message}") + return LoadResult(f"Error from server: {response.message}") else: - raise Exception(f"Unexpected response command type: {response.command_type}") + return LoadResult(f"Unexpected response command type: {response.command_type}") cdef upload_big_small_resource(self, bytes content, str filename, str directory): cdef UploadFileData upload_file_data = UploadFileData(content, filename, directory) cdef RemoteCommand upload_resp = self._send_receive_command(RemoteCommand(CommandType.UPLOAD_BIG_SMALL, data=upload_file_data.serialize())) if upload_resp.command_type == CommandType.OK: - return + return LoadResult(None, None) elif upload_resp.command_type == CommandType.ERROR: - raise Exception(f"Error from server: {upload_resp.message}") + return LoadResult(f"Error from server: {upload_resp.message}") else: - raise Exception(f"Unexpected response command type: {upload_resp.command_type}") + return LoadResult(f"Unexpected response command type: {upload_resp.command_type}") - cdef close(self): + cdef stop(self): if self._socket and not self._socket.closed: self._socket.close() - if self._context and not self._context.closed: - self._context.term() \ No newline at end of file + if self._loader_context and not self._loader_context.closed: + self._loader_context.term() \ No newline at end of file diff --git a/Azaion.Inference/main.pyx b/Azaion.Inference/main_inference.pyx similarity index 88% rename from Azaion.Inference/main.pyx rename to Azaion.Inference/main_inference.pyx index f816108..9f25e09 100644 --- a/Azaion.Inference/main.pyx +++ b/Azaion.Inference/main_inference.pyx @@ -24,7 +24,6 @@ cdef class CommandProcessor: self.remote_handler.start() self.running = True self.loader_client = LoaderClient(loader_zmq_host, loader_zmq_port) - #TODO: replace api_client to azaion_loader.exe call self.inference = Inference(self.loader_client, self.on_annotation) def start(self): @@ -45,9 +44,8 @@ cdef class CommandProcessor: if command.command_type == CommandType.INFERENCE: self.inference_queue.put(command) elif command.command_type == CommandType.AI_AVAILABILITY_CHECK: - self.inference.build_tensor_engine(lambda status: self.remote_handler.send( - command.client_id, RemoteCommand(CommandType.AI_AVAILABILITY_RESULT, None, status).serialize())) - self.remote_handler.send(command.client_id, RemoteCommand(CommandType.AI_AVAILABILITY_RESULT, None, 'enabled').serialize()) + self.inference.build_tensor_engine(lambda status: self.remote_handler.send(command.client_id, + RemoteCommand(CommandType.AI_AVAILABILITY_RESULT, None, status).serialize())) elif command.command_type == CommandType.STOP_INFERENCE: self.inference.stop() elif command.command_type == CommandType.EXIT: @@ -65,4 +63,5 @@ cdef class CommandProcessor: def stop(self): self.inference.stop() self.remote_handler.stop() + self.loader_client.stop() self.running = False diff --git a/Azaion.Inference/remote_command_handler.pyx b/Azaion.Inference/remote_command_handler.pyx index 86877ed..884ce40 100644 --- a/Azaion.Inference/remote_command_handler.pyx +++ b/Azaion.Inference/remote_command_handler.pyx @@ -8,7 +8,7 @@ import yaml cdef class RemoteCommandHandler: def __init__(self, int zmq_port, object on_command): self._on_command = on_command - self._context = zmq.Context.instance() + self._context = zmq.Context() self._router = self._context.socket(zmq.ROUTER) self._router.setsockopt(zmq.LINGER, 0) @@ -83,6 +83,7 @@ cdef class RemoteCommandHandler: self._control.send(b"TERMINATE", flags=zmq.DONTWAIT) except zmq.error.ZMQError: pass + self._router.close(linger=0) self._dealer.close(linger=0) self._control.close(linger=0) @@ -90,5 +91,4 @@ cdef class RemoteCommandHandler: self._proxy_thread.join(timeout=2) while any(w.is_alive() for w in self._workers): time.sleep(0.1) - self._context.term() diff --git a/Azaion.Inference/setup.py b/Azaion.Inference/setup.py index 62ee10d..ba60517 100644 --- a/Azaion.Inference/setup.py +++ b/Azaion.Inference/setup.py @@ -4,17 +4,17 @@ import numpy as np extensions = [ Extension('constants', ['constants.pyx']), - Extension('annotation', ['annotation.pyx']), Extension('file_data', ['file_data.pyx']), - Extension('loader_client', ['loader_client.pyx']), Extension('remote_command', ['remote_command.pyx']), Extension('remote_command_handler', ['remote_command_handler.pyx']), + Extension('annotation', ['annotation.pyx']), + Extension('loader_client', ['loader_client.pyx']), Extension('ai_config', ['ai_config.pyx']), Extension('tensorrt_engine', ['tensorrt_engine.pyx'], include_dirs=[np.get_include()]), Extension('onnx_engine', ['onnx_engine.pyx'], include_dirs=[np.get_include()]), Extension('inference_engine', ['inference_engine.pyx'], include_dirs=[np.get_include()]), Extension('inference', ['inference.pyx'], include_dirs=[np.get_include()]), - Extension('main', ['main.pyx']), + Extension('main_inference', ['main_inference.pyx']), ] setup( diff --git a/Azaion.Inference/start.py b/Azaion.Inference/start.py index 0f4cd57..97bee35 100644 --- a/Azaion.Inference/start.py +++ b/Azaion.Inference/start.py @@ -1,4 +1,4 @@ -from main import CommandProcessor +from main_inference import CommandProcessor import argparse diff --git a/Azaion.Inference/token b/Azaion.Inference/token deleted file mode 100644 index 34fc187..0000000 --- a/Azaion.Inference/token +++ /dev/null @@ -1 +0,0 @@ -eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1laWQiOiI5N2U5MWI2OC1hNmRlLTQ3YTgtOTgzYi0xOTU3YzViNDQ2MTkiLCJ1bmlxdWVfbmFtZSI6ImFkbWluLXJlbW90ZUBhemFpb24uY29tIiwicm9sZSI6IkFwaUFkbWluIiwibmJmIjoxNzM5MzUxNDEwLCJleHAiOjE3MzkzNjU4MTAsImlhdCI6MTczOTM1MTQxMCwiaXNzIjoiQXphaW9uQXBpIiwiYXVkIjoiQW5ub3RhdG9ycy9PcmFuZ2VQaS9BZG1pbnMifQ.P32xRe6nk-0u2jjBi3rdsd3YwlmGXL0NX_eE2xb7OUI \ No newline at end of file diff --git a/Azaion.Loader/api_client.pyx b/Azaion.Loader/api_client.pyx index 9c9ba2a..6c537c6 100644 --- a/Azaion.Loader/api_client.pyx +++ b/Azaion.Loader/api_client.pyx @@ -143,8 +143,9 @@ cdef class ApiClient: if self.cdn_manager.download(folder, big_part): with open(path.join( folder, big_part), 'rb') as binary_file: encrypted_bytes_big = binary_file.read() + # return encrypted_bytes_big else: - return None + raise Exception(f'Cannot download file {folder}\\{big_part} from CDN!') cdef load_big_small_resource(self, str resource_name, str folder): cdef str big_part = f'{resource_name}.big' diff --git a/Azaion.Loader/build_loader.cmd b/Azaion.Loader/build_loader.cmd index 36e006b..abf8573 100644 --- a/Azaion.Loader/build_loader.cmd +++ b/Azaion.Loader/build_loader.cmd @@ -8,6 +8,7 @@ echo remove dist folder: if exist dist rmdir dist /s /q if exist build rmdir build /s /q + echo install python and dependencies if not exist venv ( python -m venv venv @@ -39,4 +40,15 @@ venv\Scripts\pyinstaller --name=azaion-loader ^ --hidden-import credentials ^ --hidden-import api_client ^ --hidden-import hardware_service ^ -start.py \ No newline at end of file +start.py + + +robocopy "dist\azaion-loader\_internal" "..\dist-azaion\_internal" "security.cp312-win_amd64.pyd" "cdn_manager.cp312-win_amd64.pyd" +robocopy "dist\azaion-loader\_internal" "..\dist-azaion\_internal" "credentials.cp312-win_amd64.pyd" "api_client.cp312-win_amd64.pyd" +robocopy "dist\azaion-loader\_internal" "..\dist-azaion\_internal" "hardware_service.cp312-win_amd64.pyd" "user.cp312-win_amd64.pyd" +robocopy "dist\azaion-loader\_internal" "..\dist-azaion\_internal" "main_loader.cp312-win_amd64.pyd" + +robocopy "dist\azaion-loader\_internal" "..\dist-dlls\_internal" /E +robocopy "dist\azaion-loader" "..\dist-azaion" "azaion-loader.exe" /E + +cd /d %CURRENT_DIR% \ No newline at end of file diff --git a/Azaion.Loader/cdn_manager.pyx b/Azaion.Loader/cdn_manager.pyx index 5c0fc01..fb02dec 100644 --- a/Azaion.Loader/cdn_manager.pyx +++ b/Azaion.Loader/cdn_manager.pyx @@ -1,4 +1,6 @@ import io +import os + import boto3 @@ -33,8 +35,9 @@ cdef class CDNManager: cdef download(self, str folder, str filename): try: + os.makedirs(folder, exist_ok=True) self.download_client.download_file(folder, filename, f'{folder}\\{filename}') - print(f'downloaded {filename} from the {folder} to current folder') + print(f'downloaded {filename} from the {folder}') return True except Exception as e: print(e) diff --git a/Azaion.Loader/main.pyx b/Azaion.Loader/main_loader.pyx similarity index 95% rename from Azaion.Loader/main.pyx rename to Azaion.Loader/main_loader.pyx index d2085dd..3368066 100644 --- a/Azaion.Loader/main.pyx +++ b/Azaion.Loader/main_loader.pyx @@ -55,6 +55,9 @@ cdef class CommandProcessor: data = UploadFileData.from_msgpack(command.data) file_bytes = self.api_client.upload_big_small_resource(data.resource, data.filename, data.folder) self.remote_handler.send(command.client_id, RemoteCommand(CommandType.OK).serialize()) + elif command.command_type == CommandType.EXIT: + t = Thread(target=self.stop) # non-block worker: + t.start() else: pass except Exception as e: diff --git a/Azaion.Loader/setup.py b/Azaion.Loader/setup.py index acce980..f6fe08c 100644 --- a/Azaion.Loader/setup.py +++ b/Azaion.Loader/setup.py @@ -3,16 +3,16 @@ from Cython.Build import cythonize extensions = [ Extension('constants', ['constants.pyx']), - Extension('credentials', ['credentials.pyx']), Extension('file_data', ['file_data.pyx']), - Extension('hardware_service', ['hardware_service.pyx'], extra_compile_args=["-g"], extra_link_args=["-g"]), - Extension('security', ['security.pyx']), Extension('remote_command', ['remote_command.pyx']), Extension('remote_command_handler', ['remote_command_handler.pyx']), + Extension('credentials', ['credentials.pyx']), + Extension('hardware_service', ['hardware_service.pyx'], extra_compile_args=["-g"], extra_link_args=["-g"]), + Extension('security', ['security.pyx']), Extension('user', ['user.pyx']), Extension('cdn_manager', ['cdn_manager.pyx']), Extension('api_client', ['api_client.pyx']), - Extension('main', ['main.pyx']), + Extension('main_loader', ['main_loader.pyx']), ] setup( @@ -21,7 +21,7 @@ setup( extensions, compiler_directives={ "language_level": 3, - "emit_code_comments" : False, + "emit_code_comments": False, "binding": True, 'boundscheck': False, 'wraparound': False diff --git a/Azaion.Loader/start.py b/Azaion.Loader/start.py index b2d033f..5187220 100644 --- a/Azaion.Loader/start.py +++ b/Azaion.Loader/start.py @@ -1,4 +1,4 @@ -from main import CommandProcessor +from main_loader import CommandProcessor import argparse diff --git a/Azaion.LoaderUI/App.xaml.cs b/Azaion.LoaderUI/App.xaml.cs index 6ead66e..176608b 100644 --- a/Azaion.LoaderUI/App.xaml.cs +++ b/Azaion.LoaderUI/App.xaml.cs @@ -1,10 +1,18 @@ using System.Windows; +using Azaion.CommonSecurity; +using Azaion.CommonSecurity.Services; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; using Serilog; namespace Azaion.LoaderUI; public partial class App { + private LoaderClient _loaderClient = null!; + private readonly CancellationTokenSource _loaderUITokenSource = new(); + protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); @@ -22,5 +30,30 @@ public partial class App rollingInterval: RollingInterval.Day) .CreateLogger(); + var initConfig = SecurityConstants.ReadInitConfig(); + _loaderClient = new LoaderClient(initConfig.LoaderClientConfig, Log.Logger, _loaderUITokenSource.Token); + _loaderClient.StartClient(); + _loaderClient.Connect(); + + var host = Host.CreateDefaultBuilder() + .ConfigureAppConfiguration((_, config) => config + .AddCommandLine(Environment.GetCommandLineArgs()) + .AddJsonFile(SecurityConstants.CONFIG_PATH, optional: true, reloadOnChange: true)) + .UseSerilog() + .ConfigureServices((context, services) => + { + services.AddSingleton(); + }) + .Build(); + host.Start(); + + host.Services.GetRequiredService().Show(); } -} \ No newline at end of file + + + + //AFter: + //_loaderClient.Login(credentials); + //_loaderClient.Dispose(); +} + diff --git a/Azaion.LoaderUI/Login.xaml.cs b/Azaion.LoaderUI/Login.xaml.cs index d154f12..20dd6d7 100644 --- a/Azaion.LoaderUI/Login.xaml.cs +++ b/Azaion.LoaderUI/Login.xaml.cs @@ -1,4 +1,5 @@ -using System.Windows; +using System.Diagnostics; +using System.Windows; using System.Windows.Controls; using System.Windows.Input; using Azaion.CommonSecurity.DTO; @@ -7,8 +8,6 @@ namespace Azaion.LoaderUI; public partial class Login { - public bool MainSuiteOpened { get; set; } = false; - public Login() { InitializeComponent(); @@ -18,7 +17,7 @@ public partial class Login { LoginBtn.Cursor = Cursors.Wait; Cursor = Cursors.Wait; - MainSuiteOpened = true; + Process.Start("Azaion.Suite.exe", $"-e {TbEmail.Text} -p {TbPassword.Password}"); Close(); } diff --git a/Azaion.Suite/App.xaml.cs b/Azaion.Suite/App.xaml.cs index 794781f..f2625de 100644 --- a/Azaion.Suite/App.xaml.cs +++ b/Azaion.Suite/App.xaml.cs @@ -13,7 +13,6 @@ using Azaion.Common.Extensions; using Azaion.Common.Services; using Azaion.CommonSecurity; using Azaion.CommonSecurity.DTO; -using Azaion.CommonSecurity.DTO.Commands; using Azaion.CommonSecurity.Services; using Azaion.Dataset; using CommandLine; @@ -35,7 +34,7 @@ public partial class App private FormState _formState = null!; private IHost _host = null!; private static readonly Guid KeyPressTaskId = Guid.NewGuid(); - + private LoaderClient _loaderClient = null!; private readonly ICache _cache = new MemoryCache(); private readonly CancellationTokenSource _mainCTokenSource = new(); @@ -65,25 +64,13 @@ public partial class App private void ErrorHandling(IEnumerable obj) { - Log.Fatal($"Error happened: {string.Join(",", obj.Select(x => x.Tag))}"); - } - - private static InitConfig ReadInitConfig() - { - try + Log.Fatal($"Error happened: {string.Join(",", obj.Select(x => { - if (!File.Exists(SecurityConstants.CONFIG_PATH)) - throw new FileNotFoundException(SecurityConstants.CONFIG_PATH); - var configStr = File.ReadAllText(SecurityConstants.CONFIG_PATH); - var config = JsonConvert.DeserializeObject(configStr); - - return config ?? SecurityConstants.DefaultInitConfig; - } - catch (Exception e) - { - Console.WriteLine(e); - return SecurityConstants.DefaultInitConfig; - } + if (x is MissingRequiredOptionError err) + return $"{err.Tag} {err.NameInfo.NameText}"; + return x.Tag.ToString(); + } ))}"); + Current.Shutdown(); } private Stream GetSystemConfig(LoaderClient loaderClient, string apiDir) @@ -120,15 +107,15 @@ public partial class App private void Start(ApiCredentials credentials) { new ConfigUpdater().CheckConfig(); - var initConfig = ReadInitConfig(); + var initConfig = SecurityConstants.ReadInitConfig(); var apiDir = initConfig.DirectoriesConfig.ApiResourcesDirectory; - var loaderClient = new LoaderClient(initConfig.LoaderClientConfig, Log.Logger, _mainCTokenSource.Token); + _loaderClient = new LoaderClient(initConfig.LoaderClientConfig, Log.Logger, _mainCTokenSource.Token); #if DEBUG - loaderClient.StartClient(); + _loaderClient.StartClient(); #endif - loaderClient.Connect(); //Client app should be already started by LoaderUI - loaderClient.Login(credentials); + _loaderClient.Connect(); //Client app should be already started by LoaderUI + _loaderClient.Login(credentials); var azaionApi = new AzaionApi(new HttpClient { BaseAddress = new Uri(initConfig.InferenceClientConfig.ApiUrl) }, _cache, credentials); @@ -136,8 +123,8 @@ public partial class App .ConfigureAppConfiguration((_, config) => config .AddCommandLine(Environment.GetCommandLineArgs()) .AddJsonFile(SecurityConstants.CONFIG_PATH, optional: true, reloadOnChange: true) - .AddJsonStream(GetSystemConfig(loaderClient, apiDir)) - .AddJsonStream(GetSecuredConfig(loaderClient, apiDir))) + .AddJsonStream(GetSystemConfig(_loaderClient, apiDir)) + .AddJsonStream(GetSecuredConfig(_loaderClient, apiDir))) .UseSerilog() .ConfigureServices((context, services) => { @@ -155,7 +142,7 @@ public partial class App #region External Services services.ConfigureSection(context.Configuration); - services.AddSingleton(loaderClient); + services.AddSingleton(_loaderClient); services.ConfigureSection(context.Configuration); services.AddSingleton(); @@ -226,6 +213,8 @@ public partial class App protected override async void OnExit(ExitEventArgs e) { base.OnExit(e); + _loaderClient.Stop(); + _loaderClient.Dispose(); await _host.StopAsync(); } } \ No newline at end of file diff --git a/Azaion.Suite/Azaion.Suite.csproj b/Azaion.Suite/Azaion.Suite.csproj index 9af9aa0..b5b86ba 100644 --- a/Azaion.Suite/Azaion.Suite.csproj +++ b/Azaion.Suite/Azaion.Suite.csproj @@ -11,6 +11,16 @@ true + + $([System.DateTime]::UtcNow.ToString("yyyy.MM.dd")) + $([System.Convert]::ToInt32($([System.DateTime]::UtcNow.TimeOfDay.TotalSeconds))) + + $(VersionDate).$(VersionSeconds) + $(AssemblyVersion) + $(AssemblyVersion) + Copyright @ $([System.DateTime]::UtcNow.ToString("yyyy")) Azaion LLC. All rights reserved. + + @@ -53,4 +63,21 @@ PreserveNewest + + + + + $(SolutionDir)Azaion.LoaderUI\bin\$(Configuration)\$(TargetFramework)\ + + + + + + + + + + + + diff --git a/Azaion.Suite/build_loader_inf.cmd b/Azaion.Suite/build_loader_inf.cmd new file mode 100644 index 0000000..be08122 --- /dev/null +++ b/Azaion.Suite/build_loader_inf.cmd @@ -0,0 +1,3 @@ +call ..\Azaion.Inference\build_inference +call ..\Azaion.Loader\build_loader +call copy_loader_inf \ No newline at end of file diff --git a/Azaion.Suite/copy_inf_gps.cmd b/Azaion.Suite/copy_gps_denied.cmd similarity index 63% rename from Azaion.Suite/copy_inf_gps.cmd rename to Azaion.Suite/copy_gps_denied.cmd index 9d6b762..cead2c9 100644 --- a/Azaion.Suite/copy_inf_gps.cmd +++ b/Azaion.Suite/copy_gps_denied.cmd @@ -1,13 +1,3 @@ -rem Inference - -set INFERENCE_PATH=%cd%\..\Azaion.Inference -xcopy /E /Y %INFERENCE_PATH%\dist\azaion-inference %SUITE_FOLDER% -copy %INFERENCE_PATH%\venv\Lib\site-packages\tensorrt_libs\nvinfer_10.dll %SUITE_FOLDER% -copy %INFERENCE_PATH%\venv\Lib\site-packages\tensorrt_libs\nvinfer_plugin_10.dll %SUITE_FOLDER% -copy %INFERENCE_PATH%\venv\Lib\site-packages\tensorrt_libs\nvonnxparser_10.dll %SUITE_FOLDER% -copy %INFERENCE_PATH%\config.yaml %SUITE_FOLDER% - -rem Gps Denied set DESTINATION=%SUITE_FOLDER%\gps-denied set GPS_DENIED=%cd%\..\..\gps-denied\ diff --git a/Azaion.Suite/copy_loader_inf.cmd b/Azaion.Suite/copy_loader_inf.cmd new file mode 100644 index 0000000..9c712f2 --- /dev/null +++ b/Azaion.Suite/copy_loader_inf.cmd @@ -0,0 +1,13 @@ +echo Build Cython app +set CURRENT_DIR=%cd% + +REM Change to the parent directory of the current location +cd /d %~dp0 + + +robocopy "..\dist-azaion\_internal" "bin\Debug\net8.0-windows\_internal" /E +robocopy "..\dist-dlls\_internal" "bin\Debug\net8.0-windows\_internal" /E + +robocopy "..\dist-azaion" "bin\Debug\net8.0-windows" "azaion-inference.exe" "azaion-loader.exe" + +cd /d %CURRENT_DIR% \ No newline at end of file diff --git a/build/build_dotnet.cmd b/build/build_dotnet.cmd index c0302c6..9119ae1 100644 --- a/build/build_dotnet.cmd +++ b/build/build_dotnet.cmd @@ -2,22 +2,20 @@ echo Build .net app set CURRENT_DIR=%cd% cd /d %~dp0.. -dotnet build -c Release - cd Azaion.Suite -call postbuild.cmd Release -call upload-file %cd%\config.secured.json -call upload-file %cd%\config.system.json - -dotnet publish -r win-x64 -p:SatelliteResourceLanguages="en" -p:DebugSymbols=false -p:ForPublish=true --self-contained true +dotnet publish -c Release -r win-x64 -p:SatelliteResourceLanguages="en" -p:DebugSymbols=false -p:ForPublish=true --self-contained true +cd ..\Azaion.LoaderUI +dotnet publish -c Release -r win-x64 -p:SatelliteResourceLanguages="en" -p:DebugSymbols=false -p:ForPublish=true --self-contained true cd .. xcopy Azaion.Suite\bin\Release\net8.0-windows\win-x64\publish dist\ /s /e /q del dist\config.json move dist\config.production.json dist\config.json -robocopy "dist" "dist-azaion" "Azaion.Annotator.dll" "Azaion.Dataset.dll" "Azaion.Common.dll" "Azaion.CommonSecurity.dll" /MOV -robocopy "dist" "dist-azaion" "Azaion.Suite.deps.json" "Azaion.Suite.dll" "Azaion.Suite.exe" "Azaion.Suite.runtimeconfig.json" "config.json" "logo.png" /MOV +robocopy "dist" "dist-azaion" "Azaion.Annotator.dll" "Azaion.Dataset.dll" "Azaion.Common.dll" "Azaion.CommonSecurity.dll" "Azaion.Suite.dll" "Azaion.Suite.exe" /MOV +robocopy "dist" "dist-azaion" "Azaion.Suite.runtimeconfig.json" "Azaion.Suite.deps.json" "config.json" "logo.png" /MOV +robocopy "dist" "dist-azaion" "Azaion.LoaderUI.exe" "Azaion.LoaderUI.runtimeconfig.json" "Azaion.Suite.deps.json" "config.json" "logo.png" /MOV + if exist dist\libvlc\win-x86 rmdir dist\libvlc\win-x86 /s /q robocopy "dist" "dist-dlls" /E /MOVE