feat: standard parts library, fuse box configurator, and theming
Standard parts (partsLibrary.js) - ACDC TXL palette: 15 solids plus the 16 stocked stripe combinations - 29 wire functions fix colour, stripe and gauge per signal, so a wire drawn from a given pin comes out identical on every build - 16 pre-labelled parts: Skudak VCU (GRAY/BLACK), openinverter LDU 23-pin, Dilong OBC/DCDC, BMW pedal, Honeywell CSSV1500, Bender ISO175, Bosch iBooster, Prius EPS, Volvo PS pump, cluster, DNR switch, 32-way enclosure bulkhead, contactors, VW MEB BMS - OEM colours override the in-house standard where we splice into a factory loom (VW MEB LV connector, recovered from the VW bms diagram) - Brown is ground, matching the MEB loom and European practice; orange is reserved for AC mains and OEM high-voltage runs Fuse box configurator (pdmLibrary.js) - GEP FRH-A12/A24 and the 48-way PDM as 280-footprint cavity grids - Place, drag and rotate fuses, relays, diodes, breakers and bus bars - Bus bars occupy their own collision layer and feed the blades they cross, suppressing those inputs so one wire supplies the run - Cavity capacity is tracked; Apply is blocked while a placement overlaps or overhangs - Naming a circuit renames its pins: "VCU" gives "VCU in" / "VCU out" Theming (theme.js) - Light and dark modes; canvas background, grid dots, part fill and part outline are configurable and persisted - CSS converted to custom properties with property-aware light-mode pairs, since a colour used as text and as a surface must flip differently; no rule falls below 3:1 contrast in either theme - Canvas devices, pins, labels, cable rows and the harness view are themed too, since Konva bakes colours in at draw time and cannot read CSS variables Also - Pass-through bulkheads: one device covering both connector faces, with a single centred label per circuit - Pin labels scale with the device font instead of a fixed 8px - Keyboard handling is modal-scoped, so Delete no longer removes the canvas device while the fuse box editor is open Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,558 @@
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Skudak standard parts + wire colour standard
|
||||
//
|
||||
// Loaded AFTER connectorLibrary.js. Merges standard parts into CONNECTOR_LIBRARY
|
||||
// so they appear in the existing library panel, search and drag-to-canvas with
|
||||
// no UI changes.
|
||||
//
|
||||
// The point of this file: every pin on a standard part declares the wire that
|
||||
// belongs on it. Drag a wire off VCU GRAY pin 3 and it is Red/White 14 AWG every
|
||||
// time, on every build, without anyone remembering to set it.
|
||||
//
|
||||
// Wire stock: ACDC Wire Supply TXL. Solids plus the 16 stocked stripe combos.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
// ── TXL solid colours ────────────────────────────────────────────────────────
|
||||
const TXL_SOLID = {
|
||||
black: { name: "Black", hex: "#1A1A1A" },
|
||||
brown: { name: "Brown", hex: "#6B3F1D" },
|
||||
red: { name: "Red", hex: "#CC0000" },
|
||||
orange: { name: "Orange", hex: "#FF8C00" },
|
||||
yellow: { name: "Yellow", hex: "#FFD700" },
|
||||
green: { name: "Green", hex: "#007700" },
|
||||
darkGreen: { name: "Dark Green", hex: "#14532D" },
|
||||
lightGreen: { name: "Light Green", hex: "#7CB342" },
|
||||
blue: { name: "Blue", hex: "#0000CC" },
|
||||
lightBlue: { name: "Light Blue", hex: "#4FA8DC" },
|
||||
purple: { name: "Purple", hex: "#7B00CC" },
|
||||
grey: { name: "Grey", hex: "#808080" },
|
||||
white: { name: "White", hex: "#E8E8E8" },
|
||||
pink: { name: "Pink", hex: "#FF69B4" },
|
||||
tan: { name: "Tan", hex: "#D2B48C" },
|
||||
};
|
||||
|
||||
// ── TXL stocked stripe combinations ──────────────────────────────────────────
|
||||
// Exactly the 16 combos carried by ACDC. Nothing outside this list is buildable.
|
||||
const TXL_STRIPED = {
|
||||
whiteRed: { name: "White / Red stripe", hex: "#E8E8E8", stripe: "#CC0000" },
|
||||
whiteBlue: { name: "White / Blue stripe", hex: "#E8E8E8", stripe: "#0000CC" },
|
||||
pinkGreen: { name: "Pink / Green stripe", hex: "#FF69B4", stripe: "#007700" },
|
||||
tanBlack: { name: "Tan / Black stripe", hex: "#D2B48C", stripe: "#1A1A1A" },
|
||||
lightGreenDark: { name: "Light Green / Dark Green stripe", hex: "#7CB342", stripe: "#14532D" },
|
||||
yellowRed: { name: "Yellow / Red stripe", hex: "#FFD700", stripe: "#CC0000" },
|
||||
orangeBlack: { name: "Orange / Black stripe", hex: "#FF8C00", stripe: "#1A1A1A" },
|
||||
brownWhite: { name: "Brown / White stripe", hex: "#6B3F1D", stripe: "#E8E8E8" },
|
||||
greenWhite: { name: "Green / White stripe", hex: "#007700", stripe: "#E8E8E8" },
|
||||
purpleRed: { name: "Purple / Red stripe", hex: "#7B00CC", stripe: "#CC0000" },
|
||||
lightBlueWhite: { name: "Light Blue / White stripe", hex: "#4FA8DC", stripe: "#E8E8E8" },
|
||||
blackWhite: { name: "Black / White stripe", hex: "#1A1A1A", stripe: "#E8E8E8" },
|
||||
blackRed: { name: "Black / Red stripe", hex: "#1A1A1A", stripe: "#CC0000" },
|
||||
redBlack: { name: "Red / Black stripe", hex: "#CC0000", stripe: "#1A1A1A" },
|
||||
blackYellow: { name: "Black / Yellow stripe", hex: "#1A1A1A", stripe: "#FFD700" },
|
||||
redWhite: { name: "Red / White stripe", hex: "#CC0000", stripe: "#E8E8E8" },
|
||||
};
|
||||
|
||||
// ── Function → wire standard ─────────────────────────────────────────────────
|
||||
// This is the standard. A pin names a function; the function fixes the colour,
|
||||
// stripe and gauge. Change it here and every build follows.
|
||||
const WIRE_STANDARD = {
|
||||
// Power. Brown is ground, matching the MEB loom, the Land Rover build and
|
||||
// European practice — an in-house ground lands next to an OEM ground at the
|
||||
// battery, so the two must not disagree.
|
||||
KL30: { label: "Permanent 12 V (KL30)", ...TXL_SOLID.red, gauge: "14 AWG" },
|
||||
KL15: { label: "Switched 12 V (KL15)", ...TXL_STRIPED.redBlack, gauge: "16 AWG" },
|
||||
LOAD_12V: { label: "VCU-switched load feed", ...TXL_STRIPED.redWhite, gauge: "14 AWG" },
|
||||
GND: { label: "Chassis ground", ...TXL_SOLID.brown, gauge: "14 AWG" },
|
||||
GND_SIG: { label: "Signal ground", ...TXL_STRIPED.brownWhite, gauge: "18 AWG" },
|
||||
V5_REF: { label: "5 V sensor reference", ...TXL_STRIPED.pinkGreen, gauge: "20 AWG" },
|
||||
|
||||
// Networks — CAN pairs are twisted
|
||||
CAN1_H: { label: "CAN1 High (powertrain)", ...TXL_SOLID.yellow, gauge: "20 AWG", twisted: true },
|
||||
CAN1_L: { label: "CAN1 Low (powertrain)", ...TXL_SOLID.green, gauge: "20 AWG", twisted: true },
|
||||
CAN2_H: { label: "CAN2 High (HV pack)", ...TXL_STRIPED.yellowRed, gauge: "20 AWG", twisted: true },
|
||||
CAN2_L: { label: "CAN2 Low (HV pack)", ...TXL_STRIPED.greenWhite, gauge: "20 AWG", twisted: true },
|
||||
CAN3_H: { label: "CAN3 High (charge/body)", ...TXL_STRIPED.whiteBlue, gauge: "20 AWG", twisted: true },
|
||||
CAN3_L: { label: "CAN3 Low (charge/body)", ...TXL_STRIPED.lightBlueWhite, gauge: "20 AWG", twisted: true },
|
||||
LIN: { label: "LIN bus", ...TXL_SOLID.grey, gauge: "20 AWG" },
|
||||
SHIELD: { label: "Shield / drain", ...TXL_STRIPED.blackYellow, gauge: "20 AWG" },
|
||||
|
||||
// Safety. HVIL is violet, not orange — orange is reserved (see below) so the
|
||||
// interlock can never be mistaken for a live AC mains or OEM HV run.
|
||||
HVIL_OUT: { label: "HVIL drive", ...TXL_SOLID.purple, gauge: "18 AWG" },
|
||||
HVIL_RTN: { label: "HVIL return", ...TXL_STRIPED.purpleRed, gauge: "18 AWG" },
|
||||
COIL: { label: "Contactor coil", ...TXL_SOLID.black, gauge: "16 AWG" },
|
||||
WELD: { label: "Weld detect / aux contact", ...TXL_STRIPED.blackWhite, gauge: "20 AWG" },
|
||||
INHIBIT: { label: "Enable / inhibit", ...TXL_STRIPED.blackRed, gauge: "20 AWG" },
|
||||
|
||||
// Signals
|
||||
DIG_IN: { label: "Digital input", ...TXL_STRIPED.whiteRed, gauge: "20 AWG" },
|
||||
DIG_OUT: { label: "Digital output", ...TXL_SOLID.darkGreen, gauge: "18 AWG" },
|
||||
PWM_OUT: { label: "PWM output", ...TXL_SOLID.lightGreen, gauge: "18 AWG" },
|
||||
FREQ_IN: { label: "PWM / frequency input", ...TXL_SOLID.lightBlue, gauge: "20 AWG" },
|
||||
ANALOG_1: { label: "Analog signal 1", ...TXL_STRIPED.tanBlack, gauge: "20 AWG" },
|
||||
ANALOG_2: { label: "Analog signal 2", ...TXL_SOLID.tan, gauge: "20 AWG" },
|
||||
ANALOG_3: { label: "Analog signal 3", ...TXL_STRIPED.lightGreenDark, gauge: "20 AWG" },
|
||||
FAULT: { label: "Fault / lamp output", ...TXL_SOLID.pink, gauge: "18 AWG" },
|
||||
HV_SENSE: { label: "HV instrumentation", ...TXL_SOLID.blue, gauge: "18 AWG" },
|
||||
// Quadrature channel B needs its own colour. Channel A is an ordinary
|
||||
// FREQ_IN, but two identical wires in one shielded encoder bundle is how you
|
||||
// end up with A and B swapped — which reverses the sensed direction of the
|
||||
// motor. White is reclaimed from the old SPARE entry: an unassigned pin
|
||||
// should get no wire at all, not a wire in "spare" colour.
|
||||
ENC_B: { label: "Encoder channel B", ...TXL_SOLID.white, gauge: "20 AWG" },
|
||||
};
|
||||
|
||||
// ── Reserved colours ─────────────────────────────────────────────────────────
|
||||
// Deliberately NOT in WIRE_STANDARD, so nothing in-house is ever auto-assigned
|
||||
// them. Orange belongs to AC mains and to OEM high-voltage looms; taking it for
|
||||
// a signal would put a low-voltage wire in the colour that means "this can kill
|
||||
// you". Set these by hand when drawing the runs they describe.
|
||||
const RESERVED_COLOURS = {
|
||||
AC_MAINS: { label: "AC mains (L1 / L2 / AC ground)", ...TXL_SOLID.orange, gauge: "6.0 mm²" },
|
||||
OEM_HV: { label: "OEM high-voltage / HV-CAN", ...TXL_STRIPED.orangeBlack, gauge: "varies" },
|
||||
};
|
||||
|
||||
function wireSpecFor(fnKey) {
|
||||
const s = WIRE_STANDARD[fnKey];
|
||||
if (!s) return null;
|
||||
return {
|
||||
fn: fnKey,
|
||||
color_primary: s.hex,
|
||||
color_stripe: s.stripe || null,
|
||||
gauge: s.gauge,
|
||||
twisted_pair: !!s.twisted,
|
||||
label: s.label,
|
||||
};
|
||||
}
|
||||
|
||||
// Shorthand: p("3", "GPIOHP1", "LOAD_12V", "Coolant pump 12 V")
|
||||
function p(pin, name, fn, note) {
|
||||
return { pin, name, fn, note: note || "" };
|
||||
}
|
||||
|
||||
// ── OEM harness colours ──────────────────────────────────────────────────────
|
||||
// Where we splice into an existing factory harness the wire colour is not ours
|
||||
// to choose — it has to match what is already in the loom. These override the
|
||||
// WIRE_STANDARD function colours.
|
||||
//
|
||||
// VW MEB battery LV connector, recovered from the "VW bms" diagram
|
||||
// (diagrams/0005_VW_bms.json). Colours are confirmed OEM; the signal each pin
|
||||
// carries is NOT yet confirmed — the source diagram had no pin labels.
|
||||
const OEM = {
|
||||
meb: {
|
||||
brown: { name: "Brown (VW ground)", hex: "#8B4513", stripe: null, gauge: "16 AWG" },
|
||||
greenBlack: { name: "Green / Black stripe", hex: "#007700", stripe: "#000000", gauge: "18 AWG" },
|
||||
greenRed: { name: "Green / Red stripe", hex: "#007700", stripe: "#FF0000", gauge: "18 AWG" },
|
||||
greenWhite: { name: "Green / White stripe", hex: "#007700", stripe: "#CCCCCC", gauge: "18 AWG" },
|
||||
orangeBlue: { name: "Orange / Blue stripe", hex: "#FF8C00", stripe: "#0000FF", gauge: "20 AWG" },
|
||||
orangeRed: { name: "Orange / Red stripe", hex: "#FF8C00", stripe: "#FF0000", gauge: "20 AWG" },
|
||||
},
|
||||
};
|
||||
|
||||
// Shorthand for an OEM-coloured pin: po("9", "CAN H?", OEM.meb.orangeBlue, "…")
|
||||
function po(pin, name, oemColor, note) {
|
||||
return {
|
||||
pin, name, fn: null, note: note || "",
|
||||
oem: {
|
||||
color_primary: oemColor.hex,
|
||||
color_stripe: oemColor.stripe,
|
||||
gauge: oemColor.gauge,
|
||||
label: oemColor.name,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Standard parts
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
const SKUDAK_PARTS = {
|
||||
"Skudak VCU": [
|
||||
{
|
||||
id: "skudak-vcu-gray",
|
||||
name: "Skudak VCU — GRAY",
|
||||
manufacturer: "Skudak",
|
||||
partNumber: "VCU-001 (GRAY)",
|
||||
description: "VCUv2 rev A left receptacle — power, GPIOHP high-current channels, relay coils, LIN, wake, fault, aux input. Mates Molex 0334722007.",
|
||||
pinCount: 20,
|
||||
pinSpecs: [
|
||||
p("1", "12V IN", "KL30", "Fused supply"),
|
||||
p("2", "12V IN", "KL30", "Fused supply"),
|
||||
p("3", "GPIOHP1", "LOAD_12V", "High-current switched output, 8 A"),
|
||||
p("4", "GPIOHP3", "LOAD_12V", "High-current switched output, 8 A"),
|
||||
p("5", "GPIOHP5", "LOAD_12V", "High-current switched output, 8 A"),
|
||||
p("6", "GPIOHP7", "LOAD_12V", "High-current switched output, 8 A"),
|
||||
p("7", "RLY1_A", "COIL", "Relay 1 coil, terminal A"),
|
||||
p("8", "RLY2_A", "COIL", "Relay 2 coil, terminal A"),
|
||||
p("9", "LIN", "LIN", "LIN bus"),
|
||||
p("10", "WAKE", "KL15", "Ignition / wake input"),
|
||||
p("11", "GND", "GND", "Ground"),
|
||||
p("12", "GND", "GND", "Ground"),
|
||||
p("13", "GPIOHP2", "LOAD_12V", "High-current switched output, 8 A"),
|
||||
p("14", "GPIOHP4", "LOAD_12V", "High-current switched output, 8 A"),
|
||||
p("15", "GPIOHP6", "LOAD_12V", "High-current switched output, 8 A"),
|
||||
p("16", "GPIOHP8", "LOAD_12V", "High-current switched output, 8 A"),
|
||||
p("17", "RLY1_B", "COIL", "Relay 1 coil, terminal B"),
|
||||
p("18", "RLY2_B", "COIL", "Relay 2 coil, terminal B"),
|
||||
p("19", "FAULT_OUT", "FAULT", "Latched check-engine output"),
|
||||
p("20", "AUX_IN", "ANALOG_1", "0–12 V analog / frequency input"),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "skudak-vcu-black",
|
||||
name: "Skudak VCU — BLACK",
|
||||
manufacturer: "Skudak",
|
||||
partNumber: "VCU-001 (BLACK)",
|
||||
description: "VCUv2 rev A right receptacle — 12 MPIO signal channels, HVIL, 3× CAN. Mates Molex 0334722006.",
|
||||
pinCount: 20,
|
||||
pinSpecs: [
|
||||
p("1", "MPIO1", "PWM_OUT", "Source / sink / Hi-Z, PWM, analog or freq in"),
|
||||
p("2", "MPIO2", "FREQ_IN", "Source / sink / Hi-Z"),
|
||||
p("3", "MPIO3", "PWM_OUT", "Source / sink / Hi-Z"),
|
||||
p("4", "MPIO4", "FREQ_IN", "Source / sink / Hi-Z"),
|
||||
p("5", "MPIO5", "DIG_IN", "Source / sink / Hi-Z"),
|
||||
p("6", "MPIO6", "DIG_IN", "Source / sink / Hi-Z"),
|
||||
p("7", "HVIL OUT", "HVIL_OUT", "Interlock drive, VCU is master"),
|
||||
p("8", "CAN1 H", "CAN1_H", "Powertrain bus"),
|
||||
p("9", "CAN2 H", "CAN2_H", "HV pack bus"),
|
||||
p("10", "CAN3 H", "CAN3_H", "Charge & body bus"),
|
||||
p("11", "MPIO7", "DIG_OUT", "Source / sink / Hi-Z"),
|
||||
p("12", "MPIO8", "DIG_OUT", "Source / sink / Hi-Z"),
|
||||
p("13", "MPIO9", "DIG_IN", "Source / sink / Hi-Z"),
|
||||
p("14", "MPIO10", "DIG_IN", "Source / sink / Hi-Z"),
|
||||
p("15", "MPIO11", "ANALOG_2", "Source / sink / Hi-Z"),
|
||||
p("16", "MPIO12", "ANALOG_3", "Source / sink / Hi-Z"),
|
||||
p("17", "HVIL RTN", "HVIL_RTN", "Interlock return"),
|
||||
p("18", "CAN1 L", "CAN1_L", "Powertrain bus"),
|
||||
p("19", "CAN2 L", "CAN2_L", "HV pack bus"),
|
||||
p("20", "CAN3 L", "CAN3_L", "Charge & body bus"),
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
"Skudak Standard Parts": [
|
||||
{
|
||||
id: "dilong-obc",
|
||||
name: "Dilong OBC / DCDC",
|
||||
manufacturer: "Dilong",
|
||||
partNumber: "DA8KM22A",
|
||||
description: "On-board charger + DC/DC. Controlled entirely over CAN — see Dilong_DA8KM22A_OBC_DCDC_Rev0.dbc. LV connector only; HV and AC are separate.",
|
||||
pinCount: 6,
|
||||
verify: true,
|
||||
pinSpecs: [
|
||||
p("1", "12V+", "KL30", "Permanent supply"),
|
||||
p("2", "GND", "GND", "Ground"),
|
||||
p("3", "CAN H", "CAN3_H", "Charge & body bus"),
|
||||
p("4", "CAN L", "CAN3_L", "Charge & body bus"),
|
||||
p("5", "ENABLE", "DIG_OUT", "Charge enable"),
|
||||
p("6", "INTERLOCK", "HVIL_OUT", "Loop through HV connector"),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "openinverter-ldu-23p",
|
||||
name: "Openinverter LDU — 23-pin Tesla",
|
||||
manufacturer: "openinverter / Damien Maguire",
|
||||
partNumber: "Tesla LDU logic board",
|
||||
description:
|
||||
"Openinverter logic board in a Tesla Large Drive Unit, 23-way Tesla connector. " +
|
||||
"The board drives precharge (pin 3) and the main contactor (pin 6) from its own outputs, and takes the pedal, " +
|
||||
"shifter, brake, cruise and start as discrete inputs. All of those can move onto CAN instead " +
|
||||
"(potmode=2/3/6, cruisemode=2, CANIOS bitfield) if you would rather the VCU own them. Pins 19 and 20 are unused.",
|
||||
pinCount: 23,
|
||||
pinSpecs: [
|
||||
p("1", "IGN +12V", "KL15", "Ignition feed to the logic board"),
|
||||
p("2", "BRAKE ON", "DIG_IN", "brake_in — required for shift lockout"),
|
||||
p("3", "PRECHARGE RELAY", "COIL", "prec_out — board drives the precharge coil"),
|
||||
p("4", "CAN HIGH", "CAN1_H", "Powertrain bus"),
|
||||
p("5", "CAN LOW", "CAN1_L", "Powertrain bus"),
|
||||
p("6", "MAIN CONTACTOR", "COIL", "dcsw_out — board drives the main contactor coil"),
|
||||
p("7", "FORWARD", "DIG_IN", "fwd_in"),
|
||||
p("8", "REVERSE", "DIG_IN", "rev_in"),
|
||||
p("9", "ENC +5V", "V5_REF", "Encoder supply"),
|
||||
p("10", "ENC A", "FREQ_IN", "Quadrature channel A"),
|
||||
p("11", "GND", "GND", "Power ground"),
|
||||
p("12", "ACCEL 5V", "V5_REF", "Pedal supply"),
|
||||
p("13", "ACCEL INPUT", "ANALOG_1", "Pedal wiper"),
|
||||
p("14", "BRAKE TRANSDUCER", "ANALOG_2", "Analog brake pressure"),
|
||||
p("15", "ACCEL GND", "GND_SIG", "Pedal return"),
|
||||
p("16", "ENC B", "ENC_B", "Quadrature channel B"),
|
||||
p("17", "ENC GND", "GND_SIG", "Encoder return"),
|
||||
p("18", "ENC SHIELD", "SHIELD", "Encoder cable drain"),
|
||||
p("19", "—", null, "Unused"),
|
||||
p("20", "—", null, "Unused"),
|
||||
p("21", "CRUISE IN", "DIG_IN", "cruise_in"),
|
||||
p("22", "GND", "GND", "Power ground"),
|
||||
p("23", "START", "DIG_IN", "start_in"),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "bmw-pedal",
|
||||
name: "BMW Accelerator Pedal",
|
||||
manufacturer: "BMW / Bosch",
|
||||
partNumber: "BMW E-series",
|
||||
description: "Dual-channel hall pedal. Channel 2 reads roughly half of channel 1 for plausibility. Verify pin order against your specific pedal before crimping.",
|
||||
pinCount: 6,
|
||||
verify: true,
|
||||
pinSpecs: [
|
||||
p("1", "SEN2 GND", "GND_SIG", "Channel 2 ground"),
|
||||
p("2", "SEN2 +5V", "V5_REF", "Channel 2 supply"),
|
||||
p("3", "SEN2 SIG", "ANALOG_2", "Channel 2 signal (half-scale)"),
|
||||
p("4", "SEN1 SIG", "ANALOG_1", "Channel 1 signal (full-scale)"),
|
||||
p("5", "SEN1 +5V", "V5_REF", "Channel 1 supply"),
|
||||
p("6", "SEN1 GND", "GND_SIG", "Channel 1 ground"),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "honeywell-cssv1500",
|
||||
name: "Honeywell Current Sensor",
|
||||
manufacturer: "Honeywell",
|
||||
partNumber: "CSSV1500",
|
||||
description: "CAN pack-current sensor. 24-bit high-precision + 16-bit low-precision current. Lives inside the battery enclosure.",
|
||||
pinCount: 4,
|
||||
pinSpecs: [
|
||||
p("1", "12V+", "KL15", "Enclosure 12 V bus"),
|
||||
p("2", "GND", "GND", "Enclosure ground"),
|
||||
p("3", "CAN H", "CAN2_H", "HV pack bus"),
|
||||
p("4", "CAN L", "CAN2_L", "HV pack bus"),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "bender-iso175",
|
||||
name: "Bender ISO175 IMD",
|
||||
manufacturer: "Bender",
|
||||
partNumber: "ISO175",
|
||||
description: "Insulation monitoring device. CAN reporting; isolation below 100 kΩ aborts charging. Lives inside the battery enclosure.",
|
||||
pinCount: 6,
|
||||
pinSpecs: [
|
||||
p("1", "12V+", "KL15", "Enclosure 12 V bus"),
|
||||
p("2", "GND", "GND", "Enclosure ground"),
|
||||
p("3", "CAN H", "CAN2_H", "HV pack bus"),
|
||||
p("4", "CAN L", "CAN2_L", "HV pack bus"),
|
||||
p("5", "HV+", "HV_SENSE", "Pack positive sense"),
|
||||
p("6", "HV−", "HV_SENSE", "Pack negative sense"),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "bosch-ibooster",
|
||||
name: "Bosch iBooster",
|
||||
manufacturer: "Bosch",
|
||||
partNumber: "iBooster Gen2",
|
||||
description: "Electromechanical brake booster. CAN-commanded with its own power feed. PINOUT UNVERIFIED — confirm against your generation and connector before building.",
|
||||
pinCount: 8,
|
||||
verify: true,
|
||||
pinSpecs: [
|
||||
p("1", "B+", "KL30", "Battery positive, heavy feed"),
|
||||
p("2", "GND", "GND", "Power ground"),
|
||||
p("3", "KL15", "KL15", "Ignition"),
|
||||
p("4", "CAN H", "CAN1_H", "Chassis / powertrain bus"),
|
||||
p("5", "CAN L", "CAN1_L", "Chassis / powertrain bus"),
|
||||
p("6", "BLS", "DIG_IN", "Brake light switch out"),
|
||||
p("7", "WAKE", "DIG_OUT", "Wake line"),
|
||||
p("8", "GND SIG", "GND_SIG", "Signal ground"),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "prius-eps",
|
||||
name: "Toyota Prius EPS Column",
|
||||
manufacturer: "Toyota",
|
||||
partNumber: "Prius EPS",
|
||||
description: "Electric power steering column, torque sensor + motor + ECU. PINOUT UNVERIFIED — confirm generation (Gen2 / Gen3) and connector before building.",
|
||||
pinCount: 6,
|
||||
verify: true,
|
||||
pinSpecs: [
|
||||
p("1", "B+", "KL30", "Heavy motor feed"),
|
||||
p("2", "GND", "GND", "Power ground"),
|
||||
p("3", "IG", "KL15", "Ignition / enable"),
|
||||
p("4", "TRQ", "ANALOG_1", "Torque sensor signal"),
|
||||
p("5", "SPD", "FREQ_IN", "Vehicle speed input"),
|
||||
p("6", "DIAG", "DIG_IN", "Diagnostic line"),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "volvo-ps-pump",
|
||||
name: "Volvo Steering Pump",
|
||||
manufacturer: "Volvo",
|
||||
partNumber: "Electro-hydraulic PS",
|
||||
description: "Electro-hydraulic power steering pump. Speed commanded by PWM or LIN depending on variant. PINOUT UNVERIFIED — confirm variant before building.",
|
||||
pinCount: 4,
|
||||
verify: true,
|
||||
pinSpecs: [
|
||||
p("1", "B+", "KL30", "Heavy motor feed"),
|
||||
p("2", "GND", "GND", "Power ground"),
|
||||
p("3", "CTRL", "PWM_OUT", "Speed command"),
|
||||
p("4", "DIAG", "FREQ_IN", "Status / diagnostic feedback"),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "instrument-cluster",
|
||||
name: "Instrument Cluster",
|
||||
manufacturer: "varies",
|
||||
partNumber: "varies",
|
||||
description: "Gauge cluster — switched 12 V and CAN only. VCU broadcasts SOC (0x3D0) and gauge control (0x3D2).",
|
||||
pinCount: 4,
|
||||
pinSpecs: [
|
||||
p("1", "12V", "KL15", "Switched supply"),
|
||||
p("2", "GND", "GND", "Ground"),
|
||||
p("3", "CAN H", "CAN3_H", "Charge & body bus"),
|
||||
p("4", "CAN L", "CAN3_L", "Charge & body bus"),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "dnr-switch",
|
||||
name: "DNR Switch",
|
||||
manufacturer: "varies",
|
||||
partNumber: "varies",
|
||||
description: "Drive / Neutral / Reverse selector. Discrete switched-to-ground lines, one per position; firmware rejects any state where more than one is active.",
|
||||
pinCount: 4,
|
||||
pinSpecs: [
|
||||
p("1", "COM", "GND", "Switch common to ground"),
|
||||
p("2", "DRIVE", "DIG_IN", "Drive position"),
|
||||
p("3", "NEUTRAL", "DIG_IN", "Neutral position"),
|
||||
p("4", "REVERSE", "DIG_IN", "Reverse position"),
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
"Battery Enclosure": [
|
||||
{
|
||||
id: "batt-enclosure-32p",
|
||||
name: "Battery Enclosure Bulkhead — 32-pin",
|
||||
manufacturer: "TE Connectivity (Deutsch)",
|
||||
partNumber: "TBD — confirm 32-way P/N",
|
||||
description:
|
||||
"Single bulkhead between the battery enclosure and the vehicle harness. Everything inside shares one 12 V bus and one ground, fed on pins 1–4. " +
|
||||
"All contactor coils are LOW-SIDE switched by the VCU: coil+ ties to the internal 12 V bus and stays in the box, so only the coil− return crosses the bulkhead — " +
|
||||
"one wire per contactor on pins 9–13. PROPOSED ALLOCATION — confirm the Deutsch part number and re-order to suit the keying.",
|
||||
pinCount: 32,
|
||||
verify: true,
|
||||
// One device covering both faces of the bulkhead: 32 IN pins on the left,
|
||||
// 32 OUT on the right, one label per circuit down the middle.
|
||||
passThrough: true,
|
||||
pinSpecs: [
|
||||
p("1", "12V BUS", "KL15", "Enclosure 12 V bus feed"),
|
||||
p("2", "12V BUS", "KL15", "Enclosure 12 V bus feed (paralleled)"),
|
||||
p("3", "GND", "GND", "Enclosure ground"),
|
||||
p("4", "GND", "GND", "Enclosure ground (paralleled)"),
|
||||
p("5", "CAN2 H", "CAN2_H", "BMS + IMD + current sensor"),
|
||||
p("6", "CAN2 L", "CAN2_L", "BMS + IMD + current sensor"),
|
||||
p("7", "HVIL IN", "HVIL_OUT", "Interlock into enclosure"),
|
||||
p("8", "HVIL OUT", "HVIL_RTN", "Interlock out of enclosure"),
|
||||
// Coils are low-side switched by the VCU. Coil+ sits on the internal
|
||||
// 12 V bus and never crosses the bulkhead, so each contactor takes one
|
||||
// wire out, not a pair — the VCU sinks it to close the contactor.
|
||||
p("9", "MAIN COIL −", "COIL", "Main (positive) contactor — VCU sinks to close"),
|
||||
p("10", "NEG COIL −", "COIL", "Negative contactor — VCU sinks to close"),
|
||||
p("11", "PRE COIL −", "COIL", "Precharge relay — VCU sinks to close"),
|
||||
p("12", "AC COIL −", "COIL", "A/C contactor — VCU sinks to close"),
|
||||
p("13", "HEAT COIL −", "COIL", "Heat contactor — VCU sinks to close"),
|
||||
p("14", "MAIN WELD", "WELD", "Main contactor aux contact"),
|
||||
p("15", "MAIN WELD RTN","WELD", "Main aux return — drop if the aux references the internal ground bus"),
|
||||
p("16", "NEG WELD", "WELD", "Negative contactor aux contact"),
|
||||
p("17", "NEG WELD RTN", "WELD", "Negative aux return — drop if the aux references the internal ground bus"),
|
||||
p("18", "BMS WAKE", "INHIBIT", "BMS wake / enable"),
|
||||
p("19", "PRE FEEDBACK", "ANALOG_1", "Precharge bus voltage feedback"),
|
||||
p("20", "PACK TEMP", "ANALOG_2", "Spare pack thermistor"),
|
||||
p("21", "SHIELD", "SHIELD", "CAN shield drain"),
|
||||
p("22", "—", null, "Spare"),
|
||||
p("23", "—", null, "Spare"),
|
||||
p("24", "—", null, "Spare"),
|
||||
p("25", "—", null, "Spare"),
|
||||
p("26", "—", null, "Spare"),
|
||||
p("27", "—", null, "Spare"),
|
||||
p("28", "—", null, "Spare"),
|
||||
p("29", "—", null, "Spare"),
|
||||
p("30", "—", null, "Spare"),
|
||||
p("31", "—", null, "Spare"),
|
||||
p("32", "—", null, "Spare"),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "contactor-coil-aux",
|
||||
name: "HV Contactor (coil + aux)",
|
||||
manufacturer: "varies",
|
||||
partNumber: "varies",
|
||||
description: "HV contactor with auxiliary weld-detect contacts. Use for main, negative, A/C and heat. Coil must have a built-in economizer. Inside the enclosure COIL A ties to the shared 12 V bus; only COIL B leaves via the bulkhead, where the VCU sinks it.",
|
||||
pinCount: 4,
|
||||
pinSpecs: [
|
||||
p("1", "COIL A", "COIL", "Coil terminal A"),
|
||||
p("2", "COIL B", "COIL", "Coil terminal B"),
|
||||
p("3", "AUX A", "WELD", "Auxiliary contact — weld detect"),
|
||||
p("4", "AUX B", "WELD", "Auxiliary contact — weld detect"),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "precharge-relay",
|
||||
name: "Precharge Relay",
|
||||
manufacturer: "varies",
|
||||
partNumber: "varies",
|
||||
description: "Precharge relay and series resistor. Closes with the negative contactor, opens once the bus reaches threshold. COIL A ties to the enclosure 12 V bus; COIL B is the low-side return to the VCU.",
|
||||
pinCount: 2,
|
||||
pinSpecs: [
|
||||
p("1", "COIL A", "COIL", "Coil terminal A"),
|
||||
p("2", "COIL B", "COIL", "Coil terminal B"),
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "vw-meb-bms",
|
||||
name: "VW MEB BMS — LV connector",
|
||||
manufacturer: "Volkswagen",
|
||||
partNumber: "MEB",
|
||||
description:
|
||||
"VW MEB battery management master, 12-way LV connector. Pins 7–12 carry OEM harness colours recovered from the VW bms diagram and must match the factory loom. " +
|
||||
"SIGNAL ASSIGNMENT UNCONFIRMED — the source diagram recorded colours but no pin labels. Pins 1–6 were unused there.",
|
||||
pinCount: 12,
|
||||
verify: true,
|
||||
pinSpecs: [
|
||||
p("1", "—", null, "Unused in the recovered harness"),
|
||||
p("2", "—", null, "Unused in the recovered harness"),
|
||||
p("3", "—", null, "Unused in the recovered harness"),
|
||||
p("4", "—", null, "Unused in the recovered harness"),
|
||||
p("5", "—", null, "Unused in the recovered harness"),
|
||||
p("6", "—", null, "Unused in the recovered harness"),
|
||||
po("7", "OEM 7", OEM.meb.greenWhite, "OEM Green/White — signal unconfirmed"),
|
||||
po("8", "CAN L?", OEM.meb.orangeRed, "OEM Orange/Red — VW HV-CAN pair with pin 9, polarity unconfirmed"),
|
||||
po("9", "CAN H?", OEM.meb.orangeBlue, "OEM Orange/Blue — VW HV-CAN pair with pin 8, polarity unconfirmed"),
|
||||
po("10", "OEM 10", OEM.meb.greenRed, "OEM Green/Red — signal unconfirmed"),
|
||||
po("11", "GND", OEM.meb.greenBlack, "OEM Green/Black — ran to chassis ground in the recovered harness"),
|
||||
po("12", "OEM 12", OEM.meb.brown, "OEM Brown — VW convention is ground; ran to the pigtail, not to chassis"),
|
||||
],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// ── Merge into the connector library ─────────────────────────────────────────
|
||||
// Parts become ordinary library entries, so search, category filter and
|
||||
// drag-to-canvas all work with no changes to app.js.
|
||||
for (const [category, parts] of Object.entries(SKUDAK_PARTS)) {
|
||||
CONNECTOR_LIBRARY[category] = parts;
|
||||
for (const part of parts) {
|
||||
part.pinLabels = part.pinSpecs.map(s => s.name);
|
||||
_CONN_BY_ID[part.id] = part;
|
||||
}
|
||||
}
|
||||
|
||||
// ── Wire default lookup ──────────────────────────────────────────────────────
|
||||
// Given a device and pin id, return the standard wire for that pin, or null.
|
||||
function standardWireForPin(device, pinId) {
|
||||
if (!device) return null;
|
||||
const pin = (device.pins || []).find(p => p.id === pinId);
|
||||
if (!pin) return null;
|
||||
// An OEM colour is not ours to choose — it has to match the factory loom,
|
||||
// so it wins over the in-house standard.
|
||||
// The signal name is what makes a wire unambiguous on the bench. A connector
|
||||
// can legitimately carry five digital inputs in the same colour; the pin name
|
||||
// is what tells FORWARD from REVERSE.
|
||||
const signal = pin.name && pin.name !== "—" ? pin.name : null;
|
||||
if (pin.wire_oem) return { fn: "OEM", twisted_pair: false, signal, ...pin.wire_oem };
|
||||
if (pin.wire_fn) {
|
||||
const spec = wireSpecFor(pin.wire_fn);
|
||||
return spec ? { ...spec, signal } : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Expose the palette for the wire-colour swatch picker.
|
||||
const TXL_WIRE_COLORS = [
|
||||
...Object.values(TXL_SOLID).map(c => ({ name: c.name, hex: c.hex, stripe: null })),
|
||||
...Object.values(TXL_STRIPED).map(c => ({ name: c.name, hex: c.hex, stripe: c.stripe })),
|
||||
];
|
||||
Reference in New Issue
Block a user