2023-06-19 17:16:00 +02:00
|
|
|
import logging
|
2022-05-18 16:02:23 +02:00
|
|
|
import socket
|
|
|
|
from typing import Optional
|
|
|
|
import json
|
|
|
|
import base64
|
|
|
|
|
2022-07-08 16:25:46 +02:00
|
|
|
from tmtccmd.util.obj_id import ObjectIdU32
|
2022-05-18 17:01:48 +02:00
|
|
|
from dle_encoder import DleEncoder
|
2022-05-18 16:02:23 +02:00
|
|
|
|
2023-06-19 17:16:00 +02:00
|
|
|
_LOGGER = logging.getLogger(__name__)
|
2022-05-18 16:02:23 +02:00
|
|
|
|
|
|
|
|
|
|
|
class TmTcpServer:
|
2022-06-01 10:47:57 +02:00
|
|
|
def __init__(self, ip_address: str, port: int):
|
2022-05-18 16:02:23 +02:00
|
|
|
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
|
2022-06-01 10:47:57 +02:00
|
|
|
self.server_socket.bind((ip_address, port))
|
2022-05-18 16:02:23 +02:00
|
|
|
|
|
|
|
# for now, only accept one connection
|
|
|
|
self.server_socket.listen(0)
|
|
|
|
|
|
|
|
self.server_socket.setblocking(False)
|
|
|
|
|
|
|
|
self.client_connection: Optional[socket.socket] = None
|
|
|
|
|
2022-05-18 17:01:48 +02:00
|
|
|
self.dle_encoder = DleEncoder()
|
|
|
|
|
2022-05-18 16:02:23 +02:00
|
|
|
def __del__(self):
|
|
|
|
try:
|
|
|
|
self.close()
|
2023-06-19 17:16:00 +02:00
|
|
|
except IOError:
|
|
|
|
_LOGGER.warning("Could not close sockets!")
|
2022-05-18 16:02:23 +02:00
|
|
|
|
|
|
|
def close(self):
|
|
|
|
self.server_socket.close()
|
2022-05-31 11:44:08 +02:00
|
|
|
if self.client_connection is not None:
|
2022-05-18 16:02:23 +02:00
|
|
|
self.client_connection.close()
|
|
|
|
|
|
|
|
def _send_dictionary_over_socket(self, dictionary):
|
|
|
|
# keep listeners current
|
2022-05-31 11:44:08 +02:00
|
|
|
if self.client_connection is None:
|
2022-05-18 16:02:23 +02:00
|
|
|
# no running connection, see if a client wants to connect
|
|
|
|
try:
|
|
|
|
(self.client_connection, _) = self.server_socket.accept()
|
|
|
|
self.client_connection.setblocking(False)
|
2022-06-02 18:51:40 +02:00
|
|
|
print("Client connected")
|
2023-06-19 17:16:00 +02:00
|
|
|
except IOError:
|
2022-05-18 16:02:23 +02:00
|
|
|
return
|
|
|
|
|
|
|
|
data_json_bytes = json.dumps(dictionary).encode()
|
|
|
|
|
|
|
|
# dle encode the bytes
|
2022-05-18 17:01:48 +02:00
|
|
|
# adding a newline because someone might want to look at it in a console
|
2022-05-19 13:20:22 +02:00
|
|
|
data_json_bytes = self.dle_encoder.encode(data_json_bytes + b"\n")
|
2022-05-18 16:02:23 +02:00
|
|
|
|
|
|
|
try:
|
|
|
|
sent_length = self.client_connection.send(data_json_bytes)
|
2023-06-19 17:16:00 +02:00
|
|
|
except IOError:
|
2022-05-18 16:02:23 +02:00
|
|
|
self.client_connection = None
|
|
|
|
return
|
|
|
|
if sent_length == 0:
|
|
|
|
self.client_connection.close()
|
|
|
|
self.client_connection = None
|
|
|
|
|
2022-07-05 02:12:54 +02:00
|
|
|
def report_raw_hk_data(self, object_id: ObjectIdU32, set_id: int, hk_data: bytes):
|
2022-05-19 13:20:22 +02:00
|
|
|
data_dict = {
|
|
|
|
"type": "TM",
|
|
|
|
"tmType": "Raw HK",
|
2022-07-04 15:22:53 +02:00
|
|
|
"objectId": object_id.as_hex_string,
|
2022-05-19 13:20:22 +02:00
|
|
|
"setId": set_id,
|
|
|
|
"rawData": base64.b64encode(hk_data).decode(),
|
|
|
|
}
|
2022-05-18 16:02:23 +02:00
|
|
|
|
|
|
|
self._send_dictionary_over_socket(data_dict)
|
|
|
|
|
2022-07-05 02:12:54 +02:00
|
|
|
def report_parsed_hk_data(
|
|
|
|
self, object_id: ObjectIdU32, set_id: int, data_dictionary
|
|
|
|
):
|
2022-05-19 13:20:22 +02:00
|
|
|
data_dict = {
|
|
|
|
"type": "TM",
|
|
|
|
"tmType": "Parsed HK",
|
2022-07-04 15:22:53 +02:00
|
|
|
"objectId": object_id.as_hex_string,
|
2022-05-19 13:20:22 +02:00
|
|
|
"setId": set_id,
|
|
|
|
"content": data_dictionary,
|
|
|
|
}
|
|
|
|
|
|
|
|
self._send_dictionary_over_socket(data_dict)
|