Bir cihaz şablonu (MergenHub paketi), bir cihazı tüm ayrıntısıyla taşıyan tek bir JSON dosyasıdır: kanal ve sürücü ayarları, cihaz, register haritası (tag'ler), hesaplanan tag'ler, alarmlar ve operatör ekranları. Kurulumda yalnız sahaya özgü bilgiler (IP adresi, port, unit ID…) sorulur; geri kalan her şey hazır gelir. Dosya uzantısı .mhpkg.json'dur.
Bu sayfa bir paketin nasıl hazırlandığını, alanlarını ve kurulumda neler olduğunu anlatır.
Paketler nerede kullanılır
- MergenHub web arayüzü — Cihaz Kütüphanesi penceresi (proje ağacının başlığındaki kitap simgesi, Bağlantılar görünümündeki Cihaz Kütüphanesi düğmesi ya da SCADA'da yeni ekran seçicisindeki kart). Kütüphaneden kurar; Dosyadan içe aktar ile elinizdeki
.mhpkg.jsondosyasını kurar. - MergenHub Mobil — Cihaz ekle sihirbazı (kütüphane, şablonlarım, dosya, pano, QR, adres), Şablonlar sayfası ve Paket / şablon içe aktar. Bkz. MergenHub Mobil.
- Cihaz Kütüphanesi — Envest'in hazırlayıp test ettiği paketler sitede yayımlanır ve uygulamalar bunları herkese açık bir API'den okur:
GET /api/v1/library(katalog),GET /api/v1/library/{slug}(tek cihaz),GET /api/v1/library/{slug}/package(paket dosyası).

İnternete çıkamayan bir sunucuda paketi siteden indirip Dosyadan içe aktar ile kurun.

Hızlı başlangıç
En kolay yol, çalışan bir cihazdan başlamaktır:
- MergenHub Mobil'i telefon modunda açın, cihazı kanal, cihaz ve birkaç tag'iyle tanımlayın, değerlerin geldiğini görün.
- Kanallar sekmesinde cihazın ⋯ menüsünden Şablon olarak kaydet / paylaş'ı seçin. Ad, açıklama, üretici ve model girin; ekranlar da gelsin istiyorsanız Ekranları da al'ı açık bırakın.
- Dosya olarak paylaş ya da Panoya kopyala ile paketi alın. Cihaz kimliğindeki ve ayarlardaki IP adresleri kendiliğinden
{{ip}}parametresine çevrilmiştir. - Dosyayı bir metin düzenleyicide ya da bir yapay zekâyla düzenleyin (tag ekleyin, açıklama yazın, alarm ve ekran ekleyin). Dışa aktarılan dosyanın
guidebölümünde biçim kuralları, kullanılan sürücünün ayar anahtarları, adres örnekleri ve sembol listesi yazılıdır. - Paketi geri alın: telefonda Cihaz ekle › Dosya, pano, QR ya da adres, sunucuda Cihaz Kütüphanesi › Dosyadan içe aktar.

Tüm projeyi paket yapmak için telefonda Daha › Proje › Projeyi dışa aktar kullanılır (kind: "project").
Dosya yapısı
Paket tek bir JSON nesnesidir:
{
"format": "mergenhub-package",
"formatVersion": 1,
"kind": "template",
"meta": { "name": "…" },
"parameters": [],
"channels": [],
"derived": [],
"alarms": [],
"screens": [],
"notes": "…"
}
| Alan | Zorunlu | Açıklama |
|---|---|---|
format | evet | Her zaman "mergenhub-package" |
formatVersion | önerilir | Şu an 1; uygulamanın bildiğinden büyükse paket reddedilir |
kind | evet | "template" (cihaz şablonu, kurulumda parametre sorulur) ya da "project" (tüm proje) |
meta | evet | Paketin adı ve tanıtım bilgileri |
parameters | hayır | Kurulumda sorulacak değerler |
channels | evet | Kanal → cihaz → tag ağacı (en az bir kanal) |
derived | hayır | Hesaplanan (gelişmiş) tag'ler |
alarms | hayır | Alarm tanımları |
screens | hayır | Operatör ekranları |
notes | hayır | Cihazın ne işe yaradığını anlatan serbest metin (Markdown) |
guide | hayır | Dışa aktarırken yazılan açıklama bölümü; içe alırken yok sayılır |
Bir cihaz şablonunda tek kanal ve tek cihaz bulunur. Yalnız bu durumda kurulumda kanal ve cihaz adı sorulur ve ad değişince yollar taşınır.
meta
| Alan | Açıklama |
|---|---|
name | Paketin görünen adı (zorunlu), ör. "Örnek EA-100 Enerji Analizörü" |
description | Bir iki cümlelik özet |
vendor, model, version | Üretici, model ve cihaz yazılım sürümü; listelerde ve aramada görünür |
author | Hazırlayan |
keywords | Arama için anahtar kelimeler (dizi) |
homepage | Ürün sayfası adresi |
createdAt, createdWith | Dışa aktarırken kendiliğinden yazılır |
Parametreler ve yer tutucular
parameters kurulumda kullanıcıya sorulacak alanlardır. Paketin herhangi bir yerindeki dizge değerde {{anahtar}} yazılan yere kullanıcının girdiği değer konur.
"parameters": [
{ "key": "ip", "label": "IP adresi", "type": "text", "required": true, "placeholder": "192.168.1.50" },
{ "key": "port", "label": "Port", "type": "number", "default": 502, "group": "Bağlantı" },
{ "key": "unit", "label": "Unit ID", "type": "number", "default": 1, "group": "Bağlantı" }
]
| Alan | Açıklama |
|---|---|
key | Harf ya da _ ile başlar; harf, rakam ve _ içerir (ör. ip, port, unit, fins_node) |
label | Formda görünen ad |
type | text (varsayılan), number ya da select |
default | Varsayılan değer |
required | true ise boş bırakılamaz |
placeholder, hint | Alan içi örnek ve alt açıklama |
group | Formda başlık; aynı gruptakiler birlikte gösterilir |
options | select için [{ "value": 1, "label": "TCP" }, …] |
Kurallar:
- Yer tutucu yalnız dizge değerlerin içinde çalışır. Sayısal bir ayarı parametreye bağlamak için dizge yazın:
"modbus_ethernet.DEVICE_ETHERNET_PORT_NUMBER": "{{port}}". Kurulumda sürücünün sayısal ayarları sayıya çevrilir. - Cihaz kimliği tipik olarak parametrelerden kurulur:
"id": "<{{ip}}>.{{unit}}". - Kurulumdan sonra doldurulmamış bir
{{…}}kalırsa kurulum açılmaz. - IP adresinin varsayılanını boş bırakıp
required: trueyapın; örnek adresiplaceholder'a yazın. Böylece kullanıcı adresi girmeden kuramaz.
Kanallar, cihazlar ve tag'ler
"channels": [
{
"name": "Enerji",
"driver": "Modbus TCP/IP Ethernet",
"settings": {},
"devices": [
{
"name": "Analizor1",
"id": "<{{ip}}>.{{unit}}",
"scanMs": 1000,
"timeouts": { "connectS": 3, "requestMs": 1000, "retries": 3 },
"settings": { "modbus_ethernet.DEVICE_ETHERNET_PORT_NUMBER": "{{port}}" },
"tags": [
{ "name": "GerilimL1", "address": "30001", "type": "Float", "access": "read", "scanMs": 1000, "units": "V" }
],
"groups": []
}
]
}
]
Kanal
| Alan | Açıklama |
|---|---|
name | Kanal adı (zorunlu, nokta içeremez) |
driver | Sürücünün tam adı (aşağıdaki tablo) |
settings | Kanal düzeyindeki sürücü ayarları (Kepware uyumlu anahtarlar) |
description | Açıklama |
devices | Cihaz dizisi (zorunlu) |
Cihaz
| Alan | Varsayılan | Açıklama |
|---|---|---|
name | — | Cihaz adı (zorunlu, nokta içeremez) |
id | sürücüye göre | Cihaz kimliği; biçimi sürücüye bağlıdır |
description | — | Açıklama |
enabled | true | false ise cihaz taranmaz |
scanMs | 1000 | Cihaz tarama hızı (ms) |
scanMode | 4 | 0 istemciye uy, 1 en hızlı, 2 sabit hız, 3 talep, 4 tag hızına uy |
timeouts | 3 / 1000 / 3 | connectS bağlantı zaman aşımı (sn), requestMs istek zaman aşımı (ms), retries deneme sayısı |
settings | sürücü varsayılanları | Cihaz düzeyindeki sürücü ayarları |
tags, groups | — | Tag'ler ve tag grupları |
Tag
| Alan | Varsayılan | Açıklama |
|---|---|---|
name | — | Tag adı (zorunlu, nokta içeremez, cihaz ya da grup içinde tekil) |
address | — | Sürücünün adres sözdizimiyle adres (zorunlu) |
type | Default | Veri tipi (aşağıda) |
access | read | read ya da readwrite |
scanMs | 1000 | Tag tarama hızı (ms) |
description | — | Açıklama; 6 karakter ve altıysa uygulamada birim olarak gösterilir |
units | — | Birim; description boşsa açıklama olarak kullanılır |
scaling | — | Ölçekleme (aşağıda) |
Veri tipleri: Default, Boolean, Char, Byte, Short, Word, Long, DWord, Float, Double, String, BCD, LBCD, Date, LLong, QWord. Default sürücünün adrese göre seçtiği tiptir.
Ölçekleme ham değeri mühendislik birimine çevirir; yazarken ters uygulanır:
"scaling": { "type": "linear", "rawLow": 0, "rawHigh": 10, "low": 0, "high": 1, "resultType": "Double", "units": "kWh" }
type linear ya da sqrt (karekök); rawLow/rawHigh ham aralık, low/high ölçekli aralık; resultType ölçekli veri tipi (varsayılan Double); clampLow, clampHigh sınırda kırpar, negate işaret çevirir.
Gruplar tag'leri cihaz içinde klasörler; iç içe olabilir. Gruptaki tag'in yolu Kanal.Cihaz.Grup.Tag olur.
"groups": [ { "name": "Enerji", "description": "Sayaçlar", "tags": [ … ], "groups": [ … ] } ]
Sürücüler ve adres sözdizimi
driver alanına sürücünün tam adı yazılır. Adres sözdizimi ve ayar anahtarları MergenHub sunucusu ile MergenHub Mobil'de aynıdır; ayrıntılar için Protokol sürücüleri.
Sürücü (driver) | Cihaz kimliği (id) | Adres örnekleri |
|---|---|---|
Simulator | cihaz numarası, ör. 1 | SINE:10:0:100, RAMP:30:0:500, RANDOM:20:80, REG:1 |
Modbus TCP/IP Ethernet | <IP>.Unit, ör. <192.168.1.10>.1 | 40001 holding, 30001 giriş register, 00001 bobin, 10001 ayrık giriş, 40001.3 bit, 40010.16H dize |
Modbus RTU Serial, Modbus ASCII Serial | köle adresi 1–247 | Modbus TCP ile aynı |
Siemens S7 TCP/IP | <IP>.Rack.Slot, ör. <192.168.0.1>.0.1 | DB1.DBD4, DB1.DBW2, DB1.DBB0, DB1.DBX0.3, MW10, I0.0, Q0.0 |
OMRON FINS Ethernet | <IP>.Düğüm, ör. <192.168.1.10>.1 | D100, D0.05, CIO10, W5.00, H2, A3, E100 |
OMRON NJ Ethernet | <IP> | PompaDurum, Hat1.Vana[3], Matris[1,2], Sayac.5 |
MQTT Client | broker host:port (kanalda broker verilmişse yok sayılır) | sensors/temp, sensors/pump1:/flow, plant/csv;idx=2;sep=; |
DNP Client Ethernet | outstation IP | AI0, BI5, CTR2, AO1, BO3, 30.1.51.Value |
IEC 60870-5-104 Client | RTU IP | 100, IOA100, M_ME_NC.100.VALUE, C_SC_NA.3000.DIRECTVALUE |
IEC 61850 MMS Client | IED IP | LD0/MMXU1.MX.TotW.mag.f, LD0/XCBR1.ST.Pos.stVal |
OPC UA Client | kullanılmaz (endpoint kanal ayarında) | ns=2;s=Kanal.Cihaz.Tag, ns=2;i=1001 |
Sık kullanılan ayar anahtarları:
- Modbus TCP (cihaz):
modbus_ethernet.DEVICE_ETHERNET_PORT_NUMBER(502),modbus_ethernet.DEVICE_ZERO_BASED_ADDRESSING,modbus_ethernet.DEVICE_FIRST_WORD_LOW(32 bitte word sırası),modbus_ethernet.DEVICE_HOLDING_REGISTERS(blok boyutu, 1–125). - Modbus RTU/ASCII (cihaz):
servermain.DEVICE_ETHERNET_COMMUNICATIONS_IPveservermain.DEVICE_ETHERNET_COMMUNICATIONS_PORT(seri sunucu),modbus.DEVICE_…anahtarları. - Siemens S7 (cihaz):
siemens_tcpip_ethernet.DEVICE_COMMUNICATIONS_PORT_NUMBER(102),siemens_tcpip_ethernet.DEVICE_S7_COMMUNICATIONS_CPU_RACK,…_CPU_SLOT, model içinservermain.DEVICE_MODEL(0 S7-200, 1 S7-300, 2 S7-400, 3 S7-1200, 4 S7-1500). - OMRON FINS: kanalda
omron_fins_ethernet.CHANNEL_PORT_NUMBER(9600); cihazdaomron_fins_ethernet.DEVICE_PROTOCOL(0 UDP, 1 TCP) ve düğüm numaraları. - MQTT (kanal):
mqtt.BROKER_HOST,mqtt.PORT,mqtt.USERNAME,mqtt.PASSWORD,mqtt.QOS,mqtt.TRANSPORT. - OPC UA istemci (kanal):
opcuaclient.CHANNEL_UA_SERVER_ENDPOINT_URL.
Yazılmayan ayar sürücünün varsayılanını alır. Bir sürücünün tüm ayar anahtarları, o sürücüyle dışa aktarılmış bir paketin guide.drivers bölümünde açıklamalarıyla yazılıdır.
Hesaplanan tag'ler
derived dizisi başka tag'lerden hesaplanan tag'leri tanımlar. Kurulunca yolları _AdvancedTags.<ad> olur; ekranlar ve alarmlar bu yolu kullanır.
"derived": [
{
"name": "Analizor1_GorunurGuc",
"type": "Derived",
"expression": "ROUND({Enerji.Analizor1.GerilimL1} * {Enerji.Analizor1.AkimL1} / 1000, 2)",
"scanRateMs": 1000,
"description": "Görünür güç (kVA)"
}
]
| Alan | Açıklama |
|---|---|
name | Ad; sunucu genelinde tekildir, cihaz adıyla başlamalıdır (<Cihaz>_…) |
type | Derived (ifade), Totalizer, Average, Maximum, Minimum |
expression | Derived'da ifade; diğerlerinde kaynak tag'in yolu (süslü parantezsiz) |
sampleSize | Ortalama / maks / min için örnek sayısı (varsayılan 10) |
scanRateMs | Güncelleme hızı (ms, varsayılan 1000) |
enabled | Varsayılan true |
description | Açıklama |
dataType | Sunucuda sonuç veri tipi kodu (varsayılan 9 = Double); telefon yok sayar |
Totalizer, değer × saniye toplar; m³/h girişte sonucu 3600'e bölün.
Fonksiyon başvurusu
İfadede tag referansı {Kanal.Cihaz.Tag} biçimindedir (grup varsa {Kanal.Cihaz.Grup.Tag}). İşleçler: + - * / %, karşılaştırma <, <=, >, >=, ==, != (doğruysa 1, yanlışsa 0), mantık &&, ||, ! ve parantez. Ondalık ayıracı her zaman noktadır (1.5). Fonksiyon adları büyük/küçük harf duyarsızdır; argümansız fonksiyonlar da parantez ister (PI()). İfade en çok 8000 karakter olabilir. Fonksiyon listesi sunucu ve telefonda aynıdır.
| Fonksiyon | Açıklama |
|---|---|
ABS(x) | Mutlak değer |
SQRT(x) | Karekök (negatif girişte 0) |
POW(x, y) | x üssü y |
EXP(x), LN(x) | e üssü x, doğal logaritma |
LOG(x), LOG(x, taban) | 10 tabanlı ya da verilen tabanda logaritma |
ROUND(x), ROUND(x, basamak) | Yuvarlama (yarı yukarı; basamak 0–15) |
FLOOR(x), CEIL(x) | Aşağı / yukarı yuvarlama |
MOD(a, b) | Bölümden kalan (b = 0 ise 0) |
SIGN(x) | İşaret: −1, 0, 1 |
MIN(a, b, …), MAX(a, b, …) | En küçük / en büyük |
AVG(a, b, …), SUM(a, b, …) | Ortalama / toplam |
IF(koşul, a, b) | Koşul 0 değilse a, değilse b |
CLAMP(x, alt, üst) | Aralığa sıkıştırma |
MAP(x, girişAlt, girişÜst, çıkışAlt, çıkışÜst) | Doğrusal ölçekleme |
LERP(a, b, t) | a ile b arasında doğrusal ara değer |
POLY(x, c0, c1, c2, …) | Polinom: c0 + c1·x + c2·x² + … |
HYPOT(a, b) | √(a² + b²) |
SIN, COS, TAN, ASIN, ACOS, ATAN | Trigonometri (radyan) |
ATAN2(y, x) | İki argümanlı arktanjant |
SINH, COSH, TANH | Hiperbolik fonksiyonlar |
DEG(x), RAD(x) | Radyandan dereceye, dereceden radyana |
PI(), E() | Sabitler |
RANDOM(), RANDOM(üst), RANDOM(alt, üst), RND(…) | Rastgele sayı; yalnız test için |
Örnekler: ({K.C.A} + {K.C.B}) / 2, IF({K.C.Basinc} > 6, 1, 0), MAX({K.C.Seviye} - {K.C.Statik}, 0), MAP({K.C.Ham}, 4, 20, 0, 10).
Alarmlar
"alarms": [
{ "name": "Yüksek gerilim L1", "tag": "Enerji.Analizor1.GerilimL1", "conditionType": "Hi", "limit": 250,
"deadband": 2, "severity": 700, "message": "Faz 1 gerilimi 250 V üstünde", "enabled": true }
]
| Alan | Varsayılan | Açıklama |
|---|---|---|
name | — | Alarm adı |
tag | — | Paketteki bir tag'in tam yolu ya da _AdvancedTags.<ad> (zorunlu, pakette bulunmalı) |
conditionType | — | HiHi, Hi, Lo, LoLo, DevHi, DevLo (sapma), RocHi, RocLo (değişim hızı, birim/sn) |
limit | — | Sınır |
setpoint | 0 | Sapma alarmlarında ayar noktası |
deadbandType, deadband | Absolute, 0 | Ölü bant: None, Absolute, Percent |
rangeLow, rangeHigh | 0, 100 | Yüzde ölü bant için aralık |
onDelaySec, offDelaySec | 0 | Açılma ve kapanma gecikmesi (sn) |
severity | 500 | 1–1000; 800 ve üstü kritik |
message, area | — | İleti ve alan |
enabled | true | Etkin |
Ekranlar
Ekranlar sunucudaki SCADA ekranlarıyla aynı yapıdadır. Bir ekran bir koordinat alanında (width × height) konumlanmış nesnelerden (widgets) oluşur.
| Alan | Açıklama |
|---|---|
id | Paket içinde tekil kimlik (zorunlu); kurulumda yenilenir, bağlar taşınır |
name | Ekran adı; cihaz adını içerirse kurulumda yeni ada çevrilir |
target | "server" (yalnız sunucuya kurulur), "phone" (yalnız telefon moduna kurulur) ya da yok (ikisine de) |
parentId | Üst ekranın id'si; boşsa ana ekrandır |
order | Alt ekranlar arasındaki sıra |
width, height | Koordinat alanı; telefon dikey 400 × 700 (uzun ekranda yükseklik artar), sunucu ör. 1200 × 700 |
background | Zemin rengi (#eef2f7); telefon ekranında boş bırakılırsa temaya uyar |
group, zoneId | Sunucuda ekran grubu ve bölge; şablonlarda boş bırakın |
widgets | Nesneler |
İki ekran takımı
Bir cihaz için iyi bir paket iki takım taşır:
- Sunucu takımı (
"target": "server") — tek bir ana ekran (parentIdboş) ve onun altında ayar ekranları (parentId= ana ekranınid'si). Web arayüzünde ana ekran listede görünür, ayar ekranları onun alt dalındadır. Ana ekrandan ayar ekranlarına ve geri düğmeler (nav) koyun. - Telefon takımı (
"target": "phone") — dikey bir Özet ekranı (ölçümler, kumanda ve ayar ekranlarına düğmeler) ve onun alt ekranları olarak tek sütunlu ayar ekranları. Telefon modunda Özet açılınca üstte Özet ve alt ekranlardan oluşan bir sekme şeridi çıkar. Ekran adlarını<Cihaz> — Özet,<Cihaz> — Ayarlarbiçiminde verin; sekmelerde "—" işaretinden sonraki kısım görünür.
Kurulumda yalnız hedefe uyan takım kurulur. Diğer takımdaki bir üst ekrana bağlı ekran ana ekran olur; diğer takıma giden nav bağları kaldırılır. target vermezseniz ekran iki yere de kurulur.
Nesneler
{ "id": "w2", "type": "display", "x": 24, "y": 80, "w": 220, "h": 80,
"tag": "Enerji.Analizor1.GerilimL1", "props": { "label": "Gerilim L1", "units": "V", "decimals": 1 } }
| Alan | Açıklama |
|---|---|
id | Paket içinde tekil (ör. w1, w2 …) |
type | Nesne tipi (aşağıda) |
x, y, w, h | Konum ve boyut (ekran koordinatlarında) |
rot | Döndürme açısı (derece) |
tag | Bağlı tag yolu: Kanal.Cihaz.Tag ya da _AdvancedTags.<ad> |
props | Tipe göre özellikler |
anims | Koşullu kurallar |
onClick, nav | Dokununca başka ekrana geçmek için "onClick": "nav" ve "nav": "<ekran id>" |
popupScreen | Açılır pencere olarak gösterilecek ekran (sunucu) |
| Tip | Ne yapar | Önemli props |
|---|---|---|
display | Değer göstergesi | label, units, decimals, color, fontSize |
label | Sabit yazı (tag yok) | text, fontSize, color, align |
lamp | Lamba | label, onColor, offColor, onText, offText, blinkOn, onOp/onA/onB |
button | Basınca onValue/offValue yazar | label, onValue, offValue, onText, offText, onColor, offColor |
switch | Anahtar (buton gibi yazar) | label, onValue, offValue, onText, offText, onColor |
radio | Seçim düğmesi | label, onValue, offValue |
input | Değer girişi (yazılabilir tag) | label, decimals |
sfield | Ayar satırı: etiket + değer (+ birim) | label, units, decimals, editable, step |
gauge | Kadran | label, min, max, units, decimals, fillColor |
tank, levelbar | Depo seviyesi, seviye çubuğu | label, min, max, units, decimals, fillColor |
pump, motor, fan, valve | Makine simgeleri (çalışırken döner / renk değiştirir) | label, onColor, offColor, onText, offText, spin, blinkOn, onOp/onA/onB |
pipe | Boru; akış varken renklenir | thickness, flowColor, onOp/onA |
rect | Panel / dikdörtgen (tag yok) | fill, stroke, radius |
image | Resim (tag yok) | src (data URI ya da adres) |
svg | Sembol kütüphanesinden nesne | lib2 (sembol kimliği), label, onOp/onA/onB, onColor, offColor |
Açık durumu. Lamba, makine ve sembollerde nesnenin ne zaman "açık" sayılacağı onOp (gt, ge, eq, ne, lt, le, between), onA ve onB ile verilir; verilmezse değer 0,5'ten büyükse açıktır.
Koşullu kurallar (anims): { "kind": "color", "tag": "", "op": "gt", "a": 80, "b": null, "p2": "#ef4444" }. kind: color (rengi p2 yapar), blink (yanıp söner), visible (koşul doğruyken nesneyi gizler), level (dolum: a en az, b en çok, p2 renk, op always). tag boşsa nesnenin kendi tag'i kullanılır.
Semboller. svg nesnesinin lib2 alanı yerleşik sembol kütüphanesindeki kimliktir (ör. en-pumps/en_pump_submersible_1, en-meters/en_flowmeter_1, pumps_centrifugal_pump_4). Kimliklerin tam listesi dışa aktarılan paketlerin guide.symbols bölümündedir.
Sunucu ekranlarında web SCADA editörünün diğer nesne tipleri de kullanılabilir; telefon bunları soluk kutu olarak gösterir ve denetim uyarı verir. İki yerde çalışması gereken ekranlarda tablodaki tipleri kullanın.
Adlandırma ve kurulumda yeniden adlandırma
- Kanal, cihaz, grup ve tag adlarında nokta (
.) kullanılmaz; nokta yol ayıracıdır. Adlar bulunduğu düzeyde tekil olmalıdır (büyük/küçük harf duyarsız). - Tag yolu
Kanal.Cihaz.Tag(gruptaKanal.Cihaz.Grup.Tag) biçimindedir. Ekranlarda, alarmlarda ve ifadelerde her zaman tam yol yazılır. - Cihaz adı yalnız kanal içinde tekildir; aynı paket aynı kanala farklı cihaz adlarıyla birçok kez kurulabilir.
- Hesaplanan tag adları sunucu genelinde tekildir. Bu yüzden her hesaplanan tag'in adını cihaz adıyla başlatın:
Analizor1_GorunurGuc. Kurulumda cihaz adı değişince bu ön ek de değişir (Analizor2_GorunurGuc) ve aynı paket ikinci kez çakışmadan kurulur.
Kurulumda kullanıcı kanal ve cihaz adını değiştirirse paket şöyle güncellenir:
- Tüm
Kanal.Cihazile başlayan yollar (ekran nesnelerinintag'i, kurallar, alarmtag'leri, ifadelerdeki{…}referansları) yeni ada taşınır. - Adı
<EskiCihaz>_ile başlayan hesaplanan tag'ler<YeniCihaz>_ile yeniden adlandırılır;_AdvancedTags.…referansları da taşınır. - Ekran adlarında ve
labelnesnelerinintext'inde geçen eski cihaz adı (tam kelime olarak, en az 3 karakterse) yeni adla değiştirilir.
Kurulumda denetlenen çakışmalar:
- Kanal adı hedefte başka bir sürücüyle kullanılıyorsa kurulum açılmaz; aynı sürücüyle kullanılıyorsa cihaz mevcut kanala eklenir.
- Kanalda aynı adla cihaz varsa kurulum açılmaz; uygulama boştaki ilk numaralı adı önerir (Analizor1 → Analizor2).
- Hesaplanan tag adı hedefte varsa kurulum açılmaz; farklı bir cihaz adı çözer.
Doğrulama ve sık hatalar
MergenHub Mobil paketi kurmadan önce denetler; sorunlar kurulum kartında listelenir. Web arayüzünün Dosyadan içe aktar'ı parametre, ad ve çakışma denetimlerini yapar ama adresleri sürücüyle doğrulamaz; yeni bir paketi önce telefonda denemek iyi bir alışkanlıktır.
Hatalar (kurulum açılmaz):
Bu bir MergenHub paketi değil—formatalanı eksik ya da yanlış.JSON hatası (satır …, sütun …)— sözdizimi hatası; konum ve çevresindeki metin gösterilir.Bilinmeyen sürücü "…"—driveralanında sürücünün tam adını yazın (ör.Modbus TCP/IP Ethernet).Adres geçersiz (…)— adres sürücünün sözdizimine uymuyor; ileti nedenini söyler (ör. Modbus'ta alan rakamı 0, 1, 3 ya da 4 olmalı).Bilinmeyen veri tipi "…"— tip adları yukarıdaki listedeki gibi yazılır (Float,float32değil).access "read" ya da "readwrite" olmalı.… adı tekrar ediyor,… adında nokta olamaz,… adı boş.Alarm …: Tag bulunamadı— alarmın tag'i pakette yok.Geçersiz parametre anahtarı— anahtar harf, rakam ve_dışında karakter içeriyor.{{…}} için değer girilmedi— bir yer tutucunun parametresi yok ya da boş.
Uyarılar (kurulum yapılır, ama bakın):
Paket içinde olmayan tag'e bağlı— ekran nesnesi, kural ya da ifade pakette olmayan bir yolu kullanıyor; çoğunlukla yazım hatasıdır.Gidilecek ekran pakette yok—navbir ekranid'sine karşılık gelmiyor.Bu uygulamanın tanımadığı nesne tipi— telefon bu nesneyi çizemez; sunucuda çalışabilir.Sembol kütüphanede yok—lib2kimliği yanlış.
İfadeler kurulumda sunucu tarafından derlenir; hatalı bir ifade (bilinmeyen fonksiyon, yanlış argüman sayısı, 1,5 gibi virgüllü sayı) kurulum sonucunda "kurulamayan" olarak listelenir, diğer parçalar kurulur.
Uygulama // ve /* */ yorumlarını ve sondaki fazla virgülleri tolere eder, ama web arayüzü yorumları kabul etmez. Paketleri yorumsuz, geçerli JSON olarak yazın.
Tam örnek
Tek bir Modbus TCP enerji analizörü: altı tag (biri ölçeklenmiş, ikisi yazılabilir), bir hesaplanan tag, bir alarm, sunucu takımında ana ekran ve ayar ekranı, telefon takımında Özet ve ayar ekranı. Bu paket MergenHub Mobil'in denetiminden hatasız ve uyarısız geçer.
{
"format": "mergenhub-package",
"formatVersion": 1,
"kind": "template",
"meta": {
"name": "Örnek EA-100 Enerji Analizörü",
"description": "Tek fazlı enerji ölçümü, röle çıkışı ve akım trafosu ayarı.",
"vendor": "Örnek",
"model": "EA-100",
"version": "1.0",
"author": "Envest",
"keywords": ["enerji", "analizör", "Modbus TCP"]
},
"parameters": [
{ "key": "ip", "label": "IP adresi", "type": "text", "required": true, "placeholder": "192.168.1.50", "hint": "Analizörün ağdaki adresi" },
{ "key": "port", "label": "Port", "type": "number", "default": 502, "group": "Bağlantı" },
{ "key": "unit", "label": "Unit ID", "type": "number", "default": 1, "group": "Bağlantı" }
],
"channels": [
{
"name": "Enerji",
"driver": "Modbus TCP/IP Ethernet",
"devices": [
{
"name": "Analizor1",
"id": "<{{ip}}>.{{unit}}",
"scanMs": 1000,
"timeouts": { "connectS": 3, "requestMs": 1000, "retries": 3 },
"settings": { "modbus_ethernet.DEVICE_ETHERNET_PORT_NUMBER": "{{port}}" },
"tags": [
{ "name": "GerilimL1", "address": "30001", "type": "Float", "access": "read", "scanMs": 1000, "units": "V" },
{ "name": "AkimL1", "address": "30003", "type": "Float", "access": "read", "scanMs": 1000, "units": "A" },
{ "name": "AktifGuc", "address": "30005", "type": "Float", "access": "read", "scanMs": 1000, "units": "kW" },
{ "name": "ToplamEnerji", "address": "30007", "type": "DWord", "access": "read", "scanMs": 5000,
"scaling": { "type": "linear", "rawLow": 0, "rawHigh": 10, "low": 0, "high": 1, "resultType": "Double", "units": "kWh" } },
{ "name": "RoleCikis", "address": "00001", "type": "Boolean", "access": "readwrite", "scanMs": 1000, "description": "Röle çıkışı (1 = çekili)" },
{ "name": "AkimTrafoOrani", "address": "40001", "type": "Word", "access": "readwrite", "scanMs": 5000, "description": "Akım trafosu oranı (ör. 100 = 100/5 A)" }
]
}
]
}
],
"derived": [
{
"name": "Analizor1_GorunurGuc",
"type": "Derived",
"expression": "ROUND({Enerji.Analizor1.GerilimL1} * {Enerji.Analizor1.AkimL1} / 1000, 2)",
"scanRateMs": 1000,
"description": "Görünür güç (kVA) = gerilim × akım / 1000"
}
],
"alarms": [
{
"name": "Yüksek gerilim L1",
"tag": "Enerji.Analizor1.GerilimL1",
"conditionType": "Hi",
"limit": 250,
"deadband": 2,
"severity": 700,
"message": "Faz 1 gerilimi 250 V üstünde",
"enabled": true
}
],
"screens": [
{
"id": "ea100-ana", "name": "Analizor1 — Enerji Analizörü", "target": "server", "parentId": "", "order": 0,
"width": 1200, "height": 700, "background": "#eef2f7",
"widgets": [
{ "id": "w1", "type": "label", "x": 24, "y": 16, "w": 700, "h": 40, "props": { "text": "ENERJİ ANALİZÖRÜ — Analizor1", "fontSize": 24, "color": "#0f172a" } },
{ "id": "w2", "type": "display", "x": 24, "y": 80, "w": 220, "h": 80, "tag": "Enerji.Analizor1.GerilimL1", "props": { "label": "Gerilim L1", "units": "V", "decimals": 1 } },
{ "id": "w3", "type": "display", "x": 264, "y": 80, "w": 220, "h": 80, "tag": "Enerji.Analizor1.AkimL1", "props": { "label": "Akım L1", "units": "A", "decimals": 2 } },
{ "id": "w4", "type": "display", "x": 504, "y": 80, "w": 220, "h": 80, "tag": "Enerji.Analizor1.AktifGuc", "props": { "label": "Aktif güç", "units": "kW", "decimals": 2 } },
{ "id": "w5", "type": "display", "x": 744, "y": 80, "w": 220, "h": 80, "tag": "Enerji.Analizor1.ToplamEnerji", "props": { "label": "Toplam enerji", "units": "kWh", "decimals": 1 } },
{ "id": "w6", "type": "gauge", "x": 24, "y": 180, "w": 240, "h": 220, "tag": "_AdvancedTags.Analizor1_GorunurGuc", "props": { "label": "Görünür güç", "min": 0, "max": 50, "units": "kVA", "decimals": 2 } },
{ "id": "w7", "type": "switch", "x": 284, "y": 180, "w": 200, "h": 70, "tag": "Enerji.Analizor1.RoleCikis", "props": { "label": "Röle", "onValue": 1, "offValue": 0, "onText": "AÇIK", "offText": "KAPALI", "onColor": "#22c55e" } },
{ "id": "w8", "type": "rect", "x": 24, "y": 620, "w": 200, "h": 56, "props": { "fill": "#1d4ed8", "stroke": "#1d4ed8", "radius": 10 }, "onClick": "nav", "nav": "ea100-ayar" },
{ "id": "w9", "type": "label", "x": 24, "y": 620, "w": 200, "h": 56, "props": { "text": "Ayarlar", "fontSize": 16, "color": "#ffffff" }, "onClick": "nav", "nav": "ea100-ayar" }
]
},
{
"id": "ea100-ayar", "name": "Analizor1 — Ayarlar", "target": "server", "parentId": "ea100-ana", "order": 1,
"width": 1200, "height": 700, "background": "#eef2f7",
"widgets": [
{ "id": "w10", "type": "label", "x": 24, "y": 16, "w": 700, "h": 40, "props": { "text": "AYARLAR — Analizor1", "fontSize": 24, "color": "#0f172a" } },
{ "id": "w11", "type": "sfield", "x": 24, "y": 80, "w": 520, "h": 44, "tag": "Enerji.Analizor1.AkimTrafoOrani", "props": { "label": "Akım trafosu oranı", "decimals": 0, "editable": true, "step": 5 } },
{ "id": "w12", "type": "rect", "x": 24, "y": 620, "w": 200, "h": 56, "props": { "fill": "#1d4ed8", "stroke": "#1d4ed8", "radius": 10 }, "onClick": "nav", "nav": "ea100-ana" },
{ "id": "w13", "type": "label", "x": 24, "y": 620, "w": 200, "h": 56, "props": { "text": "‹ Ana ekran", "fontSize": 16, "color": "#ffffff" }, "onClick": "nav", "nav": "ea100-ana" }
]
},
{
"id": "ea100-tel", "name": "Analizor1 — Özet", "target": "phone", "parentId": "", "order": 0,
"width": 400, "height": 700, "background": "",
"widgets": [
{ "id": "w14", "type": "rect", "x": 0, "y": 0, "w": 400, "h": 64, "props": { "fill": "#1d4ed8", "stroke": "#1d4ed8", "radius": 0 } },
{ "id": "w15", "type": "label", "x": 14, "y": 8, "w": 372, "h": 48, "props": { "text": "Enerji Analizörü", "fontSize": 18, "color": "#ffffff", "align": "left" } },
{ "id": "w16", "type": "display", "x": 8, "y": 76, "w": 188, "h": 62, "tag": "Enerji.Analizor1.GerilimL1", "props": { "label": "Gerilim L1", "units": "V", "decimals": 1 } },
{ "id": "w17", "type": "display", "x": 204, "y": 76, "w": 188, "h": 62, "tag": "Enerji.Analizor1.AkimL1", "props": { "label": "Akım L1", "units": "A", "decimals": 2 } },
{ "id": "w18", "type": "display", "x": 8, "y": 146, "w": 188, "h": 62, "tag": "Enerji.Analizor1.AktifGuc", "props": { "label": "Aktif güç", "units": "kW", "decimals": 2 } },
{ "id": "w19", "type": "display", "x": 204, "y": 146, "w": 188, "h": 62, "tag": "Enerji.Analizor1.ToplamEnerji", "props": { "label": "Toplam enerji", "units": "kWh", "decimals": 1 } },
{ "id": "w20", "type": "gauge", "x": 106, "y": 220, "w": 188, "h": 178, "tag": "_AdvancedTags.Analizor1_GorunurGuc", "props": { "label": "Görünür güç", "min": 0, "max": 50, "units": "kVA", "decimals": 2 } },
{ "id": "w21", "type": "switch", "x": 8, "y": 410, "w": 384, "h": 58, "tag": "Enerji.Analizor1.RoleCikis", "props": { "label": "Röle", "onValue": 1, "offValue": 0, "onText": "AÇIK", "offText": "KAPALI", "onColor": "#22c55e" } },
{ "id": "w22", "type": "rect", "x": 8, "y": 480, "w": 188, "h": 48, "props": { "fill": "#1d4ed8", "stroke": "#1d4ed8", "radius": 10 }, "onClick": "nav", "nav": "ea100-tel-ayar" },
{ "id": "w23", "type": "label", "x": 8, "y": 480, "w": 188, "h": 48, "props": { "text": "Ayarlar", "fontSize": 14, "color": "#ffffff" }, "onClick": "nav", "nav": "ea100-tel-ayar" }
]
},
{
"id": "ea100-tel-ayar", "name": "Analizor1 — Ayarlar", "target": "phone", "parentId": "ea100-tel", "order": 1,
"width": 400, "height": 700, "background": "",
"widgets": [
{ "id": "w24", "type": "label", "x": 12, "y": 12, "w": 376, "h": 30, "props": { "text": "AKIM TRAFOSU", "fontSize": 13, "color": "#3b82f6", "align": "left" } },
{ "id": "w25", "type": "sfield", "x": 8, "y": 48, "w": 384, "h": 44, "tag": "Enerji.Analizor1.AkimTrafoOrani", "props": { "label": "Akım trafosu oranı", "decimals": 0, "editable": true, "step": 5 } }
]
}
],
"notes": "# Örnek EA-100\n\nGerilim, akım, aktif güç ve toplam enerji okunur; röle çıkışı ve akım trafosu oranı yazılabilir. Toplam enerji sayacı 0,1 kWh çözünürlüklüdür (ham değer / 10)."
}
Bu paketi kurarken cihaz adını Analizor2 yaparsanız tag yolları Enerji.Analizor2.…, hesaplanan tag Analizor2_GorunurGuc, ekran adları Analizor2 — … olur.
Yapay zekâ ile çalışma
Paket biçimi yapay zekâ asistanlarının okuyup yazabileceği şekilde tasarlanmıştır. Bir cihazın register haritasını, kılavuzunu ya da veri sayfasını bir asistana verip paketi hazırlatabilirsiniz.
MergenHub cihaz şablonu becerisini indirin (zip). İçinde:
SKILL.md— asistanın izleyeceği iş akışı ve kesin kurallar.reference/format.md— tüm alanların kısa başvurusu.reference/drivers.md— sürücü adları, cihaz kimliği biçimleri ve adres sözdizimi.reference/expressions.md— ifade fonksiyonları.examples/minimal-modbus.mhpkg.json— denetimden geçen tam örnek.
Claude uygulamasında zip dosyasını beceri (skill) olarak yükleyin ya da Claude Code'da ~/.claude/skills/ klasörüne açın; beceri desteklemeyen bir asistanda dosyaları sohbete ekleyin. Sonra örneğin şunu isteyin: "Ekteki register tablosundan bu enerji analizörü için MergenHub şablonu hazırla; IP, port ve unit ID kurulumda sorulsun; gerilim için 250 V'ta alarm ekle." Asistanla Türkçe konuşabilirsiniz.
Asistanın verdiği dosyayı önce MergenHub Mobil'de Cihaz ekle › Dosya, pano, QR ya da adres › Panodan yapıştır ile açıp denetim sonucuna bakın; sonra sunucuya kurun.
Resmi kütüphaneye cihaz ekletme
Bir cihazın Cihaz Kütüphanesi'nde yer almasını istiyorsanız sitedeki müşteri panelinden istek gönderin: Panel › Cihaz ekleme istekleri › Yeni istek. MergenHub Mobil'deki kütüphane listesinin altındaki Ekleme isteği gönderin bağlantısı ve web arayüzündeki kütüphane penceresi de aynı sayfayı açar.
Formda marka, model, yazılım sürümü, kategori, haberleşme protokolü, ürün sayfası, cihazın ne yaptığı ve hangi verilerin izleneceği, bağlantı bilgisi istenir. En çok beş dosya eklenebilir (her biri 10 MB): fotoğraf, register haritası, kılavuz; hazırladığınız bir .mhpkg.json paketi de eklenebilir.
İstekler otomatik yayımlanmaz. Envest ekibi cihazı ve belgeleri doğrular, gerekirse sizden bilgi ister, paketi (tag'ler, ekranlar) hazırlayıp test eder ve kütüphaneye kendisi ekler. İsteğin durumu (alındı, inceleniyor, onaylandı — hazırlanıyor, yayında ya da uygun bulunmadı) ve ekibin notu panelde görünür; sonuç e-postayla da bildirilir. Bir firmanın aynı anda en çok on bekleyen isteği olabilir.
MergenHub