Ders 018 — FAT/SAT Kabul Testleri, Koruma Rölesi Koordinasyonu ve SAT Kapısı¶
Ders Navigasyonu
Önceki: Ders 017 — P5 Devreye Alma: Anahtarlama Programı, Ekipman Durum Makinesi ve LOTO | Sonraki: Yakında
Faz: P5 | Dil: Türkçe | İlerleme: 19 / 19 | Tüm Dersler | Öğrenme Yol Haritası
Date: 2026-02-27 Commits: 1 commit (
b7da3db) Commit range:810c5262f2ce0da0e3db8d6f2e67f23bb87e8a25..b7da3dbf0eb66a9ec3c881ad70d2c4bff274a13aPhase: P5 (Commissioning) Roadmap sections: [Phase 5 — Section 5.3 Testing & Commissioning, Section 5.1 HV Switching & Safety] Language: Turkish Previous lesson: Lesson 017 last_commit_hash: b7da3dbf0eb66a9ec3c881ad70d2c4bff274a13a
Ne Öğreneceksiniz¶
- Fabrika Kabul Testi (FAT) kampanya yaşam döngüsünü ve 8 IEC-standardına uygun test spesifikasyonunu anlayacaksınız
- Saha Kabul Testi (SAT) ile 12 kurulum sonrası test spesifikasyonunu ve FAT-kapısı (gate) mekanizmasını öğreneceksiniz
- Koruma rölesi (protection relay) ayarlarını ve zaman kademelemesi (time grading) ile selektivite doğrulamasını kavrayacaksınız
- SAT kapısının anahtarlama programı başlatma sürecine nasıl entegre edildiğini göreceksiniz
- Tolerans bandı değerlendirmesi ile otomatik geçti/kaldı (pass/fail) mantığını kodda uygulayacaksınız
Bölüm 1: Fabrika Kabul Testi (FAT) — Ekipman Denizde Bozulursa Ne Olur?¶
Gerçek Dünya Problemi¶
Bir online mağazadan bilgisayar sipariş ettiğinizi düşünün. Kargo geldiğinde ekranı kırık çıksa, iade edip yenisini almanız kolay — mağaza yakında. Ama sipariş ettiğiniz ürün 220/66 kV transformatör olsaydı ve kırık olduğunu 45 km açıktaki deniz platformunda fark etseydiniz? Bir gemi mobilizasyonu günde ~500.000 EUR'a mal olur ve onarım aylar sürer.
İşte FAT (Factory Acceptance Test) tam da bu senaryoyu önlemek için var: ekipman üreticinin fabrikasından ayrılmadan önce tüm testlerden geçmelidir.
Standartlar Ne Diyor¶
Fabrika testlerimiz 7 farklı IEC standardını kapsar:
| Test | Standart | Fiziksel Doğrulama |
|---|---|---|
| HV dayanım (withstand) | IEC 60060-1:2010 | 460 kV AC, 60 s — yalıtım bütünlüğü |
| Kısmi deşarj (PD) | IEC 60270:2000 | < 10 pC — yalıtım yaşlanma erken tespiti |
| Transformatör oranı | IEC 60076-1:2011 | 220/66 kV = 3,333 ±%0,5 |
| Empedans testi | IEC 60076-1:2011 | ±%10 nameplate değeri |
| FRA referans | IEC 60076-18:2012 | Elektromanyetik parmak izi |
| DGA referans | IEC 60567:2011 | Yağ gaz analizi < 50 ppm |
| Röle tip testi | IEC 60255:2022 | ±%5 doğruluk |
| GIS gaz sızdırmazlık | IEC 62271-203:2022 | SF6 kaçağı < %0,5/yıl |
Ne İnşa Ettik¶
Değişen dosyalar:
backend/app/services/p5/fat.py— FAT test spesifikasyonları, kampanya yaşam döngüsü ve otomatik verdikt değerlendirmesibackend/app/schemas/commissioning.py— FAT/SAT Pydantic şemaları (API request/response modelleri)backend/app/routers/p5.py— FAT CRUD ve sonuç kayıt endpoint'leribackend/tests/test_fat.py— 8 spesifikasyon doğrulaması, kampanya yaşam döngüsü testleri
FAT modülü üç temel kavram üzerine kurulu:
- TestSpecification — değişmez (frozen) test tanımı: test ID, standart referansı, kabul sınırları (min/max)
- TestResult — ölçüm kaydı: ölçülen değer, verdikt, mühendis adı, zaman damgası
- FATCampaign — kampanya yaşam döngüsü:
CREATED → IN_PROGRESS → COMPLETED → APPROVED
Neden Önemli¶
Neden fabrikada 8 ayrı test yapıyoruz? Her test farklı bir fiziksel arıza modunu yakalıyor. HV dayanım testi yalıtım bütünlüğünü, PD testi yalıtım yaşlanma belirtilerini, FRA ise sargı/çekirdek yer değiştirmesini tespit eder. Tek bir test tüm arıza modlarını kapsayamaz — savunma derinliği (defense in depth) ilkesi geçerlidir.
Neden tolerans bantlarını
min_value/max_valueçifti olarak modelledik? Bazı testler tek taraflıdır (PD < 10 pC → sadece üst sınır), bazıları iki taraflıdır (transformatör oranı ±%0,5 → alt ve üst sınır).float('-inf')vefloat('inf')kullanarak aynıevaluate_test_verdict()fonksiyonuyla her iki durumu da ele alırız. Bu, kod tekrarını önler ve yeni test eklemek için tek yapılması gerekenFAT_SPECStuple'ına yeni birTestSpecificationeklemektir.
Kod İncelemesi¶
Tolerans bandı değerlendirmesi tüm FAT ve SAT sisteminin temel taşıdır. Fonksiyon saf (pure) bir fonksiyondur — dış duruma bağlı değildir:
def evaluate_test_verdict(spec: TestSpecification, measured_value: float) -> TestVerdict:
"""Ölçülen değeri spesifikasyon tolerans bandına göre değerlendir.
PASS koşulu: spec.min_value <= measured_value <= spec.max_value
Tek taraflı testler için sonsuzluk sınırları kullanılır:
PD testi: min=-inf, max=10.0 → ölçüm 10'un altındaysa PASS
HV testi: min=460, max=+inf → ölçüm 460'ın üstündeyse PASS
"""
if spec.min_value <= measured_value <= spec.max_value:
return TestVerdict.PASS
return TestVerdict.FAIL
Bu fonksiyon kasıtlı olarak basit tutulmuştur. Gerçek dünyada fuzzy sınırlar veya istatistiksel toleranslar olabilir, ancak IEC standartları kesin sınırlar tanımlar — ya geçersiniz ya kalırsınız.
Kampanya yaşam döngüsü bir Deterministik Sonlu Otomat (DFA) olarak modellendi:
def record_fat_result(
campaign: FATCampaign,
test_id: str,
measured_value: float,
recorded_by: str,
notes: str = "",
) -> TestResult:
# Onaylanmış kampanyaya sonuç eklenemez (geri dönüşü olmayan durum)
if campaign.status == TestCampaignStatus.APPROVED:
raise FATCampaignStateError(...)
# Test ID geçerliliğini kontrol et
if test_id not in campaign.specs:
raise FATTestNotFoundError(...)
# Otomatik verdikt değerlendirmesi
spec = campaign.specs[test_id]
verdict = evaluate_test_verdict(spec, measured_value)
result = TestResult(
test_id=test_id,
measured_value=measured_value,
verdict=verdict,
recorded_by=recorded_by,
notes=notes,
)
campaign.results[test_id] = result
# İlk sonuçta CREATED → IN_PROGRESS geçişi
if campaign.status == TestCampaignStatus.CREATED:
campaign.status = TestCampaignStatus.IN_PROGRESS
# Tüm spesifikasyonlar sonuçlandığında IN_PROGRESS → COMPLETED
if len(campaign.results) == len(campaign.specs):
campaign.status = TestCampaignStatus.COMPLETED
return result
Her sonuç kaydı iki olası durum geçişini otomatik olarak tetikler. Bu, durum makinesi mantığını iş mantığının doğal akışına gömer — ayrı bir transition() fonksiyonu gerekmez.
Temel Kavram¶
Temel Kavram: Tolerans Bandı Değerlendirmesi (Tolerance Band Evaluation)
Basitçe anlatımı: Bir sınavda geçme notu var — 50'nin üstü geçer, altı kalır. FAT testleri de aynı mantıkla çalışır: her testin bir alt ve üst sınırı var. Ölçüm bu sınırlar içindeyse PASS, dışındaysa FAIL.
Analoji: Bir mutfak termostatı düşünün. Fırın sıcaklığı 180°C-200°C arasındaysa yemek doğru pişer. 179°C'de çiğ kalır, 201°C'de yanar. FAT testlerindeki tolerans bandı tam olarak bu sıcaklık aralığıdır.
Bu projede: 510 MW rüzgar çiftliğimizde 220/66 kV transformatör oranı 3,317-3,350 aralığında olmalıdır (nominal 3,333 ±%0,5). Bu dar bantın dışına çıkmak, gerilim regülasyonunun bozulması ve koruma koordinasyonunun çökmesi demektir.
Bölüm 2: Saha Kabul Testi (SAT) — Nakliyat Sonrası Ne Değişir?¶
Gerçek Dünya Problemi¶
Bir antika vazo taşıdığınızı düşünün. Mağazada kusursuz görünüyordu (FAT geçti). Ama eve taşırken arabanın bagajında sallanıp gizli bir çatlak oluşmuş olabilir. Vazoyu kullanmadan önce suyla doldurup sızıntı kontrol edersiniz — bu SAT'tır.
Offshore ekipman deniz nakliyatı sırasında dalga kaynaklı titreşime, kurulum sırasında vinç kaldırma ve kablo çekme stresine, deniz ortamında nem ve tuz spreyi etkisine maruz kalır. Fabrikada geçen transformatörün sargıları nakliyat sırasında kayabilir — FAT'taki FRA referansı ile karşılaştırarak bu kaymayı tespit ederiz.
Standartlar Ne Diyor¶
SAT testlerimiz 10 farklı IEC/EN standardını kapsar:
| Test | Standart | Kritik Eşik |
|---|---|---|
| Yalıtım direnci | IEC 60229 | > 100 MOhm @ 5 kV DC |
| AÖ oranı (CT ratio) | IEC 61869-2 | ±%1 doğruluk |
| GT oranı (VT ratio) | IEC 61869-3 | ±%0,5 doğruluk |
| Kesici kapanma süresi | IEC 62271-100 | < 80 ms |
| Kesici açılma süresi | IEC 62271-100 | < 60 ms |
| Koruma röle trip | IEC 60255 | < 100 ms |
| GOOSE gecikmesi | IEC 61850-8-1 | < 4 ms |
| SCADA nokta doğrulama | IEC 60870-5-104 | %100 yanıt |
| Kademe değiştirici | IEC 60214 | Tam aralık |
| Yangın algılama | EN 54 | < 30 s |
Ne İnşa Ettik¶
Değişen dosyalar:
backend/app/services/p5/sat.py— 12 SAT test spesifikasyonu, FAT-kapısı uygulaması, kampanya yönetimibackend/tests/test_sat.py— FAT-gate testleri, kampanya yaşam döngüsü, anahtarlama programı entegrasyonu
SAT modülü FAT modülünün tip sistemini yeniden kullanır (TestSpecification, TestResult, TestVerdict, evaluate_test_verdict) — bu DRY (Don't Repeat Yourself) ilkesinin doğrudan uygulamasıdır. Tek fark: SAT oluşturulurken opsiyonel bir FAT kampanyası bağlanabilir.
Neden Önemli¶
Neden SAT, FAT'tan ayrı bir kampanya olarak tasarlandı? FAT ve SAT farklı zamanlarda, farklı yerlerde, farklı mühendisler tarafından yapılır. FAT üretici fabrikasında (ekipman sevkiyattan önce), SAT sahada (kurulumdan sonra). Bu ayrım sorumluluk zincirini (chain of custody) net tutar ve iz sürülebilirlik (traceability) sağlar.
Neden FAT-kapısı (gate) mekanizması opsiyonel yapıldı? Gerçek dünyada bazı ekipmanlar (örneğin mevcut stok) FAT kaydı olmadan sahaya gelebilir.
fat_campaign: FATCampaign | None = Noneparametresi bu esnekliği sağlarken, geçildiğinde onaylanmamış bir FAT'ı reddetme güvencesini korur.
Kod İncelemesi¶
FAT-kapısı mekanizması — SAT kampanyası oluşturulurken fabrika testlerinin onaylanmış olmasını zorunlu kılar:
def create_sat_campaign(
programme_id: str,
fat_campaign: FATCampaign | None = None,
) -> SATCampaign:
"""FAT-kapısı ile SAT kampanyası oluştur.
fat_campaign geçilmişse, durumu APPROVED olmalıdır.
Aksi halde SATFATGateError fırlatılır.
"""
if fat_campaign is not None and fat_campaign.status != TestCampaignStatus.APPROVED:
raise SATFATGateError(
f"FAT campaign '{fat_campaign.campaign_id}' is "
f"'{fat_campaign.status.value}', "
f"must be 'approved' before SAT can begin."
)
campaign_id = f"SAT-{datetime.now(UTC).strftime('%Y%m%d')}-"
f"{uuid.uuid4().hex[:6].upper()}"
specs = {spec.test_id: spec for spec in SAT_SPECS}
return SATCampaign(
campaign_id=campaign_id,
programme_id=programme_id,
fat_campaign_id=fat_campaign.campaign_id if fat_campaign else "",
specs=specs,
)
Bu kapı mekanizması "önce kontrol et, sonra yarat" ilkesini uygular. Fabrika testleri onaylanmamışsa, saha testi kampanyası hiç oluşturulamaz — hatalı duruma düşme şansı sıfırdır.
Temel Kavram¶
Temel Kavram: Kapı Mekanizması (Gate Pattern)
Basitçe anlatımı: Bir uçağa binmeden önce kapıda biniş kartınızı gösterirsiniz. Kartınız yoksa ya da yanlışsa içeri giremezsiniz. FAT-kapısı da aynı şekilde çalışır: fabrika testleri onaylanmadan saha testleri başlatılamaz.
Analoji: Bir bilgisayar oyunundaki seviye kilitleri gibi düşünün. Seviye 1'i bitirmeden Seviye 2'ye geçemezsiniz. FAT = Seviye 1, SAT = Seviye 2, Enerji verme = Seviye 3.
Bu projede: 510 MW rüzgar çiftliğimizde TX-OSS-01 transformatörü fabrikada 8 test geçmeden gemiye yüklenmez (FAT kapısı), sahada 12 test geçmeden enerji verilmez (SAT kapısı). Bu iki kapı, denizde arıza riskini dramatik olarak azaltır.
Bölüm 3: Koruma Rölesi Koordinasyonu — Doğru Şalter Doğru Zamanda¶
Gerçek Dünya Problemi¶
Evinizde elektrik prizinin sigortası attığında sadece o oda karanlık kalır — tüm bina değil. Bunun nedeni: her sigorta kendi bölgesini korur ve "kim önce atacak" sıralaması önceden belirlenmiştir. Offshore rüzgar çiftliğinde de durum aynıdır, ancak yanlış sıralama 34 türbinin tamamını şebekeden düşürür.
Bir 66 kV dizi kablosunda arıza olduğunda, dizi besleyici rölesi (downstream) arızayı temizlemelidir — 220 kV ihracat kablosu rölesi (upstream) değil. Eğer upstream röle önce atarsa, arızalı dizideki 6 türbin yerine tüm çiftlik devre dışı kalır.
Standartlar Ne Diyor¶
- IEC 60255-151:2009 — Aşırı akım koruması (PTOC) zaman ayarları
- IEC 60255-121:2014 — Mesafe koruması (PDIS) bölge ayarları
- IEC 60255-127:2010 — Aşırı/düşük gerilim koruması (PTOV/PTUV)
- IEC 60255-181:2019 — Aşırı/düşük frekans koruması (PTOF/PTUF)
- IEEE C37.112 — Ters zamanlı aşırı akım röle koordinasyonu
Zaman kademelemesi (time grading) formülü:
gerçek_marjin = (upstream_gecikme - downstream_gecikme) × 1000 ms
Karar: gerçek_marjin ≥ gerekli_marjin → SELEKTİF
gerçek_marjin < gerekli_marjin → SELEKTİF DEĞİL
PTOC için gereken marjin: 300 ms (kesici açma + röle hatası + güvenlik payı). PDIS için gereken marjin: 400 ms (bölgeler arası daha büyük ayrım gerekir).
Ne İnşa Ettik¶
Değişen dosyalar:
backend/app/services/p5/protection_relay.py— 8 röle ayarı, 2 kademe çifti, selektivite doğrulama fonksiyonlarıbackend/tests/test_protection_relay.py— Ayar doğrulaması, selektif/selektif olmayan senaryolarbackend/app/routers/p5.py—/protection/settingsve/protection/verify-selectivityendpoint'leri
Koruma sistemi üç veri modelinden oluşur:
- RelaySetting — değişmez röle ayarı (ID, fonksiyon, pickup değeri, zaman gecikmesi, konum)
- GradingPair — downstream→upstream röle çifti ve gereken marjin
- GradingResult — doğrulama sonucu (gerçek marjin, verdikt)
Neden Önemli¶
Neden 8 farklı koruma fonksiyonu tanımladık? Her fonksiyon farklı bir arıza tipini algılar. PTOC aşırı akımı (kablo kısa devresi), PDIS mesafe bazlı arızayı (kablo boyunca konum tespiti), PTOV/PTUV gerilim anormalliklerini, PTOF/PTUF frekans sapmalarını yakalar. Birden fazla fonksiyon "savunma derinliği" sağlar — bir röle kaçırırsa yedek (backup) devreye girer.
Neden selektivite doğrulamasını saf fonksiyon (pure function) olarak yazdık?
verify_selectivity()herhangi bir röle seti ve kademe çifti üzerinde çalışabilir (varsayılan olarak OSS setini kullanır). Bu, farklı röle konfigürasyonlarını test etmeyi, gelecekte yeni röle setleri eklemeyi ve birim testlerinde mock olmadan doğrudan test yapmayı kolaylaştırır.
Kod İncelemesi¶
Kademe çifti doğrulaması — mühendislik formülünün doğrudan kodlamaya çevrilmesi:
def check_single_grading_pair(
pair: GradingPair,
settings: dict[str, RelaySetting],
) -> GradingResult:
"""Bir downstream→upstream çifti için selektivite kontrolü.
Formül: gerçek_marjin = (upstream.time_delay - downstream.time_delay) × 1000
Örnek (PTOC):
Downstream: 0.5 s (dizi besleyici)
Upstream: 0.8 s (incomer yedek)
Gerçek marjin = (0.8 - 0.5) × 1000 = 300 ms ≥ 300 ms → SELEKTİF ✓
"""
downstream = settings[pair.downstream_id]
upstream = settings[pair.upstream_id]
actual_margin_ms = (upstream.time_delay - downstream.time_delay) * 1000.0
verdict = (
SelectivityVerdict.SELECTIVE
if actual_margin_ms >= pair.required_margin_ms
else SelectivityVerdict.NON_SELECTIVE
)
return GradingResult(
pair_id=pair.pair_id,
downstream_id=pair.downstream_id,
upstream_id=pair.upstream_id,
downstream_delay_s=downstream.time_delay,
upstream_delay_s=upstream.time_delay,
actual_margin_ms=actual_margin_ms,
required_margin_ms=pair.required_margin_ms,
verdict=verdict,
)
Kodun IEC formülü ile bire bir eşleşmesine dikkat edin. Mühendislik hesaplamasını doğrudan koda çevirmek, gözden geçirme sürecini kolaylaştırır — standart belgesindeki formül ile kodu yan yana koyabilirsiniz.
Tüm çiftlerin toplu doğrulaması tek satırda yapılır:
def verify_selectivity(
settings: tuple[RelaySetting, ...] | None = None,
grading_pairs: tuple[GradingPair, ...] | None = None,
) -> list[GradingResult]:
"""Tüm kademe çiftleri için selektivite doğrulaması.
Varsayılan olarak OSS röle setini kullanır.
Sonuç: her çift için bir GradingResult listesi.
"""
if settings is None:
settings = OSS_RELAY_SETTINGS
if grading_pairs is None:
grading_pairs = GRADING_PAIRS
settings_map = {s.setting_id: s for s in settings}
return [check_single_grading_pair(pair, settings_map) for pair in grading_pairs]
settings_map dictionary'si, her röle ayarını O(1) sürede bulmamızı sağlar. N kademe çifti için toplam karmaşıklık O(N) — tuple tarama yapılmaz.
Temel Kavram¶
Temel Kavram: Zaman Kademelemesi ile Selektivite (Time Grading for Selectivity)
Basitçe anlatımı: Bir yarışta koşucular aynı anda değil, sırayla startı alır — önce en yakındaki koşucu, sonra arkadaki. Koruma röleleri de böyledir: arızaya en yakın röle önce atar, yedek röle daha sonra devreye girer.
Analoji: Yangın söndürme sistemi düşünün. Odadaki sprinkler önce çalışır. Eğer yangın büyürse, kattaki ana vana açılır. Eğer hâlâ sönmediyse, tüm bina sistemi devreye girer. Her seviye öncekine "marjin süresi" bırakır.
Bu projede: Dizi besleyici rölesi 0,5 s'de atar. Incomer yedek rölesi 0,8 s'de atar. Aradaki 300 ms marjin, kesici açma süresi (60 ms) + röle hatası + güvenlik payını kapsar. Bu sayede sadece arızalı dizi kopuyor, tüm çiftlik ayakta kalıyor.
Bölüm 4: SAT Kapısı — Enerji Vermeden Önce Son Kilit¶
Gerçek Dünya Problemi¶
Bir nükleer santralde reaktör, tüm güvenlik kontrol listeleri tamamlanmadan çalıştırılamaz. Benzer şekilde, offshore trafo merkezinde saha kabul testleri tamamlanmadan 220 kV enerji verilemez. Bu "son kilit" mekanizması, insan hatasını yazılımla engeller.
Standartlar Ne Diyor¶
SAT kapısı, IEC 62271-100 §4.101 anahtarlama prosedürlerinin bir uzantısıdır. Standart, enerji verme öncesi "tüm koşulların karşılanması" gerektiğini belirtir. SAT kampanyasının onaylanması bu koşullardan biridir.
Ne İnşa Ettik¶
Değişen dosyalar:
backend/app/services/p5/switching_programme.py—start_programme()fonksiyonuna SAT kapısı eklendibackend/tests/test_sat.py— SAT kapısı entegrasyon testleri
Anahtarlama programı veri modeline iki yeni alan eklendi:
@dataclass
class SwitchingProgramme:
# ... mevcut alanlar ...
sat_campaign: SATCampaign | None = None # Bağlı SAT kampanyası
fat_campaign_id: str | None = None # Bağlı FAT kampanya ID'si
Neden Önemli¶
Neden SAT kapısını
start_programme()içine gömdük? Doğru yer burasıdır — enerji verme (switching programme start) en kritik andır. Kampanya oluşturma aşamasında değil, gerçek enerji verme anında kontrol yapmak, "son savunma hattı" ilkesini uygular. Böylece SAT kampanyası oluşturulup testler yapılırken program hâlâ düzenlenebilir.Neden
TYPE_CHECKINGbloğu ile lazy import kullandık?switching_programme.pyvesat.pyarasında dairesel bağımlılık (circular dependency) riski var.TYPE_CHECKINGbloğu sadece tip kontrolü araçları (mypy) tarafından yürütülür — çalışma zamanında import gerçekleşmez. Gerçekall_sat_passedimport'u fonksiyon içinde yapılır.
Kod İncelemesi¶
SAT kapısı entegrasyonu — var olan fonksiyona minimum müdahale ile eklenen güvenlik kontrolü:
def start_programme(programme: SwitchingProgramme) -> None:
"""Programı başlat.
SAT kampanyası bağlıysa, tüm testler geçmiş olmalıdır.
Bu, saha kabul testleri tamamlanmadan enerji verilmesini engeller.
"""
if programme.status != ProgrammeStatus.APPROVED:
raise ProgrammeStateError(...)
# SAT kapısı: kampanya bağlıysa tüm testler geçmiş olmalı
if programme.sat_campaign is not None:
from app.services.p5.sat import all_sat_passed
if not all_sat_passed(programme.sat_campaign):
raise ProgrammeStateError(
"Cannot start programme: SAT campaign has not passed "
"all tests. Complete and approve all site acceptance "
"tests before energisation."
)
programme.status = ProgrammeStatus.IN_PROGRESS
_add_audit(programme, "Programme started", programme.pic_name)
Dikkat edilmesi gereken noktalar:
- Geriye uyumluluk —
sat_campaign is Nonekontrolü, SAT kampanyası olmayan programların çalışmaya devam etmesini sağlar - Lazy import — Dairesel bağımlılığı kırmak için
all_sat_passedfonksiyon içinde import edilir - Açıklayıcı hata mesajı — Mühendise tam olarak ne yapması gerektiğini söyler
Temel Kavram¶
Temel Kavram: Dairesel Bağımlılık Çözümü (Circular Dependency Resolution)
Basitçe anlatımı: İki arkadaş düşünün — Ali, Veli'nin telefon numarasını biliyor, Veli de Ali'nin. Ama ikisi de aynı anda birbirini arayamaz. Yazılımda da iki modül birbirini aynı anda import edemez.
Analoji: İki kapının birbirini kilitlediğini düşünün — A kapısını açmak için B kapısının anahtarı lazım, B kapısını açmak için A'nın. Çözüm: anahtarı kapıyı açma anına kadar cebinizde tutarsınız (lazy import).
Bu projede: switching_programme.py normalde sat.py'dan tip bilgisi alır ama sat.py da FAT tiplerini kullanır. TYPE_CHECKING ile tip bilgisi sadece mypy zamanında çözülür, all_sat_passed ise çağrılma anında import edilir.
Bölüm 5: REST API Endpoint'leri — Her Şeyi Bir Araya Getirmek¶
Gerçek Dünya Problemi¶
Bir hastane bilgi sisteminde doktor vizitesini kaydetmek, reçete yazmak, tetkik sonucu girmek ayrı ayrı ekranlar ve API'lerdir — ama hepsi aynı hasta dosyasına bağlıdır. Bizim komisyonlama sistemimizde de FAT, SAT ve koruma doğrulaması ayrı endpoint'lerdir ama aynı trafo merkezi projesine bağlıdır.
Standartlar Ne Diyor¶
REST API tasarımımız kaynak odaklı (resource-oriented) mimariyi takip eder:
- FAT kampanyaları bağımsız kaynaktır (
/api/v1/commissioning/fat/...) - SAT kampanyaları programa bağlıdır (
/api/v1/commissioning/programmes/{id}/sat/...) - Koruma ayarları global kaynaktır (
/api/v1/commissioning/protection/...)
Ne İnşa Ettik¶
Değişen dosyalar:
backend/app/routers/p5.py— 10+ yeni endpoint (FAT CRUD, SAT CRUD, koruma doğrulama)backend/app/schemas/commissioning.py— 15+ yeni Pydantic şeması
Yeni endpoint'ler:
| Endpoint | Metod | İşlev |
|---|---|---|
/fat |
POST | FAT kampanyası oluştur |
/fat |
GET | Tüm FAT kampanyalarını listele |
/fat/{id} |
GET | FAT kampanya detayı |
/fat/{id}/tests/{test_id}/record |
POST | Test sonucu kaydet |
/fat/{id}/approve |
POST | Kampanyayı onayla |
/programmes/{id}/sat |
POST | SAT kampanyası oluştur |
/programmes/{id}/sat |
GET | SAT kampanya durumu |
/programmes/{id}/sat/tests/{test_id}/record |
POST | SAT test sonucu kaydet |
/programmes/{id}/sat/approve |
POST | SAT kampanyasını onayla |
/protection/settings |
GET | Tüm röle ayarları |
/protection/verify-selectivity |
POST | Selektivite doğrulama |
Neden Önemli¶
Neden FAT endpoint'leri program dışında, SAT endpoint'leri program altında? FAT kampanyaları ekipmana bağlıdır (örn. TX-OSS-01), programdan bağımsız olarak yönetilir — ekipman henüz sahaya gelmeden fabrikada test edilir. SAT kampanyaları ise belirli bir anahtarlama programına bağlıdır — kurulum sonrası, enerji verme öncesi yapılır. Bu URL yapısı domain modelini yansıtır.
Kod İncelemesi¶
FAT kampanya schema'sı domain nesnesinden API yanıtına dönüşümü gösteren yardımcı fonksiyon:
def _build_fat_schema(campaign: FATCampaign) -> FATCampaignSchema:
"""Domain nesnesini API yanıt modeline dönüştür.
Neden ayrı bir fonksiyon?
- Domain modeli (dataclass) ve API modeli (Pydantic) farklı sorumluluklar taşır
- Domain modeli iş kurallarını uygular
- API modeli serileştirme ve validasyon yapar
- Bu ayrım, domain mantığının HTTP kaygılarından bağımsız kalmasını sağlar
"""
specs = [
TestSpecificationSchema(
test_id=s.test_id, name=s.name, standard=s.standard,
description=s.description, unit=s.unit,
min_value=s.min_value, max_value=s.max_value,
)
for s in campaign.specs.values()
]
results = [
TestResultSchema(
test_id=r.test_id, measured_value=r.measured_value,
verdict=r.verdict.value, recorded_by=r.recorded_by,
recorded_at=r.recorded_at, notes=r.notes,
)
for r in campaign.results.values()
]
return FATCampaignSchema(
campaign_id=campaign.campaign_id,
equipment_tag=campaign.equipment_tag,
status=campaign.status.value,
specs=specs, results=results,
all_passed=all_fat_passed(campaign),
created_at=campaign.created_at,
approved_by=campaign.approved_by,
approved_at=campaign.approved_at,
)
Domain-API ayrımı, ileride ORM (SQLAlchemy) entegrasyonunda domain modelinin değişmemesini garantiler.
Temel Kavram¶
Temel Kavram: Domain-API Katman Ayrımı (Domain-API Layer Separation)
Basitçe anlatımı: Bir restoranın mutfağı (domain) ve menüsü (API) ayrı şeylerdir. Mutfaktaki tarif değişmeden menünün tasarımı değiştirilebilir. Aynı şekilde, iş mantığı HTTP endpoint'lerinden bağımsız çalışır.
Analoji: Bir çevirmen düşünün. Yazar kitabını kendi dilinde yazar (domain), çevirmen onu API diline (JSON) çevirir. Yazarın işi değişmez — sadece çevirmen güncellenir.
Bu projede: FATCampaign (dataclass) iş kurallarını uygular. FATCampaignSchema (Pydantic) JSON serileştirme yapar. _build_fat_schema() ikisi arasında köprüdür. İleride SQLAlchemy eklendiğinde domain katmanı değişmeyecek, sadece persistence katmanı eklenecektir.
Bağlantılar¶
Bu kavramlar ileride nerede karşınıza çıkacak:
- FAT/SAT tolerans bandı modeli → P5 frontend'inde test sonuçları yeşil/kırmızı renk kodlamasıyla gösterilecek (Plotly gauge chart'lar kullanılabilir)
- Koruma koordinasyonu → P5 enerji verme simülasyonunda koruma röle trip zamanlarının animasyonlu gösterimi
- SAT kapısı → Frontend'de "Enerji Ver" butonu, SAT durumuna göre aktif/pasif olacak (UX geri bildirimi)
- Ders 017'den genişletme: Anahtarlama programı ve LOTO (Ders 017) artık SAT kapısı ile güçlendirildi — program başlatma artık "tüm testler geçti" kontrolü içeriyor
Büyük Resim¶
Bu dersin odağı: FAT/SAT kabul testi kampanyaları, koruma rölesi koordinasyonu ve SAT kapısı ile enerji verme güvenliği.
graph TB
subgraph "P5 Komisyonlama Sistemi"
subgraph "Ders 017 — Mevcut"
SP["Anahtarlama Programı<br/>(30 adım DFA)"]
ESM["Ekipman Durum Makinesi<br/>(9 durum)"]
LOTO["LOTO İzolasyon<br/>(Kilit / Etiket)"]
end
subgraph "Ders 018 — Yeni ✦"
FAT["FAT Kampanyası<br/>(8 test, IEC standartları)"]
SAT["SAT Kampanyası<br/>(12 test, IEC standartları)"]
PROT["Koruma Rölesi<br/>(8 röle, 2 kademe çifti)"]
GATE["SAT Kapısı<br/>(Enerji verme kilidi)"]
end
end
FAT -->|"FAT onayı<br/>gerekli"| SAT
SAT -->|"SAT geçti?"| GATE
GATE -->|"Kilidi aç"| SP
SP --> ESM
SP --> LOTO
PROT -->|"Selektivite<br/>doğrulaması"| SP
style FAT fill:#1a5276,stroke:#2980b9,color:#ecf0f1
style SAT fill:#1a5276,stroke:#2980b9,color:#ecf0f1
style PROT fill:#1a5276,stroke:#2980b9,color:#ecf0f1
style GATE fill:#7d3c98,stroke:#a569bd,color:#ecf0f1
Tam sistem mimarisi için bkz. Dersler Genel Bakış.
Temel Çıkarımlar¶
- FAT, ekipman fabrikadan çıkmadan önce arızaları yakalar — offshore onarımın maliyeti (>500k EUR/gün) bunu zorunlu kılar.
- Tolerans bandı değerlendirmesi basit bir
min <= ölçüm <= maxkarşılaştırmasıdır, ancakfloat('-inf')vefloat('inf')ile tek taraflı testleri de kapsar. - SAT, nakliyat ve kurulum sonrası tekrar doğrulama yapar — fabrikada geçen ekipman sahada farklı davranabilir.
- FAT-kapısı, onaylanmamış fabrika testleriyle saha testlerine başlanmasını engeller — hata zincirine erken müdahale.
- Koruma koordinasyonu zaman kademelemesiyle sağlanır — downstream röle upstream'den önce atmalıdır, aksi halde tüm çiftlik devre dışı kalır.
- SAT kapısı, anahtarlama programı başlatma fonksiyonuna gömülmüştür — tüm saha testleri geçmeden enerji verme fiziksel olarak imkansızdır.
- Domain-API katman ayrımı, iş mantığını HTTP kaygılarından izole eder ve gelecekteki ORM entegrasyonunu kolaylaştırır.
Önerilen Okumalar¶
Öğrenme Yol Haritası — Faz 5: Komisyonlama & İşletme
| Kaynak | Tür | Neden Okunmalı |
|---|---|---|
| IEC 60060-1:2010 — HV test techniques | Standart | FAT-001 HV dayanım testinin temelini oluşturur |
| IEC 62271-100:2021 — Circuit breaker testing | Standart | SAT-004/005 kesici zamanlama testlerinin kaynağı |
| IEC 60076-1:2011 — Power transformer requirements | Standart | Transformatör oranı ve empedans tolerans değerlerini tanımlar |
| Omicron Academy — Protection Testing courses | Online kurs | Koruma rölesi koordinasyonu ve ikincil enjeksiyon test pratikleri |
| IEEE C37.112 — Inverse-time relay coordination | Standart | Zaman kademelemesi formüllerinin matematik temeli |
Sınav — Anlayışınızı Test Edin¶
Hatırlama Soruları¶
S1: FAT modülünde kaç test spesifikasyonu tanımlıdır ve her biri hangi fiziksel arıza modunu hedefler?
Cevap
8 test spesifikasyonu tanımlıdır: HV dayanım (yalıtım bütünlüğü), kısmi deşarj (yalıtım yaşlanması), transformatör oranı (gerilim dönüşüm doğruluğu), empedans (kısa devre akım sınırlaması), FRA (sargı/çekirdek yer değiştirmesi), DGA (yağ bozulması), röle tip testi (koruma doğruluğu) ve GIS gaz sızdırmazlığı (SF6 yalıtım bütünlüğü). Her test farklı bir arıza modunu yakaladığı için hepsi birlikte "savunma derinliği" oluşturur.S2: FAT kampanya yaşam döngüsündeki 4 durum nedir ve geçişler nasıl tetiklenir?
Cevap
CREATED → IN_PROGRESS (ilk test sonucu kaydedildiğinde otomatik), IN_PROGRESS → COMPLETED (tüm 8 spesifikasyon için sonuç kaydedildiğinde otomatik), COMPLETED → APPROVED (tüm testler geçtiyse ve yetkili kişi onaylarsa manuel). Geri dönüş yoktur — APPROVED durumundaki kampanyaya sonuç eklenemez.S3: PTOC-01 ve PTOC-02 arasındaki zaman kademelemesi ne kadardır ve bu neden yeterlidir?
Cevap
PTOC-01 (dizi besleyici) 0,5 s, PTOC-02 (incomer yedek) 0,8 s — aradaki marjin 300 ms'dir. Bu marjin, kesici açma süresini (~60 ms, IEC 62271-100), röle zamanlama hatasını (~%5 × 500 ms = 25 ms) ve güvenlik payını karşılar. 300 ms, IEC 60255 tarafından önerilen minimum PTOC kademe marjinidir.Anlama Soruları¶
S4: FAT-kapısı (gate) mekanizması neden SAT kampanyası oluşturma anında uygulanır, başlatma anında değil?
Cevap
Fail-fast (erken başarısızlık) ilkesi gereği: eğer FAT onaylanmamışsa, SAT kampanyası oluşturmaya bile gerek yoktur — bu, mühendislerin boşuna test planlaması yapmasını önler. Oluşturma anında kontrol, hatalı duruma düşme penceresini sıfıra indirir. SAT kapısı ise farklı bir kontrol noktasıdır: tüm testler tamamlanmış mı, enerji vermeye hazır mıyız? İkisi birlikte çift katmanlı güvenlik sağlar.S5: evaluate_test_verdict() fonksiyonunun float('-inf') ve float('inf') kullanması yerine ayrı "tek taraflı" ve "çift taraflı" fonksiyonlar yazmak nasıl olurdu?
Cevap
Ayrı fonksiyonlar yazmak, her yeni test türü için hangi fonksiyonun çağrılacağına karar vermek gerektirir — bu ek bir dallanma mantığı ve tip ayrımı demektir. `float('-inf')` ve `float('inf')` kullanarak tek fonksiyon her iki durumu da doğal olarak ele alır çünkü Python'da `float('-inf') <= x` her zaman `True`'dur. Bu yaklaşım, Open-Closed Principle'a uygundur: yeni test türü eklemek için mevcut kodu değiştirmek gerekmez, sadece yeni bir `TestSpecification` tanımlanır.S6: SAT kapısında TYPE_CHECKING bloğu ve lazy import kullanılmasının alternatifi ne olurdu ve neden bu yol tercih edildi?
Cevap
Alternatifler: (1) Ortak bir `interfaces.py` modülü oluşturup her iki modülün buradan import etmesi — ancak bu, küçük bir projede gereksiz karmaşıklık ekler. (2) SAT kontrolünü tamamen router katmanına taşımak — ancak bu, domain mantığını HTTP katmanına sızdırır. (3) Dependency Injection ile runtime'da SAT fonksiyonunu geçirmek — temiz ama overengineering. Lazy import, minimum müdahale ile dairesel bağımlılığı kırar ve domain mantığını yerinde tutar — "en az değişiklik" ilkesine uygundur.Meydan Okuma Sorusu¶
S7: Gerçek dünyada bir koruma rölesi ayarı değiştirilmek istendiğinde (örneğin PTOC-01'in zaman gecikmesi 0,5 s'den 0,6 s'ye artırıldığında), bu değişikliğin selektiviteyi bozup bozmadığını otomatik olarak doğrulayan bir "röle değişiklik yönetimi" (relay setting change management) sistemi nasıl tasarlardınız?
Cevap
Sistem şu bileşenlerden oluşurdu: (1) **Mevcut ayarlar snapshot'ı** — değişiklik öncesi `OSS_RELAY_SETTINGS`'in kopyası alınır. (2) **Proposed settings** — kullanıcının önerdiği değişiklik uygulanmış yeni tuple oluşturulur. (3) **Impact analysis** — `verify_selectivity(proposed_settings)` çağrılarak etkilenen tüm kademe çiftleri kontrol edilir. (4) **Diff raporu** — hangi çiftlerin selektivite verdiktinin değiştiğini gösteren bir rapor üretilir (SELEKTİF → SELEKTİF DEĞİL geçişleri kırmızı uyarı olarak işaretlenir). (5) **Onay mekanizması** — Koruma mühendisi değişikliği onaylamadan sistem uygulamaz (Permit-to-Work benzeri bir akış). (6) **Audit trail** — her ayar değişikliği tarih, mühendis, eski/yeni değer ve selektivite raporu ile kaydedilir. Bu tasarım, mevcut `verify_selectivity()` fonksiyonunun parametrik yapısını doğrudan kullanır — fonksiyon zaten özel ayar setleri kabul eder.Mülakat Köşesi¶
Basitçe Anlatın¶
"FAT/SAT testlerini ve koruma koordinasyonunu mühendis olmayan birine nasıl anlatırsınız?"
Denizde rüzgar türbinleri kurarken, kullanacağımız ekipmanları teslim almadan önce kontrol etmemiz gerekiyor — tıpkı yeni aldığınız bir arabayı showroom'dan çıkmadan önce kontrol etmek gibi. Buna "Fabrika Kabul Testi" diyoruz. Motor çalışıyor mu, frenler tutuyor mu, farlar yanıyor mu — her şeyi listeden tek tek kontrol ediyoruz.
Sonra ekipman deniz yoluyla sahaya ulaşıyor. Yolda sarsılmış, rüzgar ve dalga görmüş olabilir. Bu yüzden sahada tekrar kontrol ediyoruz — buna "Saha Kabul Testi" diyoruz. Arabanız galeriden evinize kadar sorunsuz geldi mi, yoksa yolda bir hasar mı aldı?
Koruma koordinasyonu ise evdeki sigorta kutusuna benzer. Sadece arızalı odanın sigortası atmalı, tüm evin değil. Deniz rüzgar çiftliğinde de bir kabloda arıza olursa sadece o bölümün şalteri atmalı — yoksa 510 MW üretimin tamamı durur. Bu sıralamayı "zaman kademelemesi" ile sağlıyoruz: arızaya en yakın şalter önce atar, yedek biraz sonra devreye girer.
Teknik Olarak Anlatın¶
"FAT/SAT kampanya yönetimi ve koruma selektivite doğrulamasını bir mülakat paneline nasıl anlatırsınız?"
P5 komisyonlama modülü, IEC standardlarına dayanan üç alt sistem barındırır. İlk olarak, FAT kampanya yönetimi 8 IEC-standard test spesifikasyonunu (IEC 60060-1, 60270, 60076-1/18, 60567, 60255, 62271-203) kapsar ve deterministik sonlu otomat (DFA) yaşam döngüsü ile yönetilir: CREATED → IN_PROGRESS → COMPLETED → APPROVED. Her test sonucu, tolerans bandı değerlendirmesi (min_value <= measured <= max_value) ile otomatik olarak verdiktlenir. float('-inf') / float('inf') sentinel değerleri, tek taraflı ve çift taraflı testleri tek bir saf fonksiyonla kapsar.
İkinci olarak, SAT modülü 12 kurulum sonrası test spesifikasyonunu (IEC 61869-2/3, 62271-100, 61850-8-1 vb.) kapsarken FAT modülünün tip sistemini yeniden kullanarak DRY ilkesini korur. FAT-gate mekanizması, SAT kampanyası oluşturulurken FAT durumunu precondition olarak kontrol eder (APPROVED olmalı). SAT kapısı ise start_programme() fonksiyonuna entegre edilmiştir — tüm SAT testleri geçmeden enerji verme engellenir. Dairesel bağımlılık, TYPE_CHECKING bloğu ve lazy import ile çözülmüştür.
Üçüncü olarak, koruma rölesi koordinasyonu 8 relay setting'i (PTOC, PDIS, PTOV, PTUV, PTOF, PTUF) ve 2 grading pair tanımlar. Selektivite doğrulaması, IEC 60255 ve IEEE C37.112 formüllerini doğrudan kodlayan saf fonksiyonlarla yapılır: actual_margin_ms = (upstream.delay - downstream.delay) × 1000 karşılaştırması required_margin_ms eşiğine göre SELECTIVE veya NON_SELECTIVE verdikti üretir. Tüm fonksiyonlar parametre olarak özel ayar setleri kabul eder, bu da farklı konfigürasyonları test etmeyi ve gelecekte yeni röle tipleri eklemeyi kolaylaştırır.