mirror of
https://github.com/azaion/annotations.git
synced 2026-04-22 22:46:30 +00:00
add pxd headers for correct work
fixes definitions can run until API call
This commit is contained in:
+14
-17
@@ -21,7 +21,7 @@ Windows
|
|||||||
- [Install CUDA](https://developer.nvidia.com/cuda-12-1-0-download-archive)
|
- [Install CUDA](https://developer.nvidia.com/cuda-12-1-0-download-archive)
|
||||||
|
|
||||||
Linux
|
Linux
|
||||||
* ```
|
```
|
||||||
sudo apt install nvidia-driver-535
|
sudo apt install nvidia-driver-535
|
||||||
|
|
||||||
wget https://developer.download.nvidia.com/compute/cudnn/9.2.0/local_installers/cudnn-local-repo-ubuntu2204-9.2.0_1.0-1_amd64.deb
|
wget https://developer.download.nvidia.com/compute/cudnn/9.2.0/local_installers/cudnn-local-repo-ubuntu2204-9.2.0_1.0-1_amd64.deb
|
||||||
@@ -33,30 +33,27 @@ Linux
|
|||||||
nvcc --version
|
nvcc --version
|
||||||
```
|
```
|
||||||
|
|
||||||
<h3>Install dependencies</h3>
|
|
||||||
```
|
|
||||||
Make sure that your virtual env is installed with links to the global python packages and headers, like this:
|
|
||||||
python -m venv --system-site-packages venv
|
|
||||||
This is crucial for the Build because build needs Python.h header and other files.
|
|
||||||
|
|
||||||
|
<h3>Install dependencies</h3>
|
||||||
|
Make sure that your virtual env is installed with links to the global python packages and headers, like this:
|
||||||
|
```
|
||||||
|
python -m venv --system-site-packages venv
|
||||||
|
```
|
||||||
|
This is crucial for the build because build needs Python.h header and other files.
|
||||||
|
|
||||||
|
```
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install --upgrade huggingface_hub
|
pip install --upgrade huggingface_hub
|
||||||
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
|
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
|
||||||
|
|
||||||
pip install git+https://github.com/airockchip/ultralytics_yolov8.git
|
|
||||||
- or
|
|
||||||
pip install ultralytics
|
pip install ultralytics
|
||||||
|
|
||||||
pip install cython
|
|
||||||
pip uninstall -y opencv-python
|
pip uninstall -y opencv-python
|
||||||
pip install opencv-python
|
pip install opencv-python cython msgpack cryptography rstream
|
||||||
pip install msgpack
|
```
|
||||||
|
In case of fbgemm.dll error (Windows specific):
|
||||||
|
|
||||||
|
- copypaste libomp140.x86_64.dll to C:\Windows\System32
|
||||||
|
|
||||||
```
|
|
||||||
* fbgemm.dll error (Windows specific)
|
|
||||||
```
|
|
||||||
copypaste libomp140.x86_64.dll to C:\Windows\System32
|
|
||||||
```
|
|
||||||
|
|
||||||
<h3>Build</h3>
|
<h3>Build</h3>
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
cdef class Detection:
|
||||||
|
cdef double x, y, w, h
|
||||||
|
cdef int cls
|
||||||
|
|
||||||
|
cdef class Annotation:
|
||||||
|
cdef bytes image
|
||||||
|
cdef float time
|
||||||
|
cdef list[Detection] detections
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
cdef class Detection:
|
||||||
|
def __init__(self, double x, double y, double w, double h, int cls):
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
self.w = w
|
||||||
|
self.h = h
|
||||||
|
self.cls = cls
|
||||||
|
|
||||||
|
cdef class Annotation:
|
||||||
|
def __init__(self, bytes image_bytes, float time, list[Detection] detections):
|
||||||
|
self.image = image_bytes
|
||||||
|
self.time = time
|
||||||
|
self.detections = detections
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
from processor_command cimport FileCommand
|
||||||
|
|
||||||
|
cdef class ApiClient:
|
||||||
|
cdef str email, password, token, folder, token_file, api_url
|
||||||
|
|
||||||
|
cdef get_encryption_key(self, str hardware_hash)
|
||||||
|
cdef login(self, str email, str password, bint persist_token=*)
|
||||||
|
cdef bytes load_file(self, str filename, bint persist_token=*)
|
||||||
|
cdef bytes load_ai_model(self)
|
||||||
|
|
||||||
+13
-20
@@ -1,47 +1,41 @@
|
|||||||
# cython: language_level=3
|
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
from http import HTTPStatus
|
from http import HTTPStatus
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import constants
|
cimport constants
|
||||||
from hardware_service import HardwareService
|
from hardware_service cimport HardwareService, HardwareInfo
|
||||||
from processor_command import FileCommand, CommandType
|
|
||||||
from security import Security
|
from security import Security
|
||||||
|
|
||||||
cdef class ApiClient:
|
cdef class ApiClient:
|
||||||
"""Handles API authentication and downloading of the AI model."""
|
"""Handles API authentication and downloading of the AI model."""
|
||||||
cdef str email
|
|
||||||
cdef str password
|
|
||||||
cdef str token
|
|
||||||
cdef str folder
|
|
||||||
|
|
||||||
def __init__(self, str email, str password, str folder):
|
def __init__(self, str email, str password, str folder):
|
||||||
self.email = email
|
self.email = email
|
||||||
self.password = password
|
self.password = password
|
||||||
self.folder = folder
|
self.folder = folder
|
||||||
if os.path.exists(constants.TOKEN_FILE):
|
if os.path.exists(<str>constants.TOKEN_FILE):
|
||||||
with open(constants.TOKEN_FILE, "r") as file:
|
with open(<str>constants.TOKEN_FILE, "r") as file:
|
||||||
self.token = file.read().strip()
|
self.token = file.read().strip()
|
||||||
else:
|
else:
|
||||||
self.token = None
|
self.token = None
|
||||||
|
|
||||||
cdef get_encryption_key(self, command: FileCommand, str hardware_hash):
|
cdef get_encryption_key(self, str hardware_hash):
|
||||||
return f'{self.email}-{self.password}-{hardware_hash}-#%@AzaionKey@%#---'
|
return f'{self.email}-{self.password}-{hardware_hash}-#%@AzaionKey@%#---'
|
||||||
|
|
||||||
cdef login(self, str email, str password, persist_token:bool=False):
|
cdef login(self, str email, str password, bint persist_token=False):
|
||||||
response = requests.post(f"{constants.API_URL}/login", json={"email": email, "password": password})
|
response = requests.post(f"{constants.API_URL}/login", json={"email": email, "password": password})
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
self.token = response.json()["token"]
|
self.token = response.json()["token"]
|
||||||
|
print(f'')
|
||||||
|
|
||||||
if persist_token:
|
if persist_token:
|
||||||
with open(constants.TOKEN_FILE, 'w') as file:
|
with open(<str>constants.TOKEN_FILE, 'w') as file:
|
||||||
file.write(self.token)
|
file.write(self.token)
|
||||||
|
|
||||||
|
|
||||||
cdef bytes load_file(self, command: FileCommand, persist_token:bool=False):
|
cdef bytes load_file(self, str filename, bint persist_token=False):
|
||||||
hardware_service = HardwareService()
|
hardware_service = HardwareService()
|
||||||
hardware = hardware_service.get_hardware_info()
|
cdef HardwareInfo hardware = hardware_service.get_hardware_info()
|
||||||
|
|
||||||
if self.token is None:
|
if self.token is None:
|
||||||
self.login(self.email, self.password, persist_token)
|
self.login(self.email, self.password, persist_token)
|
||||||
@@ -51,7 +45,7 @@ cdef class ApiClient:
|
|||||||
payload = {
|
payload = {
|
||||||
"password": self.password,
|
"password": self.password,
|
||||||
"hardware": hardware,
|
"hardware": hardware,
|
||||||
"fileName": command.filename
|
"fileName": filename
|
||||||
}
|
}
|
||||||
|
|
||||||
response = requests.post(url, json=payload, headers=headers, stream=True)
|
response = requests.post(url, json=payload, headers=headers, stream=True)
|
||||||
@@ -59,13 +53,12 @@ cdef class ApiClient:
|
|||||||
self.login(self.email, self.password, persist_token)
|
self.login(self.email, self.password, persist_token)
|
||||||
response = requests.post(url, json=payload, headers=headers, stream=True)
|
response = requests.post(url, json=payload, headers=headers, stream=True)
|
||||||
|
|
||||||
key = self.get_encryption_key(command, hardware.hash)
|
key = self.get_encryption_key(hardware.hash)
|
||||||
encrypted_stream = io.BytesIO(response.content)
|
encrypted_stream = io.BytesIO(response.content)
|
||||||
decrypted_stream = io.BytesIO()
|
decrypted_stream = io.BytesIO()
|
||||||
Security.decrypt_to(encrypted_stream, decrypted_stream, key)
|
Security.decrypt_to(encrypted_stream, decrypted_stream, key)
|
||||||
return decrypted_stream
|
return decrypted_stream
|
||||||
|
|
||||||
cdef bytes load_ai_model(self):
|
cdef bytes load_ai_model(self):
|
||||||
file_command = FileCommand(CommandType.LOAD, constants.AI_MODEL_FILE)
|
return self.load_file(constants.AI_MODEL_FILE, <bint>True)
|
||||||
return self.load_file(file_command, True)
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
cdef str SOCKET_HOST # Host for the socket server
|
||||||
|
cdef int SOCKET_PORT # Port for the socket server
|
||||||
|
cdef int SOCKET_BUFFER_SIZE # Buffer size for socket communication
|
||||||
|
|
||||||
|
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 API_URL # Base URL for the external API
|
||||||
|
cdef str TOKEN_FILE # Name of the token file where temporary token would be stored
|
||||||
|
cdef str QUEUE_CONFIG_FILENAME # queue config filename to load from api
|
||||||
|
cdef str AI_MODEL_FILE # AI Model file
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
# cython: language_level=3
|
|
||||||
|
|
||||||
cdef str SOCKET_HOST = "127.0.0.1" # Host for the socket server
|
cdef str SOCKET_HOST = "127.0.0.1" # Host for the socket server
|
||||||
cdef int SOCKET_PORT = 9127 # Port for the socket server
|
cdef int SOCKET_PORT = 9127 # Port for the socket server
|
||||||
cdef int SOCKET_BUFFER_SIZE = 4096 # Buffer size for socket communication
|
cdef int SOCKET_BUFFER_SIZE = 4096 # Buffer size for socket communication
|
||||||
@@ -8,10 +6,7 @@ cdef int QUEUE_MAXSIZE = 1000 # Maximum size of the command queue
|
|||||||
cdef str COMMANDS_QUEUE = "azaion-commands"
|
cdef str COMMANDS_QUEUE = "azaion-commands"
|
||||||
cdef str ANNOTATIONS_QUEUE = "azaion-annotations"
|
cdef str ANNOTATIONS_QUEUE = "azaion-annotations"
|
||||||
|
|
||||||
|
|
||||||
cdef str API_URL = "https://api.azaion.com" # Base URL for the external API
|
cdef str API_URL = "https://api.azaion.com" # Base URL for the external API
|
||||||
cdef str TOKEN_FILE = "token"
|
cdef str TOKEN_FILE = "token"
|
||||||
|
|
||||||
|
|
||||||
cdef str QUEUE_CONFIG_FILENAME = "secured-config.json"
|
cdef str QUEUE_CONFIG_FILENAME = "secured-config.json"
|
||||||
cdef str AI_MODEL_FILE = "azaion.pt"
|
cdef str AI_MODEL_FILE = "azaion.pt"
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import main
|
||||||
|
from main import ParsedArguments
|
||||||
|
|
||||||
|
def start_server():
|
||||||
|
args = ParsedArguments('admin@azaion.com', 'Az@1on1000Odm$n', 'stage', True)
|
||||||
|
processor = main.CommandProcessor(args)
|
||||||
|
try:
|
||||||
|
processor.start()
|
||||||
|
except Exception as e:
|
||||||
|
processor.stop()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
start_server()
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
cdef class HardwareInfo:
|
||||||
|
cdef str cpu, gpu, memory, mac_address, hash
|
||||||
|
|
||||||
|
|
||||||
|
cdef class HardwareService:
|
||||||
|
cdef bint is_windows
|
||||||
|
|
||||||
|
cdef HardwareInfo get_hardware_info(self)
|
||||||
|
cdef str calc_hash(self, str s)
|
||||||
@@ -1,15 +1,8 @@
|
|||||||
# cython: language_level=3
|
|
||||||
import base64
|
import base64
|
||||||
import subprocess
|
import subprocess
|
||||||
from hashlib import sha384
|
from hashlib import sha384
|
||||||
|
|
||||||
cdef class HardwareInfo:
|
cdef class HardwareInfo:
|
||||||
cdef str cpu
|
|
||||||
cdef str gpu
|
|
||||||
cdef str memory
|
|
||||||
cdef str mac_address
|
|
||||||
cdef str hash
|
|
||||||
|
|
||||||
def __init__(self, str cpu, str gpu, str memory, str mac_address, str hw_hash):
|
def __init__(self, str cpu, str gpu, str memory, str mac_address, str hw_hash):
|
||||||
self.cpu = cpu
|
self.cpu = cpu
|
||||||
self.gpu = gpu
|
self.gpu = gpu
|
||||||
@@ -25,11 +18,13 @@ cdef class HardwareService:
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
try:
|
try:
|
||||||
if subprocess.check_output("ver", shell=True).decode('utf-8').startswith("Microsoft"):
|
res = subprocess.check_output("ver", shell=True).decode('utf-8')
|
||||||
|
if "Microsoft Windows" in res:
|
||||||
self.is_windows = True
|
self.is_windows = True
|
||||||
else:
|
else:
|
||||||
self.is_windows = False
|
self.is_windows = False
|
||||||
except Exception:
|
except Exception:
|
||||||
|
print('Error during os type checking')
|
||||||
self.is_windows = False
|
self.is_windows = False
|
||||||
|
|
||||||
cdef HardwareInfo get_hardware_info(self):
|
cdef HardwareInfo get_hardware_info(self):
|
||||||
|
|||||||
+1
-23
@@ -1,9 +1,9 @@
|
|||||||
# cython: language_level=3
|
|
||||||
from ultralytics import YOLO
|
from ultralytics import YOLO
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import cv2
|
import cv2
|
||||||
from ultralytics.engine.results import Boxes
|
from ultralytics.engine.results import Boxes
|
||||||
from processor_command import FileCommand
|
from processor_command import FileCommand
|
||||||
|
from annotation cimport Detection, Annotation
|
||||||
|
|
||||||
cdef class Inference:
|
cdef class Inference:
|
||||||
"""Handles YOLO inference using the AI model."""
|
"""Handles YOLO inference using the AI model."""
|
||||||
@@ -66,25 +66,3 @@ cdef class Inference:
|
|||||||
_, encoded_image = cv2.imencode('.jpg', frame[0])
|
_, encoded_image = cv2.imencode('.jpg', frame[0])
|
||||||
image_bytes = encoded_image.tobytes()
|
image_bytes = encoded_image.tobytes()
|
||||||
return Annotation(image_bytes, time, detections)
|
return Annotation(image_bytes, time, detections)
|
||||||
|
|
||||||
|
|
||||||
cdef class Detection:
|
|
||||||
cdef double x
|
|
||||||
cdef double y
|
|
||||||
cdef double w
|
|
||||||
cdef double h
|
|
||||||
cdef int cls
|
|
||||||
|
|
||||||
def __init__(self, double x, double y, double w, double h, int cls):
|
|
||||||
self.x = x
|
|
||||||
self.y = y
|
|
||||||
self.w = w
|
|
||||||
self.h = h
|
|
||||||
self.cls = cls
|
|
||||||
|
|
||||||
cdef class Annotation:
|
|
||||||
|
|
||||||
def __init__(self, image_bytes: bytes, float time, detections: [Detection]):
|
|
||||||
self.image = image_bytes
|
|
||||||
self.time = time
|
|
||||||
self.detections = detections
|
|
||||||
|
|||||||
+23
-26
@@ -1,44 +1,43 @@
|
|||||||
# cython: language_level=3
|
|
||||||
import queue
|
import queue
|
||||||
import threading
|
import threading
|
||||||
import constants
|
cimport constants
|
||||||
from api_client import ApiClient
|
from api_client cimport ApiClient
|
||||||
from inference import Inference, Annotation
|
from annotation cimport Annotation
|
||||||
from processor_command import FileCommand, CommandType, ProcessorType
|
from inference import Inference
|
||||||
from remote_handlers import SocketHandler, RabbitHandler
|
from processor_command cimport FileCommand, CommandType, ProcessorType
|
||||||
|
from remote_handlers cimport SocketHandler, RabbitHandler
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
cdef enum ListenOption:
|
|
||||||
SOCKET = 1
|
|
||||||
QUEUE = 2
|
|
||||||
|
|
||||||
cdef class ParsedArguments:
|
cdef class ParsedArguments:
|
||||||
cdef ListenOption listen
|
cdef str email, password, folder;
|
||||||
cdef str email
|
|
||||||
cdef str password
|
|
||||||
cdef str folder
|
|
||||||
cdef bint persist_token
|
cdef bint persist_token
|
||||||
|
|
||||||
def __init__(self, ListenOption listen, str email, str password, str folder, bint persist_token):
|
def __init__(self, str email, str password, str folder, bint persist_token):
|
||||||
self.listen = listen
|
|
||||||
self.email = email
|
self.email = email
|
||||||
self.password = password
|
self.password = password
|
||||||
self.folder = folder
|
self.folder = folder
|
||||||
self.persist_token = persist_token
|
self.persist_token = persist_token
|
||||||
|
|
||||||
cdef class CommandProcessor:
|
cdef class CommandProcessor:
|
||||||
|
cdef ApiClient api_client
|
||||||
|
cdef SocketHandler socket_handler
|
||||||
|
cdef RabbitHandler rabbit_handler
|
||||||
|
cdef object command_queue
|
||||||
|
cdef bint running
|
||||||
|
|
||||||
def __init__(self, args: ParsedArguments):
|
def __init__(self, args: ParsedArguments):
|
||||||
self.api_client = ApiClient(args.email, args.password, args.folder)
|
self.api_client = ApiClient(args.email, args.password, args.folder)
|
||||||
self.socket_handler = SocketHandler(self.on_message)
|
self.socket_handler = SocketHandler(self.on_message)
|
||||||
self.rabbit_handler = RabbitHandler(self.on_message)
|
self.socket_handler.start()
|
||||||
|
self.rabbit_handler = RabbitHandler(self.api_client, self.on_message)
|
||||||
|
self.rabbit_handler.start()
|
||||||
self.command_queue = queue.Queue(maxsize=constants.QUEUE_MAXSIZE)
|
self.command_queue = queue.Queue(maxsize=constants.QUEUE_MAXSIZE)
|
||||||
self.running = True
|
self.running = True
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
threading.Thread(target=self.process_queue, daemon=True).start()
|
threading.Thread(target=self.process_queue, daemon=True).start()
|
||||||
|
|
||||||
cdef on_message(self, cmd: FileCommand):
|
cdef on_message(self, FileCommand cmd):
|
||||||
try:
|
try:
|
||||||
if cmd.command_type == CommandType.INFERENCE:
|
if cmd.command_type == CommandType.INFERENCE:
|
||||||
self.command_queue.put(cmd)
|
self.command_queue.put(cmd)
|
||||||
@@ -61,7 +60,7 @@ cdef class CommandProcessor:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error processing queue: {e}")
|
print(f"Error processing queue: {e}")
|
||||||
|
|
||||||
cdef process_load(self, command: FileCommand):
|
cdef process_load(self, FileCommand command):
|
||||||
response = self.api_client.load_file(command)
|
response = self.api_client.load_file(command)
|
||||||
handler = self.socket_handler if command.processor_type == ProcessorType.SOCKET else self.rabbit_handler
|
handler = self.socket_handler if command.processor_type == ProcessorType.SOCKET else self.rabbit_handler
|
||||||
handler.send(response)
|
handler.send(response)
|
||||||
@@ -72,20 +71,18 @@ cdef class CommandProcessor:
|
|||||||
|
|
||||||
def parse_arguments():
|
def parse_arguments():
|
||||||
parser = argparse.ArgumentParser(description="Command Processor")
|
parser = argparse.ArgumentParser(description="Command Processor")
|
||||||
parser.add_argument("--listen", type=ListenOption, choices=[ListenOption.SOCKET, ListenOption.QUEUE], default=ListenOption.SOCKET, help="socket: Local communication, queue: remote. Default is socket")
|
parser.add_argument("-e", "--email", type=str, default="", help="Email")
|
||||||
parser.add_argument("--email", type=str, default="", help="Email")
|
parser.add_argument("-p", "--pw", type=str, default="", help="Password")
|
||||||
parser.add_argument("--pw", type=str, default="", help="Password")
|
parser.add_argument("-f", "--folder", type=str, default="", help="Folder to API inner folder to download file from")
|
||||||
parser.add_argument("--folder", type=str, default="", help="Folder to API inner folder to download file from")
|
parser.add_argument("-t", "--persist_token", type=bool, default=True, help="True for persisting token from API")
|
||||||
parser.add_argument("--persist_token", type=bool, default=True, help="True for persisting token from API")
|
|
||||||
cdef args = parser.parse_args()
|
cdef args = parser.parse_args()
|
||||||
|
|
||||||
cdef ListenOption listen = ListenOption(args.listen)
|
|
||||||
cdef str email = args.email
|
cdef str email = args.email
|
||||||
cdef str password = args.pw
|
cdef str password = args.pw
|
||||||
cdef str folder = args.folder
|
cdef str folder = args.folder
|
||||||
cdef bint persist_token = args.persist_token
|
cdef bint persist_token = args.persist_token
|
||||||
|
|
||||||
return ParsedArguments(listen, email, password, folder, persist_token)
|
return ParsedArguments(email, password, folder, persist_token)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
args = parse_arguments()
|
args = parse_arguments()
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
cdef enum ProcessorType:
|
||||||
|
SOCKET = 1,
|
||||||
|
RABBIT = 2
|
||||||
|
|
||||||
|
cdef enum CommandType:
|
||||||
|
INFERENCE = 1
|
||||||
|
LOAD = 2
|
||||||
|
|
||||||
|
cdef class FileCommand:
|
||||||
|
cdef CommandType command_type
|
||||||
|
cdef ProcessorType processor_type
|
||||||
|
cdef str filename
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
cdef from_msgpack(bytes data, ProcessorType processor_type)
|
||||||
@@ -1,23 +1,13 @@
|
|||||||
import msgpack
|
import msgpack
|
||||||
|
|
||||||
cdef enum CommandType:
|
|
||||||
INFERENCE = 1
|
|
||||||
LOAD = 2
|
|
||||||
|
|
||||||
cdef enum ProcessorType:
|
|
||||||
SOCKET = 1,
|
|
||||||
RABBIT = 2
|
|
||||||
|
|
||||||
cdef class FileCommand:
|
cdef class FileCommand:
|
||||||
cdef str filename
|
def __init__(self, command_type: CommandType, ProcessorType processor_type, str filename):
|
||||||
|
|
||||||
def __init__(self, command_type: CommandType, processor_type: ProcessorType, str filename):
|
|
||||||
self.command_type = command_type
|
self.command_type = command_type
|
||||||
self.processor_type = processor_type
|
self.processor_type = processor_type
|
||||||
self.filename = filename
|
self.filename = filename
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
cdef from_msgpack(bytes data, processor_type: ProcessorType):
|
cdef from_msgpack(bytes data, ProcessorType processor_type):
|
||||||
unpacked = msgpack.unpackb(data, strict_map_key=False)
|
unpacked = msgpack.unpackb(data, strict_map_key=False)
|
||||||
return FileCommand(unpacked.get("CommandType"), processor_type, unpacked.get("Filename")
|
return FileCommand(unpacked.get("CommandType"), processor_type, unpacked.get("Filename")
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
from annotation cimport Annotation
|
||||||
|
|
||||||
|
cdef class SocketHandler:
|
||||||
|
cdef object on_message
|
||||||
|
cdef object _socket
|
||||||
|
cdef object _connection
|
||||||
|
|
||||||
|
cdef start(self)
|
||||||
|
cdef start_inner(self)
|
||||||
|
cdef send(self, list[Annotation] message)
|
||||||
|
cdef close(self)
|
||||||
|
|
||||||
|
cdef class RabbitHandler:
|
||||||
|
cdef object on_message
|
||||||
|
cdef object annotation_producer
|
||||||
|
cdef object command_consumer
|
||||||
|
|
||||||
|
cdef start(self)
|
||||||
|
cdef send(self, object message)
|
||||||
|
cdef close(self)
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
# cython: language_level=3
|
|
||||||
import json
|
import json
|
||||||
import socket
|
import socket
|
||||||
import struct
|
import struct
|
||||||
@@ -8,9 +7,10 @@ import msgpack
|
|||||||
from msgpack import packb
|
from msgpack import packb
|
||||||
from rstream import Producer, Consumer, AMQPMessage, ConsumerOffsetSpecification, OffsetType, MessageContext
|
from rstream import Producer, Consumer, AMQPMessage, ConsumerOffsetSpecification, OffsetType, MessageContext
|
||||||
|
|
||||||
import constants
|
cimport constants
|
||||||
from api_client import ApiClient
|
from api_client cimport ApiClient
|
||||||
from processor_command import FileCommand, ProcessorType
|
from processor_command cimport FileCommand, ProcessorType
|
||||||
|
from annotation cimport Annotation
|
||||||
|
|
||||||
cdef class QueueConfig:
|
cdef class QueueConfig:
|
||||||
cdef str host
|
cdef str host
|
||||||
@@ -35,15 +35,15 @@ cdef class QueueConfig:
|
|||||||
cdef class SocketHandler:
|
cdef class SocketHandler:
|
||||||
"""Handles socket communication with size-prefixed messages."""
|
"""Handles socket communication with size-prefixed messages."""
|
||||||
|
|
||||||
def __init__(self, on_message):
|
def __init__(self, object on_message):
|
||||||
self.on_message = on_message
|
self.on_message = on_message
|
||||||
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self._connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self._connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
self._socket.connect((constants.SOCKET_HOST, constants.SOCKET_PORT))
|
self._socket.bind((constants.SOCKET_HOST, constants.SOCKET_PORT))
|
||||||
self._socket.listen(1)
|
self._socket.listen(1)
|
||||||
|
|
||||||
cdef start(self):
|
cdef start(self):
|
||||||
threading.Thread(target=self.start, daemon=True).start()
|
threading.Thread(target=self.start_inner, daemon=True).start()
|
||||||
|
|
||||||
cdef start_inner(self):
|
cdef start_inner(self):
|
||||||
while True:
|
while True:
|
||||||
@@ -62,53 +62,50 @@ cdef class SocketHandler:
|
|||||||
cmd = FileCommand.from_msgpack(data, ProcessorType.SOCKET)
|
cmd = FileCommand.from_msgpack(data, ProcessorType.SOCKET)
|
||||||
self.on_message(cmd)
|
self.on_message(cmd)
|
||||||
|
|
||||||
async def send(self, object message):
|
cdef send(self, list[Annotation] message):
|
||||||
data = msgpack.packb(message)
|
data = msgpack.packb(message)
|
||||||
size_prefix = len(data).to_bytes(4, 'big')
|
size_prefix = len(data).to_bytes(4, 'big')
|
||||||
self._connection.sendall(size_prefix + data)
|
self._connection.sendall(size_prefix + data)
|
||||||
|
|
||||||
def close(self):
|
cdef close(self):
|
||||||
if self._socket:
|
if self._socket:
|
||||||
self._socket.close()
|
self._socket.close()
|
||||||
self._socket = None
|
self._socket = None
|
||||||
|
|
||||||
cdef class RabbitHandler:
|
cdef class RabbitHandler:
|
||||||
cdef str hardware_hash
|
def __init__(self, ApiClient api_client, object on_message):
|
||||||
|
|
||||||
def __init__(self, config_filename, on_message):
|
|
||||||
self.on_message = on_message
|
self.on_message = on_message
|
||||||
cdef str config_str = ApiClient().load_file(constants.QUEUE_CONFIG_FILENAME).decode(encoding='utf-8')
|
cdef str config_str = api_client.load_file(constants.QUEUE_CONFIG_FILENAME).decode(encoding='utf-8')
|
||||||
self.queue_config = QueueConfig.from_json(config_str)
|
queue_config = QueueConfig.from_json(config_str)
|
||||||
self.annotation_producer = Producer(
|
self.annotation_producer = Producer(
|
||||||
host=<str>self.queue_config.host,
|
host=<str>queue_config.host,
|
||||||
port=self.queue_config.port,
|
port=queue_config.port,
|
||||||
username=<str>self.queue_config.producer_user,
|
username=<str>queue_config.producer_user,
|
||||||
password=<str>self.queue_config.producer_pw
|
password=<str>queue_config.producer_pw
|
||||||
)
|
)
|
||||||
self.command_consumer = Consumer(
|
self.command_consumer = Consumer(
|
||||||
host=<str>self.queue_config.host,
|
host=<str>queue_config.host,
|
||||||
port=self.queue_config.port,
|
port=queue_config.port,
|
||||||
username=<str>self.queue_config.consumer_user,
|
username=<str>queue_config.consumer_user,
|
||||||
password=<str>self.queue_config.consumer_pw
|
password=<str>queue_config.consumer_pw
|
||||||
)
|
)
|
||||||
|
|
||||||
cdef start(self):
|
cdef start(self):
|
||||||
self.command_consumer.start()
|
self.command_consumer.start()
|
||||||
self.command_consumer.subscribe(stream=constants.COMMANDS_QUEUE, callback=self.on_message_inner,
|
self.command_consumer.subscribe(stream=<str>constants.COMMANDS_QUEUE, callback=self.on_message_inner,
|
||||||
offset_specification=ConsumerOffsetSpecification(OffsetType.FIRST, None)) # put real offset
|
offset_specification=ConsumerOffsetSpecification(OffsetType.FIRST, None)) # put real offset
|
||||||
|
|
||||||
|
def on_message_inner(self, message: AMQPMessage, message_context: MessageContext):
|
||||||
cdef on_message_inner(self, message: AMQPMessage, message_context: MessageContext):
|
|
||||||
cdef bytes body = message.body
|
cdef bytes body = message.body
|
||||||
cmd = FileCommand.from_msgpack(body, ProcessorType.RABBIT)
|
cmd = FileCommand.from_msgpack(body, ProcessorType.RABBIT)
|
||||||
self.on_message(cmd)
|
self.on_message(cmd)
|
||||||
|
|
||||||
cpdef send(self, object message):
|
cdef send(self, object message):
|
||||||
packed_message = AMQPMessage(body=packb(message))
|
packed_message = AMQPMessage(body=packb(message))
|
||||||
self.annotation_producer.send(constants.ANNOTATIONS_QUEUE, packed_message)
|
self.annotation_producer.send(<str>constants.ANNOTATIONS_QUEUE, packed_message)
|
||||||
|
|
||||||
async def close(self):
|
cdef close(self):
|
||||||
if self.annotation_producer:
|
if self.annotation_producer:
|
||||||
await self.annotation_producer.close()
|
self.annotation_producer.close()
|
||||||
if self.command_consumer:
|
if self.command_consumer:
|
||||||
await self.command_consumer.close()
|
self.command_consumer.close()
|
||||||
+7
-7
@@ -2,14 +2,15 @@ from setuptools import setup, Extension
|
|||||||
from Cython.Build import cythonize
|
from Cython.Build import cythonize
|
||||||
|
|
||||||
extensions = [
|
extensions = [
|
||||||
Extension('main', ['main.pyx']),
|
|
||||||
Extension('api_client', ['api_client.pyx']),
|
|
||||||
Extension('constants', ['constants.pyx']),
|
Extension('constants', ['constants.pyx']),
|
||||||
Extension('hardware_service', ['hardware_service.pyx']),
|
Extension('annotation', ['annotation.pyx']),
|
||||||
Extension('inference', ['inference.pyx']),
|
Extension('hardware_service', ['hardware_service.pyx'], extra_compile_args=["-g"], extra_link_args=["-g"]),
|
||||||
Extension('processor_command', ['processor_command.pyx']),
|
Extension('processor_command', ['processor_command.pyx']),
|
||||||
|
Extension('api_client', ['api_client.pyx']),
|
||||||
|
Extension('inference', ['inference.pyx']),
|
||||||
Extension('remote_handlers', ['remote_handlers.pyx']),
|
Extension('remote_handlers', ['remote_handlers.pyx']),
|
||||||
Extension('security', ['security.pyx'])
|
Extension('security', ['security.pyx']),
|
||||||
|
Extension('main', ['main.pyx']),
|
||||||
]
|
]
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
@@ -20,8 +21,7 @@ setup(
|
|||||||
"language_level": 3,
|
"language_level": 3,
|
||||||
"emit_code_comments" : False,
|
"emit_code_comments" : False,
|
||||||
"binding": True
|
"binding": True
|
||||||
},
|
}
|
||||||
gdb_debug=True
|
|
||||||
),
|
),
|
||||||
zip_safe=False
|
zip_safe=False
|
||||||
)
|
)
|
||||||
Reference in New Issue
Block a user