How to use it
Four steps, from nothing to a switch that flies the ship.
1 Turn on two rows in Settings, then press Assign switches.
Turn on Let D47 press keys in Elite and Let a HOTAS switch operate the ship, then press Assign switches.
The second row appears once the first is on, and the HOTAS switches page opens.
2 Press Assign a switch, and walk yours through its positions.
Press Assign a switch, move your switch to each position, and pause about a second and a half at each one.
Each position is recorded; press Finish when you have been through them all.
3 Give each position an action and a state.
Give each position an action and a state.
The state is available once an action is chosen; leave the middle of a three-position switch as nothing.
4 Press Save.
Press Save, then flip the switch with Elite in front.
The ship follows the switch; nothing is watched until you save.
! The one that stops people.
Bind the action to a key in Elite first.
D47 presses that key; an action bound only to a joystick button does nothing.
Why it works this way
A maintained toggle on your stick that means a state rather than a press.
1 The switch is a question, not a command.
Which is why an edge-triggered switch ends up upside down the first time the game changes its own mind — you dock, you relog, you lower the gear by voice — and stays that way until you notice.
2 Elite cannot be told what a position means.
3 It learns your switch by watching you walk it.
There is no list of sticks to pick from, and there never can be: Windows reports every controller as HID-compliant game controller, so a WinWing throttle, a Virpil base and a twenty-year-old Saitek are all the same string.
4 A switch that disagrees is announced, not corrected.
A spare three-position toggle can name pages of Directive 47's own panel instead of ship actions — three detents, three pages. That one presses nothing, reads no binds and checks no foreground, so it works whether the key-injection rows are on or off.
The details
A maintained toggle on your stick or throttle that means a state rather than a press.
Flip the gear switch down and Directive 47 asks Elite whether the gear is already down. If it is, nothing happens at all. If it is not, it presses your own landing-gear binding once. Between flips it touches nothing.
That one difference is the whole feature. Every other way of getting a switch into Elite is edge-triggered: it sends a toggle on the flip and has no idea what the game was doing. So the first time the game changes its own mind — you dock, you relog, you lower the gear by voice — the switch is upside down and stays that way until you notice.
Why your switches cannot just be bound in Elite
Because a maintained switch is held, not pressed. On the bench here, sixteen buttons were held down with nothing being touched. Elite sees a switch left in the “on” position as a button you are leaning on forever, and there is no way to express “this position means gear down” in a bindings file.
Turning it on
Two rows, and the second only appears once the first is on:
- Let D47 press keys in Elite — the master switch for all key injection.
- Let a HOTAS switch operate the ship — this feature.
Both are off until you turn them on, and neither can be turned on by the AI. They are reachable from the settings panel, from the settings hotkey, and by saying one of the fixed phrases:
“let my switches operate the ship” “stop reading my switches”
Keys for the ship are only ever sent while Elite is the window in front — and only while you are actually in the game: at the main menu a reconcile is refused and says so, and it runs when you load in.
Assigning a switch
There is no list of sticks to pick from, and there never can be. Windows reports every
controller as HID-compliant game controller — a WinWing throttle, a Virpil base and a
twenty-year-old Saitek are all the same string. Nothing exists for a device profile to be keyed
to, so Directive 47 learns your switch by watching you use it.
Press Assign and you are asked to:
Move the switch to each position in turn, and pause at each one.
Walk it all the way through. That instruction is doing four jobs at once:
| What the walk discovers | Why it cannot be assumed |
|---|---|
| How many positions the switch has | Two, three and four-position switches all exist |
| Which button index each position holds | Indices were consecutive on the bench; that is a hint, not a rule |
| Whether every position holds a button at all | A centre detent that holds nothing is a legitimate design |
| Whether the switch stays where you put it | A spring-return switch cannot mean a state |
The pause is what tells a maintained switch from a spring-return one. Hold duration cannot: the measured ranges overlap outright — switch flips ran 407–1611 ms and deliberate button presses ran 206–1751 ms. But after a second and a half, a maintained switch is still held and a spring-return one has gone home, and that is not a close call.
When a walk is declined
Directive 47 declines rather than guessing, and says which of these it was:
- “That is a hat, not a switch.” A hat returns to centre, so it can only mean a press.
- “That control went back on its own.” Spring-return, or a push button.
- “Button 5 moved but was never held still long enough to be a position.” You walked past a position. Try again, pausing at each.
- “Buttons 8 and 9 are held together at one position.” Not a switch this can read.
Every walk — including a declined one — can be exported as a capture report. Most of the devices this has to work on are ones nobody here will ever hold, so if your switch is declined and you think it should not have been, that file is the whole of the evidence.
Assigning what each position means
Each captured position gets an action and a state. Only the actions Elite reports the state of can be assigned, because those are the only ones that can be asked are you already there:
landing gear, ship lights, night vision, cargo scoop, hardpoints, supercruise, flight assist, silent running, analysis mode, SRV turret view, SRV handbrake, SRV drive assist.
A position may also mean nothing, which is what the centre of a three-position switch usually is.
A position may set several things at once
Some layouts need one position to set two states. A lights switch has up for lights on, centre for lights and night vision off, and down for night vision on; with one action per position the centre could turn only one of them off. A position can instead name a target, chosen under Several at once in the same list as the actions:
| Target | Sets |
|---|---|
| Lights on, night vision off | lights on, night vision off |
| Night vision on, lights off | night vision on, lights off |
| Lights and night vision off | lights off, night vision off |
| Combat mode, hardpoints out | analysis mode off, hardpoints on |
| Combat mode, hardpoints stowed | analysis mode off, hardpoints off |
Flipping to a target presses each part that is not already in its state, in the order above, and nothing else; if every part is already there nothing is pressed. A target has no on/off choice. Every part needs a key bound in Elite, and if one has none the row says which. If a part goes back on its own right after D47 sets it, the switch pauses, the same as for a single action; a part that never arrives is said out loud. Analysis mode on its own is already an action, so the third position of the HUD layout uses it directly.
A position may name which interface is open
A position can name the interface that should have focus, chosen under What is open. The target
is met when Elite’s Status.json reports that focus, so a three-position switch can be up for the
galaxy map, centre for the cockpit and down for the system map, or left panel, cockpit and right
panel.
| Target | Met when |
|---|---|
| Cockpit, nothing open | no full-screen interface is open |
| Galaxy map | the galaxy map is open |
| System map | the system map is open |
| Left panel | the left panel is open |
| Right panel | the right panel is open |
Flipping to a target presses nothing if it is already open. Otherwise D47 presses the open key of whatever is open, which closes it, and then the target’s open key on the poll after Elite reports the cockpit; from the cockpit it presses the target’s open key at once. Cockpit only closes. If station services, the full spectrum scanner, the codex, the orrery or the comms or role panel is open, the flip presses nothing and the row says what is open. A target needs the open keys bound in Elite, and sits behind Let a HOTAS switch operate the ship like any action. If the focus leaves the target on its own within four seconds the switch pauses, and a key that never takes is said out loud. A mismatch is annunciated as, for example, “the galaxy map is open”.
A position may name a split of the power distributor
A position can name where the pips should sit, chosen under Power distributor. D47 reads the
split from the Pips field of Elite’s Status.json: three numbers in half-pips, in the order
systems, engines, weapons, summing to twelve.
| Target | Systems, engines, weapons |
|---|---|
| Balanced | 4, 4, 4 |
| 4 pips to engines | 2, 8, 2 |
| 4 pips to weapons | 2, 2, 8 |
| 4 pips to systems | 8, 2, 2 |
| 4 systems, 2 engines | 8, 4, 0 |
| 4 systems, 2 weapons | 8, 0, 4 |
| 4 engines, 2 systems | 4, 8, 0 |
| 4 engines, 2 weapons | 0, 8, 4 |
| 4 weapons, 2 systems | 4, 0, 8 |
| 4 weapons, 2 engines | 0, 4, 8 |
Flipping to a target presses nothing if the pips already read that split. Otherwise D47 presses balance power and then the power keys that reach the target from balanced, as one reconcile with a short wait between taps. Targets are offered in the ship, a fighter and the SRV, need the distributor keys bound in Elite, and sit behind Let a HOTAS switch operate the ship like any action. If the pips leave the target on their own within four seconds the switch pauses, and pips that never arrive are said out loud. A mismatch is annunciated as, for example, “pips are 4, 4, 4”.
A position may name a page of Directive 47’s own panel instead
A spare three-position toggle with nothing bound to it can flip the Transcript between In Ship, Log File and Journal File — three detents, three pages. Each position gets a page rather than an action, chosen from the same list the spoken route reads: every page any surface shows, so there is nothing here that cannot also be said.
The same rule applies, and it fits better here than where it was invented. The flip is the
question, are you already there is asked first — and for Directive 47’s own panel the answer is
exact rather than read out of Status.json — and between flips nothing is touched. Flip to
Log File while the panel is already on Log File and nothing happens at all. Flip to it while
the panel is on the checklist and the panel goes to Log File, on both surfaces.
Two things are different, because the target is:
- It is not behind Let a HOTAS switch operate the ship, nor behind key injection. Those rows exist because a switch that reconciles the ship reaches the keyboard. A switch that changes which page is drawn presses nothing, reads no binds and checks no foreground, so it works whether those rows are on or off.
- It is never paused. Nothing else drives the panel behind Directive 47’s back, so there is nothing to desync with and nothing to stop reconciling for.
A page may also be one of the fixed pages one level below a tab’s page: Story log, Short Story, Catalogue and Story bench under Stories; Suggestions, Activities and All lists under Checklist; Compare under Ships; Route under Engineers; Progress under Plan. Story log, Short Story and Suggestions open only while their buttons would: a story under way, a model and galaxy search, a suggestion waiting. A position on a tab’s page agrees with the panel while one of these is open beside it.
A position may instead name Next tab or Previous tab, the first two entries in the page list. A flip moves the panel one tab along the bar of seven, wrapping from the last tab to the first and back, and skipping a tab with nothing on it. It lands on the tab as it was last left. Each flip moves one tab; a switch held in the position does not repeat. A spring-return rocker that rests in the centre is the natural control: push up for the next tab, down for the previous one. When the window and the headset show different tabs, each steps from its own. While a dialog holds the panel the flip does nothing and the log says so. A position that names a tab step never reports a disagreement, and like a page it works with Let a HOTAS switch operate the ship off.
A position means one thing: an action, a target, a page, a headset view or a key chord. A page the panel does not have — a key mistyped in the file, say — is reported on the row by name and never moved to. And a switch sitting on a page the panel is not showing is annunciated like any other stale switch:
transcript switch: the panel is on Conversation
Spring-return controls and hats are still declined, even for a page. The walk cannot know what a switch will be assigned to, a momentary control can only ever mean a press, and saying a page out loud already covers the press.
Switching the headset view
A position may also name a headset view: VR or Desktop, for a Virtual Desktop headset. Virtual Desktop switches between its own desktop view and SteamVR on Shift+Win+D, and Directive 47 uses the same rule here as everywhere else:
- What it reads. Which view Virtual Desktop is showing, from the shared memory its driver writes while the headset is streaming.
- What it presses. Shift+Win+D, once, and only when the headset is showing the other view. Flip to VR while the headset is already in SteamVR and nothing happens. Between flips nothing is touched.
- What comes to the front. After a press to VR, Elite is put in front, so keys go to the game. After a press to Desktop, Directive 47’s main window is put in front, restored first if it was minimised. When nothing was pressed, no window moves. If Windows refuses, Directive 47 says so with the switch’s name; Elite not running is silent.
- What it needs. Let a HOTAS switch change the headset view turned on, and Virtual Desktop streaming. It is off until you turn it on, and the AI cannot turn it on. It is not behind Let D47 press keys in Elite or Let a HOTAS switch operate the ship, and it works at the main menu and in SteamVR Home: Virtual Desktop hears its shortcut whatever window is in front. It can also be set by saying:
“let my switches change the headset view” “stop my switches changing the headset view”
When Virtual Desktop is not streaming, the view cannot be read, so nothing is pressed and the switch’s row on the HOTAS switches page reads:
Virtual Desktop is not streaming, so the headset view was left alone.
If the view has not changed four seconds after the press, the switch pauses. Virtual Desktop’s shortcut can be changed in its settings, and Directive 47 always sends Shift+Win+D:
Shift+Win+D did not change the headset view. If you changed Virtual Desktop’s shortcut, set it back, then press Resume.
While the row is on, a switch sitting in a view the headset is not showing is annunciated like any other:
view switch: the headset is showing the desktop
Pressing a key chord
A position may instead name a key chord: one key with any of Ctrl, Shift, Alt and Win held, such as Ctrl+V. It is for keys outside Elite — pasting into a browser, another program’s hotkey — so it goes to whatever window is in front, whether Elite is running or not.
- What it presses. The chord, once, on a flip into the position, including a flick too quick to be held across two readings. Nothing on first seeing the switch, nothing while it stays there, and nothing on the way out.
- What it reads. Nothing. There is no state to read back, so a chord never disagrees with anything, never pauses the switch, and is never “already there”. A switch paused by one of its other positions presses no chord until you press Resume.
- What it needs. Let a HOTAS switch press key chords in any window turned on. It is off until you turn it on, and the AI cannot turn it on. It is not behind Let D47 press keys in Elite or Let a HOTAS switch operate the ship. It can also be set by saying:
“let my switches press key chords” “stop my switches pressing key chords”
While it is off, the switch’s row on the HOTAS switches page says so. A momentary stick button is a
two-position switch — nothing held, and the button — so a stick button can paste. On the HOTAS
switches page, choose Key chord under Outside Elite in a position’s Action list. Two lists
replace ON / OFF: the modifiers, from None to Ctrl+Shift+Alt+Win, and the key. A new chord starts at
Ctrl+V. Picking any other action removes the chord. It can also be set by editing data/switches.json,
as below. Alt+F4 and Win+L are refused, and so is a modifier named as the key; the page shows the
refusal and does not save. If Windows refuses the keystroke, it is said:
I could not press Ctrl+V from paste button. Windows refused the keystroke.
When a mapping stops fitting
A mapping is stored against the controller’s HID collection and its button count, never against its vendor and product ids. This matters more than it sounds.
Turning 4x32 mode on or off on a WinWing throttle renumbers every button on it, while leaving the vendor and product ids completely unchanged. A mapping keyed on those would survive the change and silently press button 15 of a block that is no longer the same block. The button count changes, so instead the switch fails closed: the row says it needs reassigning, and nothing is pressed.
Moving a controller to another USB port, and switching between the installed app and the test drive, no longer change the stored identity, so the switches do not need walking again.
Bindings made before this change were stored under a {wgi/nrid/…} id that Windows gave to each
copy of Directive 47 separately. At start-up, once the controllers have settled, Directive 47
moves each of those ids to the controller’s HID identity where the match is certain: the same
vendor, product and shape, and, where several controllers look alike, held buttons that tell them
apart. Switches, push-to-talk and cancel move together, and the log records each move.
Where it is not certain, or the id belongs to the other copy of Directive 47, the switch keeps its old id and the flip finds it: open the HOTAS switches page and flip one of the switches that cannot find its device. Directive 47 finds the device it moved on and points every switch learned on the old id at the new one, writing the switch file at once. The card says “Found on VID 0x… PID 0x…, 32 buttons, … — 4 switches re-pointed.” A throttle in 4x32 mode has one id per block, so flip one switch on each block. A device is accepted only when it describes itself the same way as the one the switch was learned on, and a 4x32 change alters the button count, so after a 4x32 change the switch still has to be assigned again.
When Elite is bound to the same button
The most common way for this to go wrong is the one you can see, so Directive 47 looks. If a switch position sits on a button Elite also binds, both act on every flip — and the results look like Directive 47 misbehaving in two different ways at once:
- where Directive 47 correctly presses nothing, Elite’s binding toggles, so the thing moves the wrong way;
- where Directive 47 correctly presses, the two toggles cancel and nothing happens at all.
That is one setup fault wearing two disguises, and it cost an afternoon before it was understood. The switch now says so directly:
Elite binds this button to LandingGearToggle as well, so both act on every flip. Unbind it in Elite, or move this switch to a button Elite does not use.
Directive 47 will not fix it for you: your bindings file is read-only to it, always. Unbind the button in Elite, or move the switch.
When something else is driving the same switch
A virtual device is the case that cannot be seen. If SimApp Pro or Joystick Gremlin is publishing a vJoy device, Elite’s binds name that device and nothing connects it back to your physical switch.
So the symptom is watched instead. One unexplained reversal and Directive 47 stops reconciling that switch and says so, rather than fighting whatever else is there. The panel offers a Resume button; a restart clears it too.
A mode change is not counted as unexplained. Hardpoints retract by themselves when you enter supercruise, and that is the game doing its job.
And a press that simply does not take is now reported too. Watching for a reversal only catches something that fights back after the state arrives; two toggles cancelling means the state never arrives at all, and that used to be silent — the log said the key was sent, and nothing said the thing had not moved. Now:
I set the landing gear from LDG GEAR and it did not take. Something else may be bound to the same button.
Switches that disagree with the game
A stale switch is harmless — it costs one extra flip — but only if you can see it coming. So the panel and the VR surface show which assigned switches currently sit against the game’s state:
gear switch: the landing gear is up
This is the answer real aviation reached with annunciator lights rather than motorised switches, for the same reason: showing the state is cheap and moving the switch is not.
You can also ask.
Ask for it
“which switches disagree” “check my switches”
report_switches
Reports only. It cannot assign, change, pause or clear a switch — assignment is reachable from the panel and from nowhere else, because the AI reads untrusted text and a hostile in-game message must not be able to remap your throttle.
{"type":"object","properties":{},"required":[],"additionalProperties":false}
Where it is stored
data/switches.json, beside the executable like everything else Directive 47 writes. It is
hand-editable, and it is re-read while running — a mapping edited in a text editor is live
without a restart. Anything in it that does not make sense is refused by name, with the
reason, and the rest of the file still loads.
{
"switches": [
{
"name": "gear switch",
"deviceId": "{wgi/nrid/X8QoL-2>1[]-...-mA7IX7-Ac}",
"device": "VID 0x4098 PID 0xBD65, 32 buttons, 0 hats, 7 axes",
"positions": [
{ "button": 8, "action": "landing_gear", "state": "on" },
{ "button": 9, "action": "landing_gear", "state": "off" }
]
},
{
"name": "transcript switch",
"deviceId": "{wgi/nrid/X8QoL-2>1[]-...-mA7IX7-Ac}",
"device": "VID 0x4098 PID 0xBD65, 32 buttons, 0 hats, 7 axes",
"positions": [
{ "button": 4, "destination": "transcript.conversation" },
{ "button": 5, "destination": "transcript.technical" },
{ "button": 6, "destination": "transcript.log" }
]
},
{
"name": "view switch",
"deviceId": "{wgi/nrid/X8QoL-2>1[]-...-mA7IX7-Ac}",
"device": "VID 0x4098 PID 0xBD65, 32 buttons, 0 hats, 7 axes",
"positions": [
{ "button": 10, "view": "vr" },
{ "button": 11, "view": "desktop" }
]
},
{
"name": "paste button",
"deviceId": "{wgi/nrid/X8QoL-2>1[]-...-mA7IX7-Ac}",
"device": "VID 0x4098 PID 0xBD65, 32 buttons, 0 hats, 7 axes",
"positions": [
{ "button": null },
{ "button": 3, "chord": { "key": "Key_V", "modifiers": "ctrl" } }
]
}
]
}
A page is its own destination field, never a prefix on action — a statement about what the
position means rather than a naming rule a rename would silently break. The keys are the ones the
panel registers: transcript.conversation, transcript.technical, transcript.log, the
roots of every other tab, and the fixed pages below them, such as stories for the Catalogue.
A headset view is its own view field too, vr or desktop. A key chord is its own chord field:
key is one of the keyboard names Elite’s bindings use, such as Key_V or Key_F13, and
modifiers lists any of ctrl, shift, alt and win, separated by commas, such as
"ctrl, shift".
What it does not do
- It does not read axes. A throttle axis is not a switch and is not in scope.
- It does not write your Elite bindings. Those are read-only, always.
- It does not move your switches. Nothing can; they are lumps of metal.
- It does not act on a switch it has just found. On startup, and after a device reconnects, Directive 47 learns where the switch is sitting and presses nothing. The next flip is the next question.