Initial commit
This commit is contained in:
39
lib/consts.js
Normal file
39
lib/consts.js
Normal file
@@ -0,0 +1,39 @@
|
||||
'use strict';
|
||||
const dayOfWeeksFull = {
|
||||
'en': ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
||||
'de': ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
|
||||
'ru': ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота']
|
||||
};
|
||||
const dayOfWeeksShort = {
|
||||
'en': ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
|
||||
'de': ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
|
||||
'ru': ['Вс', 'По', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб']
|
||||
};
|
||||
|
||||
const monthFull = {
|
||||
'en': ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
||||
'de': ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
|
||||
'ru': ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь']
|
||||
};
|
||||
const monthFullGen = {
|
||||
'en': ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
||||
'de': ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
|
||||
'ru': ['Января', 'Февраля', 'Марта', 'Апреля', 'Мая', 'Июня', 'Июля', 'Августа', 'Сентября', 'Октября', 'Ноября', 'Декабря']
|
||||
};
|
||||
const monthShort = {
|
||||
'en': ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec'],
|
||||
'de': ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
|
||||
'ru': ['Янв', 'Фев', 'Март', 'Апр', 'Май', 'Июнь', 'Июль', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек']
|
||||
};
|
||||
const astroList = ['sunrise', 'sunset', 'sunriseEnd', 'sunsetStart', 'dawn', 'dusk', 'nauticalDawn', 'nauticalDusk', 'nightEnd', 'night', 'goldenHourEnd', 'goldenHour'];
|
||||
const astroListLow = ['sunrise', 'sunset', 'sunriseend', 'sunsetstart', 'dawn', 'dusk', 'nauticaldawn', 'nauticaldusk', 'nightend', 'night', 'goldenhourend', 'goldenhour'];
|
||||
|
||||
module.exports = {
|
||||
dayOfWeeksFull,
|
||||
dayOfWeeksShort,
|
||||
monthFull,
|
||||
monthFullGen,
|
||||
monthShort,
|
||||
astroList,
|
||||
astroListLow
|
||||
};
|
||||
104
lib/convert.js
Normal file
104
lib/convert.js
Normal file
@@ -0,0 +1,104 @@
|
||||
'use strict';
|
||||
// this file is used by controller when build uploads
|
||||
function stringify(data) {
|
||||
let obj = data.data;
|
||||
let id = data.id;
|
||||
if (data.data.type === 'channel') {
|
||||
id = id.replace(/\./g, '/').substring('script.js.'.length) + '/_dir.json';
|
||||
obj = JSON.stringify(obj, null, 2);
|
||||
} else if (data.data.type === 'script') {
|
||||
id = id.replace(/\./g, '/').substring('script.js.'.length) + '.json';
|
||||
if (obj.common && obj.common.source) {
|
||||
const source = obj.common.source;
|
||||
if (obj.common.enabled) delete obj.common.enabled;
|
||||
if (obj.common.engine === 'system.adapter.javascript.0') delete obj.common.engine;
|
||||
if (obj.common.engineType === 'Javascript/js') delete obj.common.engineType;
|
||||
delete obj.common.name;
|
||||
delete obj.common.source;
|
||||
if (JSON.stringify(obj.common) !== '{}') {
|
||||
obj = '/* -- do not edit following lines - START --\n' + JSON.stringify(obj.common, null, 2) + '\n' + '-- do not edit previous lines - END --*/\n' + source;
|
||||
} else {
|
||||
obj = source;
|
||||
}
|
||||
} else {
|
||||
obj = JSON.stringify(obj, null, 2);
|
||||
}
|
||||
} else if (data.data.type === 'script') {
|
||||
id = id.replace(/\./g, '/').substring('script.js.'.length) + '.json';
|
||||
obj = JSON.stringify(obj, null, 2);
|
||||
}
|
||||
|
||||
return {id: id, data: obj};
|
||||
}
|
||||
|
||||
function parse(data) {
|
||||
let obj = data.data;
|
||||
let id = data.id;
|
||||
let error;
|
||||
let name;
|
||||
if (id[id.length - 1] === '/') id = id.substring(0, id.length - 1);
|
||||
|
||||
if (!id.match(/\.json$/)) return null;
|
||||
|
||||
if (id.match(/_dir\.json$/)) {
|
||||
name = id.substring(0, id.length - '/_dir.json'.length).replace(/\//g, '.');
|
||||
|
||||
try {
|
||||
obj = JSON.parse(obj);
|
||||
} catch (e) {
|
||||
error = 'Cannot parse object "' + name + '": ' + e;
|
||||
obj = {
|
||||
common: {
|
||||
name: name.split('.').pop()
|
||||
},
|
||||
type: 'channel',
|
||||
_id: 'script.js.' + name
|
||||
};
|
||||
}
|
||||
id = 'script.js.' + name;
|
||||
} else {
|
||||
//script
|
||||
name = id.substring(0, id.length - '.json'.length).replace(/\//g, '.');
|
||||
let source;
|
||||
if (obj.match(/^\/\*\s--\sdo\snot/)) {
|
||||
obj = obj.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
||||
const lines = obj.split('\n');
|
||||
let strignObj = '';
|
||||
let line = 1;
|
||||
while (line < lines.length) {
|
||||
if (lines[line].match(/^--\sdo\snot/)) {
|
||||
break;
|
||||
}
|
||||
strignObj += lines[line];
|
||||
line++;
|
||||
}
|
||||
lines.splice(0, line + 1);
|
||||
source = lines.join('\n');
|
||||
try {
|
||||
obj = {};
|
||||
obj.common = JSON.parse(strignObj);
|
||||
obj.common.source = source;
|
||||
} catch (e) {
|
||||
error = 'Cannot parse object "' + id + '": ' + e;
|
||||
}
|
||||
} else {
|
||||
source = obj;
|
||||
obj = null;
|
||||
}
|
||||
|
||||
obj = obj || {};
|
||||
obj.common = obj.common || {};
|
||||
obj._id = 'script.js.' + name;
|
||||
obj.type = 'script';
|
||||
obj.common.name = name.split('.').pop();
|
||||
obj.common.enabled = (obj.common.enabled === undefined) ? true : obj.common.enabled;
|
||||
obj.common.engine = obj.common.engine || 'system.adapter.javascript.0';
|
||||
obj.common.engineType = obj.common.engineType || 'Javascript/js';
|
||||
obj.common.source = obj.common.source || source;
|
||||
id = 'script.js.' + name;
|
||||
}
|
||||
|
||||
return {id: id, data: obj, error: error};
|
||||
}
|
||||
module.exports.stringify = stringify;
|
||||
module.exports.parse = parse;
|
||||
174
lib/eventObj.js
Normal file
174
lib/eventObj.js
Normal file
@@ -0,0 +1,174 @@
|
||||
'use strict';
|
||||
const cacheObjectEnums = {};
|
||||
let inited = false;
|
||||
|
||||
function getObjectEnumsSync(context, idObj, enumIds, enumNames) {
|
||||
if (!enumIds) enumIds = [];
|
||||
if (!enumNames) enumNames = [];
|
||||
|
||||
if (cacheObjectEnums[idObj]) {
|
||||
for (let j = 0; j < cacheObjectEnums[idObj].enumIds.length; j++) {
|
||||
if (enumIds.indexOf(cacheObjectEnums[idObj].enumIds[j]) === -1) enumIds.push(cacheObjectEnums[idObj].enumIds[j]);
|
||||
}
|
||||
for (let j = 0; j < cacheObjectEnums[idObj].enumNames.length; j++) {
|
||||
if (enumNames.indexOf(cacheObjectEnums[idObj].enumNames[j]) === -1) enumNames.push(cacheObjectEnums[idObj].enumNames[j]);
|
||||
}
|
||||
return {enumIds: enumIds, enumNames: enumNames};
|
||||
}
|
||||
|
||||
|
||||
for (let i = 0, l = context.enums.length; i < l; i++) {
|
||||
if (context.objects[context.enums[i]] &&
|
||||
context.objects[context.enums[i]].common &&
|
||||
context.objects[context.enums[i]].common.members &&
|
||||
context.objects[context.enums[i]].common.members.indexOf(idObj) !== -1) {
|
||||
if (enumIds.indexOf(context.enums[i]) === -1) enumIds.push(context.enums[i]);
|
||||
if (enumNames.indexOf(context.objects[context.enums[i]].common.name) === -1) enumNames.push(context.objects[context.enums[i]].common.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (context.objects[idObj]) {
|
||||
const pos = idObj.lastIndexOf('.');
|
||||
if (pos !== -1) {
|
||||
const parent = idObj.substring(0, pos);
|
||||
if (parent && context.objects[parent]) {
|
||||
return getObjectEnumsSync(context, parent, enumIds, enumNames);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cacheObjectEnums[idObj] = {enumIds: enumIds, enumNames: enumNames};
|
||||
return cacheObjectEnums[idObj];
|
||||
}
|
||||
|
||||
function doGetter(obj, name, ret) {
|
||||
//adapter.log.debug('getter: ' + name + ' returns ' + ret);
|
||||
Object.defineProperty(obj, name, {value: ret});
|
||||
return ret;
|
||||
}
|
||||
|
||||
function EventObj(id, state, oldState) {
|
||||
if (!(this instanceof EventObj)) return new EventObj(id, state, oldState);
|
||||
this.id = id;
|
||||
this.newState = {
|
||||
val: state.val,
|
||||
ts: state.ts,
|
||||
ack: state.ack,
|
||||
lc: state.lc,
|
||||
from: state.from
|
||||
};
|
||||
//if (oldState === undefined) oldState = {};
|
||||
if (!oldState) {
|
||||
this.oldState = {
|
||||
val: undefined,
|
||||
ts: undefined,
|
||||
ack: undefined,
|
||||
lc: undefined,
|
||||
from: undefined
|
||||
};
|
||||
} else {
|
||||
this.oldState = {
|
||||
val: oldState.val,
|
||||
ts: oldState.ts,
|
||||
ack: oldState.ack,
|
||||
lc: oldState.lc,
|
||||
from: oldState.from
|
||||
};
|
||||
}
|
||||
this.state = this.newState;
|
||||
}
|
||||
|
||||
function createEventObject(context, id, state, oldState) {
|
||||
if (!inited) {
|
||||
inited = true;
|
||||
const eventObjectProperties = {
|
||||
common: {
|
||||
get: function () {
|
||||
const ret = context.objects[this.id] ? context.objects[this.id].common : {};
|
||||
return doGetter(this, 'common', ret);
|
||||
},
|
||||
configurable: true
|
||||
},
|
||||
native: {
|
||||
get: function () {
|
||||
const ret = context.objects[this.id] ? context.objects[this.id].native : {};
|
||||
return doGetter(this, 'native', ret);
|
||||
},
|
||||
configurable: true
|
||||
},
|
||||
name: {
|
||||
get: function () {
|
||||
const ret = this.common ? this.common.name : null;
|
||||
return doGetter(this, 'name', ret);
|
||||
},
|
||||
configurable: true
|
||||
},
|
||||
channelId: {
|
||||
get: function () {
|
||||
const ret = this.id.replace (/\.*[^.]+$/, '');
|
||||
return doGetter(this, 'channelId', context.objects[ret] ? ret : null);
|
||||
},
|
||||
configurable: true
|
||||
},
|
||||
channelName: {
|
||||
get: function () {
|
||||
const channelId = this.channelId;
|
||||
const ret = channelId && context.objects[channelId].common ? context.objects[channelId].common.name : null;
|
||||
return doGetter(this, 'channelName', ret);
|
||||
},
|
||||
configurable: true
|
||||
},
|
||||
deviceId: {
|
||||
get: function () {
|
||||
let deviceId;
|
||||
const channelId = this.channelId;
|
||||
if (!channelId || !(deviceId = channelId.replace (/\.*[^.]+$/, '')) || !context.objects[deviceId]) {
|
||||
Object.defineProperty(this, 'deviceName', { value: null });
|
||||
return doGetter(this, 'deviceId', null);
|
||||
}
|
||||
return doGetter(this, 'deviceId', deviceId);
|
||||
},
|
||||
configurable: true
|
||||
},
|
||||
deviceName: {
|
||||
get: function () {
|
||||
const deviceId = this.deviceId;
|
||||
const ret = deviceId && context.objects[deviceId].common ? context.objects[deviceId].common.name : null;
|
||||
return doGetter(this, 'deviceName', ret);
|
||||
},
|
||||
configurable: true
|
||||
},
|
||||
enumIds: {
|
||||
get: function () {
|
||||
if (!context.isEnums) return undefined;
|
||||
let enumIds = {};
|
||||
let enumNames = {};
|
||||
getObjectEnumsSync(context, this.id, enumIds, enumNames);
|
||||
Object.defineProperty(this, 'enumNames', {value: enumNames});
|
||||
return doGetter(this, 'enumIds', enumIds);
|
||||
},
|
||||
configurable: true
|
||||
},
|
||||
enumNames: {
|
||||
get: function () {
|
||||
if (!context.isEnums) return undefined;
|
||||
let enumIds = {};
|
||||
let enumNames = {};
|
||||
getObjectEnumsSync(context, this.id, enumIds, enumNames);
|
||||
Object.defineProperty(this, 'enumIds', {value: enumIds});
|
||||
return doGetter(this, 'enumNames', enumNames);
|
||||
},
|
||||
configurable: true
|
||||
}
|
||||
};
|
||||
Object.defineProperties(EventObj.prototype, eventObjectProperties);
|
||||
inited = true;
|
||||
}
|
||||
|
||||
return new EventObj(id, state, oldState);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createEventObject,
|
||||
getObjectEnumsSync
|
||||
};
|
||||
799
lib/javascript.d.ts
vendored
Normal file
799
lib/javascript.d.ts
vendored
Normal file
@@ -0,0 +1,799 @@
|
||||
// import all modules that are available in the sandbox
|
||||
// this has the nice side effect that we may augment the global scope
|
||||
import child_process = require("child_process");
|
||||
|
||||
type EmptyCallback = () => void;
|
||||
type ErrorCallback = (err?: string) => void;
|
||||
type GenericCallback<T> = (err: string | null, result?: T) => void;
|
||||
|
||||
// tslint:disable:no-namespace
|
||||
declare global {
|
||||
|
||||
namespace iobJS {
|
||||
|
||||
enum StateQuality {
|
||||
good = 0x00, // or undefined or null
|
||||
bad = 0x01,
|
||||
general_problem = 0x01,
|
||||
general_device_problem = 0x41,
|
||||
general_sensor_problem = 0x81,
|
||||
device_not_connected = 0x42,
|
||||
sensor_not_connected = 0x82,
|
||||
device_reports_error = 0x44,
|
||||
sensor_reports_error = 0x84,
|
||||
}
|
||||
|
||||
interface State {
|
||||
/** The value of the state. */
|
||||
val: any;
|
||||
|
||||
/** Direction flag: false for desired value and true for actual value. Default: false. */
|
||||
ack: boolean;
|
||||
|
||||
/** Unix timestamp. Default: current time */
|
||||
ts: number;
|
||||
|
||||
/** Unix timestamp of the last time the value changed */
|
||||
lc: number;
|
||||
|
||||
/** Name of the adapter instance which set the value, e.g. "system.adapter.web.0" */
|
||||
from: string;
|
||||
|
||||
/** Optional time in seconds after which the state is reset to null */
|
||||
expire?: number;
|
||||
|
||||
/** Optional quality of the state value */
|
||||
q?: StateQuality;
|
||||
|
||||
/** Optional comment */
|
||||
c?: string;
|
||||
}
|
||||
|
||||
type ObjectType = "state" | "channel" | "device";
|
||||
type CommonType = "number" | "string" | "boolean" | "array" | "object" | "mixed" | "file";
|
||||
|
||||
// Maybe this should extend Record<string, any>,
|
||||
// but the extra properties aren't defined anywhere,
|
||||
// so I'd rather force the user to explicitly state
|
||||
// he knows what he's doing by casting to any
|
||||
interface ObjectCommon {
|
||||
/** name of this object */
|
||||
name: string;
|
||||
|
||||
// Icon and role aren't defined in SCHEMA.md,
|
||||
// but they are being used by some adapters
|
||||
/** Icon for this object */
|
||||
icon?: string;
|
||||
/** role of the object */
|
||||
role?: string;
|
||||
}
|
||||
|
||||
interface StateCommon extends ObjectCommon {
|
||||
/** Type of this state. See https://github.com/ioBroker/ioBroker/blob/master/doc/SCHEMA.md#state-commonrole for a detailed description */
|
||||
type?: CommonType;
|
||||
/** minimum value */
|
||||
min?: number;
|
||||
/** maximum value */
|
||||
max?: number;
|
||||
/** unit of the value */
|
||||
unit?: string;
|
||||
/** the default value */
|
||||
def?: any;
|
||||
/** description of this state */
|
||||
desc?: string;
|
||||
|
||||
/** if this state is readable */
|
||||
read: boolean;
|
||||
/** if this state is writable */
|
||||
write: boolean;
|
||||
/** role of the state (used in user interfaces to indicate which widget to choose) */
|
||||
role: string;
|
||||
|
||||
/**
|
||||
* Dictionary of possible values for this state in the form
|
||||
* <pre>
|
||||
* {
|
||||
* "internal value 1": "displayed value 1",
|
||||
* "internal value 2": "displayed value 2",
|
||||
* ...
|
||||
* }
|
||||
* </pre>
|
||||
* In old ioBroker versions, this could also be a string of the form
|
||||
* "val1:text1;val2:text2" (now deprecated)
|
||||
*/
|
||||
states?: Record<string, string> | string;
|
||||
|
||||
/** ID of a helper state indicating if the handler of this state is working */
|
||||
workingID?: string;
|
||||
|
||||
/** attached history information */
|
||||
history?: any;
|
||||
}
|
||||
interface ChannelCommon extends ObjectCommon {
|
||||
/** description of this channel */
|
||||
desc?: string;
|
||||
}
|
||||
type OtherCommon = ObjectCommon & {
|
||||
[propName: string]: any;
|
||||
};
|
||||
|
||||
interface BaseObject {
|
||||
/** The ID of this object */
|
||||
_id?: string;
|
||||
native: Record<string, any>;
|
||||
enums?: Record<string, string>;
|
||||
type: string; // specified in the derived interfaces
|
||||
common: ObjectCommon;
|
||||
// acl?: ObjectACL;
|
||||
}
|
||||
|
||||
interface StateObject extends BaseObject {
|
||||
type: "state";
|
||||
common: StateCommon;
|
||||
// acl?: StateACL;
|
||||
}
|
||||
interface PartialStateObject extends Partial<Pick<StateObject, "_id" | "native" | "enums" | "type">> {
|
||||
common?: Partial<StateCommon>;
|
||||
// acl?: Partial<StateACL>;
|
||||
}
|
||||
|
||||
interface ChannelObject extends BaseObject {
|
||||
type: "channel";
|
||||
common: ChannelCommon;
|
||||
}
|
||||
interface PartialChannelObject extends Partial<Pick<ChannelObject, "_id" | "native" | "enums" | "type" /* | "acl"*/>> {
|
||||
common?: Partial<ChannelCommon>;
|
||||
}
|
||||
|
||||
interface DeviceObject extends BaseObject {
|
||||
type: "device";
|
||||
common: ObjectCommon; // TODO: any definition for device?
|
||||
}
|
||||
interface PartialDeviceObject extends Partial<Pick<DeviceObject, "_id" | "native" | "enums" | "type" /* | "acl"*/>> {
|
||||
common?: Partial<ObjectCommon>;
|
||||
}
|
||||
|
||||
// TODO: specify definitions for each object type
|
||||
// I grouped them together because I'm lazy...
|
||||
interface OtherObject extends BaseObject {
|
||||
type: "adapter" | "config" | "enum" | "group" | "host" | "info" | "instance" | "meta" | "script" | "user";
|
||||
common: OtherCommon;
|
||||
}
|
||||
interface PartialOtherObject extends Partial<Pick<OtherObject, "_id" | "native" | "enums" | "type" /* | "acl"*/>> {
|
||||
common?: Partial<OtherCommon>;
|
||||
}
|
||||
/** Represents the change of a state */
|
||||
interface ChangedStateObject extends StateObject {
|
||||
common: StateCommon;
|
||||
native: Record<string, any>;
|
||||
id?: string;
|
||||
name?: string;
|
||||
channelId?: string;
|
||||
channelName?: string;
|
||||
deviceId?: string;
|
||||
deviceName?: string;
|
||||
/** The IDs of enums this state is assigned to. For example ["enum.functions.Licht","enum.rooms.Garten"] */
|
||||
enumIds?: string[];
|
||||
/** The names of enums this state is assigned to. For example ["Licht","Garten"] */
|
||||
enumNames?: string[];
|
||||
/** new state */
|
||||
state: State;
|
||||
/** @deprecated Use state instead **/
|
||||
newState: State;
|
||||
/** previous state */
|
||||
oldState: State;
|
||||
/** Name of the adapter instance which set the value, e.g. "system.adapter.web.0" */
|
||||
from?: string;
|
||||
/** Unix timestamp. Default: current time */
|
||||
ts?: number;
|
||||
/** Unix timestamp of the last time the value changed */
|
||||
lc?: number;
|
||||
/** Direction flag: false for desired value and true for actual value. Default: false. */
|
||||
ack?: boolean;
|
||||
}
|
||||
|
||||
type Object = StateObject | ChannelObject | DeviceObject | OtherObject;
|
||||
type PartialObject = PartialStateObject | PartialChannelObject | PartialDeviceObject | PartialOtherObject;
|
||||
|
||||
type GetStateCallback = (err: string | null, state?: State) => void;
|
||||
type SetStateCallback = (err: string | null, id?: string) => void;
|
||||
|
||||
type StateChangeHandler = (obj: ChangedStateObject) => void;
|
||||
|
||||
type SetObjectCallback = (err: string | null, obj: { id: string }) => void;
|
||||
type GetObjectCallback = (err: string | null, obj: iobJS.Object) => void;
|
||||
|
||||
type LogLevel = "silly" | "debug" | "info" | "warn" | "error";
|
||||
|
||||
type ReadFileCallback = (err: string | null, file?: Buffer | string, mimeType?: string) => void;
|
||||
|
||||
/** Callback information for a passed message */
|
||||
interface MessageCallbackInfo {
|
||||
/** The original message payload */
|
||||
message: string | object;
|
||||
/** ID of this callback */
|
||||
id: number;
|
||||
// ???
|
||||
ack: boolean;
|
||||
/** Timestamp of this message */
|
||||
time: number;
|
||||
}
|
||||
type MessageCallback = (result?: any) => void;
|
||||
|
||||
interface Subscription {
|
||||
name: string;
|
||||
pattern: string | RegExp | string[] | iobJS.SubscribeOptions | iobJS.SubscribeTime | iobJS.AstroSchedule;
|
||||
}
|
||||
|
||||
interface SubscribeOptions {
|
||||
/** "and" or "or" logic to combine the conditions (default: "and") */
|
||||
logic?: "and" | "or";
|
||||
/** name is equal or matches to given one or name marches to any item in given list */
|
||||
id?: string | string[] | SubscribeOptions[] | RegExp | RegExp[];
|
||||
/** name is equal or matches to given one */
|
||||
name?: string | string[] | RegExp;
|
||||
/** type of change */
|
||||
change?: "eq" | "ne" | "gt" | "ge" | "lt" | "le" | "any";
|
||||
val?: any;
|
||||
/** New value must not be equal to given one */
|
||||
valNe?: any;
|
||||
/** New value must be greater than given one */
|
||||
valGt?: any;
|
||||
/** New value must be greater or equal to given one */
|
||||
valGe?: any;
|
||||
/** New value must be smaller than given one */
|
||||
valLt?: any;
|
||||
/** New value must be smaller or equal to given one */
|
||||
valLe?: any;
|
||||
/** Acknowledged state of new value is equal to given one */
|
||||
ack?: boolean;
|
||||
/** Previous value must be equal to given one */
|
||||
oldVal?: any;
|
||||
/** Previous value must be not equal to given one */
|
||||
oldValNe?: any;
|
||||
/** Previous value must be greater than given one */
|
||||
oldValGt?: any;
|
||||
/** Previous value must be greater or equal given one */
|
||||
oldValGe?: any;
|
||||
/** Previous value must be smaller than given one */
|
||||
oldValLt?: any;
|
||||
/** Previous value must be smaller or equal to given one */
|
||||
oldValLe?: any;
|
||||
/** Acknowledged state of previous value is equal to given one */
|
||||
oldAck?: boolean;
|
||||
/** New value time stamp must be equal to given one (state.ts == ts) */
|
||||
ts?: string;
|
||||
/** New value time stamp must be not equal to the given one (state.ts != ts) */
|
||||
tsGt?: string;
|
||||
/** New value time stamp must be greater than given value (state.ts > ts) */
|
||||
tsGe?: string;
|
||||
/** New value time stamp must be greater or equal to given one (state.ts >= ts) */
|
||||
tsLt?: string;
|
||||
/** New value time stamp must be smaller than given one (state.ts < ts) */
|
||||
tsLe?: string;
|
||||
/** Previous time stamp must be equal to given one (oldState.ts == ts) */
|
||||
oldTs?: string;
|
||||
/** Previous time stamp must be not equal to the given one (oldState.ts != ts) */
|
||||
oldTsGt?: string;
|
||||
/** Previous time stamp must be greater than given value (oldState.ts > ts) */
|
||||
oldTsGe?: string;
|
||||
/** Previous time stamp must be greater or equal to given one (oldState.ts >= ts) */
|
||||
oldTsLt?: string;
|
||||
/** Previous time stamp must be smaller than given one (oldState.ts < ts) */
|
||||
oldTsLe?: string;
|
||||
/** Last change time stamp must be equal to given one (state.lc == lc) */
|
||||
lc?: string;
|
||||
/** Last change time stamp must be not equal to the given one (state.lc != lc) */
|
||||
lcGt?: string;
|
||||
/** Last change time stamp must be greater than given value (state.lc > lc) */
|
||||
lcGe?: string;
|
||||
/** Last change time stamp must be greater or equal to given one (state.lc >= lc) */
|
||||
lcLt?: string;
|
||||
/** Last change time stamp must be smaller than given one (state.lc < lc) */
|
||||
lcLe?: string;
|
||||
/** Previous last change time stamp must be equal to given one (oldState.lc == lc) */
|
||||
oldLc?: string;
|
||||
/** Previous last change time stamp must be not equal to the given one (oldState.lc != lc) */
|
||||
oldLcGt?: string;
|
||||
/** Previous last change time stamp must be greater than given value (oldState.lc > lc) */
|
||||
oldLcGe?: string;
|
||||
/** Previous last change time stamp must be greater or equal to given one (oldState.lc >= lc) */
|
||||
oldLcLt?: string;
|
||||
/** Previous last change time stamp must be smaller than given one (oldState.lc < lc) */
|
||||
oldLcLe?: string;
|
||||
/** Channel ID must be equal or match to given one */
|
||||
channelId?: string | string[] | RegExp;
|
||||
/** Channel name must be equal or match to given one */
|
||||
channelName?: string | string[] | RegExp;
|
||||
/** Device ID must be equal or match to given one */
|
||||
deviceId?: string | string[] | RegExp;
|
||||
/** Device name must be equal or match to given one */
|
||||
deviceName?: string | string[] | RegExp;
|
||||
/** State belongs to given enum or one enum ID of state satisfy the given regular expression */
|
||||
enumId?: string | string[] | RegExp;
|
||||
/** State belongs to given enum or one enum name of state satisfy the given regular expression */
|
||||
enumName?: string | string[] | RegExp;
|
||||
/** New value is from defined adapter */
|
||||
from?: string | string[] | RegExp;
|
||||
/** New value is not from defined adapter */
|
||||
fromNe?: string | string[] | RegExp;
|
||||
/** Old value is from defined adapter */
|
||||
oldFrom?: string | string[] | RegExp;
|
||||
/** Old value is not from defined adapter */
|
||||
oldFromNe?: string | string[] | RegExp;
|
||||
}
|
||||
|
||||
interface QueryResult {
|
||||
/** State-ID */
|
||||
[index: number]: string;
|
||||
/** Number of matched states */
|
||||
length: number;
|
||||
|
||||
/**
|
||||
* Executes a function for each state id in the result array
|
||||
* The execution is canceled if a callback returns false
|
||||
*/
|
||||
each: (callback?: (id: string, index: number) => boolean | void) => this;
|
||||
|
||||
/**
|
||||
* Returns the first state found by this query.
|
||||
* If the adapter is configured to subscribe to all states on start,
|
||||
* this can be called synchronously and immediately returns the state.
|
||||
* Otherwise you need to provide a callback.
|
||||
*/
|
||||
getState: (callback?: GetStateCallback) => void | State;
|
||||
|
||||
/**
|
||||
* Sets all queried states to the given value.
|
||||
*/
|
||||
setState: (id: string, state: string | number | boolean | State | Partial<State>, ack?: boolean, callback?: SetStateCallback) => this;
|
||||
|
||||
/**
|
||||
* Subscribes the given callback to changes of the matched states.
|
||||
*/
|
||||
on: (callback: StateChangeHandler) => this;
|
||||
}
|
||||
|
||||
/**
|
||||
* * "sunrise": sunrise (top edge of the sun appears on the horizon)
|
||||
* * "sunriseEnd": sunrise ends (bottom edge of the sun touches the horizon)
|
||||
* * "goldenHourEnd": morning golden hour (soft light, best time for photography) ends
|
||||
* * "solarNoon": solar noon (sun is in the highest position)
|
||||
* * "goldenHour": evening golden hour starts
|
||||
* * "sunsetStart": sunset starts (bottom edge of the sun touches the horizon)
|
||||
* * "sunset": sunset (sun disappears below the horizon, evening civil twilight starts)
|
||||
* * "dusk": dusk (evening nautical twilight starts)
|
||||
* * "nauticalDusk": nautical dusk (evening astronomical twilight starts)
|
||||
* * "night": night starts (dark enough for astronomical observations)
|
||||
* * "nightEnd": night ends (morning astronomical twilight starts)
|
||||
* * "nauticalDawn": nautical dawn (morning nautical twilight starts)
|
||||
* * "dawn": dawn (morning nautical twilight ends, morning civil twilight starts)
|
||||
* * "nadir": nadir (darkest moment of the night, sun is in the lowest position)
|
||||
*/
|
||||
type AstroPattern = "sunrise" | "sunriseEnd" | "goldenHourEnd" | "solarNoon" | "goldenHour" | "sunsetStart" | "sunset" | "dusk" | "nauticalDusk" | "night" | "nightEnd" | "nauticalDawn" | "dawn" | "nadir";
|
||||
|
||||
interface AstroSchedule {
|
||||
astro: AstroPattern;
|
||||
/**
|
||||
* Shift to the astro schedule.
|
||||
*/
|
||||
shift?: number;
|
||||
}
|
||||
|
||||
interface AstroDate {
|
||||
astro: AstroPattern;
|
||||
/** Offset to the astro event in minutes */
|
||||
offset?: number;
|
||||
/** Date for which the astro time is wanted */
|
||||
date?: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* from https://github.com/node-schedule/node-schedule
|
||||
*/
|
||||
interface ScheduleRule {
|
||||
/**
|
||||
* Day of the month.
|
||||
*/
|
||||
date?: number | number[] | string | string[];
|
||||
|
||||
/**
|
||||
* Day of the week.
|
||||
*/
|
||||
dayOfWeek?: number | number[] | string | string[];
|
||||
|
||||
/**
|
||||
* Hour.
|
||||
*/
|
||||
hour?: number | number[] | string | string[];
|
||||
|
||||
/**
|
||||
* Minute.
|
||||
*/
|
||||
minute?: number | number[] | string | string[];
|
||||
|
||||
/**
|
||||
* Month.
|
||||
*/
|
||||
month?: number | number[] | string | string[];
|
||||
|
||||
/**
|
||||
* Second.
|
||||
*/
|
||||
second?: number | number[] | string | string[];
|
||||
|
||||
/**
|
||||
* Year.
|
||||
*/
|
||||
year?: number | number[] | string | string[];
|
||||
/**
|
||||
* timezone which should be used
|
||||
* https://github.com/moment/moment-timezone
|
||||
*/
|
||||
tz?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* from https://github.com/node-schedule/node-schedule
|
||||
*/
|
||||
interface ScheduleRuleConditional {
|
||||
/**
|
||||
* set a start time for schedule
|
||||
* a Data object or a dateString resp a number in milliseconds which can create a Date object
|
||||
*/
|
||||
start?: Date | string | number;
|
||||
/**
|
||||
* set an end time for schedule
|
||||
* a Data object or a dateString resp a number in milliseconds which can create a Date object
|
||||
*/
|
||||
end?: Date | string | number;
|
||||
/**
|
||||
* timezone which should be used
|
||||
* https://github.com/moment/moment-timezone
|
||||
*/
|
||||
tz?: string;
|
||||
/**
|
||||
* scheduling rule
|
||||
* schedule rule, a Data object or a dateString resp a number in milliseconds which can create a Date object
|
||||
*/
|
||||
rule: ScheduleRule | Date | string | number;
|
||||
}
|
||||
|
||||
type SchedulePattern = ScheduleRule | ScheduleRuleConditional | Date | string | number;
|
||||
|
||||
interface SubscribeTime {
|
||||
time: SchedulePattern;
|
||||
}
|
||||
} // end namespace iobJS
|
||||
|
||||
// =======================================================
|
||||
// available functions in the sandbox
|
||||
// =======================================================
|
||||
|
||||
// The already pre-loaded request module
|
||||
const request: typeof import("request");
|
||||
|
||||
/**
|
||||
* The instance number of the JavaScript adapter this script runs in
|
||||
*/
|
||||
const instance: number;
|
||||
/**
|
||||
* The name of the current script
|
||||
*/
|
||||
const name: string;
|
||||
/**
|
||||
* The name of the current script
|
||||
*/
|
||||
const scriptName: string;
|
||||
|
||||
/**
|
||||
* Queries all states with the given selector
|
||||
* @param selector See @link{https://github.com/ioBroker/ioBroker.javascript#---selector} for a description
|
||||
*/
|
||||
function $(selector: string): iobJS.QueryResult;
|
||||
|
||||
/**
|
||||
* Prints a message in the ioBroker log
|
||||
* @param message The message to print
|
||||
* @param severity (optional) severity of the message. default = "info"
|
||||
*/
|
||||
function log(message: string, severity?: iobJS.LogLevel);
|
||||
|
||||
// TODO: Do we need this?
|
||||
// namespace console {
|
||||
// /** log message with debug level */
|
||||
// function debug(message: string): void;
|
||||
// /** log message with info level (default output level for all adapters) */
|
||||
// function info(message: string): void;
|
||||
// /** log message with warning severity */
|
||||
// function warn(message: string): void;
|
||||
// /** log message with error severity */
|
||||
// function error(message: string): void;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Executes a system command
|
||||
*/
|
||||
function exec(command: string, callback?: (err: Error, stdout: string, stderr: string) => void): child_process.ChildProcess;
|
||||
|
||||
/**
|
||||
* Sends an email using the email adapter.
|
||||
* See the adapter documentation for a description of the msg parameter.
|
||||
*/
|
||||
function email(msg: any): void;
|
||||
|
||||
/**
|
||||
* Sends a pushover message using the pushover adapter.
|
||||
* See the adapter documentation for a description of the msg parameter.
|
||||
*/
|
||||
function pushover(msg: any): void;
|
||||
|
||||
/**
|
||||
* Causes all changes of the state with id1 to the state with id2.
|
||||
* The return value can be used to unsubscribe later
|
||||
*/
|
||||
function on(id1: string, id2: string): any;
|
||||
/**
|
||||
* Causes all changes of the state with id1 to the state with id2
|
||||
*/
|
||||
function subscribe(id1: string, id2: string): any;
|
||||
|
||||
/**
|
||||
* Watches the state with id1 for changes and overwrites the state with id2 with value2 when any occur.
|
||||
* @param id1 The state to watch for changes
|
||||
* @param id2 The state to update when changes occur
|
||||
* @param value2 The value to write into state `id2` when `id1` gets changed
|
||||
*/
|
||||
function on(id1: string, id2: string, value2: any): any;
|
||||
/**
|
||||
* Watches the state with id1 for changes and overwrites the state with id2 with value2 when any occur.
|
||||
* @param id1 The state to watch for changes
|
||||
* @param id2 The state to update when changes occur
|
||||
* @param value2 The value to write into state `id2` when `id1` gets changed
|
||||
*/
|
||||
function subscribe(id1: string, id2: string, value2: any): any;
|
||||
|
||||
/**
|
||||
* Subscribe to changes of the matched states.
|
||||
*/
|
||||
function on(pattern: string | RegExp | string[], handler: iobJS.StateChangeHandler): any;
|
||||
function on(options: iobJS.SubscribeOptions, handler: iobJS.StateChangeHandler): any;
|
||||
function on(schedule: iobJS.SubscribeTime, handler: iobJS.StateChangeHandler): any;
|
||||
function on(astro: iobJS.AstroSchedule, handler: iobJS.StateChangeHandler): any;
|
||||
/**
|
||||
* Subscribe to changes of the matched states.
|
||||
*/
|
||||
function subscribe(pattern: string | RegExp | string[], handler: iobJS.StateChangeHandler): any;
|
||||
function subscribe(options: iobJS.SubscribeOptions, handler: iobJS.StateChangeHandler): any;
|
||||
function subscribe(schedule: iobJS.SubscribeTime, handler: iobJS.StateChangeHandler): any;
|
||||
function subscribe(astro: iobJS.AstroSchedule, handler: iobJS.StateChangeHandler): any;
|
||||
|
||||
/**
|
||||
* Returns the list of all currently active subscriptions
|
||||
*/
|
||||
function getSubscriptions(): { [id: string]: iobJS.Subscription[] };
|
||||
|
||||
/**
|
||||
* Unsubscribe from changes of the given object ID(s) or handler(s)
|
||||
*/
|
||||
function unsubscribe(id: string | string[]): boolean;
|
||||
function unsubscribe(handler: any | any[]): boolean;
|
||||
|
||||
function adapterSubscribe(id: string): void;
|
||||
function adapterUnsubscribe(id: string): void;
|
||||
|
||||
/**
|
||||
* Schedules a function to be executed on a defined schedule.
|
||||
* The return value can be used to clear the schedule later.
|
||||
*/
|
||||
function schedule(pattern: string | iobJS.SchedulePattern, callback: () => void): any;
|
||||
function schedule(date: Date, callback: () => void): any;
|
||||
function schedule(astro: iobJS.AstroSchedule, callback: () => void): any;
|
||||
/**
|
||||
* Clears a schedule. Returns true if it was successful.
|
||||
*/
|
||||
function clearSchedule(schedule: any): boolean;
|
||||
|
||||
/**
|
||||
* Calculates the astro time which corresponds to the given pattern.
|
||||
* For valid patterns, see @link{https://github.com/ioBroker/ioBroker.javascript#astro--function}
|
||||
* @param date (optional) The date for which the astro time should be calculated. Default = today
|
||||
* @param offsetMinutes (optional) The amount of minutes to be added to the return value.
|
||||
*/
|
||||
function getAstroDate(pattern: string, date?: number, offsetMinutes?: number): Date;
|
||||
|
||||
/**
|
||||
* Determines if now is between sunrise and sunset.
|
||||
*/
|
||||
function isAstroDay(): boolean;
|
||||
|
||||
/**
|
||||
* Sets a state to the given value
|
||||
* @param id The ID of the state to be set
|
||||
*/
|
||||
function setState(id: string, state: string | number | boolean | iobJS.State | Partial<iobJS.State>, callback?: iobJS.SetStateCallback): void;
|
||||
function setState(id: string, state: string | number | boolean | iobJS.State | Partial<iobJS.State>, ack: boolean, callback?: iobJS.SetStateCallback): void;
|
||||
|
||||
/**
|
||||
* Sets a state to the given value after a timeout has passed.
|
||||
* Returns the timer so it can be manually cleared with clearStateDelayed
|
||||
* @param id The ID of the state to be set
|
||||
* @param delay The delay in milliseconds
|
||||
* @param clearRunning (optional) Whether an existing timeout for this state should be cleared
|
||||
*/
|
||||
function setStateDelayed(id: string, state: string | number | boolean | iobJS.State | Partial<iobJS.State>, delay: number, clearRunning: boolean, callback?: iobJS.SetStateCallback): any;
|
||||
function setStateDelayed(id: string, state: string | number | boolean | iobJS.State | Partial<iobJS.State>, ack: boolean, clearRunning: boolean, callback?: iobJS.SetStateCallback): any;
|
||||
function setStateDelayed(id: string, state: string | number | boolean | iobJS.State | Partial<iobJS.State>, ack: boolean, delay: number, callback?: iobJS.SetStateCallback): any;
|
||||
function setStateDelayed(id: string, state: string | number | boolean | iobJS.State | Partial<iobJS.State>, delay: number, callback?: iobJS.SetStateCallback): any;
|
||||
function setStateDelayed(id: string, state: string | number | boolean | iobJS.State | Partial<iobJS.State>, callback?: iobJS.SetStateCallback): any;
|
||||
function setStateDelayed(id: string, state: string | number | boolean | iobJS.State | Partial<iobJS.State>, ack: boolean, delay: number, clearRunning: boolean, callback?: iobJS.SetStateCallback): any;
|
||||
|
||||
/**
|
||||
* Clears a timer created by setStateDelayed
|
||||
* @param id The state id for which the timer should be cleared
|
||||
* @param timerID (optional) ID of the specific timer to clear. If none is given, all timers are cleared.
|
||||
*/
|
||||
function clearStateDelayed(id: string, timerID?: any): boolean;
|
||||
|
||||
/**
|
||||
* Returns the state with the given ID.
|
||||
* If the adapter is configured to subscribe to all states on start,
|
||||
* this can be called synchronously and immediately returns the state.
|
||||
* Otherwise you need to provide a callback.
|
||||
*/
|
||||
function getState(id: string, callback: iobJS.GetStateCallback): void;
|
||||
function getState(id: string): iobJS.State;
|
||||
|
||||
/**
|
||||
* Checks if the state with the given ID exists
|
||||
*/
|
||||
function existsState(id: string): boolean;
|
||||
/**
|
||||
* Checks if the object with the given ID exists
|
||||
*/
|
||||
function existsObject(id: string): boolean;
|
||||
|
||||
/**
|
||||
* Returns the IDs of the states with the given name
|
||||
* @param forceArray (optional) Ensures that the return value is always an array, even if only one ID was found.
|
||||
*/
|
||||
function getIdByName(name: string, forceArray?: boolean): string | string[];
|
||||
|
||||
/**
|
||||
* Reads an object from the object db
|
||||
*/
|
||||
function getObject(id: string, enumName?: string): iobJS.Object;
|
||||
/** Creates or overwrites an object in the object db */
|
||||
function setObject(id: string, obj: iobJS.Object, callback?: iobJS.SetObjectCallback): void;
|
||||
/** Extend an object and create it if it might not exist */
|
||||
function extendObject(id: string, objPart: iobJS.PartialObject, callback?: iobJS.SetObjectCallback): void;
|
||||
|
||||
function getEnums(enumName?: string): any;
|
||||
|
||||
/**
|
||||
* Creates a state and the corresponding object under the javascript namespace.
|
||||
* @param name The name of the state without the namespace
|
||||
* @param initValue (optional) Initial value of the state
|
||||
* @param forceCreation (optional) Override the state if it already exists
|
||||
* @param common (optional) Common part of the state object
|
||||
* @param native (optional) Native part of the state object
|
||||
* @param callback (optional) Called after the state was created
|
||||
*/
|
||||
function createState(name: string, callback?: iobJS.SetStateCallback): void;
|
||||
function createState(name: string, initValue: any, callback?: iobJS.SetStateCallback): void;
|
||||
function createState(name: string, initValue: any, forceCreation: boolean, callback?: iobJS.SetStateCallback): void;
|
||||
function createState(name: string, initValue: any, forceCreation: boolean, common: Partial<iobJS.StateCommon>, callback?: iobJS.SetStateCallback): void;
|
||||
function createState(name: string, initValue: any, forceCreation: boolean, common: Partial<iobJS.StateCommon>, native: any, callback?: iobJS.SetStateCallback): void;
|
||||
function createState(name: string, common: Partial<iobJS.StateCommon>, callback?: iobJS.SetStateCallback): void;
|
||||
function createState(name: string, initValue: any, common: Partial<iobJS.StateCommon>, callback?: iobJS.SetStateCallback): void;
|
||||
function createState(name: string, common: Partial<iobJS.StateCommon>, native: any, callback?: iobJS.SetStateCallback): void;
|
||||
function createState(name: string, initValue: any, common: Partial<iobJS.StateCommon>, native: any, callback?: iobJS.SetStateCallback): void;
|
||||
|
||||
/**
|
||||
* Deletes the state with the given ID
|
||||
* @param callback (optional) Is called after the state was deleted (or not).
|
||||
*/
|
||||
function deleteState(id: string, callback?: GenericCallback<boolean>): void;
|
||||
|
||||
/**
|
||||
* Sends a message to a specific instance or all instances of some specific adapter.
|
||||
* @param instanceName The instance to send this message to.
|
||||
* If the ID of an instance is given (e.g. "admin.0"), only this instance will receive the message.
|
||||
* If the name of an adapter is given (e.g. "admin"), all instances of this adapter will receive it.
|
||||
* @param command (optional) Command name of the target instance. Default: "send"
|
||||
* @param message The message (e.g. params) to send.
|
||||
*/
|
||||
function sendTo(instanceName: string, message: string | object, callback?: iobJS.MessageCallback | iobJS.MessageCallbackInfo): void;
|
||||
function sendTo(instanceName: string, command: string, message: string | object, callback?: iobJS.MessageCallback | iobJS.MessageCallbackInfo): void;
|
||||
|
||||
type CompareTimeOperations =
|
||||
"between" | "not between" |
|
||||
">" | ">=" | "<" | "<=" | "==" | "<>"
|
||||
;
|
||||
|
||||
/**
|
||||
* Compares two or more times
|
||||
* @param timeToCompare - The time to compare with startTime and/or endTime. If none is given, the current time is used
|
||||
*/
|
||||
function compareTime(
|
||||
startTime: string | number | Date | iobJS.AstroDate,
|
||||
endTime: string | number | Date | iobJS.AstroDate,
|
||||
operation: CompareTimeOperations,
|
||||
timeToCompare?: string | number | Date | iobJS.AstroDate,
|
||||
): boolean;
|
||||
|
||||
/** Sets up a callback which is called when the script stops */
|
||||
function onStop(callback: (cb?: () => void) => void, timeout?: number): void;
|
||||
|
||||
function formatValue(value: number | string, format?: any): string;
|
||||
function formatValue(value: number | string, decimals: number, format?: any): string;
|
||||
function formatDate(dateObj: string | Date | number, format: string, language?: string): string;
|
||||
function formatDate(dateObj: string | Date | number, isDuration: boolean | string, format: string, language?: string): string;
|
||||
|
||||
function getDateObject(date: number | string | Date): Date;
|
||||
|
||||
/**
|
||||
* Writes a file.
|
||||
* @param id Name of the root directory. This should be the adapter instance, e.g. "admin.0"
|
||||
* @param name File name
|
||||
* @param data Contents of the file
|
||||
* @param callback Is called when the operation has finished (successfully or not)
|
||||
*/
|
||||
function writeFile(id: string, name: string, data: Buffer | string, callback: ErrorCallback): void;
|
||||
|
||||
/**
|
||||
* Reads a file.
|
||||
* @param id Name of the root directory. This should be the adapter instance, e.g. "admin.0"
|
||||
* @param name File name
|
||||
* @param callback Is called when the operation has finished (successfully or not)
|
||||
*/
|
||||
function readFile(id: string, name: string, callback: iobJS.ReadFileCallback): void;
|
||||
|
||||
/**
|
||||
* Deletes a file.
|
||||
* @param id Name of the root directory. This should be the adapter instance, e.g. "admin.0"
|
||||
* @param name File name
|
||||
* @param callback Is called when the operation has finished (successfully or not)
|
||||
*/
|
||||
function unlink(id: string, name: string, callback: ErrorCallback): void;
|
||||
/**
|
||||
* Deletes a file.
|
||||
* @param id Name of the root directory. This should be the adapter instance, e.g. "admin.0"
|
||||
* @param name File name
|
||||
* @param callback Is called when the operation has finished (successfully or not)
|
||||
*/
|
||||
function delFile(id: string, name: string, callback: ErrorCallback): void;
|
||||
|
||||
function getHistory(instance: any, options: any, callback: any): any;
|
||||
|
||||
/**
|
||||
* Starts or restarts a script by name
|
||||
* @param scriptName (optional) Name of the script. If none is given, the current script is (re)started.
|
||||
*/
|
||||
function runScript(scriptName?: string, callback?: ErrorCallback): boolean;
|
||||
/**
|
||||
* Starts or restarts a script by name
|
||||
* @param scriptName (optional) Name of the script. If none is given, the current script is (re)started.
|
||||
*/
|
||||
function startScript(scriptName, ignoreIfStarted, callback?: GenericCallback<boolean>): boolean;
|
||||
/**
|
||||
* Stops a script by name
|
||||
* @param scriptName (optional) Name of the script. If none is given, the current script is stopped.
|
||||
*/
|
||||
function stopScript(scriptName, callback?: GenericCallback<boolean>): boolean;
|
||||
function isScriptActive(scriptName): boolean;
|
||||
|
||||
/** Converts a value to an integer */
|
||||
function toInt(val: any): number;
|
||||
/** Converts a value to a floating point number */
|
||||
function toFloat(val: any): number;
|
||||
/** Converts a value to a boolean */
|
||||
function toBoolean(val: any): boolean;
|
||||
|
||||
/**
|
||||
* Digs in an object for the property value at the given path.
|
||||
* @param obj The object to dig in
|
||||
* @param path The path of the property to dig for in the given object
|
||||
*/
|
||||
function getAttr(obj: string | Record<string, any>, path: string | string[]): any;
|
||||
}
|
||||
370
lib/patternCompareFunctions.js
Normal file
370
lib/patternCompareFunctions.js
Normal file
@@ -0,0 +1,370 @@
|
||||
'use strict';
|
||||
|
||||
function isRegExp(obj) {
|
||||
return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {{}} pattern The pattern object to use
|
||||
* @param {string} propName The name of the property to compare
|
||||
* @param {(event: any) => any} [eventPropertyExtractor] If given, this function is used to extract the property value from the event object. Otherwise the propName is used
|
||||
*/
|
||||
function stringOrRegExpCompare(pattern, propName, eventPropertyExtractor) {
|
||||
/** @type {RegExp | string | string[]} */
|
||||
const field = pattern[propName];
|
||||
const hasExtractor = typeof eventPropertyExtractor === 'function';
|
||||
if (isRegExp(field)) {
|
||||
return function (event) {
|
||||
const eventValue = hasExtractor ? eventPropertyExtractor(event) : event[propName];
|
||||
return (eventValue != null && /** @type {RegExp} */ (field).test(eventValue));
|
||||
};
|
||||
} else if (Array.isArray(field)) {
|
||||
return function (event) {
|
||||
const eventValue = hasExtractor ? eventPropertyExtractor(event) : event[propName];
|
||||
// An array matches when any element is found that satisfies the constraint
|
||||
return eventValue != null && field.find(f => f === eventValue) != null;
|
||||
};
|
||||
} else {
|
||||
return function (event) {
|
||||
const eventValue = hasExtractor ? eventPropertyExtractor(event) : event[propName];
|
||||
return (eventValue != null && field === eventValue);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const patternCompareFunctions = {
|
||||
|
||||
logic: function (pattern) {
|
||||
},
|
||||
|
||||
id: (pattern) => stringOrRegExpCompare(pattern, 'id'),
|
||||
|
||||
name: (pattern) => stringOrRegExpCompare(pattern, 'name'),
|
||||
|
||||
change: function (pattern) {
|
||||
switch (pattern.change) {
|
||||
case 'eq': return function (event) { return (event.newState.val === event.oldState.val); };
|
||||
case 'ne': return function (event) { return (event.newState.val !== event.oldState.val); };
|
||||
case 'gt': return function (event) { return (event.newState.val > event.oldState.val); };
|
||||
case 'ge': return function (event) { return (event.newState.val >= event.oldState.val); };
|
||||
case 'lt': return function (event) { return (event.newState.val < event.oldState.val); };
|
||||
case 'le': return function (event) { return (event.newState.val <= event.oldState.val); };
|
||||
default: return function (/* event */) { return true; };
|
||||
// on any other logic, just signal about message
|
||||
}
|
||||
},
|
||||
ack: function (pattern) {
|
||||
if (pattern.ack === true || pattern.ack === 'true') {
|
||||
return function (event) {
|
||||
return (event.newState.ack === true || event.newState.ack === 'true');
|
||||
};
|
||||
} else {
|
||||
return function (event) {
|
||||
return (event.newState.ack === false || event.newState.ack === 'false');
|
||||
};
|
||||
}
|
||||
},
|
||||
oldAck: function (pattern) {
|
||||
if (pattern.oldAck === true || pattern.oldAck === 'true') {
|
||||
return function (event) {
|
||||
return (event.oldState.ack === true || event.oldState.ack === 'true');
|
||||
};
|
||||
} else {
|
||||
return function (event) {
|
||||
return (event.oldState.ack === false || event.oldState.ack === 'false');
|
||||
};
|
||||
}
|
||||
},
|
||||
val: function (pattern) {
|
||||
const pval = pattern.val;
|
||||
return function (event) {
|
||||
return pval === event.newState.val;
|
||||
};
|
||||
},
|
||||
valGt: function (pattern) {
|
||||
const pvalGt = pattern.valGt;
|
||||
return function (event) {
|
||||
return event.newState.val > pvalGt;
|
||||
};
|
||||
},
|
||||
valGe: function (pattern) {
|
||||
const pvalGe = pattern.valGe;
|
||||
return function (event) {
|
||||
return event.newState.val >= pvalGe;
|
||||
};
|
||||
},
|
||||
valLt: function (pattern) {
|
||||
const pvalLt = pattern.valLt;
|
||||
return function (event) {
|
||||
return event.newState.val < pvalLt;
|
||||
};
|
||||
},
|
||||
valLe: function (pattern) {
|
||||
const pvalLe = pattern.valLe;
|
||||
return function (event) {
|
||||
return event.newState.val <= pvalLe;
|
||||
};
|
||||
},
|
||||
valNe: function (pattern) {
|
||||
const pvalNe = pattern.valNe;
|
||||
return function (event) {
|
||||
return event.newState.val !== pvalNe;
|
||||
};
|
||||
},
|
||||
|
||||
oldVal: function (pattern) {
|
||||
const poldVal = pattern.oldVal;
|
||||
return function (event) {
|
||||
return poldVal === event.oldState.val;
|
||||
};
|
||||
},
|
||||
oldValGt: function (pattern) {
|
||||
const poldValGt = pattern.oldValGt;
|
||||
return function (event) {
|
||||
return event.oldState.val > poldValGt;
|
||||
};
|
||||
},
|
||||
oldValGe: function (pattern) {
|
||||
const poldValGe = pattern.oldValGe;
|
||||
return function (event) {
|
||||
return event.oldState.val >= poldValGe;
|
||||
};
|
||||
},
|
||||
oldValLt: function (pattern) {
|
||||
const poldValLt = pattern.oldValLt;
|
||||
return function (event) {
|
||||
return event.oldState.val < poldValLt;
|
||||
};
|
||||
},
|
||||
oldValLe: function (pattern) {
|
||||
const poldValLe = pattern.oldValLe;
|
||||
return function (event) {
|
||||
return event.oldState.val <= poldValLe;
|
||||
};
|
||||
},
|
||||
oldValNe: function (pattern) {
|
||||
const poldValNe = pattern.oldValNe;
|
||||
return function (event) {
|
||||
return event.oldState.val !== poldValNe;
|
||||
};
|
||||
},
|
||||
|
||||
ts: function (pattern) {
|
||||
const pts = pattern.ts;
|
||||
return function (event) {
|
||||
return pts === event.newState.ts;
|
||||
};
|
||||
},
|
||||
tsGt: function (pattern) {
|
||||
const ptsGt = pattern.tsGt;
|
||||
return function (event) {
|
||||
return event.newState.ts > ptsGt;
|
||||
};
|
||||
},
|
||||
tsGe: function (pattern) {
|
||||
const ptsGe = pattern.tsGe;
|
||||
return function (event) {
|
||||
return event.newState.ts >= ptsGe;
|
||||
};
|
||||
},
|
||||
tsLt: function (pattern) {
|
||||
const ptsLt = pattern.tsLt;
|
||||
return function (event) {
|
||||
return event.newState.ts < ptsLt;
|
||||
};
|
||||
},
|
||||
tsLe: function (pattern) {
|
||||
const ptsLe = pattern.tsLe;
|
||||
return function (event) {
|
||||
return event.newState.ts <= ptsLe;
|
||||
};
|
||||
},
|
||||
|
||||
oldTs: function (pattern) {
|
||||
const poldTs = pattern.oldTs;
|
||||
return function (event) {
|
||||
return poldTs === event.oldState.ts;
|
||||
};
|
||||
},
|
||||
oldTsGt: function (pattern) {
|
||||
const poldTsGt = pattern.oldTsGt;
|
||||
return function (event) {
|
||||
return event.oldState.ts > poldTsGt;
|
||||
};
|
||||
},
|
||||
oldTsGe: function (pattern) {
|
||||
const poldTsGe = pattern.oldTsGe;
|
||||
return function (event) {
|
||||
return event.oldState.ts >= poldTsGe;
|
||||
};
|
||||
},
|
||||
oldTsLt: function (pattern) {
|
||||
const poldTsLt = pattern.oldTsLt;
|
||||
return function (event) {
|
||||
return event.oldState.ts < poldTsLt;
|
||||
};
|
||||
},
|
||||
oldTsLe: function (pattern) {
|
||||
const poldTsLe = pattern.oldTsLe;
|
||||
return function (event) {
|
||||
return event.oldState.ts <= poldTsLe;
|
||||
};
|
||||
},
|
||||
|
||||
lc: function (pattern) {
|
||||
const plc = pattern.lc;
|
||||
return function (event) {
|
||||
return plc === event.newState.lc;
|
||||
};
|
||||
},
|
||||
lcGt: function (pattern) {
|
||||
const plcGt = pattern.lcGt;
|
||||
return function (event) {
|
||||
return event.newState.lc > plcGt;
|
||||
};
|
||||
},
|
||||
lcGe: function (pattern) {
|
||||
const plcGe = pattern.lcGe;
|
||||
return function (event) {
|
||||
return event.newState.lc >= plcGe;
|
||||
};
|
||||
},
|
||||
lcLt: function (pattern) {
|
||||
const plcLt = pattern.lcLt;
|
||||
return function (event) {
|
||||
return event.newState.lc < plcLt;
|
||||
};
|
||||
},
|
||||
lcLe: function (pattern) {
|
||||
const plcLe = pattern.lcLe;
|
||||
return function (event) {
|
||||
return event.newState.lc <= plcLe;
|
||||
};
|
||||
},
|
||||
|
||||
oldLc: function (pattern) {
|
||||
const poldLc = pattern.oldLc;
|
||||
return function (event) {
|
||||
return poldLc === event.oldState.lc;
|
||||
};
|
||||
},
|
||||
oldLcGt: function (pattern) {
|
||||
const poldLcGt = pattern.oldLcGt;
|
||||
return function (event) {
|
||||
return event.oldState.lc > poldLcGt;
|
||||
};
|
||||
},
|
||||
oldLcGe: function (pattern) {
|
||||
const poldLcGe = pattern.oldLcGe;
|
||||
return function (event) {
|
||||
return event.oldState.lc >= poldLcGe;
|
||||
};
|
||||
},
|
||||
oldLcLt: function (pattern) {
|
||||
const poldLcLt = pattern.oldLcLt;
|
||||
return function (event) {
|
||||
return event.oldState.lc < poldLcLt;
|
||||
};
|
||||
},
|
||||
oldLcLe: function (pattern) {
|
||||
const poldLcLe = pattern.oldLcLe;
|
||||
return function (event) {
|
||||
return event.oldState.lc <= poldLcLe;
|
||||
};
|
||||
},
|
||||
|
||||
from: (pattern) => stringOrRegExpCompare(pattern, 'from',
|
||||
(event) => event && event.newState && event.newState.from
|
||||
),
|
||||
|
||||
fromNe: (pattern) => !stringOrRegExpCompare(pattern, 'fromNe',
|
||||
(event) => event && event.newState && event.newState.from
|
||||
),
|
||||
|
||||
oldFrom: (pattern) => stringOrRegExpCompare(pattern, 'oldFrom',
|
||||
(event) => event && event.oldState && event.oldState.from
|
||||
),
|
||||
|
||||
oldFromNe: (pattern) => !stringOrRegExpCompare(pattern, 'oldFromNe',
|
||||
(event) => event && event.oldState && event.oldState.from
|
||||
),
|
||||
|
||||
channelId: (pattern) => stringOrRegExpCompare(pattern, 'channelId'),
|
||||
channelName: (pattern) => stringOrRegExpCompare(pattern, 'channelName'),
|
||||
deviceId: (pattern) => stringOrRegExpCompare(pattern, 'deviceId'),
|
||||
deviceName: (pattern) => stringOrRegExpCompare(pattern, 'deviceName'),
|
||||
|
||||
enumId: (pattern) => {
|
||||
/** @type {RegExp | string | string[]} */
|
||||
const penumId = pattern.enumId;
|
||||
|
||||
function ensureEnumIDsIsArray(enumIds) {
|
||||
if (!Array.isArray(enumIds)) {
|
||||
console.error(`enumIds is of type ${typeof enumIds} but should be an array: ${JSON.stringify(enumIds)}`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isRegExp(penumId)) {
|
||||
return function (event) {
|
||||
const enumIds = event.enumIds;
|
||||
if (enumIds == null || !ensureEnumIDsIsArray(enumIds)) return false;
|
||||
// Test if any enum name matches the regex:
|
||||
return enumIds.find(e => /** @type {RegExp} */ (penumId).test(e)) != null;
|
||||
};
|
||||
} else if (Array.isArray(penumId)) {
|
||||
return function (event) {
|
||||
const enumIds = event.enumIds;
|
||||
if (enumIds == null || !ensureEnumIDsIsArray(enumIds)) return false;
|
||||
// Test if the enum names of the event and the given array intersect
|
||||
return enumIds.find(e => penumId.indexOf(e) > -1) != null;
|
||||
};
|
||||
} else {
|
||||
return function (event) {
|
||||
const enumIds = event.enumIds;
|
||||
if (enumIds == null || !ensureEnumIDsIsArray(enumIds)) return false;
|
||||
return (enumIds && enumIds.indexOf(penumId) !== -1);
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
enumName: function (pattern) {
|
||||
/** @type {RegExp | string | string[]} */
|
||||
const penumName = pattern.enumName;
|
||||
|
||||
function ensureEnumNamesIsArray(enumNames) {
|
||||
if (!Array.isArray(enumNames)) {
|
||||
console.error(`enumNames is of type ${typeof enumNames} but should be an array: ${JSON.stringify(enumNames)}`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isRegExp(penumName)) {
|
||||
return function (event) {
|
||||
const enumNames = event.enumNames;
|
||||
if (enumNames == null || !ensureEnumNamesIsArray(enumNames)) return false;
|
||||
// Test if any enum name matches the regex:
|
||||
return enumNames.find(e => /** @type {RegExp} */ (penumName).test(e)) != null;
|
||||
};
|
||||
} else if (Array.isArray(penumName)) {
|
||||
return function (event) {
|
||||
const enumNames = event.enumNames;
|
||||
if (enumNames == null || !ensureEnumNamesIsArray(enumNames)) return false;
|
||||
// Test if the enum names of the event and the given array intersect
|
||||
return enumNames.find(e => penumName.indexOf(e) > -1) != null;
|
||||
};
|
||||
} else {
|
||||
return function (event) {
|
||||
const enumNames = event.enumNames;
|
||||
if (enumNames == null || !ensureEnumNamesIsArray(enumNames)) return false;
|
||||
return (enumNames && enumNames.indexOf(penumName) !== -1);
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module.exports = patternCompareFunctions;
|
||||
2365
lib/sandbox.js
Normal file
2365
lib/sandbox.js
Normal file
File diff suppressed because it is too large
Load Diff
82
lib/utils.js
Normal file
82
lib/utils.js
Normal file
@@ -0,0 +1,82 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
/**
|
||||
* returns application name
|
||||
*
|
||||
* The name of the application can be different and this function finds it out.
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
function getAppName() {
|
||||
const parts = __dirname.replace(/\\/g, '/').split('/');
|
||||
return parts[parts.length - 2].split('.')[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* looks for js-controller home folder
|
||||
*
|
||||
* @param {boolean} isInstall
|
||||
* @returns {string}
|
||||
*/
|
||||
function getControllerDir(isInstall) {
|
||||
// Find the js-controller location
|
||||
const possibilities = [
|
||||
'yunkong2.js-controller',
|
||||
'yunkong2.js-controller',
|
||||
];
|
||||
/** @type {string} */
|
||||
let controllerPath;
|
||||
for (const pkg of possibilities) {
|
||||
try {
|
||||
const possiblePath = require.resolve(pkg);
|
||||
if (fs.existsSync(possiblePath)) {
|
||||
controllerPath = possiblePath;
|
||||
break;
|
||||
}
|
||||
} catch (e) { /* not found */ }
|
||||
}
|
||||
if (controllerPath == null) {
|
||||
if (!isInstall) {
|
||||
console.log('Cannot find js-controller');
|
||||
process.exit(10);
|
||||
} else {
|
||||
process.exit();
|
||||
}
|
||||
}
|
||||
// we found the controller
|
||||
return path.dirname(controllerPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* reads controller base settings
|
||||
*
|
||||
* @alias getConfig
|
||||
* @returns {object}
|
||||
*/
|
||||
function getConfig() {
|
||||
let configPath;
|
||||
if (fs.existsSync(
|
||||
configPath = path.join(controllerDir, 'conf', appName + '.json')
|
||||
)) {
|
||||
return JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||
} else if (fs.existsSync(
|
||||
configPath = path.join(controllerDir, 'conf', + appName.toLowerCase() + '.json')
|
||||
)) {
|
||||
return JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
||||
} else {
|
||||
throw new Error('Cannot find ' + controllerDir + '/conf/' + appName + '.json');
|
||||
}
|
||||
}
|
||||
const appName = getAppName();
|
||||
const controllerDir = getControllerDir(typeof process !== 'undefined' && process.argv && process.argv.indexOf('--install') !== -1);
|
||||
const Adapter = require(path.join(controllerDir, 'lib/adapter.js'));
|
||||
|
||||
module.exports = {
|
||||
controllerDir,
|
||||
getConfig,
|
||||
Adapter,
|
||||
appName
|
||||
};
|
||||
69
lib/words.js
Normal file
69
lib/words.js
Normal file
@@ -0,0 +1,69 @@
|
||||
/* global systemDictionary: true */
|
||||
'use strict';
|
||||
let systemLang = 'en';
|
||||
let systemDictionary = {};
|
||||
|
||||
/* eslint-disable quotes */
|
||||
systemDictionary = {
|
||||
"was not executed, while debug mode is active": {
|
||||
"en": 'was not executed, while debug mode is active',
|
||||
"de": 'was not executed, while debug mode is active',
|
||||
"ru": 'was not executed, while debug mode is active'
|
||||
}
|
||||
};
|
||||
/* eslint-enable quotes */
|
||||
|
||||
function setLanguage(language) {
|
||||
systemLang = language;
|
||||
}
|
||||
|
||||
function translateWord(text, lang, dictionary) {
|
||||
if (!text) return '';
|
||||
lang = lang || systemLang;
|
||||
dictionary = dictionary || systemDictionary;
|
||||
|
||||
if (dictionary[text]) {
|
||||
let newText = dictionary[text][lang];
|
||||
if (newText) {
|
||||
return newText;
|
||||
} else if (lang !== 'en') {
|
||||
newText = dictionary[text].en;
|
||||
if (newText) {
|
||||
return newText;
|
||||
}
|
||||
}
|
||||
} else if (typeof text === 'string' && !text.match(/_tooltip$/)) {
|
||||
console.log('"' + text + '": {"en": "' + text + '", "de": "' + text + '", "ru": "' + text + '"},');
|
||||
} else if (typeof text !== 'string') {
|
||||
console.warn('Trying to translate non-text:' + text);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
function _(text, arg1, arg2, arg3) {
|
||||
text = translateWord(text);
|
||||
|
||||
let pos = text.indexOf('%s');
|
||||
if (pos !== -1) {
|
||||
text = text.replace('%s', arg1);
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
|
||||
pos = text.indexOf('%s');
|
||||
if (pos !== -1) {
|
||||
text = text.replace('%s', arg2);
|
||||
} else {
|
||||
return text;
|
||||
}
|
||||
|
||||
pos = text.indexOf('%s');
|
||||
if (pos !== -1) {
|
||||
text = text.replace('%s', arg3);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
module.exports.setLanguage = setLanguage;
|
||||
module.exports._ = _;
|
||||
Reference in New Issue
Block a user