V O I D spawner

@voids
+5654
с 2024

Бесконечный создатель · Infinite Creator ⌜ voidsp.com ⌟ ⌜ github.com/voidspawner ⌟ ⌜ donationalerts.com/r/voidspawner

17 подписчиков
5 подписок

Он учится на примерах людей, целый GitHub в его распоряжении. Я учусь на его примерах. Лучше оставлю все эти форумы в прошлом, как страшный сон.

Так вот это и проверим. А то мне несколько лет назад один чел доказывал, что переводчик Гугла лучше Дипла, пока я его носом не ткнул.

2

Я с ним уже научился работать. Задавать запросы небольшими блоками, а потом их связывать. Мне от него нужно понимание, как то или иное действие работает. Лопатить тонны мукалатуры, чтобы узнать, у меня совершенно нет желания. На примерах учиться гораздо быстрее.

Отлично. Значит запустить можешь. Дальше допиливай уточнениями. Хоть узнал, что это за говно такое Oracle. А то в банке с ним работал, через UI.

Ясно, но ты всё равно молодец, что чела дотащил.

Так работает код или нет? Ты его запускал? Я не ипу в Oracle.

Ответ ЖПТ
Если без бюрократии — да, за 5 минут можно накидать рабочий коннектор 😄
Не «промышленный комбайн», а реальный минимально-рабочий мост Modbus TCP → Oracle DB, который ты дальше допилишь под себя.

Ниже — Python-коннектор, потому что:

Modbus TCP в Python делается быстро (pymodbus)

Oracle — через cx_Oracle / oracledb

Отлично подходит для демона / сервиса

Архитектура (коротко)
[PLC / Modbus TCP]

pymodbus

Python mapping

Oracle DB (INSERT / MERGE)

Зависимости
pip install pymodbus oracledb


Если Oracle 12c+ — лучше oracledb (новый драйвер)

Пример таблицы в Oracle
CREATE TABLE modbus_data (
device_ip VARCHAR2(50),
register_id NUMBER,
value NUMBER,
ts TIMESTAMP DEFAULT SYSTIMESTAMP,
CONSTRAINT modbus_pk PRIMARY KEY (device_ip, register_id)
);

Коннектор Modbus TCP → Oracle
from pymodbus.client import ModbusTcpClient
import oracledb
import time

# ---------- CONFIG ----------
MODBUS_IP = "192.168.1.10"
MODBUS_PORT = 502
UNIT_ID = 1

REGISTER_START = 0
REGISTER_COUNT = 10

ORACLE_DSN = "localhost/orclpdb1"
ORACLE_USER = "modbus"
ORACLE_PASSWORD = "password"

POLL_INTERVAL = 5 # seconds
# ----------------------------

def oracle_connect():
return oracledb.connect(
user=ORACLE_USER,
password=ORACLE_PASSWORD,
dsn=ORACLE_DSN
)

def read_modbus():
client = ModbusTcpClient(MODBUS_IP, port=MODBUS_PORT)
client.connect()

result = client.read_holding_registers(
address=REGISTER_START,
count=REGISTER_COUNT,
slave=UNIT_ID
)

client.close()

if result.isError():
raise RuntimeError(result)

return result.registers

def write_oracle(values):
conn = oracle_connect()
cur = conn.cursor()

sql = """
MERGE INTO modbus_data t
USING (SELECT :device_ip device_ip,
:reg_id register_id,
:val value FROM dual) s
ON (t.device_ip = s.device_ip AND t.register_id = s.register_id)
WHEN MATCHED THEN
UPDATE SET t.value = s.value, t.ts = SYSTIMESTAMP
WHEN NOT MATCHED THEN
INSERT (device_ip, register_id, value)
VALUES (s.device_ip, s.register_id, s.value)
"""

for i, val in enumerate(values):
cur.execute(sql, {
"device_ip": MODBUS_IP,
"reg_id": REGISTER_START + i,
"val": val
})

conn.commit()
cur.close()
conn.close()

def main():
while True:
try:
values = read_modbus()
write_oracle(values)
print("OK:", values)
except Exception as e:
print("ERROR:", e)

time.sleep(POLL_INTERVAL)

if __name__ == "__main__":
main()

Что уже умеет этот коннектор

✔ Modbus TCP
✔ Holding Registers
✔ Oracle INSERT / UPDATE
✔ Работает как сервис
✔ Не теряет значения (MERGE)

Что обычно добавляют дальше (по опыту)

Если нужно — сделаю сразу:
🔄 Авто-reconnect
📊 Scaling (INT → FLOAT, pressure, temp)
🧱 Register map из JSON
🧵 Мультипоточность (несколько PLC)
🕒 Буферизация при падении Oracle
🐳 Docker
🧠 Alarm-логика (out of range)

Вопросы, которые влияют на финальную версию

Ответь коротко, и я сразу дам production-вариант:
Oracle: 11g / 12c / 19c / Autonomous?
Modbus: holding / input / coils?
Типы: int16 / int32 / float / endian?
Один PLC или много?
Нужен realtime (<1s) или polling ок?

Хочешь — следующим шагом сделаем C-версию или Java (JDBC + Netty), если Python не заходит.