소스 정보
- 저장소
- JohnNuwan/EVA_CORE
- 최근 소스 활동
- 2026년 7월 18일 08:30
- 감지된 SKILL.md 언어
- 프랑스어
- 스타
- 0
- 포크
- 0
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/JohnNuwan/EVA_CORE --skill industrial-plc-connectivity명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Concevoir et maintenir un watchdog auto-correcteur pour services HTTP — checks de santé, auto-restart, état persistant, rapports et pièges bash.
Serveur de messagerie sécurisé auto-hébergé (Signal-like) avec Flask + WebSocket + AES-256-GCM + pont EVA
ADAM-SENTINEL — Veilleur technologique 24h/24h. Scanne 10 domaines, cree des rapports, met a jour les skills, alerte sur les CVE et breaking changes.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | industrial-plc-connectivity |
| description | Écrire des scripts de connexion Snap7, pycomm3 et ADS. |
| version | 1.1.0 |
| author | EVA |
| license | Privée EVA St-Étienne |
| platforms | ["linux","macos","windows"] |
| metadata | {"tags":["siemens","rockwell","ethernet-ip","s7-protocol","cip","serial","rs232","rs485","pycomm3","snap7","pylogix","pyserial","modbus-rtu","bacnet","canopen","pyvisa","opc-da","ads","industrial-automation"],"related_skills":["industrial-protocols","industrial-edge"]} |
L'acquisition de données à la source (le capteur, l'automate, la centrale de mesure ou l'instrumentation) nécessite d'utiliser des protocoles propriétaires, bas niveau ou spécialisés par domaine (GTB, automobile, laboratoire).
Cette compétence guide l'agent EVA pour écrire des scripts d'intégration robustes pour :
pycomm3 ou pylogix.python-snap7.pyserial.pymodbus.BAC0.python-can et canopen.pyvisa et les commandes SCPI.OpenOPC.pyads.À utiliser lorsque l'utilisateur demande :
Lorsqu'une connexion échoue, l'agent doit valider si le port TCP/UDP standard est ouvert sur l'adresse IP de destination en utilisant des outils de diagnostic :
| Protocole | Port par Défaut | Type de Socket | Constructeur / Standard |
|---|---|---|---|
| S7 Protocol (S7Comm) | 102 | TCP | Siemens S7-300/400/1200/1500 |
| Modbus TCP | 502 | TCP | Schneider Modicon, variateurs, compteurs |
| EtherNet/IP (CIP) | 44818 | TCP & UDP | Rockwell ControlLogix/CompactLogix, Omron |
| TwinCAT ADS | 48898 | TCP | Beckhoff TwinCAT Runtime |
| OPC UA | 4840 | TCP | Standard Universel (OPC Foundation) |
| BACnet/IP | 47808 (0xBAC0) | UDP | GTB / CVC (Chauffage, Ventilation) |
Les automates Rockwell modernes (Logix5000) utilisent le protocole CIP (Common Industrial Protocol) basé sur des noms de variables textuels (Tags).
import time
from pycomm3 import LogixDriver, RequestError
PLC_IP = '192.168.1.10'
def read_rockwell_tags_safely():
# Connexion à l'automate. Le chemin par défaut pour le slot processeur est 0.
plc = LogixDriver(PLC_IP)
# Tentative de connexion avec gestion d'erreurs
try:
plc.open()
print(f"Connecté à l'automate Rockwell ({PLC_IP})")
# Lecture multiple (optimise les requêtes réseau)
tags = ['Moteur1_Vitesse', 'Moteur1_Defaut', 'Machine_Statut']
results = plc.read(*tags)
for res in results:
if res.error is None:
print(f"Tag '{res.tag}' = {res.value} (Qualité: Good)")
else:
print(f"Tag '{res.tag}' - Erreur de lecture : {res.error}")
# Écriture d'un Tag avec validation de retour
write_res = plc.write('Moteur1_Consigne', 1500.0)
if write_res.error:
print(f"Échec d'écriture : {write_res.error}")
except RequestError as err:
print(f"Erreur CIP de l'automate : {err}")
except Exception e:
()
:
plc.close()
__name__ == :
read_rockwell_tags_safely()
Le protocole Siemens S7 est basé sur des adresses physiques directes organisées en Data Blocks (DB).
import time
import snap7
from snap7.util import get_real, set_real
from snap7.exceptions import Snap7Exception
PLC_IP = '192.168.1.100'
DB_NUMBER = 10
def connect_and_read_s7():
client = snap7.client.Client()
connected = False
# Boucle de reconnexion (tentatives toutes les 5 secondes en cas de défaillance)
while not connected:
try:
print(f"Tentative de connexion au Siemens S7 ({PLC_IP})...")
# IP, Rack (0), Slot (1 pour S7-1200/1500, 2 pour S7-300/400)
client.connect(PLC_IP, 0, 1)
connected = client.get_connected()
except Snap7Exception as err:
print(f"Échec de connexion : {err}. Retentative dans 5 secondes...")
time.sleep(5)
print("Connecté au Siemens S7.")
try:
# Lire 4 octets dans le DB à partir de l'offset 0 (ex: un Real/Float)
buffer = client.db_read(DB_NUMBER, 0, 4)
vitesse = get_real(buffer, 0)
print("Vitesse lue :", vitesse)
# Écrire un Real (50.5) dans le DB à l'offset 4
write_buffer = bytearray(4)
set_real(write_buffer, 0, 50.5)
client.db_write(DB_NUMBER, 4, write_buffer)
()
Snap7Exception e:
()
:
client.disconnect()
()
__name__ == :
connect_and_read_s7()
pyserialimport serial
ser = serial.Serial(
port='COM3', # '/dev/ttyUSB0' sous Linux
baudrate=9600,
bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=1.5 # Timeout de lecture en secondes
)
try:
if not ser.is_open:
ser.open()
ser.write(b'GET_WEIGHT\r\n')
ligne = ser.readline().decode('ascii').strip()
print("Donnée reçue :", ligne)
finally:
if ser.is_open:
ser.close()
from pymodbus.client import ModbusSerialClient
client = ModbusSerialClient(
port='COM3',
baudrate=9600,
parity='N',
stopbits=1,
bytesize=8,
timeout=2.0
)
if client.connect():
result = client.read_holding_registers(address=0, count=10, slave=3)
if not result.isError():
print("Registres Modbus RTU :", result.registers)
else:
print("Erreur Modbus RTU :", result)
client.close()
Le protocole BACnet est le standard de la GTB/GTC (Gestion Technique du Bâtiment).
import BAC0
# Initialisation locale du client BACnet (port UDP standard 47808 / 0xBAC0)
bacnet = BAC0.connect(ip='192.168.1.50')
# Lecture d'un point analogique (Analog Input 1) sur un automate de ventilation (ID 100)
temp = bacnet.read('192.168.1.150 analogInput 1 presentValue')
print(f"Température lue : {temp} °C")
# Écriture d'une consigne sur une sortie analogique (Analog Output 2, priorité 8)
bacnet.write('192.168.1.150 analogOutput 2 presentValue 21.0 - 8')
bacnet.disconnect()
python-can) :import can
bus = can.interface.Bus(bustype='pcan', channel='PCAN_USBBUS1', bitrate=250000)
# Envoi d'une trame CAN standard (ID 0x181, 8 octets)
msg = can.Message(arbitration_id=0x181, data=[0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00], is_extended_id=False)
bus.send(msg)
# Lecture d'un message avec un timeout de 2.0s
msg_recu = bus.recv(timeout=2.0)
if msg_recu:
print(f"Trame reçue - ID: {hex(msg_recu.arbitration_id)} - Data: {list(msg_recu.data)}")
bus.shutdown()
canopen) :import canopen
network = canopen.Network()
network.connect(bustype='pcan', channel='PCAN_USBBUS1', bitrate=125000)
# Déclaration d'un nœud (ID 2) et chargement de son dictionnaire d'objets EDS
node = network.add_node(2, 'profile_moteur.eds')
# Lecture d'un objet (Index 0x1018, Sub-index 1 : Vendor ID) via SDO
vendor_id = node.sdo[0x1018][1].raw
print("Vendor ID :", vendor_id)
# Écriture d'une vitesse cible (Index 0x60FF)
node.sdo[0x60FF].raw = 3000
network.disconnect()
Permet de communiquer avec des appareils de mesure (multimètres, oscilloscopes, générateurs) via GPIB, USB ou Ethernet (LXI) en utilisant des commandes standardisées SCPI.
import pyvisa
rm = pyvisa.ResourceManager()
scope = rm.open_resource('TCPIP0::192.168.1.80::inst0::INSTR')
scope_id = scope.query('*IDN?')
print("Appareil détecté :", scope_id.strip())
scope.write('AUTOSCALE')
scope.write('ACQUIRE:TYPE NORMAL')
scope.close()
Le standard historique basé sur la couche DCOM de Microsoft Windows.
import OpenOPC
opc = OpenOPC.client()
opc.connect('Matrikon.OPC.Simulation.1')
valeur, qualite, timestamp = opc.read('Random.Int4')
print(f"Valeur : {valeur} (Qualité: {qualite})")
opc.write(('Bucket Brigade.Real4', 15.6))
opc.close()
import pyads
plc = pyads.Connection('192.168.1.10.1.1', 851)
plc.open()
vitesse = plc.read_by_name('Main.fVitesseActuelle', pyads.PLCTYPE_REAL)
print("Vitesse Beckhoff ADS :", vitesse)
plc.write_by_name('Main.bDemarrageMoteur', True, pyads.PLCTYPE_BOOL)
plc.close()
Depuis juillet 2026, EVA Agent dispose d'outils intégrés pour la communication PLC en temps réel. Contrairement aux scripts standalone ci-dessus, ces outils s'appellent directement depuis l'agent via registry.register().
| Outil | Description | Dépendance |
|---|---|---|
plc_read(plc_type, endpoint, tag_path) | Lecture temps réel de tag | python-snap7 (S7), pylogix (Rockwell), pycomm3 (EIP) |
plc_write(plc_type, endpoint, tag_path, value) | Écriture temps réel | (idem) |
plc_probe(endpoint, timeout) | Détection auto du type PLC | socket (stdlib) |
plc_type | Librairie | Constructeurs |
|---|---|---|
s7 | python-snap7 | Siemens S7-1200/1500/300/400 |
rockwell | pylogix | Rockwell ControlLogix / CompactLogix |
eip | pycomm3 | Allen-Bradley via EtherNet/IP |
Siemens S7 — adressage physique (nécessite accès optimisé désactivé) :
DB1.DBX0.0 → DB 1, Byte 0, Bit 0DB1.DBD2 → DB 1, Double Word à offset 2DB1.DBW6 → DB 1, Word à offset 6MW100 → Merker Word 100MB50 → Merker Byte 50Rockwell / EIP — adressage par nom :
MyProgram.MyTag (tag structuré)Moteur1_Vitesse (tag simple)python-snap7 / pylogix / pycomm3 ci-dessus (quand le code doit tourner sur une machine sans EVA ou dans un pipeline CI/CD).plc_read / plc_write / plc_probe (quand l'agent a besoin de lire/écrire pendant une conversation).plc_probe en premier pour détecter le type, puis plc_read avec le bon plc_type.Access Denied ou erreur hexadécimale 0x20000003).1 pour les gammes S7-1200/1500, et Slot 2 pour les gammes historiques S7-300/400.ser.readline() ou ser.read() si l'équipement série n'envoie rien.timeout=1.0 (ou supérieur) lors de l'instanciation de serial.Serial.AccessDenied ou port COM indisponible).pyserial définissent une valeur de timeout explicite.try/finally ou gérées via des gestionnaires de contexte (with) pour s'assurer que les connexions soient proprement fermées en fin de script.