@eva-ics/webengine
Version:
EVA ICS HMI Web Engine
916 lines (914 loc) • 27.1 kB
TypeScript
import { Logger } from "bmat/log";
import { SubMap } from "submap";
declare enum SerializationKind {
JSON = "json",
MsgPack = "msgpack"
}
declare enum EvaErrorKind {
NOT_FOUND = -32001,
ACCESS_DENIED = -32002,
SYSTEM_ERROR = -32003,
OTHER = -32004,
NOT_READY = -32005,
UNSUPPORTED = -32006,
CORE_ERROR = -32007,
TIMEOUT = -32008,
INVALID_DATA = -32009,
FUNC_FAILED = -32010,
ABORTED = -32011,
ALREADY_EXISTS = -32012,
BUSY = -32013,
METHOD_NOT_IMPLEMENTED = -32014,
TOKEN_RESTRICTED = -32015,
IO = -32016,
REGISTRY = -32017,
EVAHI_AUTH_REQUIRED = -32018,
ACCESS_DENIED_MORE_DATA_REQUIRED = -32022,
PARSE = -32700,
INVALID_REQUEST = -32600,
METHOD_NOT_FOUND = -32601,
INVALID_PARAMS = -32602,
INTERNAL_RPC = -32603,
BUS_CLIENT_NOT_REGISTERED = -32113,
BUS_DATA = -32114,
BUS_IO = -32115,
BUS_OTHER = -32116,
BUS_NOT_SUPPORTED = -32117,
BUS_BUSY = -32118,
BUS_NOT_DELIVERED = -32119,
BUS_TIMEOUT = -32120,
BUS_ACCESS = -32121
}
declare enum EventKind {
HeartbeatSuccess = "heartbeat.success",
HeartbeatError = "heartbeat.error",
LoginSuccess = "login.success",
LoginFailed = "login.failed",
LoginOTPRequired = "login.otp_required",
LoginOTPInvalid = "login.otp_invalid",
LoginOTPSetup = "login.otp_setup",
WsEvent = "ws.event",
ServerReload = "server.reload",
ServerRestart = "server.restart",
LogRecord = "log.record",
LogPostProcess = "log.postprocess",
WASMError = "wasm.error"
}
declare enum StateProp {
Status = "status",
Value = "value",
Any = "any"
}
interface EvaConfig {
engine?: EvaEngineConfig;
}
interface EvaEngineConfig {
api_uri?: string;
apikey?: string;
debug?: boolean | number;
login?: string;
password?: string;
set_auth_cookies?: boolean;
state_updates?: boolean | Array<string>;
wasm?: boolean | string;
ws_mode?: boolean;
log_params?: LogParams;
interval: {
[key in IntervalKind]: number;
};
}
interface OTPParams {
size?: number;
issuer?: string;
user?: string;
xtr?: string;
}
interface HiQRParams {
size?: number;
url?: string;
user?: string;
password?: string;
}
interface LogRecord {
dt: string;
h: string;
l: number;
lvl: string;
mod: string;
msg: string;
t: number;
th: string | null;
}
interface SvcMessage {
kind: string;
svc: string;
message?: string;
value?: string;
}
interface JsonRpcRequest {
jsonrpc: string;
method: string;
params?: object;
id: number;
}
interface External {
fetch?: any;
WebSocket?: any;
QRious?: any;
msgpack?: any;
}
interface ActionResult {
elapsed: number;
exitcode: number | null;
finished: boolean;
node: string;
oid: string;
params: any;
priority: number;
status: string;
svc: string;
time: any;
uuid: string;
out: null | string;
err: null | string;
}
interface LogParams {
level: number;
records: number;
}
interface ItemState {
act?: number;
connected?: boolean;
enabled?: boolean;
ieid?: Array<number>;
meta?: object;
node?: string;
oid?: string;
status?: number | null;
t?: number;
value: any;
}
interface Watcher {
func: (state: ItemState) => void;
prot: boolean;
}
declare enum IntervalKind {
AjaxReload = "ajax_reload",
AjaxLogReload = "log_reload",
ActionWatch = "action_watch",
Heartbeat = "heartbeat",
Reload = "reload",
Restart = "restart",
WSBufTTL = "ws_buf_ttl"
}
declare class EvaError {
code: number;
message?: string;
data?: any;
constructor(code: number, message?: string, data?: any);
}
declare class EvaBulkRequestPartHandler {
fn_ok?: (result: any) => void;
fn_err?: (result: any) => void;
constructor();
then(fn_ok: (result: any) => void): this;
catch(fn_err: (err: any) => void): this;
}
declare class EvaBulkRequest {
requests: Map<number, EvaBulkRequestPartHandler>;
payload: Array<any>;
eva: Eva;
constructor(eva: Eva);
/**
* Prepare API function call for bulk calling
*
* Calls any available SFA API function
*
* @param p1 item OID (if required) or API call params
* @param p2 extra call params or empty object
* @param fn_ok function which is executed on successfull call
* @parma fn_err function which is executed on error
*
* @returns Part handler object
*/
prepare(method: string, p1: string | object, p2?: object): EvaBulkRequestPartHandler;
/**
* Perform bulk API call
*/
call(): Promise<boolean>;
}
declare class Eva_ACTION {
eva: Eva;
constructor(eva: Eva);
/**
* Call unit action with value=1
*
* @param oid {string} unit OID
* @param wait {boolean} wait until the action is completed (default: true)
*/
start(oid: string, wait?: boolean): Promise<ActionResult>;
/**
* Call unit action with value=0
*
* @param oid {string} unit OID
* @param wait {boolean} wait until the action is completed (default: true)
*/
stop(oid: string, wait?: boolean): Promise<ActionResult>;
/**
* Call unit action to toggle its value
*
* @param oid {string} unit OID
* @param wait {boolean} wait until the action is completed (default: true)
*/
toggle(oid: string, wait?: boolean): Promise<ActionResult>;
/**
* Call unit action
*
* @param oid {string} unit OID
* @param params {object} action params
* @param wait {boolean} wait until the action is completed (default: true)
*/
exec(oid: string, params: object, wait?: boolean): Promise<ActionResult>;
/**
* Terminate all unit actions
*
* @param oid {string} unit OID
*/
kill(oid: string): Promise<void>;
/**
* Terminate a unit action
*
* @param uuid {string} action uuid
*/
terminate(uuid: string): Promise<void>;
/**
* Run lmacro
*
* @param oid {string} lmacro oid
* @param params {object} call params
* @param wait {boolean} wait until completed (default: true)
*/
run(oid: string, params?: object, wait?: boolean): Promise<ActionResult>;
_act(method: string, oid: string, params?: object, wait?: boolean): Promise<ActionResult>;
}
declare class Eva_LVAR {
eva: Eva;
constructor(eva: Eva);
/**
* Reset lvar (set status to 1)
*
* @param oid {string} lvar oid
*/
reset(oid: string): Promise<void>;
/**
* Clear lvar (set status to 0)
*
* @param oid {string} lvar oid
*/
clear(oid: string): Promise<void>;
/**
* Toggle lvar status
*
* @param oid {string} lvar oid
*/
toggle(oid: string): Promise<void>;
/**
* Increment lvar value
*
* @param oid {string} lvar oid
*
* @returns the new value
*/
incr(oid: string): Promise<number>;
/**
* Decrement lvar value
*
* @param oid {string} lvar oid
*
* @returns the new value
*/
decr(oid: string): Promise<number>;
/**
* Set lvar state
*
* @param oid {string} lvar oid
* @param status {numberr} lvar status
* @param value lvar value
*/
set(oid: string, status?: number, value?: any): Promise<void>;
/**
* Set lvar status
*
* @param oid {string} lvar oid
* @param status {number} lvar status
*/
set_status(oid: string, status: number): Promise<void>;
/**
* Set lvar value
*
* @param oid {string} lvar oid
* @param value lvar value
*/
set_value(oid: string, value: any): Promise<void>;
/**
* Get lvar expiration time left
*
* @param lvar_oid {string} lvar OID
*
* @returns seconds to expiration, -1 if expired, -2 if stopped
*/
expires(lvar_oid: string): number | null | undefined;
}
/**
* Binary stream parameters
*/
interface EvaStreamParameters {
/**
* OID the data is streamed from
*/
oid: string;
/**
* Name of the stream, used for identification, unique
*/
name: string;
/**
* On start callback
*/
onStart?: () => void;
/**
* On data callback
*/
onData?: (data: ArrayBuffer) => void;
/**
* On error callback
*/
onError?: (err: EvaError) => void;
/**
* On end of stream callback, the stream is not closed and may receive more
* data, but the handler must be prepared certain stream parameters may
* change
*/
onEOS?: () => void;
}
declare class _EvaStream {
oid: string;
eva: Eva;
name: string;
ws: WebSocket | null;
onStart: () => void;
onData: (data: ArrayBuffer) => void;
onError: (err: EvaError) => void;
onEOS: () => void;
constructor(oid: string, name: string, eva: Eva);
_restart(): void;
_start(): void;
_stop(): void;
}
declare class _EvaStateBlock {
state_updates: boolean | Array<string>;
eva: Eva;
name: string;
_ajax_reloader: any;
constructor(name: string, state_updates: boolean | Array<string>, engine: Eva);
_start(): void;
_restart(): void;
_stop(): void;
}
declare enum TokenMode {
Normal = "normal",
ReadOnly = "readonly"
}
declare enum SessionAuthKind {
Token = "token",
Key = "key",
Login = "login",
No = "unauthorized"
}
interface SessionACI {
acl: string;
auth: SessionAuthKind;
auth_svc: string;
token_mode: TokenMode;
u: string;
}
interface ACLProp {
items: Array<string>;
pvt: Array<string>;
rpvt: Array<string>;
}
declare enum ACLOp {
Log = "log",
Developer = "developer",
Moderator = "moderator",
Supervisor = "supervisor"
}
interface SessionACL {
admin?: boolean;
deny_read: ACLProp;
deny_write: ACLProp;
from: Array<string>;
id: string;
meta: {
[key: string]: Array<any>;
};
ops: Array<ACLOp>;
read: ACLProp;
write: ACLProp;
}
interface ServerInfo {
aci: SessionACI;
acl: SessionACL;
build: number;
ok: boolean;
hmi_svc_id: string;
num_cpus: number;
product_code: string;
product_name: string;
system_name: string;
time: number;
uptime: number;
version: string;
}
declare enum LoginState {
Active = "active",
Starting = "starting",
Stopping = "stopping",
Inactive = "inactive",
Failed = "failed",
OTPRequired = "otp.required",
OTPInvalid = "otp.invalid",
OTPSetup = "otp.setup"
}
interface SessionState {
login: LoginState;
error: EvaError | null;
otp: string | null;
}
/**
* The default session state
*/
declare const defaultSessionState: () => SessionState;
type EventHandler = (topic: string, event: any) => void;
declare enum EventTopic {
ItemState = "ST",
Server = "SERVER",
Supervisor = "SUPERVISOR",
WeSession = "WE/SESSION",
WeItemState = "WE/ST"
}
declare class Eva {
#private;
action: Eva_ACTION;
lvar: Eva_LVAR;
api_uri: string;
ws_uri: string;
api_token: string;
authorized_user: string | null;
clear_unavailable: boolean;
debug: boolean | number;
allow_logged_in_calls_only: boolean;
external: External;
evajw: any;
in_evaHI: boolean;
log_params: LogParams;
log: Logger;
logged_in: boolean;
login: string;
login_xopts: object | null;
log_level_names: Map<number, string>;
set_auth_cookies: boolean;
state_updates: boolean | Array<string>;
tsdiff: number;
version: string;
wasm: boolean | string;
ws_mode: boolean;
server_info: ServerInfo | null;
ignore_password_set_on_next_login: boolean;
_event_map: SubMap<EventHandler> | null;
_api_call_id: number;
_handlers: Map<EventKind, (...args: any[]) => void | boolean>;
_intervals: Map<IntervalKind, number>;
_ws_handler_registered: boolean;
_heartbeat_reloader: any;
_ajax_reloader: any;
_log_reloader: any;
_scheduled_restarter: any;
_states: Map<string, Map<string, ItemState>>;
_blocks: Map<string, _EvaStateBlock>;
_streams: Map<string, _EvaStream>;
_last_ping: Map<string, number | null>;
_last_pong: Map<string, number | null>;
ws: Map<string, WebSocket>;
_action_states: Map<string, ActionResult>;
_action_watch_functions: Map<String, Array<(result: ActionResult | EvaError) => void>>;
_log_subscribed: boolean;
_log_started: boolean;
_log_first_load: boolean;
_log_loaded: boolean;
_update_state_functions: Map<string, Array<Watcher>>;
_update_state_mask_functions: Map<string, Array<Watcher>>;
_lr2p: Array<LogRecord>;
constructor();
/**
* Enables pub/sub event map. Usually not required to be called manually, as
* called automatically as soon as there is a subscription performed.
*/
enable_event_map(): void;
/**
* Subscribe to an event topic
*
* @param topic {string} event topic
* @param fn {EventHandler} event handler
*
* @returns true if subscription was successful
*/
subscribe_event_topic(topic: string, fn: EventHandler): boolean;
/**
* Subscribe to multiple event topics
*
* @param topics {Array<string>} event topics
* @param fn {EventHandler} event handler
* @returns true if subscription was successful
*/
subscribe_event_topics(topics: Array<string>, fn: EventHandler): boolean;
/**
* Unsubscribe from an event topic
*
* @param topic {string} event topic
* @param fn {EventHandler} event handler
*/
unsubscribe_event_topic(topic: string, fn: EventHandler): void;
/**
* Unsubscribe from multiple event topics
*
* @param topics {Array<string>} event topics
* @param fn {EventHandler} event handler
*/
unsubscribe_event_topics(topics: Array<string>, fn: EventHandler): void;
/**
* Unsubscribe from all event topics
*
* @param fn {EventHandler} event handler
*/
unsubscribe_all_event_topics(fn: EventHandler): void;
_push_event_topic(topic: string, data: any): void;
/**
* Set engine login credentials
*
* @param login {string|null} login
* @param password {string|null} password
*/
set_login_password(login?: string | null, password?: string | null): void;
/**
* Set/clear engine API key
*
* @param apikey {string | null} API key
*/
set_api_key(apikey?: string | null): void;
/**
* Is engine password set
*
* @returns true if password is set
*/
is_password_set(): boolean;
/**
* Is engine authentication set
*
* @returns true if auth is set
*/
is_auth_set(): boolean;
/**
* Clear engine authenication credentials
*/
clear_auth(): void;
/**
* Start a binary stream
*
* @param params {EvaStreamParameters} stream parameters
*/
start_stream(params: EvaStreamParameters): void;
/**
* Stop a binary stream
*
* @param name {string} stream name
*/
stop_stream(name: string): void;
/**
* Register a state block
*
* @param name {string} block name
* @param state_updates {boolean | Array<string>} state updates
*/
register_state_block(name: string, state_updates: boolean | Array<string>): void;
/**
* Unregister a state block
*
* @param name {string} block name
*/
unregister_state_block(name: string): void;
/**
* Unregister all state blocks
*/
unregister_all_state_blocks(): void;
bulk_request(): EvaBulkRequest;
/**
* Get engine mode
* @returns "js" or "wasm"
*/
get_mode(): string;
/**
* Start the engine
*
* After calling the function authenticates user, opens a WebSocket (in
* case of WS mode) or schedule AJAXs refresh interval.
*/
start(): void;
_start_engine(): boolean;
/**
* Get system name
*
* @returns the system name or null if the engine is not logged in
*/
system_name(): string;
/**
* Sleep the number of seconds
*
* @param sec {number} seconds to sleep
*/
sleep(sec: number): Promise<void>;
/**
* Start log processing
*
* Starts log processing. The engine must be already logged in.
*
* @param log_level {number} log processing level (optional)
*/
log_start(log_level?: number): void;
/**
* Set state updates without restart required
*
* @param state_updates {boolean} true/false or a string array
* @param clear_existing {boolean} clear existing states
*
*/
set_state_updates(state_updates: Array<string> | boolean, clear_existing?: boolean): Promise<void>;
/**
* Change log processing level
*
* @param log_level {number} log processing level
*/
set_log_level(log_level: number): void;
/**
* Restart the engine
*
* e.g. used on heartbeat error or if subscription parameters are changed
*/
restart(): void;
/**
* Erase auth token cookie
*
* It is recommended to call this function when login form is displayed to
* prevent old token caching
*/
erase_token_cookie(): void;
/**
* Load JSON configuration
*
* @param config_path {string} config path (default: config.json)
*
* @returns Promise object
*/
load_config(config_path?: string): Promise<EvaConfig>;
/**
* Apply configuration from an object
*
* @param config {object} configuration object
*/
apply_config(config: EvaConfig): void;
/**
* Calls any available API function
*
* @param {Object} options - The options for the API call.
* @param {string} options.method - The API method to call.
* @param {object|string|string[]} [options.params] - Parameters to pass to the API method.
* @param {SerializationKind} [options.serialization_kind] - Optional serialization kind for the request.
* @returns {Promise<any>} - A promise that resolves with the result of the API call.
*/
api_call({ method, params, serialization_kind }: {
method: string;
params?: object | string | Array<string>;
serialization_kind?: SerializationKind;
}): Promise<any>;
/**
* Call API function
*
* Calls any available API function (old version, may be deprecated soon)
*
* @param method {string} API method
* @param p1 {object} call parameters. if specified as a string/object, transformed to i=val
* @param p2 {object} additional call parameters if p1 is a string
*
* @returns Promise object
*/
call(method: string, p1?: object | string | Array<string>, p2?: object, serialization_kind?: SerializationKind): Promise<any>;
/**
* Ask server to set the token read-only (e.g. after idle)
*
* (EVA ICS 3.3.2+)
*
* the current mode can be obtained from $eva.server_info.aci.token_mode
*/
set_readonly(): Promise<void>;
/**
* Ask server to return the token to normal mode
*
* (EVA ICS 3.3.2+)
*
* @param u {string} login
* @param p {string} password
* @param xopts {object} extra options (e.g. OTP)
*/
set_normal(user?: string, password?: string, xopts?: object): boolean;
error_handler(err: EvaError, method: string): void;
/**
* Set event handler function
*
* A single kind of event can have a single handler only
*
* @param event {EventKind} engine event kind
* @param func {function} function called on event
*/
on(event: EventKind | string, func: (...args: any[]) => void | boolean): void;
/**
* Set intervals
*
* @param interval_id {IntervalKind} interval kind
* @param value {number} interval value (in seconds)
*/
set_interval(interval_id: IntervalKind, value: number): void;
date_local_to_server(date: Date): Date;
date_server_to_local(date: Date): Date;
/**
* Watch item state updates
*
* Registers the function to be called in case of state change event (or at
* first state load).
*
* If state is already loaded, function will be called immediately. One item
* (or item mask, set with "*" or a traditional OID mask) can have multiple
* watchers.
*
* @param oid {string} item oid (e.g. sensor:env/temp1, sensor:env/\*, sensor:+/temp1)
* @param func {function} function to be called
* @param ignore_initial {boolean} skip initial state callback
* @param prot {boolean} protected (not removed on global unwatch)
*
*/
watch(oid: string, func: (state: ItemState) => void, ignore_initial?: boolean, prot?: boolean): void;
/**
* Watch action state by uuid
*
* Registers the function to be called in case of action status change
* event (or at first state load).
*
* If status is already loaded, function will be called immediately.
* Otherwise status is polled from the server with "action_watch" interval
* (default: 500ms).
*
* There is no unwatch function as watching is stopped as soon as the
* action is completed (or server error is occurred)
*
* @param uuid {string} action uuid
* @param func {function} function to be called
*
*/
watch_action(uuid: string, func: (result: ActionResult | EvaError) => void): void;
/**
* Stop watching item state updates
*
* If item oid or function is not specified, all watching functions are
* removed for a single oid (mask) or for all the items watched.
*
* @param oid {string} item OID or a mask
* @param func {function} function to be removed
*/
unwatch(oid?: string, func?: (state: ItemState) => void): void;
_unwatch_func(oid: string, func?: (state: ItemState) => void): void;
_unwatch_all(oid: string): void;
_unwatch_mask_func(oid: string, func: (state: ItemState) => void): void;
_unwatch_mask_all(oid: string): void;
/**
* Get item status
*
* @param oid {string} item OID
*
* @returns item status(int) or undefined if no object found
*/
status(oid: string): number | null | undefined;
/**
* Get item value
*
* @param oid {string} item OID
*
* @returns item value or undefined if no item found
*/
value(oid: string): any | undefined;
/**
* Get item state
*
* @param oid {string} item OID or OID mask
*
* @returns state object or undefined if no item found
*/
state(oid: string): ItemState | Array<ItemState> | undefined;
_state(oid: string): ItemState;
_states_by_mask(oid_mask: string): Array<ItemState>;
/**
* Stop the engine
*
* After calling the function closes open WebSocket if available, stops all
* workers then tries to close the server session
*
* @param keep_auth {boolean} keep authentication cookies and token
*
* @returns Promise object
*/
stop(keep_auth?: boolean, further_restart?: boolean): Promise<void>;
_inject_evajw(mod: any): boolean;
_init_block(block: string): void;
_init_block_states(block: string): void;
_delete_block(block: string): void;
_delete_block_states(block: string): void;
_start_evajw(): void;
_is_ws_handler_registered(): boolean;
_clear_watchers(): void;
_report_cleanup(block: string): void;
_clear_states(block?: string): void;
_clear_last_pings(): void;
_clear(): void;
_critical(message: any, write_on_screen?: boolean, throw_err?: boolean): void;
_prepare_api_call(method: string, params?: object): JsonRpcRequest;
_api_call(method: string, params?: object, serialization_kind?: SerializationKind): Promise<any>;
_heartbeat(on_login: boolean): Promise<void>;
_load_log_entries(postprocess: boolean): void;
_schedule_restart(): void;
_cancel_scheduled_restart(): void;
_stop_engine(): void;
_prepare_call_params(params?: any): object;
_set_token_cookie(): void;
_process_loaded_states(data: Array<ItemState>, clear_unavailable: boolean, block: string): void;
_load_states(state_updates: boolean | Array<string>, block: string): Promise<void>;
_get_ws_uri(): string;
_start_ws(state_updates: boolean | Array<string>, block: string): Promise<void>;
_set_ws_log_level(level: number): void;
_process_ws_frame_pong(block: string): void;
_process_ws_frame_log(data: Array<LogRecord> | LogRecord): void;
_process_ws(payload: string, block: string): void;
_preprocess_log_record(record: LogRecord): void;
_clear_state(oid: string, block: string): void;
_process_state(state: ItemState, is_update: boolean, block: string): void;
_invoke_handler(handler: EventKind, ...args: any[]): void | boolean;
_oid_match(oid: string, mask: string): boolean;
_debug(method: string, ...data: any[]): void;
parse_svc_message(msg?: string): SvcMessage | null;
/**
* OTP setup code
*
* @param ctx html <canvas /> element or id to generate QR code in
* @param secret {string} OTP secret
* @param params {OTPParams} additional parameters
*
* @returns QRious QR object if QR code is generated
*/
otpQR(ctx: object | string, secret: string, params?: OTPParams): any;
_deserializePromise: (response: any, serialization_kind: SerializationKind) => Promise<any>;
/**
* QR code for EvaHI
*
* Generates QR code for :doc:`EvaHI</evahi>`-compatible apps (e.g. for Eva
* ICS Control Center mobile app for Android). Current engine session
* must be authorized using user login. If $eva.password is defined, QR
* code also contain password value. Requires qrious js library.
*
* @param ctx html <canvas /> element or id to generate QR code in
* @param params {HiQRParams} additional parameters
*
* @returns QRious QR object if QR code is generated
*/
hiQR(ctx: object | string, params?: HiQRParams): any;
/**
* Registers the global object window.$eva
*/
register_globals(): void;
/**
* Registers global objects + legacy globals
*/
register_legacy_globals(): void;
}
/**
* Disable tab freeze
*
* @param keep_visible {boolean} keep special elements visible
*/
declare function disableTabFreeze(keep_visible?: boolean): void;
export { Eva, EvaError, EvaErrorKind, EvaStreamParameters, SerializationKind, TokenMode, SessionAuthKind, SessionACI, ACLProp, ACLOp, SessionACL, ServerInfo, LoginState, SessionState, defaultSessionState, EventHandler, EventTopic, EventKind, IntervalKind, ActionResult, ItemState, LogParams, LogRecord, OTPParams, HiQRParams, StateProp, SvcMessage, EvaConfig, EvaEngineConfig, Watcher, disableTabFreeze };