npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

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 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[] {