Network Discovery for JCCTerminals in Node.js – Best Practices & Code Samples

Network Discovery for JCC Terminals in Node.js – Best Practices & Code Samples

Nov 18, 2025 |

10 minutes read

Network Discovery for JCCTerminals in Node.js – Best Practices & Code Samples

Node.js Connectivity Framework for JCC POS Terminal Integration

Integrating with JCC POS Terminals often requires reliable communication over a local network. One of the biggest challenges developers face is determining whether the terminal is online, reachable, and ready to process payments before the transaction begins.

A failed connection can break the customer experience — so a solid terminal discovery and health-check mechanism is essential.

In this article, we walk through:

  • Setting up environment variables for JCC terminal connectivity
  • Writing a Node.js utility to detect a terminal via IP and port
  • Building an Express API server
  • Implementing a terminal health-check endpoint
  • Returning clear online/offline API responses

By the end, you will have a complete back-end boilerplate for JCC terminal monitoring inside your Node.js application.

Environment Variables:

Before running the Node.js service, configure your JCC terminal connection settings in a .env file:


 # JCC Terminal connection 
 JCC_TERMINAL_IP = IP of the terminal on your LAN 
 TERMINAL_PORT = Default JCC TCP port (1025)

JCC_TERMINAL_IP

The IP address of the JCC POS terminal on your local network.

TERMINAL_PORT

The TCP port used for communication — JCC terminals typically use port 1025.

These environment variables help keep your application flexible, secure, and easy to configure.

Discovering the JCC Terminal Using Node.js:

To verify that the terminal is online, we perform a simple TCP connection test using Node’s built-in net.Socket().

File: utils/discoverTerminal.js


const net = require("net"); 
 const DEFAULT_PORT = 1025; 
 
 // Broadcast logs (can be overridden) 
 let broadcastLog = (msg) => console.log(msg); 
 function setLogger(fn) { 
  broadcastLog = fn; 
 } 
 /** 
 * Discover the JCC terminal on the local LAN 
 * @param {number} port TCP port (default 1025) 
 * @param {number} timeout Timeout per IP in ms 
 * @param {number} parallel Number of parallel connections 
 * @returns {Promise} Terminal IP 
 */ 
 async function discoverTerminal(port = DEFAULT_PORT, timeout = 100) { 
  const targetIp = process.env.JCC_TERMINAL_IP; 
  if (!targetIp) throw new Error("JCC_TERMINAL_IP not set"); 
 
  broadcastLog(`[DISCOVER] Checking terminal at ${targetIp}:${port}...`); 
 
  return new Promise((resolve, reject) => { 
   const client = new net.Socket(); 
   let done = false; 
   client.setTimeout(timeout); 
   client.connect(port, targetIp, () => { 
     done = true; 
     client.destroy(); 
     broadcastLog(`[DISCOVER] Terminal found at ${targetIp}:${port}`); 
     resolve(targetIp); 
   }); 
 
   client.on("error", () => { 
     if (!done) { 
       done = true; 
       client.destroy(); 
       reject(new Error("Terminal connection error"));
       	} 
   }); 
 
   client.on("timeout", () => { 
     if (!done) { 
       done = true; 
       client.destroy(); 
       reject(new Error("Terminal discovery timeout")); 
 	} 
   }); 
 }); 
} 
 
module.exports = { 
 discoverTerminal, 
 setLogger, 
}; 

How This Works

  1. Reads the IP from .env
    The function checks process.env.JCC_TERMINAL_IP.
  2. Attempts a TCP connection
    Using Node’s built-in net.Socket().
  3. Successful connection = terminal found
    If the terminal accepts the connection, we know it is alive.
  4. Timeout or error = terminal unreachable
    The promise is rejected, allowing your app to retry or display an alert to the user.

Creating the Express Server:

File: server.js


require('dotenv').config(); 
 const express = require('express'); 
 const http = require('http'); 
 const cors = require('cors'); 
 const paymentRoute = require('./routes/payment'); 
 
 const app = express(); 
 const PORT = 3001; 
 const server = http.createServer(app);
 app.use(cors()); 
 app.use(express.json()); 
 app.use('/api/payment', paymentRoute); 
 
 server.listen(PORT, () => console.log(`Server running at http://localhost:${PORT}`));

Adding a Terminal Health Check API:

File: routes/payment.js


const express = require("express"); 
 const router = express.Router(); 
 const { discoverTerminal } = require("../utils/discoverTerminal"); 
 const CACHE_TTL = 60 * 1000; 
 
 let cachedTerminal = { ip: null, port: process.env.TERMINAL_PORT, lastChecked: 0 }; 
 const port = process.env.TERMINAL_PORT; 
 
 router.get("/check-jcc", async (req, res) => { 
  const now = Date.now(); 
  if (cachedTerminal.ip && now - cachedTerminal.lastChecked < CACHE_TTL) { 
    return res.json({ status: "online", ip: cachedTerminal.ip, port:  cachedTerminal.port, cached: true }); 
 } 
 
 try { 
   const ip = await discoverTerminal(port, 200, 20); 
   cachedTerminal = { ip, port, lastChecked: now }; 
   return res.json({ status: "online", ip, port, cached: false }); 
 } catch { 
   if (cachedTerminal.ip) { 
     return res.json({ status: "online", ip: cachedTerminal.ip, port: cachedTerminal.port, cached: true, fallback: true }); 
   } else { 
     return res.json({ status: "offline", error: "Terminal not found", code: "TERMINAL_NOT_FOUND" }); 
   } 
 } 
}); 

Why This Endpoint Matters

  • Reduces repeated terminal scans using caching
  • Helps UI show terminal status instantly
  • Provides fallback behavior if the terminal briefly drops
  • Ensures payments only start when the terminal is reachable

Running & Testing the Endpoint:

Start the server: node server.js

Visit in browser or Postman

http://localhost:3000/api/payment/check-jcc

Output:

When the JCC Terminal is ONLINE:

Case A: Fresh discovery (not cached)

If the terminal responds successfully:


{ 
  "status": "online", 
  "ip": "YOUR_TERMINAL_IP", 
  "port": "1025", 
  "cached": false 
 }

Case B: Cached result (within 60 seconds)

If the terminal was already discovered recently:


{ 
  "status": "online", 
  "ip": "YOUR_TERMINAL_IP", 
  "port": "1025", 
  "cached": true 
 }

Case C: Terminal fails now, but the old cached IP exists (fallback)

If discovery fails but you have a previously known IP, it falls back to cached data:


 { 
  "status": "online", 
  "ip": "YOUR_CACHED_TERMINAL_IP", 
  "port": "1025", 
  "cached": true, 
  “fallback”: true 
 } 

When the JCC Terminal is OFFLINE:


{ 
  "status": "offline", 
  "error": "Terminal not found", 
  "code": "TERMINAL_NOT_FOUND" 
 } 

This is the final failure state when no cached valid IP exists.

Node.js powers smarter, faster JCC terminal discovery

The Way Forward

With this setup, you now have a reliable method to:

  • Automatically detect if a JCC POS Terminal is connected
  • Cache discovery responses to minimize delays
  • Provide REST APIs for terminal health monitoring
  • Keep your payment flow stable and predictable

This pattern is ideal for POS systems, kiosks, checkout counters, and any environment where JCC devices are used.

Free Consultation

    Mayur Dosi

    I am Assistant Project Manager at iFlair, specializing in PHP, Laravel, CodeIgniter, Symphony, JavaScript, JS frameworks ,Python, and DevOps. With extensive experience in web development and cloud infrastructure, I play a key role in managing and delivering high-quality software solutions. I am Passionate about technology, automation, and scalable architectures, I am ensures seamless project execution, bridging the gap between development and operations. I am adept at leading teams, optimizing workflows, and integrating cutting-edge solutions to enhance performance and efficiency. Project planning and good strategy to manage projects tasks and deliver to clients on time. Easy to adopt new technologies learn and work on it as per the new requirments and trends. When not immersed in code and project planning, I am enjoy exploring the latest advancements in AI, cloud computing, and open-source technologies.



    MAP_New

    Global Footprints

    Served clients across the globe from38+ countries

    iFlair Web Technologies
    Privacy Overview

    This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.