diff --git a/src/Components/IoT/device_housing/Internal&Holder.f3d b/src/Components/IoT/device_housing/Internal&Holder.f3d new file mode 100644 index 000000000..af0085b70 Binary files /dev/null and b/src/Components/IoT/device_housing/Internal&Holder.f3d differ diff --git a/src/Components/IoT/device_housing/OuterCase.f3d b/src/Components/IoT/device_housing/OuterCase.f3d new file mode 100644 index 000000000..2e089cd0c Binary files /dev/null and b/src/Components/IoT/device_housing/OuterCase.f3d differ diff --git a/src/Components/IoT/device_housing/README.txt b/src/Components/IoT/device_housing/README.txt new file mode 100644 index 000000000..5f13e37a8 --- /dev/null +++ b/src/Components/IoT/device_housing/README.txt @@ -0,0 +1,8 @@ +This case was created in Fusion 360, of which a free version is available for students from Autodesk + +PLA was used to print in the Makerspace on Burwood campus however, I recommend print in ASA for UV resistance. + +The current prototype is split into sections to improve print time while prototyping design, these pieces are then superglued together. While this works well for prototyping it does make the design much less water resistant and is therefore impractical for a final stage prototype. + +When redesigning the next version, the width of the inserts on each wall should be narrowed by a few millimetres on each side to allow for easier construction. + diff --git a/src/Components/IoT/edge_inference/iot_edge_client.py b/src/Components/IoT/edge_inference/iot_edge_client.py index 672fdade7..b7b2b8354 100644 --- a/src/Components/IoT/edge_inference/iot_edge_client.py +++ b/src/Components/IoT/edge_inference/iot_edge_client.py @@ -162,7 +162,7 @@ def get_gps(fallback_lat: float, fallback_lon: float) -> dict: lon = data_stream.TPV.get("lon") mode = data_stream.TPV.get("mode") if mode == 3 and lat != "n/a" and lon != "n/a": - return {"lat": float(lat), "lon": float(lon)} + return {"lat": f"{float(lat):.4f}", "lon": f"{float(lon):.4f}"} except Exception: pass return {"lat": fallback_lat, "lon": fallback_lon} @@ -196,17 +196,16 @@ def on_connect(c, userdata, flags, rc): # --------------------------------------------------------------------------- def build_payload( species: str, confidence: float, top5: list, - sensor_id: str, gps: dict, gps_uncertainty: float, + sensor_id: str, gps: dict, ) -> dict: return { "type": "prediction", - "timestamp": str(int(time.time())), + "timestamp": time.strftime("%d-%m-%Y_%H-%M-%S"), "sensor_id": sensor_id, "species": species, "confidence": confidence, "top5": top5, "gps_data": gps, - "gps_uncertainty": gps_uncertainty, } @@ -221,7 +220,6 @@ def main(): parser.add_argument("--sensor-id", default="rpi_edge_node_1") parser.add_argument("--lat", type=float, default=-37.8136) parser.add_argument("--lon", type=float, default=144.9631) - parser.add_argument("--gps-uncertainty", type=float, default=10.0) parser.add_argument("--interval", type=float, default=10.0, help="Seconds between recordings (default: 10)") parser.add_argument("--use-gps", action="store_true", @@ -248,7 +246,7 @@ def main(): payload = build_payload( species, confidence, top5, - args.sensor_id, gps, args.gps_uncertainty, + args.sensor_id, gps, ) client.publish(args.topic, json.dumps(payload), qos=1) print(f"Published to {args.topic}\n", flush=True) diff --git a/src/Components/IoT/edge_inference/requirements.txt b/src/Components/IoT/edge_inference/requirements.txt index b88b66f04..6b7bb72aa 100644 --- a/src/Components/IoT/edge_inference/requirements.txt +++ b/src/Components/IoT/edge_inference/requirements.txt @@ -6,7 +6,7 @@ # omitted and the fallback import in iot_edge_client.py will use tensorflow.lite. tflite-runtime -numpy +numpy<2 librosa sounddevice paho-mqtt==1.6.1 diff --git a/src/Components/IoT/edge_inference/server.py b/src/Components/IoT/edge_inference/server.py new file mode 100644 index 000000000..a332d6513 --- /dev/null +++ b/src/Components/IoT/edge_inference/server.py @@ -0,0 +1,40 @@ +import json +import paho.mqtt.client as mqtt +import os + +JSON_DIR = 'jsonLocal' +BROKER = "broker.hivemq.com" +PORT = 1883 +TOPIC = "iot/data/test" + +os.makedirs(JSON_DIR, exist_ok=True) + +def on_connect(client, userdata, flags, rc): + if rc == 0: + print("Subscriber connected successfully") + client.subscribe(TOPIC, qos=1) + else: + print(f"Subscriber failed to connect, code {rc}") + +def on_subscribe(client, userdata, mid, granted_qos): + print(f"Subscribed with QoS {granted_qos}") + +def on_message(client, userdata, msg): + print(f"Received message on {msg.topic}") + + payload = json.loads(msg.payload) + + print("Writing json data") + subfolder = os.path.join(JSON_DIR, f"{payload["sensor_id"]}") + os.makedirs(subfolder, exist_ok=True) + json_filename = f"data_{payload["timestamp"]}" + with open(os.path.join(subfolder, json_filename), "w") as f: + json.dump(payload, f, indent=4) + print(f"Saved JSON: {json_filename}") + +client = mqtt.Client() +client.on_connect = on_connect +client.on_subscribe = on_subscribe +client.on_message = on_message +client.connect(BROKER, PORT, 60) +client.loop_forever() \ No newline at end of file diff --git a/src/Components/IoT/edge_inference/server_requirements.txt b/src/Components/IoT/edge_inference/server_requirements.txt new file mode 100644 index 000000000..0e6c975ed --- /dev/null +++ b/src/Components/IoT/edge_inference/server_requirements.txt @@ -0,0 +1,9 @@ +# IoT server requirements +# Install with: pip install -r requirements.txt + +tflite +numpy<2 +librosa +sounddevice +paho-mqtt==1.6.1 +gps3 diff --git a/src/Components/IoT/gps_boot/README.txt b/src/Components/IoT/gps_boot/README.txt new file mode 100644 index 000000000..fa9d0867b --- /dev/null +++ b/src/Components/IoT/gps_boot/README.txt @@ -0,0 +1,21 @@ +To install and enable the automatic GPS reboot fix please +follow the provided steps: + +1. Copy the gps_reboot.sh file to the Raspberry Pi at: + /home/pi/ + +2. Copy the gps-reboot.service file to the Raspberry Pi at: + /etc/systemd/system/ + +3. Open the terminal + +4. Reload daemon by running: + sudo systemctl daemon-reload + +5. Start the service by running: + sudo systemctl start gps-reboot.service + +6. Enable the service to run at boot: + sudo systemctl enable gps-reboot.service + +7. Restart Raspberry Pi \ No newline at end of file diff --git a/src/Components/IoT/gps_boot/gps-reboot.service b/src/Components/IoT/gps_boot/gps-reboot.service new file mode 100644 index 000000000..6331e5db8 --- /dev/null +++ b/src/Components/IoT/gps_boot/gps-reboot.service @@ -0,0 +1,12 @@ +[Unit] +Description=GPS Initialisation Script +After=multi-user.target + +[Service] +Type=oneshot +ExecStart=/home/pi/gps_reboot.sh +RemainAfterExit=yes +Restart=on-failure + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/src/Components/IoT/gps_boot/gps_reboot.sh b/src/Components/IoT/gps_boot/gps_reboot.sh new file mode 100755 index 000000000..e317e00d1 --- /dev/null +++ b/src/Components/IoT/gps_boot/gps_reboot.sh @@ -0,0 +1,8 @@ +#!/bin/bash +sudo systemctl stop gpsd.socket +sudo systemctl stop gpsd.service +sudo systemctl disable gpsd.socket +sudo systemctl disable gpsd.service +sudo killall gpsd +sudo systemctl enable gpsd.socket +sudo systemctl start gpsd.socket \ No newline at end of file diff --git a/src/Components/IoT/new_member_slides/Project_Echo_IoT_Induction.pptx b/src/Components/IoT/new_member_slides/Project_Echo_IoT_Induction.pptx new file mode 100644 index 000000000..0485baf03 Binary files /dev/null and b/src/Components/IoT/new_member_slides/Project_Echo_IoT_Induction.pptx differ