# MQTT ve UNS konuları

> Edge Gateway'deki yerleşik MQTT sunucusundan canlı değerleri alın. ortak veri modeli (UNS) konu düzenini, JSON veri içeriklerini ve Sparkplug B'yi öğrenin.

Kaynak: https://proxus.io/tr/docs/develop/mqtt

Bu kılavuzu tamamladığınızda MQTT istemciniz, bir Edge Gateway'e bağlı cihazların tüm veri noktası değerlerini okundukları
anda alır. Konular, tesisin ortak veri modeline (UNS) göre düzenlenir.

## Başlamadan önce

Şunlar gereklidir:

- Verisini almak istediğiniz cihazların bağlı olduğu Edge Gateway'in adresi. Her Edge Gateway kendi MQTT sunucusunu çalıştırır
  ve yalnızca kendi cihazlarının verisini yayınlar. Merkez sunucudaki **SYSTEM** Edge Gateway'i, kendisine atanmış
  cihazların verisini yayınlar.
- Edge Gateway'in **MasterToken** değeri. Bu değer, Edge Gateway'in yapılandırma dosyasında `[MQTTBroker]` bölümünde bulunur.
  Edge Gateway açılırken değer boşsa yeni bir değer üretir ve dosyaya yazar.
- MQTT sunucusunun portuna ağ erişimi: TLS için `8883`, TLS olmadan `1883` (`MQTTBrokerPort`).
- TLS kullanılacaksa platform CA'sı. Bu dosyayı **Güvenlik > Sertifika deposu** ekranında **CA'yı indir** ile
  alabilirsiniz.
- MQTT 3.1.1 veya 5 destekleyen bir istemci: MQTT Explorer, `mosquitto_sub` ya da Python `paho-mqtt` gibi bir
  kütüphane.

> **Not:**
Cihazın konusu, tesisteki yerine (kuruluş, tesis, alan, hat veya hücre, ekipman) göre oluşur. Bu yeri cihaz
üzerinde tanımlayın. Ayrıntılar için [Ortak veri modeli (UNS)](https://proxus.io/tr/docs/concepts/unified-namespace) sayfasına bakın.

## Adım 1: Bağlanın

| Ayar | Değer |
| --- | --- |
| Sunucu adresi | Edge Gateway'in adresi |
| Port | TLS ile `8883`, TLS olmadan `1883` (veya `MQTTBrokerPort`) |
| Kullanıcı adı | Edge Gateway'in `MasterToken` değeri |
| Parola | boş |
| TLS | 8883 portunda MQTT sunucusunu platform CA'sıyla doğrulayın. Ayrıntılar için [TLS ile bağlanın](#tls-ile-bağlanın). |

MQTT sunucusu bağlantıyı üç durumda kabul eder: kullanıcı adı `MasterToken` ise, kullanıcı adı o Edge Gateway'deki bir
cihazın **Erişim anahtarı** ise (cihaz sayfasında görünür) ya da `AllowAnonymous = true` ise. Diğer bağlantılar
`Not authorized` hatasıyla reddedilir.

> **Uyarı:**
`AllowAnonymous = true` ayarı, ağdaki herkesin Edge Gateway'in tüm değerlerini okumasına yol açar. Bu ayarı `false`
bırakın ve `MasterToken` değerini yalnızca gerçekten ihtiyaç duyan sistemlere verin. MQTT sunucusunda konu bazlı
yetki yoktur. Bağlanan her istemci tüm konulara abone olabilir.

### TLS ile bağlanın

MQTT sunucusu, **8883** portunda Edge Gateway'in kendi sertifikasıyla TLS bağlantısı kabul eder. Bu sertifikayı merkez
sunucu, [Sertifika deposu](https://proxus.io/tr/docs/administer/certificates) üzerinden üretir. Port, sertifika üretildikten sonra
açılır.

1. **Güvenlik > Sertifika deposu** ekranında **CA'yı indir**'e tıklayın. İnen dosya yalnızca CA sertifikalarını (PEM)
   içerir, özel anahtar içermez.
2. İstemcinizde portu `8883` olarak ayarlayın ve bu dosyayı güvenilir CA olarak gösterin. Sunucu adı sertifikayla
   eşleşmelidir. Bu nedenle Edge Gateway'in sertifikasında yer alan bir sunucu adına veya adrese bağlanın.

```bash
mosquitto_sub -h <gateway-host> -p 8883 --cafile proxus-ca.pem -u "<MasterToken>" -t 'v1/#' -v
```

Aşağıdaki Python örneğinde TLS için `client.tls_set(ca_certs="proxus-ca.pem")` çağrısını ekleyin ve `8883` portunu
kullanın.

**1883** portu, TLS desteklemeyen cihazlar için açık kalır. Yalnızca TLS bağlantılarını kabul etmek için
`[MQTTBroker] PlainEnabled = false` ayarını yapın. Edge Gateway'in sertifikası yenilendiğinde MQTT sunucusu birkaç
saniyeliğine yeniden başlar ve istemciler yeniden bağlanır.

## Adım 2: Abone olun

Tüm veriyi almak için `v1/#` konusuna, belirli bir bölüm için ağacın ilgili dalına abone olun. Örneğin:

| Abonelik | Gelen veri |
| --- | --- |
| `v1/#` | Edge Gateway'deki tüm konular |
| `v1/Meridian/Lyon_Foods_Plant/#` | bir tesise ait tüm konular |
| `v1/+/+/+/+/+/LYS_PACKER_04/telemetry/+` | tek bir cihazın tüm veri noktaları (yer bilgisinin beş seviyesi de doluysa) |

```python
import os
import paho.mqtt.client as mqtt

BROKER = "localhost"
PORT = 1883
TOKEN = os.environ["PROXUS_MQTT_TOKEN"]  # Edge Gateway'in MasterToken değeri

def on_connect(client, userdata, flags, reason_code, properties):
    print("connected:", reason_code)
    client.subscribe("v1/#")

def on_message(client, userdata, msg):
    print(msg.topic, msg.retain, msg.payload.decode())

client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="uns-reader")
client.username_pw_set(TOKEN)
client.on_connect = on_connect
client.on_message = on_message
client.connect(BROKER, PORT)
client.loop_forever()
```

Betiği `PROXUS_MQTT_TOKEN=<token> python3 uns_reader.py` komutuyla çalıştırın.

## Konu düzeni

```text
v1/<Enterprise>/<Site>/<Area>/<Line or cell>/<Equipment>/<Device>/<category>/<name>
```

- `v1`, veri ağacının sürümünü gösterir.
- Yer seviyeleri cihazdan alınır. Boş bırakılan seviye konuya eklenmez ve konu kısalır. Yalnızca tesisi ve alanı
  tanımlı bir cihaz `v1/Lyon_Foods_Plant/Packaging/LYS_PACKER_04/...` altında yayınlanır. Hiç yer bilgisi olmayan
  bir cihaz ise `v1/<Device>/...` altında yayınlanır.
- Harf, rakam, `_` ve `-` dışındaki tüm karakterler `_` ile değiştirilir. Örneğin `Lyon Foods Plant`,
  `Lyon_Foods_Plant` olur; `Line 1` ise `Line_1` olur.
- `<category>` değerler için `telemetry`, cihaz durumu için `state` olur.

| Konu | Kalıcı (retained) | Ne zaman gönderilir |
| --- | --- | --- |
| `.../telemetry/<tag>` | hayır | veri noktası her okunduğunda |
| `.../telemetry/_summary` | hayır | cihazın tüm veri noktaları tek mesajda gelir. En sık `SummaryIntervalMs` (5 sn) aralıkla gönderilir. |
| `.../state/_lastSeen` | evet | son okumanın zamanı. En sık `LastSeenIntervalMs` (5 sn) aralıkla gönderilir. |
| `.../state/_status` | evet | değer geldikçe `Online`, cihaz devre dışı bırakıldığında veya silindiğinde `Offline`. Değerlerini kendisi yayınlayan cihazlarda (aşağıya bakın) istemcinin bağlantısı koptuğunda da `Offline`, beş dakika boyunca değer gelmezse `Timeout` gönderilir. |

Kalıcı mesajlar MQTT sunucusunda saklanır ve yeni bağlanan aboneye hemen gönderilir. Böylece sonradan bağlanan
istemci de tüm cihazların durumunu beklemeden öğrenir. Bu davranışı kapatmak için `UNSRetainMessages = false` ayarını
yapın.

## Veri içerikleri

`v1/Lyon_Foods_Plant/Packaging/LYS_PACKER_04/telemetry/Temperature` konusuna gelen tek bir veri noktası değeri:

```json
{"ts":"2026-10-15T19:01:43.450Z","value":25.4,"dataType":"Double","unit":"°C","quality":"Good","source":"Proxus"}
```

| Alan | Anlamı |
| --- | --- |
| `ts` | Değerin okunduğu an. UTC, milisaniyeli ISO 8601 biçimindedir. |
| `value` | Değerin kendisi: JSON sayısı, `true`/`false` ya da metin. |
| `dataType` | `Bool`, `Int`, `Long`, `Float`, `Double`, `DateTime` veya `String`. Tür, değerin kendisine bakılarak belirlenir. Bu yüzden `UShort` türündeki bir veri noktası `Int` olarak gelir. |
| `unit` | Veri noktasının birimi. Birim tanımlı değilse bu alan gönderilmez. |
| `quality` | Bu konuda her zaman `Good` olur. Okunamayan değerler burada yayınlanmaz. Okuma hatalarını cihaz sayfasında görebilirsiniz. |
| `source` | Her zaman `Proxus` olur. |

`TelemetryThinPayload = false` ayarlandığında her veri noktası mesajına bir `context` nesnesi de eklenir. Bu nesne
`enterprise`, `site`, `area`, `processCell`, `equipmentModule`, `deviceId`, `deviceName` ve `metric` alanlarını
içerir.

`.../telemetry/_summary` konusuna gelen özet:

```json
{
  "ts": "2026-10-15T19:01:46.955Z",
  "deviceId": "48",
  "deviceName": "MFB_LYS_MIXER_3",
  "metrics": {
    "Speed": {"value": 386, "dataType": "Int", "unit": "rpm", "quality": "Good"},
    "Running": {"value": true, "dataType": "Bool", "quality": "Good"}
  },
  "context": {"enterprise": "Meridian", "site": "Lyon Foods Plant", "area": "Processing",
              "processCell": "Dough", "equipmentModule": "_none"},
  "source": "Proxus"
}
```

`SummaryIncludeContext = false` ayarlandığında `context` gönderilmez. `_none` değeri, cihazın ekipman seviyesinin
tanımlı olmadığını gösterir.

Durum konularına gelen mesajlar:

```json
{"ts":"2026-10-15T19:01:39.551Z"}
{"status":"Online","ts":"2026-10-15T18:14:07.999Z"}
{"status":"Timeout","ts":"2026-10-15T19:20:00.000Z","reason":"Device timeout"}
```

## Bir cihazdan değer yayınlama

Bir cihaz veya program kendi değerlerini doğrudan MQTT sunucusuna gönderebilir. Bunun için kullanıcı adı olarak
cihazın **Erişim anahtarı** değeriyle bağlanır ve `telemetry` konusuna (ya da `telemetry/` altındaki herhangi bir
konuya) JSON yayınlar. JSON'daki her alan, o cihazın bir veri noktasına dönüşür:

```json
{"Temperature": 21.7, "DoorOpen": false, "Pressure": {"value": 2.4, "unit": "bar"}}
```

İç içe nesneler noktalı adlara (`Line.Speed`), diziler ise sıra numaralı adlara (`Axis[0]`) dönüşür. Bu değerler,
Edge Gateway'in kendi okuduğu değerlerle aynı yolu izler: saklanır, işlem akışlarından geçer, veri hedeflerine ve UNS
konularına gönderilir.

JSON biçiminde MQTT üzerinden, bir `command` konusuna yayın yaparak cihaza değer yazmak desteklenmez. Değer yazmak için
[kural eylemi](https://proxus.io/tr/docs/automate/rule-actions) ya da [işlem akışı](https://proxus.io/tr/docs/automate/pipelines) kullanın.

## Sparkplug B

Edge Gateway'in yapılandırma dosyasında `[UNS]` bölümüne `UNSPayloadFormat = "SparkplugB"` ayarını yazın ve Edge Gateway'i
yeniden başlatın. Edge Gateway bundan sonra yukarıdaki JSON konuları yerine, kendi MQTT sunucusunda Sparkplug B 3.0
mesajları yayınlar:

- Konular `spBv1.0/<UNSGroupId>/...` altında yer alır. Edge Gateway, `<UNSEdgeNodeId>` adlı edge node olarak görünür.
- Her cihaz bir Sparkplug cihazıdır. Önce cihazın adını, durumunu, son görülme zamanını ve yerini içeren bir `DBIRTH`
  mesajı, ardından veri noktası değerlerini taşıyan `DDATA` mesajları gönderilir. Her metrikte `Source`, `Quality`
  ve `Unit` özellikleri bulunur.
- Edge node, `Node Control/Rebirth` (birth mesajlarını yeniden gönderir), `discovery` ve `refresh_metadata` komutlarına
  yanıt verir.

Sparkplug host uygulamaları da JSON istemcileri gibi kullanıcı adı olarak `MasterToken` ile bağlanır.

## MQTT sunucusu ve UNS ayarları

Aşağıdaki anahtarlar Edge Gateway'in yapılandırma dosyasında bulunur. Aynı ayarları ortam değişkeniyle vermek için
[Yapılandırma anahtarları](https://proxus.io/tr/docs/reference/configuration) sayfasına bakın.

| Anahtar | Varsayılan | Anlamı |
| --- | --- | --- |
| `[MQTTBroker] Enabled` | `true` | MQTT sunucusunu bu Edge Gateway'de çalıştırır. `false` ise MQTT sunucusu çalışmaz ve UNS yayını yapılmaz. |
| `[MQTTBroker] MQTTBrokerPort` | `1883` | MQTT sunucusunun portu. Portu başka bir uygulama kullanıyorsa Edge Gateway boş bir port seçer ve günlüğe uyarı yazar. `AllowPortFallback = false` ise bu geçiş yapılmaz. |
| `[MQTTBroker] TlsPort` | `8883` | Edge Gateway'in sertifikasıyla çalışan TLS portu. `0` değeri TLS'i kapatır. |
| `[MQTTBroker] PlainEnabled` | `true` | `MQTTBrokerPort` üzerinden TLS'siz bağlantıları kabul eder. `false` ise yalnızca TLS bağlantıları kabul edilir. |
| `[MQTTBroker] AllowAnonymous` | `false` | Kullanıcı adı göndermeyen istemcileri kabul eder. |
| `[MQTTBroker] MasterToken` | ilk açılışta üretilir | UNS ve Sparkplug istemcilerinin kullanıcı adı. |
| `[MQTTBroker] EnableMQTTHooks` | `true` | Edge Gateway'in okuduğu değerleri UNS konularına yayınlar. `false` ise yalnızca cihazların kendi yayınladığı değerler görünür. |
| `[UNS] UNSPayloadFormat` | `"JSON"` | `JSON` veya `SparkplugB`. |
| `[UNS] UNSRetainMessages` | `true` | Durum konularındaki mesajları kalıcı tutar. |
| `[UNS] UNSGroupId`, `UNSEdgeNodeId` | `"ProxusGroup"`, `"ProxusEdge"` | Sparkplug grubu ve edge node adı. |
| `[UNS.Optimizations] TelemetryThinPayload` | `true` | Veri noktası mesajlarına `context` eklemez. |
| `[UNS.Optimizations] SummaryIntervalMs` | `5000` | Bir cihazın iki özeti arasındaki en kısa süre. `0` ise her okumada özet gönderilir. |
| `[UNS.Optimizations] SummaryIncludeContext` | `true` | Özete `context` ekler. |
| `[UNS.Optimizations] SummaryOnlyOnChange` | `false` | Özeti yalnızca bir değer değiştiğinde gönderir. |
| `[UNS.Optimizations] LastSeenIntervalMs` | `5000` | İki `_lastSeen` mesajı arasındaki en kısa süre. |
| `[UNS.Optimizations] StatusOnChangeOnly` | `true` | `_status` mesajını yalnızca durum değiştiğinde gönderir. |

Telemetri mesajları QoS `0`, durum mesajları QoS `1` ile gönderilir.

## Sonraki adımlar

- [Ortak veri modeli (UNS)](https://proxus.io/tr/docs/concepts/unified-namespace): tesis hiyerarşisinin nasıl kurulduğunu öğrenin.
- [Veri ağacı (UNS)](https://proxus.io/tr/docs/organize/uns-explorer): aynı ağacı merkez sunucuda inceleyin.
- [Veri hedefleri](https://proxus.io/tr/docs/connect/outbound-targets): değerleri kendi MQTT sunucunuza gönderin.
