Docs

Integration SDK API

Types exported by @novon/integration-sdk and the community constants.

DeviceDescriptor

Definition

interface DeviceDescriptor {
  /** Stable per-device id (serial, MAC). Entities sharing it group under one device. */
  uniqueId?: string;
  manufacturer?: string;
  model?: string;
  name?: string;
  swVersion?: string;
  hwVersion?: string;
}

Members

NameTypeOptionalDescription
uniqueIdstringyesStable per-device id (serial, MAC). Entities sharing it group under one device.
manufacturerstringyes—
modelstringyes—
namestringyes—
swVersionstringyes—
hwVersionstringyes—
Source: libs/integration-sdk/src/index.ts:46

EntityDescriptor

Per-platform attribute conventions the hub maps onto the real entity: sensor state: number|string; attributes.unitOfMeasurement, stateClass, batteryLevel, isLow binary_sensor state: 'on'|'off'|boolean; attributes.batteryLevel, isLow switch state: 'on'|'off'|boolean light state: 'on'|'off'|boolean; attributes.brightnessPercent, colorMode, kelvin, rgbColor, supportedColorModes, minColorTempKelvin, maxColorTempKelvin cover state: 'open'|'closed'|'opening'|'closing'; attributes.currentPosition, currentTiltPosition lock state: 'locked'|'unlocked'|boolean; attributes.batteryLevel, isLow select state: current option; attributes.options: string[] Any other primitive attribute is passed through as an extra attribute.

Definition

interface EntityDescriptor {
  /** Stable id within this integration (never changes for the same physical thing). */
  uniqueId: string;
  platform: Platform;
  name: string;
  deviceClass?: string | null;
  /** Platform feature bitmask (e.g. cover SET_POSITION). Omit for the default. */
  supportedFeatures?: number;
  state?: EntityState;
  attributes?: Record<string, unknown>;
  available?: boolean;
  entityCategory?: 'config' | 'diagnostic' | null;
  device?: DeviceDescriptor;
  /**
   * Handle a service call aimed at THIS entity (turnOn, setCoverPosition,
   * selectOption, …). Falls back to the integration's `handleService`.
   */
  onService?: (service: string, data: Record<string, unknown>, ctx: NovonSdk) => void | Promise<void>;
}

Members

NameTypeOptionalDescription
uniqueIdstringnoStable id within this integration (never changes for the same physical thing).
platformPlatformno—
namestringno—
deviceClassstring | nullyes—
supportedFeaturesnumberyesPlatform feature bitmask (e.g. cover SET_POSITION). Omit for the default.
stateEntityStateyes—
attributesRecord<string, unknown>yes—
availablebooleanyes—
entityCategory'config' | 'diagnostic' | nullyes—
deviceDeviceDescriptoryes—
onService(service: string, data: Record<string, unknown>, ctx: NovonSdk) => void | Promise<void>yesHandle a service call aimed at THIS entity (turnOn, setCoverPosition, selectOption, …). Falls back to the integration's handleService.
Source: libs/integration-sdk/src/index.ts:68

EntityUpdate

Definition

interface EntityUpdate {
  state?: EntityState;
  attributes?: Record<string, unknown>;
  available?: boolean;
}

Members

NameTypeOptionalDescription
stateEntityStateyes—
attributesRecord<string, unknown>yes—
availablebooleanyes—
Source: libs/integration-sdk/src/index.ts:88

HttpRequestOptions

----- the novon global ---------------------------------------------------------

Definition

interface HttpRequestOptions {
  url?: string;
  method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD';
  headers?: Record<string, string>;
  /** A string is sent as-is; an object is JSON-encoded with a JSON content-type. */
  body?: string | Record<string, unknown> | unknown[];
  /** Capped by the hub (30 s). Default 15 s. */
  timeoutMs?: number;
}

Members

NameTypeOptionalDescription
urlstringyes—
method'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD'yes—
headersRecord<string, string>yes—
bodystring | Record<string, unknown> | unknown[]yesA string is sent as-is; an object is JSON-encoded with a JSON content-type.
timeoutMsnumberyesCapped by the hub (30 s). Default 15 s.
Source: libs/integration-sdk/src/index.ts:96

HttpResponse

Definition

interface HttpResponse {
  ok: boolean;
  status: number;
  headers: Record<string, string>;
  body: string;
  text(): string;
  json<T = unknown>(): T;
}

Members

NameTypeOptionalDescription
okbooleanno—
statusnumberno—
headersRecord<string, string>no—
bodystringno—
text()text(): string;no—
json()json<T = unknown>(): T;no—
Source: libs/integration-sdk/src/index.ts:106

EntryContext

Definition

interface EntryContext {
  entryId: string;
  title: string;
  domain: string;
  version: string;
  /** Values of config-flow inputs scoped `data` (identity: host, credentials). */
  data: Record<string, unknown>;
  /** Values of inputs scoped `options` (tunables; editable after install). */
  options: Record<string, unknown>;
}

Members

NameTypeOptionalDescription
entryIdstringno—
titlestringno—
domainstringno—
versionstringno—
dataRecord<string, unknown>noValues of config-flow inputs scoped data (identity: host, credentials).
optionsRecord<string, unknown>noValues of inputs scoped options (tunables; editable after install).
Source: libs/integration-sdk/src/index.ts:115

ServiceCallInfo

Definition

interface ServiceCallInfo {
  uniqueId: string;
  platform?: Platform;
  service: string;
  data: Record<string, unknown>;
}

Members

NameTypeOptionalDescription
uniqueIdstringno—
platformPlatformyes—
servicestringno—
dataRecord<string, unknown>no—
Source: libs/integration-sdk/src/index.ts:126

IntegrationDefinition

Definition

interface IntegrationDefinition {
  /**
   * Called once per config entry when it loads (boot, install, reload).
   * Connect to the device, register entities with `ctx.entities.add`, start
   * polling with `setInterval`. Throw `ctx.notReady('...')` to have the hub
   * retry later with backoff; any other throw marks the entry FAILED.
   */
  setupEntry(ctx: NovonSdk): void | Promise<void>;
  /** Called before the entry unloads. Timers are cleared for you. */
  unloadEntry?(ctx: NovonSdk): void | Promise<void>;
  /** Service call for an entity that has no `onService` of its own. */
  handleService?(call: ServiceCallInfo, ctx: NovonSdk): void | Promise<void>;
  /**
   * The user changed the entry's options. Return normally to keep running with
   * `ctx.entry` already updated. When absent, the hub RELOADS the entry.
   */
  optionsUpdated?(ctx: NovonSdk, previous: { data: Record<string, unknown>; options: Record<string, unknown> }): void | Promise<void>;
}

Members

NameTypeOptionalDescription
setupEntry()setupEntry(ctx: NovonSdk): void | Promise<void>;noCalled once per config entry when it loads (boot, install, reload). Connect to the device, register entities with ctx.entities.add, start polling with setInterval. Throw ctx.notReady('...') to have the hub retry later with backoff; any other throw marks the entry FAILED.
unloadEntry()unloadEntry?(ctx: NovonSdk): void | Promise<void>;yesCalled before the entry unloads. Timers are cleared for you.
handleService()handleService?(call: ServiceCallInfo, ctx: NovonSdk): void | Promise<void>;yesService call for an entity that has no onService of its own.
optionsUpdated()optionsUpdated?(ctx: NovonSdk, previous: { data: Record<string, unknown>; options: Record<string, unknown> }): void | Promise<void>;yesThe user changed the entry's options. Return normally to keep running with ctx.entry already updated. When absent, the hub RELOADS the entry.
Source: libs/integration-sdk/src/index.ts:133

NovonSdk

Definition

interface NovonSdk {
  defineIntegration(definition: IntegrationDefinition): IntegrationDefinition;
  /** The config entry this isolate serves (set before `setupEntry`). */
  readonly entry: EntryContext;
  entities: {
    add(descriptors: EntityDescriptor | EntityDescriptor[]): Promise<void>;
    update(uniqueId: string, patch: EntityUpdate): void;
    remove(uniqueId: string): Promise<void>;
    list(): string[];
  };
  /** Outbound HTTP(S). Requires the `http` permission. Loopback / link-local are refused. */
  http(url: string, init?: Omit<HttpRequestOptions, 'url'>): Promise<HttpResponse>;
  http(options: HttpRequestOptions): Promise<HttpResponse>;
  /** Persistent per-entry key/value storage (JSON values ≤ 64 KiB). Requires `kv`. */
  kv: {
    get<T = unknown>(key: string): T | undefined | null;
    set(key: string, value: unknown): void;
    delete(key: string): void;
  };
  /** Build the error that makes the hub retry setup later (device offline, …). */
  notReady(message?: string): Error;
  sleep(ms: number): Promise<void>;
}

Members

NameTypeOptionalDescription
entryEntryContextnoThe config entry this isolate serves (set before setupEntry).
entities{ add(descriptors: EntityDescriptor | EntityDescriptor[]): Promise<void>; update(uniqueId: string, patch: EntityUpdate): void; remove(uniqueId: string): Promise<void>; list(): string[]; }no—
kv{ get<T = unknown>(key: string): T | undefined | null; set(key: string, value: unknown): void; delete(key: string): void; }noPersistent per-entry key/value storage (JSON values ≤ 64 KiB). Requires kv.
defineIntegration()defineIntegration(definition: IntegrationDefinition): IntegrationDefinition;no—
http()http(url: string, init?: Omit<HttpRequestOptions, 'url'>): Promise<HttpResponse>;noOutbound HTTP(S). Requires the http permission. Loopback / link-local are refused.
http()http(options: HttpRequestOptions): Promise<HttpResponse>;no—
notReady()notReady(message?: string): Error;noBuild the error that makes the hub retry setup later (device offline, …).
sleep()sleep(ms: number): Promise<void>;no—
Source: libs/integration-sdk/src/index.ts:152

Platform

Entity platforms a community integration can host, as string literals.

Definition

type Platform = 'sensor' | 'binary_sensor' | 'switch' | 'light' | 'cover' | 'lock' | 'select';
Source: libs/integration-sdk/src/index.ts:42

EntityState

Definition

type EntityState = string | number | boolean | null;
Source: libs/integration-sdk/src/index.ts:44

Ambient globals

Inside the hub's isolate these names exist without an import:

// Ambient declarations for code that runs INSIDE the hub's isolate.
//
// Reference this file from an integration's tsconfig ("types" or a
// `/// <reference types="@novon/integration-sdk/globals" />` line) so `novon`,
// `console` and the timers type-check without importing anything — the
// bundle must not import at runtime; the hub injects these globals.

import type { NovonSdk } from './index';

declare global {
  const novon: NovonSdk;

  function setTimeout(handler: (...args: unknown[]) => void, timeoutMs?: number, ...args: unknown[]): number;
  function setInterval(handler: (...args: unknown[]) => void, intervalMs?: number, ...args: unknown[]): number;
  function clearTimeout(id: number | undefined): void;
  function clearInterval(id: number | undefined): void;

  const console: {
    log(...args: unknown[]): void;
    info(...args: unknown[]): void;
    warn(...args: unknown[]): void;
    error(...args: unknown[]): void;
    debug(...args: unknown[]): void;
  };
}

export {};

Constants

ConstantValue
supportedPlatformssensor, binary_sensor, switch, light, cover, lock, select
permissionshttp, kv, timers
formInputTypesstring, password, text, email, number, boolean, enum, time, entity
iotClassesLocalPush, LocalPoll, CloudPoll, CloudPush
bundleMaxBytes2097152
domainRegex^x_[a-z0-9]+(?:_[a-z0-9]+)*$
domainMaxLength64
Generated from docs-bundle v0.1.0, novon-platform 9ce3486c (2026-10-09).

On this page