mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 22:26:31 +00:00
add azaion loader
This commit is contained in:
@@ -12,19 +12,12 @@
|
|||||||
<PackageReference Include="libc.translation" Version="7.1.1" />
|
<PackageReference Include="libc.translation" Version="7.1.1" />
|
||||||
<PackageReference Include="LibVLCSharp" Version="3.9.1" />
|
<PackageReference Include="LibVLCSharp" Version="3.9.1" />
|
||||||
<PackageReference Include="LibVLCSharp.WPF" Version="3.9.1" />
|
<PackageReference Include="LibVLCSharp.WPF" Version="3.9.1" />
|
||||||
<PackageReference Include="MediatR" Version="12.4.1" />
|
<PackageReference Include="MediatR" Version="12.5.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.3" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="RangeTree" Version="3.0.1" />
|
<PackageReference Include="RangeTree" Version="3.0.1" />
|
||||||
<PackageReference Include="Serilog" Version="4.0.0" />
|
|
||||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.1" />
|
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
|
||||||
<PackageReference Include="SkiaSharp" Version="2.88.9" />
|
<PackageReference Include="SkiaSharp" Version="2.88.9" />
|
||||||
<PackageReference Include="System.Data.SQLite" Version="1.0.119" />
|
<PackageReference Include="System.Data.SQLite" Version="1.0.119" />
|
||||||
<PackageReference Include="System.Data.SQLite.EF6" Version="1.0.119" />
|
<PackageReference Include="System.Data.SQLite.EF6" Version="1.0.119" />
|
||||||
|
|||||||
@@ -9,12 +9,12 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CsvHelper" Version="33.0.1" />
|
<PackageReference Include="CsvHelper" Version="33.0.1" />
|
||||||
<PackageReference Include="linq2db.SQLite" Version="5.4.1" />
|
<PackageReference Include="linq2db.SQLite" Version="5.4.1" />
|
||||||
<PackageReference Include="MediatR" Version="12.4.1" />
|
<PackageReference Include="MediatR" Version="12.5.0" />
|
||||||
<PackageReference Include="MessagePack" Version="3.1.0" />
|
<PackageReference Include="MessagePack" Version="3.1.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="9.0.5" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="Polly" Version="8.5.2" />
|
<PackageReference Include="Polly" Version="8.5.2" />
|
||||||
<PackageReference Include="RabbitMQ.Stream.Client" Version="1.8.9" />
|
<PackageReference Include="RabbitMQ.Stream.Client" Version="1.8.9" />
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ public class GpsMatcherClient : IGpsMatcherClient
|
|||||||
if (response != "OK")
|
if (response != "OK")
|
||||||
{
|
{
|
||||||
_logger.LogError(response);
|
_logger.LogError(response);
|
||||||
await _mediator.Publish(new SetStatusTextEvent(response, true));
|
await _mediator.Publish(new SetStatusTextEvent(response ?? "", true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,15 +7,17 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageReference Include="LazyCache.AspNetCore" Version="2.4.0" />
|
<PackageReference Include="LazyCache.AspNetCore" Version="2.4.0" />
|
||||||
<PackageReference Include="MediatR" Version="12.4.1" />
|
<PackageReference Include="MediatR" Version="12.5.0" />
|
||||||
<PackageReference Include="MessagePack" Version="3.1.0" />
|
<PackageReference Include="MessagePack" Version="3.1.0" />
|
||||||
<PackageReference Include="MessagePack.Annotations" Version="3.1.0" />
|
<PackageReference Include="MessagePack.Annotations" Version="3.1.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Options" Version="9.0.5" />
|
||||||
<PackageReference Include="NetMQ" Version="4.0.1.13" />
|
<PackageReference Include="NetMQ" Version="4.0.1.13" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
<PackageReference Include="Serilog" Version="4.2.0" />
|
||||||
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.3.0" />
|
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
using MessagePack;
|
using CommandLine;
|
||||||
|
using MessagePack;
|
||||||
|
|
||||||
namespace Azaion.CommonSecurity.DTO;
|
namespace Azaion.CommonSecurity.DTO;
|
||||||
|
|
||||||
[MessagePackObject]
|
[MessagePackObject]
|
||||||
public class ApiCredentials(string email, string password) : EventArgs
|
public class ApiCredentials : EventArgs
|
||||||
{
|
{
|
||||||
[Key(nameof(Email))]
|
[Key(nameof(Email))]
|
||||||
public string Email { get; set; } = email;
|
[Option('e', "email", Required = true, HelpText = "User Email")]
|
||||||
|
public string Email { get; set; } = null!;
|
||||||
|
|
||||||
[Key(nameof(Password))]
|
[Key(nameof(Password))]
|
||||||
public string Password { get; set; } = password;
|
[Option('p', "pass", Required = true, HelpText = "User Password")]
|
||||||
|
public string Password { get; set; } = null!;
|
||||||
}
|
}
|
||||||
@@ -4,8 +4,11 @@ public abstract class ExternalClientConfig
|
|||||||
{
|
{
|
||||||
public string ZeroMqHost { get; set; } = "";
|
public string ZeroMqHost { get; set; } = "";
|
||||||
public int ZeroMqPort { get; set; }
|
public int ZeroMqPort { get; set; }
|
||||||
public double OneTryTimeoutSeconds { get; set; }
|
}
|
||||||
public int RetryCount {get;set;}
|
|
||||||
|
public class LoaderClientConfig : ExternalClientConfig
|
||||||
|
{
|
||||||
|
public string ApiUrl { get; set; } = null!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class InferenceClientConfig : ExternalClientConfig
|
public class InferenceClientConfig : ExternalClientConfig
|
||||||
|
|||||||
+2
-1
@@ -1,7 +1,8 @@
|
|||||||
namespace Azaion.CommonSecurity.DTO;
|
namespace Azaion.CommonSecurity.DTO;
|
||||||
|
|
||||||
public class SecureAppConfig
|
public class InitConfig
|
||||||
{
|
{
|
||||||
|
public LoaderClientConfig LoaderClientConfig { get; set; } = null!;
|
||||||
public InferenceClientConfig InferenceClientConfig { get; set; } = null!;
|
public InferenceClientConfig InferenceClientConfig { get; set; } = null!;
|
||||||
public GpsDeniedClientConfig GpsDeniedClientConfig { get; set; } = null!;
|
public GpsDeniedClientConfig GpsDeniedClientConfig { get; set; } = null!;
|
||||||
public DirectoriesConfig DirectoriesConfig { get; set; } = null!;
|
public DirectoriesConfig DirectoriesConfig { get; set; } = null!;
|
||||||
@@ -8,8 +8,14 @@ public class SecurityConstants
|
|||||||
|
|
||||||
public const string DUMMY_DIR = "dummy";
|
public const string DUMMY_DIR = "dummy";
|
||||||
|
|
||||||
|
private const string DEFAULT_API_URL = "https://api.azaion.com";
|
||||||
|
|
||||||
#region ExternalClientsConfig
|
#region ExternalClientsConfig
|
||||||
|
|
||||||
|
private const string DEFAULT_ZMQ_LOADER_HOST = "127.0.0.1";
|
||||||
|
private const int DEFAULT_ZMQ_LOADER_PORT = 5025;
|
||||||
|
|
||||||
|
public const string EXTERNAL_LOADER_PATH = "azaion-loader.exe";
|
||||||
public const string EXTERNAL_INFERENCE_PATH = "azaion-inference.exe";
|
public const string EXTERNAL_INFERENCE_PATH = "azaion-inference.exe";
|
||||||
public const string EXTERNAL_GPS_DENIED_FOLDER = "gps-denied";
|
public const string EXTERNAL_GPS_DENIED_FOLDER = "gps-denied";
|
||||||
public static readonly string ExternalGpsDeniedPath = Path.Combine(EXTERNAL_GPS_DENIED_FOLDER, "image-matcher.exe");
|
public static readonly string ExternalGpsDeniedPath = Path.Combine(EXTERNAL_GPS_DENIED_FOLDER, "image-matcher.exe");
|
||||||
@@ -20,9 +26,6 @@ public class SecurityConstants
|
|||||||
public const string DEFAULT_ZMQ_GPS_DENIED_HOST = "127.0.0.1";
|
public const string DEFAULT_ZMQ_GPS_DENIED_HOST = "127.0.0.1";
|
||||||
public const int DEFAULT_ZMQ_GPS_DENIED_PORT = 5227;
|
public const int DEFAULT_ZMQ_GPS_DENIED_PORT = 5227;
|
||||||
|
|
||||||
public const int DEFAULT_RETRY_COUNT = 25;
|
|
||||||
public const int DEFAULT_TIMEOUT_SECONDS = 5;
|
|
||||||
|
|
||||||
# region Cache keys
|
# region Cache keys
|
||||||
|
|
||||||
public const string CURRENT_USER_CACHE_KEY = "CurrentUser";
|
public const string CURRENT_USER_CACHE_KEY = "CurrentUser";
|
||||||
@@ -30,21 +33,24 @@ public class SecurityConstants
|
|||||||
|
|
||||||
# endregion
|
# endregion
|
||||||
|
|
||||||
public static readonly SecureAppConfig DefaultSecureAppConfig = new()
|
public static readonly InitConfig DefaultInitConfig = new()
|
||||||
{
|
{
|
||||||
|
LoaderClientConfig = new LoaderClientConfig
|
||||||
|
{
|
||||||
|
ZeroMqHost = DEFAULT_ZMQ_LOADER_HOST,
|
||||||
|
ZeroMqPort = DEFAULT_ZMQ_LOADER_PORT,
|
||||||
|
ApiUrl = DEFAULT_API_URL
|
||||||
|
},
|
||||||
InferenceClientConfig = new InferenceClientConfig
|
InferenceClientConfig = new InferenceClientConfig
|
||||||
{
|
{
|
||||||
ZeroMqHost = DEFAULT_ZMQ_INFERENCE_HOST,
|
ZeroMqHost = DEFAULT_ZMQ_INFERENCE_HOST,
|
||||||
ZeroMqPort = DEFAULT_ZMQ_INFERENCE_PORT,
|
ZeroMqPort = DEFAULT_ZMQ_INFERENCE_PORT,
|
||||||
OneTryTimeoutSeconds = DEFAULT_TIMEOUT_SECONDS,
|
ApiUrl = DEFAULT_API_URL
|
||||||
RetryCount = DEFAULT_RETRY_COUNT
|
|
||||||
},
|
},
|
||||||
GpsDeniedClientConfig = new GpsDeniedClientConfig
|
GpsDeniedClientConfig = new GpsDeniedClientConfig
|
||||||
{
|
{
|
||||||
ZeroMqHost = DEFAULT_ZMQ_GPS_DENIED_HOST,
|
ZeroMqHost = DEFAULT_ZMQ_GPS_DENIED_HOST,
|
||||||
ZeroMqPort = DEFAULT_ZMQ_GPS_DENIED_PORT,
|
ZeroMqPort = DEFAULT_ZMQ_GPS_DENIED_PORT
|
||||||
OneTryTimeoutSeconds = DEFAULT_TIMEOUT_SECONDS,
|
|
||||||
RetryCount = DEFAULT_RETRY_COUNT,
|
|
||||||
},
|
},
|
||||||
DirectoriesConfig = new DirectoriesConfig
|
DirectoriesConfig = new DirectoriesConfig
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Text;
|
||||||
using Azaion.CommonSecurity.DTO;
|
using Azaion.CommonSecurity.DTO;
|
||||||
using MediatR;
|
using Azaion.CommonSecurity.DTO.Commands;
|
||||||
using Microsoft.Extensions.Logging;
|
using MessagePack;
|
||||||
using Microsoft.Extensions.Options;
|
using NetMQ;
|
||||||
|
using NetMQ.Sockets;
|
||||||
|
using Serilog;
|
||||||
|
using Exception = System.Exception;
|
||||||
|
|
||||||
namespace Azaion.CommonSecurity.Services;
|
namespace Azaion.CommonSecurity.Services;
|
||||||
|
|
||||||
public class LoaderClient
|
public class LoaderClient(LoaderClientConfig config, ILogger logger, CancellationToken ct = default)
|
||||||
{
|
{
|
||||||
private readonly IMediator _mediator;
|
private readonly DealerSocket _dealer = new();
|
||||||
private readonly ILogger<LoaderClient> _logger;
|
private readonly Guid _clientId = Guid.NewGuid();
|
||||||
|
|
||||||
public LoaderClient(IMediator mediator, IOptions<LoaderClientConfig> config, ILogger<LoaderClient> logger)
|
public void StartClient()
|
||||||
{
|
{
|
||||||
_mediator = mediator;
|
|
||||||
_logger = logger;
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using var process = new Process();
|
using var process = new Process();
|
||||||
process.StartInfo = new ProcessStartInfo
|
process.StartInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
FileName = SecurityConstants.LoaderPath,
|
FileName = SecurityConstants.EXTERNAL_LOADER_PATH,
|
||||||
Arguments = $"--port {config.Value.ZeroMqPort} --api {config.Value.ApiUrl}",
|
Arguments = $"--port {config.ZeroMqPort} --api {config.ApiUrl}",
|
||||||
//RedirectStandardOutput = true,
|
CreateNoWindow = true
|
||||||
//RedirectStandardError = true,
|
|
||||||
//CreateNoWindow = true
|
|
||||||
};
|
};
|
||||||
|
|
||||||
process.OutputDataReceived += (_, e) => { if (e.Data != null) Console.WriteLine(e.Data); };
|
process.OutputDataReceived += (_, e) => { if (e.Data != null) Console.WriteLine(e.Data); };
|
||||||
@@ -33,19 +33,44 @@ public class LoaderClient
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Console.WriteLine(e);
|
logger.Error(e.Message);
|
||||||
//throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_requestAddress = $"tcp://{gpsConfig.Value.ZeroMqHost}:{gpsConfig.Value.ZeroMqPort}";
|
|
||||||
_requestSocket.Connect(_requestAddress);
|
public void Connect()
|
||||||
|
{
|
||||||
_subscriberAddress = $"tcp://{gpsConfig.Value.ZeroMqHost}:{gpsConfig.Value.ZeroMqReceiverPort}";
|
_dealer.Options.Identity = Encoding.UTF8.GetBytes(_clientId.ToString("N"));
|
||||||
_subscriberSocket.Connect(_subscriberAddress);
|
_dealer.Connect($"tcp://{config.ZeroMqHost}:{config.ZeroMqPort}");
|
||||||
_subscriberSocket.Subscribe("");
|
}
|
||||||
_subscriberSocket.ReceiveReady += async (sender, e) => await ProcessClientCommand(sender, e);
|
|
||||||
|
public void Send(RemoteCommand command) =>
|
||||||
_poller.Add(_subscriberSocket);
|
_dealer.SendFrame(MessagePackSerializer.Serialize(command));
|
||||||
_poller.RunAsync();
|
|
||||||
|
public MemoryStream LoadFile(string filename, string folder)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Send(RemoteCommand.Create(CommandType.Load, new LoadFileData(filename, folder)));
|
||||||
|
|
||||||
|
var retries = 10;
|
||||||
|
var tryNum = 0;
|
||||||
|
while (!ct.IsCancellationRequested && tryNum++ < retries)
|
||||||
|
{
|
||||||
|
if (!_dealer.TryReceiveFrameBytes(TimeSpan.FromMilliseconds(150), out var bytes))
|
||||||
|
continue;
|
||||||
|
var resultCommand = MessagePackSerializer.Deserialize<RemoteCommand>(bytes, cancellationToken: ct);
|
||||||
|
if (resultCommand.Data?.Length == 0)
|
||||||
|
throw new Exception($"Can't load {filename}. Returns 0 bytes");
|
||||||
|
return new MemoryStream(resultCommand.Data!);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception($"Can't load file {filename} after {retries} retries");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
logger.Error(e, e.Message);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,8 +16,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="9.0.5" />
|
||||||
<PackageReference Include="ScottPlot.WPF" Version="5.0.46" />
|
<PackageReference Include="ScottPlot.WPF" Version="5.0.46" />
|
||||||
<PackageReference Include="VirtualizingWrapPanel" Version="2.1.0" />
|
<PackageReference Include="VirtualizingWrapPanel" Version="2.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ tmp_ret = collect_all('pycuda')
|
|||||||
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
||||||
tmp_ret = collect_all('pynvml')
|
tmp_ret = collect_all('pynvml')
|
||||||
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
||||||
tmp_ret = collect_all('boto3')
|
|
||||||
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
|
||||||
tmp_ret = collect_all('jwt')
|
tmp_ret = collect_all('jwt')
|
||||||
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ venv\Scripts\pyinstaller --name=azaion-inference ^
|
|||||||
--collect-all tensorrt ^
|
--collect-all tensorrt ^
|
||||||
--collect-all pycuda ^
|
--collect-all pycuda ^
|
||||||
--collect-all pynvml ^
|
--collect-all pynvml ^
|
||||||
--collect-all boto3 ^
|
|
||||||
--collect-all jwt ^
|
--collect-all jwt ^
|
||||||
--hidden-import constants ^
|
--hidden-import constants ^
|
||||||
--hidden-import annotation ^
|
--hidden-import annotation ^
|
||||||
|
|||||||
@@ -2,12 +2,7 @@ import time
|
|||||||
|
|
||||||
cdef str CONFIG_FILE = "config.yaml" # Port for the zmq
|
cdef str CONFIG_FILE = "config.yaml" # Port for the zmq
|
||||||
|
|
||||||
cdef int QUEUE_MAXSIZE = 1000 # Maximum size of the command queue
|
|
||||||
cdef str COMMANDS_QUEUE = "azaion-commands"
|
|
||||||
cdef str ANNOTATIONS_QUEUE = "azaion-annotations"
|
|
||||||
|
|
||||||
cdef str QUEUE_CONFIG_FILENAME = "secured-config.json"
|
cdef str QUEUE_CONFIG_FILENAME = "secured-config.json"
|
||||||
|
|
||||||
cdef str AI_ONNX_MODEL_FILE = "azaion.onnx"
|
cdef str AI_ONNX_MODEL_FILE = "azaion.onnx"
|
||||||
|
|
||||||
cdef str CDN_CONFIG = "cdn.yaml"
|
cdef str CDN_CONFIG = "cdn.yaml"
|
||||||
|
|||||||
@@ -6,27 +6,24 @@ from threading import Thread
|
|||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from api_client cimport ApiClient
|
|
||||||
from annotation cimport Annotation
|
from annotation cimport Annotation
|
||||||
from inference cimport Inference
|
from inference cimport Inference
|
||||||
from remote_command cimport RemoteCommand, CommandType
|
from remote_command cimport RemoteCommand, CommandType
|
||||||
from remote_command_handler cimport RemoteCommandHandler
|
from remote_command_handler cimport RemoteCommandHandler
|
||||||
from credentials cimport Credentials
|
|
||||||
from file_data cimport FileData
|
|
||||||
|
|
||||||
cdef class CommandProcessor:
|
cdef class CommandProcessor:
|
||||||
cdef ApiClient api_client
|
|
||||||
cdef RemoteCommandHandler remote_handler
|
cdef RemoteCommandHandler remote_handler
|
||||||
cdef object inference_queue
|
cdef object inference_queue
|
||||||
cdef bint running
|
cdef bint running
|
||||||
cdef Inference inference
|
cdef Inference inference
|
||||||
|
|
||||||
def __init__(self, int zmq_port, str api_url):
|
def __init__(self, int zmq_port, str api_url):
|
||||||
self.api_client = ApiClient(api_url)
|
|
||||||
self.remote_handler = RemoteCommandHandler(zmq_port, self.on_command)
|
self.remote_handler = RemoteCommandHandler(zmq_port, self.on_command)
|
||||||
self.inference_queue = Queue(maxsize=constants.QUEUE_MAXSIZE)
|
self.inference_queue = Queue(maxsize=constants.QUEUE_MAXSIZE)
|
||||||
self.remote_handler.start()
|
self.remote_handler.start()
|
||||||
self.running = True
|
self.running = True
|
||||||
|
#TODO: replace api_client to azaion_loader.exe call
|
||||||
self.inference = Inference(self.api_client, self.on_annotation)
|
self.inference = Inference(self.api_client, self.on_annotation)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
|||||||
@@ -16,5 +16,6 @@ cdef class ApiClient:
|
|||||||
|
|
||||||
cdef load_bytes(self, str filename, str folder)
|
cdef load_bytes(self, str filename, str folder)
|
||||||
cdef upload_file(self, str filename, bytes resource, str folder)
|
cdef upload_file(self, str filename, bytes resource, str folder)
|
||||||
|
cdef load_big_file_cdn(self, str folder, str big_part)
|
||||||
cdef load_big_small_resource(self, str resource_name, str folder, str key)
|
cdef load_big_small_resource(self, str resource_name, str folder, str key)
|
||||||
cdef upload_big_small_resource(self, bytes resource, str resource_name, str folder, str key)
|
cdef upload_big_small_resource(self, bytes resource, str resource_name, str folder, str key)
|
||||||
@@ -159,7 +159,7 @@ cdef class ApiClient:
|
|||||||
print('Local file doesnt match with api file, old version')
|
print('Local file doesnt match with api file, old version')
|
||||||
|
|
||||||
remote_bytes_big = self.load_big_file_cdn(folder, big_part)
|
remote_bytes_big = self.load_big_file_cdn(folder, big_part)
|
||||||
return Security.decrypt_to(encrypted_bytes_small + remote_bytes_big)
|
return Security.decrypt_to(encrypted_bytes_small + remote_bytes_big, key)
|
||||||
|
|
||||||
cdef upload_big_small_resource(self, bytes resource, str resource_name, str folder, str key):
|
cdef upload_big_small_resource(self, bytes resource, str resource_name, str folder, str key):
|
||||||
cdef str big_part_name = f'{resource_name}.big'
|
cdef str big_part_name = f'{resource_name}.big'
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
echo Build Cython app
|
||||||
|
set CURRENT_DIR=%cd%
|
||||||
|
|
||||||
|
REM Change to the parent directory of the current location
|
||||||
|
cd /d %~dp0
|
||||||
|
|
||||||
|
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
|
||||||
|
)
|
||||||
|
|
||||||
|
venv\Scripts\python -m pip install --upgrade pip
|
||||||
|
venv\Scripts\pip install -r requirements.txt
|
||||||
|
venv\Scripts\pip install --upgrade pyinstaller pyinstaller-hooks-contrib
|
||||||
|
|
||||||
|
venv\Scripts\python setup.py build_ext --inplace
|
||||||
|
|
||||||
|
echo install azaion-loader
|
||||||
|
venv\Scripts\pyinstaller --name=azaion-loader ^
|
||||||
|
--collect-all boto3 ^
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
cdef str CONFIG_FILE # Port for the zmq
|
||||||
|
|
||||||
|
cdef int QUEUE_MAXSIZE # Maximum size of the command queue
|
||||||
|
cdef str COMMANDS_QUEUE # Name of the commands queue in rabbit
|
||||||
|
cdef str ANNOTATIONS_QUEUE # Name of the annotations queue in rabbit
|
||||||
|
|
||||||
|
cdef str QUEUE_CONFIG_FILENAME # queue config filename to load from api
|
||||||
|
|
||||||
|
cdef str AI_ONNX_MODEL_FILE
|
||||||
|
|
||||||
|
cdef str CDN_CONFIG
|
||||||
|
cdef str MODELS_FOLDER
|
||||||
|
|
||||||
|
cdef int SMALL_SIZE_KB
|
||||||
|
|
||||||
|
|
||||||
|
cdef log(str log_message, bytes client_id=*)
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
cdef str CONFIG_FILE = "config.yaml" # Port for the zmq
|
||||||
|
|
||||||
|
cdef str QUEUE_CONFIG_FILENAME = "secured-config.json"
|
||||||
|
cdef str AI_ONNX_MODEL_FILE = "azaion.onnx"
|
||||||
|
|
||||||
|
cdef str CDN_CONFIG = "cdn.yaml"
|
||||||
|
cdef str MODELS_FOLDER = "models"
|
||||||
|
|
||||||
|
cdef int SMALL_SIZE_KB = 3
|
||||||
|
|
||||||
|
cdef log(str log_message, bytes client_id=None):
|
||||||
|
local_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
|
||||||
|
client_str = '' if client_id is None else f' {client_id}'
|
||||||
|
print(f'[{local_time}{client_str}]: {log_message}')
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
import threading
|
||||||
|
from threading import Thread
|
||||||
|
import traceback
|
||||||
|
from credentials cimport Credentials
|
||||||
|
from remote_command cimport RemoteCommand, CommandType
|
||||||
|
from remote_command_handler cimport RemoteCommandHandler
|
||||||
|
from file_data cimport FileData
|
||||||
|
from api_client cimport ApiClient
|
||||||
|
|
||||||
|
cdef class CommandProcessor:
|
||||||
|
cdef RemoteCommandHandler remote_handler
|
||||||
|
cdef ApiClient api_client
|
||||||
|
cdef bint running
|
||||||
|
cdef object shutdown_event
|
||||||
|
|
||||||
|
def __init__(self, int zmq_port, str api_url):
|
||||||
|
self.api_client = ApiClient(api_url)
|
||||||
|
self.shutdown_event = threading.Event()
|
||||||
|
self.remote_handler = RemoteCommandHandler(zmq_port, self.on_command)
|
||||||
|
self.remote_handler.start()
|
||||||
|
self.running = True
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
while self.running:
|
||||||
|
try:
|
||||||
|
while not self.shutdown_event.is_set():
|
||||||
|
self.shutdown_event.wait(timeout=1.0)
|
||||||
|
except Exception as e:
|
||||||
|
traceback.print_exc()
|
||||||
|
print('EXIT!')
|
||||||
|
|
||||||
|
cdef on_command(self, RemoteCommand command):
|
||||||
|
try:
|
||||||
|
if command.command_type == CommandType.LOGIN:
|
||||||
|
self.api_client.set_credentials(Credentials.from_msgpack(command.data))
|
||||||
|
elif command.command_type == CommandType.LOAD:
|
||||||
|
self.load_file(command)
|
||||||
|
elif command.command_type == CommandType.EXIT:
|
||||||
|
t = Thread(target=self.stop) # non-block worker:
|
||||||
|
t.start()
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error handling client: {e}")
|
||||||
|
|
||||||
|
cdef load_file(self, RemoteCommand command):
|
||||||
|
cdef RemoteCommand response
|
||||||
|
cdef FileData file_data
|
||||||
|
cdef bytes file_bytes
|
||||||
|
try:
|
||||||
|
file_data = FileData.from_msgpack(command.data)
|
||||||
|
file_bytes = self.api_client.load_bytes(file_data.filename, file_data.folder)
|
||||||
|
response = RemoteCommand(CommandType.DATA_BYTES, file_bytes)
|
||||||
|
except Exception as e:
|
||||||
|
response = RemoteCommand(CommandType.DATA_BYTES, None, str(e))
|
||||||
|
self.remote_handler.send(command.client_id, response.serialize())
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.shutdown_event.set()
|
||||||
|
self.remote_handler.stop()
|
||||||
|
self.running = False
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
cdef enum CommandType:
|
||||||
|
LOGIN = 10
|
||||||
|
LOAD = 20
|
||||||
|
DATA_BYTES = 25
|
||||||
|
INFERENCE = 30
|
||||||
|
INFERENCE_DATA = 35
|
||||||
|
STOP_INFERENCE = 40
|
||||||
|
AI_AVAILABILITY_CHECK = 80
|
||||||
|
AI_AVAILABILITY_RESULT = 85
|
||||||
|
ERROR = 90
|
||||||
|
EXIT = 100
|
||||||
|
|
||||||
|
cdef class RemoteCommand:
|
||||||
|
cdef public bytes client_id
|
||||||
|
cdef CommandType command_type
|
||||||
|
cdef str message
|
||||||
|
cdef bytes data
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
cdef from_msgpack(bytes data)
|
||||||
|
|
||||||
|
cdef bytes serialize(self)
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import msgpack
|
||||||
|
|
||||||
|
cdef class RemoteCommand:
|
||||||
|
def __init__(self, CommandType command_type, bytes data, str message=None):
|
||||||
|
self.command_type = command_type
|
||||||
|
self.data = data
|
||||||
|
self.message = message
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
command_type_names = {
|
||||||
|
10: "LOGIN",
|
||||||
|
20: "LOAD",
|
||||||
|
25: "DATA_BYTES",
|
||||||
|
30: "INFERENCE",
|
||||||
|
35: "INFERENCE_DATA",
|
||||||
|
40: "STOP_INFERENCE",
|
||||||
|
80: "AI_AVAILABILITY_CHECK",
|
||||||
|
85: "AI_AVAILABILITY_RESULT",
|
||||||
|
90: "ERROR",
|
||||||
|
100: "EXIT"
|
||||||
|
}
|
||||||
|
data_str = f'{len(self.data)} bytes' if self.data else ''
|
||||||
|
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("Data"), unpacked.get("Message"))
|
||||||
|
|
||||||
|
cdef bytes serialize(self):
|
||||||
|
return msgpack.packb({
|
||||||
|
"CommandType": self.command_type,
|
||||||
|
"Data": self.data,
|
||||||
|
"Message": self.message
|
||||||
|
})
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
cdef class RemoteCommandHandler:
|
||||||
|
cdef object _context
|
||||||
|
cdef object _router
|
||||||
|
cdef object _dealer
|
||||||
|
cdef object _control
|
||||||
|
cdef object _shutdown_event
|
||||||
|
cdef object _on_command
|
||||||
|
|
||||||
|
cdef object _proxy_thread
|
||||||
|
cdef object _workers
|
||||||
|
|
||||||
|
cdef start(self)
|
||||||
|
cdef _proxy_loop(self)
|
||||||
|
cdef _worker_loop(self)
|
||||||
|
cdef send(self, bytes client_id, bytes data)
|
||||||
|
cdef stop(self)
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
import time
|
||||||
|
import zmq
|
||||||
|
from threading import Thread, Event
|
||||||
|
from remote_command cimport RemoteCommand
|
||||||
|
cimport constants
|
||||||
|
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._router = self._context.socket(zmq.ROUTER)
|
||||||
|
self._router.setsockopt(zmq.LINGER, 0)
|
||||||
|
self._router.bind(f'tcp://*:{zmq_port}')
|
||||||
|
|
||||||
|
self._dealer = self._context.socket(zmq.DEALER)
|
||||||
|
self._dealer.setsockopt(zmq.LINGER, 0)
|
||||||
|
self._dealer.bind("inproc://backend")
|
||||||
|
|
||||||
|
self._control = self._context.socket(zmq.PAIR)
|
||||||
|
self._control.bind("inproc://control")
|
||||||
|
self._shutdown_event = Event()
|
||||||
|
|
||||||
|
self._proxy_thread = Thread(target=self._proxy_loop, daemon=True)
|
||||||
|
|
||||||
|
self._workers = []
|
||||||
|
for _ in range(4): # 4 worker threads
|
||||||
|
worker = Thread(target=self._worker_loop, daemon=True)
|
||||||
|
self._workers.append(worker)
|
||||||
|
print(f'Listening to commands on port {zmq_port}...')
|
||||||
|
|
||||||
|
cdef start(self):
|
||||||
|
self._proxy_thread.start()
|
||||||
|
for worker in self._workers:
|
||||||
|
worker.start()
|
||||||
|
|
||||||
|
cdef _proxy_loop(self):
|
||||||
|
try:
|
||||||
|
zmq.proxy_steerable(self._router, self._dealer, control=self._control)
|
||||||
|
except zmq.error.ZMQError as e:
|
||||||
|
if self._shutdown_event.is_set():
|
||||||
|
print("Shutdown, exit proxy loop.")
|
||||||
|
else:
|
||||||
|
raise
|
||||||
|
|
||||||
|
cdef _worker_loop(self):
|
||||||
|
worker_socket = self._context.socket(zmq.DEALER)
|
||||||
|
worker_socket.setsockopt(zmq.LINGER, 0)
|
||||||
|
worker_socket.connect("inproc://backend")
|
||||||
|
poller = zmq.Poller()
|
||||||
|
poller.register(worker_socket, zmq.POLLIN)
|
||||||
|
try:
|
||||||
|
|
||||||
|
while not self._shutdown_event.is_set():
|
||||||
|
try:
|
||||||
|
socks = dict(poller.poll(500))
|
||||||
|
if worker_socket in socks:
|
||||||
|
client_id, message = worker_socket.recv_multipart()
|
||||||
|
cmd = RemoteCommand.from_msgpack(<bytes> message)
|
||||||
|
cmd.client_id = client_id
|
||||||
|
constants.log(<str>f'{cmd}', client_id)
|
||||||
|
self._on_command(cmd)
|
||||||
|
except Exception as e:
|
||||||
|
if not self._shutdown_event.is_set():
|
||||||
|
constants.log(f"Worker error: {e}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
finally:
|
||||||
|
worker_socket.close()
|
||||||
|
|
||||||
|
cdef send(self, bytes client_id, bytes data):
|
||||||
|
self._router.send_multipart([client_id, data])
|
||||||
|
|
||||||
|
# with self._context.socket(zmq.DEALER) as socket:
|
||||||
|
# socket.connect("inproc://backend")
|
||||||
|
# socket.send_multipart([client_id, data])
|
||||||
|
# # constants.log(<str>f'Sent {len(data)} bytes.', client_id)
|
||||||
|
|
||||||
|
cdef stop(self):
|
||||||
|
self._shutdown_event.set()
|
||||||
|
try:
|
||||||
|
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)
|
||||||
|
|
||||||
|
self._proxy_thread.join(timeout=2)
|
||||||
|
while any(w.is_alive() for w in self._workers):
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
self._context.term()
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
pyinstaller
|
||||||
|
Cython
|
||||||
|
psutil
|
||||||
|
msgpack
|
||||||
|
pyjwt
|
||||||
|
zmq
|
||||||
|
requests
|
||||||
|
pyyaml
|
||||||
|
boto3
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
from setuptools import setup, Extension
|
||||||
|
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('user', ['user.pyx']),
|
||||||
|
Extension('cdn_manager', ['cdn_manager.pyx']),
|
||||||
|
Extension('api_client', ['api_client.pyx']),
|
||||||
|
Extension('main', ['main.pyx']),
|
||||||
|
]
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="azaion.loader",
|
||||||
|
ext_modules=cythonize(
|
||||||
|
extensions,
|
||||||
|
compiler_directives={
|
||||||
|
"language_level": 3,
|
||||||
|
"emit_code_comments" : False,
|
||||||
|
"binding": True,
|
||||||
|
'boundscheck': False,
|
||||||
|
'wraparound': False
|
||||||
|
}
|
||||||
|
),
|
||||||
|
zip_safe=False
|
||||||
|
)
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
from main import CommandProcessor
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("-p", "--port", type=str, default="5025", help="zero mq port")
|
||||||
|
parser.add_argument("-a", "--api", type=str, default="https://api.azaion.com", help="api url")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
processor = CommandProcessor(int(args.port), args.api)
|
||||||
|
try:
|
||||||
|
processor.start()
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
processor.stop()
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<Application x:Class="Azaion.LoaderUI.App"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||||
|
<Application.Resources>
|
||||||
|
|
||||||
|
</Application.Resources>
|
||||||
|
</Application>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using System.Windows;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace Azaion.LoaderUI;
|
||||||
|
|
||||||
|
public partial class App
|
||||||
|
{
|
||||||
|
protected override void OnStartup(StartupEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnStartup(e);
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
Log.Logger = new LoggerConfiguration()
|
||||||
|
.Enrich.FromLogContext()
|
||||||
|
.MinimumLevel.Information()
|
||||||
|
.WriteTo.Console()
|
||||||
|
.WriteTo.File(
|
||||||
|
path: "Logs/log.txt",
|
||||||
|
rollingInterval: RollingInterval.Day)
|
||||||
|
.CreateLogger();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using System.Windows;
|
||||||
|
|
||||||
|
[assembly: ThemeInfo(
|
||||||
|
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// or application resource dictionaries)
|
||||||
|
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||||
|
//(used if a resource is not found in the page,
|
||||||
|
// app, or any theme specific resource dictionaries)
|
||||||
|
)]
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<UseWPF>true</UseWPF>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Azaion.CommonSecurity\Azaion.CommonSecurity.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.5" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.5" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
|
||||||
|
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.1" />
|
||||||
|
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<Window x:Class="Azaion.Suite.Login"
|
<Window x:Class="Azaion.LoaderUI.Login"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Azaion.Common.DTO;
|
|
||||||
using Azaion.CommonSecurity.DTO;
|
using Azaion.CommonSecurity.DTO;
|
||||||
|
|
||||||
namespace Azaion.Suite;
|
namespace Azaion.LoaderUI;
|
||||||
|
|
||||||
public partial class Login
|
public partial class Login
|
||||||
{
|
{
|
||||||
@@ -15,20 +14,17 @@ public partial class Login
|
|||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public event EventHandler<ApiCredentials>? CredentialsEntered;
|
|
||||||
|
|
||||||
private void LoginClick(object sender, RoutedEventArgs e)
|
private void LoginClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
LoginBtn.Cursor = Cursors.Wait;
|
LoginBtn.Cursor = Cursors.Wait;
|
||||||
Cursor = Cursors.Wait;
|
Cursor = Cursors.Wait;
|
||||||
CredentialsEntered?.Invoke(this, new ApiCredentials(TbEmail.Text, TbPassword.Password));
|
|
||||||
MainSuiteOpened = true;
|
MainSuiteOpened = true;
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CloseClick(object sender, RoutedEventArgs e) => Close();
|
private void CloseClick(object sender, RoutedEventArgs e) => Close();
|
||||||
|
|
||||||
private void MainMouseMove(object sender, MouseEventArgs e)
|
private void MainMouseMove(object sende0r, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.OriginalSource is Button || e.OriginalSource is TextBox)
|
if (e.OriginalSource is Button || e.OriginalSource is TextBox)
|
||||||
return;
|
return;
|
||||||
+94
-122
@@ -1,6 +1,5 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
@@ -17,12 +16,12 @@ using Azaion.CommonSecurity.DTO;
|
|||||||
using Azaion.CommonSecurity.DTO.Commands;
|
using Azaion.CommonSecurity.DTO.Commands;
|
||||||
using Azaion.CommonSecurity.Services;
|
using Azaion.CommonSecurity.Services;
|
||||||
using Azaion.Dataset;
|
using Azaion.Dataset;
|
||||||
|
using CommandLine;
|
||||||
using LibVLCSharp.Shared;
|
using LibVLCSharp.Shared;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
@@ -32,131 +31,24 @@ namespace Azaion.Suite;
|
|||||||
|
|
||||||
public partial class App
|
public partial class App
|
||||||
{
|
{
|
||||||
private IHost _host = null!;
|
|
||||||
private ILogger<App> _logger = null!;
|
|
||||||
private IMediator _mediator = null!;
|
private IMediator _mediator = null!;
|
||||||
private FormState _formState = null!;
|
private FormState _formState = null!;
|
||||||
|
private IHost _host = null!;
|
||||||
private IInferenceClient _inferenceClient = null!;
|
|
||||||
private Stream _securedConfig = null!;
|
|
||||||
private Stream _systemConfig = null!;
|
|
||||||
private static readonly Guid KeyPressTaskId = Guid.NewGuid();
|
private static readonly Guid KeyPressTaskId = Guid.NewGuid();
|
||||||
private string _loadErrors = "";
|
|
||||||
|
|
||||||
|
|
||||||
private readonly ICache _cache = new MemoryCache();
|
private readonly ICache _cache = new MemoryCache();
|
||||||
private IAzaionApi _azaionApi = null!;
|
private readonly CancellationTokenSource _mainCTokenSource = new();
|
||||||
private CancellationTokenSource _mainCTokenSource = new();
|
|
||||||
|
|
||||||
private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
|
private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
|
||||||
{
|
{
|
||||||
_logger.LogError(e.Exception, e.Exception.Message);
|
Log.Logger.Error(e.Exception, "Unhandled exception");
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnStartup(StartupEventArgs e)
|
protected override void OnStartup(StartupEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnStartup(e);
|
base.OnStartup(e);
|
||||||
StartLogin();
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly List<string> _encryptedResources =
|
|
||||||
[
|
|
||||||
"Azaion.Annotator",
|
|
||||||
"Azaion.Dataset"
|
|
||||||
];
|
|
||||||
|
|
||||||
private static SecureAppConfig ReadSecureAppConfig()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!File.Exists(SecurityConstants.CONFIG_PATH))
|
|
||||||
throw new FileNotFoundException(SecurityConstants.CONFIG_PATH);
|
|
||||||
var configStr = File.ReadAllText(SecurityConstants.CONFIG_PATH);
|
|
||||||
var config = JsonConvert.DeserializeObject<SecureAppConfig>(configStr);
|
|
||||||
|
|
||||||
return config ?? SecurityConstants.DefaultSecureAppConfig;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine(e);
|
|
||||||
return SecurityConstants.DefaultSecureAppConfig;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StartLogin()
|
|
||||||
{
|
|
||||||
new ConfigUpdater().CheckConfig();
|
|
||||||
var secureAppConfig = ReadSecureAppConfig();
|
|
||||||
var apiDir = secureAppConfig.DirectoriesConfig.ApiResourcesDirectory;
|
|
||||||
_inferenceClient = new InferenceClient(new OptionsWrapper<InferenceClientConfig>(secureAppConfig.InferenceClientConfig), _mainCTokenSource.Token);
|
|
||||||
var login = new Login();
|
|
||||||
|
|
||||||
var loader = (IResourceLoader)_inferenceClient;
|
|
||||||
login.CredentialsEntered += (_, credentials) =>
|
|
||||||
{
|
|
||||||
_inferenceClient.Send(RemoteCommand.Create(CommandType.Login, credentials));
|
|
||||||
_azaionApi = new AzaionApi(new HttpClient { BaseAddress = new Uri(secureAppConfig.InferenceClientConfig.ApiUrl) }, _cache, credentials);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_securedConfig = loader.LoadFile("config.secured.json", apiDir);
|
|
||||||
_systemConfig = loader.LoadFile("config.system.json", apiDir);
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Console.WriteLine(e);
|
|
||||||
_securedConfig = new MemoryStream("{}"u8.ToArray());
|
|
||||||
var systemConfig = new
|
|
||||||
{
|
|
||||||
AnnotationConfig = Constants.DefaultAnnotationConfig,
|
|
||||||
AIRecognitionConfig = Constants.DefaultAIRecognitionConfig,
|
|
||||||
ThumbnailConfig = Constants.DefaultThumbnailConfig,
|
|
||||||
};
|
|
||||||
_systemConfig = new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(systemConfig)));
|
|
||||||
}
|
|
||||||
|
|
||||||
AppDomain.CurrentDomain.AssemblyResolve += (_, a) =>
|
|
||||||
{
|
|
||||||
var assemblyName = a.Name.Split(',').First();
|
|
||||||
if (_encryptedResources.Contains(assemblyName))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var stream = loader.LoadFile($"{assemblyName}.dll", apiDir);
|
|
||||||
return Assembly.Load(stream.ToArray());
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
Log.Logger.Error(e, $"Failed to load assembly {assemblyName}");
|
|
||||||
_loadErrors += $"{e.Message}{Environment.NewLine}{Environment.NewLine}";
|
|
||||||
var currentLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
|
|
||||||
var dllPath = Path.Combine(currentLocation, SecurityConstants.DUMMY_DIR, $"{assemblyName}.dll");
|
|
||||||
return Assembly.LoadFile(dllPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var loadedAssembly = AppDomain.CurrentDomain.GetAssemblies()
|
|
||||||
.FirstOrDefault(a => a.GetName().Name == assemblyName);
|
|
||||||
|
|
||||||
return loadedAssembly;
|
|
||||||
};
|
|
||||||
|
|
||||||
StartMain();
|
|
||||||
_host.Start();
|
|
||||||
EventManager.RegisterClassHandler(typeof(UIElement), UIElement.PreviewKeyDownEvent, new RoutedEventHandler(GlobalKeyHandler));
|
|
||||||
_host.Services.GetRequiredService<MainSuite>().Show();
|
|
||||||
};
|
|
||||||
login.Closed += (sender, args) =>
|
|
||||||
{
|
|
||||||
if (!login.MainSuiteOpened)
|
|
||||||
_inferenceClient.Dispose();
|
|
||||||
};
|
|
||||||
login.ShowDialog();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StartMain()
|
|
||||||
{
|
|
||||||
Log.Logger = new LoggerConfiguration()
|
Log.Logger = new LoggerConfiguration()
|
||||||
.Enrich.FromLogContext()
|
.Enrich.FromLogContext()
|
||||||
.MinimumLevel.Information()
|
.MinimumLevel.Information()
|
||||||
@@ -166,12 +58,86 @@ public partial class App
|
|||||||
rollingInterval: RollingInterval.Day)
|
rollingInterval: RollingInterval.Day)
|
||||||
.CreateLogger();
|
.CreateLogger();
|
||||||
|
|
||||||
|
Parser.Default.ParseArguments<ApiCredentials>(e.Args)
|
||||||
|
.WithParsed(Start)
|
||||||
|
.WithNotParsed(ErrorHandling);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ErrorHandling(IEnumerable<Error> obj)
|
||||||
|
{
|
||||||
|
Log.Fatal($"Error happened: {string.Join(",", obj.Select(x => x.Tag))}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InitConfig ReadInitConfig()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!File.Exists(SecurityConstants.CONFIG_PATH))
|
||||||
|
throw new FileNotFoundException(SecurityConstants.CONFIG_PATH);
|
||||||
|
var configStr = File.ReadAllText(SecurityConstants.CONFIG_PATH);
|
||||||
|
var config = JsonConvert.DeserializeObject<InitConfig>(configStr);
|
||||||
|
|
||||||
|
return config ?? SecurityConstants.DefaultInitConfig;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
return SecurityConstants.DefaultInitConfig;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream GetSystemConfig(LoaderClient loaderClient, string apiDir)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return loaderClient.LoadFile("config.system.json", apiDir);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Logger.Error(e, e.Message);
|
||||||
|
return new MemoryStream(Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(new
|
||||||
|
{
|
||||||
|
AnnotationConfig = Constants.DefaultAnnotationConfig,
|
||||||
|
AIRecognitionConfig = Constants.DefaultAIRecognitionConfig,
|
||||||
|
ThumbnailConfig = Constants.DefaultThumbnailConfig,
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream GetSecuredConfig(LoaderClient loaderClient, string apiDir)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return loaderClient.LoadFile("config.secured.json", apiDir);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Log.Logger.Error(e, e.Message);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Start(ApiCredentials credentials)
|
||||||
|
{
|
||||||
|
new ConfigUpdater().CheckConfig();
|
||||||
|
var initConfig = ReadInitConfig();
|
||||||
|
var apiDir = initConfig.DirectoriesConfig.ApiResourcesDirectory;
|
||||||
|
var loaderClient = new LoaderClient(initConfig.LoaderClientConfig, Log.Logger, _mainCTokenSource.Token);
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
loaderClient.StartClient();
|
||||||
|
#endif
|
||||||
|
loaderClient.Connect(); //Client app should be already started by LoaderUI
|
||||||
|
|
||||||
|
loaderClient.Send(RemoteCommand.Create(CommandType.Login, credentials));
|
||||||
|
var azaionApi = new AzaionApi(new HttpClient { BaseAddress = new Uri(initConfig.InferenceClientConfig.ApiUrl) }, _cache, credentials);
|
||||||
|
|
||||||
_host = Host.CreateDefaultBuilder()
|
_host = Host.CreateDefaultBuilder()
|
||||||
.ConfigureAppConfiguration((context, config) => config
|
.ConfigureAppConfiguration((_, config) => config
|
||||||
.AddCommandLine(Environment.GetCommandLineArgs())
|
.AddCommandLine(Environment.GetCommandLineArgs())
|
||||||
.AddJsonFile(SecurityConstants.CONFIG_PATH, optional: true, reloadOnChange: true)
|
.AddJsonFile(SecurityConstants.CONFIG_PATH, optional: true, reloadOnChange: true)
|
||||||
.AddJsonStream(_securedConfig)
|
.AddJsonStream(GetSystemConfig(loaderClient, apiDir))
|
||||||
.AddJsonStream(_systemConfig))
|
.AddJsonStream(GetSecuredConfig(loaderClient, apiDir)))
|
||||||
.UseSerilog()
|
.UseSerilog()
|
||||||
.ConfigureServices((context, services) =>
|
.ConfigureServices((context, services) =>
|
||||||
{
|
{
|
||||||
@@ -188,15 +154,20 @@ public partial class App
|
|||||||
|
|
||||||
#region External Services
|
#region External Services
|
||||||
|
|
||||||
|
services.ConfigureSection<LoaderClientConfig>(context.Configuration);
|
||||||
|
services.AddSingleton(loaderClient);
|
||||||
|
|
||||||
services.ConfigureSection<InferenceClientConfig>(context.Configuration);
|
services.ConfigureSection<InferenceClientConfig>(context.Configuration);
|
||||||
services.ConfigureSection<GpsDeniedClientConfig>(context.Configuration);
|
services.AddSingleton<IInferenceClient, InferenceClient>();
|
||||||
services.AddSingleton<IInferenceClient>(_inferenceClient);
|
|
||||||
services.AddSingleton<IGpsMatcherClient, GpsMatcherClient>();
|
|
||||||
services.AddSingleton<IInferenceService, InferenceService>();
|
services.AddSingleton<IInferenceService, InferenceService>();
|
||||||
|
|
||||||
|
services.ConfigureSection<GpsDeniedClientConfig>(context.Configuration);
|
||||||
|
services.AddSingleton<IGpsMatcherClient, GpsMatcherClient>();
|
||||||
services.AddSingleton<IGpsMatcherService, GpsMatcherService>();
|
services.AddSingleton<IGpsMatcherService, GpsMatcherService>();
|
||||||
services.AddSingleton<ISatelliteDownloader, SatelliteDownloader>();
|
services.AddSingleton<ISatelliteDownloader, SatelliteDownloader>();
|
||||||
|
|
||||||
services.AddHttpClient();
|
services.AddHttpClient();
|
||||||
services.AddSingleton(_azaionApi);
|
services.AddSingleton(azaionApi);
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
services.AddSingleton<IConfigUpdater, ConfigUpdater>();
|
services.AddSingleton<IConfigUpdater, ConfigUpdater>();
|
||||||
@@ -235,12 +206,13 @@ public partial class App
|
|||||||
datasetExplorer.Hide();
|
datasetExplorer.Hide();
|
||||||
|
|
||||||
_mediator = _host.Services.GetRequiredService<IMediator>();
|
_mediator = _host.Services.GetRequiredService<IMediator>();
|
||||||
if (!string.IsNullOrEmpty(_loadErrors))
|
|
||||||
_mediator.Publish(new LoadErrorEvent(_loadErrors));
|
|
||||||
|
|
||||||
_logger = _host.Services.GetRequiredService<ILogger<App>>();
|
|
||||||
_formState = _host.Services.GetRequiredService<FormState>();
|
_formState = _host.Services.GetRequiredService<FormState>();
|
||||||
DispatcherUnhandledException += OnDispatcherUnhandledException;
|
DispatcherUnhandledException += OnDispatcherUnhandledException;
|
||||||
|
|
||||||
|
_host.Start();
|
||||||
|
EventManager.RegisterClassHandler(typeof(UIElement), UIElement.PreviewKeyDownEvent, new RoutedEventHandler(GlobalKeyHandler));
|
||||||
|
_host.Services.GetRequiredService<MainSuite>().Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GlobalKeyHandler(object sender, RoutedEventArgs e)
|
private void GlobalKeyHandler(object sender, RoutedEventArgs e)
|
||||||
|
|||||||
@@ -12,19 +12,21 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="CommandLineParser" Version="2.9.1" />
|
||||||
<PackageReference Include="GMap.NET.WinPresentation" Version="2.1.7" />
|
<PackageReference Include="GMap.NET.WinPresentation" Version="2.1.7" />
|
||||||
<PackageReference Include="LibVLCSharp" Version="3.9.1" />
|
<PackageReference Include="LibVLCSharp" Version="3.9.1" />
|
||||||
<PackageReference Include="LibVLCSharp.WPF" Version="3.9.1" />
|
<PackageReference Include="LibVLCSharp.WPF" Version="3.9.1" />
|
||||||
<PackageReference Include="MediatR" Version="12.4.1" />
|
<PackageReference Include="MediatR" Version="12.5.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.5" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="RabbitMQ.Stream.Client" Version="1.8.9" />
|
<PackageReference Include="RabbitMQ.Stream.Client" Version="1.8.9" />
|
||||||
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
|
<PackageReference Include="Serilog.Extensions.Hosting" Version="9.0.0" />
|
||||||
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.4" />
|
<PackageReference Include="Serilog.Extensions.Logging" Version="9.0.1" />
|
||||||
|
<PackageReference Include="Serilog.Settings.Configuration" Version="9.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
|
||||||
<PackageReference Include="SharpVectors" Version="1.8.4.2" />
|
<PackageReference Include="SharpVectors" Version="1.8.4.2" />
|
||||||
<PackageReference Include="SharpVectors.Wpf" Version="1.8.4.2" />
|
<PackageReference Include="SharpVectors.Wpf" Version="1.8.4.2" />
|
||||||
<PackageReference Include="System.Data.SQLite" Version="1.0.119" />
|
<PackageReference Include="System.Data.SQLite" Version="1.0.119" />
|
||||||
@@ -51,20 +53,4 @@
|
|||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Page Update="Login.xaml">
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
<XamlRuntime>Wpf</XamlRuntime>
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
</Page>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<Target Name="PostBuild" AfterTargets="Build">
|
|
||||||
<MakeDir Directories="$(TargetDir)dummy" />
|
|
||||||
<Copy SourceFiles="$(TargetDir)Azaion.Annotator.dll" DestinationFolder="$(TargetDir)dummy" />
|
|
||||||
<Copy SourceFiles="$(TargetDir)Azaion.Dataset.dll" DestinationFolder="$(TargetDir)dummy" />
|
|
||||||
<Exec Command="postbuild.cmd $(ConfigurationName) stage" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,17 +1,18 @@
|
|||||||
{
|
{
|
||||||
|
"LoaderClientConfig": {
|
||||||
|
"ZeroMqHost": "127.0.0.1",
|
||||||
|
"ZeroMqPort": 5025,
|
||||||
|
"ApiUrl": "https://api.azaion.com"
|
||||||
|
},
|
||||||
"InferenceClientConfig": {
|
"InferenceClientConfig": {
|
||||||
"ZeroMqHost": "127.0.0.1",
|
"ZeroMqHost": "127.0.0.1",
|
||||||
"ZeroMqPort": 5127,
|
"ZeroMqPort": 5127,
|
||||||
"RetryCount": 25,
|
|
||||||
"TimeoutSeconds": 5,
|
|
||||||
"ApiUrl": "https://api.azaion.com"
|
"ApiUrl": "https://api.azaion.com"
|
||||||
},
|
},
|
||||||
"GpsDeniedClientConfig": {
|
"GpsDeniedClientConfig": {
|
||||||
"ZeroMqHost": "127.0.0.1",
|
"ZeroMqHost": "127.0.0.1",
|
||||||
"ZeroMqPort": 5555,
|
"ZeroMqPort": 5555,
|
||||||
"ZeroMqReceiverPort": 5556,
|
"ZeroMqReceiverPort": 5556
|
||||||
"RetryCount": 25,
|
|
||||||
"TimeoutSeconds": 5
|
|
||||||
},
|
},
|
||||||
"DirectoriesConfig": {
|
"DirectoriesConfig": {
|
||||||
"ApiResourcesDirectory": "stage",
|
"ApiResourcesDirectory": "stage",
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
set CONFIG=%1
|
|
||||||
set RESOURCES_FOLDER=%2
|
|
||||||
|
|
||||||
set FILE1_TO_UPLOAD=%cd%\..\Azaion.Annotator\bin\%CONFIG%\net8.0-windows\Azaion.Annotator.dll
|
|
||||||
call upload-file %FILE1_TO_UPLOAD% %RESOURCES_FOLDER%
|
|
||||||
|
|
||||||
set FILE2_TO_UPLOAD=%cd%\..\Azaion.Dataset\bin\%CONFIG%\net8.0-windows\Azaion.Dataset.dll
|
|
||||||
call upload-file %FILE2_TO_UPLOAD% %RESOURCES_FOLDER%
|
|
||||||
|
|
||||||
set SUITE_FOLDER=%cd%\bin\%CONFIG%\net8.0-windows\
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
setlocal enabledelayedexpansion
|
|
||||||
|
|
||||||
set API_URL=https://api.azaion.com
|
|
||||||
set SOURCE_FILE=%1
|
|
||||||
set DESTINATION=%2
|
|
||||||
|
|
||||||
set "SOURCE_FILE=%SOURCE_FILE:\=/%"
|
|
||||||
|
|
||||||
set EMAIL=uploader@azaion.com
|
|
||||||
set PASSWORD=Az@1on_10Upl0@der
|
|
||||||
|
|
||||||
for /f "tokens=*" %%i in ('curl -s -X POST -H "Content-Type: application/json" ^
|
|
||||||
-d "{\"email\":\"%EMAIL%\",\"password\":\"%PASSWORD%\"}" %API_URL%/login') do set RESPONSE=%%i
|
|
||||||
|
|
||||||
for /f "tokens=2 delims=:" %%a in ('echo %RESPONSE% ^| findstr /i "token"') do (
|
|
||||||
set "TOKEN=%%a"
|
|
||||||
set "TOKEN=!TOKEN:~1,-1!"
|
|
||||||
set "TOKEN=!TOKEN:~0,-2!"
|
|
||||||
)
|
|
||||||
|
|
||||||
set UPLOAD_URL=%API_URL%/resources/%DESTINATION%
|
|
||||||
|
|
||||||
echo Uploading %SOURCE_FILE% to %UPLOAD_URL%...
|
|
||||||
curl --location %UPLOAD_URL% ^
|
|
||||||
-H "Authorization: Bearer %TOKEN%" ^
|
|
||||||
-H "Content-Type: multipart/form-data" ^
|
|
||||||
--form "data=@%SOURCE_FILE%"
|
|
||||||
echo Upload complete!
|
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
<PackageReference Include="FluentAssertions" Version="8.3.0" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
<PackageReference Include="Moq" Version="4.20.72" />
|
<PackageReference Include="Moq" Version="4.20.72" />
|
||||||
<PackageReference Include="xunit" Version="2.8.0" />
|
<PackageReference Include="xunit" Version="2.8.0" />
|
||||||
|
|||||||
@@ -11,19 +11,12 @@
|
|||||||
<PackageReference Include="libc.translation" Version="7.1.1" />
|
<PackageReference Include="libc.translation" Version="7.1.1" />
|
||||||
<PackageReference Include="LibVLCSharp" Version="3.9.1" />
|
<PackageReference Include="LibVLCSharp" Version="3.9.1" />
|
||||||
<PackageReference Include="LibVLCSharp.WPF" Version="3.9.1" />
|
<PackageReference Include="LibVLCSharp.WPF" Version="3.9.1" />
|
||||||
<PackageReference Include="MediatR" Version="12.4.1" />
|
<PackageReference Include="MediatR" Version="12.5.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.3" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="RangeTree" Version="3.0.1" />
|
<PackageReference Include="RangeTree" Version="3.0.1" />
|
||||||
<PackageReference Include="Serilog" Version="4.0.0" />
|
|
||||||
<PackageReference Include="Serilog.Extensions.Hosting" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Serilog.Settings.Configuration" Version="8.0.1" />
|
|
||||||
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
|
|
||||||
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
|
||||||
<PackageReference Include="SkiaSharp" Version="2.88.9" />
|
<PackageReference Include="SkiaSharp" Version="2.88.9" />
|
||||||
<PackageReference Include="VideoLAN.LibVLC.Windows" Version="3.0.21" />
|
<PackageReference Include="VideoLAN.LibVLC.Windows" Version="3.0.21" />
|
||||||
<PackageReference Include="WindowsAPICodePack" Version="7.0.4" />
|
<PackageReference Include="WindowsAPICodePack" Version="7.0.4" />
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.5" />
|
||||||
<PackageReference Include="ScottPlot.WPF" Version="5.0.46" />
|
<PackageReference Include="ScottPlot.WPF" Version="5.0.46" />
|
||||||
<PackageReference Include="VirtualizingWrapPanel" Version="2.1.0" />
|
<PackageReference Include="VirtualizingWrapPanel" Version="2.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -16,9 +16,8 @@ xcopy Azaion.Suite\bin\Release\net8.0-windows\win-x64\publish dist\ /s /e /q
|
|||||||
del dist\config.json
|
del dist\config.json
|
||||||
move dist\config.production.json dist\config.json
|
move dist\config.production.json dist\config.json
|
||||||
|
|
||||||
mkdir dist-azaion\dummy
|
robocopy "dist" "dist-azaion" "Azaion.Annotator.dll" "Azaion.Dataset.dll" "Azaion.Common.dll" "Azaion.CommonSecurity.dll" /MOV
|
||||||
robocopy "dist" "dist-azaion\dummy" "Azaion.Annotator.dll" "Azaion.Dataset.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.Common.dll" "Azaion.CommonSecurity.dll" "Azaion.Suite.deps.json" "Azaion.Suite.dll" "Azaion.Suite.exe" "Azaion.Suite.runtimeconfig.json" "config.json" "logo.png" /MOV
|
|
||||||
if exist dist\libvlc\win-x86 rmdir dist\libvlc\win-x86 /s /q
|
if exist dist\libvlc\win-x86 rmdir dist\libvlc\win-x86 /s /q
|
||||||
robocopy "dist" "dist-dlls" /E /MOVE
|
robocopy "dist" "dist-dlls" /E /MOVE
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user