keytalk-api
v1.0.15
Published
Keylogic KeyTalk API
Downloads
3
Readme
KeyTalk-API 1.0
Typescript definition included.
Installation
Using npm:
npm install keytalk-api --save
In Node.js:
// Plain JS
const kt = require("keytalk-api");
// ES6/Typescript
import * as kt from "keytalk-api";
Include additional modules as you need them:
import * as trend from "keytalk-api/trend";
import * as sh from "keytalk-api/dist/scriptHelper";
import * as x2j from "keytalk-api/dist/excel2json";
Basic usage
Setup
import kt from "keytalk-api";
let engine:kt.engine.KeyTalkEngine=new kt.engine.KeyTalkEngine();
Connect and login
engine.url="https://mysite.com/";
engine.login("user", "password").then(
() => {
// CONNECTED
// ..code goes here..
},
() => {
// FAILED
}
);
Logout
engine.logout((ci,kv)=> {
// DISCONNECTED
// ..code goes here..
});
Read value
engine.requestAsync("*time", undefined).promise().then((kv:kt.engine.IKeyTalkValue )=> {
if(kv.isValue()) {
// .. code goes here..
console.log(kv.asJavascriptValue().toString());
} else {
if(kv.isError()) {
console.log(kv.error);
}
}
});
Request will return object (variable kv above) of type kt.IKeyTalkValue
Notable members of this object are:
typ: KeyTalkValueTyp;
error?: string;
asJavascriptValue(): any;
asBool(def?: boolean): boolean;
asNumber(): number;
asString(): string;
asDate(): Date;
asDateTime(): Date;
asTimeSpan(): number;
isError(): boolean;
isNull(): boolean;
isValue(): boolean;
KeyTalkValueTyp
is a string defined in typescript as
declare type KeyTalkValueTyp = "BOOL" | "STRING" | "INT8" | "UINT8" | "INT16" | "UINT16" | "INT32" | "UINT32" | "SINGLE" | "DOUBLE" | "TIMESPAN" | "DATE" | "TIME" | "DATETIME" | "NULL" | "RAW";
isValue()
can be used to quickly determine if the received value is valid (not error & not null).
Subscribe to value
// ... code to connect engine goes here ...
let cci=engine.subscribe("*time", (ci: kt.engine.IKeyTalkClientItem, kv: kt.engine.IKeyTalkValue)=> {
if(kv.isValue()) {
// .. code goes here..
console.log(kv.asJavascriptValue());
} else {
if(kv.isError()) {
console.log(kv.error);
}
}
});
// ... code to disconnect engine goes here ...
cci
will referencing the same object as the callback parameter ci
.
To stop subscribing call
cci.cancel();
Write value
// ... code to connect engine goes here ...
engine.pokeAsync("tag", "SINGLE", "1.3",undefined).promise().then( (pr)=> {
if(pr.isError()) {
console.log(pr.error);
}
});
// ... code to disconnect engine goes here ...
The third argument to pokeAsync is the value to be written. It need to be specified as a string and formatted correctly depending on it's type (the second parameter). If the type is unknown, use requestAsync
to read it's type in the returned typ
field.
SINGLE
andDOUBLE
should use . as decimal separator, no thousands separator characters. Example:"1.23"
BOOLEAN
should be set as"true"
or"false"
RAW
should be Base64 encodedDATE
should be as"yyyy-MM-dd"
DATETIME
should be as"yyyy-MM-dd HH:mm:ss"
TIMESPAN
should be a string with time length units, examples: "10ms", "1s", "1m", "1h", "1d", "2d4h", "5m 2000ms"
Eventlog
Changes of values, logins (and more) are stored in an events log. Sometime it's better to avoid this, for example if a script logon ever 10 minutes to read a value, the events log would be drowned with uninteresting logons entires.
engine.noEvLog=true;
Trenddata (Historic data)
Get raw data
KeyTalk stores it's trend data as events. Values are periodic read, but only when the value is changes more than a threshold is a new event stored.
import * as trend from "keytalk-api/trend";
// ... code to connect engine goes here ...
let lh = new trend.v3.LoggDownloadHandler(engine, tag);
return lh.query(startDate.valueOf(), endDate).then(
(decoder: trend.trend.IDecoder) => {
while (!decoder.eof()) {
console.log(decoder.getData())
decoder.next();
}
},
(err: string) => {
console.error("Error, "+err);
return err;
}
);
// ... code to disconnect engine goes here ...
Observe, data entries outside the passed start and end range may also be returned. Data is stored in lager "blocks", and the all downloaded data will be returned.
Observe, the ´tag´ must refer to a "log object". It is most often named the same as the value tag appended with "/log". Not all value has a log object.
The getData() function of the IDecode returns a LogEntry
enum LoggerTyp {
empty = 0,
start = 1,
stop = 2,
chg = 3,
err = 4
}
interface LogEntry {
ltyp: LoggerTyp;
stamp: number; // ms sedan 1970
ktyp: KeyTyp;
val: any;
}
Helpers
Convert event data to periodic data
enum LoggStatus {
ok = 0,
error = 1,
closed = 2
}
interface LogV {
stamp: number; // ms sedan 1970
ktyp: KeyTyp;
val: any;
dval: number;
status: LoggStatus;
}
function getAllInRange2(startX: number, endX: number, timeRef: number, interv: number, ld: trend.IDecoder, onlyPositiveChange?: boolean, callback?: ((v: trend.LogV) => boolean)): trend.LogV[];
This helper function will calculate the value at every (timeRef
+ interv
* N) inside startX
and endX
.
let lh = new trend.v3.LoggDownloadHandler(engine, tag);
return lh.query(startDate.valueOf(), endDate).then(
(decoder: trend.trend.IDecoder) =>
trend.calc.getAllInRange2(startDate, endDate,
new Date(2000, 0, 1, 0, 0).valueOf(),
30 * 60 * 1000,
decoder)
)
.then( (data:trend.trend.LogV[]) => {
data.forEach(lv=>console.log(lv));
})
When reading meter values (energy, volume, ...) the values are stored as meter readings, to get the delta values between time intervals
the getAllInRangeMeterReading
function can be used.
getAllInRangeMeterReading(start: number, end: number, timeref: number, interv: number, ld: trend.IDecoder, isGrouped: boolean, callback?: ((v: trend.LogV) => boolean)): trend.LogV[];
isGrouped
should be set to false if group calculation isn't used (not yet documented)
Grouping and group functions
Need to get the average temperature per week?
Use the helper calc
to apply grouping on a list of values.
enum LoggFunc {
none = 0,
sum = 1,
average = 2,
min = 3,
max = 4
}
enum LoggGroup {
none = 0,
hour = 1,
day = 2,
week = 3,
month = 4,
year = 5
}
function calc(data: trend.LogV[], f: trend.LoggFunc, g: trend.LoggGroup,callback?:((v:trend.LogV)=>boolean)): trend.LogV[] {