Seda Elektronik AI Uyumlu Ethernet ve USB IO Kartları

AI & Machine Learning Uyumlu IO Çözümleri

Python ve Node.js ile Yapay Zeka Destekli Röle Kontrolü ve Giriş Takip

MQTT ve Makine Öğrenmesi Tabanlı Otomasyon

📄Hızlı Bakış Kontrol Parametreleri - Ethernet - Usb ( 7 PYTHON DOC Header, module docstring, usage header )

Python, Node.js MQTT, Modbus TCP ve HTTP ile çalışan Ethernet & USB IO kartları — yapay zekâ projelerinizi fiziksel dünyaya bağlayın.

Yapay Zekâ Destekli Donanım Entegrasyonu - Makine Öğrenmesi PYTHON ve NODE JS Api Örnekleri
AI ML Röle Kontrol - Seda Elektronik

AI Karar Tabanlı Röle Kontrolü

Makine öğrenimi çıktılarıyla otomatik röle, alarm ve yük kontrolü.

Edge AI & Sensör Analizi

Gaz, sıcaklık, nem ve dijital giriş verileriyle anomali tespiti.

MQTT & Event-Driven Mimari

AI olaylarıyla düşük gecikmeli tetikleme ve uzaktan kontrol.

Endüstriyel AI Entegrasyonu

SCADA, Modbus TCP ve server tabanlı AI sistemleriyle uyum.

Yapay Zeka asistanımızı deneyin

Meta LLM 3.1 70b parametrelidir. buradan test edin.,

Python node.js & AI Uyumluluğu

Python ve node.js tabanlı AI modelleri; TensorFlow, PyTorch veya özel algoritmalar ile üretilen kararlar, Ethernet veya USB üzerinden IO kartlarımıza doğrudan uygulanabilir. Aşağıdaki Get, Tcp, Udp read-write-sensor USB Hid Cdc kod örneklerini Ürünlerimizle Python Node.js projelerinizde kullanabilirsiniz.

Aşağıdaki Get, Tcp, Udp read-write-sensor USB Hid Cdc kod örneklerini Ürünlerimizle Python projelerinizde kullanabilirsiniz.

C# delphi vbnet ve diğer dillerin ethernet örneklerini buradan, usb örneklerini buradan inceleyebilir, Canlı Demo Testlerini buradan yapabilirsiniz. Yapay zeka ile kullanmak istediğiniz bütün sensörleri, dijital io'ları ai projenize aktarırız.

NODE.JS ve PHYTON GET TCP UDP READ-WRITE SENSOR DS18B20 ÖRNEK KODLAR İNDİRİLEBİLİR. BURADAN ve BURADAN, İNDİREBİLİRSİNİZ.
KOD TESTLERİ İÇİN bolt.new KULLANILABİLİR

Güncel Kod Listesi (08 Mart 2026):

1-1 PYTHON API GET TCP MODBUS UDP MAIN.PY


# ============================================================
#  main.py  –  Seda Elektronik sedaio API Kod Rehberi
#  Bu dosya bir KOD REHBERİDİR. Kullanmak istediğiniz
#  bölümün yorum (#) işaretini kaldırın ve çalıştırın.
# ============================================================

# GEREKSİNİMLER:
#   pip install requests
#   py -m pip install requests veya python -m pip install requests
#
# DOSYA YAPISI:
#   project/
#       sedaio.py   <-- API kütüphanesi (bu dosyayla aynı klasörde olmalı)
#       main.py     <-- bu dosya

from sedaio import (
    HttpRelay, TcpRelay, UdpRelay,
    # --- Röle AÇMA ---
    R1_1, R2_1, R3_1, R4_1, R5_1, R6_1, R7_1, R8_1,
    R9_1, R10_1, R11_1, R12_1, R13_1, R14_1, R15_1, R16_1,
    # --- Röle KAPATMA ---
    R1_0, R2_0, R3_0, R4_0, R5_0, R6_0, R7_0, R8_0,
    R9_0, R10_0, R11_0, R12_0, R13_0, R14_0, R15_0, R16_0,
    # --- Röle TOGGLE ---
    R1_T, R2_T, R3_T, R4_T, R5_T, R6_T, R7_T, R8_T,
    R9_T, R10_T, R11_T, R12_T, R13_T, R14_T, R15_T, R16_T,
    # --- Özel ---
    ALL, OFF, NetCon,
    # --- TCP Linkage ---
    linkage_1_8, normal_1_8, linkage_9_16, normal_9_16,
    la_no_1_8, la_no_9_16,
)

# ============================================================
#  BAĞLANTI BİLGİLERİ  –  IP ve Port numarasını değiştirin
# ============================================================

IP   = "169.254.1.2" # Ethernet röle kartınızın ip no ve port numaralarını bu alana giriniz.
PORT = 3000


# ╔══════════════════════════════════════════════════════════╗
#  1. BÖLÜM: HTTP GET  (HttpRelay)
# ╚══════════════════════════════════════════════════════════╝
#
#  Nesneyi if __name__ == "__main__": bloğu içinde oluşturun.
#  Böylece cihaza ulaşılamasa bile import sırasında hata almazsınız.
#
#  get = HttpRelay(IP, PORT)

# ── A) Röle Açma ─────────────────────────────────────────
# get.relay_on(R1_1)    # Röle 1  aç  -> GET /1
# get.relay_on(R2_1)    # Röle 2  aç  -> GET /2
# get.relay_on(R3_1)    # Röle 3  aç  -> GET /3
# get.relay_on(R4_1)    # Röle 4  aç  -> GET /4
# get.relay_on(R5_1)    # Röle 5  aç  -> GET /5
# get.relay_on(R6_1)    # Röle 6  aç  -> GET /6
# get.relay_on(R7_1)    # Röle 7  aç  -> GET /7
# get.relay_on(R8_1)    # Röle 8  aç  -> GET /8
# get.relay_on(R9_1)    # Röle 9  aç  -> GET /9
# get.relay_on(R10_1)   # Röle 10 aç  -> GET /0
# get.relay_on(R11_1)   # Röle 11 aç  -> GET /a
# get.relay_on(R12_1)   # Röle 12 aç  -> GET /b
# get.relay_on(R13_1)   # Röle 13 aç  -> GET /c
# get.relay_on(R14_1)   # Röle 14 aç  -> GET /d
# get.relay_on(R15_1)   # Röle 15 aç  -> GET /e
# get.relay_on(R16_1)   # Röle 16 aç  -> GET /L
# get.relay_on(ALL)     # Tüm röleler aç -> GET /ALL

# ── B) Röle Kapatma ───────────────────────────────────────
# get.relay_off(R1_0)   # Röle 1  kapat -> GET /i
# get.relay_off(R2_0)   # Röle 2  kapat -> GET /g
# get.relay_off(R3_0)   # Röle 3  kapat -> GET /h
# get.relay_off(R4_0)   # Röle 4  kapat -> GET /j
# get.relay_off(R5_0)   # Röle 5  kapat -> GET /k
# get.relay_off(R6_0)   # Röle 6  kapat -> GET /l
# get.relay_off(R7_0)   # Röle 7  kapat -> GET /m
# get.relay_off(R8_0)   # Röle 8  kapat -> GET /n
# get.relay_off(R9_0)   # Röle 9  kapat -> GET /o
# get.relay_off(R10_0)  # Röle 10 kapat -> GET /p
# get.relay_off(R11_0)  # Röle 11 kapat -> GET /q
# get.relay_off(R12_0)  # Röle 12 kapat -> GET /t
# get.relay_off(R13_0)  # Röle 13 kapat -> GET /u
# get.relay_off(R14_0)  # Röle 14 kapat -> GET /v
# get.relay_off(R15_0)  # Röle 15 kapat -> GET /w
# get.relay_off(R16_0)  # Röle 16 kapat -> GET /M
# get.relay_off(OFF)    # Tüm röleler kapat -> GET /OFF

# ── C) Röle Toggle ────────────────────────────────────────
# get.relay_toggle(R1_T)    # Röle 1  toggle -> GET /y0
# get.relay_toggle(R2_T)    # Röle 2  toggle -> GET /y1
# get.relay_toggle(R3_T)    # Röle 3  toggle -> GET /y2
# get.relay_toggle(R4_T)    # Röle 4  toggle -> GET /y3
# get.relay_toggle(R5_T)    # Röle 5  toggle -> GET /y4
# get.relay_toggle(R6_T)    # Röle 6  toggle -> GET /y5
# get.relay_toggle(R7_T)    # Röle 7  toggle -> GET /y6
# get.relay_toggle(R8_T)    # Röle 8  toggle -> GET /y7
# get.relay_toggle(R9_T)    # Röle 9  toggle -> GET /z0
# get.relay_toggle(R10_T)   # Röle 10 toggle -> GET /z1
# get.relay_toggle(R11_T)   # Röle 11 toggle -> GET /z2
# get.relay_toggle(R12_T)   # Röle 12 toggle -> GET /z3
# get.relay_toggle(R13_T)   # Röle 13 toggle -> GET /z4
# get.relay_toggle(R14_T)   # Röle 14 toggle -> GET /z5
# get.relay_toggle(R15_T)   # Röle 15 toggle -> GET /z6
# get.relay_toggle(R16_T)   # Röle 16 toggle -> GET /z7

# ── D) Durum Okuma ────────────────────────────────────────
# Tek seferlik okuma:
# status = get.read_status()
# print(status)
# Örnek çıktı:
# {"PORTB": "00000101", "PORTD": "00000000", "PORTA": "11111111",
#  "PORTE": "00000000", "TEMP1": 22.3, "TEMP2": 22.2}
# PORT değerleri 8 haneli binary string: bit0=Röle1, bit1=Röle2 ...

# Her 400ms'de sürekli okuma (Ctrl+C ile durdurulur):
# get.read_status_loop()

# ── E) Ağ Konfigürasyonu Okuma ────────────────────────────
# Cihazın IP, Gateway, Subnet Mask bilgilerini gösterir:
# print(get.config())
# Örnek çıktı:
# NETWORK IP:= 169.254.1.2 PORTNO: 3000 GATEWAY:= 169.254.1.1 SUBNET MASK:= 255.255.255.0


# ╔══════════════════════════════════════════════════════════╗
#  2. BÖLÜM: TCP MODBUS RTU  (TcpRelay)
# ╚══════════════════════════════════════════════════════════╝
#
#  Nesneyi if __name__ == "__main__": bloğu içinde oluşturun.
#  Böylece cihaza ulaşılamasa bile import sırasında hata almazsınız.
#  Bağlantı kesilirse arka planda (non-blocking) yeniden bağlanır.
#  Bağlantı sonunda tcp.disconnect() çağrın.
#
#  tcp = TcpRelay(IP, PORT)

# ── A) Röle Açma ─────────────────────────────────────────
# tcp.relay_on(R1_1)    # Röle 1  aç   (Relay 0 on)
# tcp.relay_on(R2_1)    # Röle 2  aç   (Relay 1 on)
# tcp.relay_on(R3_1)    # Röle 3  aç
# tcp.relay_on(R4_1)    # Röle 4  aç
# tcp.relay_on(R5_1)    # Röle 5  aç
# tcp.relay_on(R6_1)    # Röle 6  aç
# tcp.relay_on(R7_1)    # Röle 7  aç
# tcp.relay_on(R8_1)    # Röle 8  aç
# tcp.relay_on(R9_1)    # Röle 9  aç
# tcp.relay_on(R10_1)   # Röle 10 aç
# tcp.relay_on(R11_1)   # Röle 11 aç
# tcp.relay_on(R12_1)   # Röle 12 aç
# tcp.relay_on(R13_1)   # Röle 13 aç
# tcp.relay_on(R14_1)   # Röle 14 aç
# tcp.relay_on(R15_1)   # Röle 15 aç
# tcp.relay_on(R16_1)   # Röle 16 aç
# tcp.relay_on(ALL)     # Tüm röleler aç

# ── B) Röle Kapatma ───────────────────────────────────────
# tcp.relay_off(R1_0)   # Röle 1  kapat
# tcp.relay_off(R2_0)   # Röle 2  kapat
# tcp.relay_off(R3_0)   # Röle 3  kapat
# tcp.relay_off(R4_0)   # Röle 4  kapat
# tcp.relay_off(R5_0)   # Röle 5  kapat
# tcp.relay_off(R6_0)   # Röle 6  kapat
# tcp.relay_off(R7_0)   # Röle 7  kapat
# tcp.relay_off(R8_0)   # Röle 8  kapat
# tcp.relay_off(R9_0)   # Röle 9  kapat
# tcp.relay_off(R10_0)  # Röle 10 kapat
# tcp.relay_off(R11_0)  # Röle 11 kapat
# tcp.relay_off(R12_0)  # Röle 12 kapat
# tcp.relay_off(R13_0)  # Röle 13 kapat
# tcp.relay_off(R14_0)  # Röle 14 kapat
# tcp.relay_off(R15_0)  # Röle 15 kapat
# tcp.relay_off(R16_0)  # Röle 16 kapat
# tcp.relay_off(OFF)    # Tüm röleler kapat

# ── C) Linkage / Normal Mod ───────────────────────────────
# tcp.relay_la(linkage_1_8)   # 1-8 Röle LINKAGE moda geçir  (IO Board)
# tcp.relay_la(normal_1_8)    # 1-8 Röle NORMAL moda geçir
# tcp.relay_la(linkage_9_16)  # 9-16 Röle LINKAGE moda geçir (IO Board)
# tcp.relay_la(normal_9_16)   # 9-16 Röle NORMAL moda geçir

# ── D) Linkage / Normal Mod Sorgulama ─────────────────────
# tcp.relay_linkage_or_normal(la_no_1_8)   # 1-8 Röle: Linkage mı Normal mi?
# tcp.relay_linkage_or_normal(la_no_9_16)  # 9-16 Röle: Linkage mı Normal mi?

# ── E) Flash ON (index 0-47) ──────────────────────────────
# Her röle için 6 farklı süre seçeneği mevcuttur (800ms-5000ms).
# Gruplama: Her grup 6 index. No.0=index 0-5, No.1=index 6-11 ...
#
# tcp.flash_on(0)   # No.0 Relay1  800ms
# tcp.flash_on(1)   # No.0 Relay1 1000ms
# tcp.flash_on(2)   # No.0 Relay1 2000ms
# tcp.flash_on(3)   # No.0 Relay1 3000ms
# tcp.flash_on(4)   # No.0 Relay1 4000ms
# tcp.flash_on(5)   # No.0 Relay1 5000ms
# tcp.flash_on(6)   # No.1 Relay2  800ms
# tcp.flash_on(7)   # No.1 Relay2 1000ms
# tcp.flash_on(8)   # No.1 Relay2 2000ms
# tcp.flash_on(9)   # No.1 Relay2 3000ms
# tcp.flash_on(10)  # No.1 Relay2 4000ms
# tcp.flash_on(11)  # No.1 Relay2 5000ms
# tcp.flash_on(12)  # No.2 Relay3  800ms
# tcp.flash_on(13)  # No.2 Relay3 1000ms
# tcp.flash_on(14)  # No.2 Relay3 2000ms
# tcp.flash_on(15)  # No.2 Relay3 3000ms
# tcp.flash_on(16)  # No.2 Relay3 4000ms
# tcp.flash_on(17)  # No.2 Relay3 5000ms
# tcp.flash_on(18)  # No.3 Relay4  800ms
# tcp.flash_on(19)  # No.3 Relay4 1000ms
# tcp.flash_on(20)  # No.3 Relay4 2000ms
# tcp.flash_on(21)  # No.3 Relay4 3000ms
# tcp.flash_on(22)  # No.3 Relay4 4000ms
# tcp.flash_on(23)  # No.3 Relay4 5000ms
# tcp.flash_on(24)  # No.4 Relay5  800ms
# tcp.flash_on(25)  # No.4 Relay5 1000ms
# tcp.flash_on(26)  # No.4 Relay5 2000ms
# tcp.flash_on(27)  # No.4 Relay5 3000ms
# tcp.flash_on(28)  # No.4 Relay5 4000ms
# tcp.flash_on(29)  # No.4 Relay5 5000ms
# tcp.flash_on(30)  # No.5 Relay6  800ms
# tcp.flash_on(31)  # No.5 Relay6 1000ms
# tcp.flash_on(32)  # No.5 Relay6 2000ms
# tcp.flash_on(33)  # No.5 Relay6 3000ms
# tcp.flash_on(34)  # No.5 Relay6 4000ms
# tcp.flash_on(35)  # No.5 Relay6 5000ms
# tcp.flash_on(36)  # No.6 Relay7  800ms
# tcp.flash_on(37)  # No.6 Relay7 1000ms
# tcp.flash_on(38)  # No.6 Relay7 2000ms
# tcp.flash_on(39)  # No.6 Relay7 3000ms
# tcp.flash_on(40)  # No.6 Relay7 4000ms
# tcp.flash_on(41)  # No.6 Relay7 5000ms
# tcp.flash_on(42)  # No.7 Relay8  800ms
# tcp.flash_on(43)  # No.7 Relay8 1000ms
# tcp.flash_on(44)  # No.7 Relay8 2000ms
# tcp.flash_on(45)  # No.7 Relay8 3000ms
# tcp.flash_on(46)  # No.7 Relay8 4000ms
# tcp.flash_on(47)  # No.7 Relay8 5000ms

# ── F) Flash OFF (index 0-47) ─────────────────────────────
# tcp.flash_off(0)   # No.0 Relay1  800ms
# tcp.flash_off(1)   # No.0 Relay1 1000ms
# tcp.flash_off(2)   # No.0 Relay1 2000ms
# tcp.flash_off(3)   # No.0 Relay1 3000ms
# tcp.flash_off(4)   # No.0 Relay1 4000ms
# tcp.flash_off(5)   # No.0 Relay1 5000ms
# tcp.flash_off(6)   # No.1 Relay2  800ms
# tcp.flash_off(7)   # No.1 Relay2 1000ms
# tcp.flash_off(8)   # No.1 Relay2 2000ms
# tcp.flash_off(9)   # No.1 Relay2 3000ms
# tcp.flash_off(10)  # No.1 Relay2 4000ms
# tcp.flash_off(11)  # No.1 Relay2 5000ms
# tcp.flash_off(12)  # No.2 Relay3  800ms
# tcp.flash_off(13)  # No.2 Relay3 1000ms
# tcp.flash_off(14)  # No.2 Relay3 2000ms
# tcp.flash_off(15)  # No.2 Relay3 3000ms
# tcp.flash_off(16)  # No.2 Relay3 4000ms
# tcp.flash_off(17)  # No.2 Relay3 5000ms
# tcp.flash_off(18)  # No.3 Relay4  800ms
# tcp.flash_off(19)  # No.3 Relay4 1000ms
# tcp.flash_off(20)  # No.3 Relay4 2000ms
# tcp.flash_off(21)  # No.3 Relay4 3000ms
# tcp.flash_off(22)  # No.3 Relay4 4000ms
# tcp.flash_off(23)  # No.3 Relay4 5000ms
# tcp.flash_off(24)  # No.4 Relay5  800ms
# tcp.flash_off(25)  # No.4 Relay5 1000ms
# tcp.flash_off(26)  # No.4 Relay5 2000ms
# tcp.flash_off(27)  # No.4 Relay5 3000ms
# tcp.flash_off(28)  # No.4 Relay5 4000ms
# tcp.flash_off(29)  # No.4 Relay5 5000ms
# tcp.flash_off(30)  # No.5 Relay6  800ms
# tcp.flash_off(31)  # No.5 Relay6 1000ms
# tcp.flash_off(32)  # No.5 Relay6 2000ms
# tcp.flash_off(33)  # No.5 Relay6 3000ms
# tcp.flash_off(34)  # No.5 Relay6 4000ms
# tcp.flash_off(35)  # No.5 Relay6 5000ms
# tcp.flash_off(36)  # No.6 Relay7  800ms
# tcp.flash_off(37)  # No.6 Relay7 1000ms
# tcp.flash_off(38)  # No.6 Relay7 2000ms
# tcp.flash_off(39)  # No.6 Relay7 3000ms
# tcp.flash_off(40)  # No.6 Relay7 4000ms
# tcp.flash_off(41)  # No.6 Relay7 5000ms
# tcp.flash_off(42)  # No.7 Relay8  800ms
# tcp.flash_off(43)  # No.7 Relay8 1000ms
# tcp.flash_off(44)  # No.7 Relay8 2000ms
# tcp.flash_off(45)  # No.7 Relay8 3000ms
# tcp.flash_off(46)  # No.7 Relay8 4000ms
# tcp.flash_off(47)  # No.7 Relay8 5000ms

# ── G) Röle Durum Okuma ───────────────────────────────────
# tcp.read_relay_status_8bit()  # 1-8 Röle durumu hex olarak
# tcp.read_relay_status_9_16()  # 9-16 Röle durumu hex olarak
# tcp.RS_18_8BIT()              # 1-8 Röle durumu 1/0 olarak
# tcp.RS_916_8BIT()             # 9-16 Röle durumu 1/0 olarak

# ── H) Input Durum Okuma ──────────────────────────────────
# tcp.read_input_status()  # 8 input durumu hex olarak
# tcp.read_input_binary()  # 8 input durumu 1/0 olarak

# ── Bağlantı Kapatma ──────────────────────────────────────
# tcp.disconnect()

# ── CRC16 Flash Parametre Geliştirme ──────────────────────
# Farklı zamanlama süreleri için kendi hex parametrenizi oluşturabilirsiniz.
# Adımlar:
#   1) İlk 6 byte'ı belirleyin. Örnek: 01 05 02 00 00 07 (röle1, 700ms)
#   2) Bu 6 byte için CRC16 (Modbus, little endian) hesaplayın:
#      https://github.com/sedaelektronik/modbus-crc16-parameter-generator
#   3) CRC çıktısını (2 byte, LE) sonuna ekleyin: 01 05 02 00 00 07 8D B0
#   4) 5. byte (index 4) süreyi hex olarak tutar: 07=700ms, 0A=1000ms
#      Maksimum süre: FF FF = ~4.25 dakika
# Bu parametreyi TcpRelay._FLASH_MAP sözlüğüne ekleyerek kullanabilirsiniz.


# ╔══════════════════════════════════════════════════════════╗
#  3. BÖLÜM: UDP GET  (UdpRelay)
# ╚══════════════════════════════════════════════════════════╝
#
#  Nesneyi if __name__ == "__main__": bloğu içinde oluşturun.
#  Röle kontrolü UDP üzerinden yapılır.
#  Status okuma ve config HTTP GET üzerinden yapılır.
#  UDP ürünler aynı zamanda GET özelliğine sahiptir.
#
#  udp = UdpRelay(IP, PORT)

# ── A) Röle Açma ─────────────────────────────────────────
# udp.relay_on(R1_1)    # Röle 1  aç  -> UDP "1"
# udp.relay_on(R2_1)    # Röle 2  aç  -> UDP "2"
# udp.relay_on(R3_1)    # Röle 3  aç  -> UDP "3"
# udp.relay_on(R4_1)    # Röle 4  aç  -> UDP "4"
# udp.relay_on(R5_1)    # Röle 5  aç  -> UDP "5"
# udp.relay_on(R6_1)    # Röle 6  aç  -> UDP "6"
# udp.relay_on(R7_1)    # Röle 7  aç  -> UDP "7"
# udp.relay_on(R8_1)    # Röle 8  aç  -> UDP "8"
# udp.relay_on(R9_1)    # Röle 9  aç  -> UDP "9"
# udp.relay_on(R10_1)   # Röle 10 aç  -> UDP "0"
# udp.relay_on(R11_1)   # Röle 11 aç  -> UDP "a"
# udp.relay_on(R12_1)   # Röle 12 aç  -> UDP "b"
# udp.relay_on(R13_1)   # Röle 13 aç  -> UDP "c"
# udp.relay_on(R14_1)   # Röle 14 aç  -> UDP "d"
# udp.relay_on(R15_1)   # Röle 15 aç  -> UDP "e"
# udp.relay_on(R16_1)   # Röle 16 aç  -> UDP "L"
# udp.relay_on(ALL)     # Tüm röleler aç -> UDP "ALL"

# ── B) Röle Kapatma ───────────────────────────────────────
# udp.relay_off(R1_0)   # Röle 1  kapat -> UDP "i"
# udp.relay_off(R2_0)   # Röle 2  kapat -> UDP "g"
# udp.relay_off(R3_0)   # Röle 3  kapat -> UDP "h"
# udp.relay_off(R4_0)   # Röle 4  kapat -> UDP "j"
# udp.relay_off(R5_0)   # Röle 5  kapat -> UDP "k"
# udp.relay_off(R6_0)   # Röle 6  kapat -> UDP "l"
# udp.relay_off(R7_0)   # Röle 7  kapat -> UDP "m"
# udp.relay_off(R8_0)   # Röle 8  kapat -> UDP "n"
# udp.relay_off(R9_0)   # Röle 9  kapat -> UDP "o"
# udp.relay_off(R10_0)  # Röle 10 kapat -> UDP "p"
# udp.relay_off(R11_0)  # Röle 11 kapat -> UDP "q"
# udp.relay_off(R12_0)  # Röle 12 kapat -> UDP "t"
# udp.relay_off(R13_0)  # Röle 13 kapat -> UDP "u"
# udp.relay_off(R14_0)  # Röle 14 kapat -> UDP "v"
# udp.relay_off(R15_0)  # Röle 15 kapat -> UDP "w"
# udp.relay_off(R16_0)  # Röle 16 kapat -> UDP "M"
# udp.relay_off(OFF)    # Tüm röleler kapat -> UDP "OFF"

# ── C) Durum Okuma (HTTP GET üzerinden) ───────────────────
# Tek seferlik okuma:
# status = udp.read_status()
# print(status)
# Örnek çıktı:
# {"PORTB": "00000101", "PORTD": "00000000", "PORTA": "11111111",
#  "PORTE": "00000000", "TEMP1": 22.3, "TEMP2": 22.2}

# Her 400ms'de sürekli okuma (Ctrl+C ile durdurulur):
# udp.read_status_loop()

# ── D) Ağ Konfigürasyonu Okuma (HTTP GET üzerinden) ───────
# print(udp.config())

# ── Bağlantı Kapatma ──────────────────────────────────────
# udp.disconnect()


# ============================================================
#  ÖRNEK KULLANIM  –  aktif kod bloğu
# ============================================================

if __name__ == "__main__":
    import time

    print("=" * 50)
    print("  Seda Elektronik sedaio API – Test")
    print(f"  Hedef: {IP}:{PORT}")
    print("=" * 50)

    # Nesneler burada oluşturuluyor – cihaza ulaşılamazsa
    # sadece bu blok hata verir, import sırasında değil.
    get = HttpRelay(IP, PORT)
    tcp = TcpRelay(IP, PORT)
    udp = UdpRelay(IP, PORT)

    # --- HTTP GET örneği ---
    print("\n[GET] Röle 1 aç...")
    get.relay_on(R1_1)
    time.sleep(1)

    print("[GET] Röle 1 kapat...")
    get.relay_off(R1_0)
    time.sleep(0.5)

    print("[GET] Durum oku...")
    s = get.read_status()
    print(f"  Durum: {s}")

    # --- TCP örneği ---
    print("\n[TCP] Röle 1 aç...")
    tcp.relay_on(R1_1)
    time.sleep(1)

    print("[TCP] Röle 1 kapat...")
    tcp.relay_off(R1_0)
    time.sleep(0.5)

    print("[TCP] Röle 1 durum oku...")
    r = tcp.read_relay_status_8bit()
    if r:
        print(f"  Cevap: {r.hex(' ').upper()}")

    tcp.disconnect()

    # --- UDP örneği ---
    print("\n[UDP] Röle 1 aç...")
    udp.relay_on(R1_1)
    time.sleep(1)

    print("[UDP] Röle 1 kapat...")
    udp.relay_off(R1_0)
    time.sleep(0.5)

    print("[UDP] Durum oku (HTTP)...")
    s = udp.read_status()
    print(f"  Durum: {s}")

    udp.disconnect()

    print("\n  Tamamlandı.")

1-2 PYTHON API GET TCP MODBUS UDP SEDAIO.PY


# ============================================================
#  sedaio.py  –  Seda Elektronik Ethernet Röle Kartı API
#  Protokoller : HTTP GET | TCP Modbus RTU | UDP GET
#  Sınıflar    : HttpRelay | TcpRelay | UdpRelay
#  Versiyon    : 1.0
# ============================================================

import re
import time
import socket
import logging
import threading
import binascii

try:
    import requests
except ImportError:
    requests = None  # HttpRelay / UdpRelay.read_status için gerekli

logging.basicConfig(level=logging.INFO, format="[sedaio] %(levelname)s: %(message)s")
logger = logging.getLogger("sedaio")

# ============================================================
#  GLOBAL SABİTLER  –  GET / TCP / UDP ortak değişkenler
# ============================================================

# --- Röle AÇMA değişkenleri (Röle 1-16) ---
R1_1  = "1"
R2_1  = "2"
R3_1  = "3"
R4_1  = "4"
R5_1  = "5"
R6_1  = "6"
R7_1  = "7"
R8_1  = "8"
R9_1  = "9"
R10_1 = "0"
R11_1 = "a"
R12_1 = "b"
R13_1 = "c"
R14_1 = "d"
R15_1 = "e"
R16_1 = "L"

# --- Röle KAPATMA değişkenleri (Röle 1-16) ---
R1_0  = "i"
R2_0  = "g"
R3_0  = "h"
R4_0  = "j"
R5_0  = "k"
R6_0  = "l"
R7_0  = "m"
R8_0  = "n"
R9_0  = "o"
R10_0 = "p"
R11_0 = "q"
R12_0 = "t"
R13_0 = "u"
R14_0 = "v"
R15_0 = "w"
R16_0 = "M"

# --- Röle TOGGLE değişkenleri (GET Röle 1-16) ---
R1_T  = "y0"
R2_T  = "y1"
R3_T  = "y2"
R4_T  = "y3"
R5_T  = "y4"
R6_T  = "y5"
R7_T  = "y6"
R8_T  = "y7"
R9_T  = "z0"
R10_T = "z1"
R11_T = "z2"
R12_T = "z3"
R13_T = "z4"
R14_T = "z5"
R15_T = "z6"
R16_T = "z7"

# --- Tüm Röleler ---
ALL = "ALL"
OFF = "OFF"

# --- Network Konfigürasyon ---
NetCon = "IP?"

# --- TCP Linkage / Normal mod değişkenleri ---
linkage_1_8  = "linkage_1_8"
normal_1_8   = "normal_1_8"
linkage_9_16 = "linkage_9_16"
normal_9_16  = "normal_9_16"

# --- TCP Linkage sorgu değişkenleri ---
la_no_1_8  = "la_no_1_8"
la_no_9_16 = "la_no_9_16"


# ============================================================
#  YARDIMCI FONKSİYON
# ============================================================

def _parse_status(raw: str) -> dict:
    """
    Kartın /s endpoint'inden dönen ham metni parse eder.
    Döndürür: {"PORTB": str, "PORTD": str, "PORTA": str, "PORTE": str,
               "TEMP1": float, "TEMP2": float}
    PORT değerleri 8 haneli binary string'e dönüştürülür.
    Örn: 5 -> "00000101", 255 -> "11111111"
    """
    result = {}
    for port in ["PORTB", "PORTD", "PORTA", "PORTE"]:
        m = re.search(rf"(?:var\s+)?{port}\s*=\s*(\d+)", raw)
        if m:
            val = int(m.group(1))
            result[port] = bin(val)[2:].zfill(8)
        else:
            result[port] = "00000000"
    for temp in ["TEMP1", "TEMP2"]:
        m = re.search(rf"(?:var\s+)?{temp}\s*=\s*([\d]+\.[\d]+)", raw)
        if m:
            result[temp] = float(m.group(1))
        else:
            result[temp] = 0.0
    return result


# ============================================================
#  1) HttpRelay  –  HTTP GET Protokolü
# ============================================================

class HttpRelay:
    """
    Seda Elektronik HTTP GET Röle Kartı API sınıfı.

    Kullanım:
        get = HttpRelay("169.254.1.2", 3000)
        get.relay_on(R1_1)
        get.relay_off(R1_0)
        get.relay_toggle(R1_T)
        get.relay_on(ALL)
        get.relay_off(OFF)
        status = get.read_status()
        get.read_status_loop()
        get.config()
    """

    def __init__(self, ip: str, port: int, timeout: int = 3):
        if requests is None:
            raise ImportError("HttpRelay için 'requests' kütüphanesi gereklidir: pip install requests")
        self.ip      = ip
        self.port    = port
        self.timeout = timeout
        self._base   = f"http://{ip}:{port}"
        self._loop_running = False

    def _get(self, param: str) -> bool:
        """Ham GET isteği gönderir."""
        url = f"{self._base}/{param}"
        try:
            r = requests.get(url, timeout=self.timeout)
            r.raise_for_status()
            logger.info(f"GET {url} -> {r.status_code}")
            return True
        except Exception as e:
            logger.error(f"GET hatası ({url}): {e}")
            return False

    def relay_on(self, param: str) -> bool:
        """Röle açar. Parametre: R1_1 ... R16_1 veya ALL"""
        return self._get(param)

    def relay_off(self, param: str) -> bool:
        """Röle kapatır. Parametre: R1_0 ... R16_0 veya OFF"""
        return self._get(param)

    def relay_toggle(self, param: str) -> bool:
        """Röle toggle yapar. Parametre: R1_T ... R16_T"""
        return self._get(param)

    def read_status(self) -> dict:
        """
        /s endpoint'inden tek seferlik okuma yapar.
        Döndürür: {"PORTB": str, "PORTD": str, "PORTA": str, "PORTE": str,
                   "TEMP1": float, "TEMP2": float}
        PORT değerleri 8 haneli binary string (örn: "00000101")
        """
        url = f"{self._base}/s"
        try:
            r = requests.get(url, timeout=self.timeout)
            r.raise_for_status()
            return _parse_status(r.text)
        except Exception as e:
            logger.error(f"read_status hatası: {e}")
            return False

    def read_status_loop(self, interval: float = 0.4):
        """
        /s endpoint'inden her 400ms'de bir okuma yapar.
        Çıkmak için Ctrl+C kullanın.
        Döndürür: {"PORTB": str, "PORTD": str, "PORTA": str, "PORTE": str,
                   "TEMP1": float, "TEMP2": float}
        PORT değerleri 8 haneli binary string (örn: "00000101")
        """
        self._loop_running = True
        logger.info("read_status_loop başladı. Durdurmak için Ctrl+C.")
        try:
            while self._loop_running:
                data = self.read_status()
                if data:
                    print(data)
                time.sleep(interval)
        except KeyboardInterrupt:
            self._loop_running = False
            logger.info("read_status_loop durduruldu.")

    def config(self) -> str:
        """
        /IP? endpoint'inden ağ konfigürasyonunu okur.
        Döndürür: IP, PORTNO, GATEWAY, SUBNET MASK bilgileri (ham metin)
        """
        url = f"{self._base}/{NetCon}"
        try:
            r = requests.get(url, timeout=self.timeout)
            r.raise_for_status()
            logger.info(f"config -> {r.text.strip()}")
            return r.text.strip()
        except Exception as e:
            logger.error(f"config hatası: {e}")
            return False


# ============================================================
#  2) TcpRelay  –  TCP Modbus RTU Protokolü
# ============================================================

class TcpRelay:
    """
    Seda Elektronik TCP Modbus RTU Röle Kartı API sınıfı.
    Non-blocking otomatik yeniden bağlanma threading ile sağlanır.

    Kullanım:
        tcp = TcpRelay("169.254.1.2", 3000)
        tcp.relay_on(R1_1)
        tcp.relay_off(R1_0)
        tcp.relay_toggle(R1_T)
        tcp.relay_on(ALL)
        tcp.relay_off(OFF)
        tcp.relay_la(linkage_1_8)
        tcp.relay_la(normal_1_8)
        tcp.relay_linkage_or_normal(la_no_1_8)
        tcp.flash_on(0)   # 0-47
        tcp.flash_off(0)  # 0-47
        tcp.read_relay_status_8bit()
        tcp.read_relay_status_9_16()
        tcp.RS_18_8BIT()
        tcp.RS_916_8BIT()
        tcp.read_input_status()
        tcp.read_input_binary()
    """

    # ----------------------------------------------------------
    #  Dahili Hex Eşleştirme Sözlüğü
    # ----------------------------------------------------------
    _RELAY_MAP = {
        # -------------------------------------------------------
        # Anahtarlar global sabitlerin DEĞERLERİyle eşleşir.
        # Örn: R2_1 = "2"  →  anahtar "2"
        #      R2_0 = "g"  →  anahtar "g"
        # -------------------------------------------------------

        # 1-16 Röle ON  (Relay 0 = R1 ... Relay 15 = R16)
        "1": b'\x01\x05\x00\x00\xFF\x00\x8C\x3A',  # R1_1
        "2": b'\x01\x05\x00\x01\xFF\x00\xDD\xFA',  # R2_1
        "3": b'\x01\x05\x00\x02\xFF\x00\x2D\xFA',  # R3_1
        "4": b'\x01\x05\x00\x03\xFF\x00\x7C\x3A',  # R4_1
        "5": b'\x01\x05\x00\x04\xFF\x00\xCD\xFB',  # R5_1
        "6": b'\x01\x05\x00\x05\xFF\x00\x9C\x3B',  # R6_1
        "7": b'\x01\x05\x00\x06\xFF\x00\x6C\x3B',  # R7_1
        "8": b'\x01\x05\x00\x07\xFF\x00\x3D\xFB',  # R8_1
        "9": b'\x01\x05\x00\x08\xFF\x00\x0D\xF8',  # R9_1
        "0": b'\x01\x05\x00\x09\xFF\x00\x5C\x38',  # R10_1
        "a": b'\x01\x05\x00\x0A\xFF\x00\xAC\x38',  # R11_1
        "b": b'\x01\x05\x00\x0B\xFF\x00\xFD\xF8',  # R12_1
        "c": b'\x01\x05\x00\x0C\xFF\x00\x4C\x39',  # R13_1
        "d": b'\x01\x05\x00\x0D\xFF\x00\x1D\xF9',  # R14_1
        "e": b'\x01\x05\x00\x0E\xFF\x00\xED\xF9',  # R15_1
        "L": b'\x01\x05\x00\x0F\xFF\x00\xBC\x39',  # R16_1

        # 1-16 Röle OFF
        "i": b'\x01\x05\x00\x00\x00\x00\xCD\xCA',  # R1_0
        "g": b'\x01\x05\x00\x01\x00\x00\x9C\x0A',  # R2_0
        "h": b'\x01\x05\x00\x02\x00\x00\x6C\x0A',  # R3_0
        "j": b'\x01\x05\x00\x03\x00\x00\x3D\xCA',  # R4_0
        "k": b'\x01\x05\x00\x04\x00\x00\x8C\x0B',  # R5_0
        "l": b'\x01\x05\x00\x05\x00\x00\xDD\xCB',  # R6_0
        "m": b'\x01\x05\x00\x06\x00\x00\x2D\xCB',  # R7_0
        "n": b'\x01\x05\x00\x07\x00\x00\x7C\x0B',  # R8_0
        "o": b'\x01\x05\x00\x08\x00\x00\x4C\x08',  # R9_0
        "p": b'\x01\x05\x00\x09\x00\x00\x1D\xC8',  # R10_0
        "q": b'\x01\x05\x00\x0A\x00\x00\xED\xC8',  # R11_0
        "t": b'\x01\x05\x00\x0B\x00\x00\xBC\x08',  # R12_0
        "u": b'\x01\x05\x00\x0C\x00\x00\x0D\xC9',  # R13_0
        "v": b'\x01\x05\x00\x0D\x00\x00\x5C\x09',  # R14_0
        "w": b'\x01\x05\x00\x0E\x00\x00\xAC\x09',  # R15_0
        "M": b'\x01\x05\x00\x0F\x00\x00\xFD\xC9',  # R16_0

        # 1-16 Röle TOGGLE
        "y0": b'\x01\x05\x00\x00\x55\x00\xF2\x9A',  # R1_T
        "y1": b'\x01\x05\x00\x01\x55\x00\xA3\x5A',  # R2_T
        "y2": b'\x01\x05\x00\x02\x55\x00\x53\x5A',  # R3_T
        "y3": b'\x01\x05\x00\x03\x55\x00\x02\x9A',  # R4_T
        "y4": b'\x01\x05\x00\x04\x55\x00\xB3\x5B',  # R5_T
        "y5": b'\x01\x05\x00\x05\x55\x00\xE2\x9B',  # R6_T
        "y6": b'\x01\x05\x00\x06\x55\x00\x12\x9B',  # R7_T
        "y7": b'\x01\x05\x00\x07\x55\x00\x43\x5B',  # R8_T
        "z0": b'\x01\x05\x00\x08\x55\x00\x73\x58',  # R9_T
        "z1": b'\x01\x05\x00\x09\x55\x00\x22\x98',  # R10_T
        "z2": b'\x01\x05\x00\x0A\x55\x00\xD2\x98',  # R11_T
        "z3": b'\x01\x05\x00\x0B\x55\x00\x83\x58',  # R12_T
        "z4": b'\x01\x05\x00\x0C\x55\x00\x32\x99',  # R13_T
        "z5": b'\x01\x05\x00\x0D\x55\x00\x63\x59',  # R14_T
        "z6": b'\x01\x05\x00\x0E\x55\x00\x93\x59',  # R15_T
        "z7": b'\x01\x05\x00\x0F\x55\x00\xC2\x99',  # R16_T

        # Tümü ON / OFF
        "ALL": b'\x01\x05\x00\xFF\xFF\x00\xBC\x0A',
        "OFF": b'\x01\x05\x00\xFF\x00\x00\xFD\xFA',

        # Linkage / Normal mod
        "normal_1_8":   b'\x01\x10\x10\x00\x00\x08\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0B\x5C',
        "linkage_1_8":  b'\x01\x10\x10\x00\x00\x08\x10\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x7C\xB1',
        "normal_9_16":  b'\x01\x10\x10\x00\x00\x09\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x5A\xA0',
        "linkage_9_16": b'\x01\x10\x10\x00\x00\x09\x10\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x2D\x4D',

        # Linkage sorgu
        "la_no_1_8":  b'\x01\x03\x10\x00\x00\x08\x40\xCC',
        "la_no_9_16": b'\x01\x03\x10\x00\x00\x09\x81\x0C',

        # Röle durum sorgular
        "read_relay_status_8bit":  b'\x01\x01\x00\x00\x00\x08\x3D\xCC',
        "read_relay_status_9_16":  b'\x01\x01\x00\x00\x00\x09\xFC\x0C',
        "RS_18_8BIT":              b'\x01\x03\x10\x00\xFF\x08\x01\x3C',
        "RS_916_8BIT":             b'\x01\x03\x10\x00\xFF\x09\xC0\xFC',

        # Input durum sorgular
        "read_input_status": b'\x01\x02\x00\x00\x00\x08\x79\xCC',
        "read_input_binary": b'\x01\x03\x10\x00\x01\x08\x41\x5C',
    }

    # ----------------------------------------------------------
    #  Flash ON – 48 parametre (index 0-47)
    #  flash_on(0)  = No.0 relay1 800ms
    #  flash_on(1)  = No.0 relay1 1000ms
    #  flash_on(2)  = No.0 relay1 2000ms
    #  flash_on(3)  = No.0 relay1 3000ms
    #  flash_on(4)  = No.0 relay1 4000ms
    #  flash_on(5)  = No.0 relay1 5000ms
    #  flash_on(6)  = No.1 relay2 800ms
    #  ...
    #  flash_on(47) = No.7 relay8 5000ms
    # ----------------------------------------------------------
    _FLASH_MAP = {
        "FON_0":  b'\x01\x05\x02\x00\x00\x08\xCD\xB4',
        "FON_1":  b'\x01\x05\x02\x00\x00\x0A\x4C\x75',
        "FON_2":  b'\x01\x05\x02\x00\x00\x14\xCC\x7D',
        "FON_3":  b'\x01\x05\x02\x00\x00\x1E\x4C\x7A',
        "FON_4":  b'\x01\x05\x02\x00\x00\x28\xCC\x6C',
        "FON_5":  b'\x01\x05\x02\x00\x00\x32\x4D\xA7',
        "FON_6":  b'\x01\x05\x02\x01\x00\x08\x9C\x74',
        "FON_7":  b'\x01\x05\x02\x01\x00\x0A\x1D\xB5',
        "FON_8":  b'\x01\x05\x02\x01\x00\x14\x9D\xBD',
        "FON_9":  b'\x01\x05\x02\x01\x00\x1E\x1D\xBA',
        "FON_10": b'\x01\x05\x02\x01\x00\x28\x9D\xAC',
        "FON_11": b'\x01\x05\x02\x01\x00\x32\x1C\x67',
        "FON_12": b'\x01\x05\x02\x02\x00\x08\x6C\x74',
        "FON_13": b'\x01\x05\x02\x02\x00\x0A\xED\xB5',
        "FON_14": b'\x01\x05\x02\x02\x00\x14\x6D\xBD',
        "FON_15": b'\x01\x05\x02\x02\x00\x1E\xED\xBA',
        "FON_16": b'\x01\x05\x02\x02\x00\x28\x6D\xAC',
        "FON_17": b'\x01\x05\x02\x02\x00\x32\xEC\x67',
        "FON_18": b'\x01\x05\x02\x03\x00\x08\x3D\xB4',
        "FON_19": b'\x01\x05\x02\x03\x00\x0A\xBC\x75',
        "FON_20": b'\x01\x05\x02\x03\x00\x14\x3C\x7D',
        "FON_21": b'\x01\x05\x02\x03\x00\x1E\xBC\x7A',
        "FON_22": b'\x01\x05\x02\x03\x00\x28\x3C\x6C',
        "FON_23": b'\x01\x05\x02\x03\x00\x32\xBD\xA7',
        "FON_24": b'\x01\x05\x02\x04\x00\x08\x8C\x75',
        "FON_25": b'\x01\x05\x02\x04\x00\x0A\x0D\xB4',
        "FON_26": b'\x01\x05\x02\x04\x00\x14\x8D\xBC',
        "FON_27": b'\x01\x05\x02\x04\x00\x1E\x0D\xBB',
        "FON_28": b'\x01\x05\x02\x04\x00\x28\x8D\xAD',
        "FON_29": b'\x01\x05\x02\x04\x00\x32\x0C\x66',
        "FON_30": b'\x01\x05\x02\x05\x00\x08\xDD\xB5',
        "FON_31": b'\x01\x05\x02\x05\x00\x0A\x5C\x74',
        "FON_32": b'\x01\x05\x02\x05\x00\x14\xDC\x7C',
        "FON_33": b'\x01\x05\x02\x05\x00\x1E\x5C\x7B',
        "FON_34": b'\x01\x05\x02\x05\x00\x28\xDC\x6D',
        "FON_35": b'\x01\x05\x02\x05\x00\x32\x5D\xA6',
        "FON_36": b'\x01\x05\x02\x06\x00\x08\x2D\xB5',
        "FON_37": b'\x01\x05\x02\x06\x00\x0A\xAC\x74',
        "FON_38": b'\x01\x05\x02\x06\x00\x14\x2C\x7C',
        "FON_39": b'\x01\x05\x02\x06\x00\x1E\xAC\x7B',
        "FON_40": b'\x01\x05\x02\x06\x00\x28\x2C\x6D',
        "FON_41": b'\x01\x05\x02\x06\x00\x32\xAD\xA6',
        "FON_42": b'\x01\x05\x02\x07\x00\x08\x7C\x75',
        "FON_43": b'\x01\x05\x02\x07\x00\x0A\xFD\xB4',
        "FON_44": b'\x01\x05\x02\x07\x00\x14\x7D\xBC',
        "FON_45": b'\x01\x05\x02\x07\x00\x1E\xFD\xBB',
        "FON_46": b'\x01\x05\x02\x07\x00\x28\x7D\xAD',
        "FON_47": b'\x01\x05\x02\x07\x00\x32\xFC\x66',

        # Flash OFF – 48 parametre (index 0-47)
        # flash_off(0)  = No.0 relay1 800ms
        # flash_off(47) = No.7 relay8 5000ms
        "FOFF_0":  b'\x01\x05\x04\x00\x00\x08\xCD\x3C',
        "FOFF_1":  b'\x01\x05\x04\x00\x00\x0A\x4C\xFD',
        "FOFF_2":  b'\x01\x05\x04\x00\x00\x14\xCC\xF5',
        "FOFF_3":  b'\x01\x05\x04\x00\x00\x1E\x4C\xF2',
        "FOFF_4":  b'\x01\x05\x04\x00\x00\x28\xCC\xE4',
        "FOFF_5":  b'\x01\x05\x04\x00\x00\x32\x4D\x2F',
        "FOFF_6":  b'\x01\x05\x04\x01\x00\x08\x9C\xFC',
        "FOFF_7":  b'\x01\x05\x04\x01\x00\x0A\x1D\x3D',
        "FOFF_8":  b'\x01\x05\x04\x01\x00\x14\x9D\x35',
        "FOFF_9":  b'\x01\x05\x04\x01\x00\x1E\x1D\x32',
        "FOFF_10": b'\x01\x05\x04\x01\x00\x28\x9D\x24',
        "FOFF_11": b'\x01\x05\x04\x01\x00\x32\x1C\xEF',
        "FOFF_12": b'\x01\x05\x04\x02\x00\x08\x6C\xFC',
        "FOFF_13": b'\x01\x05\x04\x02\x00\x0A\xED\x3D',
        "FOFF_14": b'\x01\x05\x04\x02\x00\x14\x6D\x35',
        "FOFF_15": b'\x01\x05\x04\x02\x00\x1E\xED\x32',
        "FOFF_16": b'\x01\x05\x04\x02\x00\x28\x6D\x24',
        "FOFF_17": b'\x01\x05\x04\x02\x00\x32\xEC\xEF',
        "FOFF_18": b'\x01\x05\x04\x03\x00\x08\x3D\x3C',
        "FOFF_19": b'\x01\x05\x04\x03\x00\x0A\xBC\xFD',
        "FOFF_20": b'\x01\x05\x04\x03\x00\x14\x3C\xF5',
        "FOFF_21": b'\x01\x05\x04\x03\x00\x1E\xBC\xF2',
        "FOFF_22": b'\x01\x05\x04\x03\x00\x28\x3C\xE4',
        "FOFF_23": b'\x01\x05\x04\x03\x00\x32\xBD\x2F',
        "FOFF_24": b'\x01\x05\x04\x04\x00\x08\x8C\xFD',
        "FOFF_25": b'\x01\x05\x04\x04\x00\x0A\x0D\x3C',
        "FOFF_26": b'\x01\x05\x04\x04\x00\x14\x8D\x34',
        "FOFF_27": b'\x01\x05\x04\x04\x00\x1E\x0D\x33',
        "FOFF_28": b'\x01\x05\x04\x04\x00\x28\x8D\x25',
        "FOFF_29": b'\x01\x05\x04\x04\x00\x32\x0C\xEE',
        "FOFF_30": b'\x01\x05\x04\x05\x00\x08\xDD\x3D',
        "FOFF_31": b'\x01\x05\x04\x05\x00\x0A\x5C\xFC',
        "FOFF_32": b'\x01\x05\x04\x05\x00\x14\xDC\xF4',
        "FOFF_33": b'\x01\x05\x04\x05\x00\x1E\x5C\xF3',
        "FOFF_34": b'\x01\x05\x04\x05\x00\x28\xDC\xE5',
        "FOFF_35": b'\x01\x05\x04\x05\x00\x32\x5D\x2E',
        "FOFF_36": b'\x01\x05\x04\x06\x00\x08\x2D\x3D',
        "FOFF_37": b'\x01\x05\x04\x06\x00\x0A\xAC\xFC',
        "FOFF_38": b'\x01\x05\x04\x06\x00\x14\x2C\xF4',
        "FOFF_39": b'\x01\x05\x04\x06\x00\x1E\xAC\xF3',
        "FOFF_40": b'\x01\x05\x04\x06\x00\x28\x2C\xE5',
        "FOFF_41": b'\x01\x05\x04\x06\x00\x32\xAD\x2E',
        "FOFF_42": b'\x01\x05\x04\x07\x00\x08\x7C\xFD',
        "FOFF_43": b'\x01\x05\x04\x07\x00\x0A\xFD\x3C',
        "FOFF_44": b'\x01\x05\x04\x07\x00\x14\x7D\x34',
        "FOFF_45": b'\x01\x05\x04\x07\x00\x1E\xFD\x33',
        "FOFF_46": b'\x01\x05\x04\x07\x00\x28\x7D\x25',
        "FOFF_47": b'\x01\x05\x04\x07\x00\x32\xFC\xEE',
    }

    def __init__(self, ip: str, port: int, timeout: int = 5, reconnect_interval: float = 3.0):
        self.ip                 = ip
        self.port               = port
        self.timeout            = timeout
        self.reconnect_interval = reconnect_interval
        self._sock              = None
        self._lock              = threading.Lock()
        self._connected         = False
        self._reconnect_thread  = None
        self._stop_reconnect    = False
        self._connect()

    # --- Bağlantı yönetimi ---

    def _connect(self) -> bool:
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(self.timeout)
            s.connect((self.ip, self.port))
            with self._lock:
                self._sock      = s
                self._connected = True
            logger.info(f"TCP bağlandı: {self.ip}:{self.port}")
            return True
        except Exception as e:
            logger.error(f"TCP bağlantı hatası: {e}")
            self._connected = False
            return False

    def _start_reconnect(self):
        """Non-blocking arka plan yeniden bağlanma thread'i."""
        if self._reconnect_thread and self._reconnect_thread.is_alive():
            return
        self._stop_reconnect   = False
        self._reconnect_thread = threading.Thread(target=self._reconnect_loop, daemon=True)
        self._reconnect_thread.start()

    def _reconnect_loop(self):
        while not self._stop_reconnect and not self._connected:
            logger.warning(f"Yeniden bağlanılıyor... ({self.reconnect_interval}s)")
            time.sleep(self.reconnect_interval)
            if self._connect():
                break

    def disconnect(self):
        """Bağlantıyı kapatır."""
        self._stop_reconnect = True
        with self._lock:
            if self._sock:
                try:
                    self._sock.close()
                except Exception:
                    pass
                self._sock      = None
                self._connected = False

    # --- Ham gönderim ---

    def _send(self, data: bytes) -> bytes:
        """Veri gönderir, cevabı alır. Hata durumunda reconnect başlatır."""
        with self._lock:
            if not self._connected or self._sock is None:
                logger.warning("Bağlantı yok, gönderim yapılamadı.")
                self._start_reconnect()
                return b''
            try:
                self._sock.sendall(data)
                logger.debug(f"TX: {binascii.hexlify(data, b' ').decode().upper()}")
                rx = self._sock.recv(1024)
                if rx:
                    logger.debug(f"RX: {binascii.hexlify(rx, b' ').decode().upper()}")
                return rx
            except Exception as e:
                logger.error(f"Gönderim hatası: {e}")
                self._connected = False
                self._sock      = None
        self._start_reconnect()
        return b''

    def _send_key(self, key: str) -> bytes:
        """_RELAY_MAP'ten key ile hex gönderir."""
        try:
            cmd = self._RELAY_MAP[key]
            return self._send(cmd)
        except KeyError:
            logger.error(f"Geçersiz Parametre: '{key}' _RELAY_MAP içinde bulunamadı.")
            return b''

    # --- Ortak metotlar ---

    def relay_on(self, param: str) -> bytes:
        """Röle açar. Parametre: R1_1 ... R16_1 veya ALL"""
        return self._send_key(param)

    def relay_off(self, param: str) -> bytes:
        """Röle kapatır. Parametre: R1_0 ... R16_0 veya OFF"""
        return self._send_key(param)

    def relay_toggle(self, param: str) -> bytes:
        """Röle toggle yapar. Parametre: R1_T ... R16_T"""
        return self._send_key(param)

    def relay_la(self, param: str) -> bytes:
        """
        Linkage / Normal mod ayarlar.
        Parametre: linkage_1_8 | normal_1_8 | linkage_9_16 | normal_9_16
        """
        return self._send_key(param)

    def relay_linkage_or_normal(self, param: str) -> bytes:
        """
        Röle modunu sorgular (Linkage mı Normal mı?).
        Parametre: la_no_1_8 | la_no_9_16
        """
        return self._send_key(param)

    def flash_on(self, index: int) -> bytes:
        """
        Flash ON komutu gönderir. index: 0-47
        flash_on(0)  = No.0 relay1 800ms
        flash_on(1)  = No.0 relay1 1000ms
        flash_on(2)  = No.0 relay1 2000ms
        flash_on(3)  = No.0 relay1 3000ms
        flash_on(4)  = No.0 relay1 4000ms
        flash_on(5)  = No.0 relay1 5000ms
        flash_on(6)  = No.1 relay2 800ms  ...  flash_on(47) = No.7 relay8 5000ms
        """
        try:
            key = f"FON_{index}"
            cmd = self._FLASH_MAP[key]
            return self._send(cmd)
        except KeyError:
            logger.error(f"Geçersiz flash_on index: {index}. Geçerli aralık: 0-47")
            return b''

    def flash_off(self, index: int) -> bytes:
        """
        Flash OFF komutu gönderir. index: 0-47
        flash_off(0)  = No.0 relay1 800ms
        flash_off(47) = No.7 relay8 5000ms
        """
        try:
            key = f"FOFF_{index}"
            cmd = self._FLASH_MAP[key]
            return self._send(cmd)
        except KeyError:
            logger.error(f"Geçersiz flash_off index: {index}. Geçerli aralık: 0-47")
            return b''

    def read_relay_status_8bit(self) -> bytes:
        """1-8 Röle durum hex sorgular."""
        return self._send_key("read_relay_status_8bit")

    def read_relay_status_9_16(self) -> bytes:
        """9-16 Röle durum hex sorgular."""
        return self._send_key("read_relay_status_9_16")

    def RS_18_8BIT(self) -> bytes:
        """1-8 Röle durumunu 1/0 olarak sorgular."""
        return self._send_key("RS_18_8BIT")

    def RS_916_8BIT(self) -> bytes:
        """9-16 Röle durumunu 1/0 olarak sorgular."""
        return self._send_key("RS_916_8BIT")

    def read_input_status(self) -> bytes:
        """8 input durumunu hex olarak sorgular."""
        return self._send_key("read_input_status")

    def read_input_binary(self) -> bytes:
        """8 input durumunu 1/0 olarak sorgular."""
        return self._send_key("read_input_binary")


    


# ============================================================
#  3) UdpRelay  –  UDP GET Protokolü
# ============================================================

class UdpRelay:
    """
    Seda Elektronik UDP GET Röle Kartı API sınıfı.
    Röle kontrolü UDP üzerinden ASCII parametre göndererek yapılır.
    Status okuma ve config HTTP GET üzerinden yapılır.

    Kullanım:
        udp = UdpRelay("169.254.1.2", 3000)
        udp.relay_on(R1_1)
        udp.relay_off(R1_0)
        udp.relay_toggle(R1_T)
        udp.relay_on(ALL)
        udp.relay_off(OFF)
        status = udp.read_status()
        udp.read_status_loop()
        udp.config()
    """

    # UDP üzerinden gönderilecek parametre → bytes eşleşmesi
    _UDP_MAP = {
        # Röle AÇMA
        "1": b"1", "2": b"2", "3": b"3", "4": b"4",
        "5": b"5", "6": b"6", "7": b"7", "8": b"8",
        "9": b"9", "0": b"0", "a": b"a", "b": b"b",
        "c": b"c", "d": b"d", "e": b"e", "L": b"L",
        # Röle KAPATMA
        "i": b"i", "g": b"g", "h": b"h", "j": b"j",
        "k": b"k", "l": b"l", "m": b"m", "n": b"n",
        "o": b"o", "p": b"p", "q": b"q", "t": b"t",
        "u": b"u", "v": b"v", "w": b"w", "M": b"M",
        # Toggle
        "y0": b"y0", "y1": b"y1", "y2": b"y2", "y3": b"y3",
        "y4": b"y4", "y5": b"y5", "y6": b"y6", "y7": b"y7",
        "z0": b"z0", "z1": b"z1", "z2": b"z2", "z3": b"z3",
        "z4": b"z4", "z5": b"z5", "z6": b"z6", "z7": b"z7",
        # Tümü
        "ALL": b"ALL", "OFF": b"OFF",
    }

    def __init__(self, ip: str, port: int, timeout: int = 3, reconnect_interval: float = 3.0):
        if requests is None:
            raise ImportError("UdpRelay.read_status için 'requests' kütüphanesi gereklidir: pip install requests")
        self.ip                 = ip
        self.port               = port
        self.timeout            = timeout
        self.reconnect_interval = reconnect_interval
        self._sock              = None
        self._connected         = False
        self._lock              = threading.Lock()
        self._reconnect_thread  = None
        self._stop_reconnect    = False
        self._loop_running      = False
        self._base_http         = f"http://{ip}:{port}"
        self._connect()

    # --- Bağlantı yönetimi ---

    def _connect(self) -> bool:
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.settimeout(self.timeout)
            with self._lock:
                self._sock      = s
                self._connected = True
            logger.info(f"UDP soketi hazır: {self.ip}:{self.port}")
            return True
        except Exception as e:
            logger.error(f"UDP soket hatası: {e}")
            self._connected = False
            return False

    def _start_reconnect(self):
        if self._reconnect_thread and self._reconnect_thread.is_alive():
            return
        self._stop_reconnect   = False
        self._reconnect_thread = threading.Thread(target=self._reconnect_loop, daemon=True)
        self._reconnect_thread.start()

    def _reconnect_loop(self):
        while not self._stop_reconnect and not self._connected:
            logger.warning(f"UDP yeniden bağlanılıyor... ({self.reconnect_interval}s)")
            time.sleep(self.reconnect_interval)
            if self._connect():
                break

    def disconnect(self):
        self._stop_reconnect = True
        with self._lock:
            if self._sock:
                try:
                    self._sock.close()
                except Exception:
                    pass
                self._sock      = None
                self._connected = False

    # --- Ham gönderim ---

    def _send(self, data: bytes) -> bool:
        with self._lock:
            if not self._connected or self._sock is None:
                logger.warning("UDP bağlantı yok, gönderim yapılamadı.")
                self._start_reconnect()
                return False
            try:
                self._sock.sendto(data, (self.ip, self.port))
                logger.info(f"UDP TX: {data.decode(errors='replace')} -> {self.ip}:{self.port}")
                return True
            except Exception as e:
                logger.error(f"UDP gönderim hatası: {e}")
                self._connected = False
                self._sock      = None
        self._start_reconnect()
        return False

    def _send_param(self, param: str) -> bool:
        try:
            data = self._UDP_MAP[param]
            return self._send(data)
        except KeyError:
            logger.error(f"Geçersiz Parametre: '{param}' _UDP_MAP içinde bulunamadı.")
            return False

    # --- Ortak metotlar ---

    def relay_on(self, param: str) -> bool:
        """Röle açar. Parametre: R1_1 ... R16_1 veya ALL"""
        return self._send_param(param)

    def relay_off(self, param: str) -> bool:
        """Röle kapatır. Parametre: R1_0 ... R16_0 veya OFF"""
        return self._send_param(param)

    def relay_toggle(self, param: str) -> bool:
        """Röle toggle yapar. Parametre: R1_T ... R16_T"""
        return self._send_param(param)

    def read_status(self) -> dict:
        """
        HTTP GET /s endpoint'inden tek seferlik okuma yapar.
        Döndürür: {"PORTB": str, "PORTD": str, "PORTA": str, "PORTE": str,
                   "TEMP1": float, "TEMP2": float}
        PORT değerleri 8 haneli binary string (örn: "00000101")
        """
        url = f"{self._base_http}/s"
        try:
            r = requests.get(url, timeout=self.timeout)
            r.raise_for_status()
            return _parse_status(r.text)
        except Exception as e:
            logger.error(f"read_status hatası: {e}")
            return False

    def read_status_loop(self, interval: float = 0.4):
        """
        HTTP GET /s endpoint'inden her 400ms'de bir okuma yapar.
        Çıkmak için Ctrl+C kullanın.
        """
        self._loop_running = True
        logger.info("read_status_loop başladı. Durdurmak için Ctrl+C.")
        try:
            while self._loop_running:
                data = self.read_status()
                if data:
                    print(data)
                time.sleep(interval)
        except KeyboardInterrupt:
            self._loop_running = False
            logger.info("read_status_loop durduruldu.")

    def config(self) -> str:
        """
        HTTP GET /IP? endpoint'inden ağ konfigürasyonunu okur.
        Döndürür: IP, PORTNO, GATEWAY, SUBNET MASK bilgileri (ham metin)
        """
        url = f"{self._base_http}/{NetCon}"
        try:
            r = requests.get(url, timeout=self.timeout)
            r.raise_for_status()
            logger.info(f"config -> {r.text.strip()}")
            return r.text.strip()
        except Exception as e:
            logger.error(f"config hatası: {e}")
            return False

2- PYTHON GET WRITE-READ PORTS and READ SENSOR DS18B20


#Seda Elektronik Ethernet Röle Kartı – Python API Wrapper
#Bu modül Seda Elektronik Get Ethernet röle kartlarından port durumlarını
#okumak için kullanılır. HTTP üzerinden karttan veri çekilir ve port
#değerleri parse edilerek JSON formatında döndürülür.
#────────────────────────────────────────
#CİHAZ BAĞLANTI BİLGİLERİ
#────────────────────────────────────────
#Protokol  : HTTP GET
#Port      : 3000
#URL (write)       : http://IP_ADRESI:3000/"parametre"
#URL (read)       : http://IP_ADRESI:3000/s
#Örnek:
#http://169.254.1.2:3000/s
#Cihazın döndürdüğü veri formatı:
#    var PORTB=     0;
#    var PORTD=     0;
#    var PORTA=     0;
#    var PORTE=     0;
#    var TEMP1=  22.3;
#    var TEMP2=  22.2;

#────────────────────────────────────────
#RÖLE AÇMA GET REQUEST KOMUTLARI (ETHERNET 2 RÖLE İÇİN AŞAĞIDAKİ BİLGİLERİ İNCELEYİNİZ)
#(web browserdan butonlardan doğrudan kontrol veya kod bloğundan request'le)
#Daha fazla bilgi için pdf kılavuzumuzu inceleyiniz:
#https://sedaelektronik.com.tr/KULLANIM-KILAVUZLARI/HIZLI-KURULUM-KILAVUZU.pdf 
#────────────────────────────────────────

#|  Röle   | Parametre |          Örnek            |
#|------   |-----------|---------------------------|
#| RÖLE 1  | `/1`      | http://169.254.1.2:3000/1 |
#| RÖLE 2  | `/2`      | http://169.254.1.2:3000/2 |
#| RÖLE 3  | `/3`      | http://169.254.1.2:3000/3 |
#| RÖLE 4  | `/4`      | http://169.254.1.2:3000/4 |
#| RÖLE 5  | `/5`      | http://169.254.1.2:3000/5 |
#| RÖLE 6  | `/6`      | http://169.254.1.2:3000/6 |
#| RÖLE 7  | `/7`      | http://169.254.1.2:3000/7 |
#| RÖLE 8  | `/8`      | http://169.254.1.2:3000/8 |
#| RÖLE 9  | `/9`      | http://169.254.1.2:3000/9 |
#| RÖLE 10 | `/0`      | http://169.254.1.2:3000/0 |
#| RÖLE 11 | `/a`      | http://169.254.1.2:3000/a |
#| RÖLE 12 | `/b`      | http://169.254.1.2:3000/b |
#| RÖLE 13 | `/c`      | http://169.254.1.2:3000/c |
#| RÖLE 14 | `/d`      | http://169.254.1.2:3000/d |
#| RÖLE 15 | `/e`      | http://169.254.1.2:3000/e |
#| RÖLE 16 | `/L`      | http://169.254.1.2:3000/L |

#────────────────────────────────────────
#RÖLE KAPATMA GET REQUEST KOMUTLARI
#(web browserdan butonlardan doğrudan kontrol veya kod bloğundan request'le) 
#────────────────────────────────────────

#|  Röle   | Parametre |          Örnek            |
#|------   |-----------|---------------------------|
#| RÖLE 1  | `/i`      | http://169.254.1.2:3000/i |
#| RÖLE 2  | `/g`      | http://169.254.1.2:3000/g |
#| RÖLE 3  | `/h`      | http://169.254.1.2:3000/h |
#| RÖLE 4  | `/j`      | http://169.254.1.2:3000/j |
#| RÖLE 5  | `/k`      | http://169.254.1.2:3000/k |
#| RÖLE 6  | `/l`      | http://169.254.1.2:3000/l |
#| RÖLE 7  | `/m`      | http://169.254.1.2:3000/m |
#| RÖLE 8  | `/n`      | http://169.254.1.2:3000/n |
#| RÖLE 9  | `/o`      | http://169.254.1.2:3000/o |
#| RÖLE 10 | `/p`      | http://169.254.1.2:3000/p |
#| RÖLE 11 | `/q`      | http://169.254.1.2:3000/q |
#| RÖLE 12 | `/t`      | http://169.254.1.2:3000/t |
#| RÖLE 13 | `/u`      | http://169.254.1.2:3000/u |
#| RÖLE 14 | `/v`      | http://169.254.1.2:3000/v |
#| RÖLE 15 | `/w`      | http://169.254.1.2:3000/w |
#| RÖLE 16 | `/M`      | http://169.254.1.2:3000/M |

#────────────────────────────────────────
### ÖZEL KOMUTLAR
#(web browserdan butonlardan doğrudan kontrol veya kod bloğundan request'le) 
#────────────────────────────────────────

#IPNO:PORTNO/s - Röle TEMP durumları görülür
#IPNO:PORTNO/I veya IPNO:PORTNO/IP? - Cihazın ağ konfigürasyon bilgileri

#────────────────────────────────────────
#ETHERNET 2 RÖLE KAPATMA VE AÇMA GET REQUEST KOMUTLARI
#(web browserdan butonlardan doğrudan kontrol veya kod bloğundan request'le) 
#────────────────────────────────────────
#RÖLE AÇMA:
#|  Röle   | Parametre |          Örnek            |
#|------   |-----------|---------------------------|
#| RÖLE 1  | `/w`      | http://169.254.1.2:3000/w |
#| RÖLE 2  | `/m`      | http://169.254.1.2:3000/m |

#RÖLE KAPATMA:
#|  Röle   | Parametre |          Örnek            |
#|------   |-----------|---------------------------|
#| RÖLE 1  | `/n`      | http://169.254.1.2:3000/n |
#| RÖLE 2  | `/t`      | http://169.254.1.2:3000/t |


#────────────────────────────────────────
#PORT DEĞERLERİ
#────────────────────────────────────────
#Kaynak sayfa http://169.254.1.2:3000/s (veya sizin belirlediğin ip:portno/s) Her port 
#için 8 bitlik değerler ve 2 adet ısı durumu için küsüratlı ısı değerleri sunar.
#Örnek:
#PORTB = 42
#Binary karşılığı:
#00101010

#bit0 → Röle 1
#bit1 → Röle 2
#bit2 → Röle 3
#bit3 → Röle 4
#bit4 → Röle 5
#bit5 → Röle 6
#bit6 → Röle 7
#bit7 → Röle 8

#────────────────────────────────────────
#TEMP1 TEMP2 DESİMAL ISI DEĞERLERİ
#────────────────────────────────────────

#TEMP1 = 22.3
#TEMP2 = 22.2
#────────────────────────────────────────

#────────────────────────────────────────
#GEREKSİNİMLER
#────────────────────────────────────────
#import requests
#import re
#import time
#────────────────────────────────────────

#CODE:

import requests
import re
import time

# Tetikleme URL'leri röleler on off yapılıyor
PRE_URLS = [
    "http://95.70.192.96:249/1",
    "http://95.70.192.96:249/i",
    "http://95.70.192.96:249/2",
    "http://95.70.192.96:249/g",
    "http://95.70.192.96:249/3",
    "http://95.70.192.96:249/h",
    "http://95.70.192.96:249/4",
    "http://95.70.192.96:249/j",
]

# Okuma URL'i
URL = "http://95.70.192.96:249/s" # bu sayfadan değerleri alıyoruz

def to_bin8(val):
    return format(val, '08b')

try:
    # === 1) Ön tetikleme ===
    for u in PRE_URLS:
        try:
            r = requests.get(u, timeout=2)
            r.raise_for_status()
            print(f"Tetik gönderildi -> {u}")
        except Exception as e:
            print(f"Tetik HATA ({u}):", e)

        time.sleep(1)

    # === 2) Okuma ===
    r = requests.get(URL, timeout=3)
    r.raise_for_status()
    data = r.text

    # === 3) TEMP okuma ===
    temps = {}
    for t in ["TEMP1", "TEMP2"]:
        m = re.search(
            rf"{t}\s*=\s*([\d]+)\.\s*([\d]+)\s*C",
            data
        )
        if not m:
            raise ValueError(f"{t} bulunamadı")

        temp_val = float(f"{m.group(1)}.{m.group(2)}")
        temps[t] = temp_val

    # === 4) PORT okuma ===
    ports = {}
    for p in ["PORTB", "PORTD", "PORTA", "PORTE"]:
        m = re.search(rf"{p}\s*=\s*(\d+)", data)
        if not m:
            raise ValueError(f"{p} bulunamadı")

        value = int(m.group(1))
        if value > 255:
            raise ValueError(f"{p} 255'i geçti")

        ports[p] = value

    # === 5) Sonuçlar ===
    print("\n--- SICAKLIKLAR ---")
    for t, v in temps.items():
        print(f"{t}: {v:.2f} °C")

    print("\n--- PORT DURUMLARI ---")
    for p, v in ports.items():
        print(f"{p}: {v:3d}  ->  {to_bin8(v)}")

except Exception as e:
    print("Genel Hata:", e)

3- PYTHON GET READ PORTS SAMPLE CODE


#Seda Elektronik Ethernet Röle Kartı – Python API Wrapper
#Bu modül Seda Elektronik Get Ethernet röle kartlarından port durumlarını
#okumak için kullanılır. HTTP üzerinden karttan veri çekilir ve port
#değerleri parse edilerek JSON formatında döndürülür.
#────────────────────────────────────────
#CİHAZ BAĞLANTI BİLGİLERİ
#────────────────────────────────────────
#Protokol  : HTTP GET
#Port      : 3000
#URL (read)       : http://IP_ADRESI:3000/s
#URL (write)       : http://IP_ADRESI:3000/"parametre"
#Örnek:
#http://169.254.1.2:3000/s
#Cihazın döndürdüğü veri formatı:
#    var PORTB=     0;
#    var PORTD=     0;
#    var PORTA=     0;
#    var PORTE=     0;
#────────────────────────────────────────
#PORT DEĞERLERİ
#────────────────────────────────────────
#Her port 8 bitlik bir değerdir.
#Örnek:
#PORTB = 42
#Binary karşılığı:
#00101010

#bit0 → Röle 1
#bit1 → Röle 2
#bit2 → Röle 3
#bit3 → Röle 4
#bit4 → Röle 5
#bit5 → Röle 6
#bit6 → Röle 7
#bit7 → Röle 8

#3 kullanım şekli var:
#1) Flask REST API olarak çalıştır (müşteri HTTP ile bağlanır):
#bashpython relay_card_api.py
# → http://localhost:5000/api/ports
# → http://localhost:5000/api/ports/PORTB
#2) Kütüphane olarak import et (kendi koduna göm):
#pythonfrom relay_card_api import fetch_ports, get_port
#ports = fetch_ports()       # {'PORTB': 42, 'PORTD': 0, ...}
#portb = get_port("PORTB")  # + binary, hex, bit bazında breakdown
#3) Terminal testi:
#bashpython relay_card_api.py test

#────────────────────────────────────────
#KULLANIM
#────────────────────────────────────────
#1) Flask REST API olarak çalıştır:
#    python relay_card_api.py
#Sonra:
#    http://localhost:5000/api/ports
#    http://localhost:5000/api/ports/PORTB
#2) Python kütüphanesi olarak kullan:
#    from relay_card_api import fetch_ports, get_port
#    ports = fetch_ports()
#    portb = get_port("PORTB")
#3) Terminal test modu:
#    python relay_card_api.py test

#────────────────────────────────────────
### ÖZEL KOMUTLAR
#(web browserdan butonlardan doğrudan kontrol veya kod bloğundan request'le)
#Daha fazla bilgi için pdf kılavuzumuzu inceleyiniz:
#https://sedaelektronik.com.tr/KULLANIM-KILAVUZLARI/HIZLI-KURULUM-KILAVUZU.pdf  
#────────────────────────────────────────

#IPNO:PORTNO/s - Röle TEMP durumları görülür
#IPNO:PORTNO/I veya IPNO:PORTNO/IP? - Cihazın ağ konfigürasyon bilgileri

#────────────────────────────────────────
#GEREKSİNİMLER
#────────────────────────────────────────

#pip install -r requirements.txt
#requests
#flask
#flask-cors

#────────────────────────────────────────
#CODE:

import re
import requests
from flask import Flask, jsonify
from flask_cors import CORS

# ──────────────────────────────────────────────
# CORE: Cihazdan veri çek ve parse et
# ──────────────────────────────────────────────

DEVICE_URL = "http://169.254.1.2:3000/s"
#veya ethernet röle kartına verdiğiniz herhangi bir IP no: 
#DEVICE_URL = "http://192.168.1.200:3000/s"

def fetch_ports(url: str = DEVICE_URL, timeout: int = 3) -> dict:
    """
    Ethernet kartına HTTP GET atar, JS değişkenlerini parse eder.
    
    Kart şu formatta yanıt döner:
        var PORTB=     0;var PORTD=     0;PORTA=     0;PORTE=     0;
    
    Returns:
        {
            "PORTA": 0,
            "PORTB": 0,
            "PORTD": 0,
            "PORTE": 0,
            "raw": "...",
            "status": "ok"
        }
    """
    try:
        response = requests.get(url, timeout=timeout)
        response.raise_for_status()
        raw_text = response.text.strip()

        # Hem "var PORTB= 0;" hem "PORTA= 0;" formatını yakala
        pattern = r'(?:var\s+)?(PORT[A-Z])\s*=\s*(\d+)\s*;'
        matches = re.findall(pattern, raw_text)

        if not matches:
            return {"status": "error", "message": "Port verisi bulunamadı", "raw": raw_text}

        ports = {name: int(value) for name, value in matches}
        ports["raw"] = raw_text
        ports["status"] = "ok"
        return ports

    except requests.ConnectionError:
        return {"status": "error", "message": "Cihaza bağlanılamadı. IP/Port kontrol edin."}
    except requests.Timeout:
        return {"status": "error", "message": f"Bağlantı zaman aşımına uğradı ({timeout}s)"}
    except requests.HTTPError as e:
        return {"status": "error", "message": f"HTTP hatası: {e}"}


def get_port(port_name: str, url: str = DEVICE_URL) -> dict:
    """
    Tek bir portu döner. Örnek: get_port("PORTB")
    
    Returns:
        {"port": "PORTB", "value": 42, "binary": "00101010", "status": "ok"}
    """
    port_name = port_name.upper()
    data = fetch_ports(url)

    if data["status"] != "ok":
        return data

    if port_name not in data:
        available = [k for k in data if k.startswith("PORT")]
        return {
            "status": "error",
            "message": f"'{port_name}' bulunamadı. Mevcut portlar: {available}"
        }

    value = data[port_name]
    return {
        "status": "ok",
        "port": port_name,
        "value": value,
        "binary": format(value, "08b"),   # 8-bit binary string
        "hex": hex(value),
        "bits": {f"bit{i}": (value >> i) & 1 for i in range(8)}
    }


# ──────────────────────────────────────────────
# FLASK REST API
# ──────────────────────────────────────────────

app = Flask(__name__)
CORS(app)  # Tarayıcıdan erişim için

@app.route("/api/ports", methods=["GET"])
def all_ports():
    """Tüm portları döner."""
    data = fetch_ports()
    data.pop("raw", None)
    return jsonify(data)

@app.route("/api/ports/", methods=["GET"])
def single_port(port_name):
    """Tek port döner. Örn: /api/ports/PORTB"""
    return jsonify(get_port(port_name))

@app.route("/api/health", methods=["GET"])
def health():
    """API sağlık kontrolü."""
    return jsonify({"status": "ok", "device": DEVICE_URL})

@app.route("/", methods=["GET"])
def index():
    return jsonify({
        "api": "Röle Kartı API",
        "endpoints": {
            "GET /api/ports":            "Tüm portlar",
            "GET /api/ports/PORTA":      "Tek port (PORTA/PORTB/PORTD/PORTE)",
            "GET /api/health":           "Cihaz bağlantı durumu"
        }
    })


# ──────────────────────────────────────────────
# DOĞRUDAN KULLANIM (kütüphane olarak import)
# ──────────────────────────────────────────────

if __name__ == "__main__":
    import sys

    # Argümansız çalıştırılırsa Flask sunucusu başlat
    if len(sys.argv) == 1:
        print("=" * 45)
        print("  Röle Kartı REST API Sunucusu")
        print(f"  Cihaz  : {DEVICE_URL}")
        print("  API    : http://localhost:5000")
        print("=" * 45)
        app.run(host="0.0.0.0", port=5000, debug=True)

    # "test" argümanıyla doğrudan port oku
    elif sys.argv[1] == "test":
        print("Tüm portlar okunuyor...\n")
        result = fetch_ports()
        for key, val in result.items():
            if key not in ("raw", "status"):
                binary = format(val, "08b") if isinstance(val, int) else val
                print(f"  {key:6s} = {val:3d}  (0b{binary})")
        print(f"\n  Ham yanıt: {result.get('raw', 'N/A')}") 

4-1 PYTHON MQTT TCP READ-WRITE CODE


#Seda Elektronik TCP Ethernet Röle Kartı – Python API Wrapper
#Bu modül Seda Elektronik TCP MODBUS RTU Ethernet röle kartlarından port durumlarını
#yazmak ve okumak için kullanılır. TCP üzerinden karta hex veri gönderilir ve kartın CRC 
#yüklü cevabı alınır.
#Bağlantı için kendi programınız veya hercules vb. tcp programlarını kullanılabilirsiniz. 
#CİHAZ BAĞLANTI BİLGİLERİ
#────────────────────────────────────────
#Protokol  : TCP MODBUS RTU (CRC var)
#IP = "95.70.192.96"
#PORT = 3000

#────────────────────────────────────────
#HEX DEĞERLER ile KONTROL ve KULLANIM
#────────────────────────────────────────
#Örneğin kodda 1 nolu röle on değeri olan:
#HEX_COMMAND = "010500015500A35A" gönderilmiş ve sonra kart crc cevabı alınmıştır.
 
#Daha fazla kontrol hex değeri için linkteki pdf dosyamızı inceleyiniz  sayfa 7-11 
#Ve basit parametreler sayfa 1-6:
#https://sedaelektronik.com.tr/KULLANIM-KILAVUZLARI/TELNET-KURULUM-KILAVUZU.pdf

#Sisteminize özel parametreler üretmek için github sayfamızdaki crc jeneratörünü
#Pdf kılavuzdaki röle zamanlı çalışma değerleri harici özel zaman değerleri ihtiyacı
#vb. için kullanabilirsiniz.
#CRC üreteci HTML yapıdadır kurulum gerektirmez bütün web browserlarda çalışır.
#https://github.com/sedaelektronik/modbus-crc16-parameter-generator

#────────────────────────────────────────
#CODE:
import socket
import paho.mqtt.client as mqtt
import time

# --- YAPILANDIRMA ---
DEVICE_IP = "95.70.192.96"
DEVICE_PORT = 3000
HEX_COMMAND = "010500015500A35A" 

MQTT_BROKER = "broker.emqx.io" 
MQTT_TOPIC = "sedaelektronik/cihaz1/yanit"

def send_tcp_and_publish_mqtt():
    # 2 kez tekrar etmesi için döngü kuruyoruz
    for i in range(1, 3):
        try:
            print(f"\n--- {i}. Deneme Başlatıldı ---")
            
            # 1. TCP Bağlantısı Kur ve Veri Gönder
            message = bytes.fromhex(HEX_COMMAND)
            
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(5)
            sock.connect((DEVICE_IP, DEVICE_PORT))
            
            print(f"Cihaza bağlandı. Komut gönderiliyor...")
            sock.sendall(message)
            
            # Cihazdan cevap bekle
            response = sock.recv(1024)
            response_hex = response.hex().upper()
            print(f"Cihaz Cevabı: {response_hex}")
            sock.close()

            # 2. MQTT ile Yayınla
            client = mqtt.Client()
            client.connect(MQTT_BROKER, 1883, 60)
            client.publish(MQTT_TOPIC, response_hex)
            print(f"Veri MQTT'ye iletildi: {MQTT_TOPIC}")
            client.disconnect()

        except Exception as e:
            print(f"Hata oluştu: {e}")

        # Eğer ilk deneme bittiyse, ikinci deneme öncesi 1 saniye bekle
        if i < 2:
            print("1 saniye bekleniyor...")
            time.sleep(1)

    print("\nİşlem tamamlandı, program durduruldu.")

if __name__ == "__main__":
    send_tcp_and_publish_mqtt()

4-2 PYTHON TCP READ-WRITE CODE

	  
#Seda Elektronik TCP Ethernet Röle Kartı – Python API Wrapper
#Bu modül Seda Elektronik TCP MODBUS RTU Ethernet röle kartlarından port durumlarını
#yazmak ve okumak için kullanılır. TCP üzerinden karta hex veri gönderilir ve kartın CRC 
#yüklü cevabı alınır.
#Bağlantı için kendi programınız veya hercules vb. tcp programlarını kullanılabilirsiniz. 
#CİHAZ BAĞLANTI BİLGİLERİ
#────────────────────────────────────────
#Protokol  : TCP MODBUS RTU (CRC var)
#IP = "95.70.192.96"
#PORT = 3000

#────────────────────────────────────────
#HEX DEĞERLER ile KONTROL ve KULLANIM
#────────────────────────────────────────
#Örneğin kodda 1 nolu röle on değeri olan:
#HEX_COMMAND = "010500015500A35A" gönderilmiş ve sonra kart crc cevabı alınmıştır.
 
#Daha fazla kontrol hex değeri için linkteki pdf dosyamızı inceleyiniz sayfa 7-11 
#Ve basit parametreler sayfa 1-6:
#https://sedaelektronik.com.tr/KULLANIM-KILAVUZLARI/TELNET-KURULUM-KILAVUZU.pdf

#Sisteminize özel parametreler üretmek için github sayfamızdaki crc jeneratörünü
#Pdf kılavuzdaki röle zamanlı çalışma değerleri harici özel zaman değerleri ihtiyacı
#vb. için kullanabilirsiniz.
#CRC üreteci HTML yapıdadır kurulum gerektirmez bütün web browserlarda çalışır.
#https://github.com/sedaelektronik/modbus-crc16-parameter-generator

#────────────────────────────────────────
#CODE:
	  
import socket
import binascii

IP = "95.70.192.96"
PORT = 3000

# Gönderilecek HEX veri
hex_data = "01 05 00 01 55 00 A3 5A"
tx_data = bytes.fromhex(hex_data)

try:
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.settimeout(5)  # 5 saniye timeout
        s.connect((IP, PORT))
        print(f"Bağlandı: {IP}:{PORT}")

        # Veri gönder
        s.sendall(tx_data)
        print("Gönderilen:", binascii.hexlify(tx_data, b' ').decode().upper())

        # Cevap al
        rx_data = s.recv(1024)

        if rx_data:
            print("Gelen cevap:", binascii.hexlify(rx_data, b' ').decode().upper())
        else:
            print("Cihazdan cevap gelmedi")

except socket.timeout:
    print("Bağlantı zaman aşımına uğradı")

except Exception as e:
    print("Hata:", e)

5- PYTHON UDP WRITE, GET READ CODE:


#Seda Elektronik UDP GET Ethernet Röle Kartı – Python API Wrapper
#Bu modül Seda Elektronik UDP GET Ethernet röle kartlarından port durumlarını
#yazmak ve okumak için kullanılır. TCP üzerinden karta hex veri gönderilir ve kartın CRC 
#yüklü cevabı alınır.
#Bağlantı için kendi programınız veya hercules vb. tcp programlarını kullanılabilirsiniz. 
#CİHAZ BAĞLANTI BİLGİLERİ
#────────────────────────────────────────
#Protokol  : UDP GET
#IP = "95.70.192.96"
#PORT = 3000

#────────────────────────────────────────
#RÖLE KONTROL DEĞERLERİ
#────────────────────────────────────────

#RÖLE AÇMA UDP GET DEĞERLERİ
#(web browserdan butonlardan doğrudan kontrol veya kod bloğundan request'le)
#Daha fazla bilgi için pdf kılavuzumuzu inceleyiniz:
#https://sedaelektronik.com.tr/KULLANIM-KILAVUZLARI/HIZLI-KURULUM-KILAVUZU.pdf
#https://sedaelektronik.com.tr/KULLANIM-KILAVUZLARI/TELNET-KURULUM-KILAVUZU.pdf 
#────────────────────────────────────────

#|  Röle   | Parametre |
#|------   |-----------|
#| RÖLE 1  | `/1`      |
#| RÖLE 2  | `/2`      | 
#| RÖLE 3  | `/3`      | 
#| RÖLE 4  | `/4`      | 
#| RÖLE 5  | `/5`      |
#| RÖLE 6  | `/6`      | 
#| RÖLE 7  | `/7`      | 
#| RÖLE 8  | `/8`      | 
#| RÖLE 9  | `/9`      | 
#| RÖLE 10 | `/0`      | 
#| RÖLE 11 | `/a`      | 
#| RÖLE 12 | `/b`      | 
#| RÖLE 13 | `/c`      | 
#| RÖLE 14 | `/d`      | 
#| RÖLE 15 | `/e`      | 
#| RÖLE 16 | `/L`      | 

#────────────────────────────────────────
#RÖLE KAPATMA UDP GET DEĞERLERİ
#(web browserdan butonlardan doğrudan kontrol veya kod bloğundan request'le) 
#────────────────────────────────────────

#|  Röle   | Parametre |
#|------   |-----------|
#| RÖLE 1  | `/i`      | ESKİ VERSİYON ÜRÜNLERDE: `GET DEĞER /f`
#| RÖLE 2  | `/g`      | 
#| RÖLE 3  | `/h`      | 
#| RÖLE 4  | `/j`      | 
#| RÖLE 5  | `/k`      | 
#| RÖLE 6  | `/l`      | 
#| RÖLE 7  | `/m`      | 
#| RÖLE 8  | `/n`      |
#| RÖLE 9  | `/o`      | 
#| RÖLE 10 | `/p`      | 
#| RÖLE 11 | `/q`      | 
#| RÖLE 12 | `/t`      | 
#| RÖLE 13 | `/u`      | 
#| RÖLE 14 | `/v`      | 
#| RÖLE 15 | `/w`      | 
#| RÖLE 16 | `/M`      |

#GEREKSİNİMLER
#────────────────────────────────────────
#import socket
#import time
#import re
#import requests
#──────────────────────────────────────── 

#CODE:

#Seda Elektronik Ethernet Röle Kartı – Birleşik Kontrol Scripti
───────────────────────────────────────────────────────────────
#1) UDP ile 16 röleyi sırayla AÇAR (500ms arayla)
#2) HTTP GET ile PORTB, PORTD, PORTA, PORTE değerlerini OKUR
#3) UDP ile 16 röleyi sırayla KAPAR (500ms arayla)

#GEREKSİNİMLER:
pip install requests

YAPILANDIRMA:
#UDP_IP      → Röle kartının IP adresi (UDP)
#UDP_PORT    → Röle kartı UDP portu
#DEVICE_URL  → HTTP GET için kart URL'i
#UDP_IP   = "95.70.192.96"
#UDP_PORT = 250
import re
import socket
import time
import requests

# ──────────────────────────────────────────────
# YAPILANDIRMA
# ──────────────────────────────────────────────

UDP_IP   = "95.70.192.96"
UDP_PORT = 250

# Alternatif:
DEVICE_URL = "http://95.70.192.96:250/s"

RELAY_DELAY = 0.5  # Röleler arası bekleme süresi (saniye)

# ──────────────────────────────────────────────
# RÖLE PARAMETRELERI
# ──────────────────────────────────────────────

# UDP → Röle AÇMA parametreleri (Röle 1–16)
RELAY_ON = [
    b"1", b"2", b"3", b"4", b"5", b"6", b"7", b"8",
    b"9", b"0", b"a", b"b", b"c", b"d", b"e", b"L"
]

# UDP → Röle KAPATMA parametreleri (Röle 1–16)
RELAY_OFF = [
    b"i", b"g", b"h", b"j", b"k", b"l", b"m", b"n",
    b"o", b"p", b"q", b"t", b"u", b"v", b"w", b"M"
]

# ──────────────────────────────────────────────
# UDP FONKSİYONLARI
# ──────────────────────────────────────────────

def udp_send_sequence(commands: list, label: str = ""):
    """
    UDP üzerinden bir komut listesini sırayla gönderir.
    Her komut arasında RELAY_DELAY kadar bekler.
    """
    print(f"\n{'─'*45}")
    print(f"  {label}")
    print(f"{'─'*45}")

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    try:
        for i, cmd in enumerate(commands, start=1):
            sock.sendto(cmd, (UDP_IP, UDP_PORT))
            print(f"  Röle {i:2d}  →  '{cmd.decode()}' gönderildi")
            if i < len(commands):          # Son komuttan sonra bekleme yok
                time.sleep(RELAY_DELAY)
    finally:
        sock.close()

    print(f"  ✓ {label} tamamlandı.")


# ──────────────────────────────────────────────
# HTTP GET / PORT OKUMA FONKSİYONLARI
# ──────────────────────────────────────────────

def fetch_ports(url: str = DEVICE_URL, timeout: int = 3) -> dict:
    """
    Ethernet kartına HTTP GET atar, JS değişkenlerini parse eder.

    Kart yanıt formatı:
        var PORTB=     0;var PORTD=     0;PORTA=     0;PORTE=     0;

    Returns:
        {"PORTA": 0, "PORTB": 42, ..., "status": "ok"}
    """
    try:
        response = requests.get(url, timeout=timeout)
        response.raise_for_status()
        raw_text = response.text.strip()

        pattern = r'(?:var\s+)?(PORT[A-Z])\s*=\s*(\d+)\s*;'
        matches = re.findall(pattern, raw_text)

        if not matches:
            return {"status": "error", "message": "Port verisi bulunamadı", "raw": raw_text}

        ports = {name: int(value) for name, value in matches}
        ports["raw"]    = raw_text
        ports["status"] = "ok"
        return ports

    except requests.ConnectionError:
        return {"status": "error", "message": "Cihaza bağlanılamadı. IP/Port kontrol edin."}
    except requests.Timeout:
        return {"status": "error", "message": f"Bağlantı zaman aşımına uğradı ({timeout}s)"}
    except requests.HTTPError as e:
        return {"status": "error", "message": f"HTTP hatası: {e}"}


def print_ports(data: dict):
    """Port değerlerini binary breakdown ile ekrana basar."""
    print(f"\n{'─'*45}")
    print("  PORT DURUMU OKUNUYOR")
    print(f"{'─'*45}")

    if data["status"] != "ok":
        print(f"  ✗ Hata: {data.get('message', 'Bilinmeyen hata')}")
        return

    for key in ("PORTA", "PORTB", "PORTD", "PORTE"):
        if key not in data:
            print(f"  {key:6s}  →  (bulunamadı)")
            continue

        val    = data[key]
        binary = format(val, "08b")
        bits   = "  ".join(
            f"b{i}={'1' if (val >> i) & 1 else '0'}"
            for i in range(7, -1, -1)   # MSB → LSB
        )
        print(f"  {key:6s}  =  {val:3d}  │  0b{binary}  │  {bits}")

    print(f"\n  Ham yanıt: {data.get('raw', 'N/A')}")
    print(f"{'─'*45}")


# ──────────────────────────────────────────────
# ANA AKIŞ
# ──────────────────────────────────────────────

def main():
    print("=" * 45)
    print("  Seda Elektronik – Röle Kontrol Scripti")
    print(f"  UDP  : {UDP_IP}:{UDP_PORT}")
    print(f"  HTTP : {DEVICE_URL}")
    print("=" * 45)

    # 1) 16 röleyi sırayla AÇ
    udp_send_sequence(RELAY_ON, label="16 RÖLE AÇILIYOR")

    # Kartın durumu güncellemesi için kısa bekleme
    time.sleep(1)

    # 2) Port değerlerini OKU
    port_data = fetch_ports()
    print_ports(port_data)

    # 3) 16 röleyi sırayla KAPAT
    udp_send_sequence(RELAY_OFF, label="16 RÖLE KAPATILIYOR")

    print("\n  ✓ İşlem tamamlandı.\n")


if __name__ == "__main__":
    main()

#CODE (only udp data sender):
#import socket
#import time

#UDP_IP = "95.70.192.96"
#UDP_PORT = 3000

# UDP socket oluştur
#sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

#try:
#    # İlk veri: "2"
#    sock.sendto(b"2", (UDP_IP, UDP_PORT))
#    print("Gonderildi: 2")

    # 500 ms bekle
#    time.sleep(0.5)

    # İkinci veri: "g"
#   sock.sendto(b"g", (UDP_IP, UDP_PORT))
#    print("Gonderildi: g")

#finally:
#    sock.close()

6- PYTHON USB HID CODE


# ===============================
# CİHAZ BİLGİLERİ
# ===============================
#VENDOR_ID  = 0x178E   # <-- kendi VID'in
#PRODUCT_ID = 0x07D9   # <-- kendi PID'in

# ===============================
# BAĞLANTI TİPİ: USB HID
# ===============================

# ===============================
# RÖLE KOMUTLARI
# ===============================
RELAY_ON_VALUES  = [1, 2, 3, 4, 5, 6, 7, 8]
RELAY_OFF_VALUES = [17, 18, 19, 20, 21, 22, 23, 24]
# ===============================

# ===============================
# GEREKSİNİMLER
# ===============================
#import hid
#import time
# ===============================


#CODE:

VENDOR_ID  = 0x178E   # <-- kendi VID'in
PRODUCT_ID = 0x07D9   # <-- kendi PID'in

import hid
import time

RELAY_ON_VALUES  = [1, 2, 3, 4, 5, 6, 7, 8]
RELAY_OFF_VALUES = [17, 18, 19, 20, 21, 22, 23, 24]

device = None

def connect():
    global device
    device = hid.device()
    device.open(VENDOR_ID, PRODUCT_ID)
    device.set_nonblocking(1)
    print("✔ HID cihaz bağlandı")


def disconnect():
    global device
    if device:
        device.close()
        device = None
        print("✖ HID cihaz kapatıldı")


def send_command(value):
    """
    WebHID'deki:
    new Uint8Array([0,0,0,value,0,0,0,0])
    birebir karşılığı
    """
    if not device:
        print("⚠ Cihaz bağlı değil")
        return

    report = [0x00, 0x00, 0x00, value, 0x00, 0x00, 0x00, 0x00]
    device.write(report)
    print(f"→ Komut gönderildi: {value} | {report}")


def relay_on(relay_no):
    send_command(RELAY_ON_VALUES[relay_no - 1])


def relay_off(relay_no):
    send_command(RELAY_OFF_VALUES[relay_no - 1])


def all_on():
    for v in RELAY_ON_VALUES:
        send_command(v)
        time.sleep(0.05)
    print("🔥 Tüm röleler AÇIK")


def all_off():
    for v in RELAY_OFF_VALUES:
        send_command(v)
        time.sleep(0.05)
    print("❄ Tüm röleler KAPALI")


# ===============================
# TEST
# ===============================
if __name__ == "__main__":
    try:
        connect()

        relay_on(1)
        time.sleep(1)

        relay_off(1)
        time.sleep(1)

        all_on()
        time.sleep(1)

        all_off()

    except Exception as e:
        print("Hata:", e)

    finally:
        disconnect() 

7- PYTHON USB CDC COM CODE

	  
# ===============================
# CİHAZ BİLGİLERİ
# ===============================
#USB COM PORT CDC
# ===============================
# BAĞLANTI TİPİ: COM Port
#9600 baud
#8 data bits
#1 stop bit
#No parity
# ===============================
# ===============================
# RÖLE KOMUTLARI
# ===============================
RELAY_ON_VALUES  = [1, 2, 3, 4, 5, 6, 7, 8]
RELAY_OFF_VALUES = [17, 18, 19, 20, 21, 22, 23, 24]
# ===============================
# ===============================
# GEREKSİNİMLER
# ===============================
#import serial
#import threading
#import time
# ===============================


#CODE:	  
	  	  
import serial
import threading
import time

# ==============================
# AYARLAR
# ==============================
COM_PORT = "COM5"      # Windows: COM5, COM6...
# Linux: "/dev/ttyACM0"
# Mac: "/dev/tty.usbmodemXXXX"
BAUDRATE = 9600

keep_reading = True


# ==============================
# OKUMA THREAD'I
# ==============================
def read_loop(ser):
    global keep_reading
    try:
        while keep_reading:
            if ser.in_waiting > 0:
                data = ser.readline().decode(errors="ignore").strip()
                if data:
                    print(f"📥 Receipt: {data}")
            time.sleep(0.01)
    except Exception as e:
        print("❌ Reading error:", e)


# ==============================
# ANA PROGRAM
# ==============================
try:
    ser = serial.Serial(
        port=COM_PORT,
        baudrate=BAUDRATE,
        timeout=1
    )

    print("✅ The connection is established.")

    # Okuma thread başlat
    read_thread = threading.Thread(target=read_loop, args=(ser,))
    read_thread.daemon = True
    read_thread.start()

    # Veri gönderme döngüsü
    while True:
        text = input("📤 Send data (exit için q): ")
        if text.lower() == "q":
            break

        ser.write((text + "\n").encode())
        print("📤 Sending:", text)

except Exception as e:
    print("❌ Connection error:", e)

finally:
    keep_reading = False
    time.sleep(0.2)
    if 'ser' in locals() and ser.is_open:
        ser.close()
    print("🔌 Connection closed.")

8-1 RASPBERRY PI RASPBIAN PYTHON GET CODE

	  
# ===============================
# CİHAZ BİLGİLERİ
# ===============================
#IP BUTON RASPERRY PI GET UDP SENDER - RASPBIAN OS
# ===============================
#BAĞLANTI TİPİ: ETHERNET - WIFI
#GET
#UDP
# ===============================
#────────────────────────────────────────
#RÖLE KONTROL DEĞERLERİ
#────────────────────────────────────────

#RÖLE AÇMA UDP GET DEĞERLERİ
#(web browserdan butonlardan doğrudan kontrol veya kod bloğundan request'le)
#Daha fazla bilgi için pdf kılavuzumuzu inceleyiniz:
#https://sedaelektronik.com.tr/KULLANIM-KILAVUZLARI/ip-button-kullanim-kilavuzu.pdf
#https://sedaelektronik.com.tr/KULLANIM-KILAVUZLARI/terminal-ayarlari.txt 
#────────────────────────────────────────

#|  Röle   | Parametre |
#|------   |-----------|
#| RÖLE 1  | `/1`      |
#| RÖLE 2  | `/2`      | 
#| RÖLE 3  | `/3`      | 
#| RÖLE 4  | `/4`      | 
#| RÖLE 5  | `/5`      |
#| RÖLE 6  | `/6`      | 
#| RÖLE 7  | `/7`      | 
#| RÖLE 8  | `/8`      | 
#| RÖLE 9  | `/9`      | 
#| RÖLE 10 | `/0`      | 
#| RÖLE 11 | `/a`      | 
#| RÖLE 12 | `/b`      | 
#| RÖLE 13 | `/c`      | 
#| RÖLE 14 | `/d`      | 
#| RÖLE 15 | `/e`      | 
#| RÖLE 16 | `/L`      | 

#────────────────────────────────────────
#RÖLE KAPATMA UDP GET DEĞERLERİ
#(web browserdan butonlardan doğrudan kontrol veya kod bloğundan request'le) 
#────────────────────────────────────────

#|  Röle   | Parametre |
#|------   |-----------|
#| RÖLE 1  | `/i`      | ESKİ VERSİYON ÜRÜNLERDE: `GET DEĞER /f`
#| RÖLE 2  | `/g`      | 
#| RÖLE 3  | `/h`      | 
#| RÖLE 4  | `/j`      | 
#| RÖLE 5  | `/k`      | 
#| RÖLE 6  | `/l`      | 
#| RÖLE 7  | `/m`      | 
#| RÖLE 8  | `/n`      |
#| RÖLE 9  | `/o`      | 
#| RÖLE 10 | `/p`      | 
#| RÖLE 11 | `/q`      | 
#| RÖLE 12 | `/t`      | 
#| RÖLE 13 | `/u`      | 
#| RÖLE 14 | `/v`      | 
#| RÖLE 15 | `/w`      | 
#| RÖLE 16 | `/M`      |
# ===============================
# GEREKSİNİMLER
# ===============================
#!/usr/bin/env python
#dos2unix must be setup and convert this file
#import tkinter
#from tkinter import *
#from PIL import Image, ImageTk #ImageTK hatası için terminale şu kodun girilmesi gerekmektedir. sudo apt-get install python3-pil.imagetk
#from tkinter import messagebox
#import requests
#from tkinter import ttk
#import RPi.GPIO as GPIO
# ===============================


#CODE:	  
	  
#!/usr/bin/env python
#dos2unix must be setup and convert this file
import tkinter
from tkinter import *
from PIL import Image, ImageTk #ImageTK hatası için terminale şu kodun girilmesi gerekmektedir. sudo apt-get install python3-pil.imagetk
from tkinter import messagebox
import requests
from tkinter import ttk
import RPi.GPIO as GPIO


GPIO.setmode(GPIO.BCM)

root = Tk()
root.title("SEDA ELEKTRONİK")
root.geometry("700x800")
root.config(bd=0)

my_notebook = ttk.Notebook(root)
my_notebook.pack(pady = 15)

my_frame_1 = Frame(my_notebook, width = 700,height=800,bd=0)
my_frame_2 = Frame(my_notebook, width = 700,height=800,bd=0)

my_frame_1.pack(fill="both",expand=1)
my_frame_2.pack(fill="both",expand=1)

my_notebook.add(my_frame_2,text="RELAY/BUTON KONTROL")
my_notebook.add(my_frame_1,text="KONTROL IP DÜZENLEME")



is_on_1 = False
is_on_2 = False
is_on_3 = False
is_on_4 = False
is_on_5 = False
is_on_6 = False
is_on_7 = False
is_on_8 = False
is_on_9 = False
is_on_10 = False
is_on_11 = False
is_on_12 = False
is_on_13 = False
is_on_14 = False
is_on_15 = False
is_on_16 = False

loc = r"./role_urls"

button_in_1 =  9
button_in_2 =  10 
button_in_3 =  11
button_in_4 =  12
button_in_5 =  13
button_in_6 =  16
button_in_7 =  17
button_in_8 =  18
button_in_9 =  19
button_in_10 =  20
button_in_11 =  21
button_in_12 =  22
button_in_13 =  23
button_in_14 =  24
button_in_15 =  25
button_in_16 =  26

#GPIO.setup(button_in_1,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_2,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_3,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_4,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_5,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_6,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_7,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_8,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_9,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_10,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_11,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_12,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_13,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_14,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_15,GPIO.IN,pull_up_down = GPIO.PUD_UP)
#GPIO.setup(button_in_16,GPIO.IN,pull_up_down = GPIO.PUD_UP)
try:
    def ip_list():
        role_keys = ['1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','L','f','g','h','j','k','l','m','n','o','p','q','t','u','v','w','M']
        
        urls_role = list()
        for key in role_keys:
            role_ip = enter_txt.get()
            role_ip = "http://" + role_ip + ":3000" + "/" + key
            urls_role.append(role_ip)
        return urls_role

    def deafult_ip_list():
        role_keys = ['1','2','3','4','5','6','7','8','9','0','a','b','c','d','e','L','f','g','h','j','k','l','m','n','o','p','q','t','u','v','w','M']
        
        urls_role = list()
        for key in role_keys:
            role_ip = "169.254.1.2"
            role_ip = "http://" + role_ip + ":3000" + "/" + key
            urls_role.append(role_ip)
        return urls_role


    def change_ip():
        
        ip = enter_txt.get()
        ip +=":3000"
        info_ip.config(text=ip)
        
        role_urls = ip_list()

        with open(loc, 'r') as file :
            filedata = file.read()
            splitfile = filedata.split(' , ')

        role_urls = ip_list()

        c=0
        for url in role_urls:
            if c==32: c=0
            filedata = filedata.replace(splitfile[c], url,1)
            c+=1
        
        with open(loc, 'w') as file:
            file.write(filedata)
            

       
        
    def default_ip():
        with open(loc, 'r') as file :
            filedata = file.read()
            splitfile = filedata.split(' , ')
      
        ip = "169.254.1.2"
        ip +=":3000"
        info_ip.config(text=ip)
        
        role_urls = deafult_ip_list()

        with open(loc, 'r') as file :
            filedata = file.read()
            splitfile = filedata.split(' , ')
        c=0
        for url in role_urls:
            if c==32: c=0
            filedata = filedata.replace(splitfile[c], url,1)
            c+=1
        
        with open(loc, 'w') as file:
            file.write(filedata)
        messagebox.showinfo("BAŞARILI","YENİ IP = " + ip)

    def button_click(args):
        global is_on_1
        global is_on_2
        global is_on_3
        global is_on_4
        global is_on_5
        global is_on_6
        global is_on_7
        global is_on_8
        global is_on_9
        global is_on_10
        global is_on_11
        global is_on_12
        global is_on_13
        global is_on_14
        global is_on_15
        global is_on_16
        
        with open(loc, 'r') as file :
                filedata = file.read()
                urls = filedata.split(' , ')
            
        if (args == 1 and is_on_1 == False):
            try:
                request = requests.get(urls[0],timeout = 3)
                button_1.config(image = on)
                request.raise_for_status()
                is_on_1 = True
                button_1_label.config(fg="green")
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası","Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
           
        elif (args == 1 and is_on_1 == True):
            try:
                
                button_1.config(image = off)
                request = requests.get(urls[16],timeout=3)
                request.raise_for_status()
                is_on_1 = False
                button_1_label.config(fg="red")
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası","Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        
        if (args == 2 and is_on_2 == False):
            try:
                request = requests.get(urls[1],timeout=3)
                request.raise_for_status()
                button_2.config(image = on)
                button_2_label.config(fg="green")
                is_on_2 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 2 and is_on_2 == True):
            try:
                request = requests.get(urls[17],timeout=3)
                request.raise_for_status()
                button_2.config(image = off)
                button_2_label.config(fg="red")
                is_on_2 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        
        if (args == 3 and is_on_3 == False):
            try:
                request = requests.get(urls[2],timeout=3)
                request.raise_for_status()
                button_3.config(image = on)
                is_on_3 = True
                button_3_label.config(fg="green")
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
        elif (args == 3 and is_on_3 == True):
            try:
                request = requests.get(urls[18],timeout=3)
                request.raise_for_status()
                button_3.config(image = off)
                button_3_label.config(fg="red")
                is_on_3 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
         
        
        if (args == 4 and is_on_4 == False):
            try:
                request = requests.get(urls[3],timeout=3)
                request.raise_for_status()
                button_4.config(image = on)
                button_4_label.config(fg="green")
                is_on_4 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 4 and is_on_4 == True):
            try:
                request = requests.get(urls[19],timeout=3)
                request.raise_for_status()
                button_4.config(image = off)
                button_4_label.config(fg="red")
                is_on_4 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        
        if (args == 5 and is_on_5 == False):
            try:
                request = requests.get(urls[4],timeout=3)
                request.raise_for_status()
                button_5.config(image = on)
                button_5_label.config(fg="green")
                is_on_5 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 5 and is_on_5 == True):
            try:
                request = requests.get(urls[20],timeout=3)
                request.raise_for_status()
                button_5.config(image = off)
                button_5_label.config(fg="red")
                is_on_5 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
            
        if (args == 6 and is_on_6 == False):
            try:
                request = requests.get(urls[5],timeout=3)
                request.raise_for_status()
                button_6.config(image = on)
                button_6_label.config(fg="green")
                is_on_6 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 6 and is_on_6 == True):
            try:
                request = requests.get(urls[21],timeout=3)
                request.raise_for_status()
                button_6.config(image = off)
                button_6_label.config(fg="red")
                is_on_6 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        
        if (args == 7 and is_on_7 == False):
            try:
                request = requests.get(urls[6],timeout=3)
                request.raise_for_status()
                button_7.config(image = on)
                button_7_label.config(fg="green")
                is_on_7 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 7 and is_on_7 == True):
            try:
                request = requests.get(urls[22],timeout=3)
                request.raise_for_status()
                button_7.config(image = off)
                button_7_label.config(fg="red")
                is_on_7 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        
        if (args == 8 and is_on_8 == False):
            try:
                request = requests.get(urls[7],timeout=3)
                request.raise_for_status()
                button_8.config(image = on)
                button_8_label.config(fg="green")
                is_on_8 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 8 and is_on_8 == True):
            try:
                request = requests.get(urls[23],timeout=3)
                request.raise_for_status()
                button_8.config(image = off)
                button_8_label.config(fg="red")
                is_on_8 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        
        if (args == 9 and is_on_9 == False):
            try:
                request = requests.get(urls[8],timeout=3)
                request.raise_for_status()
                button_9.config(image = on)
                button_9_label.config(fg="green")
                is_on_9 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 9 and is_on_9 == True):
            try:
                request = requests.get(urls[24],timeout=3)
                request.raise_for_status()
                button_9.config(image = off)
                button_9_label.config(fg="red")
                is_on_9 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        
        if (args == 10 and is_on_10 == False):
            try:
                request = requests.get(urls[9],timeout=3)
                request.raise_for_status()
                button_10.config(image = on)
                button_10_label.config(fg="green")
                is_on_10 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 10 and is_on_10 == True):
            try:
                request = requests.get(urls[25],timeout=3)
                request.raise_for_status()
                button_10.config(image = off)
                button_10_label.config(fg="red")
                is_on_10 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        
        if (args == 11 and is_on_11 == False):
            try:
                request = requests.get(urls[10],timeout=3)
                request.raise_for_status()
                button_11.config(image = on)
                button_11_label.config(fg="green")
                is_on_11 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 11 and is_on_11 == True):
            try:
                request = requests.get(urls[26],timeout=3)
                request.raise_for_status()
                button_11.config(image = off)
                button_11_label.config(fg="red")
                is_on_11 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        
        if (args == 12 and is_on_12 == False):
            try:
                request = requests.get(urls[11],timeout=3)
                request.raise_for_status()
                button_12.config(image = on)
                button_12_label.config(fg="green")
                is_on_12 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 12 and is_on_12 == True):
            try:
                request = requests.get(urls[27],timeout=3)
                request.raise_for_status()
                button_12.config(image = off)
                button_12_label.config(fg="red")
                is_on_12 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        
        if (args == 13 and is_on_13 == False):
            try:
                request = requests.get(urls[12],timeout=3)
                request.raise_for_status()
                button_13.config(image = on)
                button_13_label.config(fg="green")
                is_on_13 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 13 and is_on_13 == True):
            try:
                request = requests.get(urls[28],timeout=3)
                request.raise_for_status()
                button_13.config(image = off)
                button_13_label.config(fg="red")
                is_on_13 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        
        if (args == 14 and is_on_14 == False):
            try:
                request = requests.get(urls[13],timeout=3)
                request.raise_for_status()
                button_14.config(image = on)
                button_14_label.config(fg="green")
                is_on_14 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 14 and is_on_14 == True):
            try:
                request = requests.get(urls[29],timeout=3)
                request.raise_for_status()
                button_14.config(image = off)
                button_14_label.config(fg="red")
                is_on_14 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        
        if (args == 15 and is_on_15 == False):
            try:
                request = requests.get(urls[14],timeout=3)
                request.raise_for_status()
                button_15.config(image = on)
                button_15_label.config(fg="green")
                is_on_15 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 15 and is_on_15 == True):
            try:
                request = requests.get(urls[30],timeout=3)
                request.raise_for_status()
                button_15.config(image = off)
                button_15_label.config(fg="red")
                is_on_15 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        
        if (args == 16 and is_on_16 == False):
            try:
                request = requests.get(urls[15],timeout=3)
                request.raise_for_status()
                button_16.config(image = on)
                button_16_label.config(fg="green")
                is_on_16 = True
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
        elif (args == 16 and is_on_16 == True):
            try:
                request = requests.get(urls[31],timeout=3)
                request.raise_for_status()
                button_16.config(image = off)
                button_16_label.config(fg="red")
                is_on_16 = False
            except requests.ConnectionError:
                messagebox.showerror("Bağlantı Hatası",
                "Ethernet Röle Kartı Bulunamadı. Lütfen IP adresinizi kontrol ediniz.")
            
    def check_ip_address():
        with open(loc, 'r') as file :
            filedata = file.read()
            splitfile = filedata.split(' , ')
        splitfile_2 =splitfile[0].split(':')
        ip = splitfile_2[0]+":"+splitfile_2[1]
        ip +=":3000"
        info_ip.config(text=ip)
        

    def check_button ():
        global is_on_1
        global is_on_2
        global is_on_3
        global is_on_4
        global is_on_5
        global is_on_6
        global is_on_7
        global is_on_8
        global is_on_9
        global is_on_10
        global is_on_11
        global is_on_12
        global is_on_13
        global is_on_14
        global is_on_15
        global is_on_16
        
        if GPIO.input(button_in_1)==0:
            is_on_1 = True
            button_1.config(image = on)
            button_1_label.config(fg="green")
        if GPIO.input(button_in_1)==1:
            button_1.config(image = off)
            button_1_label.config(fg="red")
        if GPIO.input(button_in_2)==0:
            is_on_2 = True
            button_2.config(image = on)
            button_2_label.config(fg="green")
        if GPIO.input(button_in_2)==1:
            button_2.config(image = off)
            button_2_label.config(fg="red")
        if GPIO.input(button_in_3)==0:
            is_on_3 = True
            button_3.config(image = on)
            button_3_label.config(fg="green")
        if GPIO.input(button_in_3)==1:
            button_3.config(image = off)
            button_3_label.config(fg="red")
        if GPIO.input(button_in_4)==0:
            is_on_4 = True
            button_4.config(image = on)
            button_4_label.config(fg="green")
        if GPIO.input(button_in_4)==1:
            button_4.config(image = off)
            button_4_label.config(fg="red")
        if GPIO.input(button_in_5)==0:
            is_on_5 = True
            button_5.config(image = on)
            button_5_label.config(fg="green")
        if GPIO.input(button_in_5)==1:
            button_5.config(image = off)
            button_5_label.config(fg="red")
        if GPIO.input(button_in_6)==0:
            is_on_6 = True 
            button_6.config(image = on)
            button_6_label.config(fg="green")
        if GPIO.input(button_in_6)==1:
            button_6.config(image = off)
            button_6_label.config(fg="red")
        if GPIO.input(button_in_7)==0:
            is_on_7 = True
            button_7.config(image = on)
            button_7_label.config(fg="green")
        if GPIO.input(button_in_7)==1:
            button_7.config(image = off)
            button_7_label.config(fg="red")
        if GPIO.input(button_in_8)==0:
            is_on_8 = True
            button_8.config(image = on)
            button_8_label.config(fg="green")
        if GPIO.input(button_in_8)==1:
            button_8.config(image = off)
            button_8_label.config(fg="red")
        if GPIO.input(button_in_9)==0:
            is_on_9 = True
            button_9.config(image = on)
            button_9_label.config(fg="green")
        if GPIO.input(button_in_9)==1:
            button_9.config(image = off)
            button_9_label.config(fg="red")
        if GPIO.input(button_in_10)==0:
            is_on_10 = True
            button_10.config(image = on)
            button_10_label.config(fg="green")
            
        if GPIO.input(button_in_10)==1:
            button_10.config(image = off)
            button_10_label.config(fg="red")
        if GPIO.input(button_in_11)==0:
            is_on_11 = True
            button_11.config(image = on)
            button_11_label.config(fg="green")
        if GPIO.input(button_in_11)==1:
            button_11.config(image = off)
            button_11_label.config(fg="red")
        if GPIO.input(button_in_12)==0:
            is_on_12 = True
            button_12.config(image = on)
            button_12_label.config(fg="green")
        if GPIO.input(button_in_12)==1:
            button_12.config(image = off)
            button_12_label.config(fg="red")
        if GPIO.input(button_in_13)==0:
            is_on_13 = True
            button_13.config(image = on)
            button_13_label.config(fg="green")
        if GPIO.input(button_in_13)==1:
            button_13.config(image = off)
            button_13_label.config(fg="red")
        if GPIO.input(button_in_14)==0:
            is_on_14 = True
            button_14.config(image = on)
            button_14_label.config(fg="green")
        if GPIO.input(button_in_14)==1:
            button_14.config(image = off)
            button_14_label.config(fg="red")
        if GPIO.input(button_in_15)==0:
            is_on_15 = True
            button_15.config(image = on)
            button_15_label.config(fg="green")
        if GPIO.input(button_in_15)==1:
            button_15.config(image = off)
            button_15_label.config(fg="red")
        if GPIO.input(button_in_16)==0:
            is_on_16 = True
            button_16.config(image = on)
            button_16_label.config(fg="green")
        if GPIO.input(button_in_16)==1:
            button_16.config(image = off)
            button_16_label.config(fg="red")
        

   


    heading = Label(my_frame_1, text = "KONTROL-IP'si DEĞİŞİTİRME PROGRAMI",font=("Trebucet MS",20,"bold"),bd=0,fg="black")
    heading.pack(pady=(50,0))
    heading.place(x=50,y=150)
    
    enter_txt = Entry(my_frame_1,justify="center",width=30,font=("poppins",25),bg="white",border=2)
    enter_txt.pack(pady=10)
    enter_txt.focus()
    enter_txt.place(x=30,y=215)

    button_degistir = Button(my_frame_1,text="Değiştir",font=("arial",20,"bold"),foreground="white",bg="red",command=change_ip)
    button_degistir.pack()
    button_degistir.place(x=445,y=304)

    button_default = Button(my_frame_1,text="Default",font=("arial",20,"bold"),foreground="white",bg="red",command=default_ip)
    button_default.pack()
    button_default.place(x=125,y=304)
    
    button_bc = Button(my_frame_2,text="BUTON RÖLE DURUMLARI",font=("arial",20,"bold"),foreground="white",bg="red",command=check_button)
    button_bc.pack()
    button_bc.place(x=170,y=650)

    info_ip = Label(my_frame_1,text="",font=("poppins",20),bd=0,fg="black")
    info_ip.place(x=377,y=400)

    cs = Label(my_frame_1,text="Kullanılan IP Adres : ",font=("poppins",20,"bold"),bd=0,fg="black",)
    cs.place(x=60,y=400)

    image1 = Image.open(r"./sedaelektronik_logo.png")
    logo = ImageTk.PhotoImage(image1)

    label1 = tkinter.Label(my_frame_1,image=logo)
    label1.image = logo
    label1.place(x=250, y=40)
    
    label2 = tkinter.Label(my_frame_2,image=logo)
    label2.image = logo
    label2.place(x=250, y=40)

    on = PhotoImage(file = r"./on.png")
    off = PhotoImage(file = r"./off.png")

    button_1 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(1))
    button_1.pack()
    button_1.place(x=190,y=200)
    button_1_label = Label(my_frame_2,text="-RELAY 1-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_1_label.place(x=55,y=205)

    button_2 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(2))
    button_2.pack()
    button_2.place(x=190,y=250)
    button_2_label = Label(my_frame_2,text="-RELAY 2-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_2_label.place(x=55,y=255)


    button_3 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(3))
    button_3.pack()
    button_3.place(x=190,y=300)
    button_3_label = Label(my_frame_2,text="-RELAY 3-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_3_label.place(x=55,y=305)

    button_4 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(4))
    button_4.pack()
    button_4.place(x=190,y=350)
    button_4_label = Label(my_frame_2,text="-RELAY 4-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_4_label.place(x=55,y=355)

    button_5 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(5))
    button_5.pack()
    button_5.place(x=190,y=400)
    button_5_label = Label(my_frame_2,text="-RELAY 5-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_5_label.place(x=55,y=405)

    button_6 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(6))
    button_6.pack()
    button_6.place(x=190,y=450)
    button_6_label = Label(my_frame_2,text="-RELAY 6-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_6_label.place(x=55,y=455)

    button_7 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(7))
    button_7.pack()
    button_7.place(x=190,y=500)
    button_7_label = Label(my_frame_2,text="-RELAY 7-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_7_label.place(x=55,y=505)

    button_8 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(8))
    button_8.pack()
    button_8.place(x=190,y=550)
    button_8_label = Label(my_frame_2,text="-RELAY 8-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_8_label.place(x=55,y=555)

    button_9 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(9))
    button_9.pack()
    button_9.place(x=410,y=200)
    button_9_label = Label(my_frame_2,text="-RELAY 9-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_9_label.place(x=525,y=205)

    button_10 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(10))
    button_10.pack()
    button_10.place(x=410,y=250)
    button_10_label = Label(my_frame_2,text="-RELAY 10-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_10_label.place(x=525,y=255)

    button_11 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(11))
    button_11.pack()
    button_11.place(x=410,y=300)
    button_11_label = Label(my_frame_2,text="-RELAY 11-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_11_label.place(x=525,y=305)

    button_12 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(12))
    button_12.pack()
    button_12.place(x=410,y=350)
    button_12_label = Label(my_frame_2,text="-RELAY 12-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_12_label.place(x=525,y=355)

    button_13 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(13))
    button_13.pack()
    button_13.place(x=410,y=400)
    button_13_label = Label(my_frame_2,text="-RELAY 13-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_13_label.place(x=525,y=405)


    button_14 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(14))
    button_14.pack()
    button_14.place(x=410,y=450)
    button_14_label = Label(my_frame_2,text="-RELAY 14-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_14_label.place(x=525,y=455)

    button_15 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(15))
    button_15.pack()
    button_15.place(x=410,y=500)
    button_15_label = Label(my_frame_2,text="-RELAY 15-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_15_label.place(x=525,y=505)

    button_16 = Button(my_frame_2,image = off,bd=0,command=lambda:button_click(16))
    button_16.pack()
    button_16.place(x=410,y=550)
    button_16_label = Label(my_frame_2,text="-RELAY 16-",font=("poppins",16,"bold"),bd=0,fg="red")
    button_16_label.place(x=525,y=555)
    my_frame_2.after(1,check_ip_address)
    my_frame_2.after(1,check_button)
    
    my_frame_2.mainloop()
    
except:
    tkinter.messagebox.showwarning(title="HATA MESAJI", message="LÜTFEN DOĞRU BİR IP ADRESİ GİRİNİZ")
   
                                                                                                                                                                                     		 






	  
	 

8-2 RASPBERRY PI RASPBIAN PYTHON RELAY CONTROLLER LIST CODE



#!/usr/bin/env python3
import time
import requests
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)

loc = r"/home/pi/Desktop/Program/role_urls"

button_1 =  9
button_2 =  10 
button_3 =  11
button_4 =  12
button_5 =  13
button_6 =  16
button_7 =  17
button_8 =  18
button_9 =  19
button_10 =  20
button_11 =  21
button_12 =  22
button_13 =  23
button_14 =  24
button_15 =  25
button_16 =  26

GPIO.setup(button_1,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_2,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_3,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_4,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_5,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_6,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_7,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_8,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_9,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_10,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_11,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_12,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_13,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_14,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_15,GPIO.IN,pull_up_down = GPIO.PUD_UP)
GPIO.setup(button_16,GPIO.IN,pull_up_down = GPIO.PUD_UP)

BS1 = False
BS2 = False
BS3 = False
BS4 = False
BS5 = False
BS6 = False
BS7 = False
BS8 = False
BS9 = False
BS10 = False
BS11 = False
BS12 = False
BS13 = False
BS14 = False
BS15 = False
BS16 = False
while(1):    
    try:
        with open(loc, 'r') as file :
            filedata = file.read()
            urls = filedata.split(' , ')
        if GPIO.input(button_1)==0:
            if BS1==False:
                request = requests.get(urls[0])
                BS1=True
                print("Buton 1 is OPEN")

        if GPIO.input(button_1)==1:
            if BS1==True:
                
                request = requests.get(urls[16])
                BS1 = False
                print("Buton 1 is CLOSE")
 	  
        if GPIO.input(button_2)==0:
            if BS2==False:
                print("Buton 2 is OPEN")
                request = requests.get(urls[1])
                BS2 = True

        if GPIO.input(button_2)==1:
            if BS2==True:
                print("Buton 2 is CLOSE")
                request = requests.get(urls[17])
                BS2 = False

        if GPIO.input(button_3)==0:
            if BS3==False:
                print("Buton 3 is OPEN")
                request = requests.get(urls[2])
                BS3 = True

        if GPIO.input(button_3)==1:
            if BS3==True:
                print("Buton 3 is CLOSE")
                request = requests.get(urls[18])
                BS3 = False

        if GPIO.input(button_4)==0:
            if BS4==False:
                print("Buton 4 is OPEN")
                request = requests.get(urls[3])
                BS4 = True

        if GPIO.input(button_4)==1:
            if BS4==True:
                print("Buton 4 is CLOSE")
                request = requests.get(urls[19])
                BS4 = False
                
        if GPIO.input(button_5)==0:
            if BS5==False:
                print("Buton 5 is OPEN")
                request = requests.get(urls[4])
                BS5 = True

        if GPIO.input(button_5)==1:
            if BS5==True:
                print("Buton 5 is CLOSE")
                request = requests.get(urls[20])
                BS5 = False
              
        if GPIO.input(button_6)==0:
            if BS6==False:
                print("Buton 6 is OPEN")
                request = requests.get(urls[5])
                BS6 = True
     
        if GPIO.input(button_6)==1:
            if BS6==True:
                print("Buton 6 is CLOSE")
                request = requests.get(urls[21])
                BS6 = False

        if GPIO.input(button_7)==0:
            if BS7==False:
                print("Buton 7 is OPEN")
                request = requests.get(urls[6])
                BS7 = True

        if GPIO.input(button_7)==1:
            if BS7==True:
                print("Buton 7 is CLOSE")
                request = requests.get(urls[22])
                BS7 = False

        if GPIO.input(button_8)==0:
            if BS8==False:
                print("Buton 8 is OPEN")
                request = requests.get(urls[7])
                BS8 = True

        if GPIO.input(button_8)==1:
            if BS8==True:
                print("Buton 8 is CLOSE")
                request = requests.get(urls[23])
                BS8 = False

        if GPIO.input(button_9)==0:
            if BS9==False:
                print("Buton 9 is OPEN")
                request = requests.get(urls[8])
                BS9 = True
      
        if GPIO.input(button_9)==1:
            if BS9==True:
                print("Buton 9 is CLOSE")
                request = requests.get(urls[24])
                BS9 = False

        if GPIO.input(button_10)==0:
            if BS10==False:
                print("Buton 10 is OPEN")
                request = requests.get(urls[9])
                BS10 = True

        if GPIO.input(button_10)==1:
            if BS10==True:
                print("Buton 10 is CLOSE")
                request = requests.get(urls[25])
                BS10 = False

        if GPIO.input(button_11)==0:
            if BS11==False:
                print("Buton 11 is OPEN")
                request = requests.get(urls[10])
                BS11 = True
         
        if GPIO.input(button_11)==1:
            if BS11==True:
                print("Buton 11 is CLOSE")
                request = requests.get(urls[26])
                BS11 = False
            
        if GPIO.input(button_12)==0:
            if BS12==False:
                print("Buton 12 is OPEN")
                request = requests.get(urls[11])
                BS12 = True
          
        if GPIO.input(button_12)==1:
            if BS12==True:
                print("Buton 12 is CLOSE")
                request = requests.get(urls[27])
                BS12 = False
     
        if GPIO.input(button_13)==0:
            if BS13==False:
                print("Buton 13 is OPEN")
                request = requests.get(urls[12])
                BS13 = True
            
        if GPIO.input(button_13)==1:
            if BS13==True:
                print("Buton 13 is CLOSE")
                request = requests.get(urls[28])
                BS13 = False
                
        if GPIO.input(button_14)==0:
            if BS14==False:
                print("Buton 14 is OPEN")
                request = requests.get(urls[13])
                BS14 = True
              
        if GPIO.input(button_14)==1:
            if BS14==True:
                print("Buton 14 is CLOSE")
                request = requests.get(urls[29])
                BS14 = False
              
        if GPIO.input(button_15)==0:
            if BS15==False:
                print("Buton 15 is OPEN")
                request = requests.get(urls[14])
                BS15 = True
              
        if GPIO.input(button_15)==1:
            if BS15==True:
                print("Buton 15 is CLOSE")
                request = requests.get(urls[30])
                BS15 = False
            
        if GPIO.input(button_16)==0:
            if BS16==False:
                print("Buton 16 is OPEN")
                request = requests.get(urls[15])
                BS16 = True
      
        if GPIO.input(button_16)==1:
            if BS16==True:
                print("Buton 16 is CLOSE")
                request = requests.get(urls[31])
                BS16 = False
    except:
        print("Doğru IP Girmelisiz. Lütfen IP değiştirme programına girip değişiklik yapınız.")


                                                                                                                                                                                     		 
	  
	 

8-3 RASPBERRY PI RASPBIAN PYTHON RELAY URLS LIST


	  
http://169.254.1.2:3000/1 , http://169.254.1.2:3000/2 , http://169.254.1.2:3000/3 , http://169.254.1.2:3000/4 , http://169.254.1.2:3000/5 , http://169.254.1.2:3000/6 , http://169.254.1.2:3000/7 , http://169.254.1.2:3000/8 , http://169.254.1.2:3000/9 , http://169.254.1.2:3000/0 , http://169.254.1.2:3000/a , http://169.254.1.2:3000/b , http://169.254.1.2:3000/c , http://169.254.1.2:3000/d , http://169.254.1.2:3000/e , http://169.254.1.2:3000/L , http://169.254.1.2:3000/i , http://169.254.1.2:3000/g , http://169.254.1.2:3000/h , http://169.254.1.2:3000/j , http://169.254.1.2:3000/k , http://169.254.1.2:3000/l , http://169.254.1.2:3000/m , http://169.254.1.2:3000/n , http://169.254.1.2:3000/o , http://169.254.1.2:3000/p , http://169.254.1.2:3000/q , http://169.254.1.2:3000/t , http://169.254.1.2:3000/u , http://169.254.1.2:3000/v , http://169.254.1.2:3000/w , http://169.254.1.2:3000/M