keytalk-api
TypeScript icon, indicating that this package has built-in type declarations

1.0.15 • Public • Published

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 and DOUBLE should use . as decimal separator, no thousands separator characters. Example: "1.23"
  • BOOLEAN should be set as "true" or "false"
  • RAW should be Base64 encoded
  • DATE 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[] {

Readme

Keywords

none

Package Sidebar

Install

npm i keytalk-api

Weekly Downloads

0

Version

1.0.15

License

UNLICENSED

Unpacked Size

457 kB

Total Files

36

Last publish

Collaborators

  • mliesen