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 🙏

© 2026 – Pkg Stats / Ryan Hefner

connector-ws-api

v5.0.0

Published

Comprehensive WebSocket API for connector Dispensers with full command support

Downloads

7

Readme

Cash Dispenser WebSocket API

A comprehensive WebSocket-based API for communicating with Genmega cash dispensers. This package provides a complete set of methods for controlling and monitoring cash dispenser operations.

Installation

npm install dispenser-ws-api

Quick Start

import DispenserSDK from "dispenser-ws-api";

// Initialize the SDK
const dispenser = new DispenserSDK("ws://your-server-url");

// Connect to the dispenser
await dispenser.connect();

// Initialize the dispenser
await dispenser.initialize();

// Get current status
const status = await dispenser.getStatus();
console.log("Dispenser Status:", status);

// Dispense cash
await dispenser.dispense([
  { cassetteNumber: 1, count: 5, denomination: 20 }, // 5x $20 bills
  { cassetteNumber: 2, count: 2, denomination: 50 }, // 2x $50 bills
]);

API Reference

Connection Management

constructor(wsUrl)

Creates a new DispenserSDK instance.

  • wsUrl (string): WebSocket URL for the dispenser server

connect()

Establishes WebSocket connection to the dispenser.

  • Returns: Promise<string> - Resolves when connected

disconnect()

Closes the WebSocket connection.

onMessage(callback)

Registers a listener for all incoming messages.

  • callback (function): Function to call when messages are received

removeListener(callback)

Removes a message listener.

  • callback (function): The listener function to remove

Core Dispenser Operations

initialize()

Initializes the cash dispenser system.

  • Returns: Promise - Resolves when initialization is complete

getStatus()

Gets the current status of the dispenser.

  • Returns: Promise<Object> - Status information including:
    • status: Current operational status
    • error: Any error conditions
    • cassettes: Cassette status array

reset()

Resets the cash dispenser to initial state.

  • Returns: Promise - Resolves when reset is complete

dispense(cassettes)

Dispenses cash from specified cassettes.

  • cassettes (Array): Array of cassette objects:
    [
      {
        cassetteNumber: 1, // Cassette number (1-4)
        count: 5, // Number of notes
        denomination: 20, // Value per note
      },
    ];
  • Returns: Promise<Object> - Dispense result with transaction details

sendDispenseCommand(cassetteNumber, count) (Legacy)

Legacy method for dispensing from a single cassette.

  • cassetteNumber (number): Cassette number (1-4)
  • count (number): Number of notes to dispense
  • Returns: Promise - Resolves when dispense is complete

Cassette Management

getCassetteInfo()

Gets detailed information about all cassettes.

  • Returns: Promise<Object> - Cassette information including counts and denominations

getCashLevels()

Gets current cash levels for all cassettes.

  • Returns: Promise<Array> - Array of cassette levels

setCassetteDenomination(cassetteNumber, denomination)

Sets the denomination for a specific cassette.

  • cassetteNumber (number): Cassette number
  • denomination (number): Note denomination value
  • Returns: Promise - Resolves when denomination is set

setCassetteCount(cassetteNumber, count)

Sets the note count for a cassette (used during refilling).

  • cassetteNumber (number): Cassette number
  • count (number): Number of notes
  • Returns: Promise - Resolves when count is set

Configuration & Control

setConfiguration(config)

Sets dispenser configuration.

  • config (Object): Configuration object
  • Returns: Promise - Resolves when configuration is applied

getConfiguration()

Gets current dispenser configuration.

  • Returns: Promise<Object> - Current configuration

setEnabled(enabled)

Enables or disables the dispenser.

  • enabled (boolean): Enable/disable state
  • Returns: Promise - Resolves when state is changed

lock()

Locks the dispenser (prevents operations).

  • Returns: Promise - Resolves when locked

unlock()

Unlocks the dispenser.

  • Returns: Promise - Resolves when unlocked

Testing & Maintenance

selfTest(options)

Performs self-test of dispenser mechanisms.

  • options (Object): Test configuration options
  • Returns: Promise<Object> - Test results

calibrate()

Calibrates the dispenser mechanisms.

  • Returns: Promise - Resolves when calibration is complete

performMaintenance(operation, parameters)

Performs maintenance operations.

  • operation (string): Maintenance operation type
  • parameters (Object): Operation parameters
  • Returns: Promise - Resolves when maintenance is complete

testSensors(sensorIds)

Tests specific sensors.

  • sensorIds (Array): Array of sensor IDs to test
  • Returns: Promise<Object> - Test results

getSensorReadings()

Gets current sensor readings.

  • Returns: Promise<Object> - Sensor data

Monitoring & Logging

getErrorLogs(options)

Retrieves error logs from the dispenser.

  • options (Object): Filter options for logs
  • Returns: Promise<Array> - Array of error log entries

clearErrorLogs()

Clears the error log.

  • Returns: Promise - Resolves when logs are cleared

getTransactionHistory(options)

Gets transaction history.

  • options (Object): Filter options
  • Returns: Promise<Array> - Array of transaction records

Limits & Security

setLimits(limits)

Sets dispenser operational limits.

  • limits (Object): Limit configuration:
    {
      dailyLimit: 10000,      // Daily cash limit
      transactionLimit: 1000, // Per-transaction limit
      hourlyLimit: 5000       // Hourly limit
    }
  • Returns: Promise - Resolves when limits are set

getLimits()

Gets current operational limits.

  • Returns: Promise<Object> - Current limits

Emergency Operations

emergencyStop()

Immediately halts all dispenser operations.

  • Returns: Promise - Resolves when stopped

resumeOperations()

Resumes operations after emergency stop.

  • Returns: Promise - Resolves when resumed

System Information

getFirmwareVersion()

Gets firmware version information.

  • Returns: Promise<Object> - Firmware version details

updateFirmware(firmwareData)

Updates dispenser firmware (if supported).

  • firmwareData (Object): Firmware update data
  • Returns: Promise - Resolves when update is complete

verifyFunctionality()

Verifies overall dispenser functionality.

  • Returns: Promise<Object> - Verification results

Event Handling

The SDK emits various events that you can listen for:

dispenser.onMessage((data) => {
  switch (data.type) {
    case "STATUS_UPDATE":
      console.log("Status changed:", data.status);
      break;
    case "ERROR":
      console.error("Dispenser error:", data.error);
      break;
    case "DISPENSE_COMPLETE":
      console.log("Dispense completed:", data.result);
      break;
    case "CASH_LOW":
      console.warn("Cash low in cassette:", data.cassetteNumber);
      break;
    case "MAINTENANCE_REQUIRED":
      console.warn("Maintenance required:", data.details);
      break;
  }
});

Error Handling

All methods return promises that can be caught for error handling:

try {
  await dispenser.dispense([{ cassetteNumber: 1, count: 5, denomination: 20 }]);
  console.log("Dispense successful");
} catch (error) {
  console.error("Dispense failed:", error.message);
}

Example Usage

Complete Transaction Flow

import DispenserSDK from "dispenser-ws-api";

class ATMController {
  constructor(wsUrl) {
    this.dispenser = new DispenserSDK(wsUrl);
    this.setupEventListeners();
  }

  async initialize() {
    try {
      await this.dispenser.connect();
      await this.dispenser.initialize();

      const status = await this.dispenser.getStatus();
      console.log("Dispenser ready:", status);

      return true;
    } catch (error) {
      console.error("Initialization failed:", error);
      return false;
    }
  }

  async dispenseCash(amount) {
    try {
      // Check cash levels first
      const levels = await this.dispenser.getCashLevels();
      console.log("Current cash levels:", levels);

      // Calculate optimal note combination
      const cassettes = this.calculateOptimalDispense(amount, levels);

      // Perform dispense
      const result = await this.dispenser.dispense(cassettes);
      console.log("Dispense completed:", result);

      return result;
    } catch (error) {
      console.error("Dispense failed:", error);
      throw error;
    }
  }

  calculateOptimalDispense(amount, levels) {
    // Your logic to calculate optimal note combination
    // This is a simplified example
    const cassettes = [];

    // Try to use largest denominations first
    if (amount >= 100 && levels[3].count > 0) {
      const count = Math.min(Math.floor(amount / 100), levels[3].count);
      cassettes.push({ cassetteNumber: 4, count, denomination: 100 });
      amount -= count * 100;
    }

    if (amount >= 50 && levels[2].count > 0) {
      const count = Math.min(Math.floor(amount / 50), levels[2].count);
      cassettes.push({ cassetteNumber: 3, count, denomination: 50 });
      amount -= count * 50;
    }

    if (amount >= 20 && levels[1].count > 0) {
      const count = Math.min(Math.floor(amount / 20), levels[1].count);
      cassettes.push({ cassetteNumber: 2, count, denomination: 20 });
      amount -= count * 20;
    }

    if (amount >= 10 && levels[0].count > 0) {
      const count = Math.min(Math.floor(amount / 10), levels[0].count);
      cassettes.push({ cassetteNumber: 1, count, denomination: 10 });
      amount -= count * 10;
    }

    if (amount > 0) {
      throw new Error(
        "Cannot dispense exact amount with available denominations"
      );
    }

    return cassettes;
  }

  setupEventListeners() {
    this.dispenser.onMessage((data) => {
      switch (data.type) {
        case "CASH_LOW":
          this.handleLowCash(data);
          break;
        case "ERROR":
          this.handleError(data);
          break;
        case "MAINTENANCE_REQUIRED":
          this.handleMaintenanceRequired(data);
          break;
      }
    });
  }

  handleLowCash(data) {
    console.warn(
      `Cash low in cassette ${data.cassetteNumber}: ${data.remainingCount} notes`
    );
    // Implement notification logic
  }

  handleError(data) {
    console.error(`Dispenser error: ${data.error}`);
    // Implement error handling logic
  }

  handleMaintenanceRequired(data) {
    console.warn(`Maintenance required: ${data.details}`);
    // Implement maintenance scheduling logic
  }
}

// Usage
const atm = new ATMController("ws://localhost:3000");
await atm.initialize();
await atm.dispenseCash(200); // Dispense $200

WebSocket Message Format

All messages follow this format:

{
  messageId: 123,                    // Unique message ID
  type: "COMMAND_TYPE",              // Command type
  timestamp: "2024-01-01T00:00:00Z", // ISO timestamp
  // ... command-specific payload
}

Response format:

{
  messageId: 123,                    // Matching request message ID
  type: "RESPONSE_TYPE",             // Response type
  success: true,                     // Success/failure flag
  timestamp: "2024-01-01T00:00:00Z", // ISO timestamp
  data: { /* response data */ },     // Response payload
  error: "Error message"             // Error message (if success: false)
}

License

ISC

Support

For support and issues, please contact the development team or refer to the Genmega documentation.