soem-node
v1.2.1
Published
Bindings Node-API pour SOEM (Simple Open EtherCAT Master)
Maintainers
Readme
SOEM-Nodejs
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-nodePré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-gypetbinding.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 buildLe 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/headersPour 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 securityCouverture 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 testStructure 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 eth0Ce 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.nodeaprèsnpm 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
- Vue d'ensemble
- Import & types
- Cycle de vie minimal
- Tableau récapitulatif
- 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
- Exemples avancés
- Erreurs & diagnostics
- Bonnes pratiques performance
- 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/nullindique é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
LRWau 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.
