@huaqiu/dsh-kicad 0.4.6 → 0.4.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/skills/kicad-ipc/scripts/__pycache__/add_footprint_from_board_template.cpython-313.pyc +0 -0
- package/skills/kicad-ipc/scripts/__pycache__/create_copper_zone.cpython-313.pyc +0 -0
- package/skills/kicad-ipc/scripts/__pycache__/create_track.cpython-313.pyc +0 -0
- package/skills/kicad-ipc/scripts/__pycache__/create_via.cpython-313.pyc +0 -0
- package/skills/kicad-ipc/scripts/__pycache__/diagnose_ipc_connection.cpython-313.pyc +0 -0
- package/skills/kicad-ipc/scripts/__pycache__/kipy_common.cpython-313.pyc +0 -0
- package/skills/kicad-ipc/scripts/__pycache__/move_rotate_footprint.cpython-313.pyc +0 -0
- package/skills/kicad-ipc/scripts/__pycache__/refill_zones.cpython-313.pyc +0 -0
- package/skills/kicad-ipc/scripts/__pycache__/remove_selected_items.cpython-313.pyc +0 -0
- package/skills/kicad-ipc/scripts/__pycache__/update_selected_track_width.cpython-313.pyc +0 -0
- package/skills/kicad-ipc/scripts/__pycache__/verify_live_ipc.cpython-313.pyc +0 -0
- package/skills/kicad-ipc/scripts/add_footprint_from_board_template.py +12 -12
- package/skills/kicad-ipc/scripts/create_copper_zone.py +11 -11
- package/skills/kicad-ipc/scripts/create_track.py +12 -12
- package/skills/kicad-ipc/scripts/create_via.py +11 -11
- package/skills/kicad-ipc/scripts/diagnose_ipc_connection.py +10 -10
- package/skills/kicad-ipc/scripts/kipy_common.py +6 -6
- package/skills/kicad-ipc/scripts/move_rotate_footprint.py +11 -11
- package/skills/kicad-ipc/scripts/refill_zones.py +4 -4
- package/skills/kicad-ipc/scripts/remove_selected_items.py +7 -7
- package/skills/kicad-ipc/scripts/update_selected_track_width.py +8 -8
- package/skills/kicad-ipc/scripts/verify_live_ipc.py +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@huaqiu/dsh-kicad",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./lib/index.mjs",
|
|
6
6
|
"types": "./lib/index.d.mts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"@deepseek-ai/dsh-tools": "^0.1.0-rc.0"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@huaqiu/dsh-plugin-log": "0.4.
|
|
25
|
+
"@huaqiu/dsh-plugin-log": "0.4.7"
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
28
|
"lib",
|
package/skills/kicad-ipc/scripts/__pycache__/add_footprint_from_board_template.cpython-313.pyc
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -23,25 +23,25 @@ def get_unique_footprint(board, reference: str):
|
|
|
23
23
|
if footprint.reference_field.text.value == reference
|
|
24
24
|
]
|
|
25
25
|
if len(matches) != 1:
|
|
26
|
-
raise RuntimeError(f"source reference {reference!r}
|
|
26
|
+
raise RuntimeError(f"source reference {reference!r} matched {len(matches)} footprints.")
|
|
27
27
|
return matches[0]
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
def main() -> None:
|
|
31
31
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
32
|
-
parser.add_argument("--source-reference", required=True, help="
|
|
33
|
-
parser.add_argument("--new-reference", required=True, help="
|
|
34
|
-
parser.add_argument("--dx-mm", type=float, required=True, help="
|
|
35
|
-
parser.add_argument("--dy-mm", type=float, required=True, help="
|
|
36
|
-
parser.add_argument("--save", action="store_true", help="
|
|
32
|
+
parser.add_argument("--source-reference", required=True, help="existing reference to use as the full-definition template")
|
|
33
|
+
parser.add_argument("--new-reference", required=True, help="unique reference for the new footprint")
|
|
34
|
+
parser.add_argument("--dx-mm", type=float, required=True, help="X offset relative to the template, in mm")
|
|
35
|
+
parser.add_argument("--dy-mm", type=float, required=True, help="Y offset relative to the template, in mm")
|
|
36
|
+
parser.add_argument("--save", action="store_true", help="save the PCB over IPC after successful validation")
|
|
37
37
|
args = parser.parse_args()
|
|
38
38
|
if args.source_reference == args.new_reference:
|
|
39
|
-
parser.error("--new-reference
|
|
39
|
+
parser.error("--new-reference must differ from --source-reference")
|
|
40
40
|
|
|
41
41
|
kicad, board = connect_board()
|
|
42
42
|
try:
|
|
43
43
|
if any(fp.reference_field.text.value == args.new_reference for fp in board.get_footprints()):
|
|
44
|
-
raise RuntimeError(f"reference {args.new_reference!r}
|
|
44
|
+
raise RuntimeError(f"reference {args.new_reference!r} already exists; no footprint created.")
|
|
45
45
|
|
|
46
46
|
source = get_unique_footprint(board, args.source_reference)
|
|
47
47
|
new_footprint = source.clone()
|
|
@@ -50,9 +50,9 @@ def main() -> None:
|
|
|
50
50
|
|
|
51
51
|
def validate(created):
|
|
52
52
|
if len(created) != 1:
|
|
53
|
-
raise RuntimeError("KiCad
|
|
53
|
+
raise RuntimeError("KiCad did not create exactly one footprint.")
|
|
54
54
|
if created[0].reference_field.text.value != args.new_reference:
|
|
55
|
-
raise RuntimeError("KiCad
|
|
55
|
+
raise RuntimeError("KiCad returned a footprint reference that does not match the request.")
|
|
56
56
|
|
|
57
57
|
created, = commit_or_drop(
|
|
58
58
|
board,
|
|
@@ -60,10 +60,10 @@ def main() -> None:
|
|
|
60
60
|
lambda: board.create_items(new_footprint),
|
|
61
61
|
validate,
|
|
62
62
|
)
|
|
63
|
-
print(f"
|
|
63
|
+
print(f"Created {created.reference_field.text.value}: {created.id}")
|
|
64
64
|
if args.save:
|
|
65
65
|
board.save()
|
|
66
|
-
print("
|
|
66
|
+
print("Saved PCB over IPC.")
|
|
67
67
|
finally:
|
|
68
68
|
close_kicad(kicad)
|
|
69
69
|
|
|
@@ -30,10 +30,10 @@ def polygon(value: str) -> PolygonWithHoles:
|
|
|
30
30
|
x_mm, y_mm = (float(part.strip()) for part in token.split(",", 1))
|
|
31
31
|
points.append((x_mm, y_mm))
|
|
32
32
|
except ValueError as exc:
|
|
33
|
-
raise argparse.ArgumentTypeError("--points
|
|
33
|
+
raise argparse.ArgumentTypeError("--points format should be x,y;x,y;x,y, in mm") from exc
|
|
34
34
|
|
|
35
35
|
if len(points) < 3:
|
|
36
|
-
raise argparse.ArgumentTypeError("
|
|
36
|
+
raise argparse.ArgumentTypeError("copper zone outline needs at least three distinct vertices")
|
|
37
37
|
if points[0] != points[-1]:
|
|
38
38
|
points.append(points[0])
|
|
39
39
|
|
|
@@ -47,10 +47,10 @@ def polygon(value: str) -> PolygonWithHoles:
|
|
|
47
47
|
|
|
48
48
|
def main() -> None:
|
|
49
49
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
50
|
-
parser.add_argument("--net", required=True, help="
|
|
51
|
-
parser.add_argument("--layer", default="F.Cu", help="
|
|
52
|
-
parser.add_argument("--points", type=polygon, required=True, help="
|
|
53
|
-
parser.add_argument("--save", action="store_true", help="
|
|
50
|
+
parser.add_argument("--net", required=True, help="name of an existing PCB net")
|
|
51
|
+
parser.add_argument("--layer", default="F.Cu", help="target copper layer, default F.Cu")
|
|
52
|
+
parser.add_argument("--points", type=polygon, required=True, help="outline vertices x,y;x,y;..., in mm")
|
|
53
|
+
parser.add_argument("--save", action="store_true", help="save the PCB over IPC after successful validation")
|
|
54
54
|
args = parser.parse_args()
|
|
55
55
|
|
|
56
56
|
kicad, board = connect_board()
|
|
@@ -62,9 +62,9 @@ def main() -> None:
|
|
|
62
62
|
|
|
63
63
|
def validate(created):
|
|
64
64
|
if len(created) != 1:
|
|
65
|
-
raise RuntimeError("KiCad
|
|
65
|
+
raise RuntimeError("KiCad did not create exactly one zone.")
|
|
66
66
|
if created[0].net is None or created[0].net.name != args.net:
|
|
67
|
-
raise RuntimeError("KiCad
|
|
67
|
+
raise RuntimeError("KiCad returned a zone net that does not match the request.")
|
|
68
68
|
|
|
69
69
|
created_zone, = commit_or_drop(
|
|
70
70
|
board,
|
|
@@ -72,11 +72,11 @@ def main() -> None:
|
|
|
72
72
|
lambda: board.create_items(zone),
|
|
73
73
|
validate,
|
|
74
74
|
)
|
|
75
|
-
print(f"
|
|
76
|
-
print("
|
|
75
|
+
print(f"Created an unfilled copper zone: {created_zone.id}")
|
|
76
|
+
print("After reviewing the outline, run refill_zones.py to fill the zone.")
|
|
77
77
|
if args.save:
|
|
78
78
|
board.save()
|
|
79
|
-
print("
|
|
79
|
+
print("Saved PCB over IPC.")
|
|
80
80
|
finally:
|
|
81
81
|
close_kicad(kicad)
|
|
82
82
|
|
|
@@ -22,22 +22,22 @@ def point(value: str) -> Vector2:
|
|
|
22
22
|
try:
|
|
23
23
|
x_mm, y_mm = (float(part.strip()) for part in value.split(",", 1))
|
|
24
24
|
except ValueError as exc:
|
|
25
|
-
raise argparse.ArgumentTypeError("
|
|
25
|
+
raise argparse.ArgumentTypeError("coordinates must be x,y (in mm), e.g. 10,20") from exc
|
|
26
26
|
return Vector2.from_xy(from_mm(x_mm), from_mm(y_mm))
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
def main() -> None:
|
|
30
30
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
31
|
-
parser.add_argument("--net", required=True, help="
|
|
32
|
-
parser.add_argument("--start", type=point, required=True, help="
|
|
33
|
-
parser.add_argument("--end", type=point, required=True, help="
|
|
34
|
-
parser.add_argument("--width-mm", type=float, required=True, help="
|
|
35
|
-
parser.add_argument("--layer", default="F.Cu", help="
|
|
36
|
-
parser.add_argument("--save", action="store_true", help="
|
|
31
|
+
parser.add_argument("--net", required=True, help="name of an existing PCB net")
|
|
32
|
+
parser.add_argument("--start", type=point, required=True, help="start point x,y, in mm")
|
|
33
|
+
parser.add_argument("--end", type=point, required=True, help="end point x,y, in mm")
|
|
34
|
+
parser.add_argument("--width-mm", type=float, required=True, help="track width, in mm")
|
|
35
|
+
parser.add_argument("--layer", default="F.Cu", help="target copper layer, default F.Cu")
|
|
36
|
+
parser.add_argument("--save", action="store_true", help="save the PCB over IPC after successful validation")
|
|
37
37
|
args = parser.parse_args()
|
|
38
38
|
|
|
39
39
|
if args.width_mm <= 0:
|
|
40
|
-
parser.error("--width-mm
|
|
40
|
+
parser.error("--width-mm must be greater than 0")
|
|
41
41
|
|
|
42
42
|
kicad, board = connect_board()
|
|
43
43
|
try:
|
|
@@ -50,9 +50,9 @@ def main() -> None:
|
|
|
50
50
|
|
|
51
51
|
def validate(created):
|
|
52
52
|
if len(created) != 1:
|
|
53
|
-
raise RuntimeError("KiCad
|
|
53
|
+
raise RuntimeError("KiCad did not create exactly one track.")
|
|
54
54
|
if created[0].width != track.width or created[0].net.name != args.net:
|
|
55
|
-
raise RuntimeError("KiCad
|
|
55
|
+
raise RuntimeError("KiCad returned a result that does not match the request.")
|
|
56
56
|
|
|
57
57
|
created_track, = commit_or_drop(
|
|
58
58
|
board,
|
|
@@ -61,10 +61,10 @@ def main() -> None:
|
|
|
61
61
|
validate,
|
|
62
62
|
)
|
|
63
63
|
|
|
64
|
-
print(f"
|
|
64
|
+
print(f"Created track: {created_track.id}")
|
|
65
65
|
if args.save:
|
|
66
66
|
board.save()
|
|
67
|
-
print("
|
|
67
|
+
print("Saved PCB over IPC.")
|
|
68
68
|
finally:
|
|
69
69
|
close_kicad(kicad)
|
|
70
70
|
|
|
@@ -14,16 +14,16 @@ from kipy_common import close_kicad, commit_or_drop, connect_board, get_required
|
|
|
14
14
|
|
|
15
15
|
def main() -> None:
|
|
16
16
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
17
|
-
parser.add_argument("--net", required=True, help="
|
|
18
|
-
parser.add_argument("--x-mm", type=float, required=True, help="X
|
|
19
|
-
parser.add_argument("--y-mm", type=float, required=True, help="Y
|
|
20
|
-
parser.add_argument("--diameter-mm", type=float, required=True, help="
|
|
21
|
-
parser.add_argument("--drill-mm", type=float, required=True, help="
|
|
22
|
-
parser.add_argument("--save", action="store_true", help="
|
|
17
|
+
parser.add_argument("--net", required=True, help="name of an existing PCB net")
|
|
18
|
+
parser.add_argument("--x-mm", type=float, required=True, help="X coordinate, in mm")
|
|
19
|
+
parser.add_argument("--y-mm", type=float, required=True, help="Y coordinate, in mm")
|
|
20
|
+
parser.add_argument("--diameter-mm", type=float, required=True, help="outer diameter, in mm")
|
|
21
|
+
parser.add_argument("--drill-mm", type=float, required=True, help="drill diameter, in mm")
|
|
22
|
+
parser.add_argument("--save", action="store_true", help="save the PCB over IPC after successful validation")
|
|
23
23
|
args = parser.parse_args()
|
|
24
24
|
|
|
25
25
|
if args.drill_mm <= 0 or args.diameter_mm <= args.drill_mm:
|
|
26
|
-
parser.error("
|
|
26
|
+
parser.error("must satisfy 0 < --drill-mm < --diameter-mm")
|
|
27
27
|
|
|
28
28
|
kicad, board = connect_board()
|
|
29
29
|
try:
|
|
@@ -35,9 +35,9 @@ def main() -> None:
|
|
|
35
35
|
|
|
36
36
|
def validate(created):
|
|
37
37
|
if len(created) != 1:
|
|
38
|
-
raise RuntimeError("KiCad
|
|
38
|
+
raise RuntimeError("KiCad did not create exactly one via.")
|
|
39
39
|
if created[0].net.name != args.net:
|
|
40
|
-
raise RuntimeError("KiCad
|
|
40
|
+
raise RuntimeError("KiCad returned a result that does not match the request.")
|
|
41
41
|
|
|
42
42
|
created_via, = commit_or_drop(
|
|
43
43
|
board,
|
|
@@ -46,10 +46,10 @@ def main() -> None:
|
|
|
46
46
|
validate,
|
|
47
47
|
)
|
|
48
48
|
|
|
49
|
-
print(f"
|
|
49
|
+
print(f"Created via: {created_via.id}")
|
|
50
50
|
if args.save:
|
|
51
51
|
board.save()
|
|
52
|
-
print("
|
|
52
|
+
print("Saved PCB over IPC.")
|
|
53
53
|
finally:
|
|
54
54
|
close_kicad(kicad)
|
|
55
55
|
|
|
@@ -13,30 +13,30 @@ def main() -> int:
|
|
|
13
13
|
try:
|
|
14
14
|
from kipy import KiCad
|
|
15
15
|
except ModuleNotFoundError:
|
|
16
|
-
print("
|
|
16
|
+
print("kicad-python/kipy not found. Use the KiCad IPC plugin environment or install the matching official package.")
|
|
17
17
|
return 2
|
|
18
18
|
|
|
19
19
|
kicad = None
|
|
20
20
|
try:
|
|
21
21
|
kicad = KiCad(timeout_ms=5000)
|
|
22
22
|
if not kicad.check_version():
|
|
23
|
-
print("
|
|
23
|
+
print("Connected, but kicad-python and the KiCad API version do not match.")
|
|
24
24
|
return 3
|
|
25
25
|
|
|
26
26
|
board = kicad.get_board()
|
|
27
27
|
if board is None:
|
|
28
|
-
print("
|
|
28
|
+
print("Connected to KiCad API, but no .kicad_pcb is open in PCB Editor.")
|
|
29
29
|
return 4
|
|
30
30
|
|
|
31
|
-
print(f"
|
|
32
|
-
print(f"
|
|
31
|
+
print(f"Connected to KiCad {kicad.get_version()}.")
|
|
32
|
+
print(f"Current PCB: {board.name}")
|
|
33
33
|
return 0
|
|
34
34
|
except Exception as exc:
|
|
35
|
-
print(f"
|
|
36
|
-
print("
|
|
37
|
-
print(" 1.
|
|
38
|
-
print(" 2.
|
|
39
|
-
print(" 3.
|
|
35
|
+
print(f"Could not connect to KiCad IPC API: {exc}")
|
|
36
|
+
print("Please confirm:")
|
|
37
|
+
print(" 1. PCB Editor is open (opening the project manager alone is not enough).")
|
|
38
|
+
print(" 2. The API service is enabled in KiCad Preferences -> Plugins, and PCB Editor has been restarted.")
|
|
39
|
+
print(" 3. If running in DSH, the current task has Full Access; without Full Access the KiCad named pipe cannot be accessed.")
|
|
40
40
|
return 1
|
|
41
41
|
finally:
|
|
42
42
|
if kicad is not None:
|
|
@@ -16,12 +16,12 @@ def connect_board(timeout_ms: int = 5000):
|
|
|
16
16
|
|
|
17
17
|
if not kicad.check_version():
|
|
18
18
|
raise RuntimeError(
|
|
19
|
-
"kicad-python
|
|
19
|
+
"kicad-python does not match the connected KiCad's API version; use the matching official package."
|
|
20
20
|
)
|
|
21
21
|
|
|
22
22
|
board = kicad.get_board()
|
|
23
23
|
if board is None:
|
|
24
|
-
raise RuntimeError("
|
|
24
|
+
raise RuntimeError("No PCB is open; please open a .kicad_pcb in PCB Editor first.")
|
|
25
25
|
|
|
26
26
|
return kicad, board
|
|
27
27
|
|
|
@@ -38,7 +38,7 @@ def get_required_net(board, name: str):
|
|
|
38
38
|
for net in board.get_nets():
|
|
39
39
|
if net.name == name:
|
|
40
40
|
return net
|
|
41
|
-
raise ValueError(f"
|
|
41
|
+
raise ValueError(f"Net {name!r} does not exist in the PCB; please sync nets from the schematic first.")
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
def resolve_copper_layer(board, name: str):
|
|
@@ -48,7 +48,7 @@ def resolve_copper_layer(board, name: str):
|
|
|
48
48
|
if layer != BoardLayer.BL_UNDEFINED:
|
|
49
49
|
if layer in board.get_enabled_layers():
|
|
50
50
|
return layer
|
|
51
|
-
raise ValueError(f"
|
|
51
|
+
raise ValueError(f"Layer {name!r} is not enabled in the current PCB.")
|
|
52
52
|
|
|
53
53
|
standard_layers = {
|
|
54
54
|
"F.Cu": BoardLayer.BL_F_Cu,
|
|
@@ -58,11 +58,11 @@ def resolve_copper_layer(board, name: str):
|
|
|
58
58
|
layer = standard_layers[name]
|
|
59
59
|
except KeyError as exc:
|
|
60
60
|
raise ValueError(
|
|
61
|
-
f"
|
|
61
|
+
f"Cannot resolve layer {name!r} in this KiCad version; use F.Cu/B.Cu or upgrade."
|
|
62
62
|
) from exc
|
|
63
63
|
|
|
64
64
|
if hasattr(board, "get_enabled_layers") and layer not in board.get_enabled_layers():
|
|
65
|
-
raise ValueError(f"
|
|
65
|
+
raise ValueError(f"Layer {name!r} is not enabled in the current PCB.")
|
|
66
66
|
return layer
|
|
67
67
|
|
|
68
68
|
|
|
@@ -17,20 +17,20 @@ def get_footprint(board, reference: str):
|
|
|
17
17
|
if footprint.reference_field.text.value == reference
|
|
18
18
|
]
|
|
19
19
|
if len(matches) != 1:
|
|
20
|
-
raise RuntimeError(f"reference {reference!r}
|
|
20
|
+
raise RuntimeError(f"reference {reference!r} matched {len(matches)} footprints; no changes made.")
|
|
21
21
|
return matches[0]
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def main() -> None:
|
|
25
25
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
26
|
-
parser.add_argument("--reference", required=True, help="
|
|
27
|
-
parser.add_argument("--dx-mm", type=float, default=0.0, help="X
|
|
28
|
-
parser.add_argument("--dy-mm", type=float, default=0.0, help="Y
|
|
29
|
-
parser.add_argument("--rotation-deg", type=float, default=0.0, help="
|
|
30
|
-
parser.add_argument("--save", action="store_true", help="
|
|
26
|
+
parser.add_argument("--reference", required=True, help="target footprint reference, e.g. R1")
|
|
27
|
+
parser.add_argument("--dx-mm", type=float, default=0.0, help="X offset, in mm")
|
|
28
|
+
parser.add_argument("--dy-mm", type=float, default=0.0, help="Y offset, in mm")
|
|
29
|
+
parser.add_argument("--rotation-deg", type=float, default=0.0, help="incremental rotation angle, in degrees")
|
|
30
|
+
parser.add_argument("--save", action="store_true", help="save the PCB over IPC after successful validation")
|
|
31
31
|
args = parser.parse_args()
|
|
32
32
|
if args.dx_mm == 0 and args.dy_mm == 0 and args.rotation_deg == 0:
|
|
33
|
-
parser.error("
|
|
33
|
+
parser.error("specify at least one offset or rotation parameter")
|
|
34
34
|
|
|
35
35
|
kicad, board = connect_board()
|
|
36
36
|
try:
|
|
@@ -42,9 +42,9 @@ def main() -> None:
|
|
|
42
42
|
|
|
43
43
|
def validate(updated):
|
|
44
44
|
if len(updated) != 1:
|
|
45
|
-
raise RuntimeError("KiCad
|
|
45
|
+
raise RuntimeError("KiCad did not update exactly one footprint.")
|
|
46
46
|
if updated[0].position == old_position and updated[0].orientation == old_orientation:
|
|
47
|
-
raise RuntimeError("KiCad
|
|
47
|
+
raise RuntimeError("KiCad did not apply the footprint transform.")
|
|
48
48
|
|
|
49
49
|
updated, = commit_or_drop(
|
|
50
50
|
board,
|
|
@@ -52,10 +52,10 @@ def main() -> None:
|
|
|
52
52
|
lambda: board.update_items(footprint),
|
|
53
53
|
validate,
|
|
54
54
|
)
|
|
55
|
-
print(f"
|
|
55
|
+
print(f"Updated {args.reference}: position={updated.position}, orientation={updated.orientation}")
|
|
56
56
|
if args.save:
|
|
57
57
|
board.save()
|
|
58
|
-
print("
|
|
58
|
+
print("Saved PCB over IPC.")
|
|
59
59
|
finally:
|
|
60
60
|
close_kicad(kicad)
|
|
61
61
|
|
|
@@ -10,21 +10,21 @@ from kipy_common import close_kicad, connect_board
|
|
|
10
10
|
|
|
11
11
|
def main() -> None:
|
|
12
12
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
13
|
-
parser.add_argument("--save", action="store_true", help="
|
|
13
|
+
parser.add_argument("--save", action="store_true", help="save the PCB over IPC after filling")
|
|
14
14
|
args = parser.parse_args()
|
|
15
15
|
|
|
16
16
|
kicad, board = connect_board(timeout_ms=30000)
|
|
17
17
|
try:
|
|
18
18
|
zones = list(board.get_zones())
|
|
19
19
|
if not zones:
|
|
20
|
-
print("
|
|
20
|
+
print("The current PCB has no zones; nothing to fill.")
|
|
21
21
|
return
|
|
22
22
|
|
|
23
23
|
board.refill_zones(block=True, max_poll_seconds=120.0)
|
|
24
|
-
print(f"
|
|
24
|
+
print(f"Requested and waited for {len(zones)} zones to finish filling.")
|
|
25
25
|
if args.save:
|
|
26
26
|
board.save()
|
|
27
|
-
print("
|
|
27
|
+
print("Saved PCB over IPC.")
|
|
28
28
|
finally:
|
|
29
29
|
close_kicad(kicad)
|
|
30
30
|
|
|
@@ -10,28 +10,28 @@ from kipy_common import close_kicad, commit_or_drop, connect_board
|
|
|
10
10
|
|
|
11
11
|
def main() -> None:
|
|
12
12
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
13
|
-
parser.add_argument("--yes", action="store_true", help="
|
|
14
|
-
parser.add_argument("--save", action="store_true", help="
|
|
13
|
+
parser.add_argument("--yes", action="store_true", help="confirm deletion of all objects in the current selection")
|
|
14
|
+
parser.add_argument("--save", action="store_true", help="save the PCB over IPC after deletion")
|
|
15
15
|
args = parser.parse_args()
|
|
16
16
|
if not args.yes:
|
|
17
|
-
parser.error("
|
|
17
|
+
parser.error("deletion requires passing --yes explicitly")
|
|
18
18
|
|
|
19
19
|
kicad, board = connect_board()
|
|
20
20
|
try:
|
|
21
21
|
targets = list(board.get_selection())
|
|
22
22
|
if not targets:
|
|
23
|
-
raise RuntimeError("KiCad
|
|
23
|
+
raise RuntimeError("KiCad currently has no selection; no changes made.")
|
|
24
24
|
|
|
25
|
-
print(f"
|
|
25
|
+
print(f"About to delete {len(targets)} objects in the current selection.")
|
|
26
26
|
commit_or_drop(
|
|
27
27
|
board,
|
|
28
28
|
f"Delete {len(targets)} selected items",
|
|
29
29
|
lambda: board.remove_items(targets),
|
|
30
30
|
)
|
|
31
|
-
print("
|
|
31
|
+
print("Deleted objects in the current selection.")
|
|
32
32
|
if args.save:
|
|
33
33
|
board.save()
|
|
34
|
-
print("
|
|
34
|
+
print("Saved PCB over IPC.")
|
|
35
35
|
finally:
|
|
36
36
|
close_kicad(kicad)
|
|
37
37
|
|
|
@@ -13,17 +13,17 @@ from kipy_common import close_kicad, commit_or_drop, connect_board
|
|
|
13
13
|
|
|
14
14
|
def main() -> None:
|
|
15
15
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
16
|
-
parser.add_argument("--width-mm", type=float, required=True, help="
|
|
17
|
-
parser.add_argument("--save", action="store_true", help="
|
|
16
|
+
parser.add_argument("--width-mm", type=float, required=True, help="target track width, in mm")
|
|
17
|
+
parser.add_argument("--save", action="store_true", help="save the PCB over IPC after successful validation")
|
|
18
18
|
args = parser.parse_args()
|
|
19
19
|
if args.width_mm <= 0:
|
|
20
|
-
parser.error("--width-mm
|
|
20
|
+
parser.error("--width-mm must be greater than 0")
|
|
21
21
|
|
|
22
22
|
kicad, board = connect_board()
|
|
23
23
|
try:
|
|
24
24
|
targets = [item for item in board.get_selection() if isinstance(item, (Track, ArcTrack))]
|
|
25
25
|
if not targets:
|
|
26
|
-
raise RuntimeError("
|
|
26
|
+
raise RuntimeError("The current KiCad selection has no straight or arc tracks; no changes made.")
|
|
27
27
|
|
|
28
28
|
requested_width = from_mm(args.width_mm)
|
|
29
29
|
for target in targets:
|
|
@@ -31,9 +31,9 @@ def main() -> None:
|
|
|
31
31
|
|
|
32
32
|
def validate(updated):
|
|
33
33
|
if len(updated) != len(targets):
|
|
34
|
-
raise RuntimeError("KiCad
|
|
34
|
+
raise RuntimeError("KiCad did not update all target tracks.")
|
|
35
35
|
if any(item.width != requested_width for item in updated):
|
|
36
|
-
raise RuntimeError("KiCad
|
|
36
|
+
raise RuntimeError("KiCad did not accept all target widths.")
|
|
37
37
|
|
|
38
38
|
updated = commit_or_drop(
|
|
39
39
|
board,
|
|
@@ -42,10 +42,10 @@ def main() -> None:
|
|
|
42
42
|
validate,
|
|
43
43
|
)
|
|
44
44
|
|
|
45
|
-
print(f"
|
|
45
|
+
print(f"Updated {len(updated)} selected tracks.")
|
|
46
46
|
if args.save:
|
|
47
47
|
board.save()
|
|
48
|
-
print("
|
|
48
|
+
print("Saved PCB over IPC.")
|
|
49
49
|
finally:
|
|
50
50
|
close_kicad(kicad)
|
|
51
51
|
|
|
@@ -23,7 +23,7 @@ def main() -> None:
|
|
|
23
23
|
try:
|
|
24
24
|
nets = {net.name: net for net in board.get_nets()}
|
|
25
25
|
if "GND" not in nets:
|
|
26
|
-
raise RuntimeError("
|
|
26
|
+
raise RuntimeError("The smoke test requires the current board to already have a GND net.")
|
|
27
27
|
source = board.get_footprints()[0]
|
|
28
28
|
before = (len(board.get_tracks()), len(board.get_vias()), len(board.get_zones()), len(board.get_footprints()))
|
|
29
29
|
|
|
@@ -79,7 +79,7 @@ def main() -> None:
|
|
|
79
79
|
|
|
80
80
|
after = (len(board.get_tracks()), len(board.get_vias()), len(board.get_zones()), len(board.get_footprints()))
|
|
81
81
|
if after != before:
|
|
82
|
-
raise RuntimeError(f"drop_commit
|
|
82
|
+
raise RuntimeError(f"object count mismatch after drop_commit: before={before}, after={after}")
|
|
83
83
|
print("IPC live smoke test passed; all temporary changes were dropped and not saved.")
|
|
84
84
|
finally:
|
|
85
85
|
if commit is not None:
|