Revize 22c09a00
Přidáno uživatelem Jakub Šilhavý před asi 3 roky(ů)
client/resources/client.conf | ||
---|---|---|
1 |
# This file is the configuration of the application. |
|
2 |
# ================================================== |
|
3 |
|
|
1 | 4 |
[usb_detector] |
5 |
# Number of seconds after which all USB devices are periodically scanned. |
|
6 |
# This value is a float number. It can be set to, for example, 0.1, 0.5, 300, etc. |
|
2 | 7 |
scan_period_seconds = 1 |
8 |
|
|
9 |
# Path to the file that contains a list of the currently |
|
10 |
# connected USB devices. This file is updated whenever a device |
|
11 |
# is plugged or unplugged. |
|
3 | 12 |
connected_devices_filename = data/devices.json |
4 | 13 |
|
14 |
# ================================================== |
|
15 |
|
|
5 | 16 |
[server] |
17 |
# IP address of the server that the client sends data to. |
|
6 | 18 |
url = http://127.0.0.1 |
19 |
|
|
20 |
# Port that the server listens on. |
|
7 | 21 |
port = 8000 |
22 |
|
|
23 |
# Endpoint through which the server receives data from the client. |
|
24 |
# These three values (url, port, end_point) make up a URI that is |
|
25 |
# created internally by the client e.g. http://127.0.0.1:8000/api/v1/usb-logs |
|
8 | 26 |
end_point = /api/v1/usb-logs |
9 | 27 |
|
28 |
# ================================================== |
|
29 |
|
|
10 | 30 |
[logger] |
31 |
# Path to the logger configuration file |
|
11 | 32 |
config_file = ../resources/logger.conf |
12 | 33 |
|
34 |
# ================================================== |
|
35 |
|
|
13 | 36 |
[cache] |
37 |
# Name of the folder where the cache is held. This folder is created |
|
38 |
# automatically by the client. |
|
14 | 39 |
directory = data |
15 |
max_entries = 100 |
|
16 |
max_retries = 20 |
|
40 |
|
|
41 |
# Number of seconds after which the application attempts to resent a predefined |
|
42 |
# number of cached payloads to the server (periodically). |
|
17 | 43 |
retry_period_seconds = 20 |
44 |
|
|
45 |
# Maximum number of entries (payloads) that can be cached. If the total number of cached |
|
46 |
# payloads reaches this number, the application will discard the oldest record with |
|
47 |
# every new payload (FIFO - queue). |
|
48 |
max_entries = 100 |
|
49 |
|
|
50 |
# Number of cached entries (payloads) that can be sent to the server at a time (within one period). |
|
51 |
max_retries = 20 |
client/resources/logger.conf | ||
---|---|---|
1 |
# This file is the logger configuration file. |
|
2 |
# ========================================== |
|
3 |
|
|
1 | 4 |
[loggers] |
5 |
# Name of the logger. |
|
2 | 6 |
keys=root |
3 | 7 |
|
8 |
# ========================================== |
|
9 |
|
|
4 | 10 |
[handlers] |
5 |
keys=consoleHandler,logFileHandler |
|
11 |
# List of different types of handlers defined within the application. |
|
12 |
keys=consoleHandler, logFileHandler |
|
13 |
|
|
14 |
# ========================================== |
|
6 | 15 |
|
7 | 16 |
[formatters] |
17 |
# Name of the formatter used for the log messages. |
|
8 | 18 |
keys=simpleFormatter |
9 | 19 |
|
20 |
# ========================================== |
|
21 |
|
|
10 | 22 |
[logger_root] |
23 |
# Level of debugging set for the root logger. |
|
11 | 24 |
level=DEBUG |
25 |
|
|
26 |
# Handler set for the root logger. |
|
12 | 27 |
handlers=consoleHandler |
13 | 28 |
|
29 |
# ========================================== |
|
30 |
|
|
14 | 31 |
[handler_consoleHandler] |
32 |
# Class used for the console logger. |
|
15 | 33 |
class=StreamHandler |
34 |
|
|
35 |
# Level of debugging set for the console logger. |
|
16 | 36 |
level=DEBUG |
37 |
|
|
38 |
# Formatter used for for the console logger. |
|
17 | 39 |
formatter=simpleFormatter |
40 |
|
|
41 |
# Arguments passed in upon instantiating the logger. |
|
18 | 42 |
args=(sys.stdout,) |
19 | 43 |
|
44 |
# ========================================== |
|
45 |
|
|
20 | 46 |
[handler_logFileHandler] |
47 |
# Class used for the file logger - rotating file. |
|
21 | 48 |
class=handlers.RotatingFileHandler |
49 |
|
|
50 |
# Level of debugging set for the file logger. |
|
22 | 51 |
level=NOTSET |
52 |
|
|
53 |
# Arguments passed in when instantiating the logger. |
|
54 |
# log_file.log - name of the rotating log file |
|
55 |
# a - append to the file - do not overwrite it |
|
56 |
# 10485760 - maximum size of the file - 10 MB |
|
57 |
# 1 - number of backups kept on the disk |
|
23 | 58 |
args=('log_file.log', 'a', 10485760, 1) |
59 |
|
|
60 |
# Formatter used for the file logger. |
|
24 | 61 |
formatter=simpleFormatter |
25 | 62 |
|
63 |
# ========================================== |
|
64 |
|
|
26 | 65 |
[formatter_simpleFormatter] |
66 |
# Definition of a custom log formatter. All log |
|
67 |
# messages have the following format: [datetime] - [level] - [message] |
|
27 | 68 |
format=%(asctime)s - %(levelname)s - %(message)s |
client/src/usb_detector/api_client.py | ||
---|---|---|
6 | 6 |
from requests import HTTPError, ConnectionError |
7 | 7 |
from requests.exceptions import InvalidSchema |
8 | 8 |
|
9 |
_uri = None |
|
10 |
_cache = None |
|
11 |
_config = None |
|
9 |
|
|
10 |
_uri = None # server uri (url, port, and endpoint) |
|
11 |
_cache = None # cache (failed payloads) |
|
12 |
_config = None # instance of Config |
|
12 | 13 |
|
13 | 14 |
|
14 | 15 |
def api_client_set_config(config): |
16 |
"""Initializes the client API module. |
|
17 |
|
|
18 |
This function is meant to be called prior to calling any other function |
|
19 |
of the API module. It stores the instance of Config (config manager) |
|
20 |
into a private variable. It also initializes the cache for unsuccessful |
|
21 |
payloads and constructs a URI (endpoint on the server side). |
|
22 |
|
|
23 |
:param config: instance of Config which holds all values defined |
|
24 |
in the configuration file. |
|
25 |
""" |
|
26 |
# Store the variables globally within the module (file). |
|
15 | 27 |
global _config, _cache, _uri |
28 |
|
|
29 |
# Store the instance of Config and initialize the cache. |
|
16 | 30 |
_config = config |
17 | 31 |
_cache = _init_cache() |
32 |
|
|
33 |
# Creates the URI which is made of the server url, port, and path (endpoint). |
|
18 | 34 |
_uri = config.server_url + ":" + config.server_port + config.server_endpoint |
19 | 35 |
|
20 | 36 |
|
21 | 37 |
def _init_cache(): |
38 |
""" Initializes and returns a disk-based cache. |
|
39 |
|
|
40 |
The cache holds payloads that the application failed |
|
41 |
to send to the server. It periodically attempts to resent |
|
42 |
them to the server. All parameters can be seen in the |
|
43 |
configuration file. |
|
44 |
|
|
45 |
:return: instance of a new cache (Deque - FIFO) |
|
46 |
""" |
|
22 | 47 |
return Deque(directory=_config.cache_dir) |
23 | 48 |
|
24 | 49 |
|
25 | 50 |
def send_data(payload: dict): |
51 |
"""Sends a payload off to the server. |
|
52 |
|
|
53 |
This function is called whenever a USB is connected |
|
54 |
or disconnected. If there is no internet connection or the |
|
55 |
server is not up and running, the payload will be stored |
|
56 |
into the disk cache. |
|
57 |
|
|
58 |
:param payload: |
|
59 |
""" |
|
60 |
# Make sure that the URI has been constructed properly. |
|
61 |
# It's supposed to be done by calling the api_client_set_config function |
|
62 |
# with appropriate parameters. |
|
26 | 63 |
if _uri is None: |
27 | 64 |
logging.warning(f"sending payload = {payload} failed because uri is set to None") |
28 | 65 |
_cache_failed_payload(payload) |
... | ... | |
40 | 77 |
|
41 | 78 |
|
42 | 79 |
def _cache_failed_payload(payload: dict): |
80 |
""" Caches a payload. |
|
81 |
|
|
82 |
This function is called when the application fails to send a payload |
|
83 |
to the server. The payload gets stored into a file-based cache from which |
|
84 |
it will be periodically retrieved as the client will attempt to send |
|
85 |
it to the server again. All parameters regarding the cache can be found |
|
86 |
in the configuration file. |
|
87 |
|
|
88 |
:param payload: payload to be cached |
|
89 |
""" |
|
90 |
# If the cache is "full", discard the oldest record. |
|
43 | 91 |
if len(_cache) >= _config.cache_max_entries: |
44 | 92 |
oldest_payload = _cache.pop() |
45 | 93 |
logging.warning(f"cache is full - discarding payload = {oldest_payload}") |
46 | 94 |
|
95 |
# Store the payload into the cache. |
|
47 | 96 |
logging.info(f"adding payload = {payload} into cache") |
48 | 97 |
_cache.append(payload) |
49 | 98 |
|
50 | 99 |
|
51 | 100 |
def _resend_cached_payloads(): |
101 |
"""Reattempts to send cached payloads to the server (API). |
|
102 |
|
|
103 |
In the configuration file, there is a predefined number of |
|
104 |
payloads that can be sent to the server with each call of this function. |
|
105 |
This function is called periodically from api_client_run in order |
|
106 |
to resend failed payloads to the server. |
|
107 |
|
|
108 |
""" |
|
109 |
# Calculate how many payload will be sent to the server |
|
52 | 110 |
retries = min(_config.cache_max_retries, len(_cache)) |
53 | 111 |
logging.info(f"emptying the cache ({retries} records)") |
112 |
|
|
113 |
# Send the payloads to the server one by one. |
|
54 | 114 |
for _ in range(0, retries): |
55 | 115 |
payload = _cache.pop() |
56 | 116 |
send_data(payload) |
57 | 117 |
|
58 | 118 |
|
59 | 119 |
def api_client_run(): |
120 |
""" Keeps resending failed payloads to the server. |
|
121 |
|
|
122 |
This function is instantiated as a thread that periodically |
|
123 |
calls the _resend_cached_payloads function in order to empty |
|
124 |
the cache (failed payloads). The period can be set in the |
|
125 |
configuration file. |
|
126 |
""" |
|
60 | 127 |
while True: |
128 |
# Resend a predefined amount of failed payloads to the server. |
|
61 | 129 |
_resend_cached_payloads() |
130 |
|
|
131 |
# Sleep for a predefined amount of seconds. |
|
62 | 132 |
sleep(_config.cache_retry_period_seconds) |
Také k dispozici: Unified diff
re #9422 Commented both config files and api_client.py.