Squash feature/mate+autogenerate branch

This commit is contained in:
Daniel Rojas 2020-10-22 18:12:36 +02:00
parent a6efd28124
commit 8ea8248721
15 changed files with 512 additions and 134 deletions

View File

@ -22,9 +22,8 @@ connectors:
X4:
<<: *molex_f
pinlabels: [GND, +12V, MISO, MOSI, SCK]
ferrule_crimp:
F:
style: simple
autogenerate: true
type: Crimp ferrule
subtype: 0.25 mm²
color: YE
@ -64,6 +63,6 @@ connections:
- W3: [1-4]
- X4: [1,3-5]
-
- ferrule_crimp
- F.
- W4: [1,2]
- X4: [1,2]

View File

@ -8,13 +8,12 @@ cables:
category: bundle
connectors:
ferrule_crimp:
F:
style: simple
autogenerate: true
type: Crimp ferrule
connections:
-
- ferrule_crimp
- F.
- W1: [1-6]
- ferrule_crimp
- F.

View File

@ -140,7 +140,6 @@ class Connector:
show_name: Optional[bool] = None
show_pincount: Optional[bool] = None
hide_disconnected_pins: bool = False
autogenerate: bool = False
loops: List[List[Pin]] = field(default_factory=list)
ignore_in_bom: bool = False
additional_components: List[AdditionalComponent] = field(default_factory=list)
@ -172,7 +171,8 @@ class Connector:
raise Exception('Pins are not unique')
if self.show_name is None:
self.show_name = not self.autogenerate # hide auto-generated designators by default
# hide designators for simple and for auto-generated connectors by default
self.show_name = (self.style != 'simple' and self.name[0:2] != '__')
if self.show_pincount is None:
self.show_pincount = self.style != 'simple' # hide pincount for simple (1 pin) connectors by default
@ -227,7 +227,7 @@ class Cable:
colors: List[Colors] = field(default_factory=list)
wirelabels: List[Wire] = field(default_factory=list)
color_code: Optional[ColorScheme] = None
show_name: bool = True
show_name: Optional[bool] = None
show_wirecount: bool = True
show_wirenumbers: Optional[bool] = None
ignore_in_bom: bool = False
@ -310,9 +310,11 @@ class Cable:
else:
raise Exception('lists of part data are only supported for bundles')
# by default, show wire numbers for cables, hide for bundles
if self.show_wirenumbers is None:
self.show_wirenumbers = self.category != 'bundle'
if self.show_name is None:
self.show_name = self.name[0:2] != '__' # hide designators for auto-generated cables by default
if not self.show_wirenumbers:
self.show_wirenumbers = self.category != 'bundle' # by default, show wire numbers for cables, hide for bundles
for i, item in enumerate(self.additional_components):
if isinstance(item, dict):
@ -351,3 +353,17 @@ class Connection:
via_port: Wire
to_name: Optional[Designator]
to_port: Optional[PinIndex]
@dataclass
class MatePin:
from_name: Designator
from_port: PinIndex
to_name: Designator
to_port: PinIndex
shape: str
@dataclass
class MateComponent:
from_name: Designator
to_name: Designator
shape: str

View File

@ -9,7 +9,7 @@ from itertools import zip_longest
import re
from wireviz import wv_colors, __version__, APP_NAME, APP_URL
from wireviz.DataClasses import Metadata, Options, Tweak, Connector, Cable
from wireviz.DataClasses import Cable, Connector, MatePin, MateComponent, Metadata, Options, Tweak
from wireviz.wv_colors import get_color_hex, translate_color
from wireviz.wv_gv_html import nested_html_table, \
html_bgcolor_attr, html_bgcolor, html_colorbar, \
@ -19,8 +19,7 @@ from wireviz.wv_bom import pn_info_string, component_table_entry, \
HEADER_PN, HEADER_MPN, HEADER_SPN
from wireviz.wv_html import generate_html_output
from wireviz.wv_helper import awg_equiv, mm2_equiv, tuplelist2tsv, flatten2d, \
open_file_read, open_file_write
open_file_read, open_file_write, is_arrow
@dataclass
class Harness:
@ -31,6 +30,7 @@ class Harness:
def __post_init__(self):
self.connectors = {}
self.cables = {}
self.mates = []
self._bom = [] # Internal Cache for generated bom
self.additional_bom_items = []
@ -40,6 +40,12 @@ class Harness:
def add_cable(self, name: str, *args, **kwargs) -> None:
self.cables[name] = Cable(name, *args, **kwargs)
def add_mate_pin(self, *args, **kwargs) -> None:
self.mates.append(MatePin(*args, **kwargs))
def add_mate_component(self, *args, **kwargs) -> None:
self.mates.append(MateComponent(*args, **kwargs))
def add_bom_item(self, item: dict) -> None:
self.additional_bom_items.append(item)
@ -66,7 +72,12 @@ class Harness:
raise Exception(f'{name}:{pin} not found.')
# check via cable
if via_name in self.cables:
if is_arrow(via_name):
if '-' in via_name:
self.mates[(from_name, from_pin, to_name, to_pin)] = via_name
elif '=' in via_name:
self.mates[(from_name, to_name)] = via_name
elif via_name in self.cables:
cable = self.cables[via_name]
# check if provided name is ambiguous
if via_wire in cable.colors and via_wire in cable.wirelabels:
@ -114,8 +125,17 @@ class Harness:
for connection_color in cable.connections:
if connection_color.from_port is not None: # connect to left
self.connectors[connection_color.from_name].ports_right = True
self.connectors[connection_color.from_name].activate_pin(connection_color.from_port)
if connection_color.to_port is not None: # connect to right
self.connectors[connection_color.to_name].ports_left = True
self.connectors[connection_color.to_name].activate_pin(connection_color.to_port)
for mate in self.mates:
if isinstance(mate, MatePin):
self.connectors[mate.from_name].ports_right = True
self.connectors[mate.from_name].activate_pin(mate.from_port)
self.connectors[mate.to_name].ports_left = True
self.connectors[mate.to_name].activate_pin(mate.to_port)
for connector in self.connectors.values():
@ -409,6 +429,30 @@ class Harness:
typecheck('tweak.append', self.tweak.append, str)
dot.body.append(self.tweak.append)
for mate in self.mates:
if mate.shape[0] == '<' and mate.shape[-1] == '>':
dir = 'both'
elif mate.shape[0] == '<':
dir = 'back'
elif mate.shape[-1] == '>':
dir = 'forward'
else:
dir = 'none'
if isinstance(mate, MatePin):
color = '#000000'
elif isinstance(mate, MateComponent):
color = '#000000:#000000'
else:
raise Exception(f'{mate} is an unknown mate')
dot.attr('edge', color=color, style='dashed', dir=dir)
from_port = f':p{mate.from_port}r' if isinstance(mate, MatePin) and self.connectors[mate.from_name].style != 'simple' else ''
code_from = f'{mate.from_name}{from_port}:e'
to_port = f':p{mate.to_port}l' if isinstance(mate, MatePin) and self.connectors[mate.to_name].style != 'simple' else ''
code_to = f'{mate.to_name}{to_port}:w'
dot.edge(code_from, code_to)
return dot
@property

View File

@ -15,7 +15,7 @@ if __name__ == '__main__':
from wireviz import __version__
from wireviz.DataClasses import Metadata, Options, Tweak
from wireviz.Harness import Harness
from wireviz.wv_helper import expand, open_file_read
from wireviz.wv_helper import expand, get_single_key_and_value, is_arrow, open_file_read
def parse(yaml_input: str, file_out: (str, Path) = None, return_types: (None, str, Tuple[str]) = None) -> Any:
@ -35,20 +35,33 @@ def parse(yaml_input: str, file_out: (str, Path) = None, return_types: (None, st
yaml_data = yaml.safe_load(yaml_input)
# define variables =========================================================
# containers for parsed component data and connection sets
template_connectors = {}
template_cables = {}
connection_sets = []
# actual harness
harness = Harness(
metadata = Metadata(**yaml_data.get('metadata', {})),
options = Options(**yaml_data.get('options', {})),
tweak = Tweak(**yaml_data.get('tweak', {})),
)
# others
designators_and_templates = {} # store mapping of components to their respective template
autogenerated_designators = {} # keep track of auto-generated designators to avoid duplicates
if 'title' not in harness.metadata:
harness.metadata['title'] = Path(file_out).stem
# add items
# parse YAML input file ====================================================
sections = ['connectors', 'cables', 'connections']
types = [dict, dict, list]
for sec, ty in zip(sections, types):
if sec in yaml_data and type(yaml_data[sec]) == ty:
if len(yaml_data[sec]) > 0:
if sec in yaml_data and type(yaml_data[sec]) == ty: # section exists
if len(yaml_data[sec]) > 0: # section has contents
if ty == dict:
for key, attribs in yaml_data[sec].items():
# The Image dataclass might need to open an image file with a relative path.
@ -56,132 +69,191 @@ def parse(yaml_input: str, file_out: (str, Path) = None, return_types: (None, st
if isinstance(image, dict):
image['gv_dir'] = Path(file_out if file_out else '').parent # Inject context
# store component templates only; do not generate instances yet
if sec == 'connectors':
if not attribs.get('autogenerate', False):
harness.add_connector(name=key, **attribs)
template_connectors[key] = attribs
elif sec == 'cables':
harness.add_cable(name=key, **attribs)
else:
pass # section exists but is empty
template_cables[key] = attribs
else: # section exists but is empty
pass
else: # section does not exist, create empty section
if ty == dict:
yaml_data[sec] = {}
elif ty == list:
yaml_data[sec] = []
# add connections
connection_sets = yaml_data['connections']
def check_designators(what, where): # helper function
for i, x in enumerate(what):
if x not in yaml_data[where[i]]:
return False
return True
# go through connection sets, generate and connect components ==============
autogenerated_ids = {}
for connection in yaml_data['connections']:
# find first component (potentially nested inside list or dict)
first_item = connection[0]
if isinstance(first_item, list):
first_item = first_item[0]
elif isinstance(first_item, dict):
first_item = list(first_item.keys())[0]
elif isinstance(first_item, str):
pass
template_separator_char = '.' # TODO: make user-configurable (in case user wants to use `.` as part of their template/component names)
# check which section the first item belongs to
alternating_sections = ['connectors','cables']
for index, section in enumerate(alternating_sections):
if first_item in yaml_data[section]:
expected_index = index
break
def resolve_designator(inp, separator):
if separator in inp: # generate a new instance of an item
if inp.count(separator) > 1:
raise Exception(f'{inp} - Found more than one separator ({separator})')
template, designator = inp.split(separator)
if designator == '':
autogenerated_designators[template] = autogenerated_designators.get(template, 0) + 1
designator = f'__{template}_{autogenerated_designators[template]}'
# check if redefining existing component to different template
if designator in designators_and_templates:
if designators_and_templates[designator] != template:
raise Exception(f'Trying to redefine {designator} from {designators_and_templates[designator]} to {template}')
else:
raise Exception('First item not found anywhere.')
expected_index = 1 - expected_index # flip once since it is flipped back at the *beginning* of every loop
designators_and_templates[designator] = template
else:
template, designator = (inp, inp)
if designator in designators_and_templates:
pass # referencing an exiting connector, no need to add again
else:
designators_and_templates[designator] = template
return (template, designator)
# check that all iterable items (lists and dicts) are the same length
# and that they are alternating between connectors and cables/bundles, starting with either
itemcount = None
for item in connection:
expected_index = 1 - expected_index # make sure items alternate between connectors and cables
expected_section = alternating_sections[expected_index]
if isinstance(item, list):
itemcount_new = len(item)
for subitem in item:
if not subitem in yaml_data[expected_section]:
raise Exception(f'{subitem} is not in {expected_section}')
elif isinstance(item, dict):
if len(item.keys()) != 1:
raise Exception('Dicts may contain only one key here!')
itemcount_new = len(expand(list(item.values())[0]))
subitem = list(item.keys())[0]
if not subitem in yaml_data[expected_section]:
raise Exception(f'{subitem} is not in {expected_section}')
elif isinstance(item, str):
if not item in yaml_data[expected_section]:
raise Exception(f'{item} is not in {expected_section}')
continue
if itemcount is not None and itemcount_new != itemcount:
raise Exception('All lists and dict lists must be the same length!')
itemcount = itemcount_new
if itemcount is None:
raise Exception('No item revealed the number of connections to make!')
# utilities to check for alternating connectors and cables/arrows ==========
# populate connection list
connection_list = []
for i, item in enumerate(connection):
if isinstance(item, str): # one single-pin component was specified
sublist = []
for i in range(1, itemcount + 1):
if yaml_data['connectors'][item].get('autogenerate'):
autogenerated_ids[item] = autogenerated_ids.get(item, 0) + 1
new_id = f'_{item}_{autogenerated_ids[item]}'
harness.add_connector(new_id, **yaml_data['connectors'][item])
sublist.append([new_id, 1])
else:
sublist.append([item, 1])
connection_list.append(sublist)
elif isinstance(item, list): # a list of single-pin components were specified
sublist = []
for subitem in item:
if yaml_data['connectors'][subitem].get('autogenerate'):
autogenerated_ids[subitem] = autogenerated_ids.get(subitem, 0) + 1
new_id = f'_{subitem}_{autogenerated_ids[subitem]}'
harness.add_connector(new_id, **yaml_data['connectors'][subitem])
sublist.append([new_id, 1])
else:
sublist.append([subitem, 1])
connection_list.append(sublist)
elif isinstance(item, dict): # a component with multiple pins was specified
sublist = []
id = list(item.keys())[0]
pins = expand(list(item.values())[0])
for pin in pins:
sublist.append([id, pin])
connection_list.append(sublist)
else:
raise Exception('Unexpected item in connection list')
alternating_types = ['connector','cable/arrow']
expected_type = None
# actually connect components using connection list
for i, item in enumerate(connection_list):
id = item[0][0] # TODO: make more elegant/robust/pythonic
if id in harness.cables:
for j, con in enumerate(item):
if i == 0: # list started with a cable, no connector to join on left side
from_name = None
from_pin = None
def check_type(designator, template, actual_type):
nonlocal expected_type
if not expected_type: # each connection set may start with either section
expected_type = actual_type
if actual_type != expected_type: # did not alternate
raise Exception(f'Expected {expected_type}, but "{designator}" ("{template}") is {actual_type}')
def alternate_type(): # flip between connector and cable/arrow
nonlocal expected_type
expected_type = alternating_types[1 - alternating_types.index(expected_type)]
for connection_set in connection_sets:
# figure out number of parallel connections within this set
connectioncount = []
for entry in connection_set:
if isinstance(entry, list):
connectioncount.append(len(entry))
elif isinstance(entry, dict):
connectioncount.append(len(expand(list(entry.values())[0]))) # - X1: [1-4,6] yields 5
else:
from_name = connection_list[i-1][j][0]
from_pin = connection_list[i-1][j][1]
via_name = item[j][0]
via_pin = item[j][1]
if i == len(connection_list) - 1: # list ends with a cable, no connector to join on right side
to_name = None
to_pin = None
pass # strings do not reveal connectioncount
if not any(connectioncount):
raise Exception('No item in connection set revealed number of connections')
# TODO: The following should be a valid connection set,
# even though no item reveals the connection count;
# the count is not needed because only a component-level mate happens.
# -
# - CONNECTOR
# - ==>
# - CONNECTOR
# check that all entries are the same length
if len(set(connectioncount)) > 1:
raise Exception('All items in connection set must reference the same number of connections')
# all entries are the same length, connection count is set
connectioncount = connectioncount[0]
# expand string entries to list entries of correct length
for index, entry in enumerate(connection_set):
if isinstance(entry, str):
connection_set[index] = [entry] * connectioncount
# resolve all designators
for index, entry in enumerate(connection_set):
if isinstance(entry, list):
for subindex, item in enumerate(entry):
template, designator = resolve_designator(item, template_separator_char)
connection_set[index][subindex] = designator
elif isinstance(entry, dict):
key = list(entry.keys())[0]
template, designator = resolve_designator(key, template_separator_char)
value = entry[key]
connection_set[index] = {designator: value}
else:
to_name = connection_list[i+1][j][0]
to_pin = connection_list[i+1][j][1]
pass # string entries have been expanded in previous step
# expand all pin lists
for index, entry in enumerate(connection_set):
if isinstance(entry, list):
connection_set[index] = [{designator: 1} for designator in entry]
elif isinstance(entry, dict):
designator = list(entry.keys())[0]
pinlist = expand(entry[designator])
connection_set[index] = [{designator: pin} for pin in pinlist]
else:
pass # string entries have been expanded in previous step
# Populate wiring harness ==============================================
expected_type = None # reset check for alternating types
# at the beginning of every connection set
# since each set may begin with either type
# generate components
for entry in connection_set:
for item in entry:
designator = list(item.keys())[0]
template = designators_and_templates[designator]
if designator in harness.connectors: # existing connector instance
check_type(designator, template, 'connector')
elif template in template_connectors.keys(): # generate new connector instance from template
check_type(designator, template, 'connector')
harness.add_connector(name = designator, **template_connectors[template])
elif designator in harness.cables: # existing cable instance
check_type(designator, template, 'cable/arrow')
elif template in template_cables.keys(): # generate new cable instance from template
check_type(designator, template, 'cable/arrow')
harness.add_cable(name = designator, **template_cables[template])
elif is_arrow(designator):
check_type(designator, template, 'cable/arrow')
# arrows do not need to be generated here
else:
raise Exception(f'{template} is an unknown template/designator/arrow.')
alternate_type() # entries in connection set must alternate between connectors and cables/arrows
# transpose connection set list
# before: one item per component, one subitem per connection in set
# after: one item per connection in set, one subitem per component
connection_set = list(map(list, zip(*connection_set)))
# connect components
for index_entry, entry in enumerate(connection_set):
for index_item, item in enumerate(entry):
designator = list(item.keys())[0]
if designator in harness.cables:
if index_item == 0: # list started with a cable, no connector to join on left side
from_name, from_pin = (None, None)
else:
from_name, from_pin = get_single_key_and_value(connection_set[index_entry][index_item-1])
via_name, via_pin = (designator, item[designator])
if index_item == len(entry) - 1: # list ends with a cable, no connector to join on right side
to_name, to_pin = (None, None)
else:
to_name, to_pin = get_single_key_and_value(connection_set[index_entry][index_item+1])
harness.connect(from_name, from_pin, via_name, via_pin, to_name, to_pin)
elif is_arrow(designator):
if index_item == 0: # list starts with an arrow
raise Exception('An arrow cannot be at the start of a connection set')
elif index_item == len(entry) - 1: # list ends with an arrow
raise Exception('An arrow cannot be at the end of a connection set')
from_name, from_pin = get_single_key_and_value(connection_set[index_entry][index_item-1])
via_name, via_pin = (designator, None)
to_name, to_pin = get_single_key_and_value(connection_set[index_entry][index_item+1])
if '-' in designator: # mate pin by pin
harness.add_mate_pin(from_name, from_pin, to_name, to_pin, designator)
elif '=' in designator and index_entry == 0: # mate two connectors as a whole
harness.add_mate_component(from_name, to_name, designator)
# harness population completed =============================================
if "additional_bom_items" in yaml_data:
for line in yaml_data["additional_bom_items"]:
harness.add_bom_item(line)

View File

@ -65,6 +65,12 @@ def expand(yaml_data):
return output
def get_single_key_and_value(d: dict):
k = list(d.keys())[0]
v = d[k]
return (k, v)
def int2tuple(inp):
if isinstance(inp, tuple):
output = inp
@ -105,6 +111,18 @@ def open_file_write(filename):
def open_file_append(filename):
return open(filename, 'a', encoding='UTF-8')
def is_arrow(inp):
"""
Matches strings of one or multiple `-` or `=` (but not mixed)
optionally starting with `<` and/or ending with `>`.
Examples:
<-, --, ->, <->
<==, ==, ==>, <=>
"""
# regex by @shiraneyo
return bool(re.match(r"^\s*(?P<leftHead><?)(?P<body>-+|=+)(?P<rightHead>>?)\s*$", inp))
def aspect_ratio(image_src):
try:
from PIL import Image

5
test/.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
*.bom.tsv
*.gv
*.html
*.png
*.svg

25
test/test1.yml Normal file
View File

@ -0,0 +1,25 @@
# based on @stmaxed's example in #134
connectors:
X1: &X
type: Screw connector
subtype: male
color: GN
pincount: 4
pinlabels: [A, B, C, D]
F:
style: simple
type: Ferrule
color: GY
cables:
W:
color: BK
colors: [BK, WH, BU, BN]
connections:
- # ferrules + connector X1
- W.W1: [1-4]
- F.
- -->
- X1: [1-4]

25
test/test2.yml Normal file
View File

@ -0,0 +1,25 @@
# based on @MSBGit's example in #134
connectors:
X1: &dupont
type: Dupont 2.54mm
subtype: male
pincount: 5
color: BK
X2:
<<: *dupont
subtype: female
cables:
W:
category: bundle
colors: [RD, BK, BU, GN]
length: 0.2
connections:
-
- W.W1: [1-4]
- X1: [1-4]
- ==>
- X2: [1-4]
- W.W2: [1-4]

33
test/test3.yml Normal file
View File

@ -0,0 +1,33 @@
# expanding upon @stmaxed's example in #134
connectors:
X1: &X
type: Screw connector
subtype: male
color: GN
pincount: 4
pinlabels: [A, B, C, D]
X2:
<<: *X
subtype: female
F:
style: simple
type: Ferrule
color: GY
cables:
W:
color: BK
colors: [BK, WH, BU, BN]
connections:
- # ferrules + connector X1
- W.W1: [1-4]
- F.
- -->
- X1: [1-4]
- ==>
- X2: [1-4]
- <--
- F.
- W.W2: [1-4]

26
test/test4.yml Normal file
View File

@ -0,0 +1,26 @@
# based on @formatc1702's example in #184
connectors:
X:
pincount: 4
pinlabels: [A, B, C, D]
F:
style: simple
type: ferrule
cables:
C:
wirecount: 4
color_code: DIN
connections:
-
- X.X1: [1-4]
- C.C1: [1-4]
- [F.F1, F.F2, F.F3, F.F4] # generate new instances of F and assign designators
- C.C2: [1-4]
- X.X2: [1-4]
-
- [F1, F2, F3, F4] # use previously assigned designators
- C.C3: [1-4]
- X.X3: [1-4]

64
test/test5.yml Normal file
View File

@ -0,0 +1,64 @@
connectors:
XS:
type: Screw terminal connector
subtype: male
color: GN
pincount: 3
XM:
type: Molex KK 254
subtype: female
pincount: 3
F:
style: simple
type: Ferrule
subtype: 0.25 mm2
color: LB
LED_RD: &LED
type: LED
subtype: 5mm
show_pincount: false
color: RD
pins: [+, -]
pinlabels: [Anode, Cathode]
LED_GN:
<<: *LED
color: GN
LED_YE:
<<: *LED
color: YE
cables:
C:
category: bundle
# show_name: false
colors: [RD, BK]
gauge: 0.25 mm2
W:
category: bundle
# show_name: false
colors: [BN]
gauge: 0.25 mm2
connections:
-
- [F.F1, F.F2]
- C.W1: [1,2]
- LED_RD: [+,-]
-
- F.F3
- W.W2: [1]
- LED_GN: [+]
-
- LED_GN: [-]
- W.W3: [1]
-
- XS.X1: [1-3]
- <--
- [F1, F2, F3]
-
- LED_YE: [+,-]
- C.W4: [1,2]
- XM.X2: [1,2]
-
- W3: [1]
- X2: [3]

55
test/test9.yml Normal file
View File

@ -0,0 +1,55 @@
connectors:
JSTMALE: &JST_SM # use generic names here, assign designators at generation time
type: JST SM
subtype: male
pincount: 4
pinlabels: [A, B, C, D]
JSTFEMALE:
<<: *JST_SM # easily create JSTMALE's matching connector
subtype: female
X4: # this connector is only used once, use fixed designator here already
type: Screw terminal connector
pincount: 4
color: GN
pinlabels: [W, X, Y, Z]
S:
style: simple
type: Splice
color: CU
F:
style: simple
type: Ferrule
color: GY
cables:
CABLE:
wirecount: 4
color_code: DIN
length: 0.1
WIRE:
wirecount: 1
colors: [BK]
length: 0.1
connections:
-
- JSTMALE.X1: [4-1] # use `.` syntax to generate a new instance of JSTMALE, named X1
- CABLE.W1: [1-4] # same syntax for cables
- [S., S., S.S1, S.] # splice W1 and W2 together; only wire #3 needs a user-defined designator
- CABLE.W2: [1-4]
- S. # test shorthand, auto-get required number of ferrules from context
- CABLE.W21: [1-4]
- JSTFEMALE.X2: [1-4]
- <=> # mate X2 and X3
- JSTMALE.X3: [1-4]
- CABLE.W3: [1-4]
- [F., F., F., F.]
- --> # insert ferrules into screw terminal connector
- X4: [2,1,4,3] # X4 does not require auto-generation, thus no `.` syntax here
-
- S1: [1] # reuse previously generated splice
# TODO: Make it work with `- F1` only, making pin 1 is implied
- WIRE.: [1] # We don't care about a simple wire's designator, auto-generate please!
# TODO: Make it work with `- W.W4: 1`, dropping the need for `[]`
- X2: [4]

View File

@ -5,7 +5,6 @@ connectors:
subtype: female
F1:
style: simple
autogenerate: true
type: Crimp ferrule
subtype: 0.5 mm²
color: OG # optional color
@ -19,6 +18,6 @@ cables:
connections:
-
- F1 # a new ferrule is auto-generated for each of the four wires
- F1. # a new ferrule is auto-generated for each of the four wires
- W1: [1-4]
- X1: [1-4]

View File

@ -5,13 +5,11 @@ connectors:
subtype: female
F_10: # this is a unique ferrule
style: simple
show_name: false # non-autogenerated connectors show their name by default; override
type: Crimp ferrule
subtype: 1.0 mm²
color: YE # optional color
F_05: # this is a ferrule that will be auto-generated on demand
style: simple
autogenerate: true
type: Crimp ferrule
subtype: 0.5 mm²
color: OG
@ -25,6 +23,6 @@ cables:
connections:
-
- [F_05, F_10, F_10, F_05]
- [F_05., F_10.F1, F_10.F1, F_05.]
- W1: [1-4]
- X1: [1-4]