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

@samlab-corp/usb-relay-hid

v1.0.0

Published

Advanced USB HID Relay controller for Node.js with auto-reconnect, handshake validation, and event-based monitoring

Readme

USB Relay HID Controller

고급 USB HID 릴레이 제어 라이브러리로, 자동 재연결, 핸드셰이크 검증, 이벤트 기반 모니터링 기능을 제공합니다.

npm version License: MIT

✨ 주요 기능

  • 🔌 자동 장치 검색 및 연결: USB 릴레이 장치 자동 탐지
  • 🔄 자동 재연결: 연결 끊김 시 자동으로 재연결 시도
  • 🤝 핸드셰이크 검증: 장치 연결 시 통신 검증
  • 📊 실시간 상태 모니터링: 릴레이 상태 폴링 및 이벤트 알림
  • 이벤트 기반 아키텍처: EventEmitter 기반 비동기 처리
  • 🛡️ 에러 복구: 자동 재시도 및 에러 핸들링
  • 📝 상세한 로깅: 디버깅을 위한 로그 시스템
  • 🎯 TypeScript 지원: 타입 정의 포함

📦 설치

npm install usb-relay-hid

시스템 요구사항

  • Node.js >= 14.0.0
  • USB HID 릴레이 장치 (VID: 0x16c0, PID: 0x05df)

Windows

추가 설정 불필요

Linux

# USB 접근 권한 설정
sudo usermod -a -G plugdev $USER

macOS

# Xcode Command Line Tools 필요
xcode-select --install

🚀 빠른 시작

기본 사용법

const USBRelayController = require('usb-relay-hid');

// 컨트롤러 인스턴스 생성
const relay = new USBRelayController({
  autoReconnect: true,
  reconnectInterval: 1000,  // 1초마다 재연결 시도
  enableLogging: true
});

// 장치 연결
async function main() {
  // 1. 장치 검색
  const devices = relay.enumerate();
  console.log(`발견된 장치: ${devices.length}개`);

  // 2. 첫 번째 장치 연결
  const success = await relay.open();

  if (success) {
    console.log('연결 성공!');

    // 3. 릴레이 제어
    await relay.openRelay(1);   // 릴레이 1번 열기
    await relay.closeRelay(1);  // 릴레이 1번 닫기

    // 4. 모든 릴레이 제어
    await relay.openAllRelays();
    await relay.closeAllRelays();

    // 5. 상태 확인
    const status = relay.getAllRelayStates();
    console.log('릴레이 상태:', status);
  }
}

main();

이벤트 기반 사용

const relay = new USBRelayController();

// 연결 이벤트
relay.on('connected', (data) => {
  console.log('장치 연결됨:', data.deviceInfo);
  console.log('초기 상태:', data.status);
});

// 연결 끊김 이벤트
relay.on('disconnected', () => {
  console.log('장치 연결 끊김');
});

// 재연결 이벤트
relay.on('reconnecting', () => {
  console.log('재연결 시도 중...');
});

relay.on('reconnected', () => {
  console.log('재연결 성공!');
});

// 릴레이 상태 변경 이벤트
relay.on('relay-changed', (data) => {
  console.log(`릴레이 ${data.channel}: ${data.state ? '열림' : '닫힘'}`);
});

// 상태 폴링 이벤트
relay.on('status-changed', (data) => {
  console.log('상태 변경 감지:', {
    이전: data.oldStatus,
    현재: data.newStatus
  });
});

// 에러 이벤트
relay.on('error', (data) => {
  console.error('에러 발생:', data.error);
});

// 장치 연결
await relay.open();

📖 API 문서

생성자 옵션

new USBRelayController(options)

| 옵션 | 타입 | 기본값 | 설명 | |------|------|--------|------| | autoReconnect | boolean | true | 자동 재연결 활성화 | | reconnectInterval | number | 1000 | 재연결 시도 간격 (ms) | | maxRetries | number | 3 | 명령 재시도 최대 횟수 | | commandTimeout | number | 1000 | 명령 타임아웃 (ms) | | statusPollingInterval | number | 0 | 상태 폴링 간격 (0=비활성화) | | enableLogging | boolean | true | 로깅 활성화 |

메서드

장치 관리

// 장치 검색
relay.enumerate() // => Array<DeviceInfo>

// 장치 연결
await relay.open(serialNumber?) // => Promise<boolean>

// 장치 연결 해제
relay.close() // => void

// 연결 상태 확인
relay.isDeviceConnected() // => boolean

// 장치 정보 가져오기
relay.getDeviceInfo() // => DeviceInfo | null

릴레이 제어

// 특정 릴레이 열기 (켜기)
await relay.openRelay(channel) // channel: 1-8

// 특정 릴레이 닫기 (끄기)
await relay.closeRelay(channel) // channel: 1-8

// 모든 릴레이 열기
await relay.openAllRelays()

// 모든 릴레이 닫기
await relay.closeAllRelays()

// 릴레이 토글
await relay.toggleRelay(channel)

상태 확인

// 전체 상태 확인 (비트마스크)
relay.getStatus() // => number

// 특정 릴레이 상태
relay.getRelayStatus(channel) // => boolean | null

// 모든 릴레이 상태 배열
relay.getAllRelayStates() // => Array<boolean>

이벤트

| 이벤트 | 인자 | 설명 | |--------|------|------| | connected | { deviceInfo, status } | 장치 연결 성공 | | disconnected | - | 장치 연결 해제 | | reconnecting | - | 재연결 시도 중 | | reconnected | - | 재연결 성공 | | handshake-failed | { error } | 핸드셰이크 실패 | | connection-failed | { error } | 연결 실패 | | relay-changed | { channel, state } | 릴레이 상태 변경 | | all-relays-changed | { state } | 모든 릴레이 상태 변경 | | status-changed | { oldStatus, newStatus } | 상태 변경 감지 | | command-failed | { command, error } | 명령 실행 실패 | | device-error | { error } | 장치 에러 | | error | { type, error } | 일반 에러 |

💡 예제

1. 간단한 릴레이 제어

const USBRelayController = require('usb-relay-hid');

async function simpleControl() {
  const relay = new USBRelayController();

  await relay.open();

  // 릴레이 1번 1초 동안 켜기
  await relay.openRelay(1);
  await new Promise(resolve => setTimeout(resolve, 1000));
  await relay.closeRelay(1);

  relay.close();
}

simpleControl();

2. 순차 제어

async function sequentialControl() {
  const relay = new USBRelayController({ enableLogging: false });

  await relay.open();

  // 릴레이 1-8 순차 제어
  for (let i = 1; i <= 8; i++) {
    console.log(`릴레이 ${i} 켜기`);
    await relay.openRelay(i);
    await new Promise(resolve => setTimeout(resolve, 500));

    console.log(`릴레이 ${i} 끄기`);
    await relay.closeRelay(i);
    await new Promise(resolve => setTimeout(resolve, 500));
  }

  relay.close();
}

3. 상태 모니터링

const relay = new USBRelayController({
  statusPollingInterval: 1000 // 1초마다 상태 폴링
});

relay.on('status-changed', (data) => {
  const oldBinary = data.oldStatus.toString(2).padStart(8, '0');
  const newBinary = data.newStatus.toString(2).padStart(8, '0');

  console.log(`상태 변경: 0b${oldBinary} → 0b${newBinary}`);
});

await relay.open();

4. 자동 재연결

const relay = new USBRelayController({
  autoReconnect: true,
  reconnectInterval: 1000  // 1초마다 재연결 시도
});

relay.on('disconnected', () => {
  console.log('⚠️ USB 연결이 끊어졌습니다');
});

relay.on('reconnecting', () => {
  console.log('🔄 재연결 시도 중...');
});

relay.on('reconnected', () => {
  console.log('✅ 재연결 성공!');
});

await relay.open();

// USB를 뽑았다 다시 꽂으면 자동으로 재연결됩니다

5. 에러 처리

const relay = new USBRelayController();

relay.on('error', (data) => {
  console.error(`에러 발생 [${data.type}]:`, data.error.message);
});

relay.on('command-failed', (data) => {
  console.error(`명령 실패 [${data.command}]:`, data.error);
});

try {
  await relay.open();
  await relay.openRelay(1);
} catch (error) {
  console.error('치명적 에러:', error);
}

🔧 고급 사용

TypeScript 사용

import USBRelayController from 'usb-relay-hid';

const relay = new USBRelayController({
  autoReconnect: true,
  reconnectInterval: 1000,  // 1초마다 재연결 시도
  maxRetries: 5,
  enableLogging: true
});

relay.on('connected', (data) => {
  console.log('Device:', data.deviceInfo.product);
});

await relay.open();

Express.js와 함께 사용

const express = require('express');
const USBRelayController = require('usb-relay-hid');

const app = express();
const relay = new USBRelayController();

app.use(express.json());

// 릴레이 제어 API
app.post('/relay/:channel/open', async (req, res) => {
  const channel = parseInt(req.params.channel);
  const success = await relay.openRelay(channel);
  res.json({ success, channel, state: 'open' });
});

app.post('/relay/:channel/close', async (req, res) => {
  const channel = parseInt(req.params.channel);
  const success = await relay.closeRelay(channel);
  res.json({ success, channel, state: 'closed' });
});

app.get('/status', (req, res) => {
  const states = relay.getAllRelayStates();
  res.json({ states });
});

// 서버 시작
relay.open().then(() => {
  app.listen(3000, () => {
    console.log('릴레이 제어 서버 실행 중: http://localhost:3000');
  });
});

🖥️ GUI 애플리케이션

이 패키지는 Electron 기반 GUI 애플리케이션도 포함하고 있습니다.

npm start          # GUI 앱 실행
npm run dev        # 개발 모드 (로그 활성화)
npm run build      # 실행 파일 빌드

🛠️ 문제 해결

USB 장치를 찾을 수 없음

const devices = relay.enumerate();
if (devices.length === 0) {
  console.log('USB 릴레이 장치가 연결되지 않았습니다');
  console.log('- USB 케이블 확인');
  console.log('- 드라이버 설치 확인');
  console.log('- VID/PID 확인: 0x16c0/0x05df');
}

연결은 되지만 제어가 안됨

relay.on('handshake-failed', (data) => {
  console.error('핸드셰이크 실패:', data.error);
  console.log('장치가 올바른 USB 릴레이인지 확인하세요');
});

Linux 권한 문제

# udev 규칙 추가
sudo nano /etc/udev/rules.d/99-usb-relay.rules

# 다음 내용 추가:
# SUBSYSTEM=="usb", ATTR{idVendor}=="16c0", ATTR{idProduct}=="05df", MODE="0666"

# udev 재시작
sudo udevadm control --reload-rules
sudo udevadm trigger

📄 라이선스

MIT License - 자유롭게 사용하세요!

🤝 기여

이슈와 풀 리퀘스트를 환영합니다!

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📞 지원

🙏 감사의 말

  • node-hid - USB HID 통신 라이브러리
  • USB 릴레이 커뮤니티의 모든 기여자분들

Made with ❤️ by Samlab Corp