skill / adom-schematics
!

Not installable via adompkg

This skill has no published release. adompkg install kyle/adom-schematics will not work until a maintainer publishes a tarball with install.sh and uninstall.sh.

See the publishing docs for the package.json schema and tarball layout required to ship this skill.


name: schematic-crud
description: Edit schematic JSON files in the Hydrogen project. Use when creating, parsing, or modifying schematic JSON: structure, MoleculeSymbol, Wire, NetLabel, symbolSource, pinOverrides, connectionData, or when the user asks how the schematic JSON format works.

Schematic JSON

How the schematic file is structured and how to edit it. All edits are to the raw JSON; the app handles loading and resolving.

Root structure

{
  "title": "Schematic",
  "version": "2.0",
  "pages": [
    { "name": "Page 1", "components": [ /* component objects */ ] }
  ],
  "componentCount": 123
}
  • title — Use "Schematic" for consistency with the app (optional; other titles load but this is the default).
  • version"2.0" for the current format.
  • Legacy: Root may have "components": [ ... ] instead of pages (single page). When editing, prefer normalizing to pages with one entry.

Every component in pages[i].components must have:

  • __name__ — type: "MoleculeSymbol" | "Wire" | "NetLabel" | "GND" | "PowerRail" | etc.
  • id — string (e.g. UUID). Must be unique. Wires and NetLabels reference other components by this.

MoleculeSymbol

Two valid shapes. Use one or the other.

Minimal (symbol from library)

Use when the symbol is identified by owner/molecule name; pin layout is not stored.

{
  "__name__": "MoleculeSymbol",
  "id": "uuid",
  "enabled": true,
  "locked": false,
  "position": [x, y],
  "name": "Display name",
  "referenceDesignator": "U1",
  "symbolSource": {
    "owner": "string",
    "moleculeName": "string",
    "version": "v1"
  },
  "pinOverrides": {
    "left:0": "net_1",
    "right:3": "net_2"
  }
}
  • symbolSource — Identifies which symbol to load. Required in this format.
  • pinOverrides — Optional. Map side:index → net id or net name (e.g. "left:0": "net_gnd" or "right:3": "wire-uuid"). Values can be a net name (string like "net_gnd", "VCC") or a wire id (UUID of a Wire component). Use side:index when a symbol has duplicate pin names (e.g. many GNDs). Legacy files may use pin name as key; on load only the first pin per name is applied.
  • referenceDesignator — e.g. "U1", "U2". Stable; wires/labels can reference the symbol by this.
  • symbolSourceowner, moleculeName, and version must match exactly what exists in Curium; if the symbol file is missing, the symbol loads as a red box with no pins and pinOverrides are not applied.

Full (embedded pins)

Use when the symbol was file-dropped or for legacy files. No symbolSource; full pin data is stored.

{
  "__name__": "MoleculeSymbol",
  "id": "uuid",
  "enabled": true,
  "locked": false,
  "position": [x, y],
  "name": "Display name",
  "referenceDesignator": "U1",
  "numPins": 20,
  "leftPins": [
    { "name": "GND", "uid": "pin_xxx", "index": 0, "side": "left", "description": "", "holeType": "medium", "netID": "net_1" }
  ],
  "topPins": [],
  "rightPins": [],
  "bottomPins": [],
  "groups": [ { "name": "...", "side": "left", "pins": ["uid1", "uid2"] } ],
  "jumpers": [],
  "cornerPins": [ { "type": 0, "pinUid": "uid" } ]
}
  • leftPins / topPins / rightPins / bottomPins — Arrays of pin objects. Each pin: name, uid, index, side, description, holeType, netID (optional).
  • groups / jumpersname, side, pins (array of pin uids).
  • cornerPinstype (e.g. 0–3 for FL/FR/BL/BR), pinUid.

When editing full format, keep uid values consistent: wires and net labels reference pins by uid in this file. When editing minimal format, pinOverrides keys are side:index (e.g. left:0); wires still reference pins by pinName in connectionData.


Wire

Connects two endpoints (components + pins) and stores a path. Wires attach to pins via connectionData: the app uses it to snap the wire to the pin, draw the connection, and set the pin’s net (filled dot). You must add Wire components for visible segments; pinOverrides and NetLabels alone do not create wires.

Attaching a wire to a pin: Set connectionData.startPin and connectionData.endPin with componentId (or referenceDesignator) and pinName. pinName must match the symbol’s pin name exactly (e.g. "VCC", "GND", "VOUT", "DOUT", "SDA")—use names from the molecule’s symbol in Curium; wrong names will not attach. Use pinIndex (0-based among pins with that name) when the symbol has duplicate pin names (e.g. several "GND"). uniqueId can be omitted; the app resolves by pinName on load. pinOverrides on MoleculeSymbol can be omitted when every connection is made by a Wire; the app sets each pin’s net from the wire on load.

{
  "__name__": "Wire",
  "id": "uuid",
  "enabled": true,
  "locked": false,
  "position": [0, 0],
  "x1": 100, "y1": 200, "x2": 300, "y2": 200,
  "color": "#ffffff",
  "lineWidth": 0.5,
  "segments": [ { "x": 100, "y": 200 }, { "x": 200, "y": 200 }, { "x": 300, "y": 200 } ],
  "bendDirection": "horizontal-first",
  "netName": "net_1",
  "connectionData": {
    "startPin": {
      "componentId": "uuid-of-MoleculeSymbol",
      "referenceDesignator": "U1",
      "pinName": "MC16",
      "pinIndex": 0,
      "uniqueId": "pin_xxx"
    },
    "endPin": {
      "componentId": "uuid-of-other-symbol",
      "referenceDesignator": "U2",
      "pinName": "HSDO",
      "pinIndex": 0,
      "uniqueId": "pin_yyy"
    }
  }
}
  • connectionData — Required for the wire to attach to pins. startPin and endPin each have:
    • componentIdid of the component (e.g. MoleculeSymbol). Must match an existing component in the same file.
    • referenceDesignator — Optional but stable (e.g. "U1"). Use for readability and as fallback when componentId is missing.
    • pinName — Must match the symbol pin name exactly (wrong names prevent attachment).
    • pinIndex — Optional; use when the symbol has duplicate pin names (e.g. several GND).
    • uniqueId — Optional; app resolves by pinName on load. When editing JSON, you can leave it or set it from the symbol’s pin list in full format.
  • segments — Array of { x, y }. The drawn path. x1,y1 and x2,y2 usually match first and last segment (or endpoints).
  • netName — Net this wire belongs to (for netlist/highlight).

Pin names: Wire connectionData.pinName must match the symbol pin list exactly (e.g. from Curium). Mismatched names prevent attachment; pins then stay unconnected (hollow). pinOverrides on MoleculeSymbol can be omitted when every connection is made by a Wire; the app sets pin nets from wires on load.

Editing wires: Use pinName from the symbol actual pin list (e.g. Control Panel: VCC, GND, LED_DATA, SERVO_OUT, US_TRIG, US_ECHO, I2C_SDA, I2C_SCL). uniqueId can be wrong after a symbol is re-loaded from symbolSource; the app resolves by pinName. When adding a new wire, copy componentId from the target MoleculeSymbol and pinName from that symbol’s pin list.


NetLabel

Labels a net. Either attached to a pin or to a wire.

{
  "__name__": "NetLabel",
  "id": "uuid",
  "enabled": true,
  "locked": false,
  "position": [x, y],
  "netName": "net_1",
  "labelId": 1,
  "color": "#ff0000",
  "showBorder": true,
  "direction": "right",
  "attachedWireId": null,
  "wireAttachmentPoint": 0.5,
  "attachedMoleculeId": "uuid-of-MoleculeSymbol",
  "attachedPinId": "pin_xxx",
  "attachedPinName": "MC16",
  "stubWireEndpoint": { "x": 120, "y": 200 },
  "pinOffset": { "x": 20, "y": 0 }
}

Pin attachment (label on a component pin):

  • attachedMoleculeId — Component id.
  • attachedPinId — Pin uid (in full-format symbols). Can become stale after load; app resolves by attachedPinName.
  • attachedPinName — Pin name. Stable; always set this when editing so the label still works after load.
  • pinOffset{ x, y } offset from pin position to label position (keeps label in place when symbol moves).
  • stubWireEndpoint — Pin position (or same as pin); can be { x, y }.
  • attachedWireId — null.

Wire attachment (label on a wire):

  • attachedWireId — Wire id.
  • wireAttachmentPoint — 0–1, position along wire.
  • stubWireEndpoint — Point on wire.
  • attachedMoleculeId / attachedPinId / attachedPinName — null.

Editing net labels: When attaching to a pin, set attachedMoleculeId, attachedPinName, and pinOffset; attachedPinId is optional (app can resolve by name). When renaming nets, update netName and any pinOverrides or wire netName that share that net.


Editing rules

  1. IDs — Every component has a unique id. Wires use connectionData.startPin/endPin.componentId; net labels use attachedMoleculeId or attachedWireId. Do not reuse ids; do not remove a component and leave wires/labels pointing at its id without updating or removing them.
  2. Stable identifiers — Prefer referenceDesignator (e.g. "U1") and pinName when editing. uniqueId and componentId can change after load for symbols that use symbolSource; the app matches by refDes and pin name.
  3. MoleculeSymbol — Use minimal (symbolSource + pinOverrides) when the symbol is from the library; use full only when the symbol has no symbolSource (e.g. file-dropped). Do not mix: either symbolSource is present (and no leftPins/topPins/…) or it is absent (and full pin arrays are present).
  4. Consistency — After moving a symbol, position and pinOffset on attached net labels determine where the label sits; wire segments and x1,y1,x2,y2 can be updated to match new endpoints, or leave for the app to recompute on load.
  5. Rename net — Update netName on every Wire and NetLabel on that net, and every pinOverrides entry whose value is that net id.
  6. Delete — Remove the component from pages[i].components. Remove or fix any Wire whose connectionData references that component, and any NetLabel whose attachedMoleculeId (or attachedWireId) references it.
  7. Default Control Panel — Leave the Control Panel in its default position and locked. The app adds it as a MoleculeSymbol (U1, adom/Control Panel/v1) at position [-70, 500] and locked: true. When editing or generating JSON, keep that symbol at "position": [-70, 500] and "locked": true so it matches the default and stays in place.

If pins look unconnected or everything looks “floating” after load: (1) pinOverrides are applied only after the symbol loads from Curium—symbolSource (owner, moleculeName, version) must match exactly; wrong or missing molecules load as a red box with no pins. (2) Wire components are required for visible wire segments; without them you only have symbols and labels, so there are no lines between components. (3) Use root title "Schematic" and version "2.0" for consistency.


Quick reference

Item Required / stable for editing
Any component name, id
MoleculeSymbol (minimal) symbolSource, position, referenceDesignator, pinOverrides (side:index → net id)
MoleculeSymbol (full) position, referenceDesignator, leftPins/etc., pin uid and name
Wire connectionData.startPin/endPin: componentId, pinName; segments; netName
NetLabel (on pin) attachedMoleculeId, attachedPinName, pinOffset, netName
NetLabel (on wire) attachedWireId, wireAttachmentPoint, netName