mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 08:36:29 +00:00
write logs for inference and loader to file
This commit is contained in:
@@ -26,6 +26,8 @@ tmp_ret = collect_all('pynvml')
|
||||
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
||||
tmp_ret = collect_all('jwt')
|
||||
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
||||
tmp_ret = collect_all('loguru')
|
||||
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
|
||||
|
||||
|
||||
a = Analysis(
|
||||
|
||||
@@ -33,6 +33,7 @@ venv\Scripts\pyinstaller --name=azaion-inference ^
|
||||
--collect-all pycuda ^
|
||||
--collect-all pynvml ^
|
||||
--collect-all jwt ^
|
||||
--collect-all loguru ^
|
||||
--hidden-import constants ^
|
||||
--hidden-import file_data ^
|
||||
--hidden-import remote_command ^
|
||||
|
||||
@@ -13,5 +13,5 @@ cdef str MODELS_FOLDER
|
||||
|
||||
cdef int SMALL_SIZE_KB
|
||||
|
||||
|
||||
cdef log(str log_message, bytes client_id=*)
|
||||
cdef log(str log_message)
|
||||
cdef logerror(str error)
|
||||
@@ -1,4 +1,6 @@
|
||||
import time
|
||||
import sys
|
||||
|
||||
from loguru import logger
|
||||
|
||||
cdef str CONFIG_FILE = "config.yaml" # Port for the zmq
|
||||
|
||||
@@ -10,7 +12,32 @@ 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}')
|
||||
logger.remove()
|
||||
log_format = "[{time:HH:mm:ss} {level}] {message}"
|
||||
logger.add(
|
||||
sink="Logs/log_inference_{time:YYYYMMDD}.txt",
|
||||
level="INFO",
|
||||
format=log_format,
|
||||
enqueue=True,
|
||||
rotation="1 day",
|
||||
retention="30 days",
|
||||
)
|
||||
logger.add(
|
||||
sys.stdout,
|
||||
level="DEBUG",
|
||||
format=log_format,
|
||||
filter=lambda record: record["level"].name in ("INFO", "DEBUG", "SUCCESS"),
|
||||
colorize=True
|
||||
)
|
||||
logger.add(
|
||||
sys.stderr,
|
||||
level="WARNING",
|
||||
format=log_format,
|
||||
colorize=True
|
||||
)
|
||||
|
||||
cdef log(str log_message):
|
||||
logger.info(log_message)
|
||||
|
||||
cdef logerror(str error):
|
||||
logger.error(error)
|
||||
@@ -16,7 +16,7 @@ cdef int check_tensor_gpu_index():
|
||||
deviceCount = pynvml.nvmlDeviceGetCount()
|
||||
|
||||
if deviceCount == 0:
|
||||
print('No NVIDIA GPUs found.')
|
||||
constants.logerror('No NVIDIA GPUs found.')
|
||||
return -1
|
||||
|
||||
for i in range(deviceCount):
|
||||
@@ -24,10 +24,10 @@ cdef int check_tensor_gpu_index():
|
||||
major, minor = pynvml.nvmlDeviceGetCudaComputeCapability(handle)
|
||||
|
||||
if major > 6 or (major == 6 and minor >= 1):
|
||||
print('found NVIDIA GPU!')
|
||||
constants.log('found NVIDIA GPU!')
|
||||
return i
|
||||
|
||||
print('NVIDIA GPU doesnt support TensorRT!')
|
||||
constants.logerror('NVIDIA GPU doesnt support TensorRT!')
|
||||
return -1
|
||||
|
||||
except pynvml.NVMLError:
|
||||
@@ -36,7 +36,7 @@ cdef int check_tensor_gpu_index():
|
||||
try:
|
||||
pynvml.nvmlShutdown()
|
||||
except:
|
||||
print('Failed to shutdown pynvml cause probably no NVidia GPU')
|
||||
constants.logerror('Failed to shutdown pynvml cause probably no NVIDIA GPU')
|
||||
pass
|
||||
|
||||
tensor_gpu_index = check_tensor_gpu_index()
|
||||
@@ -70,15 +70,15 @@ cdef class Inference:
|
||||
|
||||
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')
|
||||
constants.log('tensor rt engine is here, no need to build')
|
||||
self.is_building_engine = False
|
||||
updater_callback('enabled')
|
||||
return
|
||||
|
||||
print(res.err)
|
||||
constants.logerror(res.err)
|
||||
# time.sleep(8) # prevent simultaneously loading dll and models
|
||||
updater_callback('converting')
|
||||
print('try to load onnx')
|
||||
constants.log('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}')
|
||||
@@ -87,7 +87,7 @@ cdef class Inference:
|
||||
res = self.loader_client.upload_big_small_resource(model_bytes, <str> 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')
|
||||
constants.log(f'uploaded {engine_filename} to CDN and API')
|
||||
self.is_building_engine = False
|
||||
updater_callback('enabled')
|
||||
except Exception as e:
|
||||
@@ -212,11 +212,11 @@ cdef class Inference:
|
||||
# images first, it's faster
|
||||
if len(images) > 0:
|
||||
for chunk in self.split_list_extend(images, self.engine.get_batch_size()):
|
||||
print(f'run inference on {" ".join(chunk)}...')
|
||||
constants.log(f'run inference on {" ".join(chunk)}...')
|
||||
self._process_images(cmd, ai_config, chunk)
|
||||
if len(videos) > 0:
|
||||
for v in videos:
|
||||
print(f'run inference on {v}...')
|
||||
constants.log(f'run inference on {v}...')
|
||||
self._process_video(cmd, ai_config, v)
|
||||
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ cdef class CommandProcessor:
|
||||
continue
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
print('EXIT!')
|
||||
constants.log('EXIT!')
|
||||
|
||||
cdef on_command(self, RemoteCommand command):
|
||||
try:
|
||||
@@ -54,7 +54,7 @@ cdef class CommandProcessor:
|
||||
else:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f"Error handling client: {e}")
|
||||
constants.logerror(f"Error handling client: {e}")
|
||||
|
||||
cdef on_annotation(self, RemoteCommand cmd, Annotation annotation):
|
||||
cdef RemoteCommand response = RemoteCommand(CommandType.INFERENCE_DATA, annotation.serialize())
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
from inference_engine cimport InferenceEngine
|
||||
import onnxruntime as onnx
|
||||
cimport constants
|
||||
|
||||
cdef class OnnxEngine(InferenceEngine):
|
||||
def __init__(self, model_bytes: bytes, batch_size: int = 1, **kwargs):
|
||||
@@ -10,9 +11,9 @@ cdef class OnnxEngine(InferenceEngine):
|
||||
self.input_name = self.model_inputs[0].name
|
||||
self.input_shape = self.model_inputs[0].shape
|
||||
self.batch_size = self.input_shape[0] if self.input_shape[0] != -1 else batch_size
|
||||
print(f'AI detection model input: {self.model_inputs} {self.input_shape}')
|
||||
constants.log(f'AI detection model input: {self.model_inputs} {self.input_shape}')
|
||||
model_meta = self.session.get_modelmeta()
|
||||
print("Metadata:", model_meta.custom_metadata_map)
|
||||
constants.log(f"Metadata: {model_meta.custom_metadata_map}")
|
||||
|
||||
cpdef tuple get_input_shape(self):
|
||||
shape = self.input_shape
|
||||
|
||||
@@ -3,7 +3,6 @@ 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):
|
||||
@@ -28,7 +27,7 @@ cdef class RemoteCommandHandler:
|
||||
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}...')
|
||||
constants.log(f'Listening to commands on port {zmq_port}...')
|
||||
|
||||
cdef start(self):
|
||||
self._proxy_thread.start()
|
||||
@@ -40,7 +39,7 @@ cdef class RemoteCommandHandler:
|
||||
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.")
|
||||
constants.log("Shutdown, exit proxy loop.")
|
||||
else:
|
||||
raise
|
||||
|
||||
@@ -59,7 +58,7 @@ cdef class RemoteCommandHandler:
|
||||
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)
|
||||
constants.log(cmd)
|
||||
self._on_command(cmd)
|
||||
except Exception as e:
|
||||
if not self._shutdown_event.is_set():
|
||||
|
||||
@@ -14,3 +14,4 @@ pycuda
|
||||
tensorrt
|
||||
pynvml
|
||||
boto3
|
||||
loguru
|
||||
@@ -103,11 +103,11 @@ cdef class TensorRTEngine(InferenceEngine):
|
||||
constants.log('Converting to supported fp16')
|
||||
config.set_flag(trt.BuilderFlag.FP16)
|
||||
else:
|
||||
print('Converting to supported fp32. (fp16 is not supported)')
|
||||
constants.log('Converting to supported fp32. (fp16 is not supported)')
|
||||
plan = builder.build_serialized_network(network, config)
|
||||
|
||||
if plan is None:
|
||||
print('Conversion failed.')
|
||||
constants.logerror('Conversion failed.')
|
||||
return None
|
||||
constants.log('conversion done!')
|
||||
return bytes(plan)
|
||||
|
||||
@@ -215,7 +215,7 @@ class Api:
|
||||
response = requests.post(url, data=payload, headers=headers, stream=True)
|
||||
|
||||
if response.status_code == HTTPStatus.INTERNAL_SERVER_ERROR:
|
||||
print('500!')
|
||||
print('500!') #test
|
||||
|
||||
key = self.get_encryption_key(hardware.hash)
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ cdef class ApiClient:
|
||||
token = response.json()["token"]
|
||||
self.set_token(token)
|
||||
except HTTPError as e:
|
||||
constants.log(response.json())
|
||||
constants.logerror(response.json())
|
||||
if response.status_code == HTTPStatus.CONFLICT:
|
||||
res = response.json()
|
||||
raise Exception(res['Message'])
|
||||
@@ -95,7 +95,7 @@ cdef class ApiClient:
|
||||
r.raise_for_status()
|
||||
constants.log(f"Uploaded {filename} to {self.api_url}/{folder} successfully: {r.status_code}.")
|
||||
except Exception as e:
|
||||
constants.log(f"Upload fail: {e}")
|
||||
constants.logerror(f"Upload fail: {e}")
|
||||
|
||||
cdef list_files(self, str folder, str search_file):
|
||||
response = self.request('get', f'{self.api_url}/resources/list/{folder}', {
|
||||
@@ -173,7 +173,7 @@ cdef class ApiClient:
|
||||
resource = Security.decrypt_to(encrypted_bytes_small + local_bytes_big, key)
|
||||
return resource
|
||||
except Exception as ex:
|
||||
constants.log('Local file {folder}\\{big_part} doesnt match with api file, old version')
|
||||
constants.logerror('Local file {folder}\\{big_part} doesnt match with api file, old version')
|
||||
|
||||
remote_bytes_big = self.load_big_file_cdn(folder, big_part)
|
||||
return Security.decrypt_to(encrypted_bytes_small + remote_bytes_big, key)
|
||||
|
||||
@@ -30,6 +30,7 @@ venv\Scripts\pyinstaller --name=azaion-loader ^
|
||||
--collect-all boto3 ^
|
||||
--collect-all cryptography ^
|
||||
--collect-all yaml ^
|
||||
--collect-all loguru ^
|
||||
--hidden-import constants ^
|
||||
--hidden-import file_data ^
|
||||
--hidden-import remote_command ^
|
||||
|
||||
@@ -30,7 +30,7 @@ cdef class CDNManager:
|
||||
constants.log(f'uploaded {filename} ({len(file_bytes)} bytes) to the {bucket}')
|
||||
return True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
constants.logerror(e)
|
||||
return False
|
||||
|
||||
cdef download(self, str folder, str filename):
|
||||
@@ -40,5 +40,5 @@ cdef class CDNManager:
|
||||
constants.log(f'downloaded {filename} from the {folder}')
|
||||
return True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
constants.logerror(e)
|
||||
return False
|
||||
|
||||
@@ -14,4 +14,5 @@ cdef str MODELS_FOLDER
|
||||
cdef int SMALL_SIZE_KB
|
||||
|
||||
|
||||
cdef log(str log_message, bytes client_id=*)
|
||||
cdef log(str log_message)
|
||||
cdef logerror(str error)
|
||||
@@ -1,4 +1,6 @@
|
||||
import sys
|
||||
import time
|
||||
from loguru import logger
|
||||
|
||||
cdef str CONFIG_FILE = "config.yaml" # Port for the zmq
|
||||
|
||||
@@ -10,7 +12,34 @@ 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}')
|
||||
cdef int ALIGNMENT_WIDTH = 32
|
||||
|
||||
logger.remove()
|
||||
log_format = "[{time:HH:mm:ss} {level}] {message}"
|
||||
logger.add(
|
||||
sink="Logs/log_loader_{time:YYYYMMDD}.txt",
|
||||
level="INFO",
|
||||
format=log_format,
|
||||
enqueue=True,
|
||||
rotation="1 day",
|
||||
retention="30 days",
|
||||
)
|
||||
logger.add(
|
||||
sys.stdout,
|
||||
level="DEBUG",
|
||||
format=log_format,
|
||||
filter=lambda record: record["level"].name in ("INFO", "DEBUG", "SUCCESS"),
|
||||
colorize=True
|
||||
)
|
||||
logger.add(
|
||||
sys.stderr,
|
||||
level="WARNING",
|
||||
format=log_format,
|
||||
colorize=True
|
||||
)
|
||||
|
||||
cdef log(str log_message):
|
||||
logger.info(log_message)
|
||||
|
||||
cdef logerror(str error):
|
||||
logger.error(error)
|
||||
@@ -1,6 +1,7 @@
|
||||
import threading
|
||||
from threading import Thread
|
||||
import traceback
|
||||
cimport constants
|
||||
from credentials cimport Credentials
|
||||
from remote_command cimport RemoteCommand, CommandType
|
||||
from remote_command_handler cimport RemoteCommandHandler
|
||||
@@ -29,7 +30,7 @@ cdef class CommandProcessor:
|
||||
self.shutdown_event.wait(timeout=1.0)
|
||||
except Exception as e:
|
||||
traceback.print_exc()
|
||||
print('EXIT!')
|
||||
constants.log('EXIT!')
|
||||
|
||||
|
||||
cdef on_command(self, RemoteCommand command):
|
||||
@@ -66,7 +67,7 @@ cdef class CommandProcessor:
|
||||
else:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f"Error handling client: {e}")
|
||||
constants.logerror(f"Error handling client: {e}")
|
||||
err_command = RemoteCommand(CommandType.ERROR, None, str(e))
|
||||
self.remote_handler.send(command.client_id, err_command.serialize())
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ cdef class RemoteCommandHandler:
|
||||
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}...')
|
||||
constants.log(f'Listening to commands on port {zmq_port}...')
|
||||
|
||||
cdef start(self):
|
||||
self._proxy_thread.start()
|
||||
@@ -40,7 +40,7 @@ cdef class RemoteCommandHandler:
|
||||
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.")
|
||||
constants.log("Shutdown, exit proxy loop.")
|
||||
else:
|
||||
raise
|
||||
|
||||
@@ -59,11 +59,11 @@ cdef class RemoteCommandHandler:
|
||||
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)
|
||||
constants.log(<str>f'{cmd}')
|
||||
self._on_command(cmd)
|
||||
except Exception as e:
|
||||
if not self._shutdown_event.is_set():
|
||||
constants.log(f"Worker error: {e}")
|
||||
constants.logerror(f"Worker error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
finally:
|
||||
@@ -72,11 +72,6 @@ cdef class RemoteCommandHandler:
|
||||
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:
|
||||
|
||||
@@ -7,4 +7,5 @@ zmq
|
||||
requests
|
||||
pyyaml
|
||||
boto3
|
||||
loguru
|
||||
cryptography==44.0.2
|
||||
@@ -2,7 +2,6 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Serilog;
|
||||
|
||||
namespace Azaion.LoaderUI;
|
||||
@@ -29,7 +28,7 @@ public partial class App
|
||||
var host = Host.CreateDefaultBuilder()
|
||||
.ConfigureAppConfiguration((_, config) => config
|
||||
.AddCommandLine(Environment.GetCommandLineArgs())
|
||||
.AddJsonFile(Constants.CONFIG_JSON_FILE))
|
||||
.AddJsonFile(Constants.CONFIG_JSON_FILE, optional: true))
|
||||
.UseSerilog()
|
||||
.ConfigureServices((context, services) =>
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWPF>true</UseWPF>
|
||||
<ApplicationIcon>..\logo.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -22,9 +23,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="loaderconfig.json" />
|
||||
<Content Include="loaderconfig.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -10,8 +10,8 @@ namespace Azaion.LoaderUI;
|
||||
public interface IAzaionApi
|
||||
{
|
||||
void Login(ApiCredentials credentials);
|
||||
string GetLastInstallerName(string folder);
|
||||
(string name, Stream stream) DownloadInstaller(string folder);
|
||||
Task<string> GetLastInstallerName(string folder);
|
||||
Task<(string name, Stream stream)> DownloadInstaller(string folder);
|
||||
}
|
||||
|
||||
public class AzaionApi(HttpClient client) : IAzaionApi
|
||||
@@ -25,39 +25,39 @@ public class AzaionApi(HttpClient client) : IAzaionApi
|
||||
_credentials = credentials;
|
||||
}
|
||||
|
||||
public string GetLastInstallerName(string folder)
|
||||
public async Task<string> GetLastInstallerName(string folder)
|
||||
{
|
||||
var res = Get<List<string>>($"/resources/list/{folder}");
|
||||
var res = await Get<List<string>>($"/resources/list/{folder}");
|
||||
return res?.FirstOrDefault() ?? "";
|
||||
}
|
||||
|
||||
public (string name, Stream stream) DownloadInstaller(string folder)
|
||||
public async Task<(string name, Stream stream)> DownloadInstaller(string folder)
|
||||
{
|
||||
var response = Send(new HttpRequestMessage(HttpMethod.Get, $"resources/get-installer/{folder}"));
|
||||
var fileStream = response.Content.ReadAsStream();
|
||||
var response = await Send(new HttpRequestMessage(HttpMethod.Get, $"resources/get-installer/{folder}"));
|
||||
var fileStream = await response.Content.ReadAsStreamAsync();
|
||||
var fileName = response.Content.Headers.ContentDisposition?.FileName?.Trim('"') ?? "installer.exe";
|
||||
return (fileName, fileStream);
|
||||
}
|
||||
|
||||
private HttpResponseMessage Send(HttpRequestMessage request)
|
||||
private async Task<HttpResponseMessage> Send(HttpRequestMessage request)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_jwtToken))
|
||||
Authorize();
|
||||
await Authorize();
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _jwtToken);
|
||||
var response = client.Send(request);
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
if (response.StatusCode == HttpStatusCode.Unauthorized)
|
||||
{
|
||||
Authorize();
|
||||
await Authorize();
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _jwtToken);
|
||||
response = client.Send(request);
|
||||
response = await client.SendAsync(request);
|
||||
}
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
return response;
|
||||
|
||||
var stream = response.Content.ReadAsStream();
|
||||
var content = new StreamReader(stream).ReadToEnd();
|
||||
var stream = await response.Content.ReadAsStreamAsync();
|
||||
var content = await new StreamReader(stream).ReadToEndAsync();
|
||||
if (response.StatusCode == HttpStatusCode.Conflict)
|
||||
{
|
||||
var result = JsonConvert.DeserializeObject<BusinessExceptionDto>(content);
|
||||
@@ -66,23 +66,23 @@ public class AzaionApi(HttpClient client) : IAzaionApi
|
||||
throw new Exception($"Failed: {response.StatusCode}! Result: {content}");
|
||||
}
|
||||
|
||||
private T? Get<T>(string url)
|
||||
private async Task<T?> Get<T>(string url)
|
||||
{
|
||||
var response = Send(new HttpRequestMessage(HttpMethod.Get, url));
|
||||
var stream = response.Content.ReadAsStream();
|
||||
var json = new StreamReader(stream).ReadToEnd();
|
||||
var response = await Send(new HttpRequestMessage(HttpMethod.Get, url));
|
||||
var stream = await response.Content.ReadAsStreamAsync();
|
||||
var json = await new StreamReader(stream).ReadToEndAsync();
|
||||
return JsonConvert.DeserializeObject<T>(json);
|
||||
}
|
||||
|
||||
private void Put<T>(string url, T obj)
|
||||
private async Task Put<T>(string url, T obj)
|
||||
{
|
||||
Send(new HttpRequestMessage(HttpMethod.Put, url)
|
||||
await Send(new HttpRequestMessage(HttpMethod.Put, url)
|
||||
{
|
||||
Content = new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, APP_JSON)
|
||||
});
|
||||
}
|
||||
|
||||
private void Authorize()
|
||||
private async Task Authorize()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -95,13 +95,13 @@ public class AzaionApi(HttpClient client) : IAzaionApi
|
||||
password = _credentials.Password
|
||||
}), Encoding.UTF8, APP_JSON);
|
||||
var message = new HttpRequestMessage(HttpMethod.Post, "login") { Content = content };
|
||||
var response = client.Send(message);
|
||||
var response = await client.SendAsync(message);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
throw new Exception($"EnterCredentials failed: {response.StatusCode}");
|
||||
|
||||
var stream = response.Content.ReadAsStream();
|
||||
var json = new StreamReader(stream).ReadToEnd();
|
||||
var stream = await response.Content.ReadAsStreamAsync();
|
||||
var json = await new StreamReader(stream).ReadToEndAsync();
|
||||
var result = JsonConvert.DeserializeObject<LoginResponse>(json);
|
||||
|
||||
if (string.IsNullOrEmpty(result?.Token))
|
||||
|
||||
@@ -3,6 +3,7 @@ namespace Azaion.LoaderUI;
|
||||
public static class Constants
|
||||
{
|
||||
public const string CONFIG_JSON_FILE = "loaderconfig.json";
|
||||
public const string API_URL = "http://localhost:5219"; //"https://api.azaion.com";
|
||||
public const string API_URL = "https://api.azaion.com";
|
||||
public const string AZAION_SUITE_EXE = "Azaion.Suite.exe";
|
||||
public const string SUITE_FOLDER = "suite";
|
||||
}
|
||||
+41
-32
@@ -23,7 +23,7 @@
|
||||
Color ="Gray" />
|
||||
</Border.Effect>
|
||||
<StackPanel Orientation="Vertical"
|
||||
Margin="20">
|
||||
Margin="15">
|
||||
<Canvas>
|
||||
<Button Padding="5" ToolTip="Закрити" Background="DarkGray" BorderBrush="DarkGray" Canvas.Left="290" Cursor="Hand"
|
||||
Name="CloseBtn"
|
||||
@@ -59,6 +59,8 @@
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Text="Email"
|
||||
Grid.Row="0"
|
||||
@@ -90,38 +92,45 @@
|
||||
BorderThickness="0,0,0,1"
|
||||
HorizontalAlignment="Left"
|
||||
Password=""/>
|
||||
|
||||
<Button x:Name="LoginBtn"
|
||||
Grid.Row="4"
|
||||
Content="Вхід"
|
||||
Foreground="White"
|
||||
Background="DimGray"
|
||||
Margin="0,15"
|
||||
Height="35"
|
||||
Width="280"
|
||||
Cursor="Hand"
|
||||
Click="LoginClick">
|
||||
<Button.Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border x:Name="LoginBorder" Background="{TemplateBinding Background}"
|
||||
CornerRadius="16">
|
||||
<ContentPresenter HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="LightGray" TargetName="LoginBorder" />
|
||||
<Setter Property="TextBlock.Foreground" Value="Black" TargetName="LoginBorder" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
<TextBlock Name="TbStatus"
|
||||
Text=""
|
||||
Grid.Row="5"
|
||||
Margin="0, -10, 0, 5"
|
||||
HorizontalAlignment="Left"/>
|
||||
</Grid>
|
||||
<Button x:Name="LoginBtn"
|
||||
Content="Вхід"
|
||||
Foreground="White"
|
||||
Background="DimGray"
|
||||
Margin="0,25"
|
||||
Height="35"
|
||||
Width="280"
|
||||
Cursor="Hand"
|
||||
Click="LoginClick">
|
||||
<Button.Style>
|
||||
<Style TargetType="Button">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type Button}">
|
||||
<Border x:Name="LoginBorder" Background="{TemplateBinding Background}"
|
||||
CornerRadius="16">
|
||||
<ContentPresenter HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center"/>
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter Property="Background" Value="LightGray" TargetName="LoginBorder" />
|
||||
<Setter Property="TextBlock.Foreground" Value="Black" TargetName="LoginBorder" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Button.Style>
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Window>
|
||||
|
||||
@@ -3,23 +3,27 @@ using System.IO;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
|
||||
|
||||
namespace Azaion.LoaderUI;
|
||||
|
||||
public partial class Login
|
||||
{
|
||||
private readonly IAzaionApi _azaionApi;
|
||||
private readonly DirectoriesConfig _dirConfig;
|
||||
private readonly ILogger<Login> _logger;
|
||||
private readonly DirectoriesConfig? _dirConfig;
|
||||
|
||||
public Login(IAzaionApi azaionApi, IOptions<DirectoriesConfig> directoriesConfig)
|
||||
public Login(IAzaionApi azaionApi, IOptions<DirectoriesConfig> directoriesConfig, ILogger<Login> logger)
|
||||
{
|
||||
_azaionApi = azaionApi;
|
||||
_logger = logger;
|
||||
_dirConfig = directoriesConfig.Value;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void LoginClick(object sender, RoutedEventArgs e)
|
||||
private async void LoginClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var creds = new ApiCredentials(TbEmail.Text, TbPassword.Password);
|
||||
if (!creds.IsValid())
|
||||
@@ -30,33 +34,43 @@ public partial class Login
|
||||
|
||||
_azaionApi.Login(creds);
|
||||
|
||||
if (GetInstallerVer() > GetLocalVer())
|
||||
DownloadAndRunInstaller();
|
||||
var installerVersion = await GetInstallerVer();
|
||||
var localVersion = GetLocalVer();
|
||||
|
||||
if (installerVersion > localVersion)
|
||||
{
|
||||
TbStatus.Text = $"Updating from {localVersion} to {installerVersion}...";
|
||||
await DownloadAndRunInstaller();
|
||||
TbStatus.Text = $"Installed {installerVersion}!";
|
||||
}
|
||||
else
|
||||
TbStatus.Text = $"Your version is up to date!";
|
||||
|
||||
Process.Start(Constants.AZAION_SUITE_EXE, $"-e {creds.Email} -p {creds.Password}");
|
||||
Close();
|
||||
}
|
||||
|
||||
private void DownloadAndRunInstaller()
|
||||
private async Task DownloadAndRunInstaller()
|
||||
{
|
||||
var (installerName, stream) = _azaionApi.DownloadInstaller(_dirConfig.SuiteInstallerDirectory);
|
||||
var (installerName, stream) = await _azaionApi.DownloadInstaller(_dirConfig?.SuiteInstallerDirectory ?? "");
|
||||
var localFileStream = new FileStream(installerName, FileMode.Create, FileAccess.Write);
|
||||
stream.CopyTo(localFileStream);
|
||||
await stream.CopyToAsync(localFileStream);
|
||||
localFileStream.Close();
|
||||
stream.Close();
|
||||
|
||||
var processInfo = new ProcessStartInfo(installerName)
|
||||
{
|
||||
UseShellExecute = true,
|
||||
Verb = "runas"
|
||||
Arguments = "/VERYSILENT"
|
||||
};
|
||||
|
||||
Process.Start(processInfo);
|
||||
var process = Process.Start(processInfo);
|
||||
await process!.WaitForExitAsync();
|
||||
}
|
||||
|
||||
private Version GetInstallerVer()
|
||||
private async Task<Version> GetInstallerVer()
|
||||
{
|
||||
var installerName = _azaionApi.GetLastInstallerName(_dirConfig.SuiteInstallerDirectory);
|
||||
TbStatus.Text = "Checking for the newer version...";
|
||||
var installerName = await _azaionApi.GetLastInstallerName(_dirConfig?.SuiteInstallerDirectory ?? Constants.SUITE_FOLDER);
|
||||
var version = installerName
|
||||
.Replace("AzaionSuite.Iterative.", "")
|
||||
.Replace(".exe", "");
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"DirectoriesConfig":
|
||||
{
|
||||
"SuiteInstallerDirectory": ""
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Build", "Build", "{CF141A48
|
||||
build\init.cmd = build\init.cmd
|
||||
build\installer.full.iss = build\installer.full.iss
|
||||
build\installer.iterative.iss = build\installer.iterative.iss
|
||||
build\publish-full.cmd = build\publish-full.cmd
|
||||
build\publish.cmd = build\publish.cmd
|
||||
build\requirements.txt = build\requirements.txt
|
||||
build\upload.cmd = build\upload.cmd
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#define MyAppVersion GetFileVersion("..\dist-azaion\Azaion.Suite.exe")
|
||||
|
||||
[Setup]
|
||||
AppId={{CCFEC8E2-0FCC-4B03-8EEA-00AF20D265E5}}
|
||||
AppName=Azaion Suite
|
||||
AppVersion=1.5.0
|
||||
AppPublisher=Azaion Ukraine
|
||||
AppVersion={#MyAppVersion}
|
||||
VersionInfoVersion={#MyAppVersion}
|
||||
AppPublisher=Azaion LLC
|
||||
DefaultDirName={localappdata}\Azaion\Azaion Suite
|
||||
DefaultGroupName=Azaion Suite
|
||||
OutputDir=..\
|
||||
OutputBaseFilename=AzaionSuite.Full.1.5.0
|
||||
OutputBaseFilename=AzaionSuite.Full.{#MyAppVersion}
|
||||
SetupIconFile=..\dist-azaion\logo.ico
|
||||
UninstallDisplayName=Azaion Suite
|
||||
UninstallDisplayIcon={app}\Azaion.Suite.exe
|
||||
@@ -25,7 +28,7 @@ Source: "..\dist-dlls\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs
|
||||
Source: "..\dist-azaion\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs;
|
||||
|
||||
[Icons]
|
||||
Name: "{group}\Azaion Suite"; Filename: "{app}\Azaion.Suite.exe"
|
||||
Name: "{commondesktop}\Azaion Suite"; Filename: "{app}\Azaion.Suite.exe"; Tasks: desktopicon
|
||||
Name: "{group}\Azaion Suite"; Filename: "{app}\Azaion.LoaderUI.exe"
|
||||
Name: "{commondesktop}\Azaion Suite"; Filename: "{app}\Azaion.LoaderUI.exe"; Tasks: desktopicon
|
||||
|
||||
[UninstallRun]
|
||||
@@ -26,7 +26,7 @@ Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{
|
||||
Source: "..\dist-azaion\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs;
|
||||
|
||||
[Icons]
|
||||
Name: "{group}\Azaion Suite"; Filename: "{app}\Azaion.Suite.exe"
|
||||
Name: "{commondesktop}\Azaion Suite"; Filename: "{app}\Azaion.Suite.exe"; Tasks: desktopicon
|
||||
Name: "{group}\Azaion Suite"; Filename: "{app}\Azaion.LoaderUI.exe"
|
||||
Name: "{commondesktop}\Azaion Suite"; Filename: "{app}\Azaion.LoaderUI.exe"; Tasks: desktopicon
|
||||
|
||||
[UninstallRun]
|
||||
+4
-2
@@ -15,10 +15,12 @@ call ..\gps-denied\image-matcher\build_gps
|
||||
|
||||
call build\download_models
|
||||
|
||||
echo building installer...
|
||||
echo building and upload iterative installer...
|
||||
iscc build\installer.iterative.iss
|
||||
|
||||
call build\upload.cmd "suite"
|
||||
|
||||
echo building full installer
|
||||
iscc build\installer.full.iss
|
||||
|
||||
cd /d %CURRENT_DIR%
|
||||
echo Done!
|
||||
Reference in New Issue
Block a user