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

soem-node

v1.2.1

Published

Bindings Node-API pour SOEM (Simple Open EtherCAT Master)

Readme

SOEM-Nodejs

CI/CD npm version License: GPL v2 Node.js Version Platform Coverage

Bindings Node.js haute performance pour SOEM (Simple Open EtherCAT Master) avec détection automatique des interfaces réseau et utilitaires de gestion avancés.

🚀 Fonctionnalités

  • Détection automatique d'interfaces - Trouve automatiquement les meilleures interfaces EtherCAT
  • Support multi-plateforme - Windows, Linux (x64, arm64)
  • TypeScript complet - Types de sécurité avec auto-complétion
  • API moderne - Interface intuitive et bien documentée
  • Utilitaires intégrés - Outils de gestion et de diagnostic
  • Tests complets - Suite de tests robuste avec couverture de code
  • Exemples pratiques - Cas d'usage réels et tutoriels

📦 Installation

npm install soem-node

Prérequis système

  • Node.js >= 18
  • Compilateur C/C++ (MSVC Build Tools sous Windows, gcc ou clang sous Linux)
  • Python (détecté par node-gyp)

CMake n'est plus requis : la chaîne de build utilise uniquement node-gyp et binding.gyp.

Windows

  • Npcap (recommandé) ou WinPcap (pour l'accès réseau)
    • Téléchargez depuis npcap.com
    • Installation requise pour les opérations réseau
  • Visual Studio Build Tools ou Visual Studio

Linux

  • libpcap-dev (Ubuntu/Debian) ou libpcap (autres distributions)
  • Permissions réseau pour les sockets bruts

Configuration des permissions (Linux)

Pour éviter d'exécuter en tant que root :

sudo setcap cap_net_raw,cap_net_admin+eip $(which node)

🎯 Démarrage rapide

1. Découverte des interfaces

const { SoemMaster } = require('soem-node');

// Lister toutes les interfaces disponibles
const interfaces = SoemMaster.listInterfaces();
console.log('Interfaces disponibles:', interfaces);

2. Création automatique de master

const { EtherCATUtils } = require('soem-node/examples/ethercat-utils');

// Création automatique avec la meilleure interface
const master = EtherCATUtils.createMaster();
if (master) {
  try {
    const slaves = master.configInit();
    console.log(`${slaves} esclaves EtherCAT détectés`);
  } finally {
    master.close();
  }
}

3. Communication EtherCAT complète

const { SoemMaster } = require('soem-node');

async function main() {
  const master = new SoemMaster('eth0'); // ou interface Windows
  
  if (!master.init()) {
    throw new Error('Échec d\'initialisation EtherCAT');
  }

  try {
    // Configuration
    const slaves = master.configInit();
    if (slaves > 0) {
      master.configMapPDO();
      
      // Communication cyclique
      for (let i = 0; i < 100; i++) {
        master.sendProcessdata();
        const wkc = master.receiveProcessdata();
        console.log(`Cycle ${i}: WKC=${wkc}`);
        
        await new Promise(r => setTimeout(r, 10)); // 10ms cycle
      }
      
      // Lecture SDO
      const deviceType = master.sdoRead(1, 0x1000, 0);
      if (deviceType) {
        console.log('Type de périphérique:', deviceType.readUInt32LE(0).toString(16));
      }
    }
  } finally {
    master.close();
  }
}

main().catch(console.error);

Build manuel

La construction appelle node-gyp et génère automatiquement ec_options.h via l'action déclarée dans binding.gyp (script scripts/generate-ec-options.js).

npm run build

Le binaire natif est produit dans build/Release/soem_addon.node.

Utilisation avec Electron

Basé sur Node-API (N-API) : la plupart des versions d'Electron compatibles avec le niveau N-API supporté fonctionnent sans rebuild. Si nécessaire (erreur de chargement/ABI) :

npm rebuild --runtime=electron --target=30.0.0 --dist-url=https://electronjs.org/headers

Pour electron-builder :

{
  "asarUnpack": [
    "node_modules/soem-node/build/Release/*.node"
  ]
}

Checklist rapide :

  • Installer Npcap (Windows) ou libpcap (Linux)
  • Vérifier l'architecture (x64 / arm64)
  • Ajuster les capabilities Linux (voir plus haut)

Réf. : https://www.electronjs.org/docs/latest/tutorial/native-code-and-electron

🧪 Tests et Qualité

Exécution des tests

# Tests de base
npm test

# Tests avec couverture
npm run test:ci

# Tests en mode watch
npm run test:watch

# Tous les tests (incluant ceux en développement)
npm run test:all

# Vérification du code
npm run lint

# Audit de sécurité
npm run security

Couverture de code

Le projet maintient une couverture de code élevée avec des tests unitaires et d'intégration complets :

  • ✅ Tests unitaires pour toutes les API principales
  • ✅ Tests d'intégration pour les flux de travail complets
  • ✅ Mocks intelligents pour les environnements CI/CD
  • ✅ Tests de performance et de stabilité

CI/CD

Le projet utilise GitHub Actions pour :

  • ✅ Tests automatisés sur Windows, Linux
  • ✅ Vérification TypeScript et ESLint
  • ✅ Audit de sécurité
  • ✅ Build multi-plateforme
  • ✅ Publication automatique NPM

🔧 Développement

Setup de développement

# Cloner le repository
git clone https://github.com/MXASoundNDEv/SOEM-Nodejs.git
cd SOEM-Nodejs

# Installer les dépendances
npm install

# Build du projet
npm run build

# Lancer les tests
npm test

Structure du projet

soem-node/
├── src/               # Code source TypeScript
├── examples/          # Exemples et utilitaires
├── test/              # Suite de tests
├── types/             # Définitions TypeScript
├── external/          # Sous-modules (SOEM)
├── docs/              # Documentation
└── scripts/           # Scripts utilitaires (génération options, release, CI)

Exemple

node examples/scan-and-read.js eth0

Ce script détecte les esclaves, échange les processdata et lit l'SDO 0x1000 du slave 1.

Dépannage

  • Binaire introuvable : vérifier build/Release/soem_addon.node après npm run build.
  • Erreurs compilation : vérifier Python + toolchain C/C++.
  • Accès réseau refusé : Npcap/libpcap + permissions/capabilities.
  • Rebuild forcé : npm rebuild --verbose (ajouter flags Electron si besoin).
  • Debug approfondi : node-gyp configure build --verbose.

Licence

Ce projet est distribué sous licence GPL-2.0-or-later. SOEM est GPLv2 avec exceptions ; la distribution de binaires précompilés peut imposer de publier votre code source. Une licence commerciale de SOEM est disponible pour des utilisations propriétaires.

📘 API détaillée (SoemMaster)

Cette section résume et intègre la documentation de docs/API-SoemMaster.md directement dans le README. Pour des détails supplémentaires (contexte EtherCAT, glossaire), voir le dossier docs/.

Table des matières

  1. Vue d'ensemble
  2. Import & types
  3. Cycle de vie minimal
  4. Tableau récapitulatif
  5. Référence par catégorie
    • Initialisation & découverte
    • Process Data (PDO / Groupes)
    • Accès objets (SDO / SoE / EEPROM)
    • Gestion d'état & récupération
    • Distributed Clocks & Sync
    • Accès bas-niveau (APRD/APWR/LRW/LRD/LWR)
    • Utilitaires & diagnostics
  6. Exemples avancés
  7. Erreurs & diagnostics
  8. Bonnes pratiques performance
  9. FAQ courte

1. Vue d'ensemble

SoemMaster est un wrapper TypeScript au-dessus du binding natif SOEM. Il fournit:

  • Découverte et configuration des esclaves
  • Mapping PDO et échanges cycliques
  • Lecture/écriture SDO, SoE, EEPROM
  • Primitives bas-niveau (APRD, etc.)
  • Gestion de Distributed Clocks (DC)
  • Fonctions de récupération et reconfiguration d'esclaves

Les méthodes reflètent les primitives SOEM. Les validations avancées sont faites côté natif. Vérifiez systématiquement les retours.

2. Import & types

CommonJS:

const { SoemMaster } = require('soem-node');

ESM / TypeScript:

import { SoemMaster } from 'soem-node';

Type principal supplémentaire:

interface NetworkInterface { name: string; description: string }

3. Cycle de vie minimal

new SoemMaster(ifname) -> init() -> configInit() -> (slaves > 0 ?) -> configMapPDO() -> [boucle]
  sendProcessdata(); receiveProcessdata(); (SDO/SoE accès ponctuels) -> close()

4. Tableau récapitulatif

| Méthode | Retour | Catégorie | Notes | |---------|--------|-----------|-------| | constructor(ifname?) | instance | Init | Interface réseau par défaut eth0 (adapter sous Windows) | | init() | boolean | Init | Ouvre l'interface | | configInit() | number | Découverte | Nombre d'esclaves | | configMapPDO() | void | PDO | Map processdata | | state() | number | État | Lecture cache | | readState() | number | État | Force rafraîchissement | | sdoRead(slave,i,sub,ca?) | Buffer|null | SDO | Complete Access optionnel | | sdoWrite(slave,i,sub,data,ca?) | boolean | SDO | Complete Access optionnel | | sendProcessdata() | number | PDO | Envoi cycle | | receiveProcessdata() | number | PDO | WKC / octets | | writeState(slave,state) | number | État | Workcounter/code | | stateCheck(slave,req,timeout?) | number | État | Bloque jusqu'état | | reconfigSlave(slave,timeout?) | number | Récupération | Reconfigure | | recoverSlave(slave,timeout?) | number | Récupération | >0 = ok | | slaveMbxCyclic(slave) | number | Mailbox | Active cyclique | | configDC() | boolean | DC | Active DC | | getSlaves() | any[] | Info | Métadonnées esclaves | | initRedundant(if1,if2) | boolean | Redondance | Master redondant | | configMapGroup(group?) | Buffer|null | PDO Group | Mapping groupe | | sendProcessdataGroup(group?) | number | PDO Group | Variante | | receiveProcessdataGroup(group?,timeout?) | number | PDO Group | Variante | | mbxHandler(group?,limit?) | number | Mailbox | Traitement messages | | elist2string() | string | Diagnostic | Journal erreurs | | SoEread(slave,driveNo,flags,idn) | Buffer|null | SoE | Lecture élément | | SoEwrite(slave,driveNo,flags,idn,data) | boolean | SoE | Écriture élément | | readeeprom(slave,addr,timeout?) | number | EEPROM | Lecture mot | | writeeeprom(slave,addr,data,timeout?) | number | EEPROM | Écriture mot | | APRD(ADP,ADO,length,timeout?) | Buffer|null | Bas-niveau | Application Read | | APWR(ADP,ADO,data,timeout?) | number | Bas-niveau | Application Write | | LRW(LogAdr,length,buf,timeout?) | number | Bas-niveau | Logical Read/Write | | LRD(LogAdr,length,timeout?) | Buffer|null | Bas-niveau | Logical Read | | LWR(LogAdr,data,timeout?) | number | Bas-niveau | Logical Write | | dcsync0(slave,act,CyclTime,CyclShift) | boolean | DC | Sync simple | | dcsync01(slave,act,CyclTime0,CyclTime1,CyclShift) | boolean | DC | Sync dual | | SoemMaster.listInterfaces() | NetworkInterface[] | Utilitaire | Découverte interfaces |

5. Référence par catégorie

Initialisation & découverte

init(), configInit(), configMapPDO(), initRedundant() Ordre recommandé: init -> configInit -> (slaves>0) -> configMapPDO.

Process Data (PDO / Groupes)

sendProcessdata(), receiveProcessdata(), variantes *Group() pour segmenter plusieurs groupes de slaves et gérer des cadences différentes.

Accès objets (SDO / SoE / EEPROM)

SDO: sdoRead / sdoWrite (+ flag ca Complete Access). SoE pour drives supportant protocole SoE. EEPROM pour opérations bas-niveau (attention aux timings et verrouillages matériels).

Gestion d'état & récupération

state(), readState(), writeState(), stateCheck(), reconfigSlave(), recoverSlave(). Utiliser stateCheck après une transition (ex: PRE-OP -> SAFE-OP) pour attendre de façon synchrone.

Distributed Clocks & Sync

configDC(), dcsync0(), dcsync01(). Configure la synchronisation temporelle matérielle pour minimiser la dérive. Ajuster CyclTime en ns.

Accès bas-niveau

APRD, APWR, LRW, LRD, LWR donnent un contrôle fin sur le trafic EtherCAT. Réservé aux usages avancés (diagnostic spécifique, optimisation bas-niveau, tests conformance).

Utilitaires & diagnostics

elist2string() agrège les logs internes SOEM. getSlaves() permet d'inspecter dynamiquement le bus. mbxHandler() pour traitement mailbox périodique.

6. Exemples avancés

Boucle temps réel simplifiée (pseudo 1 kHz) :

const master = new SoemMaster('eth0');
if (!master.init()) throw new Error('init failed');
try {
  const slaves = master.configInit();
  if (!slaves) return;
  master.configMapPDO();
  master.configDC();
  const periodUs = 1000; // 1 kHz
  const start = process.hrtime.bigint();
  for (let i = 0; i < 5000; i++) {
    master.sendProcessdata();
    master.receiveProcessdata();
    // Work... (lire/écrire buffers partagés)
    const target = start + BigInt(i + 1) * BigInt(periodUs) * 1000n;
    while (process.hrtime.bigint() < target) {}
  }
} finally { master.close(); }

Lecture groupée d'objets SDO (ex: indices consécutifs) :

function readU32(master, slave, index, sub) {
  const b = master.sdoRead(slave, index, sub);
  return b ? b.readUInt32LE(0) : null;
}
const items = [0x1000,0x1001,0x1008];
const results = Object.fromEntries(items.map(i => [i.toString(16), readU32(master,1,i,0)]));

Activation DC Sync simple :

if (master.configDC()) {
  master.dcsync0(1, true, 1000000, 0); // 1 ms cycle
}

Redondance :

const red = new SoemMaster('eth0');
if (red.initRedundant('eth0','eth1')) {
  // Procéder comme un master classique (configInit, etc.)
}

7. Erreurs & diagnostics

  • Retour false/null indique échec non fatal (ex: SDO non lu)
  • Exceptions: problèmes init majeurs, erreurs N-API
  • elist2string() pour journal interne après anomalies
  • Timeouts: ajuster paramètres timeout? sur méthodes correspondantes
  • WKC (Working Counter) anormal: vérifier topologie, câblage, état esclave, pertes paquets

8. Bonnes pratiques performance

  • Pré-allouer buffers pour LRW au lieu de recréer chaque cycle
  • Minimiser les appels SDO pendant la boucle temps réel (faire hors cycle ou avant)
  • Activer DC pour réduire la gigue de synchronisation
  • Sur Linux, isoler le CPU (isolcpus) et utiliser un scheduler temps réel si critique
  • Sur Windows, réduire les interruptions (désactiver services non nécessaires)

9. FAQ courte

Q: Pourquoi sdoRead retourne null ? L'esclave n'a pas répondu ou index/sub invalide. Q: Besoin de root sous Linux ? Non si capabilities cap_net_raw,cap_net_admin définies. Q: Peut-on utiliser Electron ? Oui, basé N-API; rebuild seulement si ABI incompatible. Q: Comment diagnostiquer un WKC = 0 ? Vérifier lien physique, interface sélectionnée, câbles et alimentation des esclaves.


Pour plus de détails ou contributions, consultez docs/API-SoemMaster.md et ouvrez une Issue/PR.