telemetry-server 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,58 @@
1
+ Metadata-Version: 2.4
2
+ Name: telemetry_server
3
+ Version: 0.1.0
4
+ Project-URL: repository, https://github.com/autoboat-vt/telemetry_server
5
+ Description-Content-Type: text/markdown
6
+ Requires-Dist: flask
7
+ Requires-Dist: gunicorn
8
+
9
+ # Autoboat Telemetry Server
10
+
11
+ A lightweight Flask-based web server to collect, display, and manage telemetry data from the Virginia Tech Autoboat project.
12
+
13
+ ## 📦 Project Structure
14
+
15
+ ```txt
16
+ autoboat_telemetry_server/
17
+ ├── __init__.py # App factory
18
+ ├── routes
19
+ ├── __init__.py # Routes initialization
20
+ ├── autopilot_parameters.py # Autopilot parameters routes
21
+ ├── boat_status.py # Boat status routes
22
+ ├── waypoints.py # Waypoints management routes
23
+
24
+ instance/
25
+ ├── config.py # Configuration file
26
+ ```
27
+
28
+ ## 🚀 Quick Start
29
+
30
+ ### Installation
31
+
32
+ ```bash
33
+ pip install -e .
34
+ ```
35
+
36
+ ### Running the server
37
+
38
+ 1. Production ([Gunicorn](https://gunicorn.org/)):
39
+
40
+ ```bash
41
+ gunicorn "autoboat_telemetry_server:create_app()"
42
+ ```
43
+
44
+ 2. Development (Flask):
45
+
46
+ ```bash
47
+ flask run
48
+ ```
49
+
50
+ ## Server (Long term)
51
+
52
+ ### Installation
53
+
54
+ ```bash
55
+ git clone https://github.com/autoboat-vt/telemetry_server
56
+ cd telemetry_server
57
+ ./server_files/install.sh
58
+ ```
@@ -0,0 +1,50 @@
1
+ # Autoboat Telemetry Server
2
+
3
+ A lightweight Flask-based web server to collect, display, and manage telemetry data from the Virginia Tech Autoboat project.
4
+
5
+ ## 📦 Project Structure
6
+
7
+ ```txt
8
+ autoboat_telemetry_server/
9
+ ├── __init__.py # App factory
10
+ ├── routes
11
+ ├── __init__.py # Routes initialization
12
+ ├── autopilot_parameters.py # Autopilot parameters routes
13
+ ├── boat_status.py # Boat status routes
14
+ ├── waypoints.py # Waypoints management routes
15
+
16
+ instance/
17
+ ├── config.py # Configuration file
18
+ ```
19
+
20
+ ## 🚀 Quick Start
21
+
22
+ ### Installation
23
+
24
+ ```bash
25
+ pip install -e .
26
+ ```
27
+
28
+ ### Running the server
29
+
30
+ 1. Production ([Gunicorn](https://gunicorn.org/)):
31
+
32
+ ```bash
33
+ gunicorn "autoboat_telemetry_server:create_app()"
34
+ ```
35
+
36
+ 2. Development (Flask):
37
+
38
+ ```bash
39
+ flask run
40
+ ```
41
+
42
+ ## Server (Long term)
43
+
44
+ ### Installation
45
+
46
+ ```bash
47
+ git clone https://github.com/autoboat-vt/telemetry_server
48
+ cd telemetry_server
49
+ ./server_files/install.sh
50
+ ```
@@ -0,0 +1,146 @@
1
+ [project]
2
+ name = "telemetry_server"
3
+ version = "0.1.0"
4
+ readme = "README.md"
5
+ dependencies = ["flask", "gunicorn"]
6
+
7
+ [project.urls]
8
+ repository = "https://github.com/autoboat-vt/telemetry_server"
9
+
10
+ [build-system]
11
+ requires = ["setuptools", "wheel"]
12
+ build-backend = "setuptools.build_meta"
13
+
14
+ [tool.ruff]
15
+ # Exclude a variety of commonly ignored directories.
16
+ exclude = [
17
+ ".bzr",
18
+ ".direnv",
19
+ ".eggs",
20
+ ".git",
21
+ ".git-rewrite",
22
+ ".hg",
23
+ ".ipynb_checkpoints",
24
+ ".mypy_cache",
25
+ ".nox",
26
+ ".pants.d",
27
+ "**/.pyenv/**",
28
+ ".pyenv",
29
+ ".pytest_cache",
30
+ ".pytype",
31
+ ".ruff_cache",
32
+ ".svn",
33
+ ".tox",
34
+ ".venv",
35
+ ".vscode",
36
+ "__pypackages__",
37
+ "_build",
38
+ "buck-out",
39
+ "build",
40
+ "dist",
41
+ "node_modules",
42
+ "site-packages",
43
+ "venv",
44
+ ]
45
+
46
+ # Same as Black.
47
+ line-length = 135
48
+ indent-width = 4
49
+
50
+ # Assume Python 3.12
51
+ target-version = "py312"
52
+
53
+ # Also format files in .gitignore
54
+ respect-gitignore = false
55
+
56
+ [tool.ruff.lint]
57
+ # Enable all rules, then selectively ignore some below.
58
+ select = ["ALL"]
59
+
60
+ ignore = [
61
+ "BLE001", # Do not catch blind exception: `Exception`
62
+ "CPY001", # Missing copyright notice at top of file
63
+ "COM812", # Trailing comma missing
64
+ "S101", # Use of `assert` detected
65
+ "S113", # Probable use of `requests` call without timeout
66
+ "SIM115", # Use a context manager for opening files
67
+ "SLF001", # Private member accessed
68
+ "I001", # Import block is un-sorted or un-formatted
69
+ "INP001", # implicit-namespace-package
70
+ "D100", # undocumented-public-module
71
+ "D101", # undocumented-public-class
72
+ "D102", # undocumented-public-method
73
+ "D107", # undocumented-public-init
74
+ "D202", # blank-line-after-function
75
+ "D205", # missing-blank-line-after-summary
76
+ "D400", # missing-trailing-period
77
+ "D401", # non-imperative-mood
78
+ "C901", # Method is too complex
79
+ "E401", # multiple-imports-on-one-line
80
+ "E501", # line-too-long
81
+ "E741", # ambiguous-variable-name
82
+ "E711", # Comparison to `None` should be `if cond is None:`
83
+ "E712", # Comparison to `True` or `False` should use `is`
84
+ "EM101", # Exception must not use a string literal, assign to variable first
85
+ "ERA001", # commented-out-code
86
+ "EXE002", # The file is executable but no shebang is present
87
+ "EM102", # Exception must not use an f-string literal, assign to variable first
88
+ "F403", # undefined-local-with-import-star
89
+ "F405", # undefined-local-with-import-star-usage
90
+ "FA100", # future-rewritable-type-annotation
91
+ "FBT001", # Boolean positional value in function definition
92
+ "FBT002", # Boolean positional value in function definition with default value
93
+ "FBT003", # Boolean positional value in function call
94
+ "N802", # checks for functions names that do not follow the snake_case naming convention.
95
+ "N813", # checks for variable names that do not follow the snake_case naming convention.
96
+ "PLR0904", # Too many public methods (... > 20)
97
+ "PLR0912", # Too many branches
98
+ "PLR0913", # Too many arguments for function (... > 5)
99
+ "PLR0915", # too-many-statements
100
+ "PLR2004", # Magic value used in comparison
101
+ "PTH", # use of functions that can be replaced by pathlib module.
102
+ "T201", # Checks for print statements.
103
+ "TD002", # Missing author in TODO `# TODO(<author_name>): ...`
104
+ "TD003", # missing-todo-link
105
+ "TD004", # todo missing colon
106
+ "TRY002", # Create your own exception
107
+ "TRY003", # Avoid specifying long messages outside the exception class
108
+ "TRY301", # raise-within-try
109
+ "RET504", # Unnecessary assignment of `return` value to a variable
110
+ "RET505", # Unnecessary `else` after `return` statement
111
+ "G004", # logging-f-string
112
+ "UP015", # Unnecessary mode argument for `open` function
113
+ "W293", # Blank line contains whitespace
114
+ "Q000", # Single quotes found but double quotes preferred
115
+ ]
116
+
117
+ unfixable = [
118
+ "F401", # Module imported but unused
119
+ ]
120
+
121
+ # Allow unused variables when underscore-prefixed.
122
+ dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
123
+
124
+ [tool.ruff.lint.pydocstyle]
125
+ convention = "pep257"
126
+
127
+ [tool.ruff.format]
128
+ # Like Black, use double quotes for strings.
129
+ quote-style = "double"
130
+
131
+ # Like Black, indent with spaces, rather than tabs.
132
+ indent-style = "space"
133
+
134
+ # Like Black, respect magic trailing commas.
135
+ skip-magic-trailing-comma = false
136
+
137
+ # Like Black, automatically detect the appropriate line ending.
138
+ line-ending = "auto"
139
+
140
+ # Enable auto-formatting of code examples in docstrings. Markdown,
141
+ # reStructuredText code/literal blocks and doctests are all supported.
142
+ docstring-code-format = true
143
+
144
+ # Set the line length limit used when formatting code snippets in
145
+ # docstrings (only has an effect when docstring-code-format is enabled).
146
+ docstring-code-line-length = "dynamic"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,6 @@
1
+ from autoboat_telemetry_server import create_app
2
+
3
+ app = create_app()
4
+
5
+ if __name__ == "__main__":
6
+ app.run()
@@ -0,0 +1,44 @@
1
+ """Telemetry server for Autoboat at Virginia Tech."""
2
+
3
+ import os
4
+ from flask import Flask as _flask
5
+ from autoboat_telemetry_server.routes import AutopilotParametersEndpoint, BoatStatusEndpoint, WaypointEndpoint
6
+
7
+ __all__ = ["create_app"]
8
+
9
+
10
+ def create_app() -> _flask:
11
+ """
12
+ Create and configure the Flask application instance.
13
+
14
+ Returns
15
+ -------
16
+ _flask
17
+ Configured Flask application instance.
18
+ """
19
+
20
+ app = _flask(__name__)
21
+
22
+ instance_dir = "/home/ubuntu/telemetry_server/src/instance"
23
+ config_path = os.path.join(instance_dir, "config.py")
24
+
25
+ app.config.from_pyfile(config_path)
26
+
27
+ app.register_blueprint(AutopilotParametersEndpoint().blueprint)
28
+ app.register_blueprint(BoatStatusEndpoint().blueprint)
29
+ app.register_blueprint(WaypointEndpoint().blueprint)
30
+
31
+ @app.route("/")
32
+ def index() -> str:
33
+ """
34
+ Root route for the telemetry server.
35
+
36
+ Returns
37
+ -------
38
+ str
39
+ Confirmation message indicating which server is running.
40
+ """
41
+
42
+ return "This is the production telemetry server. It is running!"
43
+
44
+ return app
@@ -0,0 +1,29 @@
1
+ """
2
+ Module containing the routes for the Autoboat telemetry server.
3
+
4
+ Autopilot Routes:
5
+ - `/autopilot_parameters/test`: Test route for autopilot parameters.
6
+ - `/autopilot_parameters/get`: Get the current autopilot parameters.
7
+ - `/autopilot_parameters/get_new`: Get the latest autopilot parameters if they haven't been seen yet.
8
+ - `/autopilot_parameters/get_default`: Get the default autopilot parameters.
9
+ - `/autopilot_parameters/set`: Set the autopilot parameters from the request data.
10
+ - `/autopilot_parameters/set_default`: Set the default autopilot parameters from the request data.
11
+
12
+ Boat Status Routes:
13
+ - `/boat_status/test`: Test route for boat status.
14
+ - `/boat_status/get`: Get the current boat status.
15
+ - `/boat_status/get_new`: Get the latest boat status if it hasn't been seen yet.
16
+ - `/boat_status/set`: Set the boat status from the request data.
17
+
18
+ Waypoint Routes:
19
+ - `/waypoints/test`: Test route for waypoints.
20
+ - `/waypoints/get`: Get the current waypoints.
21
+ - `/waypoints/get_new`: Get the latest waypoints if they haven't been seen yet.
22
+ - `/waypoints/set`: Set the waypoints from the request data.
23
+ """
24
+
25
+ __all__ = ["AutopilotParametersEndpoint", "BoatStatusEndpoint", "WaypointEndpoint"]
26
+
27
+ from .autopilot_parameters import AutopilotParametersEndpoint
28
+ from .boat_status import BoatStatusEndpoint
29
+ from .waypoints import WaypointEndpoint
@@ -0,0 +1,176 @@
1
+ from flask import Blueprint, Response, jsonify, request
2
+ from typing import Literal, Any
3
+
4
+
5
+ class AutopilotParametersEndpoint:
6
+ """Endpoint for handling autopilot parameters."""
7
+
8
+ def __init__(self) -> None:
9
+ self._blueprint = Blueprint("autopilot_parameters_page", __name__, url_prefix="/autopilot_parameters")
10
+ self.autopilot_parameters: dict[str, Any] = {}
11
+ self.default_autopilot_parameters: dict[str, Any] = {}
12
+ self.new_flag: bool = False
13
+ self._register_routes()
14
+
15
+ @property
16
+ def blueprint(self) -> Blueprint:
17
+ """Returns the Flask blueprint for autopilot parameters."""
18
+
19
+ return self._blueprint
20
+
21
+ def _register_routes(self) -> str:
22
+ """
23
+ Registers the routes for the autopilot parameters endpoint.
24
+
25
+ Returns
26
+ -------
27
+ str
28
+ Confirmation message indicating the routes have been registered successfully.
29
+ """
30
+
31
+ @self._blueprint.route("/test", methods=["GET"])
32
+ def test_route() -> Literal["autopilot_parameters route testing!"]:
33
+ """
34
+ Test route for autopilot parameters.
35
+
36
+ Method: GET
37
+
38
+ Returns
39
+ -------
40
+ Literal["autopilot_parameters route testing!"]
41
+ Confirmation message for testing the autopilot parameters route.
42
+ """
43
+
44
+ return "autopilot_parameters route testing!"
45
+
46
+ @self._blueprint.route("/get", methods=["GET"])
47
+ def get_route() -> tuple[Response, int]:
48
+ """
49
+ Get the current autopilot parameters.
50
+
51
+ Method: GET
52
+
53
+ Returns
54
+ -------
55
+ tuple[Response, int]
56
+ A tuple containing the JSON response of the autopilot parameters and the HTTP status code.
57
+ """
58
+
59
+ return jsonify(self.autopilot_parameters), 200
60
+
61
+ @self._blueprint.route("/get_new", methods=["GET"])
62
+ def get_new_route() -> tuple[Response, int]:
63
+ """
64
+ Get the latest autopilot parameters if they haven't been seen yet.
65
+
66
+ Method: GET
67
+
68
+ Returns
69
+ -------
70
+ tuple[Response, int]
71
+ A tuple containing the JSON response of the autopilot parameters if new,
72
+ otherwise an empty JSON object, along with the HTTP status code.
73
+ """
74
+
75
+ if self.new_flag:
76
+ self.new_flag = False
77
+ return jsonify(self.autopilot_parameters), 200
78
+
79
+ else:
80
+ return jsonify({}), 200
81
+
82
+ @self._blueprint.route("/get_default", methods=["GET"])
83
+ def get_default_route() -> tuple[Response, int]:
84
+ """
85
+ Get the default autopilot parameters.
86
+
87
+ Method: GET
88
+
89
+ Returns
90
+ -------
91
+ tuple[Response, int]
92
+ A tuple containing the JSON response of the default autopilot parameters and the HTTP status code.
93
+ """
94
+
95
+ return jsonify(self.default_autopilot_parameters), 200
96
+
97
+ @self._blueprint.route("/set", methods=["POST"])
98
+ def set_route() -> tuple[Response, int]:
99
+ """
100
+ Set the autopilot parameters from the request data.
101
+
102
+ Method: POST
103
+
104
+ Returns
105
+ -------
106
+ tuple[Response, int]
107
+ A tuple containing a success message or error message and the corresponding HTTP status code.
108
+ """
109
+
110
+ try:
111
+ new_parameters = request.json
112
+ if not isinstance(new_parameters, dict):
113
+ raise TypeError("Invalid autopilot parameters format. Expected a dictionary.")
114
+
115
+ if self.default_autopilot_parameters != {}:
116
+ new_parameters_keys = list(new_parameters.keys())
117
+ if len(new_parameters_keys) == 1 and new_parameters_keys[0] in self.default_autopilot_parameters:
118
+ self.autopilot_parameters[new_parameters_keys[0]] = new_parameters[new_parameters_keys[0]]
119
+
120
+ elif new_parameters_keys == list(self.default_autopilot_parameters.keys()):
121
+ self.autopilot_parameters = new_parameters
122
+
123
+ else:
124
+ raise ValueError("Invalid keys in autopilot parameters.")
125
+
126
+ else:
127
+ self.autopilot_parameters = new_parameters
128
+
129
+ self.new_flag = True
130
+ return jsonify("Autopilot parameters updated successfully."), 200
131
+
132
+ except TypeError as e:
133
+ return jsonify(str(e)), 400
134
+
135
+ except ValueError as e:
136
+ return jsonify(str(e)), 400
137
+
138
+ except Exception as e:
139
+ return jsonify(str(e)), 500
140
+
141
+ @self._blueprint.route("/set_default", methods=["POST"])
142
+ def set_default_route() -> tuple[Response, int]:
143
+ """
144
+ Set the default autopilot parameters from the request data.
145
+
146
+ Method: POST
147
+
148
+ Returns
149
+ -------
150
+ tuple[Response, int]
151
+ A tuple containing a success message or error message and the corresponding HTTP status code.
152
+ """
153
+
154
+ try:
155
+ new_default_parameters = request.json
156
+ if not isinstance(new_default_parameters, dict):
157
+ raise TypeError("Invalid default autopilot parameters format. Expected a dictionary.")
158
+
159
+ if new_default_parameters != {}:
160
+ filtered_autopilot_parameters = {}
161
+ for key in new_default_parameters:
162
+ if key in self.default_autopilot_parameters:
163
+ filtered_autopilot_parameters[key] = new_default_parameters[key]
164
+
165
+ self.autopilot_parameters = filtered_autopilot_parameters
166
+
167
+ self.default_autopilot_parameters = new_default_parameters
168
+ return jsonify("Default autopilot parameters updated successfully."), 200
169
+
170
+ except TypeError as e:
171
+ return jsonify(str(e)), 400
172
+
173
+ except Exception as e:
174
+ return jsonify(str(e)), 500
175
+
176
+ return f"autopilot_parameters paths registered successfully: {self._blueprint.url_prefix}"
@@ -0,0 +1,108 @@
1
+ from flask import Blueprint, Response, jsonify, request
2
+ from typing import Literal, Any
3
+
4
+
5
+ class BoatStatusEndpoint:
6
+ """Endpoint for handling boat status."""
7
+
8
+ def __init__(self) -> None:
9
+ self._blueprint = Blueprint("boat_status_page", __name__, url_prefix="/boat_status")
10
+ self.boat_status: dict[str, Any] = {}
11
+ self.new_flag: bool = False
12
+ self._register_routes()
13
+
14
+ @property
15
+ def blueprint(self) -> Blueprint:
16
+ """Returns the Flask blueprint for autopilot parameters."""
17
+ return self._blueprint
18
+
19
+ def _register_routes(self) -> str:
20
+ """
21
+ Registers the routes for the boat status endpoint.
22
+
23
+ Returns
24
+ -------
25
+ str
26
+ Confirmation message indicating the routes have been registered successfully.
27
+ """
28
+
29
+ @self._blueprint.route("/test", methods=["GET"])
30
+ def test_route() -> Literal["boat_status route testing!"]:
31
+ """
32
+ Test route for boat status.
33
+
34
+ Method: GET
35
+
36
+ Returns
37
+ -------
38
+ Literal["boat_status route testing!"]
39
+ Confirmation message for testing the boat status route.
40
+ """
41
+
42
+ return "boat_status route testing!"
43
+
44
+ @self._blueprint.route("/get", methods=["GET"])
45
+ def get_route() -> tuple[Response, int]:
46
+ """
47
+ Get the current boat status.
48
+
49
+ Method: GET
50
+
51
+ Returns
52
+ -------
53
+ tuple[Response, int]
54
+ A tuple containing the JSON response of the boat status and the HTTP status code.
55
+ """
56
+
57
+ return jsonify(self.boat_status)
58
+
59
+ @self._blueprint.route("/get_new", methods=["GET"])
60
+ def get_new_route() -> tuple[Response, int]:
61
+ """
62
+ Get the latest boat status if it hasn't been seen yet.
63
+
64
+ Method: GET
65
+
66
+ Returns
67
+ -------
68
+ tuple[Response, int]
69
+ A tuple containing the JSON response of the new boat status (or empty if none) and the HTTP status code.
70
+ """
71
+
72
+ if self.new_flag:
73
+ self.new_flag = False
74
+ return jsonify(self.boat_status), 200
75
+
76
+ else:
77
+ return jsonify({}), 200
78
+
79
+ @self._blueprint.route("/set", methods=["POST"])
80
+ def set_route() -> tuple[Response, int]:
81
+ """
82
+ Set the boat status from the request data.
83
+
84
+ Method: POST
85
+
86
+ Returns
87
+ -------
88
+ tuple[Response, int]
89
+ A tuple containing a confirmation message and the HTTP status code.
90
+ """
91
+
92
+ try:
93
+ new_status = request.json
94
+ if not isinstance(new_status, dict):
95
+ raise TypeError("Invalid boat status format. Expected a dictionary.")
96
+
97
+ self.boat_status = new_status
98
+ self.new_flag = True
99
+
100
+ return jsonify("Boat status updated successfully."), 200
101
+
102
+ except TypeError as e:
103
+ return jsonify(str(e)), 400
104
+
105
+ except Exception as e:
106
+ return jsonify(str(e)), 500
107
+
108
+ return f"boat_status paths registered successfully: {self._blueprint.url_prefix}"
@@ -0,0 +1,108 @@
1
+ from flask import Blueprint, Response, jsonify, request
2
+ from typing import Literal
3
+
4
+
5
+ class WaypointEndpoint:
6
+ """Endpoint for handling waypoints."""
7
+
8
+ def __init__(self) -> None:
9
+ self._blueprint = Blueprint("waypoints_page", __name__, url_prefix="/waypoints")
10
+ self.waypoints: list[list[float]] = []
11
+ self.new_flag: bool = False
12
+ self._register_routes()
13
+
14
+ @property
15
+ def blueprint(self) -> Blueprint:
16
+ """Returns the Flask blueprint for autopilot parameters."""
17
+ return self._blueprint
18
+
19
+ def _register_routes(self) -> str:
20
+ """
21
+ Registers the routes for the waypoints endpoint.
22
+
23
+ Returns
24
+ -------
25
+ str
26
+ Confirmation message indicating the routes have been registered successfully.
27
+ """
28
+
29
+ @self._blueprint.route("/test", methods=["GET"])
30
+ def test_route() -> Literal["waypoints route testing!"]:
31
+ """
32
+ Test route for waypoints.
33
+
34
+ Method: GET
35
+
36
+ Returns
37
+ -------
38
+ Literal["waypoints route testing!"]
39
+ Confirmation message for testing the waypoints route.
40
+ """
41
+
42
+ return "waypoints route testing!"
43
+
44
+ @self._blueprint.route("/get", methods=["GET"])
45
+ def get_route() -> tuple[Response, int]:
46
+ """
47
+ Get the current waypoints.
48
+
49
+ Method: GET
50
+
51
+ Returns
52
+ -------
53
+ tuple[Response, int]
54
+ A tuple containing the JSON response of the waypoints and the HTTP status code.
55
+ """
56
+
57
+ return jsonify(self.waypoints), 200
58
+
59
+ @self._blueprint.route("/get_new", methods=["GET"])
60
+ def get_new_route() -> tuple[Response, int]:
61
+ """
62
+ Get the latest waypoints if they haven't been seen yet.
63
+
64
+ Method: GET
65
+
66
+ Returns
67
+ -------
68
+ tuple[Response, int]
69
+ A tuple containing the JSON response of the new waypoints (or empty if none) and the HTTP status code.
70
+ """
71
+
72
+ if self.new_flag:
73
+ self.new_flag = False
74
+ return jsonify(self.waypoints), 200
75
+
76
+ else:
77
+ return jsonify({}), 200
78
+
79
+ @self._blueprint.route("/set", methods=["POST"])
80
+ def set_route() -> tuple[Response, int]:
81
+ """
82
+ Set the waypoints from the request data.
83
+
84
+ Method: POST
85
+
86
+ Returns
87
+ -------
88
+ tuple[Response, int]
89
+ A tuple containing a confirmation message and the HTTP status code.
90
+ """
91
+
92
+ try:
93
+ new_waypoints = request.json
94
+ if not isinstance(new_waypoints, list):
95
+ raise TypeError("Invalid waypoints format. Expected a list of lists of floats.")
96
+
97
+ self.waypoints = new_waypoints
98
+ self.new_flag = True
99
+
100
+ return jsonify("Waypoints updated successfully."), 200
101
+
102
+ except TypeError as e:
103
+ return jsonify(str(e)), 400
104
+
105
+ except Exception as e:
106
+ return jsonify(str(e)), 500
107
+
108
+ return f"waypoints paths registered successfully: {self._blueprint.url_prefix}"
@@ -0,0 +1,5 @@
1
+ import os
2
+
3
+ BASE_DIR = os.path.abspath(os.path.dirname(__file__))
4
+ SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.join(BASE_DIR, 'app.db')}"
5
+ SQLALCHEMY_TRACK_MODIFICATIONS = False
@@ -0,0 +1,58 @@
1
+ Metadata-Version: 2.4
2
+ Name: telemetry_server
3
+ Version: 0.1.0
4
+ Project-URL: repository, https://github.com/autoboat-vt/telemetry_server
5
+ Description-Content-Type: text/markdown
6
+ Requires-Dist: flask
7
+ Requires-Dist: gunicorn
8
+
9
+ # Autoboat Telemetry Server
10
+
11
+ A lightweight Flask-based web server to collect, display, and manage telemetry data from the Virginia Tech Autoboat project.
12
+
13
+ ## 📦 Project Structure
14
+
15
+ ```txt
16
+ autoboat_telemetry_server/
17
+ ├── __init__.py # App factory
18
+ ├── routes
19
+ ├── __init__.py # Routes initialization
20
+ ├── autopilot_parameters.py # Autopilot parameters routes
21
+ ├── boat_status.py # Boat status routes
22
+ ├── waypoints.py # Waypoints management routes
23
+
24
+ instance/
25
+ ├── config.py # Configuration file
26
+ ```
27
+
28
+ ## 🚀 Quick Start
29
+
30
+ ### Installation
31
+
32
+ ```bash
33
+ pip install -e .
34
+ ```
35
+
36
+ ### Running the server
37
+
38
+ 1. Production ([Gunicorn](https://gunicorn.org/)):
39
+
40
+ ```bash
41
+ gunicorn "autoboat_telemetry_server:create_app()"
42
+ ```
43
+
44
+ 2. Development (Flask):
45
+
46
+ ```bash
47
+ flask run
48
+ ```
49
+
50
+ ## Server (Long term)
51
+
52
+ ### Installation
53
+
54
+ ```bash
55
+ git clone https://github.com/autoboat-vt/telemetry_server
56
+ cd telemetry_server
57
+ ./server_files/install.sh
58
+ ```
@@ -0,0 +1,14 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/app.py
4
+ src/autoboat_telemetry_server/__init__.py
5
+ src/autoboat_telemetry_server/routes/__init__.py
6
+ src/autoboat_telemetry_server/routes/autopilot_parameters.py
7
+ src/autoboat_telemetry_server/routes/boat_status.py
8
+ src/autoboat_telemetry_server/routes/waypoints.py
9
+ src/instance/config.py
10
+ src/telemetry_server.egg-info/PKG-INFO
11
+ src/telemetry_server.egg-info/SOURCES.txt
12
+ src/telemetry_server.egg-info/dependency_links.txt
13
+ src/telemetry_server.egg-info/requires.txt
14
+ src/telemetry_server.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ flask
2
+ gunicorn
@@ -0,0 +1,3 @@
1
+ app
2
+ autoboat_telemetry_server
3
+ instance