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

loxone-ts-api

v2.1.1

Published

TypeScript client for the Loxone API

Readme

loxone-ts-api

A Node module written in TypeScript for facilitating communication with Loxone Miniservers. Communication is done using http and WebSockets.

Tested on Gen.1 Miniservers, but https support also added, so should work with Gen.2 Miniservers too.

Key featrues

  • Connects to the Loxone Miniserver via WebSocket
    • Support for both Gen.1 and Gen.2 Miniservers
    • Support for token-based auth, token refresh and token invalidation
    • Supports automatic reconnect
    • Automatically maintains connection upon disconnect or error
    • Supports determining Miniserver address via Loxone RemoteConnect
  • Event emitting
    • emits events on key connection events
    • emits events for message received
    • ability to filter events to specific UUIDs
  • Loxone structure file parsing
    • Ability to read and parse structure file
    • Provides rich TypeScript classes representing Loxone rooms, controls and states
    • Supplies rich event context for each event (value or text update)
  • Control any Loxone control
    • Supports websocket-based control of any Loxone control
  • Nerdy stuff
    • Fully typed TypeScript objects, avoiding the any type
    • Implemented with async/await - code waits for async websocket response message before returning
    • This package is used as the foundation of matterbridge-loxone

Structure file parsing

After calling LoxoneClient.parseStructureFile(), the client will read the LoxAPP3.json and parse all rooms, their available controls and states associated. These can be read on the client object through the rooms, controls and states collections. It will also start enriching the received events with the associates State object that contains details about the state, its associated control and the room the control is in.

Finding controls and states

const { controls, states } = await new LoxoneClient(ip, user, pass).find("controlname");

Prints a table of matching controls and states with their UUIDs, category, room, control path and state name, and returns the matching objects. See LoxoneClient.find() below.

Watchlist

By default the client will emit all events received via websocket. You can add status UUIDs to the watchlist by calling LoxoneClient.addUuidToWatchList(uuid). Upon adding items to the watchlist, the client will only log and emit events received for statuses associated with the watched UUIDs.

Error handling

The client tries to maintain the connection with the Miniserver even when network interruptions occur. Errors in command calls should not make the client crash. Await command calls inside try/catch or handle their promise rejections. In particular, control() rejects failed Miniserver responses as described below.

Requirements

Requires a Loxone Miniserver with firmware version 11.2 or higher.

Authentication

Uses token authentication with the Miniserver. Automatically attempts token refresh before expiry.

Usage examples

import { AnsiLogger, LogLevel, TimestampFormat } from "node-ansi-logger";
import LoxoneClient from "./LoxoneClient.js";

let log = new AnsiLogger({ logName: "workbench", logTimestampFormat: TimestampFormat.TIME_MILLIS });

// instantiate the client
let client = new LoxoneClient("192.168.1.253:80", "user", "pass");

// alternatively use MAC address to use Loxone Remote Connect
let client = new LoxoneClient("AA:BB:CC:DD:EE:FF", "user", "pass");

// sets log level to debug for more verbose logging
client.setLogLevel(LogLevel.DEBUG);

// subscribe to basic events
client.on("disconnected", () => {
  log.warn("Loxone client disconnected");
});
client.on("error", (error) => {
  log.error(`Loxone client error: ${error.message}`, error);
});

// initiate connection
await client.connect();

// gets acquired token
const token = client.auth.tokenHandler.token;

// disconnects and skips invalidation of token
await client.disconnect(true);

// uses supplied token for auth instead of acquiring a new one
await client.connect(token);

// sets a switch to on
await client.control("90f7abe3-8772-476d-b1dd-a5c1c4cf1ed9", "on");

// subscribe to Loxone value updates
client.on("event_value", (event) => {
  log.info(`Received value event: ${event.uuid.stringValue}`);
  log.info(`  Room: ${event.state?.parentControl?.room?.name}`);
  log.info(`  Control: ${event.state?.parentControl?.name}`);
  log.info(`  State: ${event.state?.name}`);
  log.info(`  Event path: ${event.toPath()}`);
  log.info(`  Full event: ${event.toString()}`);
});

// initiates streaming of events
await client.enableUpdates();

// disconnects and kills token
await client.disconnect();

This will yield a log output similar to:

...
[09:04:59.568] [LoxoneClient] Loxone event: Not Assigned/Control/Subcontrol/total = 2446.4848200150127
[09:04:59.568] [workbench] Received value event: 1cc4333c-02c9-60ec-05ff6d4c46418939
[09:04:59.569] [workbench]   Room: Not Assigned
[09:04:59.569] [workbench]   Control: Control/Subcontrol
[09:04:59.569] [workbench]   State: total
[09:04:59.570] [workbench]   Event path: Not Assigned/Control/Subcontrol/total
[09:04:59.570] [workbench]   Full event: Not Assigned/Control/Subcontrol/total = 2446.4848200150127
...

API surface

LoxoneClient

Key entrypoint to the module.

    LoxoneClient(
        address: string,
        username: string,
        password: string,
        clientOptions: Partial<LoxoneClientOptions>
    )

Parameters

| parameter | description | | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | | address | IP address, hostname, URL or MAC address of the Loxone Miniserver | | username | username to use | | password | password for the user | | clientOptions.autoReconnectEnabled | optional parameter to override the default behavior of automatically reconnecting on failure/disconnection | | clientOptions.keepAliveEnabled | optional parameter to override the default behavior of enabling a 15 second keepalive | | clientOptions.messageLogEnabled | optional parameter to override the default behavior of enabling a logging of messages and responses | | clientOptions.logAllEvents | optional parameter to log all value and text update events to the console | | clientOptions.maintainLatestEvents | optional parameter to override the default behavior of maintaining the latest event for each control | | clientOptions.clientUuid | optional parameter to override the default client UUID of '11fecda8-c89a-48fb-8209-45ed851e81c7' used during authentication |

Instantiating a LoxoneClient instance does not trigger any network communication.

LoxoneClient.connect()

Initiates the connection to the Loxone Miniserver, negotiates session keys and encryption parameters, as well as attempts token authentication.

Goes through the following sequence

  1. Wire up events so LoxoneClient starts emitting connection and Loxone related events
  2. Checks the Loxone Miniserver generation and firmware version
  3. Connects the WebSocket connection
  4. Performs key exchange and authentication, and schedules automatic token refresh
  5. Enables keepalive (unless disabled by clientOptions.keepAliveEnabled)

Parameters

async connect(existingToken: string = "")

| parameter | description | | ------------- | ------------------------------------------------------------------- | | existingToken | if supplied, uses the supplied token instead of acquiring a new one |

LoxoneClient.disconnect()

Disconnects the connection and cleans up internal states.

Parameters

async disconnect(preserveToken: boolean = false)

| parameter | description | | ------------- | --------------------------------------------------------------------------------------------- | | preserveToken | optional parameter to skip killing the obtained token so it remains valid after disconnection |

LoxoneClient.getStructureFile()

Retrieves the Loxone structure file (LoxAPP3.json)

Parameters

async getStructureFile()

LoxoneClient.parseStructureFile()

Parses the Loxone structure file (LoxAPP3.json). After calling this method, event updates will contain enriched information about the room, control and states. Each State of all Controls will also start remembering the latest event received (unless disabled by clientOptions.maintainLatestEvents)

Parameters

async parseStructureFile()

LoxoneClient.enableUpdates()

Enables the streaming of binary event updates.

Parameters

async enableUpdates()

LoxoneClient.sendTextCommand()

Sends a text command to the Miniserver and waits for the response till timeout (default: 5s, overridable). Automatically applies Command Encryption as needed.

Parameters

async sendTextCommand(command: string, timeoutOverride = this.COMMAND_TIMEOUT): Promise<TextMessage>

| parameter | description | | --------------- | ------------------------------------------------------------------------------------ | | command | The Loxone command to execute | | timeoutOverride | optional parameter allowing override of the default 5s timeout. Unit is milliseconds |

Returns

TextMessage object with the response to the command, or an exception.

LoxoneClient.sendFileCommand()

Retrieves a file from the Miniserver and waits for the response till timeout (default: 5s, overridable).

Parameters

async sendFileCommand(filename: string, timeoutOverride = this.COMMAND_TIMEOUT): Promise<FileMessage>

| parameter | description | | --------------- | ------------------------------------------------------------------------------------ | | filename | Filename of the file to be retrieved | | timeoutOverride | optional parameter allowing override of the default 5s timeout. Unit is milliseconds |

Returns

FileMessage object with the file contents, or an exception.

LoxoneClient.control()

Executes a command on a Loxone control identified by its UUID and waits for the response till timeout (default: 15s, overridable).

See the Loxone structure file for documentation on possible commands.

Parameters

async control(uuid: UUID | string, command: string, timeoutOverride = this.COMMAND_TIMEOUT): Promise<TextMessage>

| parameter | description | | --------------- | ------------------------------------------------------------------------------------ | | uuid | UUID of the Loxone control to operate | | command | The command to send | | timeoutOverride | optional parameter allowing override of the default 5s timeout. Unit is milliseconds |

Returns

Resolves with the original TextMessage when response.code === 200 and response.value !== "0". This acknowledges the command response, not the resulting device state; state feedback remains authoritative.

Rejects with the named export LoxoneControlError when:

  • The API response code is not 200 (including 404 or a missing code).
  • The API response code is 200 but the value is the string "0", indicating unsuccessful command execution. Only the string "0" is treated as this failure marker.

The error message includes the control UUID, command, and response code. error.response retains the original TextMessage, including its code, value, control, and parsed response data. A 404 error also identifies the control as not found. Failures are logged; commands are not retried or compensated.

Transport failures and calls made before the client is ready continue to reject with an Error whose cause is the original failure.

Compatibility change: Non-200 responses and responses with value: "0" previously only logged errors and resolved. Callers must now handle their rejected promises. The successful return type remains Promise<TextMessage>.

import LoxoneClient, { LoxoneControlError } from "loxone-ts-api";

try {
  await client.control("90f7abe3-8772-476d-b1dd-a5c1c4cf1ed9", "on");
} catch (error) {
  if (error instanceof LoxoneControlError) {
    console.error(error.message, error.response.code, error.response.value);
  }
  throw error; // Propagate the failure to the caller.
}

LoxoneClient.find()

async find(searchString: string): Promise<LoxoneFindResult>
// LoxoneFindResult is a named type export: { controls: Control[]; states: State[] }

Searches category names, room names, control names (including parent/subcontrol paths) and state names using case-insensitive substring matching. Categories are resolved from the structure file; subcontrols inherit their parent's category when absent. A control matches its category, room or control path. A state matches those fields of its control or its own state name. A state-name-only match does not add its control to the controls array.

An empty string or "*" returns everything. Other strings are literal substrings, not wildcard patterns or regular expressions. No matches returns empty arrays. The returned arrays contain the original objects from the client's collections.

Every call prints a table, regardless of the configured log level.

The method reuses an already parsed structure or parses a previously loaded one. Otherwise it fetches and parses the structure, connecting and authenticating first if necessary. A connection opened by find() is disconnected afterward, even on failure; an existing connection is left open. One-shot connections do not automatically retry. Calls made while the client is connecting/reconnecting reject if they need a connection. Connection, download and parsing failures are logged and reject the promise.

await new LoxoneClient(ip, user, pass).find("*"); // Print all controls and states.
const { states } = await client.find("kitchen"); // Reuse an existing client.

LoxoneClient.setLogLevel()

Sets the log level. By default it is set to INFO.

Parameters

setLogLevel(level: LogLevel)

| parameter | description | | --------- | -------------------------------------------------------------- | | level | Loglevel to set logging to. Uses the node-ansi-logger module |

LoxoneClient.addUuidToWatchList()

Adds UUIDs to the watch list. Value and text update events will only be emitted for these UUIDs. If the watchlist is empty, all events will be emitted.

Parameters

addUuidToWatchList(uuid: string | string[])

| parameter | description | | --------- | ------------------------------------------------------- | | uuid | UUID string or array of strings to add to the watchlist |

LoxoneClient.removeUuidFromWatchList()

Removes UUIDs from the watch list.

Parameters

removeUuidFromWatchList(uuid: string | string[])

| parameter | description | | --------- | ------------------------------------------------------------ | | uuid | UUID string or array of strings to remove from the watchlist |

LoxoneClient.checkToken()

Checks whether the token is still valid.

Parameters

async checkToken(token: string = "")

| parameter | description | | --------- | ----------------------------------------------------------------------------- | | token | If supplied, checks the supplied token instead of the remembered (active) one |

LoxoneClient.refreshToken()

Refreshes the active token if it is still valid. If not, attempts to acquire a new one.

Parameters

async refreshToken()

Events

The LoxoneClient emits the following events:

  connected: () => void;

Fires when the connection is successfully established.

  authenticated: () => void;

Fires when authentication was successful.

  ready: () => void;

Fires when LoxoneClient is ready to receive commands.

  disconnected: (reason: string) => void;

Fires when the underlying WebSocket is disconnected.

  error: (err: Error) => void;

Fires when a WebSocket error is encountered.

  header: (header: ParsedHeader) => void;

Fires when a header message is received.

  keepalive: (header: ParsedHeader) => void;

Fires when a keepalive message is received.

  text_message: (text: TextMessage) => void;

Fires when a text message is received on the WebSocket channel.

  file_message: (file: FileMessage) => void;

Fires when a file message is received on the WebSocket channel.

  event_table_values: (eventTable: LoxoneValueEvent[]) => void;
  event_table_text: (eventTable: LoxoneTextEvent[]) => void;
  event_table_day_timer: (eventTable: LoxoneDayTimerEvent[]) => void;
  event_table_weather: (eventTable: LoxoneWeatherEvent[]) => void;

Fires when an event update message is received on the WebSocket channel. EventTables can contain multiple update events of the same kind.

  stateChanged: (newState: string) => void;

Fires when the LoxoneClient changes its state. Possible states are:

  • disconnected
  • disconnecting
  • connecting
  • connected
  • authenticating
  • authenticated
  • ready
  • reconnecting
  • error
  event_value: (event: LoxoneValueEvent) => void;
  event_text: (event: LoxoneTextEvent) => void;

Fires when Loxone value or text update events are received. Events can be filtered using the watchlist functionality (addUuidToWatchList() and removeUuidFromWatchList()). If the watchlist contains any items, events event_value and event_text events are only emitted for the UUIDs that are on the watchlist. If the watchlist is empty, events are emitted for all value and text updates.

Disclaimer

While the author took special care to follow Loxone official documentation, use this module at your own risk.

Acknowledgements, credits

This module is heavily inspired by and based on the node-lox-ws-api module: https://github.com/alladdin/node-lox-ws-api