Skip to content

Commit b5f4f0f

Browse files
committed
fix conflicts
2 parents b3d09a4 + a5f7b66 commit b5f4f0f

16 files changed

Lines changed: 298 additions & 507 deletions

File tree

CONTRIBUTING.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ If the issue is not created yet, go to the issues page and create a new *task* i
2222
* If the issue is specific to one module (e.g. backend, ethernet view, etc.) start the title with `[module_name]`, changing *module_name* to the appropiate one.
2323
* Add the appropiate labels: is the issue related to the *frontend*, the *backend*, is it a *documentation* task? Try to identify these before creating the issue.
2424
* Assign yourself (or the member who will work on it) so they get notified with updates and everyone knows what everyone is doing.
25-
* Add the issue to the `Software H9` project to keep track of its progress.
25+
* Add the issue to the `Software HX` project to keep track of its progress.
2626
* Assign the issue to a milestone if possible.
2727
* Describe the task briefly. Write some lines on the task itself, what should be done, any details, notes on it, etc.
2828
* Add related issues / PRs. This is not required, but is useful, specially when tasks get blocked by other tasks.
@@ -36,7 +36,7 @@ Of course don't become too obsessed with this, it's always best to try out somet
3636

3737
It is also recommended to ask other members their points of view, what they are doing, dependencies they might have, etc. To get more ideas and ensure your changes won't screw with other person changes.
3838

39-
Also make sure to take notes, maybe in `software-docs` or as a comment on the issue, with anything relevant you found from this research. It might even be necessary to open new issues if you find anything outside the scope of the task.
39+
Also make sure to take notes and create a wiki entry with anything relevant you found from this research. It might even be necessary to open new issues if you find anything outside the scope of the task.
4040

4141
But once again, don't take more than a day doing this.
4242

@@ -66,15 +66,15 @@ Examples of good branch names are: `backend/tcp-keepalive-error`, `ethernet-view
6666

6767
Some bad examples are: `abc`, `backend/minor-fixes` or `unrelated-module/some-feature`.
6868

69-
### writing code
69+
### Writing code
7070

7171
With the latest changes ready, the new branch created, and everything set up, you are ready to write code at last. These are some guidelines on how to make good changes:
7272

7373
* Keep changes to the module you are working on, if your task involves multiple modules make the changes in the first module's branch and then switch to the second module's branch.
7474
* Keep commits atomic. These are commits that change just one specific thing, allowing the app to be compiled before and after.
7575
* Don't extend a branch life time, try to merge changes as soon as possible. If there are a lot of changes create multiple PRs and do it progresively.
7676
* Keep PRs small. Of course there are exceptions to this and sometimes a PR will have more lines than others.
77-
* Document what you do, dedicate some time to write down the why and how of your changes. Documentation not that related to the code should be written to `software-docs`.
77+
* Document what you do, dedicate some time to write down the why and how of your changes. Documentation not that related to the code should be written to the wiki.
7878
* Try to test the code. Prepare at least a primitive test to ensure it works, of course, it is better if tests are automatic, but in some cases, it is just easier to check by hand.
7979

8080
## 4. Open pull request

README.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,32 @@
1-
# Software
1+
# Software - Control Station
2+
3+
[![CI](https://github.com/HyperloopUPV-H8/software/actions/workflows/build-backend.yaml/badge.svg)](https://github.com/HyperloopUPV-H8/software/actions/workflows/build-backend.yaml)
4+
[![CI](https://github.com/HyperloopUPV-H8/software/actions/workflows/build-ethernet-view.yaml/badge.svg)](https://github.com/HyperloopUPV-H8/software/actions/workflows/build-ethernet-view.yaml)
5+
[![CI](https://github.com/HyperloopUPV-H8/software/actions/workflows/build-control-station.yaml/badge.svg)](https://github.com/HyperloopUPV-H8/software/actions/workflows/build-control-station.yaml)
6+
7+
Hyperloop UPV's Control STtaion is a unified software solution for monitoring and commanding the pod in real time. It combines a back-end (Go) that ingests and interprets sensor data–defined via the JSON-based "ADJ" specifications–and a front-end (Typescript/React) that displays metrics, logs, and diagnostics to operators. With features like packet parsing, logging, and live dashboards, it acts as the central hub to safely interface the pod, making it easier for team members to oversee performance, detect faults, and send precise orders to the vehicle.
8+
9+
### Installation
10+
11+
Download the last release, unzip it and leave the executable compatible with your OS in the folder.
12+
13+
### Developing
14+
15+
The main project file is inside `backend/cmd`. Make sure to have the proper `config.toml` configuration and that you are in the `develop` branch. To build the project just run `go build` inside the folder. With everything set up execute the `cmd` executable, then move to `ethernet-view` and run `npm run dev`, then to the `control-station` and do the same.
16+
17+
### Contributing
18+
19+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for ways to contribute to the Control Station.
20+
21+
### Authors
22+
23+
- [Juan Martinez Alonso](https://github.com/jmaralo)
24+
- [Marc Sanchis Llinares](https://github.com/msanlli)
25+
- [Sergio Moreno Suay](https://github.com/smorsua)
26+
- [Felipe Zaballa Martinez](https://github.com/lipezaballa)
27+
- [Andrés de la Torre Mora](https://github.com/andresdlt03)
28+
- [Alejandro Losa](https://github.com/Losina24)
29+
30+
### About
31+
32+
HyperloopUPV is a student team based at Universitat Politècnica de València (Spain), which works every year to develop the transport of the future, the hyperloop. Check out [our website](https://hyperloopupv.com/#/)

backend/README.md

Lines changed: 0 additions & 26 deletions
This file was deleted.

backend/cmd/main.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"net/http"
1313
_ "net/http/pprof"
1414
"os"
15+
"os/exec"
1516
"os/signal"
1617
"path"
1718
"runtime"
@@ -105,6 +106,13 @@ func main() {
105106
trace.Fatal().Err(err).Msg("setting up ADJ")
106107
}
107108

109+
test := exec.Command("python3", "testadj.py")
110+
out, err := test.CombinedOutput()
111+
if err != nil || len(out) != 0 {
112+
fmt.Printf("\nPython test failed:\nError: %v\nOutput: %s\n", err, string(out))
113+
os.Exit(1)
114+
}
115+
108116
podData, err := pod_data.NewPodData(adj.Boards, adj.Info.Units)
109117
if err != nil {
110118
fmt.Println(err)
@@ -558,7 +566,7 @@ func getIPIPfilter() string {
558566
return "ip[9] == 4"
559567
}
560568

561-
func getUDPFilter(addrs []net.IP, backendAddr net.IP, port uint16) string {
569+
func getUDPFilter(addrs []net.IP, backendAddr net.IP, _ uint16) string {
562570
udpPort := "udp" // TODO use proper ports for the filter
563571
srcUdpAddrs := common.Map(addrs, func(addr net.IP) string {
564572
return fmt.Sprintf("(src host %s)", addr)

backend/cmd/testadj.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import os
2+
import json
3+
4+
5+
def validate_json_structure(data):
6+
errors = []
7+
8+
if "board_id" in data:
9+
if not isinstance(data["board_id"], int):
10+
errors.append(f"'board_id' debe ser un entero, pero se encontró: {type(data['board_id']).__name__}.")
11+
12+
if "board_ip" in data:
13+
if not isinstance(data["board_ip"], str):
14+
errors.append(f"'board_ip' debe ser una cadena, pero se encontró: {type(data['board_ip']).__name__}.")
15+
16+
17+
if "measurements" in data:
18+
if not isinstance(data["measurements"], list):
19+
errors.append("La clave 'measurements' debe ser una lista.")
20+
else:
21+
for measurement in data["measurements"]:
22+
if isinstance(measurement, dict):
23+
required_keys = ["id", "name", "type", "podUnits", "displayUnits"]
24+
for key in required_keys:
25+
if key not in measurement:
26+
errors.append(f"Falta la clave '{key}' en un objeto de 'measurements'.")
27+
if "id" in measurement and not isinstance(measurement["id"], str):
28+
errors.append(f"El 'id' debe ser una cadena en: {measurement}")
29+
if "name" in measurement and not isinstance(measurement["name"], str):
30+
errors.append(f"El 'name' debe ser una cadena en: {measurement}")
31+
if "type" in measurement and not isinstance(measurement["type"], str):
32+
errors.append(f"El 'type' debe ser una cadena en: {measurement}")
33+
if "safeRange" in measurement and not isinstance(measurement.get("safeRange", []), list):
34+
errors.append(f"'safeRange' debe ser una lista en: {measurement}")
35+
if "warningRange" in measurement and not isinstance(measurement.get("warningRange", []), list):
36+
errors.append(f"'warningRange' debe ser una lista en: {measurement}")
37+
if "displayUnits" in measurement and not isinstance(measurement["displayUnits"], str):
38+
errors.append(f"El 'podUnits' debe ser una cadena en: {measurement}")
39+
if "podUnits" in measurement and not isinstance(measurement["podUnits"], str):
40+
errors.append(f"El 'podUnits' debe ser una cadena en: {measurement}") #esto se puede quitar (json 516)
41+
elif not isinstance(measurement, str):
42+
errors.append("Cada elemento en 'measurements' debe ser un objeto o una cadena (nombre de archivo).")
43+
44+
45+
if "packets" in data:
46+
if not isinstance(data["packets"], list):
47+
errors.append("La clave 'packets' debe ser una lista.")
48+
else:
49+
for packet in data["packets"]:
50+
if isinstance(packet, dict):
51+
required_keys = ["id", "name", "type","variable"]
52+
for key in required_keys:
53+
if key not in packet:
54+
errors.append(f"Falta la clave '{key}' en un objeto de 'packets'.")
55+
if "id" in packet and not isinstance(packet["id"], str):
56+
errors.append(f"El 'id' debe ser una cadena en: {packet}")
57+
if "name" in packet and not isinstance(packet["name"], str):
58+
errors.append(f"El 'name' debe ser una cadena en: {packet}")
59+
if "type" in packet and not isinstance(packet["type"], str):
60+
errors.append(f"El 'type' debe ser una cadena en: {packet}")
61+
if "variables" in packet:
62+
if not isinstance(packet["variables"], list):
63+
errors.append(f"'variables' debe ser una lista en: {packet}")
64+
else:
65+
for variable in packet["variables"]:
66+
if not isinstance(variable, dict):
67+
errors.append(f"Cada elemento en 'variables' debe ser un objeto en: {packet}")
68+
if "name" not in variable:
69+
errors.append(f"Falta la clave 'name' en un objeto de 'variables' en: {packet}")
70+
elif not isinstance(packet, str):
71+
errors.append("Cada elemento en 'packets' debe ser un objeto o una cadena (nombre de archivo).")
72+
73+
return errors
74+
75+
76+
77+
def validate_json_folder(folder_path):
78+
boards_file_path = os.path.join(folder_path, "boards.json")
79+
80+
try:
81+
with open(boards_file_path, 'r') as boards_file:
82+
boards_data = json.load(boards_file)
83+
boards = boards_data.get("boards", {})
84+
85+
86+
board_keys = list(boards.keys())
87+
duplicate_keys = [key for key in board_keys if board_keys.count(key) > 1]
88+
89+
if duplicate_keys:
90+
print(f"Error: El archivo boards.json contiene claves duplicadas: {', '.join(duplicate_keys)}")
91+
return
92+
93+
except json.JSONDecodeError as e:
94+
print(f"Error al decodificar JSON en {boards_file_path}: {e}")
95+
return
96+
except Exception as e:
97+
print(f"Error al procesar el archivo {boards_file_path}: {e}")
98+
return
99+
100+
101+
for board_name, board_file_path in boards.items():
102+
full_path = os.path.join(folder_path, board_file_path)
103+
try:
104+
with open(full_path, 'r') as board_file:
105+
data = json.load(board_file)
106+
errors = validate_json_structure(data)
107+
if errors:
108+
print(f"Errores encontrados en {full_path} para la placa '{board_name}':")
109+
for error in errors:
110+
print(f"- {error}")
111+
112+
except json.JSONDecodeError as e:
113+
print(f"Error al decodificar JSON en {full_path}: {e}")
114+
except Exception as e:
115+
print(f"Error al procesar el archivo {full_path}: {e}")
116+
117+
118+
if os.path.exists('./JSON_ADE/') == False:
119+
print("La carpeta JSON_ADE no existe")
120+
if __name__ == "__main__":
121+
validate_json_folder("./JSON_ADE/")

backend/docs/docs_structure.md

Lines changed: 0 additions & 42 deletions
This file was deleted.

backend/go.mod

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,18 @@ module github.com/HyperloopUPV-H8/h9-backend
33
go 1.21.3
44

55
require (
6-
github.com/HyperloopUPV-H8/ade-linter v0.0.0-20230530153315-3379f05a664f
76
github.com/go-git/go-git/v5 v5.12.0
87
github.com/google/gopacket v1.1.19
98
github.com/google/uuid v1.3.0
109
github.com/gorilla/websocket v1.5.0
1110
github.com/jmaralo/sntp v0.0.0-20240116111937-45a0a3419272
1211
github.com/pelletier/go-toml/v2 v2.0.7
1312
github.com/pin/tftp/v3 v3.0.0
14-
github.com/pkg/errors v0.9.1
1513
github.com/rs/zerolog v1.29.0
16-
github.com/xuri/excelize/v2 v2.7.1
1714
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
18-
google.golang.org/api v0.114.0
1915
)
2016

2117
require (
22-
cloud.google.com/go/compute v1.19.1 // indirect
23-
cloud.google.com/go/compute/metadata v0.2.3 // indirect
2418
dario.cat/mergo v1.0.0 // indirect
2519
github.com/Microsoft/go-winio v0.6.1 // indirect
2620
github.com/ProtonMail/go-crypto v1.0.0 // indirect
@@ -30,33 +24,19 @@ require (
3024
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
3125
github.com/go-git/go-billy/v5 v5.5.0 // indirect
3226
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
33-
github.com/golang/protobuf v1.5.3 // indirect
34-
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
35-
github.com/googleapis/gax-go/v2 v2.7.1 // indirect
3627
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
3728
github.com/kevinburke/ssh_config v1.2.0 // indirect
3829
github.com/mattn/go-colorable v0.1.13 // indirect
3930
github.com/mattn/go-isatty v0.0.17 // indirect
40-
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
4131
github.com/pjbgf/sha1cd v0.3.0 // indirect
42-
github.com/richardlehane/mscfb v1.0.4 // indirect
43-
github.com/richardlehane/msoleps v1.0.3 // indirect
32+
github.com/pkg/errors v0.9.1 // indirect
4433
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
4534
github.com/skeema/knownhosts v1.2.2 // indirect
4635
github.com/xanzy/ssh-agent v0.3.3 // indirect
47-
github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
48-
github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
49-
go.opencensus.io v0.24.0 // indirect
5036
golang.org/x/crypto v0.21.0 // indirect
5137
golang.org/x/mod v0.12.0 // indirect
52-
golang.org/x/oauth2 v0.7.0 // indirect
5338
golang.org/x/sys v0.18.0 // indirect
54-
golang.org/x/text v0.14.0 // indirect
5539
golang.org/x/tools v0.13.0 // indirect
56-
google.golang.org/appengine v1.6.7 // indirect
57-
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
58-
google.golang.org/grpc v1.56.3 // indirect
59-
google.golang.org/protobuf v1.30.0 // indirect
6040
gopkg.in/warnings.v0 v0.1.2 // indirect
6141
)
6242

0 commit comments

Comments
 (0)