npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

n8n-nodes-uno-q

v0.4.0

Published

n8n community nodes for the Arduino UNO Q — read sensors, drive GPIO, react to MCU events, and expose MCU methods as AI Agent tools.

Readme

n8n-nodes-uno-q

n8n community nodes for the Arduino UNO Q — read sensors, drive GPIO, call I²C devices, and expose MCU methods as tools for n8n's AI Agent. Workflows talk directly to the on-board microcontroller via arduino-router, no Python proxy in the way.

n8n can run on the Q itself (unix socket, same host) or on any other machine that can reach the Q over TCP via a relay container. Two relay flavours ship with this project:

  • deploy/relay/ — plain socat, for trusted LANs. No auth, no encryption.
  • deploy/relay-mtls/stunnel with mutual TLS, for untrusted networks. Requires issuing a client cert via the bundled pki wrapper.
  • deploy/relay-ssh/autossh reverse tunnel, for NAT-ed Qs that can dial out but not be dialled. n8n hosts an embedded SSH server; the Q opens an outbound SSH connection that carries the router socket back through it.

All four setups (unix socket, plain TCP, mTLS, reverse-SSH) use the same nodes and the same Arduino UNO Q Router credential — the Transport dropdown picks which one.

Running n8n in Docker? The reverse-SSH transport listens on a TCP port (default 2222) inside the container. You must publish that port from the container to the host — otherwise the Q's autossh will hit "Connection refused" even though the listener is up. Add the port (matching your credential's Listen Port) to the ports: list in your compose file alongside 5678.

Requirements

  • n8n 1.x (community-nodes-enabled)
  • An arduino-router reachable either via a unix socket (same-host setup) or TCP (remote setup — see the relay container linked above)
  • MCU sketch using Arduino_RouterBridge to register methods with Bridge.provide(...)
  • Node ≥ 20 in the container (the official n8nio/n8n image already meets this)

Install

From n8n: Settings → Community Nodes → Install → type n8n-nodes-uno-q → Install.

n8n fetches the package (and the bridge as a transitive dep) from npm and persists the install in its n8n_data volume. Updates are a click away from the same page.

To enable the Arduino UNO Q Method node as an AI Agent tool, set N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true on the n8n process (already set in the sample docker-compose).

Credential — Arduino UNO Q Router

Each node needs one Arduino UNO Q Router credential assigned. Create it under Settings → Credentials → New → Arduino UNO Q Router:

| Field | When shown | Meaning | |---|---|---| | Transport | always | Unix Socket (local) for same-host, TCP for remote (plain or mTLS — picked by the Use TLS toggle below). | | Socket Path | Transport = Unix | Path to arduino-router's unix socket. Default /var/run/arduino-router.sock fits the sample docker-compose. | | Host | Transport = TCP | Hostname or IP of the Q running the relay container. | | Port | Transport = TCP | TCP port of the relay container. Default 5775. | | Use TLS (mTLS) | Transport = TCP | Toggle on for Variant C (mTLS) relays. See below. | | CA / Client Cert / Client Key | Use TLS = on | PEM contents from your n8n client bundle (see below). |

Test Connection runs $/version end-to-end over the configured transport and returns the router's version on success, or a specific failure message (socket not found, connection refused, timeout, etc.).

mTLS (Variant C)

Plain TCP is unauthenticated and unencrypted — only safe on a trusted LAN. For untrusted networks, enable Use TLS (mTLS) to speak to a Variant C stunnel relay. Three extra fields appear:

  1. CA Certificate (PEM) — paste ca.pem from your n8n client bundle.
  2. Client Certificate (PEM) — paste client.pem.
  3. Client Key (PEM) — paste client.key. n8n stores the key encrypted.

All three come from the same bundle issued by the pki wrapper: running ./pki add n8n laptop produces pki/out/n8n/laptop/{ca.pem,client.pem,client.key}. Paste the contents of each file (not the path) into the matching field.

If any of the three is missing when Use TLS is on, the node errors on first use with a message naming the empty field(s). Test Connection catches the same case before you save.

Turning Use TLS back off ignores any stale cert data — the descriptor reverts to plain TCP on the same host + port.

Multiple Qs

Define one credential per Q (Kitchen Q, Garage Q, …) and assign a different one to each node in a workflow. A workflow that reads a temperature sensor on the kitchen Q and fires a fan relay on the garage Q is two nodes, one credential each — no other coordination needed.

Nodes

  • Arduino UNO Q Call — call an MCU method from a workflow. Pass parameters typed or as a JSON array.
  • Arduino UNO Q Trigger — fire a workflow when the MCU calls or notifies. Two modes:
    • Notification — fire-and-forget (Bridge.notify(...) on the MCU side).
    • Request — the MCU does Bridge.call(...); choose either immediate-ack or Wait for Respond Node to compute a response from workflow data.
  • Arduino UNO Q Respond — companion to Trigger's Wait for Respond Node mode. Same idea as Respond to Webhook, but over the router socket. Takes no credential of its own — it matches the pending request by msgid carried on the incoming item.
  • Arduino UNO Q Method — exposes one MCU method as a tool for the Tools AI Agent. The LLM fills parameter values at runtime via $fromAI('name', 'description', 'type') expressions.

AI Agent usage

Add an Arduino UNO Q Method node per MCU method you want the agent to have access to. Wire each to the Agent's Tool port and fill:

  • Description — clear, action-oriented prose. The LLM reads this to decide when to call.
  • Method — the MCU method name (e.g. set_led_state).
  • Parameters — for each argument the LLM should provide, put {{ $fromAI('name', 'description', 'type') }} in the Value field. Static values pass through unchanged.
  • Idempotent — the one retry flag. See Idempotency and retry below.
  • Method Guard — optional JS predicate that decides whether each invocation may proceed. See Method guard below.
  • Rate Limit — optional cap on invocations per minute/hour/day. See Rate limit and budget below.

Example for an LED on/off tool:

| Field | Value | |---|---| | Description | Turns the onboard LED on or off. Pass true to turn on, false to turn off. | | Method | set_led_state | | Parameter #1 | Type: Boolean, Value: {{ $fromAI('state', 'true for on, false for off', 'boolean') }} | | Idempotent | true — setting the LED to true twice leaves it on |

Idempotency and retry

The Idempotent checkbox (default false, fail-closed) answers one question: if the socket drops and the bridge replays this call with the same params, does the MCU end up in the same state?

  • Yes → tick the box. The bridge auto-retries on mid-call ConnectionError within the remaining timeout budget. Covers absolute writes (set_valve(closed)), pure reads, anything whose end-state is deterministic.
  • No → leave it off. Relative moves, pulses, counters — a replay would double the effect. The ConnectionError surfaces and a human (or the LLM, per your description) decides what to do.

The Arduino UNO Q Call node (non-AI) has the same top-level Idempotent checkbox. For details of the bridge-level retry contract (how many retries, budget handling, what never retries), see the bridge README's Retry and idempotency section.

Method guard

An AI Agent fills $fromAI(...) parameters at runtime — there is no workflow-visible node to intercept and validate. The Method Guard is a small JavaScript body you can attach to a Method node to decide, at invocation time, whether the call should proceed. It gets three variables in scope:

  • method — the MCU method name (string).
  • params — positional arguments, coerced to their declared types (array).
  • budget — a read-only view of recent call history for this node (see Rate limit and budget below).

Typical uses:

  • Argument validation — clamp numeric ranges, reject destructive strings, require non-empty values.
  • Time-of-day / calendar gating — deny calls outside operating hours.
  • External-state checks — read a flag, poll a cache, forbid calls during a maintenance window.
  • Traffic-aware rejection — using budget.used(window) or budget.remaining, reserve quota for higher-priority requests or apply a soft cap without committing to a hard one.

Return values decide the fate of the call:

  • true / undefined / null — allow.
  • false — reject with a generic message.
  • any string — reject with that exact string; when wired to an Agent, the string is fed back as tool output so the LLM can self-correct.
  • throw — the thrown message surfaces prefixed with "Method guard threw:".

A rejected call does not consume rate-limit budget — only calls that pass both gates and reach the MCU count toward maxCalls.

Example — clamp a speed argument and close the door outside business hours:

if (typeof params[0] !== 'number') return 'Refused: speed must be a number';
if (params[0] < 0)   return 'Refused: speed must be >= 0';
if (params[0] > 100) return 'Refused: max speed is 100';

const hour = new Date().getHours();
if (hour < 8 || hour >= 18) return 'Refused: outside operating hours';

return true;

The guard runs without a sandbox, same trust model as n8n's Code node. Leave the field empty to skip. The Arduino UNO Q Call node has no equivalent — non-AI workflows can gate with standard IF/Code nodes before the Call.

Rate limit and budget

An LLM driving the Agent can issue tool calls faster than a microcontroller wants to handle them — bursts from retry loops, exploratory prompting, or just an eager model can swamp the MCU or eat actuator life. The Rate Limit field on the Method node caps invocations in a sliding window:

  • Max Calls — integer, e.g. 10.
  • Perminute, hour, or day.

When exceeded, the node returns { refused: true, error: "Refused: rate limit of 10 per minute exceeded. Retry in ~Xs." } — the same rejection shape the Method Guard uses, so the LLM can read it and back off. The check runs before the Method Guard, so rate-limited calls never execute guard code and never reach the MCU.

Counters are in-memory per n8n process. They reset when the container restarts, and they are not shared across queue-mode workers (one more reason queue mode is unsupported, see Limits).

budget in the Method Guard

The Method Guard sees a budget object whether or not the Rate Limit field is configured, so you can build traffic-aware policies in either setup:

| Property | Type | Meaning | |---|---|---| | budget.used(window) | (window: 'minute' \| 'hour' \| 'day') => number | Prior successful calls in the last window. Always available. | | budget.remaining | number \| null | Calls left under the Rate Limit field. null when no cap is configured. | | budget.resetsInMs | number \| null | Ms until the oldest in-window call rolls off. null when the window is empty or no cap is configured. |

Three patterns you can compose:

// Pattern 1 — hard cap (no guard needed). Set Rate Limit and leave guard empty.

// Pattern 2 — soft cap without committing to enforcement. Works even with no
// Rate Limit set, since budget.used always tracks history.
if (budget.used("minute") >= 20) return "Refused: soft cap at 20/min";
return true;

// Pattern 3 — prioritise. Hard cap plus reservation for critical calls.
// Rate Limit is set (e.g. 10/min); this guard keeps the last 3 slots for
// params that matter most.
if (budget.remaining !== null && budget.remaining < 3 && params[0] < 50) {
  return "Refused: near quota, reserving remaining calls for higher priority";
}
return true;

Limits

  • Per-process singleton bridge — n8n queue mode is not supported. One BridgeManager instance per n8n process keeps a connection per credential and refcounts provide / onNotify subscriptions. With queue mode, each worker would register separately and the MCU would see duplicate registrations. Rate-limit counters are per-process for the same reason.
  • No authentication on the TCP transport. The relay container is a plain socat proxy — deploy only on trusted networks, or restrict with firewall rules / an SSH tunnel.

See also

  • n8n-nodes-arduino-cloud — companion package for the hosted Arduino Cloud story (Nano 33 IoT, MKR WiFi 1010, Portenta, UNO R4 WiFi, Nano ESP32, …). Read / write Thing Properties, react to MQTT property updates, and expose properties as AI Agent tools with the same Property Guard + Rate Limit safety rails this package ships for the UNO Q. Independent from this package — install both side by side if you have UNO Q hardware and other Arduino Cloud-connected boards. The two address different semantics (sub-10 ms LAN-local RPC vs. cloud pub/sub) and don't share state.
  • @raasimpact/arduino-uno-q-bridge — the underlying pure-Node.js MessagePack-RPC client. Useful on its own for Node.js apps on the UNO Q (Express, Fastify, Bun, raw scripts).
  • Project repo and design docs

License

MIT