@binaryme/open-zone
TypeScript icon, indicating that this package has built-in type declarations

1.4.0 • Public • Published

open-zone

An EyezOn EnvisaLink-MQTT bridge. See the npm package.

The EnvisaLink™ EVL-4EZR interface module.

An app that received commands from the EnvisaLink module and publishes states to an MQTT broker.

CLI

Usage: open-zone <command> [options]

Commands:
  mqtt      communicates EnvisaLink commands to MQTT
  log       prints MQTT-destined traffic to stdout instead

Options:
  -h, --host <value>    the host of the module (default: localhost)
  -p, --port <value>    the module TCP port number (default: 4025)
  -s, --pass <value>    the password to authenticate with after the TCP
connection is established (default: user)
  -c, --code <value>    the keypad code used to disarm (default: 1234)
  -u, --url <value>     the MQTT broker URL (default: mqtt://localhost)
  -t, --topic <value>   the MQTT topic for publishing states (default:
open-zone)
      --mqtt-username   an optional MQTT broker username
      --mqtt-password   an optional MQTT broker password
  -l, --log <value>     extra logging for socket connection issues

Environment variables may also be used to set any of the options prepended with OZ_.

Example: OZ_PASS=user open-zone mqtt -h 192.168.0.3 -u mqtt://192.168.0.2;

A config file named .open-zone-config.json may also be used.

Example:

{
  "host": "192.168.0.10",
  "port": "4025",
  "pass": "user",
  "code": "1234",
  "url": "mqtts://myserver.com:8883",
  "topic": "alarm",
  "log": 1,
  "mqttUsername": "open-zone",
  "mqttPassword": "password123",
}

MQTT messages

Zone states are published to tele/[topic]/zone/[zone#] (and retained) as JSON with the following properties.

{
  "id": 1, /* the zone number */
  "situation": "normal", /* | `alarm` | `tamper` | `fault` */
  "restored": true, /* the zone is either open or restored. See TPI
  commands 601 - 610 in the documentation. */
  "since": 1630748000000, /* epoch milli seconds since the last state
  change was published */
  "partition": "1" /* when the zone is part of an armed partition the
  situations `alarm` and `tamper` will be acompanied by a partition
  number */
}

Partition states are published to tele/[topic]/partition/[partition#] (and retained) as JSON with the following properties.

{
  "id": 1, /* the partition number */
  "state": "", /* `PartitionActivityType`See TPI commands 650 - 659 in the
  documentation */
  "since": 1630748000000 /* epoch milli seconds since the last state
  change was published */
}

Keypad LEDs are published to tele/[topic]/indicator/[indicator#] (and retained) as JSON with the following properties.

{
  "id": 0, /* LED index (0-7) as described in the documentation about TPI
  command 510 */
  "state": 0, /* 0=OFF, 1=ON, 2=FLASHING */
  "since": 1630748000000, /* epoch milli seconds since the last state change
  was published */
}

Troubles are published to tele/[topic]/trouble/[trouble#] (and retained) as JSON with the following properties.

{
  "id": 0, /* trouble index (0-7) as described in the documentation about
  TPI command 849 */
  "state": false, /* true if the trouble is active and needs attention */
  "since": 1630748000000, /* epoch milli seconds since the last state
  change was published */
}

Any error codes (TPI command 502) are published to tele/[topic]/error as SystemErrorCode (string).

Partition instructions are read from cmnd/[topic]/partition/[parition#]. The message payload can be either arm, arm-stay or disarm. The latter requires the code argument.

Panic instructions are read from cmnd/[topic]/panic. The message payload can be either fire, ambulance or police.

Get started

const port: number = 4025; // default
const host: string = '192.168.0.10'; // IP of your EnvisaLink
const envisaLinkPass: 'user'; // EnvisaLink TPI password

// create a subject used to send command back to the EnvisaLink TPI
const commandStreamToEnvisalink = new Subject<[string,string]>();

// callback for when login to the EnvisaLink TPI was successful
const onEnvisaLinkReady = () => {
  commandStreamToEnvisalink.next([ApplicationCommand.DumpZoneTimers,'']);
  commandStreamToEnvisalink.next([ApplicationCommand.StatusReport,'']);
}

// create the TCP socket and make an observable to stream to incoming commands
const commandStreamFromEnvisaLink$ = createCommandStream(commandStreamToEnvisalink, host, port);

// modify the command stream as you please
const commandStream$ = commandStreamFromEnvisaLink$.pipe(
  // optional out-of-the-box operator to assist with the login process
  handleCmdLogin(commandStreamToEnvisalink, envisaLinkPass, onEnvisaLinkReady),
  // it would be a good idea to multicast
  shareReplay(),
);

commandStream$
  .pipe(
    filter(([command,data]:[string,string]) => command === TPICommand.PartitionInAlarm),
  )
  .subscribe(([command,data]:[string,string]) => {
    console.log(`Partition ${data} is in alarm!`);
  });

The CLI is of course a comprehensive example.

Roadmap

  • [x] Communicate zone and partition statuses
  • [x] Communicate trouble indicators
  • [x] Communicate keypad indicators
  • [x] Act on partition command (arming and panic)
  • [x] Move sensative CLI args to environment variables
  • [x] Optional CLI config file
  • [x] Provide options to connect to a MQTT broker using a username and password
  • [x] Improve connection failure handling

Package dependencies

mqtt for easy interaction with an MQTT broker

yargs to assist with CLI parameters.

rxjs as events will steam thick and fast. Observables will be a useful building block.

EnvisaLink TPI documentation

The third party inreface documentation (v1.08) can be found in this EyezOn forum thread.

Package Sidebar

Install

npm i @binaryme/open-zone

Weekly Downloads

2

Version

1.4.0

License

MIT

Unpacked Size

134 kB

Total Files

15

Last publish

Collaborators

  • gwest7