UEP-0001: Terminals, terminal strips and wires¶
| UEP | 0001 |
| Title | Terminals, terminal strips and wires |
| Status | Draft. The part that the current format can carry, for tree cables (wire_marking, wire_marks, cable.marks, exports wires / markers / cables, marks --write) is implemented in the reference library |
| Target | uniwire format 2.0 |
| Type | Format change (additive) |
| Created | 2026-10-12 |
| Discussion | GitHub issue with the uep label |
The key words MUST, MUST NOT, SHOULD and MAY are to be interpreted as described in RFC 2119. Section references of the form "SPEC §n" point to the uniwire specification (format 1.0).
Abstract¶
This proposal adds wiring information to uniwire without changing what a 1.x document means. It adds:
- named ports on every node (the terminals of the equipment:
1,2,A1,A2,13,14,U1,PE…), with defaults taken from the type registry, overrides on the node, and a reference syntax<node id>#<port>; - terminal strips (
terminal_strips[]), whose terminals are addressable like ports (X1#3, shown as-X1:3); - wires (
wires[]) and cables (cables[]) as first-class objects; - potentials (equipotential nets): derived from the power tree and the wires, and optionally named
(
potentials[]); - wire marking rules in views, and exports of the wire marker list, the terminal plan and the cable schedule;
- a sketch (not normative) of a future
"control"view kind that would draw control schematics from the same data; - consistency rules, and mappings to IEC 81346, IEC 61082, IEC 60445, CIM, IFC and IEC 61850 SCL.
Layout stays automatic. A document still contains no coordinates. The single-line diagram stays the main use case: everything added here is optional.
1. Motivation¶
1.1 Use cases¶
A single-line diagram is rarely the only electrical document of a project. The same installation is also described by:
- control schematics: coils, auxiliary contacts, push buttons, pilot lights, PLC inputs and outputs, self-hold circuits, interlocks, arranged in current paths with cross-references from each coil to its contacts;
- panel wiring: point-to-point connection lists used to build a cabinet, often with one row per wire (from terminal, to terminal, cross-section, colour, mark);
- terminal plans: for each terminal strip, what lands on each terminal on the cabinet side and on the field side, the bridges, and the cable cores;
- wire marking and ferrule lists: the marks printed on sleeves at both ends of each wire;
- cable schedules: each cable with its type, its cores, its length, the enclosures it connects and the use of each core;
- commissioning: loop checks and point-to-point tests, done terminal by terminal;
- maintenance: finding where a wire goes, which terminals are on a potential, which contacts a coil drives.
Electrical CAD tools hold this information in proprietary databases. No open, compact, text-based format covers it with the same principles as uniwire: describe the installation, not the drawing.
1.2 What uniwire 1.x cannot express¶
The 1.x format describes power topology (a tree plus links) and stops at the level of a device:
terminal_block.terminalsis free text ("X1.1-X1.12"). Individual terminals cannot be referenced, so a terminal plan cannot be generated or checked.links[].from_port/to_portare free strings. Only the PLC formslot.channelis checked (ruleplc.port). A link{"kind": "control", "from": "A1", "from_port": "2.1", "to": "KM1"}says that a PLC output controls a contactor; it does not say that the output lands on terminalA1of the coil through terminal 10 of strip-X1.- Auxiliary equipment is a list of names (
aux: ["MX", "OF"]). An auxiliary contact or a release cannot be wired, and its relation to its parent cannot be shown in a cross-reference. - A cable belongs to exactly one tree edge (
node.cable). A control cable that carries several circuits between a cabinet and a push-button station has nowhere to go, and its cores cannot be listed. - The multi-line view already derives one conductor per phase and draws the poles of each device. The conductors have no identity in the file, so they cannot be marked or exported.
- The specification already lists "named ports (
Q1#MX,T1#N)" and "cable as a first-class edge" among the items planned for 2.0 (SPEC §3a, "Out of scope").
2. Goals and non-goals¶
2.1 Goals¶
- G1. Any terminal of any device, and any terminal of a terminal strip, can be referenced by a short, stable string.
- G2. A wire can be described with the attributes used in practice: ends, mark, cross-section, colour, cable and core, conductor function, potential.
- G3. A terminal plan, a wire list, a wire marker list and a cable schedule can be generated from a document and checked by rules.
- G4. Power conductors already derived by the multi-line view get an identity (ports and potentials) with no extra data, so they can be marked and exported.
- G5. A future control-schematic view needs no other data than what this proposal adds.
- G6. Every 1.x document stays valid and keeps its meaning. A 2.0 document that uses none of the new sections reads exactly like a 1.x document.
2.2 Non-goals¶
- N1. Not a full electrical CAD model. No sheets, symbols, coordinates, wire routing, ducts, rail layout or 3D panel layout. The file still describes the installation, and the drawing is computed.
- N2. Geometry stays automatic. Views may carry preferences (marking scheme, order of current paths); they never carry topology.
- N3. The single-line diagram stays the main use case. Ports, wires and terminal strips are optional. A
single-line diagram never needs them, and no rule of the
coreprofile requires them. - N4. Not a product database. Port defaults follow common marking conventions. Products that differ declare their own ports (on the node, in a template, or through the product).
- N5. No PLC programming, no signal lists beyond what wiring needs (channel, label).
3. Proposal¶
3.1 Named ports¶
3.1.1 Port model¶
A port is a terminal of a node: a point where a conductor can be connected. Each node has a set of ports.
The set comes from the type registry (§3.1.3), optionally merged with a ports list on the node (§3.1.4).
| Field | Type | Description |
|---|---|---|
id |
string, required | Port identifier, unique within the node. Pattern ^[A-Za-z0-9+-][A-Za-z0-9_.:/+-]*$. Examples: 1, 2, A1, 13, U1, PE, 2N, L+, 3.1 (PLC slot 3, channel 1), X1:3 (pin 3 of the device's own connector X1). Case-sensitive |
marking |
string | Terminal marking printed on the device, when it differs from id or repeats (N on both sides of a neutral pole). Default: id |
aliases |
string[] | Other accepted names in references (L1 for 1, T1 for 2, N for 2N, U for U1) |
function |
enum | pole_in, pole_out, power_in, power_out, neutral, earth, shield, coil, contact_no, contact_nc, contact_co, signal_in, signal_out, supply, comm, other |
pole |
integer ≥ 1 | Rank of the pole or winding. Used to assign a conductor by position (§3.4.2) |
conductor |
enum | Fixed conductor of the port when it does not depend on the circuit: N, PE, PEN, L+, L-… |
pair |
string | The other terminal of the same pole, contact, coil or winding (2 for 1, A2 for A1, 14 for 13) |
label |
text | Description (Start, Run feedback) |
mandatory |
boolean | The port must be connected when the node is wired (§3.7). Registry default: true for coils and for power poles of wired nodes, false otherwise |
capacity |
integer ≥ 1 | Maximum number of conductors on the terminal. Registry default: 2; PLC channels: 1 |
section_max_mm2 |
number | Largest conductor the terminal accepts |
ext |
object | Extensions |
Port functions:
function |
Meaning | Examples |
|---|---|---|
pole_in / pole_out |
Line side / load side of a power pole of a switching or protective device | breaker 1 / 2, contactor 1/L1 / 2/T1 |
power_in / power_out |
Power terminal of a load, or the input / output of a source or converter | motor U1, power supply L / L+, transformer 1U / 2U |
neutral, earth, shield |
Neutral, protective or functional earth, cable screen | N, PE, screen clamp |
coil |
Operating coil or release | A1, A2; shunt release C1, C2; undervoltage release D1, D2 |
contact_no / contact_nc / contact_co |
Auxiliary contact: normally open, normally closed, common of a changeover | 13-14, 21-22, 11 (common) with 12 / 14 |
signal_in / signal_out |
Input / output of a controller or a sensor | PLC 1.1, 2.1 |
supply |
Auxiliary supply of an electronic device | PLC L+, M |
comm |
Communication port | RJ45, RS485 terminals |
3.1.2 Port references¶
A port is referenced by <node id>#<port>:
KM1#A1 coil terminal A1 of contactor KM1
Q1#2 load-side terminal of pole 1 of breaker Q1
A1#2.1 PLC A1, slot 2, channel 1
X1#3 terminal 3 of terminal strip X1 (§3.2)
T1#N neutral of transformer T1 (alias of port 2N)
Q1#MX the shunt-release auxiliary of Q1, as a whole (§3.1.5)
Q1.MX#C1 terminal C1 of that auxiliary
- The node part matches the identifier pattern of SPEC §3 (
^[A-Za-z_][A-Za-z0-9_.-]*$), which excludes#. A reference is split at its first#. - Only nodes with an explicit
idcan be referenced. Generated identifiers are not stable, so a reference to a generated identifier is an error. - The port part is matched against
idfirst, then againstaliases. An alias that matches two ports of the same node is an error.uniwire normalizerewrites aliases to the canonicalid. - Identifiers of nodes, terminal strips, cables, wires and potentials share one namespace (unique within
the document), so
X1#3is never ambiguous. Enclosure identifiers keep their own namespace, as in 1.x. - Display: a port is displayed as
<ref>:<marking>, for example-KM1:A1or-X1:3. The colon is the terminal prefix of IEC 81346 reference designations. When the node has noref, itsidis used. Views and exports MAY prefix the location (+FS3-S1:11) when the two ends of a wire are in different enclosures.
Links. The fields links[].from_port / to_port keep their place. In 2.0 their value is the port
part of a port reference: {"from": "A1", "from_port": "2.1"} designates A1#2.1 and is checked like
one. As a shorthand, from / to MAY carry a full port reference ("from": "A1#2.1"). A link that carries
both forms MUST be consistent. Links remain the single-line abstraction ("A1 controls KM1"). Wires (§3.3)
describe the physical connections behind them.
3.1.3 Registry defaults¶
Each type of the registry (core.json)
gains an optional ports entry. Defaults may depend on a field of the node, usually poles or contacts. The
registry stores port sets selected by that field, or a generator for ports that depend on the node's
content (PLC channels, contact lists, conductors of a load).
"breaker": {
"ports": {
"by": "poles",
"sets": {
"1P": [{"id": "1", "function": "pole_in", "pole": 1, "pair": "2"},
{"id": "2", "function": "pole_out", "pole": 1, "pair": "1"}],
"3P+N": ["… 1-2, 3-4, 5-6 …",
{"id": "N1", "marking": "N", "function": "neutral", "pair": "N2"},
{"id": "N2", "marking": "N", "function": "neutral", "pair": "N1"}]
},
"default": "3P"
}
}
The defaults below follow common practice for low-voltage equipment (IEC 60445 for equipment terminals and conductors, and the terminal marking conventions used for control devices in the IEC 60947 series). Products that differ declare their own ports.
| Type | Default ports |
|---|---|
breaker, fuse, fuse_switch, switch_disconnector, disconnector, main_breaker |
One pair per pole: 1-2, 3-4, 5-6 (1P: 1-2; 2P: 1-2, 3-4; 4P: + 7-8). Unprotected neutral pole of 1P+N / 3P+N: N1-N2, both marked N. Odd = line side (pole_in), even = load side (pole_out) |
rcd, rcbo |
Same as the breaker. A 2-pole RCD is 1-2 and N1-N2 |
contactor |
Main poles 1-2, 3-4, 5-6 (+ 7-8 for 4P), aliases L1/T1, L2/T2, L3/T3. Coil A1-A2. Built-in auxiliary contacts from the new optional field contacts (below) |
impulse_relay |
Poles as the contactor, coil A1-A2 |
thermal_relay |
1-2, 3-4, 5-6 (aliases L1/T1…), auxiliary contacts 95-96 (NC) and 97-98 (NO) |
motor_starter |
Poles 1-2, 3-4, 5-6. Other terminals (drive control terminals) are product-specific: declare them, for instance X1:3 |
motor |
U1, V1, W1 (aliases U, V, W), PE. Single-phase (phases: 1): U1, U2, PE. Six-terminal motors (star-delta) add U2, V2, W2 through ports or a template |
transformer |
1U, 1V, 1W (primary), 2U, 2V, 2W (secondary), 2N (alias N) when the vector group has a neutral (Dyn11), PE |
power_supply |
L, N, PE (input), L+, L- (output, aliases +, -). AC output: L, N of the secondary as 2L, 2N |
plc |
Head unit supply L+, M, PE. One port per channel, generated from onboard[] and modules[]: <slot>.<channel> (0.3 = built-in channel 3), signal_in for di / ai / counter / temperature modules, signal_out for do / ao / relay_out. Capacity 1. Commons and module supply terminals are declared in ports |
spd |
One terminal per protected conductor (L1, L2, L3, N), and PE |
grid, generator, ups, offpage, busbar |
One port per conductor of the derived system: L1, L2, L3, N, PEN, PE (L+, L- in DC) |
board |
PE (protective conductor terminal of the enclosure); N when the board carries a neutral |
earth_bar |
PE with a capacity of 0 (unlimited). Further terminals are declared |
Loads (socket, lighting, heating, load…) |
One port per derived conductor: L (or L1, L2, L3), N, PE |
| Control devices (§3.1.6) | From contacts: see below |
Contact lists. Types that carry auxiliary contacts (contactor, control_relay, push_button,
selector_switch, auxiliary) accept an optional field contacts, an ordered list of NO, NC and CO
(changeover). Default ports follow the two-digit convention: the first digit is the position of the contact in
the list (1, 2, 3…), the second digit is its function (1-2 normally closed, 3-4 normally open, 1
common with 2 / 4 for a changeover). So ["NO", "NC"] gives 13-14 and 21-22, a stop button
["NC"] gives 11-12, and a start button ["NO"] gives 13-14.
3.1.4 Overrides on the node¶
Every node gains two optional fields:
| Field | Description |
|---|---|
ports |
List of ports (§3.1.1). Merged by id with the registry defaults: an entry with an existing id replaces the default, a new id adds a port |
port_defaults |
false drops the registry defaults, so only ports applies. Default true |
ports is an ordinary attribute, so it can come from a template (use, SPEC §3.3). A template is the natural
place for the terminal layout of a product range. Overriding the marking of a contactor whose built-in contact
is a normally closed contact marked 21-22:
{"id": "KM2", "type": "contactor", "ref": "-KM2", "poles": "3P", "coil_V": 230, "contacts": ["NC"],
"ports": [{"id": "21", "function": "contact_nc", "pair": "22"},
{"id": "22", "function": "contact_nc", "pair": "21"}]}
With contacts: ["NC"] alone, the default would be 11-12. The two override entries add 21-22, but
11-12 are still generated. To replace them, set port_defaults: false and declare every port, or use a
template that does so.
3.1.5 Auxiliary blocks as sub-components¶
Add-on auxiliary contact blocks, shunt releases (MX), undervoltage releases (MN), signalling contacts (OF, SD)
and similar parts have terminals of their own, and they act on, or report, the state of their parent device.
They become nodes of a new type auxiliary, placed in devices[] (SPEC §3a), with a parent relation:
| Field | Description |
|---|---|
type |
auxiliary |
parent |
Required. id of the device the block is mounted on (switching or protective device, relay) |
kind |
aux_contact, alarm_contact, shunt_release, undervoltage_release, motor_operator, other |
name |
Short name used in references and in the 1.x aux[] list: MX, MN, OF, SD |
contacts |
For contact blocks: list of NO / NC / CO (§3.1.3) |
coil_V |
For releases and motor operators |
ref |
Usually the parent's reference designation (-Q1). Auxiliaries are exempt from the duplicate reference rule |
Default ports: shunt_release C1-C2, undervoltage_release D1-D2 (function coil). Contact blocks
number their contacts after the parent's own contacts: the first digit continues from the parent's last
contact. Products differ a lot here, so declaring ports is recommended.
Compatibility with aux[]. Each name of a 1.x aux list implicitly creates an auxiliary with id
<parent id>.<name> (Q1.MX), name = the entry and kind deduced from the name (MX → shunt_release,
MN → undervoltage_release, OF → aux_contact with ["CO"], SD → alarm_contact with ["CO"], any
other name → other). An explicit auxiliary with the same parent and name replaces the implicit one.
Resolution of Q1#MX. When a node has no port MX (by id or alias) but has an auxiliary with
name: "MX", the reference Q1#MX designates that auxiliary as a whole. Such a reference is valid as a
link end ({"kind": "trip", "from": "F10", "to": "Q1#MX"}) but not as a wire end: a wire always ends on a
terminal (Q1.MX#C1).
Cross-references. The contact set of a device is its own contact ports plus the contact ports of all
auxiliaries whose parent is that device. This is what a control view prints under a coil (§3.6). The
relation also gives the bill of materials the accessories of a device.
3.1.6 Control device types¶
Control schematics need a few devices that the 1.x registry does not have. They are added as types allowed in
devices[] (they do not carry power, SPEC §3a):
| Type | Specific fields | Default ports | IEC 81346 letter |
|---|---|---|---|
push_button |
contacts, kind (momentary, maintained, mushroom, emergency_stop, key), color |
From contacts |
S |
selector_switch |
contacts, positions (["0", "1", "2"] or labels) |
From contacts |
S |
pilot_light |
color, un_V |
X1, X2 |
P |
control_relay |
contacts, coil_V, kind (monostable, latching, timer, safety) |
A1, A2 + contacts |
K |
auxiliary |
§3.1.5 | §3.1.5 | as the parent |
Colours use the IEC 60757 two-letter codes (RD, GN, YE, BU, WH, BK…), like wire colours (§3.3).
The IEC 81346-2 class codes are left to the optional data package, as for existing types.
3.2 Terminal strips¶
3.2.1 Decision: a top-level section, not a node¶
Terminal strips are declared in a new top-level section terminal_strips[], not as nodes of the tree.
The reasons:
- A strip is not on a power path. It is crossed by many circuits, power and control, from different feeders. Placing it in the tree would give it one parent. Placing one copy per circuit would split one physical object.
- Its terminals are many independent potentials. A node has one input and one output (SPEC §8). A strip has dozens of unrelated pass-through points.
- The single-line diagram stays as it is. Most single-line diagrams do not show control terminals. Power
terminals that a single-line diagram does show keep using the 1.x
terminal_blocknode, which can now point at a strip (§3.2.3). - It matches how terminal plans are produced and read: one table per strip, terminals in mounting order.
Like enclosures[] (SPEC §3a), the section is a flat list of addressable objects, linked to the rest by
identifiers.
3.2.2 Model¶
"terminal_strips": [
{"id": "X1", "ref": "-X1", "enclosure": "MCC1", "label": "Conveyor 3 field terminals",
"product": {"part_number": "…", "description": "Feed-through terminal 4 mm²"},
"terminals": [
{"no": "1", "kind": "feed_through", "label": "M1 U1", "section_max_mm2": 4},
{"no": "4", "kind": "earth", "label": "M1 PE"},
{"no": "20", "kind": "feed_through", "bridge_group": "B0V", "label": "0 V"},
{"no": "21", "kind": "feed_through", "bridge_group": "B0V", "label": "0 V"},
{"no": "30", "kind": "fuse", "fuse_A": 2, "label": "Sensor supply"}
]}
]
Strip fields:
| Field | Description |
|---|---|
id |
Required. Identifier, in the shared namespace (§3.1.2) |
ref |
Reference designation (-X1) |
label |
Description |
enclosure |
id of the enclosure: an entry of enclosures[], or a board node. When both exist with the same identifier, the enclosure wins |
location |
Free text (IEC 81346 + aspect), when no enclosure is described |
product |
Default product of the terminals (SPEC §3b) |
terminals |
Ordered list, in mounting order on the rail |
status, note, ext |
As on nodes |
Terminal fields:
| Field | Description |
|---|---|
no |
Required. Terminal number, unique within the strip, used as the port id: "1", "PE", "10a". Same pattern as port ids |
kind |
feed_through (default), disconnect, fuse, earth, neutral, spare. Enumeration values use snake_case, like the rest of the format |
bridge_group |
Terminals that share a value are bridged together (plug-in or screw bridge). Bridges never leave the strip |
label |
Description, or the function of the terminal |
section_max_mm2 |
Largest conductor accepted |
points |
Clamping points per side. Default 1 (so 2 conductors per terminal: one on each side) |
fuse_A |
Fuse rating of a fuse terminal |
potential |
Expected potential (§3.4), checked |
product |
Product, when it differs from the strip default |
status, ext |
As on nodes |
A terminal is a port with two sides. A feed-through, earth or neutral terminal connects everything that lands on
it into one net. A disconnect terminal is one net in its normal (closed) state. A fuse terminal behaves like a
fuse: two nets, one on each side, the field side being the protected one. Exports distinguish the two sides of a
terminal (cabinet side, field side) by following the wires: a wire whose other end is in the same enclosure lands
on the cabinet side; a wire that belongs to a cable leaving the enclosure lands on the field side.
3.2.3 Addressing and display¶
- Reference:
X1#3. A strip has no registry ports: its ports are its terminals. - Display:
-X1:3(<ref>:<no>), as for device ports. - The 1.x
terminal_blocknode gains an optional fieldstrip(id of a terminal strip). The single-line diagram can then show a power terminal block in the tree and the terminal plan can list its terminals. The 1.x fieldterminal_block.terminals(free text) is kept and deprecated (§5.3).
3.3 Wires and cables¶
3.3.1 Wires¶
A wire is a conductor with two ends, each on a port or a strip terminal. Wires are listed in a new top-level
section wires[].
"wires": [
{"id": "w25", "from": "X1#11", "to": "KM1#13", "mark": "102", "section_mm2": 0.75, "color": "BU"},
{"id": "w21", "from": "X1#10", "to": "S1#11", "mark": "101", "cable": "W12", "core": "1"},
{"id": "w8", "from": "X1#1", "to": "M1#U1", "cable": "M1.cable", "core": "BN", "conductor": "L1"}
]
| Field | Description |
|---|---|
id |
Identifier (shared namespace). Optional: generated when absent, but then not stable. An explicit id is recommended once marks are frozen |
from, to |
Required. Port references (§3.1.2). They MUST designate terminals, not auxiliaries as a whole |
mark |
Wire mark (ferrule text). When absent, computed by the view's marking rules (§3.5) |
section_mm2 |
Cross-section. For a cable core, defaults to the cable's section_mm2 (or pe_section_mm2 for a PE core) |
size_awg |
Size as printed in AWG, as on cables |
color |
IEC 60757 code: BK, BN, RD, OG, YE, GN, BU, VT, GY, WH, PK, GD, TQ, SR, and GNYE (green-and-yellow) |
designation |
Conductor type (single-core flexible wire type designation…) |
material |
Cu / Al |
cable |
id of the cable this wire is a core of (§3.3.2) |
core |
Core identification within the cable: number ("1") or colour ("BN", "GNYE") |
conductor |
Conductor function: L1, L2, L3, N, PE, PEN, L+, L-. Absent for control and signal wires |
potential |
id of a potential (§3.4), or a port reference (the net containing that port) |
length_m |
Length |
kind |
wire (default) or bridge (a bridge between device terminals, when it is not a strip bridge_group) |
label, status, note, ext |
As on nodes |
Wires are undirected. from and to only fix the order in exports. A port may carry several wires up to its
capacity.
Wires are optional and partial. A document may describe the wiring of one starter and leave the rest of the installation as a single-line description. Tree connections that no wire describes stay implicit (§3.4.2).
3.3.2 Cables¶
A cable groups cores between two places. Cables become first-class objects in a new section cables[]:
"cables": [
{"id": "W12", "ref": "W12", "designation": "control cable, screened", "cores": "4x", "section_mm2": 1.5,
"length_m": 30, "from_enclosure": "MCC1", "to_enclosure": "FS3"}
]
A cable object has every field of the 1.x cable (SPEC §3.2 and §3a: designation, cores, section_mm2,
pe_section_mm2, material, length_m, install, insulation, ref, kind, conductors, cpr_class,
raceway, status…), plus:
| Field | Description |
|---|---|
id |
Required. Identifier (shared namespace) |
from_enclosure, to_enclosure |
Enclosures (or board nodes) at the two ends |
from, to |
Optional end devices or strips, when the cable lands on one object at each end ("from": "X1", "to": "M1") |
core_ids |
Optional explicit list of core identifications (["1", "2", "3", "4"], ["BN", "BK", "GY", "GNYE"]) when the composition does not make it obvious |
screen |
Description of the screen, which may be wired as a core named SH |
Link with the 1.x node.cable. Compatibility is kept both ways:
- An inline 1.x cable stays valid and keeps its meaning (the cable feeding the node from its parent). It is
also addressable by wires with the implicit id
<node id>.cable(M1.cable), and on a link with the implicit id<link id>.cable. The tree does not have to change for wires to use an existing cable. - In 2.0,
node.cableandlinks[].cableMAY instead be a string: the id of an entry ofcables[]("cable": "W11"). A cable shared by several feeders, or one that is not a tree edge (a control cable), is declared once incables[]. - Rendering and rules that read
node.cable(circuit schedule, voltage drop,iec60364.iz) resolve the string to the cable object.
3.4 Potentials¶
3.4.1 Nets and potentials¶
A net is a set of ports connected together by conductors with no device in between: wires, bridges, feed-through terminals, busbars, and the implicit connections of the tree. A potential is the identity of a net. All its wires have the same voltage, and with potential-based numbering they carry the same mark (§3.5).
- A device separates potentials. Each pole of a switch, each contact and each coil has a different net on each side.
- A conductor that passes through a device without being switched (an uncut neutral, the PE) keeps its net.
- A strip terminal does not separate potentials, except a
fuseterminal.
Nets are derived. The optional section potentials[] names some of them and gives them attributes:
"potentials": [
{"id": "P24", "name": "24V", "kind": "control", "un_V": 24, "dc": true, "mark": "24V", "ports": ["F2#2"]},
{"id": "P0V", "name": "0V", "kind": "control", "un_V": 0, "dc": true, "mark": "0V", "ports": ["PS#L-"]}
]
| Field | Description |
|---|---|
id |
Required. Identifier (shared namespace) |
name |
Displayed name (24V, 0V, L1) |
kind |
power, control, signal, earth, neutral |
un_V, dc |
Voltage, and whether it is DC |
mark |
Fixed mark for every wire of the potential. It overrides the marking scheme |
color |
Default wire colour |
section_mm2 |
Default cross-section of its wires |
ports |
Port references that belong to the potential. They anchor it to the derived nets with no wire needed |
A wire's potential field, a terminal's potential field and a potential's ports are assertions,
checked by rule wire.potential (§3.7). Two declared potentials MUST NOT end up in the same net.
3.4.2 Power conductors: mapping the multi-line derivation to potentials¶
The multi-line view already derives the conductors of every node of the power tree with no extra data
(SPEC §7.1; implementation in
layout/multiline.py).
For each node it computes:
inp: the conductors at its input (for exampleL1, L2, L3, PE);out: the conductors at its output (different frominpfor a transformer, a converter, or the board that splits a PEN);src: for each input conductor, the conductor of the parent's output it comes from (Nonewhen the conductor starts here, such as the PE at the main earthing terminal of a TT installation, orPENfor theNand thePEafter a PEN split).
The conductors come, in order of precedence, from the phase of a single-phase circuit, the poles of a device,
the cable cores, the motor phases, the system of a board or busbar, the usual connection of the load type,
and otherwise from upstream. The supply follows installation.system and the earthing system, and transformers
start a new system. For a switching device, the derivation also tells which conductors are switched (the
poles) and which pass through (1P / 3P leave the neutral uncut, 1P+N / 3P+N add an unprotected neutral
pole, a PEN is never switched).
This proposal gives these conductors an identity, with these rules:
- Conductor of a port. A port with a fixed
conductorhas that conductor. Otherwise, a port with apolerank takes the rank-th switched conductor of the node, in the orderL1, L2, L3, L+, L-, N. A1Pbreaker on a circuit withphase: "L2"has ports1,2onL2. A3P+Nbreaker has1-2onL1, …, andN1-N2onN. Loads and sources whose ports are named after conductors are matched by name. - Implicit connections. For each tree edge (parent P, child C) and each conductor c of
C.inp, the output port of P forsrc[c]is connected to the input port of C for c. When a node has no port for a conductor (a board, a busbar, an uncut neutral, a PE through a breaker), it is transparent for that conductor: the connection goes on to the next port up or down the tree. - Nets. Union of the implicit connections, the wires, the strip terminals and the bridges. A busbar or a board with several children gives one net per conductor shared by all its outgoing feeders. Each pole of a device ends a net and starts another.
- Explicit wiring replaces implicit connections. When an end of an implicit connection carries at least one
wire, that implicit connection is dropped. The wires must then connect the same ports, possibly through strip
terminals. In the example (§4),
KM1#2 → X1#1 → M1#U1replaces the implicitKM1#2 → M1#U1. Rulewire.treereports wiring that contradicts the tree (a phase landing on the wrong motor terminal). - Default names. A derived power net is named after its conductor and the device or circuit it leaves:
L1on the supply side, then for instance-Q1:2or circuitC3 L1. These names are for display only. They are not identifiers. A wire refers to a derived net through any of its ports ("potential": "Q1#2"). - PEN split. At the board that splits a PEN, the PEN net continues as the PE net. The N gets a new net,
bonded to it at the split point. In exports the bond appears as a bridge on the board's
PE/Nterminals.
So a document without any wire already has a complete, deterministic set of power nets and ports. That is enough to mark the conductors of a multi-line diagram (§3.5) and to export them.
3.5 Wire marking, exports and display¶
3.5.1 Marking rules in views¶
A view gains an optional wire_marking object, and a boolean wire_marks that shows or hides marks
(default true when wire_marking is present):
"views": [{"id": "ml", "kind": "multi-line",
"wire_marking": {"scheme": "potential", "start": 100, "step": 1, "power": "conductor",
"keep_manual": true}}]
| Field | Default | Description |
|---|---|---|
scheme |
manual |
manual: only wires[].mark is shown. potential: one number per net, shared by all its wires. sequential: one number per wire. pattern: marks built from pattern |
pattern |
- | Template for pattern: tokens {circuit}, {conductor}, {ref} (reference designation of the from node), {from}, {to} (display form of the ends), {from_port}, {to_port}, {potential} (potential name), {strip}, {terminal}, {cable} (cable tag, else cable id), {n} (sequence number). Example "{circuit}-{conductor}" → C3-L1 |
start, step |
1, 1 | First number and increment for potential and sequential |
prefix, suffix |
"" |
Added around generated numbers |
per |
document |
Numbering restarts per document, sheet or enclosure |
power |
conductor |
Power nets: conductor marks them with their conductor (L1, N, PE), number numbers them like the other nets, none leaves them unmarked |
keep_manual |
true |
A wire with an explicit mark, and a potential with a fixed mark, keep it. Generated numbers skip the values already used |
order |
layout |
Numbering order: layout (order of appearance in the view: sheet, then column, then top to bottom), or document (order of wires[], then of the tree) |
Rules:
- Marking is deterministic: the same document and the same view always produce the same marks.
- Generated marks depend on the document and on the view. Before manufacturing, the marks SHOULD be frozen.
uniwire marks FILE --view ID --writewrites the generated marks intowires[].mark(creatingwires[]entries for implicit power connections when asked). The marking is thenmanualfrom that point on, and later edits do not renumber printed ferrules. - A view never carries topology. Removing
wire_markingchanges the displayed marks, not the meaning of the document.
3.5.2 Exports¶
The reference implementation adds four CSV exports (UTF-8, comma separated, one header line). Column names are
stable English snake_case tokens, so that other tools can read them. Optional localized headers follow
--lang. Display values (-KM1:A1) follow the document's ref fields and are not translated.
Wire list (uniwire wires FILE [--view ID]), one row per wire, implicit power connections included when
--all is given:
wire_id, mark, from, from_display, from_enclosure, to, to_display, to_enclosure, potential, conductor,
section_mm2, color, cable, core, length_m, status
Wire marker list (ferrules / sleeves, uniwire markers FILE), one row per wire end:
mark, wire_id, end (from|to), terminal_display, section_mm2, color, enclosure, quantity
Identical rows are merged and their quantity is summed, so the list can be sent to a marker printer.
Terminal plan (uniwire terminals FILE [--strip X1]), one row per terminal, in mounting order:
strip, terminal, kind, bridge_group, label, potential, mark, inside_targets, inside_sections_mm2,
outside_targets, outside_cable, outside_cores, fuse_A, product
inside_targets lists the cabinet-side ends (-KM1:13; -KM1:14), outside_targets the field-side ends with
their cable and core.
Cable schedule (uniwire cables FILE), one row per cable (from cables[] and inline cables):
cable_id, ref, designation, cores, section_mm2, length_m, from_enclosure, to_enclosure, from, to,
cores_used, cores_spare, status
A PDF form of the terminal plan (one table per strip) belongs to phase 2 (§6).
3.5.3 Display¶
- Multi-line view. When
wire_marksis on, each conductor segment between two ports carries its mark, written along the line next to each port. Strip terminals referenced by power wires are drawn on the conductor as a small terminal symbol with-X1:1. The layout stays automatic. - Single-line view. Unchanged. A
terminal_blocknode with astripMAY show the terminal range (-X1:1…4). - Control view. See §3.6.
3.6 Control schematic view (sketch, not normative)¶
This section is future work. It only shows that the data of §3.1-3.5 is enough to draw a control schematic automatically. The normative definition will be a separate UEP.
A view of kind "control" would draw the control circuits as current paths between two supply potentials:
{"id": "ctl", "kind": "control", "supply": ["P24", "P0V"], "paper": "A3", "columns": 10}
- Rails. The upper supply potential (
P24, or a PLC output) at the top, the lower one (P0V) at the bottom. - Current paths. Each path from the upper rail to the lower rail through two-terminal elements (a contact
13-14, a coilA1-A2, a pilot lightX1-X2, a PLC channel and its common) becomes one column. The order follows the order of the coils in the document, and a view MAY override it with a list of coil ids. Parallel branches (the self-hold contact across the start button) are drawn side by side, joined at the nets they share. Coils sit at the bottom of their path, as is usual. - Columns and sheets. Columns are numbered on each sheet. A position is written
sheet.column(3.4). - Terminals. Strip terminals on a path are drawn where the wire crosses them (
-X1:10). The field devices of an enclosure are framed with itsref(+FS3). - Cross-references. Under each coil, a table lists the contact set of the device (§3.1.5): main poles, own
contacts and the contacts of its auxiliaries, with the position where each contact is used, in NO / NC
columns. Next to each contact, its parent's position is written (
-KM1 / 3.4). PLC channels show the channel label and the position of the module. - Marks. From
wire_marking, as in the multi-line view.
All of these come from ports (functions and pairs), wires, nets, auxiliaries (parent) and terminal strips.
Nothing has to be added to the document.
3.7 Rules¶
New rules in the core profile. They apply only to documents that use the new sections. A document without
wires[], terminal_strips[] or explicit ports gets no new findings, except port.unknown on links that use
ports.
| Rule | Check | Level |
|---|---|---|
port.unknown |
A port reference (wire, link from_port / to_port, potential ports) names no node, no port, no alias and no auxiliary; or uses a generated identifier; or an alias matches two ports |
error |
port.unconnected |
A mandatory port of a node that has at least one wire is not connected (a wired contactor with an unwired coil terminal) |
warning (error for coil) |
port.capacity |
More conductors on a port than its capacity; a PLC channel shared by two wires that are not on the same net |
error |
port.conductor |
A wire's conductor differs from the conductor of a port it lands on; a PE conductor on a port that is not earth; a GNYE colour on a conductor other than PE / PEN (the green-and-yellow combination is reserved for protective conductors by IEC 60445) |
error |
wire.endpoints |
from = to; an end on an auxiliary as a whole (Q1#MX) |
error |
wire.section |
The cross-section is too small for the protective device that supplies the net: the device found by walking up the nets to the first protective pole_out, and its rating (ir_A, fuse_A, in_A, as in iec60364.iz). The data table is a registry file whose source is given in the finding |
warning |
wire.cable |
Unknown cable; a core used twice; more cores used than the composition gives; a core's section different from the cable's; a wire of a cable whose ends are not in the cable's enclosures |
error (warning for enclosures) |
wire.potential |
Two declared potentials in one net; a wire, terminal or potential assertion that disagrees with the derived net; a fixed mark given to two potentials |
error |
wire.mark |
The same mark on wires of different nets (manual or frozen marks); with the potential scheme, two different explicit marks within one net |
error / warning |
wire.tree |
Explicit wiring that contradicts an implicit tree connection: the wires of a tree edge reach a port of another conductor (crossed phases), or do not reach the child at all | warning |
strip.terminal |
Duplicate terminal number in a strip; unknown enclosure |
error |
strip.capacity |
A wire larger than section_max_mm2; more conductors than points on one side |
error |
strip.bridge |
A bridge_group with a single terminal (warning); a bridge between an earth terminal and another kind, or between terminals asserted on different potentials (error) |
warning / error |
strip.earth |
A PE conductor on a terminal that is not earth; an earth terminal on a net that is not PE / PEN |
warning |
aux.parent |
An auxiliary with an unknown parent, a parent that is not a switching, protective or relay device, or an auxiliary placed in the tree instead of devices[] |
error |
Every finding carries the identifiers involved (wire, port, strip, terminal), so that editors and the LLM tools
(describe, patch) can point to it.
3.8 Mappings to standards and data models¶
Claims are kept general where the mapping depends on the profile or on the edition of a standard.
| uniwire | IEC 81346 | IEC 61082 / IEC 60445 | CIM (IEC 61970/61968) | IFC 4.x | IEC 61850 SCL |
|---|---|---|---|---|---|
Port KM1#A1, displayed -KM1:A1 |
Terminal designation: product designation followed by the terminal prefix : |
IEC 60445: alphanumeric identification of equipment terminals (U1, V1, W1, L1, N, PE…). Coil and contact markings follow the conventions of the IEC 60947 series |
Terminal of a ConductingEquipment (sequenceNumber from the port order) |
IfcDistributionPort nested in the element (IfcRelNests), with flow direction and electrical system type |
Terminal of a ConductingEquipment (primary equipment only) |
Terminal strip and terminals X1#3 |
Product -X1, terminals -X1:3 |
IEC 61082: terminal and connection tables | Junction / Connector, or not modelled (secondary wiring is mostly outside CIM's scope) |
No dedicated entity; a terminal-strip element with one port per terminal (see open question 6) | Not modelled |
| Net / potential | - | Conductor identification by potential (IEC 60445 for power conductors) | ConnectivityNode |
Set of ports joined by IfcRelConnectsPorts |
ConnectivityNode (primary) |
| Wire | - | IEC 61082: connection diagrams and tables; IEC 60445: conductor colours and alphanumeric marks | No direct class for panel wiring | IfcCableSegment (conductor type), joined to ports by IfcRelConnectsPorts |
Not modelled |
Cable cables[] |
Product -W12 |
Cable schedules (IEC 61082 documentation rules) | ACLineSegment for power cables in network models |
IfcCableSegment (cable type), carried in IfcCableCarrierSegment |
Not modelled |
Auxiliary with parent |
Sub-product of the parent | - | - | Element nested in the parent (IfcRelNests) |
Logical nodes cover functions, not wiring |
- IEC 81346.
refalready holds the product designation (-KM1). The terminal aspect is appended with:. Location (+FS3) and function (=) prefixes can be put in front for display and exports. - IEC 60445 / IEC 61082. The default port sets (§3.1.3) and the
conductorandcolorvalues follow these identification conventions. The wire list and the terminal plan are tables in the sense of the documentation rules of IEC 61082. - CIM.
uniwire graph(SPEC §8) already produces terminals and connectivity nodes for the tree with aggregated terminals (in,out,in2). With ports it emits oneTerminalper port that carries a conductor, and the power nets of §3.4.2 becomeConnectivityNodes. Control wiring is not exported to CIM. - IFC. Each port becomes an
IfcDistributionPort, each wire or cable anIfcCableSegmentconnected byIfcRelConnectsPorts. The exact predefined types are left to the exporter. - IEC 61850 SCL. Only the primary (power) part maps:
TerminalandConnectivityNodein the substation section. Secondary wiring stays out of SCL.
4. Complete example: a DOL motor starter¶
A conveyor motor -M1 (4 kW) is started direct-on-line by contactor -KM1, protected by motor circuit breaker
-Q1. The 24 V DC control circuit is fed by an output of PLC -A1 (enable). It goes out to a push-button station
+FS3 through terminal strip -X1 and cable W12: stop button -S1 (NC), start button -S2 (NO). The
contactor holds itself in through its auxiliary contact 13-14. An add-on auxiliary block on -KM1 reports
"running" to a PLC input. The motor cable W11 lands on -X1:1…4.
{
"$schema": "https://uniwire.sh/schema/v2/uniwire.schema.json",
"uniwire": "2.0.0",
"meta": {"title": "Conveyor 3: DOL starter with hardwired self-hold", "lang": "en"},
"installation": {"earthing": "TN-S", "system": "3P", "un_V": 400, "f_Hz": 50},
"sources": [
{"id": "IN", "type": "offpage", "label": "From main switchboard", "children": [
{"id": "MCC1", "type": "board", "ref": "MCC-1", "kind": "mcc", "children": [
{"id": "Q1", "type": "breaker", "ref": "-Q1", "label": "Conveyor 3", "in_A": 10, "ir_A": 8.5,
"poles": "3P", "icu_kA": 50, "children": [
{"id": "KM1", "type": "contactor", "ref": "-KM1", "in_A": 9, "poles": "3P", "coil_V": 24,
"contacts": ["NO"], "children": [
{"id": "M1", "type": "motor", "ref": "-M1", "label": "Conveyor 3", "p_kW": 4, "in_A": 8.2,
"phases": 3,
"cable": {"ref": "W11", "designation": "U1000R2V", "cores": "4G", "section_mm2": 2.5,
"length_m": 35, "material": "Cu"}}]}]},
{"id": "Q2", "type": "breaker", "ref": "-Q2", "label": "Control supply", "in_A": 4, "curve": "C",
"poles": "2P", "children": [
{"id": "PS", "type": "power_supply", "ref": "-T1", "u1_V": 400, "u2_V": 24, "in_A": 5, "children": [
{"id": "F2", "type": "breaker", "ref": "-F2", "label": "24 V control", "in_A": 2, "curve": "C",
"poles": "1P"},
{"id": "A1", "type": "plc", "ref": "-A1", "role": "controller", "un_V": 24,
"modules": [
{"slot": 1, "kind": "di", "channels": 8, "un_V": 24, "channel_labels": {"1": "KM1 running"}},
{"slot": 2, "kind": "do", "channels": 8, "un_V": 24, "rating_A": 0.5,
"channel_labels": {"1": "Conveyor 3 enable"}}]}]}]}]}]}
],
"devices": [
{"id": "KM1_B", "type": "auxiliary", "parent": "KM1", "ref": "-KM1", "kind": "aux_contact",
"contacts": ["NO", "NC"], "port_defaults": false,
"ports": [{"id": "53", "function": "contact_no", "pair": "54"},
{"id": "54", "function": "contact_no", "pair": "53"},
{"id": "61", "function": "contact_nc", "pair": "62"},
{"id": "62", "function": "contact_nc", "pair": "61"}]},
{"id": "S1", "type": "push_button", "ref": "-S1", "label": "Stop", "contacts": ["NC"], "color": "RD"},
{"id": "S2", "type": "push_button", "ref": "-S2", "label": "Start", "contacts": ["NO"], "color": "GN"}
],
"enclosures": [
{"id": "FS3", "kind": "box", "ref": "+FS3", "label": "Push-button station, conveyor 3",
"nodes": ["S1", "S2"]}
],
"terminal_strips": [
{"id": "X1", "ref": "-X1", "enclosure": "MCC1", "label": "Conveyor 3 field terminals",
"terminals": [
{"no": "1", "kind": "feed_through", "label": "M1 U1", "section_max_mm2": 4},
{"no": "2", "kind": "feed_through", "label": "M1 V1", "section_max_mm2": 4},
{"no": "3", "kind": "feed_through", "label": "M1 W1", "section_max_mm2": 4},
{"no": "4", "kind": "earth", "label": "M1 PE", "section_max_mm2": 4},
{"no": "10", "kind": "feed_through", "label": "Stop", "section_max_mm2": 2.5},
{"no": "11", "kind": "feed_through", "label": "Start", "section_max_mm2": 2.5},
{"no": "12", "kind": "feed_through", "label": "Self-hold", "section_max_mm2": 2.5},
{"no": "20", "kind": "feed_through", "label": "0 V", "bridge_group": "B0V", "section_max_mm2": 2.5},
{"no": "21", "kind": "feed_through", "label": "0 V", "bridge_group": "B0V", "section_max_mm2": 2.5}
]}
],
"cables": [
{"id": "W12", "ref": "W12", "designation": "control cable, screened", "cores": "4x", "section_mm2": 1.5,
"length_m": 30, "from_enclosure": "MCC1", "to_enclosure": "FS3"}
],
"potentials": [
{"id": "P24", "name": "24V", "kind": "control", "un_V": 24, "dc": true, "mark": "24V", "ports": ["F2#2"]},
{"id": "P0V", "name": "0V", "kind": "control", "un_V": 0, "dc": true, "mark": "0V", "ports": ["PS#L-"]}
],
"wires": [
{"id": "w4", "from": "KM1#2", "to": "X1#1", "conductor": "L1", "section_mm2": 2.5, "color": "BK"},
{"id": "w5", "from": "KM1#4", "to": "X1#2", "conductor": "L2", "section_mm2": 2.5, "color": "BK"},
{"id": "w6", "from": "KM1#6", "to": "X1#3", "conductor": "L3", "section_mm2": 2.5, "color": "BK"},
{"id": "w7", "from": "MCC1#PE", "to": "X1#4", "conductor": "PE", "section_mm2": 2.5, "color": "GNYE"},
{"id": "w8", "from": "X1#1", "to": "M1#U1", "cable": "M1.cable", "core": "BN", "conductor": "L1"},
{"id": "w9", "from": "X1#2", "to": "M1#V1", "cable": "M1.cable", "core": "BK", "conductor": "L2"},
{"id": "w10", "from": "X1#3", "to": "M1#W1", "cable": "M1.cable", "core": "GY", "conductor": "L3"},
{"id": "w11", "from": "X1#4", "to": "M1#PE", "cable": "M1.cable", "core": "GNYE", "conductor": "PE"},
{"id": "w20", "from": "A1#2.1", "to": "X1#10", "mark": "101", "section_mm2": 0.75, "color": "BU"},
{"id": "w21", "from": "X1#10", "to": "S1#11", "mark": "101", "cable": "W12", "core": "1"},
{"id": "w22", "from": "S1#12", "to": "X1#11", "mark": "102", "cable": "W12", "core": "2"},
{"id": "w23", "from": "S1#12", "to": "S2#13", "mark": "102", "section_mm2": 0.75, "color": "BU"},
{"id": "w24", "from": "S2#14", "to": "X1#12", "mark": "103", "cable": "W12", "core": "3"},
{"id": "w25", "from": "X1#11", "to": "KM1#13", "mark": "102", "section_mm2": 0.75, "color": "BU"},
{"id": "w26", "from": "X1#12", "to": "KM1#14", "mark": "103", "section_mm2": 0.75, "color": "BU"},
{"id": "w27", "from": "KM1#14", "to": "KM1#A1", "mark": "103", "section_mm2": 0.75, "color": "BU"},
{"id": "w28", "from": "KM1#A2", "to": "X1#20", "potential": "P0V", "section_mm2": 0.75, "color": "BU"},
{"id": "w29", "from": "PS#L-", "to": "X1#21", "potential": "P0V", "section_mm2": 1.5, "color": "BU"},
{"id": "w30", "from": "F2#2", "to": "KM1_B#53", "potential": "P24", "section_mm2": 0.75, "color": "BU"},
{"id": "w31", "from": "KM1_B#54", "to": "A1#1.1", "mark": "104", "section_mm2": 0.75, "color": "BU"}
],
"links": [
{"kind": "control", "from": "A1", "from_port": "2.1", "to": "KM1", "label": "enable"}
],
"views": [
{"id": "sld", "paper": "A3"},
{"id": "ml", "kind": "multi-line", "paper": "A3",
"wire_marking": {"scheme": "potential", "start": 100, "power": "conductor", "keep_manual": true}}
]
}
What the example shows:
- The single-line data does not change.
sources, thecontrollink and thesldview are 1.x content. The only addition to the tree is the optional fieldcontacts: ["NO"]onKM1, which declares its built-in contact13-14. The single-line diagram rendered from this document is identical to the one rendered from the same document without the new sections. - Ports come from the registry.
Q1#2,KM1#A1,KM1#13,M1#U1,A1#2.1,PS#L-,S1#11andMCC1#PEare defaults. Only the add-on blockKM1_Bdeclares its ports, because its markings depend on the product. - Implicit connections fill the gaps.
Q1 → KM1has no wires: its three connections (Q1#2toKM1#1…) are derived from the tree, and thepotentialscheme marks themL1,L2,L3(power: "conductor"). The edgeKM1 → M1is described by wires through-X1:1…4, which replace the implicit connection. Rulewire.treechecks thatKM1#2still reachesM1#U1. - Inline cable reused. The motor cable stays inline on
M1(1.x form) and its cores are referenced asM1.cable. The control cableW12, which belongs to no tree edge, is declared incables[]. Its core 4 is reported as spare by the cable schedule. - Nets and marks. Net
101= {A1#2.1,X1#10,S1#11}. Net102= {S1#12,S2#13,X1#11,KM1#13}. Net103= {S2#14,X1#12,KM1#14,KM1#A1}. The self-hold contactKM1:13-14lies in parallel withS2:13-14, between nets102and103.P0Vtakes inKM1#A2,X1#20,X1#21(bridgeB0V) andPS#L-, and all its wires get the fixed mark0V. Net104carries the feedback to input1.1. - Terminal plan of
-X1(abridged):
| terminal | kind | bridge | inside | outside |
|---|---|---|---|---|
| 1 | feed_through | -KM1:2 (L1, 2.5 mm²) |
W11 BN → -M1:U1 |
|
| 4 | earth | MCC-1:PE |
W11 GNYE → -M1:PE |
|
| 10 | feed_through | -A1:2.1 (101) |
W12 1 → +FS3-S1:11 |
|
| 11 | feed_through | -KM1:13 (102) |
W12 2 → +FS3-S1:12 |
|
| 12 | feed_through | -KM1:14 (103) |
W12 3 → +FS3-S2:14 |
|
| 20 | feed_through | B0V | -KM1:A2 (0V) |
|
| 21 | feed_through | B0V | -T1:L- (0V) |
- Cross-reference under the coil of
-KM1(control view, §3.6): main poles1-2,3-4,5-6; NO13-14(self-hold, path of the coil); NO53-54(feedback to-A1:1.1); NC61-62(unused). - Rules. The 2 A breaker
-F2protects theP24net andwire.sectionaccepts 0.75 mm².A1#2.1protection is the PLC output itself (plc.coilalready checks the 24 V coil).port.unconnectedwould warn ifKM1#A2were not wired.
5. Compatibility and migration¶
5.1 Everything is additive¶
- Every 1.x document is a valid 2.0 document with the same meaning. None of the new fields is required.
- New top-level sections:
terminal_strips,wires,cables,potentials. New node fields:ports,port_defaults,contacts(contactor and control types),strip(terminal block). New types:auxiliary,push_button,selector_switch,pilot_light,control_relay. New view fields:wire_marking,wire_marks. New view kind:control(reserved until its own UEP). - The only widening of an existing field:
node.cableandlinks[].cableaccept a string (the id of acables[]entry) in addition to the 1.x object. - 1.x readers reject unknown top-level keys (
additionalProperties: false, SPEC §9). A document that uses the new sections therefore declares"uniwire": "2.0.0"and the/v2/schema. A 2.0 document that uses none of them can be written as 1.x by changing the version string.
5.2 from_port / to_port become port references¶
- Current values
slot.channel("2.1") are already valid port ids of the generated PLC ports. Existing documents keep working, and the check that ruleplc.portdid for PLCs is now done byport.unknownfor every type. - Other free strings (
"MX","N") resolve through ports, aliases and auxiliaries (§3.1.5). Unresolvable values produceplc.portonly for PLCs in the current format. In 2.0 they raiseport.unknownas a warning for documents that declareuniwire1.x, and as an error for 2.0 documents.
5.3 terminal_block.terminals → terminal strips¶
uniwire migrate (the migration function required by SPEC §9 for a major version) converts what it can:
"X1.1-X1.12","X1:1-12","1-12": a stripX1(or<block id>when no prefix is given) with terminals1…12of kindfeed_through, and the node getsstrip: "X1". The original text is kept innote.- Lists such as
"X1.1, X1.2, X1.PE": one terminal per entry,PEasearth. - Anything else is left as it is, with an info finding. The field stays valid and is only deprecated.
The function is idempotent and never deletes data.
5.4 Other migrations¶
aux[]names stay valid. They create implicit auxiliaries (§3.1.5).migrate --explicit-auxwrites them out asdevices[]entries.- Inline cables stay valid.
migrate --hoist-cablesmoves them tocables[]and replaces them with their id (optional; useful when wires reference them).
6. Implementation plan¶
Phase 1, 2.0-alpha: model, rules, exports
- Pydantic models:
Port,TerminalStrip,Terminal,Wire,CableObject,Potential, the new node types and fields. Regenerated/v2/schema. Registryportsentries for every existing type. - Port resolution (ids, aliases, auxiliaries, implicit
<id>.cableand<id>.<aux>), net derivation (union-find over implicit connections, wires, strips and bridges) reusing the conductor derivation of the multi-line layout. - Rules of §3.7. CLI exports
wires,markers,terminals,cables(CSV).uniwire marks --write. uniwire migratefor §5.uniwire graphwith one terminal per port.- LLM tools: the reference card,
describe(ports and wires of a node) andpatchoperations for wires and terminals. - Specification updated in English and French. This example added as
examples/and covered by tests.
Phase 2, 2.0-beta: drawings
- Wire marks in the multi-line view. Strip terminals drawn on power conductors.
- Terminal plan as PDF/SVG (one table per strip). Cable schedule sheet.
- Viewer: show the ports and nets of a selected node.
Phase 3, later: control view
- A separate UEP for the
"control"view kind (§3.6): current paths, columns, cross-reference tables, sheet numbering. Then its rendering in the reference implementation.
7. Open questions¶
- Where do marking rules live? This proposal puts
wire_markingin views and relies on freezing (marks --write) for stable ferrules. Should there also be a document-level default, so that exports do not depend on choosing a view? - Should implicit power connections be materialised? Should
normalizewrite them aswires[]entries, or leave them derived, as proposed? - Multi-level terminals: should they be written with numbers such as
"5.1","5.2", or with a separatelevelfield and a reference syntaxX1#5/2? - Port id case and aliases: ids are case-sensitive, as proposed. Should
UvsU1(old and current motor markings) be an alias in the registry, or a profile choice? - Version number: everything is additive. Should this ship as a 1.x minor version (with
cableas a string deferred), rather than wait for 2.0 and the graph-first changes planned there? - IFC representation of terminal strips: is there an entity better suited than a generic element with ports, and should each terminal be an element or a port?
- Data source for
wire.section: panel wiring needs a current-capacity table for small sections in enclosures. Which openly licensed source can the registry cite? - Coil ↔ contact positions in files: should a document be able to store a frozen cross-reference
(
sheet.column) for contacts, the way marks are frozen, so that printed schematics keep their references when the layout changes?
8. References¶
- uniwire specification: SPEC §3 (nodes), §3a (common fields,
devices[],enclosures[],terminal_block), §3b (PLC ports), §7.1 (multi-line view), §8 (derived graph form), §9 (versions). - Contributing: UEP process.
- IEC 81346-1 and -2: structuring principles and reference designations.
- IEC 61082-1: preparation of documents used in electrotechnology.
- IEC 60445: identification of equipment terminals, conductor terminations and conductors.
- IEC 60757: code for designation of colours.
- IEC 60947 series: low-voltage switchgear and controlgear (terminal marking conventions of control devices).
- IEC 61970 / 61968 (CIM):
Terminal,ConnectivityNode. ISO 16739 (IFC):IfcDistributionPort,IfcRelConnectsPorts,IfcCableSegment. IEC 61850-6 (SCL):Terminal,ConnectivityNode.