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.
- ✅ 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
npm install soem-node- 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.
- 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
- libpcap-dev (Ubuntu/Debian) ou libpcap (autres distributions)
- Permissions réseau pour les sockets bruts
Pour éviter d'exécuter en tant que root :
sudo setcap cap_net_raw,cap_net_admin+eip $(which node)const { SoemMaster } = require('soem-node');
// Lister toutes les interfaces disponibles
const interfaces = SoemMaster.listInterfaces();
console.log('Interfaces disponibles:', interfaces);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();
}
}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);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.
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 :
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 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 securityLe 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é
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
# 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 testsoem-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)
node examples/scan-and-read.js eth0
Ce script détecte les esclaves, échange les processdata et lit l'SDO 0x1000 du slave 1.
- 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.
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.
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/.
- 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
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.
CommonJS:
const { SoemMaster } = require('soem-node');ESM / TypeScript:
import { SoemMaster } from 'soem-node';Type principal supplémentaire:
interface NetworkInterface { name: string; description: string }new SoemMaster(ifname) -> init() -> configInit() -> (slaves > 0 ?) -> configMapPDO() -> [boucle]
sendProcessdata(); receiveProcessdata(); (SDO/SoE accès ponctuels) -> close()
| 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 |
init(), configInit(), configMapPDO(), initRedundant()
Ordre recommandé: init -> configInit -> (slaves>0) -> configMapPDO.
sendProcessdata(), receiveProcessdata(), variantes *Group() pour segmenter plusieurs groupes de slaves et gérer des cadences différentes.
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).
state(), readState(), writeState(), stateCheck(), reconfigSlave(), recoverSlave(). Utiliser stateCheck après une transition (ex: PRE-OP -> SAFE-OP) pour attendre de façon synchrone.
configDC(), dcsync0(), dcsync01(). Configure la synchronisation temporelle matérielle pour minimiser la dérive. Ajuster CyclTime en ns.
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).
elist2string() agrège les logs internes SOEM. getSlaves() permet d'inspecter dynamiquement le bus. mbxHandler() pour traitement mailbox périodique.
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.)
}- 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
- 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)
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.
{ "asarUnpack": [ "node_modules/soem-node/build/Release/*.node" ] }