UNPKG

uhppoted

Version:

NodeJS module wrapper for the interface to UHPPOTE TCP/IP Wiegand Access Controllers

1,117 lines (1,043 loc) 57.1 kB
/** * UHPPOTE controller API implementation. * @module uhppoted */ const broadcast = require('./driver.js').broadcast const get = require('./driver.js').get const set = require('./driver.js').set const send = require('./driver.js').send const listen = require('./driver.js').listen const opcodes = require('./opcodes.js') const errors = require('./errors.js') const translate = require('./internationalisation.js').translate const log = require('./logger.js') const validate = require('./common.js').validate const resolve = require('./common.js').resolve const clamp = require('./common.js').clamp const initialise = require('./common.js').initialise module.exports = { /** * Discovers UHPPOTE controllers accessible on the local LAN. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * * @example * uhppoted.getDevices(ctx) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ getDevices: function (ctx) { return validate({}, ctx.locale) .then(() => initialise(ctx)) .then((context) => broadcast(context, opcodes.GetDevice, {})) .then((response) => translate(response, ctx.locale)) }, /** * Retrieves device information for a single UHPPOTE access controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * * @example * uhppoted.getDevice(ctx, 405419896) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.getDevice(ctx, {id:405419896, address:'192.168.1.100', protocol:'tcp'}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ getDevice: function (ctx, controller) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.GetDevice, {}, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Sets the IP address, subnet mask and gateway address for a UHPPOTE access controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {string} address IPv4 address assigned to controller * @param {string} netmask IPv4 subnet mask assigned to controller * @param {string} gateway IPv4 LAN gateway address for controller * * @example * uhppoted.setIP(ctx, 405419896, '192.168.1.100', '255.255.255.0', '192.168.1.1') * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.setIP(ctx, {id:405419896, address:'192.168.1.100', protocol:'tcp'}, 192.168.1.100', '255.255.255.0', '192.168.1.1') * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ setIP: function (ctx, controller, address, netmask, gateway) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => send( context, id, opcodes.SetIP, { address, netmask, gateway }, addr, protocol, ), ) .then((response) => translate(response, ctx.locale)) }, /** * Retrieves the IPv4 address and port to which the controller is configured to send events, as well as * the auto-send interval. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * * @example * uhppoted.getListener(ctx, 405419896) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.getListener(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ getListener: function (ctx, controller) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.GetListener, {}, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Sets the IPv4 address and port to which the controller should send events, as well as the auto-send * interval for the current status and most recent event. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {string} address IPv4 address of event listener * @param {int} port IPv4 UDP port of event listener * @param {uint8} interval Auto-send interval (seconds, in the range [0..255]). A zero value * (default) disables auto-send. * * @example * uhppoted.setListener(ctx, 405419896, '192.168.1.100', 600001, 15) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.setListener(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp' }, '192.168.1.100', 600001,15) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ setListener: function (ctx, controller, address, port, interval) { const { id, address: addr, protocol } = resolve(controller) const autosend = Number.isNaN(interval) ? 0 : clamp(interval, 0, 255) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => set( context, id, opcodes.SetListener, { address, port, interval: autosend }, addr, protocol, ), ) .then((response) => translate(response, ctx.locale)) }, /** * Retrieves the controller current date and time. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * * @example * uhppoted.getTime(ctx, 405419896) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.getTime(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ getTime: function (ctx, controller) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.GetTime, {}, addr, protocol)) .then((response) => translate(response, ctx.locale)) }, /** * Sets the controller date and time. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {string} datetime Date and time (YYYY-mm-dd HH:mm:ss) * * @example * uhppoted.setTime(ctx, 405419896, '2021-06-04 15:25:43') * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.setTime(ctx, {id:405419896, address:'192.168.1.100', protocol:'tcp'}, '2021-06-04 15:25:43') * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ setTime: function (ctx, controller, datetime) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => set(context, id, opcodes.SetTime, { datetime }, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Retrieves the door unlock duration and control mode settings from a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {uint} door Door ID in the range [1..4] * * @example * uhppoted.getDoorControl(ctx, 405419896, 3) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.getDoorControl(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}, 3) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ getDoorControl: function (ctx, controller, door) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id, door }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.GetDoorControl, { door }, addr, protocol), ) .then((response) => translate(response, ctx.locale)) .then((response) => translate(response, ctx.locale)) }, /** * Sets the door unlock duration and control mode from a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {uint} door Door ID in the range [1..4] * @param {uint} delay Door unlock duration (seconds) * @param {string} mode Door control mode ('normally open', 'normally closed' or 'controlled') * * @example * uhppoted.setDoorControl(ctx, 405419896, 3, 5, 'controlled') * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.setDoorControl(ctx, {id:405419896, address:'192.168.1.100', protocol:'tcp'}, 3, 5, 'controlled') * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ setDoorControl: function (ctx, controller, door, delay, mode) { let control = 0x00 switch (mode) { case 'normally open': control = opcodes.NormallyOpen break case 'normally closed': control = opcodes.NormallyClosed break case 'controlled': control = opcodes.Controlled break default: throw errors.InvalidDoorControl(mode, ctx.locale) } const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id, door }, ctx.locale) .then(() => initialise(ctx)) .then((context) => set( context, id, opcodes.SetDoorControl, { door, delay, control }, addr, protocol, ), ) .then((response) => translate(response, ctx.locale)) }, /** * Enables or disables door open and closed input events. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * * @example * uhppoted.recordSpecialEvents(ctx, 405419896, true) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.recordSpecialEvents(ctx, , { id:405419896, address:'192.168.1.100', protocol:'tcp'}, true) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ recordSpecialEvents: function (ctx, controller, enable) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => set( context, id, opcodes.RecordSpecialEvents, { enable }, addr, protocol, ), ) .then((response) => translate(response, ctx.locale)) }, /** * Retrieves the controller status, including the most recent event (if any). * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * * @example * uhppoted.getStatus(ctx, 405419896) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.getStatus(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ getStatus: function (ctx, controller) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.GetStatus, {}, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Retrieves the number of cards records stored in the controller (including deleted cards). * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * * @example * uhppoted.getCards(ctx, 405419896) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.getCards(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ getCards: function (ctx, controller) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.GetCards, {}, addr, protocol)) .then((response) => translate(response, ctx.locale)) }, /** * Retrieves the card record for a card number from a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {uint} card Card number * * @example * uhppoted.getCard(ctx, 405419896, 10058400) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.getCard(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}, 10058400) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ getCard: function (ctx, controller, card) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id, cardNumber: card }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.GetCardByID, { card }, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Retrieves the card record at the index from a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {uint} index Record index * * @example * uhppoted.getCardByIndex(ctx, 405419896, 23) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.getCardByIndex(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}, 23) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ getCardByIndex: function (ctx, controller, index) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id, cardIndex: index }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.GetCardByIndex, { index }, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Creates or updates a card record on a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {uint} card Card number * @param {string} validFrom Date from which card is valid (YYYY-mm-dd) * @param {string} validUntil Date ater which card is no longer valid (YYYY-mm-dd) * @param {object} doors map of doors and associated access permissions. A permission * may be true, false or a time profile in the range [2..254]. * @param {uint} PIN Optional card keypad PIN code (in the range [0..999999]) * * @example * uhppoted.putCard(ctx, 405419896, 8165538, '2021-01-01', '2021-12-31', { 1: true, 2: false, 3: 29, 4: true }, 7531) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.putCard(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}, 8165538, '2021-01-01', '2021-12-31', { 1: true, 2: false, 3: 29, 4: true }, 7531) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ putCard: function (ctx, controller, card, validFrom, validUntil, doors, PIN) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id, cardNumber: card, doors }, ctx.locale) .then(() => initialise(ctx)) .then((context) => set( context, id, opcodes.PutCard, { card, from: validFrom, to: validUntil, doors, PIN }, addr, protocol, ), ) .then((response) => translate(response, ctx.locale)) }, /** * Deletes a card record from a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {uint} card Card number * * @example * uhppoted.deleteCard(ctx, 405419896, 10058400) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.deleteCard(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}, 10058400) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ deleteCard: function (ctx, controller, card) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id, cardNumber: card }, ctx.locale) .then(() => initialise(ctx)) .then((context) => set(context, id, opcodes.DeleteCard, { card }, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Erases all card records from a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * * @example * uhppoted.deleteCards(ctx, 405419896) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.deleteCards(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ deleteCards: function (ctx, controller) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => set(context, id, opcodes.DeleteCards, {}, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Retrieves a time profile from a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {uint8} profile Time profile ID ([2..254]) * * @example * uhppoted.getTimeProfile(ctx, 405419896, 29) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.getTimeProfile(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}, 29) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ getTimeProfile: function (ctx, controller, profile) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id, profileId: profile }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get( context, id, opcodes.GetTimeProfile, { profileId: profile }, addr, protocol, ), ) .then((response) => translate(response, ctx.locale)) }, /** * Defines a time profile on a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {object} profile Time profile * * @example * uhppoted.setTimeProfile(ctx, 405419896, {...}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.setTimeProfile(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}, {...}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ setTimeProfile: function (ctx, controller, profile) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id, profile }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.SetTimeProfile, { profile }, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Deletes all time profiles from a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * * @example * uhppoted.clearTimeProfiles(ctx, 405419896) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.clearTimeProfiles(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ clearTimeProfiles: function (ctx, controller) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.ClearTimeProfiles, {}, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Clears the task list on a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * * @example * uhppoted.clearTaskList(ctx, 405419896) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.clearTaskList(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ clearTaskList: function (ctx, controller) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.ClearTaskList, {}, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Adds a task to the controller's task list. the task is not activated until refreshTaskList is * invoked. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {object} task Task definition * * @example * uhppoted.addTask(ctx, 405419896, {...}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.addTask(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}, {...}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ addTask: function (ctx, controller, task) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id, task }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.AddTask, { task }, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Refreshes the task list on a controller to activate the added tasks. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * * @example * uhppoted.refreshTaskList(ctx, 405419896) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.refreshTaskList(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ refreshTaskList: function (ctx, controller) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.RefreshTaskList, {}, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Retrieves the indices of the first and last event records stored on a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * * @example * uhppoted.getEvents(ctx, 405419896) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.getEvents(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ getEvents: function (ctx, controller) { const { id, address: addr, protocol } = resolve(controller) const first = validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.GetEvent, { index: 0 }, addr, protocol), ) const last = validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get( context, id, opcodes.GetEvent, { index: 0xffffffff }, addr, protocol, ), ) const promise = Promise.all([first, last]).then(([p, q]) => { const object = { deviceId: id, first: 0, last: 0 } if (p && p.event) { object.first = p.event.index } if (q && q.event) { object.last = q.event.index } return object }) return promise.then((response) => translate(response, ctx.locale)) }, /** * Retrieves the event record stored at the index from a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {uint} index Event index * * @example * uhppoted.getEvent(ctx, 405419896, 29) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.getEvent(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}, 29) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ getEvent: function (ctx, controller, index) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id, eventIndex: index }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.GetEvent, { index }, addr, protocol), ) .then((response) => { if ( response && response.event && response.event.type && response.event.type.code && response.event.type.code === 255 ) { throw errors.EventOverwritten(controller, index, ctx.locale) } if (response && response.event && response.event.index === 0) { throw errors.MissingEvent(controller, index, ctx.locale) } return translate(response, ctx.locale) }) }, /** * Retrieves the 'user event index' value from a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * * @example * uhppoted.getEventIndex(ctx, 405419896) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.getEventIndex(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ getEventIndex: function (ctx, controller) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => get(context, id, opcodes.GetEventIndex, {}, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Sets the 'user event index' value on a controller. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {uint} index User event index value * * @example * uhppoted.setEventIndex(ctx, 405419896, 47) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.setEventIndex(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}, 47) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ setEventIndex: function (ctx, controller, index) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id, eventIndex: index }, ctx.locale) .then(() => initialise(ctx)) .then((context) => set(context, id, opcodes.SetEventIndex, { index }, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Remotely unlocks a door. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {uint} door Door ([1..4]) * * @example * uhppoted.openDoor(ctx, 405419896, 3) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.openDoor(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}, 3) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ openDoor: function (ctx, controller, door) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id, door }, ctx.locale) .then(() => initialise(ctx)) .then((context) => set(context, id, opcodes.OpenDoor, { door }, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Enables or disables remote access control. When enabled, the controller expects a remote * host to listen for card swipe events and open the associated door (after verifying the card * access permissions). In remote access control mode, the controller will revert to local * access control if it hasn't received any communication from the host within the last 30 * seconds (any command is sufficient - a set-pc-control command is not required). A controller * will reassert remote control mode on receipt of any message from the host if it has reverted * to local access management. * * Remote access control mode is not volatile and persists across controller restarts. * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {bool} enable Enable/disable remote access control * * @example * uhppoted.setPCControl(ctx, 405419896, true) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.setPCControl(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}, true) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ setPCControl: function (ctx, controller, enable) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => set(context, id, opcodes.SetPCControl, { enable }, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Sets the controller door interlock mode: * - 0: no interlock * - 1: doors 1 & 2 interlocked * - 2: doors 3 & 4 interlocked * - 3: doors 1 & 2 and doors 3 & 4 interlocked * - 4: doors 1 & 2 & 3 interlocked * - 8: doors 1 & 2 & 3 & 4 interlocked * * @param {object} ctx Context with configuration, locale (optional) and logger (optional). * @param {uint|object} controller Either a controller serial number (legacy implementation) or an * object of the form { controller, address, protocol }: * @param {uint} controller.id Controller serial number * @param {string} controller.address Optional controller IPv4 address. Defaults to UDP broadcast. * @param {string} controller.protocol Optional connection protocol ('udp' or 'tcp'). Defaults to * 'udp' unless 'tcp' * @param {uint} interlock Interlock mode (0,1,2,3,4 or 8) * * @example * uhppoted.setInterlock(ctx, 405419896, 3) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) * * @example * uhppoted.setInterlock(ctx, { id:405419896, address:'192.168.1.100', protocol:'tcp'}, 3) * .then(response => { console.log(response) }) * .catch(err => { console.log(`${err.message}`) */ setInterlock: function (ctx, controller, interlock) { const { id, address: addr, protocol } = resolve(controller) return validate({ controller: id }, ctx.locale) .then(() => initialise(ctx)) .then((context) => set(context, id, opcodes.SetInterlock, { interlock }, addr, protocol), ) .then((response) => translate(response, ctx.locale)) }, /** * Activates and deactivates a controller's reader access keypads. The controller does not * provide the fu