UNPKG

bacnet-device

Version:

A TypeScript library for implementing BACnet IP devices in Node.js.

141 lines 4.92 kB
/** * BACnet singlet property implementation module * * This module provides the implementation for BACnet properties * that contain a single value (as opposed to array properties). * * @module */ import fastq from 'fastq'; import {} from '../value.js'; import { BDEvented } from '../evented.js'; import { BDError } from '../errors.js'; import { PropertyIdentifier, ErrorCode, ErrorClass, ApplicationTag } from '@innovation-system/node-bacnet'; /** * Implementation of a BACnet property with a single value * * This class represents a BACnet property that contains a single value (not an array). * It manages the property's value and handles read/write operations and change notifications. * * @typeParam Tag - The BACnet application tag for the property value * @typeParam Type - The JavaScript type corresponding to the application tag * @extends BDEvented<BDSingletPropertyEvents<Tag, Type>> */ export class BDSingletProperty extends BDEvented { /** Indicates this is not a list/array property */ list; /** The BACnet application tag for this property's value */ type; /** Whether this property can be written to */ writable; settable; /** The BACnet property identifier */ identifier; /** * The current value of this property * @private */ #value; /** * Queue for serializing value changes * @private */ #queue; /** * Creates a new BACnet singlet property * * @param identifier - The BACnet property identifier * @param type - The BACnet application tag for this property's value * @param writable - Whether this property can be written to * @param value - The initial value for this property */ constructor(identifier, type, writable, value) { super(); this.list = false; this.type = type; this.writable = typeof value !== 'function' && writable; this.settable = typeof value !== 'function'; this.identifier = identifier; this.#value = typeof value === 'function' ? value : { type, value }; this.#queue = fastq.promise(this.#worker, 1); } /** * Gets the current value of this property * * @returns The current property value */ getValue() { return typeof this.#value === 'function' ? this.#value().value : this.#value.value; } /** * Sets a new value for this property * * This method queues the value change to ensure proper event * notification and serialization of changes. * * @param value - The new value to set * @returns A promise that resolves when the value has been set */ async setValue(value) { if (this.settable) { await this.#queue.push({ type: this.type, value }); } else { throw new Error(`Property ${this.identifier} is not settable`); } } /** * Reads the current value of this property for BACnet operations * * This internal method is used by BACnet objects to read the property value * when handling BACnet protocol operations. * * @returns The current property value in BACnet format * @internal */ ___readValue() { return typeof this.#value === 'function' ? this.#value() : this.#value; } /** * Writes a new value to this property for BACnet operations * * This internal method is used by BACnet objects to write the property value * when handling BACnet protocol operations. * * @param value - The new value to write in BACnet format * @returns A promise that resolves when the value has been set * @throws BACnetError if the property is not writable or the value type is invalid * @internal */ async ___writeValue(value) { if (!this.writable || !this.settable) { throw new BDError('not writable', ErrorCode.WRITE_ACCESS_DENIED, ErrorClass.PROPERTY); } if (Array.isArray(value)) { if (value.length !== 1) { throw new BDError('not a list', ErrorCode.REJECT_INVALID_PARAMETER_DATA_TYPE, ErrorClass.PROPERTY); } else { value = value[0]; } } if (value.type !== this.type) { throw new BDError('not a list', ErrorCode.REJECT_INVALID_PARAMETER_DATA_TYPE, ErrorClass.PROPERTY); } await this.#queue.push(value); } /** * Worker function for processing the value change queue * * This method processes each value change and triggers the appropriate events. * * @param value - The new value to set * @private */ #worker = async (value) => { await this.trigger('beforecov', this, value); this.#value = value; await this.trigger('aftercov', this, value); }; } //# sourceMappingURL=singlet.js.map