UNPKG

@cygnus-reach/reach-protocol

Version:

Improve the Reachâ„  remote support experience with straightforward device interactions via the Reach Protocol.

518 lines (517 loc) • 31.9 kB
import { Observable, Subject } from 'rxjs'; import { FileTransfer, FileTransferConfig, FileTransferDirection } from './file-transfer'; import { NetworkAccess } from './network-access'; import { CLIData, CommandInfo, DiscoverWiFiResponse, ErrorReport, FileInfo, FileTransferDataNotification, FileTransferResponse, ParameterInfo, ParameterNotifyConfig, ParameterValue, PingResponse, ReachMessage, ReachMessageHeader, ReachMessageTypes, TimeGetResponse, WiFiConnectionResponse } from './proto/reach'; import { DeviceInfo, ParamNotifSettings, ParameterExtendedInfo, ParsedParameterInfo, ProtoVersion } from './models/extensions'; import { Request, RequestConfig, RequestMechanics, RequestMessage } from './models/request'; export declare class DeviceAccess { private _networkAccess; protected onMessageSubject: Subject<ReachMessage>; protected onErrorReportSubject: Subject<{ header: ReachMessageHeader; payload: ErrorReport; }>; protected onFileTransferSubject: Subject<FileTransfer>; protected onCliMesssageSubject: Subject<void>; /** * Observable fired whenever a Reach Protocol message is received. */ onMessage$: Observable<ReachMessage>; /** * Observable fired whenever an error report message is received from the server. * The header and payload are both provided. */ onErrorReport: Observable<{ header: ReachMessageHeader; payload: ErrorReport; }>; /** * Observable fired upon successful completion of a file transfer. * The value associated with the event is the complete FileTransfer object, which will no longer be accessible in the fileTransfers map. */ onFileTransfer$: Observable<FileTransfer>; /** * Observable fired whenever a CLI message is received. The CLI messages are available in the cliMessages map. */ onCliMessage$: Observable<void>; protected _classicHeaders: boolean; protected _transactionId: number; protected _clientId: number; protected _endpointId: number; protected _transactionTimeout: number; /** * This map is keyed off of the string generated by RequestID.key */ protected _transactions: Map<string, Request<any>>; protected _deviceInfo: DeviceInfo | undefined; protected _paramInfos: Map<number, ParsedParameterInfo>; protected _paramValues: Map<number, ParameterValue>; protected _paramExtInfos: Map<number, ParameterExtendedInfo>; protected _paramNotifications: Map<number, ParameterNotifyConfig>; protected _commandInfos: Map<number, CommandInfo>; protected _cliMessages: Map<Date, CLIData>; protected _currentFileTransferId: number | undefined; protected _fileInfos: Map<number, FileInfo>; protected _fileTransfers: Map<number, FileTransfer>; protected _ackRate: number; protected _transferTimeout: number; protected _timeOffset: bigint | undefined; protected _timezone: number | undefined; /** * Creates a new system for interfacing with a Reach Protocol device. * @param _networkAccess - The implemented system for communicating with the device * @param classicHeaders - Whether the deprecated original Reach Protocol header format should be used. Defaults to false. */ constructor(_networkAccess: NetworkAccess, classicHeaders?: boolean); /** * General initialization of device communication. */ init(): void; /** * Handles receipt of a Reach Protocol message, attempting to associate it with known transactions, and parsing any relevant data if it is not part of a known transaction. * @param binaryData - The raw data containing a Reach Protocol message */ handleMessage(binaryData: ArrayBuffer): void; /** * Sends a provided Reach Protocol message via the transport method defined by NetworkAccess. * @param message - The message to be sent to the server. * @returns the result of sending the bytes via NetworkAccess */ send(message: ReachMessage): Promise<void | Uint8Array>; /** * Sends a request with the specified category and payload, routing responses to the specified message handler. * Detailed configuration can be achieved through the config and mechanics arguments. * @typeParam T - The type expected to be returned upon a request being successfully fulfilled. * @param messageCategory - The category of message to be sent. * Unless otherwise specified in the config, responses to the initial message must be of this category to be considered valid. * @param payload - The payload for the message sent * @param onMessage - A handler for valid messages received as responses, returning an updated state for the request unless marked as stateless * @param config - High-level configuration for the request. * @param mechanics - Low-level configuration for the request. * @returns A Request with the specified configuration and typing */ sendRequest<T>(messageCategory: ReachMessageTypes, messages: RequestMessage[] | RequestMessage, onMessage: (message: ReachMessage) => T, config?: Partial<RequestConfig>, mechanics?: Partial<RequestMechanics>): Promise<Request<T>>; /** * Sends a ping containing binary data to the server, waiting for a response from the server. * @param data - The data contained in the ping, which should be returned by the server. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns Upon a non-error response from the server. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. */ ping(data: Uint8Array, config?: Partial<RequestConfig>): Promise<PingResponse>; /** * Sends a ping containing string data to the server, waiting for a response from the server. * @param data - The string included in the ping, which should be returned by the server. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns The response upon successful receipt from the server. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. * @remarks This is a wrapper for the {@link ping} method, encoding a string into raw bytes. */ pingString(data: string, config?: Partial<RequestConfig>): Promise<PingResponse>; /** * Gets metadata from the device via a DeviceInfoRequest. * @param challengeKey - An optional challenge key sent to the device to grant modified access to services. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns The metadata (DeviceInfo) upon a successful response from the server. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. */ getDeviceInfo(challengeKey?: string, config?: Partial<RequestConfig>): Promise<DeviceInfo>; /** * Fetches core parameter information from the server. * @param parameterIds - A list of potential parameter IDs to be checked for. An empty array means that all available parameters will be discovered. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns A map of parameter information upon successful receipt of responses from the server. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. * @remarks If there are more parameter IDs provided than can be fit into a single message, a provided transaction ID will be incremented with each message. */ discoverParameters(parameterIds?: number[], config?: Partial<RequestConfig>): Promise<Map<number, ParsedParameterInfo>>; /** * Fetches extended parameter information from the server. * @param paramExtInfoIds - A list of potential parameter extended info (PEI) IDs to be checked for. An empty array means that all available PEI IDs will be discovered. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns A map of parameter extended info upon successful receipt of responses from the server. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. * @remarks If there are more PEI IDs provided than can be fit into a single message, a provided transaction ID will be incremented with each message. */ discoverParametersExt(paramExtInfoIds?: number[], config?: Partial<RequestConfig>): Promise<Map<number, ParameterExtendedInfo>>; /** * Reads the value of a single specified parameter. * @remarks The underlying message and response is equivalent to reading multiple parameters, and as such is not inherently optimized compared to that case. * @param parameterId - The parameter ID to be read. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns The parameter value upon successful receipt of a response from the server. * @throws A descriptive Error upon a transaction timeout or error response from the server. */ readParameter(parameterId: number, config?: Partial<RequestConfig>): Promise<ParameterValue>; /** * Reads the values of the specified parameters, or all known parameters if no parameters are specified. * @param parameterIds - The parameter IDs to be read, reading all parameters if undefined or an empty array. The array will be deduplicated before sending read requests. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns A map of parameter values upon successful receipt from the server. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. * @remarks If there are more parameter IDs provided than can be fit into a single message, a provided transaction ID will be incremented with each message. */ readParameters(parameterIds?: number[], config?: Partial<RequestConfig>): Promise<Map<number, ParameterValue>>; /** * Writes the specified parameter values to a server. * @param values - The values to be written. * @param parameterKey - Optional access key for the parameter(s) being written. * @param paramsPerMessage - Optional custom definition of the number of values written per message. * If a limit is known from device info, that limit will cap the number of values per message. * If not provided, a safe default will be chosen. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns Upon completion of the last write. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. * @remarks Internal accounting of parameter values is updated as writes are reported to be successful. */ writeParameters(values?: ParameterValue[], paramsPerMessage?: number, config?: Partial<RequestConfig>): Promise<void>; /** * Gets the existing configuration of parameter notifications being tracked by the server. * @param parameterIds - The parameters to be checked for notifications. If not provided, all parameters will be checked. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns The current configuration of parameter notifications on the server. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. */ discoverParameterNotifs(parameterIds?: number[], config?: Partial<RequestConfig>): Promise<Map<number, ParameterNotifyConfig>>; /** * Enables parameter notifications on the device for the specified parameters. * @param toEnable - Settings for parameter notifications to be enabled. Defaults to instant notifications on changes with a delta of 1. * @param disableAllFirst - Whether all existing parameter notifications should be disabled before enabling new notifications. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns The resulting notification configuration, upon a successful response from the server * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. */ enableParameterNotifs(toEnable: Array<ParamNotifSettings>, disableAllFirst?: boolean, config?: Partial<RequestConfig>): Promise<Map<number, ParameterNotifyConfig>>; /** * Disables parameter notifications on the device for the specified parameters. * @param parameterIds - The parameters whose notifications are to be disabled. If not provided, all notifications will be disabled. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns The current configuration of parameter notifications on the server. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. */ disableParameterNotifs(parameterIds?: number[], config?: Partial<RequestConfig>): Promise<Map<number, ParameterNotifyConfig>>; /** * Fetches core information about files available to the client from the server. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns A map of file information upon successful receipt from the server. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. */ discoverFiles(config?: Partial<RequestConfig>): Promise<Map<number, FileInfo>>; /** * Reads the specified file from the device, returning the file's data upon success. * @param fileID - The ID of the file to be read. * @param transferConfig - Configuration applying to the data transfer process. * @param requestConfig - General message configuration, applying only to init and completion messages if otherwise set in the transfer config. * @param initData - If reading a file with full data provided, data read from the device will be inserted starting at the provided byte offset. Not generally used. * @returns The file data upon successful completion. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. */ readFile(fileID: number, transferConfig?: Partial<FileTransferConfig>, requestConfig?: Partial<RequestConfig>, initData?: Uint8Array): Promise<number[]>; /** * Writes the provided data to the specified file on the device. * @param fileID - The ID of the file to be written to. * @param data - The bytes to be written to the file. * If fullDataProvided is set in the transfer config, data will be pulled from the specified offset within this data rather than the beginning. * @param transferConfig - Configuration applying to the data transfer process. * @param requestConfig - General message configuration, applying only to init and completion messages if otherwise set in the transfer config. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. */ writeFile(fileID: number, data: Uint8Array, transferConfig?: Partial<FileTransferConfig>, requestConfig?: Partial<RequestConfig>): Promise<void>; /** * Sends a FileTransferInit to the device with the specified configuration * @param fileID - The ID of the file to be written to. * @param direction - The direction of the transfer being initated. * @param transferConfig - Configuration to be included in the init. * @param requestConfig - Configuration for how the init is sent to the device. * @returns The response from the device, or errors encountered or reported by the device. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. */ fileTransferInit(fileId: number, direction: FileTransferDirection, transferConfig?: Partial<FileTransferConfig>, requestConfig?: Partial<RequestConfig>): Promise<FileTransferResponse>; /** * Sends a FileTransferDataNotification message to the device and collects responses to the notification. * @param transferId - The ID of the transfer being notified about. * @param complete - If the transfer is being marked as complete. Defaults to false. * @param config - Configuration for how the notification is sent to the device. * @param result - The result code to report to the device. Defaults to 0 (no error). * @param errorMessage - An error message to report to the device. Defaults to blank (no error). * @param retryOffset - A byte offset within the file transfer to allow the device to retry after an error. System for use still undefined. * @returns The data reported by the device, or if sent as a complete transfer, the response from the device. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. */ transferDataNotification(transferId: number, complete?: boolean, config?: Partial<RequestConfig>, result?: number, errorMessage?: string, retryOffset?: number): Promise<number[] | FileTransferDataNotification>; /** * Sends a group of FileTransferData messages to the device and reports the device's response. * @param transferId - The ID of the transfer this data is associated with. * @param dataChunks - Groups of bytes to be sent to the device. * @param config - Configuration for how the messages are sent to the device. * @param checksums - RFC 1071 checksums for additional integrity verification. * @returns The response from the device. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. */ transferData(transferId: number, dataChunks: Uint8Array[], config?: Partial<RequestConfig>, checksums?: number[]): Promise<FileTransferDataNotification>; /** * Fetches information about predefined commands available to the client from the server. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns A map of command information upon successful receipt from the server. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. */ discoverCommands(config?: Partial<RequestConfig>): Promise<Map<number, CommandInfo>>; /** * Instructs the server to perform a specified command. * @param id - The ID of the command to be performed. * @param config - Optional configuration of the Reach Protocol message being sent. * @throws A descriptive Error upon a transaction timeout or error response from the server. */ sendCommand(id: number, config?: Partial<RequestConfig>): Promise<void>; /** * Sends command line data to the device. * As the device does not provide a specific response to this command, * this function returns upon successfully sending the message via the transport. * @param data - The data to be sent to the device's command line. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns The CLIData successfully sent. * @throws A descriptive error if no data is provided, and any errors produced when trying to send the Reach Protocol message. */ sendCLIData(data: string, config?: Partial<RequestConfig>): Promise<CLIData>; /** * Sets the device's internal representation of time. * @remarks The DeviceAccess' timeOffset and timezone fields are not updated by this, due to variations in time service implementations. * @param time - The time to be set, offset as necessary if setting a raw time. * @param timezoneOffset - A timezone represented as an offset from UTC, in seconds. Handling of undefined values is determined by the device. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns Upon a successful write. * @throws A descriptive Error upon a transaction timeout or error response from the server. */ setTime(time: Date, timezoneOffset?: number, config?: Partial<RequestConfig>): Promise<void>; /** * Gets the device's internal representation of time. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns The response to the message, including the device time. * @throws A descriptive Error upon a transaction timeout or error response from the server. */ getTime(config?: Partial<RequestConfig>): Promise<TimeGetResponse>; /** * Fetches information about WiFi networks available to the server. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns The response from the server upon success. * @throws A descriptive Error upon a transaction timeout or unexpected/error response from the server. */ discoverWiFi(config?: Partial<RequestConfig>): Promise<DiscoverWiFiResponse>; /** * Attempts to connect to a specified WiFi network. * @param ssid - The SSID of the network to be connected to. * @param password - Password used to connect to the network. * @param autoconnect - Whether the server should automatically connect to this network. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns The response from the server upon success. * @throws A descriptive Error upon a transaction timeout or error response from the server. * @remarks This is a wrapper for the {@link setWiFiConnection} method, which more directly reflects the Reach Protocol message sent to the server. */ connectWiFi(ssid: string, password: string, autoconnect: boolean, config?: Partial<RequestConfig>): Promise<WiFiConnectionResponse>; /** * Attempts to disconnect from a specified WiFi network. * @param ssid - The SSID of the network to disconnect from. * @param config - Optional configuration of the Reach Protocol message being sent. * @returns The response from the server upon success. * @throws A descriptive Error upon a transaction timeout or error response from the server. * @remarks This is a wrapper for the {@link setWiFiConnection} method, which more directly reflects the Reach Protocol message sent to the server. */ disconnectWiFi(ssid: string, config?: Partial<RequestConfig>): Promise<WiFiConnectionResponse>; /** * Sends a WiFi connection request to the device, and reports the response upon success. * @param ssid - The ID of the network to connect to/disconnect from * @param connect - Whether the specified network should be connected to. * @param disconnect - Whether the specified network should be disconnected from. * @param config - Optional configuration of the Reach Protocol message being sent. * @param password - If connecting, the password to be used to connect to the network. * @param autoconnect - If connection is successful, whether this network should be automatically connected to. * @returns The response from the server, including the RSSI of the network. * @throws A descriptive Error upon a transaction timeout or error response from the server. * @remarks * If called with connect and disconnect set to false, information about the network will be returned without action. * The meaning of a message with both connect and disconnect set to true has not been agreed upon at this stage. * One option would be for the server to disconnect from any current network(s) and connect to the network specified. */ setWiFiConnection(ssid: string, connect: boolean, disconnect: boolean, config?: Partial<RequestConfig>, password?: string, autoconnect?: boolean): Promise<WiFiConnectionResponse>; handlePing(message: ReachMessage): PingResponse; handleDeviceInfo(message: ReachMessage): DeviceInfo; handleDiscoverParameters(message: ReachMessage): Map<number, ParsedParameterInfo>; handleDiscoverParametersExt(message: ReachMessage): Map<number, ParameterExtendedInfo>; /** * Processes an incoming ReachMessage, both updating the global paramValues map and returning a map of the received values (adding onto the existing state if it represents part of an ongoing transaction). * @param message - The ReachMessage to be processed, assumed to contain a ParameterReadResponse in the payload. * @returns A map of the ParameterValues received in the payload, potentially including values received in previous messages from the transaction. */ handleReadParameters(message: ReachMessage): Map<number, ParameterValue>; handleWriteParameters(message: ReachMessage): void; handleDiscoverParameterNotifs(message: ReachMessage): Map<number, ParameterNotifyConfig>; handleConfigParamNotify(message: ReachMessage): void; handleParameterNotification(message: ReachMessage): void; handleDiscoverFiles(message: ReachMessage): Map<number, FileInfo>; handleTransferInit(message: ReachMessage): FileTransferResponse; handleTransferData(message: ReachMessage): { data: number[]; messageNumber: number; }; handleTransferDataNotification(message: ReachMessage): FileTransferDataNotification; handleDiscoverCommands(message: ReachMessage): Map<number, CommandInfo>; handleSendCommand(message: ReachMessage): void; handleCliNotification(message: ReachMessage): void; handleSetTime(message: ReachMessage): void; handleGetTime(message: ReachMessage): TimeGetResponse; handleDiscoverWiFi(message: ReachMessage): DiscoverWiFiResponse; handleWiFiConnection(message: ReachMessage): WiFiConnectionResponse; handleErrorReport(message: ReachMessage): { header: ReachMessageHeader; payload: ErrorReport; }; protected generalErrorHelper(category: string, payload?: any): void; protected responseErrorHelper(category: string, payload?: { result: number; resultMessage?: string; }): void; /** Setters & Getters */ /** * The version of the Reach Protocol the DeviceAccess object is built around. */ get reachProtoVersion(): ProtoVersion; /** * Configures if messages sent should use the deprecated classic header format. */ get classicHeaders(): boolean; set classicHeaders(classic: boolean); /** * The unique transaction ID for an interaction with a Reach device */ get transactionId(): number; set transactionId(id: number); /** * The unique ID for a client of a Reach device */ get clientId(): number; set clientId(id: number); /** * The ID for an endpoint within a Reach device */ get endpointId(): number; set endpointId(value: number); /** * The timeout for a Reach message, in ms. * If a transaction is not acknowledged in some way within this period, the associated Request will error out. */ get transactionTimeout(): number; set transactionTimeout(value: number); /** * Transactions made with the server (device) */ get transactions(): Map<string, Request<any>>; set transactions(value: Map<string, Request<any>>); /** * The most recently received DeviceInfo from a server. */ get deviceInfo(): DeviceInfo | undefined; set deviceInfo(deviceInfo: DeviceInfo | undefined); /** * Known commands reported by the server, keyed by command ID. */ get commandInfos(): Map<number, CommandInfo>; set commandInfos(commandInfos: Map<number, CommandInfo>); hasCommandInfo(commandId: number): boolean; getCommandInfo(commandId: number): CommandInfo | undefined; setCommandInfo(commandId: number, commandInfo: CommandInfo): void; /** * @deprecated Use fileInfos instead. This method will be removed in future versions. */ get fileInfoMap(): Map<number, FileInfo>; /** * Known files reported by the server, keyed by file ID. */ get fileInfos(): Map<number, FileInfo>; /** * @deprecated Use fileInfos instead. This method will be removed in future versions. */ set fileInfoMap(fileInfoMap: Map<number, FileInfo>); set fileInfos(fileInfoMap: Map<number, FileInfo>); /** * @deprecated Use fileTransfers instead. This method will be removed in future versions. */ get fileTransferMap(): Map<number, FileTransfer>; /** * Known ongoing file transfers, keyed by transfer ID. */ get fileTransfers(): Map<number, FileTransfer>; /** * @deprecated Use fileTransfers instead. This method will be removed in future versions. */ set fileTransferMap(fileTransfers: Map<number, FileTransfer>); set fileTransfers(fileTransfers: Map<number, FileTransfer>); hasFileTransfer(transferId: number): boolean; getFileTransfer(transferId: number): FileTransfer | undefined; setFileTransfer(transferId: number, fileTransfer: FileTransfer): void; /** * The ID of the file transfer currently in progress, if one exists. */ get currentFileTransferId(): number | undefined; set currentFileTransferId(id: number | undefined); /** * The network connection used to communicate with a Reach Protocol device. */ get networkAccess(): NetworkAccess; /** * Known parameter info from the server, keyed by parameter ID. */ get paramInfos(): Map<number, ParsedParameterInfo>; set paramInfos(paramInfos: Map<number, ParsedParameterInfo>); isParamInfosEmpty(): boolean; hasParamInfo(parameterId: number): boolean; getParamInfo(parameterId: number): ParsedParameterInfo | undefined; setParamInfo(parameterId: number, paramInfo: ParameterInfo): void; clearParamInfos(): void; /** * Known parameter extended info from the server, keyed by PEI ID. */ get paramExtInfos(): Map<number, ParameterExtendedInfo>; set paramExtInfos(paramExtensions: Map<number, ParameterExtendedInfo>); /** * Known parameter values from the server, keyed by parameter ID. */ get paramValues(): Map<number, ParameterValue>; set paramValues(paramValues: Map<number, ParameterValue>); getParamValue(parameterId: number): ParameterValue | undefined; setParamValue(parameterId: number, paramValue: ParameterValue): void; get paramNotifications(): Map<number, ParameterNotifyConfig>; /** * Known active parameter notifications, keyed by parameter ID. */ set paramNotifications(value: Map<number, ParameterNotifyConfig>); /** * CLI data received from the server or sent by the client, keyed by the timestamp of receipt/sending */ get cliMessages(): Map<Date, CLIData>; set cliMessages(messages: Map<Date, CLIData>); /** * The acknowledgement rate for file transfers. */ get ackRate(): number; set ackRate(ackRate: number); /** * Timeout for file transfer messages, in ms */ get transferTimeout(): number; set transferTimeout(timeoutMs: number); /** Device's reported time as an offset in seconds from the system time, or undefined if not read. */ get timeOffset(): bigint | undefined; set timeOffset(offset: bigint | undefined); /** Device's reported timezone as an offset from UTC in seconds. Undefined if time unread or the device does not have a persistent timezone. */ get timezone(): number | undefined; set timezone(tz: number | undefined); /** Device's time in UTC, or undefined if unread. */ get deviceTime(): Date | undefined; }