From 844f4d0b8b3390c42a983cb5e5dbb646536317f4 Mon Sep 17 00:00:00 2001 From: Phlabry Date: Thu, 22 Oct 2026 20:25:25 -0500 Subject: [PATCH 1/2] Issue #239 solved: use the iMotions port read off the lab machine The placeholder and the validation message now say 5050, and the mock server's 9999 is labelled as its own testing port. --- README.md | 19 +++++++++++++++---- relay/src/state.rs | 2 +- relay/src/view.rs | 7 ++++++- src/server/src/main.rs | 4 +++- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b1e0042..d3162a1 100644 --- a/README.md +++ b/README.md @@ -102,9 +102,10 @@ Then, in order: 1. Start iMotions, or the mock server, first, so that something is listening. 2. Launch the relay. The IPC listener that the plugin connects to starts automatically. You do not need to press `Connect IPC`. That button exists only to reconnect after you have pressed `Disconnect IPC`. -3. Type the iMotions address into the text box, for example `127.0.0.1:9999`. - - There is no default value. The greyed-out `127.0.0.1:9999` is placeholder text, not a setting. - - A literal IP address and port are required. `localhost:9999` is rejected. +3. Type the iMotions address into the text box, for example `127.0.0.1:5050`. + - There is no default value. The greyed-out `127.0.0.1:5050` is placeholder text, not a setting. + - 5050 is the port iMotions was listening on in the lab. It is a setting, not a fixed default, so check it on the machine you are using (see below). + - A literal IP address and port are required. `localhost:5050` is rejected. - Addresses that connect successfully are remembered in the `Saved IPs` dropdown (stored on Windows at `%APPDATA%\PilotDataSynchronization\relay_ips.json`). 4. Press `Connect TCP`. 5. Press `Check TCP Connection Status` to refresh the status line. It does not update by itself. This button is the only thing that changes it. @@ -139,7 +140,15 @@ E;1;PilotDataSync;;;;;AltitudeSync;1250.5;1250.5 Packets are semicolon-delimited and CRLF-terminated. The value appears twice because each sample carries both a `FlightModel*` and a `Pilot*` field. -> Needs verification. How `iMotions.xml` is imported into iMotions, and which port iMotions actually listens on, are not documented anywhere in this repository. `127.0.0.1:9999` appears only as placeholder text in the relay's UI. Nothing confirms it is iMotions' real port. If you have iMotions access, please confirm both and update this section. +### Which port iMotions listens on + +Read it off the iMotions machine: `Global Settings`, `API` tab, `Event Receiving`. The relay needs `Enable event reception` ticked and `Use TCP` ticked, and the port in that box is the one to type into the relay. On the lab machine it is 5050. + +The same panel lists the registered event sources. Ours shows as `Id: PilotDataSync`, version 1, `Positional Flight Data`, which is what the generated `iMotions.xml` defines. If it is missing, iMotions will drop our packets. + +Three other ports appear on that tab and none of them are ours: `Remote Control`, and the `Destination Server` ports under `Event Forwarding` and `Replay Event Forwarding`. Those are for iMotions sending data out, not receiving it. + +> Still needs verification. How the generated `iMotions.xml` is imported into iMotions is not documented anywhere in this repository, and nobody on the team has done the import themselves. It was already registered on the lab machine. See #195. ### No iMotions? Use the mock server @@ -155,6 +164,8 @@ Enter `127.0.0.1:9999` in the relay and press `Connect TCP`. The mock server prints every packet it receives, numbered, until the relay disconnects. It does not reply to the relay. +9999 is this mock's own port, picked for local testing. It is not iMotions' port and never was. + ## Verifying it works In the relay's terminal, you should see roughly this sequence: diff --git a/relay/src/state.rs b/relay/src/state.rs index 18976ce..5f2a64b 100644 --- a/relay/src/state.rs +++ b/relay/src/state.rs @@ -346,7 +346,7 @@ impl State { let _parsed = address .trim() .parse::() - .map_err(|_| anyhow!("Invalid IP address. Use format: 127.0.0.1:9999"))?; + .map_err(|_| anyhow!("Invalid IP address. Use format: 127.0.0.1:5050"))?; Ok(()) } diff --git a/relay/src/view.rs b/relay/src/view.rs index 9371601..09ecb91 100644 --- a/relay/src/view.rs +++ b/relay/src/view.rs @@ -11,7 +11,12 @@ use crate::{Message, State}; type UIElement<'a> = Element<'a, Message>; -const DEFAULT_TCP_PLACEHOLDER: &str = "127.0.0.1:9999"; +/// Where iMotions listens, read off the lab machine: Global Settings, API tab, +/// Event Receiving, with TCP enabled. It is a setting rather than a fixed +/// default, so other installs can differ and this stays a hint, not a value the +/// relay assumes. 9999 used to sit here and was only ever the mock server's +/// port. +const DEFAULT_TCP_PLACEHOLDER: &str = "127.0.0.1:5050"; /// How many of the most recent `event_log` entries the GUI renders. const EVENT_LOG_VISIBLE: usize = 5; diff --git a/src/server/src/main.rs b/src/server/src/main.rs index 670a798..b8ac5f0 100644 --- a/src/server/src/main.rs +++ b/src/server/src/main.rs @@ -4,7 +4,9 @@ use std::net::{TcpListener, TcpStream}; use std::process; use std::thread; -// Matches the relay's placeholder address, 127.0.0.1:9999 +// A local testing port, not iMotions'. iMotions listens on whatever its Event +// Receiving setting says, 5050 on the lab machine. Keeping this one distinct +// means running the mock can never be mistaken for talking to iMotions. const DEFAULT_PORT: u16 = 9999; // Reads newline-terminated packets until the peer closes the connection, From cbd9ac51502fba4c84d866985328f852612f58fa Mon Sep 17 00:00:00 2001 From: Phlabry Date: Sun, 25 Oct 2026 04:09:42 -0500 Subject: [PATCH 2/2] Address review: make the address hint unusable as a literal The placeholder and the validation message now share one constant and read :5050, since iMotions is on its own machine in the lab. The mock server says in its output that its port is local, not iMotions'. --- README.md | 7 ++++--- docs/client_meeting_notes.md | 1 + relay/src/state.rs | 11 ++++++++++- relay/src/view.rs | 10 ++-------- src/server/src/main.rs | 7 +++++-- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index d3162a1..ed06ab5 100644 --- a/README.md +++ b/README.md @@ -102,10 +102,11 @@ Then, in order: 1. Start iMotions, or the mock server, first, so that something is listening. 2. Launch the relay. The IPC listener that the plugin connects to starts automatically. You do not need to press `Connect IPC`. That button exists only to reconnect after you have pressed `Disconnect IPC`. -3. Type the iMotions address into the text box, for example `127.0.0.1:5050`. - - There is no default value. The greyed-out `127.0.0.1:5050` is placeholder text, not a setting. +3. Type the iMotions address into the text box. + - There is no default value. The greyed-out `:5050` is placeholder text, not a setting, and not an address that works. + - The IP is the machine running iMotions. In the lab that is a different computer from the one running the relay, so `127.0.0.1` only applies if both are on the same machine. - 5050 is the port iMotions was listening on in the lab. It is a setting, not a fixed default, so check it on the machine you are using (see below). - - A literal IP address and port are required. `localhost:5050` is rejected. + - A literal IP address and port are required. A host name such as `localhost:5050` is rejected. - Addresses that connect successfully are remembered in the `Saved IPs` dropdown (stored on Windows at `%APPDATA%\PilotDataSynchronization\relay_ips.json`). 4. Press `Connect TCP`. 5. Press `Check TCP Connection Status` to refresh the status line. It does not update by itself. This button is the only thing that changes it. diff --git a/docs/client_meeting_notes.md b/docs/client_meeting_notes.md index 7656ab5..a7f62dd 100644 --- a/docs/client_meeting_notes.md +++ b/docs/client_meeting_notes.md @@ -59,6 +59,7 @@ Vocabulary follows [GLOSSARY.md](../GLOSSARY.md). ## Network port - The X-Plane plugin sent to a placeholder port in the code. A new port was set, but it is **still unverified** that it matches the port iMotions listens on. The client, who handles the iMotions machine, will check. See [README.md](../README.md) for the open question. + - Answered since this meeting: iMotions listens on 5050, read off the machine under Global Settings, API, Event Receiving. See the comment on #195. - Whether developers get administrator rights on the simulator machine was not settled. ## Open items diff --git a/relay/src/state.rs b/relay/src/state.rs index 5f2a64b..23b261f 100644 --- a/relay/src/state.rs +++ b/relay/src/state.rs @@ -34,6 +34,13 @@ use std::sync::{OnceLock, Mutex}; /// a future `log_event` call lands on a hot path, as happened before #203. pub(crate) const EVENT_LOG_CAPACITY: usize = 200; +/// What to type into the relay's address box. Deliberately not a working +/// address: iMotions runs on its own machine in the lab, so the IP has to come +/// from there. 5050 is the port it was listening on, read from Global Settings, +/// API tab, Event Receiving, and that is a setting rather than a fixed default. +/// The placeholder text and the validation message both come from here. +pub(crate) const IMOTIONS_ADDR_HINT: &str = ":5050"; + // --- State definition ------------------------------------------------------- #[allow(unused)] pub(crate) struct State { @@ -346,7 +353,9 @@ impl State { let _parsed = address .trim() .parse::() - .map_err(|_| anyhow!("Invalid IP address. Use format: 127.0.0.1:5050"))?; + .map_err(|_| { + anyhow!("Invalid address. Enter a literal IP and port, for example {IMOTIONS_ADDR_HINT}") + })?; Ok(()) } diff --git a/relay/src/view.rs b/relay/src/view.rs index 09ecb91..3732a13 100644 --- a/relay/src/view.rs +++ b/relay/src/view.rs @@ -7,17 +7,11 @@ use iced::widget::{button, column, container, pick_list, row, text, text_input, use iced::{Element, Length}; use iced_aw::{helpers::card, style}; +use crate::state::IMOTIONS_ADDR_HINT; use crate::{Message, State}; type UIElement<'a> = Element<'a, Message>; -/// Where iMotions listens, read off the lab machine: Global Settings, API tab, -/// Event Receiving, with TCP enabled. It is a setting rather than a fixed -/// default, so other installs can differ and this stays a hint, not a value the -/// relay assumes. 9999 used to sit here and was only ever the mock server's -/// port. -const DEFAULT_TCP_PLACEHOLDER: &str = "127.0.0.1:5050"; - /// How many of the most recent `event_log` entries the GUI renders. const EVENT_LOG_VISIBLE: usize = 5; @@ -179,7 +173,7 @@ fn ipc_disconnect_button() -> UIElement<'static> { /// Build the TCP address input widget wired to `Message::TcpAddrFieldUpdate`. fn tcp_addr_input(state: &State) -> UIElement { - text_input(DEFAULT_TCP_PLACEHOLDER, &state.tcp_addr_field) + text_input(IMOTIONS_ADDR_HINT, &state.tcp_addr_field) .on_input(|addr| Message::TcpAddrFieldUpdate(addr)) .into() } diff --git a/src/server/src/main.rs b/src/server/src/main.rs index b8ac5f0..cfd154a 100644 --- a/src/server/src/main.rs +++ b/src/server/src/main.rs @@ -51,13 +51,16 @@ fn main() -> std::io::Result<()> { Ok(port) => port, Err(e) => { eprintln!("{e}"); - eprintln!("Usage: cargo run -- [port] (default {DEFAULT_PORT})"); + eprintln!( + "Usage: cargo run -- [port] (default {DEFAULT_PORT}, a local testing port, not iMotions')" + ); process::exit(2); } }; let listener = TcpListener::bind(("127.0.0.1", port))?; - println!("Server listening on {}", listener.local_addr()?); + println!("Mock server listening on {}", listener.local_addr()?); + println!("This stands in for iMotions. The port is local to this mock, not iMotions'."); // Listen for incoming connections for stream in listener.incoming() {