Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 154 additions & 7 deletions libraries/boards/r2uppityspinner-alt.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "droidnet-command-library/library/v1",
"generatedFrom": "R2UppitySpinnerV3 ALT fw 3.5.3 (highfalutintodd fork of Mimir Reynisson's original)",
"generatedFrom": "Uppity Spinner ALT v4.0.0-beta.1 (the clean-sheet rewrite, highfalutintodd/R2UppitySpinner_ALT); based on the community v3.5.3 entry",
"enums": {
"uppity.lightMode": {
"label": "Light Kit Mode",
Expand Down Expand Up @@ -128,6 +128,47 @@
"label": "Normally Open"
}
]
},
"uppity.randomLight": {
"label": "Light Kit in Random Mode",
"values": [
{
"code": "0",
"label": "Leave alone"
},
{
"code": "1",
"label": "Off"
},
{
"code": "2",
"label": "Obi-Wan (blue)"
},
{
"code": "3",
"label": "Yoda (green fade)"
},
{
"code": "4",
"label": "Sith (red flash)"
},
{
"code": "5",
"label": "Search Light (white)"
},
{
"code": "6",
"label": "Dagobah (screen-accurate)"
},
{
"code": "7",
"label": "Sparkle"
},
{
"code": "8",
"label": "A new mode each action"
}
]
}
},
"components": [
Expand All @@ -136,13 +177,14 @@
"name": "R2 Uppity Spinner ALT (Periscope)",
"kind": "device-native",
"confidence": "community",
"firmware": "v3.5.3",
"firmware": "v4.0.0-beta.1",
"routing": {
"class": "broadcast",
"nativeWrapper": "none",
"durationSuffix": {
"supported": false
}
},
"notes": "Every v3 :P/#P command keeps its syntax, so this entry also drives boards on v3.5.3 and later; the commands marked (v4) are new in 4.0, and RC mode is v3 only. v4: the same :P/#P grammar on the command serial (Marcduino bus), the USB console and, when the builder turns it on, the WCB mesh as its own client device (off by default). :PX, ?STOP and &ESTOP latch an E-STOP that only #PRESUME, the board's web page or &ESTOP,RESET releases. With the mesh on it sends &PERI,HB/POS/STATE/FAULT telemetry. Settings, unlocking and rescue commands are refused from the mesh; the bus refuses the rescue override."
},
"commands": [
{
Expand Down Expand Up @@ -238,7 +280,7 @@
},
{
"id": "uppity.lifter.home",
"name": "Return Home",
"name": "Lower Safely (home the head first if needed)",
"safety": "movement",
"encoder": "template",
"template": ":PH",
Expand Down Expand Up @@ -274,7 +316,7 @@
},
{
"id": "uppity.estop",
"name": "Emergency Stop",
"name": "Emergency Stop (on v4 it latches until released)",
"safety": "power",
"encoder": "template",
"template": ":PX",
Expand Down Expand Up @@ -865,7 +907,7 @@
},
{
"id": "uppity.cfg.rc",
"name": "RC (PPM) Mode",
"name": "RC (PPM) Mode (v3 only)",
"safety": "config",
"encoder": "template",
"template": "#PRC{state}",
Expand All @@ -881,7 +923,7 @@
"#PRC0",
"#PRC1"
],
"commentLabel": "Uppity RC mode",
"commentLabel": "Uppity RC mode (v3 only; v4 has no RC input and ignores it)",
"category": "Setup"
},
{
Expand Down Expand Up @@ -961,6 +1003,111 @@
],
"commentLabel": "Uppity rotary limit",
"category": "Setup"
},
{
"id": "uppity.cfg.resume",
"name": "Release E-STOP (v4)",
"category": "Power",
"safety": "power",
"encoder": "template",
"template": "#PRESUME",
"params": [],
"examples": [
"#PRESUME"
],
"commentLabel": "Uppity release E-STOP"
},
{
"id": "uppity.cfg.state",
"name": "Report State (v4)",
"category": "Config",
"safety": "cosmetic",
"encoder": "template",
"template": "#PSTATE",
"params": [],
"examples": [
"#PSTATE"
],
"commentLabel": "Uppity state"
},
{
"id": "uppity.cfg.clearFault",
"name": "Clear Fault (v4)",
"category": "Power",
"safety": "config",
"encoder": "template",
"template": "#PCLEARFAULT",
"params": [],
"examples": [
"#PCLEARFAULT"
],
"commentLabel": "Uppity clear fault"
},
{
"id": "uppity.cfg.rotaryTest",
"name": "Rotary Test (v4: measure ticks per turn, then home)",
"category": "Setup",
"safety": "movement",
"encoder": "template",
"template": "#PROTARYTEST{turns}",
"params": [
{
"name": "turns",
"type": "int",
"min": 1,
"max": 10,
"required": true,
"default": 3
}
],
"examples": [
"#PROTARYTEST3"
],
"commentLabel": "Uppity rotary test"
},
{
"id": "uppity.cfg.randomLight",
"name": "Light Kit During Random Mode (v4)",
"category": "Setup",
"safety": "config",
"encoder": "template",
"template": "#PRANDOMLIGHT{mode}",
"params": [
{
"name": "mode",
"enum": "uppity.randomLight",
"required": true,
"default": "0"
}
],
"examples": [
"#PRANDOMLIGHT0",
"#PRANDOMLIGHT7"
],
"commentLabel": "Uppity random light"
},
{
"id": "uppity.cfg.meshHeartbeat",
"name": "Mesh Heartbeat Period (v4)",
"category": "Setup",
"safety": "config",
"encoder": "template",
"template": "#PMESHHB{seconds}",
"params": [
{
"name": "seconds",
"type": "int",
"min": 5,
"max": 300,
"required": true,
"default": 10
}
],
"examples": [
"#PMESHHB10",
"#PMESHHB30"
],
"commentLabel": "Uppity mesh heartbeat"
}
],
"categories": [
Expand Down
4 changes: 2 additions & 2 deletions libraries/manifest.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"$schema": "droidnet-command-library/catalog/v1",
"libraryVersion": "4.6.0",
"libraryVersion": "4.7.0",
"schemaVersion": "v1",
"generatedFrom": "C2B5 firmware + WIPDocs (2026-06); R2UppitySpinnerV3 ALT fw 3.5.3 (2026-07); Printed Droid Magic Panel 32 Wireless KB (2026-07); WCB 6.1.5_290119RJUN2026 (2026-07); WCB 6.2.1_021242RSEP2026 + WcbCmd 0.8.0 (2026-09); DroidNet forks (2026-09)",
"generatedFrom": "C2B5 firmware + WIPDocs (2026-06); R2 Uppity Spinner ALT fw 4.0.0-beta.1 (2026-10); Printed Droid Magic Panel 32 Wireless KB (2026-07); WCB 6.1.5_290119RJUN2026 (2026-07); WCB 6.2.1_021242RSEP2026 + WcbCmd 0.8.0 (2026-09); DroidNet forks (2026-09)",
"boards": [
{
"id": "flthy-hps",
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "droidnet-command-library",
"version": "4.6.0",
"version": "4.7.0",
"description": "Schema-driven encoder/decoder and visual composer for building serial commands to control a vibrant community of Astromech droid components. Anyone can add their board by editing a JSON library — no code changes required.",
"license": "MPL-2.0",
"keywords": [
Expand Down
8 changes: 4 additions & 4 deletions releases.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
"$schema": "droidnet-command-library/releases/v1",
"_comment": "Update pointer for the 'Update Library' flow. A device fetches this file, compares latest.libraryVersion to its installed catalog, and (if newer) downloads latest.url (the catalog manifest), then fetches each board listed in manifest.boards in order, validates them, and loads them via loadLibrary(boards, { libraryVersion }).",
"latest": {
"libraryVersion": "4.6.0",
"libraryVersion": "4.7.0",
"schemaVersion": "v1",
"releasedAt": "2026-10-02",
"releasedAt": "2026-10-24",
"url": "https://raw.githubusercontent.com/travisccook/droidnet-command-library/main/libraries/manifest.json",
"notes": "Minor: comments keep their place, and the composer can follow a host's text field. Engine: a *** comment after an empty segment (^^***) is a standalone note step on its own line instead of the previous step's label, and buildWCBValue writes a note step that follows another step as ^^***text (a note first in the value stays ***text). A comment parsed from a single ^ after a delay, a labelled step or another note carries inline: true and is written back with one ^, so those values rebuild byte for byte. A comment directly after a command or raw step (^***) is still that step's label. The WCB skips empty segments and comments alike, so the firmware runs the same commands. + Note after a step now writes ^^*** (its own line) instead of ^*** (which read back as the step's label). UI: renderComposer returns { setValue(value) }: equal to the compiled steps it does nothing; otherwise it re-parses the steps, cancels a step being edited in the add bar and re-renders the step list, length and safety note, keeping a half-filled add bar. It never calls onChange; callers that ignore the return value are unaffected. No ids, templates or params change; board and command counts are unchanged."
"notes": "Minor: R2 Uppity Spinner ALT updated for firmware 4.0.0-beta.1 (the v4 rewrite; it keeps every v3 :P/#P command). Added: #PRESUME (release a latched E-STOP), #PSTATE, #PCLEARFAULT, #PROTARYTEST<turns>, #PRANDOMLIGHT<mode> (new enum uppity.randomLight) and #PMESHHB<seconds>. :PX and :PH keep their ids and templates with names that say what they do on v4 (:PX latches; :PH lowers safely, homing the head first). The six new commands are marked (v4); #PRC (RC/PPM mode) is kept and marked v3 only: v4 has no RC input and ignores it. The board's routing note describes v4. No ids removed or renamed; other boards unchanged."
},
"libraries": [
{
"id": "droidnet-astromech",
"name": "DroidNet Astromech Boards",
"libraryVersion": "4.6.0",
"libraryVersion": "4.7.0",
"schemaVersion": "v1",
"url": "https://raw.githubusercontent.com/travisccook/droidnet-command-library/main/libraries/manifest.json"
}
Expand Down
2 changes: 1 addition & 1 deletion test/engine.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('engine lookups', () => {
expect(cb.getComponents().map(c => c.id)).toEqual(expect.arrayContaining(['flthy-hps', 'ia-magic-panel']));
});
test('getLibraryVersion reports the loaded version', () => {
expect(cb.getLibraryVersion()).toBe('4.6.0');
expect(cb.getLibraryVersion()).toBe('4.7.0');
});
test('getCommand resolves and back-links its component', () => {
const cmd = cb.getCommand('flthy.led.solid');
Expand Down
6 changes: 3 additions & 3 deletions test/load-node.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,20 @@ const { readCatalog, loadCatalog } = require('../src/load-node.js');

test('readCatalog returns the manifest and every board, in order', () => {
const { manifest, boards } = readCatalog();
expect(manifest.libraryVersion).toBe('4.6.0');
expect(manifest.libraryVersion).toBe('4.7.0');
expect(boards).toHaveLength(manifest.boards.length);
expect(boards.map(b => b.components[0].id)).toEqual(manifest.boards.map(b => b.id));
});

test('loadCatalog({ load: false }) returns the merged catalog object', () => {
const lib = loadCatalog({ load: false });
expect(lib.libraryVersion).toBe('4.6.0');
expect(lib.libraryVersion).toBe('4.7.0');
expect(lib.components.length).toBe(24);
});

test('loadCatalog() loads the engine and resolves commands', () => {
const engine = loadCatalog();
expect(engine.getLibraryVersion()).toBe('4.6.0');
expect(engine.getLibraryVersion()).toBe('4.7.0');
expect(engine.getCommand('flthy.led.solid')).not.toBeNull();
expect(engine.encode(engine.getCommand('flthy.led.solid'), { designator: 'A', color: '5' }, {})).toBe('A0055');
});
Expand Down
Loading