Abstract Class: Sensor<P, Params>
A value coming from the device (a power reading, a door state). Write one sensor class per kind
of value and list it in the plugin's static sensors. Each configured sensor (a capability plus params) is one
instance, created when the signal is added and disposed when it is removed or the plugin stops.
Editing a signal's params in the UI disposes the instance and creates a new one, so start()
runs again with the new params; keep state that must outlive that in the plugin.
A sensor has no value until it emits: in start(), emit what you already know (the plugin's latest poll, the entity's current state), or the signal stays empty until the next change.
The class declares itself with static fields (see SensorClass; only id is required):
export class PowerSensor extends Sensor<FroniusPlugin, { path: string }> {
static readonly id = "power"
static readonly params = z.object({ path: z.string() })
static readonly valueType = "number"
override start() { this.listen(this.plugin.poller, "data", data => this.emit(Value.number(...))) }
}
Extends
Type Parameters
P
Params
Params = unknown
Constructors
Constructor
new Sensor<
P,Params>(plugin,params,output,signal?):Sensor<P,Params>
plugin is the plugin instance, for what sensors share (a poller, an API client). params
are validated against the static params schema before construction, with defaults applied,
and are available in field initializers. signal names
the configured signal this sensor is (for panels and log lines); a subclass that declares its
own constructor must pass it on to super().
Parameters
plugin
P
params
Params
output
signal?
SignalInfo = ...
Returns
Sensor<P, Params>
Overrides
Properties
MAX_TIMER_MS
readonlystaticMAX_TIMER_MS:2147483647=2_147_483_647
the largest delay setTimeout/setInterval honour; Node turns anything longer into 1 ms
Inherited from
plugin
readonlyplugin:P
params
readonlyparams:Params
signal
readonlysignal:SignalInfo
Accessors
isDisposed
Get Signature
get isDisposed():
boolean
true from the moment dispose() starts, not when it finishes
Returns
boolean
Inherited from
clock
Get Signature
get clock():
Clock
the plugin's clock: this.clock.now() instead of Date.now(); every() and after() run on it
Returns
Methods
dispose()
dispose():
Promise<void>
Releases everything registered with this object. Plugin code seldom needs it: the runtime disposes plugins, sensors and actuators, and own() disposes children. Call it yourself for an object you created without own(), or to end a child early.
Runs all teardowns in reverse registration order and keeps going when one fails. Idempotent: every call returns the same promise, so a second caller also waits for async teardowns.
Returns
Promise<void>
Throws
AggregateError collecting every teardown error, after all teardowns have run
Inherited from
onDispose()
protectedonDispose(teardown):void
Registers a callback that runs on dispose(), for cleanup the helpers don't cover (closing a socket, flushing a buffer). Async callbacks are awaited one after the other, last registered first, so a flush can use what was registered before it. Keep the total under the five seconds a stop has.
Parameters
teardown
Returns
void
Throws
Error if already disposed
Inherited from
useClock()
protecteduseClock(clock):void
Sets the clock for every() and after() calls from now on, unless one is set already; without one they run on the system clock. Timers started before keep the clock they started on. Plugin, Sensor and Actuator set it from the plugin's context.
Parameters
clock
Clock | undefined
Returns
void
Inherited from
currentClock()
protectedcurrentClock():Clock
The clock this object runs on: every() and after() use it, and a Disposable that isn't a
plugin, sensor or actuator reads the time from it (this.currentClock().now()).
Returns
Inherited from
own()
protectedown<T>(resource):T
ties the lifetime of a child resource to this object; returns it so construction and registration fit in one expression. A Disposable child without a clock of its own runs on this one's, looked up when a timer starts, so a chain of owners (plugin → client → poller) shares the plugin's clock. Timers a child starts in its constructor, before it is owned, run on the system clock.
Type Parameters
T
T extends DisposableLike
Parameters
resource
T
Returns
T
Inherited from
every()
protectedevery(ms,fn): () =>void
runs fn every ms milliseconds until disposed or until the returned cancel function is called. The first run is after ms, not at once; call fn yourself first if you want an immediate run. Runs are not queued: a slow async fn can overlap its next run, so guard it yourself if needed.
Parameters
ms
number
fn
() => void
Returns
() => void
Throws
RangeError unless 0 < ms <= MAX_TIMER_MS
Inherited from
after()
protectedafter(ms,fn): () =>void
runs fn once after ms milliseconds unless disposed before; returns a cancel function. Both firing and cancelling forget the teardown, so repeated use does not accumulate entries. Delays beyond MAX_TIMER_MS are scheduled in steps, so they don't fire early.
The delay counts elapsed time, not wall-clock time: a clock step (an NTP sync after boot) is not noticed. For a deadline given as a wall-clock time, wait in shorter slices and re-check the time each time.
Parameters
ms
number
fn
() => void
Returns
() => void
Throws
RangeError for negative or non-finite delays
Inherited from
listen()
protectedlisten(emitter,event,listener):void
Subscribes listener to event of an EventEmitter (or anything with on/off) and removes it
again on dispose(), so a long-lived emitter such as the plugin's poller does not keep a
disposed sensor alive. Prefer it to calling emitter.on yourself.
Parameters
emitter
event
string | symbol
listener
Returns
void
Inherited from
start()
start():
void|Promise<void>
Starts producing values. Called once, right after construction, when the signal is added; the host waits for it (at most 30 seconds). A rejection makes adding the signal fail with the message and disposes the sensor. Emitting from inside start() is allowed.
Returns
void | Promise<void>
emit()
protectedemit(value):void
Sends a value to the bus, tagged with the cause of the work that is running. Equal consecutive
values are dropped there, so emit on every poll without comparing yourself. A value of another
type than the declared valueType is converted to it by the host before it is published. Clears a failure reported
with fail(). Does nothing once the sensor is disposed, so a late callback is harmless.
Parameters
value
Returns
void
fail()
protectedfail(message):void
Reports that the sensor can't deliver values anymore, e.g. the entity it follows was deleted.
The message shows on the signal and the instance's error topic until the next emit() or
recover(). The last value stays on the bus. For a temporary outage of the whole device use
plugin.status.set("degraded", …) instead. Repeating the same message sends nothing.
Parameters
message
string
Returns
void
recover()
protectedrecover():void
Clears a failure reported with fail() when the sensor works again but has no value to send (an entity back as "unavailable"). Cheap to call often: it only tells the host after a fail().
Returns
void