Bu sayfa, en kısa yolla tek bir istek-yanıt döngüsünü adım adım gösterir: cihaza bağlanma → mesaj kodlayıcıyı hazırlama → istek gönderme → yanıt alma. Örnekler projenin Python istemci sarmalayıcısını kullanır ve arayüze bağlı değildir.
Ön Koşullar
Başlamadan önce şunlardan emin olun:
- Cihaz açık ve ana bilgisayarınızla aynı ağda (USB veya Wi-Fi, bkz. Bağlantı ve Kimlik Doğrulama).
- Bir OpenAPI Key anahtarınız var (nasıl alınacağı: Bağlantı ve Kimlik Doğrulama · OpenAPI Key Talep Etme).
- Ana bilgisayarda örnek proje ile bağımlılıkları yüklü bir Python ortamı var (aşağıya bakın).
Ortam ve bağımlılıklar
| Öğe | Gereksinim |
|---|---|
| İşletim sistemi | Linux, Windows (arayüz sırasıyla PySide2 ve PySide6 kullanır) |
| Python | 3.8 veya üzeri |
| MQTT istemcisi | paho-mqtt, 2.0.0 veya üzeri |
| Codec | protobuf, grpcio-tools (proto dosyasını derlemek için) |
| Nokta bulutu açma (isteğe bağlı) | lz4, zstandard (yalnızca gerçek zamanlı nokta bulutuna abone olurken gerekir) |
Örnek projeyi alma ve bağımlılıkları yükleme
Örnek proje, herkese açık Lixel_OpenAPI deposudur. Aşağıdaki komutlar Ubuntu 22.04 içindir; Windows için depodaki README.md dosyasına bakın:
sudo apt-get update
sudo apt-get install -y python3-pip python3-venv git
git clone --branch 1.1.0 https://github.com/xgrids/Lixel_OpenAPI.git
cd Lixel_OpenAPI # repository root
python3 -m venv venv
source venv/bin/activate # after activation you can use python and pip directly
unset PYTHONPATH # needed on machines with ROS installed, to avoid ROS packages leaking in
pip install --upgrade pip
pip install -r python/requirements.txt # includes paho-mqtt, protobuf, grpcio-tools
pip install lz4 zstandard # install when you need the real-time point cloud
Şunlara dikkat edin:
- Sistemin Python paketlerini değil, bir sanal ortam kullanın: Ubuntu 22.04,
python/requirements.txtdosyasının gerektirdiği 5.26.0 sürümünün altında olanpython3-protobuf3.12.4 ile gelir. - Ubuntu 22.04'te varsayılan olarak
pip,python3-venvveyapythonkomutu yoktur. Önce yukarıdaki paketleri yükleyin vepythonkomutunu yalnızca sanal ortamı etkinleştirdikten sonra kullanın. - Aşağıdaki tüm Python kod parçaları
python/dizininde çalıştırılmalıdır (öncecd pythonyapın, örneğin kod parçasınıpython/quick.pyolarak kaydedippython quick.pyçalıştırın). Aksi haldefrom example.core import …ifadesiexamplepaketini bulamaz.src/generate_proto.pygibipython/önekli komutlar depo kök dizininden çalıştırılır. python/requirements.txtarayüz bağımlılıklarını içermez; arayüzü çalıştırmak için ayrıcapython/requirements-linux.txt(PySide2) veyapython/requirements-windows.txt(PySide6) dosyasını yükleyin.
Adım 1: Protobuf Modülünü Hazırlama
Tüm iş mesajları Protobuf kullanır. Önce proto tanımını bir Python modülüne derleyin:
python python/src/generate_proto.py
Not: Derleme, geçerli ortamın
grpc_tools.protocaracını kullanır; böylece gencode sürümü çalışma zamanındaki protobuf sürümüyle uyumlu kalır. Çalışma zamanında, ortamlar arası C uzantısı uyumsuzluklarını önlemek içinPROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=pythonayarlanması önerilir.
Adım 2: Cihaza Bağlanma
Bağlanmak için istemci sarmalayıcısını kullanın. Kablolu bağlantıda cihazın varsayılan adresi 192.168.55.1, MQTT portu 1883'tür. Aşağıdaki örnek L2PRO için geçerlidir; MQTTS kullanan modeller için Bağlantı ve Kimlik Doğrulama bölümüne bakın. Bu modeller use_tls=True, port=8883 ve üretici tarafından verilen kimlik bilgilerini gerektirir:
from example.core import ClientOptions, OpenApiClient
opts = ClientOptions(
host="192.168.55.1",
port=1883,
openapi_key="<provided by XGRIDS>",
)
with OpenApiClient(opts) as client:
print("connected:", client.is_connected)
with ifadesi girişte bağlanır, çıkışta bağlantıyı keser. Başarısız bir bağlantı istisna oluşturur: erişilemeyen bir adres veya kapalı port OSError oluşturur (ConnectionRefusedError dahil; Python 3.10+ sürümünde ağ zaman aşımı TimeoutError olur). TCP bağlantısı kurulmuş ancak 10 saniye içinde başarılı bir CONNACK gelmemişse (broker'ın bağlantıyı reddetmesi dahil) TimeoutError oluşur; zaman aşımı süresi ClientOptions.connect_timeout ile ayarlanır.
Adım 3: İlk İsteğinizi Gönderme
En basit "cihaz bilgisi sorgulama" isteğini gönderin ve yanıtı bekleyin. İstek-yanıt, senkron bir çağrıdır: önce yanıt konusuna abone olur, ardından isteği yayınlar, sonra yanıt gelene kadar bekler:
from example.core import ClientOptions, OpenApiClient
opts = ClientOptions(host="192.168.55.1", openapi_key="<provided by XGRIDS>")
with OpenApiClient(opts) as client:
rsp = client.request(
req_topic="lixel/application/request/device_info",
req_message="DeviceInfoRequest",
payload={}, # an empty payload is fine
rsp_topic="lixel/application/response/device_info",
rsp_message="DeviceInfoResponse",
)
print(rsp) # already decoded into a dict
request() işlevi OpenAPI Key anahtarını başlığa otomatik olarak ekler. Dönüş değeri; cihaz modeli, firmware sürümü, kamera listesi gibi bilgileri içeren çözülmüş bir sözlüktür (dict).
Adım 4: Raporlara Abone Olma
İstek-yanıtın yanı sıra birçok veri cihaz tarafından kendiliğinden bildirilir. Saniyede bir alınan cihaz durumuna abone olun:
import time
from example.core import ClientOptions, OpenApiClient
def on_status(topic, data): # data is already decoded into a dict
print(topic, data)
opts = ClientOptions(host="192.168.55.1", openapi_key="<provided by XGRIDS>")
with OpenApiClient(opts) as client:
client.subscribe(
"lixel/application/report/device_status",
"DeviceStatusReport",
on_status,
)
time.sleep(5) # keep the connection alive to receive reports
subscribe() hemen döner; bu nedenle geri çağırmanın (callback) tetiklenmesi için programı çalışır durumda tutun. Geri çağırmada oluşan bir istisna kaydedilir (Python varsayılan olarak terminale yazdırır) ve diğer abonelikleri kesintiye uğratmaz.
Not: OpenAPI tarafından sunulan arayüzler arasında yalnızca kalp atışı (heartbeat) JSON metni kullanır. Kalp atışına abone olurken
messageiçin boş bir dize geçin; geri çağırma sözlük (dict) değil, bir dize alır.Not: Kalp atışının alınması yalnızca cihazın ağa bağlı olduğunu gösterir, işlemler için hazır olduğunu göstermez. Açılıştan hemen sonra port açıktır ve kalp atışı gönderilir, ancak
device_infogibi isteklere bir süre yanıt verilmeyebilir. Açılıştan sonra öncedevice_infoisteğini yeniden deneyin, başarılı olduktan sonra diğer istekleri gönderin.
Tam Örnek: Tek Bir Tarama
Tipik bir uçtan uca akış şöyledir: bağlanma → bekleme durumunu doğrulama → taramayı başlatma → cihazın gerçekten tarama yaptığını bekleme → bir süre tarama → taramayı durdurma → bekleme durumunu bekleme.
connect → subscribe device_status → confirm standby → AC_START → wait for scanning → scan → AC_STOP → wait for standby → disconnect
Başlatma ve durdurma işlemlerinin ikisi de asenkrondur. AC_START yanıtı yalnızca cihazın isteği aldığını gösterir; ardından cihaz sırasıyla bekleme → başlıyor → tarama durumlarına geçer. AC_START komutundan 14-15 saniye sonra taramaya geçildiği ölçülmüştür. Tarama başlamadan gönderilen AC_STOP ertelenir ve cihaz taramaya girmez. AC_STOP sonrasında cihaz durduruluyor durumundan geçerek beklemeye döner; durduruluyor durumuna girişten itibaren bekleme durumuna dönüş 43-46 saniye sürmüştür (3 çalıştırma). AC_STOP gönderildiği andan itibaren tek bir çalıştırmada 52,1 saniye ölçülmüştür (Lixel L2Pro, firmware V3.2.1, durum saniyede bir bildirilir, 1 saniye hassasiyet). Bu nedenle örnek, report/device_status konusuna abone olur, modeling_state değerini okur ve sabit bir sleep yerine hedef durumu bekler. modeling_state değerleri için Hata Kodları · Scan status codes bölümüne bakın.
import threading
import time
from example.core import ClientOptions, OpenApiClient
SCAN_READY = 0x1204012C # EC_ScanReady, standby
SCAN_MODELING = 0x1204012E # EC_ScanModeling, scanning
state = {"modeling_state": None}
cond = threading.Condition()
def on_status(topic, data):
with cond:
state["modeling_state"] = data["modeling_state"]
cond.notify_all()
def wait_for(target, timeout):
deadline = time.monotonic() + timeout
with cond:
while state["modeling_state"] != target:
remaining = deadline - time.monotonic()
if remaining <= 0:
return False
cond.wait(remaining)
return True
def modeling(client, payload):
return client.request(
req_topic="lixel/application/request/modeling",
req_message="ModelingRequest",
payload=payload,
rsp_topic="lixel/application/response/modeling",
rsp_message="ModelingResponse",
)
opts = ClientOptions(host="192.168.55.1", openapi_key="<provided by XGRIDS>")
with OpenApiClient(opts) as client:
client.subscribe("lixel/application/report/device_status",
"DeviceStatusReport", on_status)
if not wait_for(SCAN_READY, 10):
raise SystemExit("device not in standby: 0x%X" % (state["modeling_state"] or 0)) # values: see scan status codes on page 07
rsp = modeling(client, {"action": "AC_START", "project_name": "demo",
"record_mode": "RM_RECORD_CALC", "scan_mode": "SM_PCL",
"mount_type": "MT_HAND"})
code = rsp.get("error", {}).get("code")
if code not in (0x12040001, 0x12040002): # EC_Success / EC_SuccessAndReboot
raise SystemExit("device did not accept the start request: %s" % rsp.get("error"))
if wait_for(SCAN_MODELING, 90): # measured: scanning 14 to 15 s after AC_START
time.sleep(10) # scan for 10 s
else:
print("timed out waiting for scanning")
modeling(client, {"action": "AC_STOP"})
wait_for(SCAN_READY, 180) # measured: up to 52 s back to standby after AC_STOP, 180 s is margin
Bu örnek, depodaki python/example/usage/modeling.py dosyasının sadeleştirilmiş sürümüdür: akış aynıdır, ancak Ctrl-C işleme, bekleme zaman aşımından sonra gönderilen ek AC_STOP ve çıkış kodları yoktur. Başlatma isteğinin reddedilmesi genellikle yanlış bir anahtardan veya hatalı biçimlendirilmiş bir mesajdan kaynaklanır; cihaz yalnızca bekleme durumunda olmadığı için isteği bir dönüş koduyla reddetmez, bu yüzden örnek önce modeling_state değerini kontrol eder. Gerçek kullanımda doğrudan modeling.py dosyasını çalıştırın. 1.0.1 sürümünden itibaren cihazın gerçekten taramaya geçmesini bekler, istek kabul edilmezse çıkar ve Ctrl-C ile kesildiğinde ya da bekleme zaman aşımında durdurma komutu gönderir: python python/example/usage/modeling.py --host 192.168.55.1 --key <provided by XGRIDS> --project demo. Tam bir çalıştırma bir dakika veya daha uzun sürer. 1.0.0 sürümündeki modeling.py, cihaz taramaya girmeden önce durdurmadan yalnızca birkaç saniye sabit süre bekler; 1.0.1 veya daha yeni bir sürüm kullanın.
Bekleme durumunda poz verisine abone olunduğunda 3 saniye içinde hiçbir veri alınmamıştır (ölçülmüştür); poz ve nokta bulutu yalnızca tarama sırasında kullanılabilir. Tarama sırasında bunları almak için cihaz taramaya girdikten sonra abone olun; örneğin wait_for(SCAN_MODELING, 90) başarılı olduktan sonra client.subscribe("lixel/application/report/lio_pose", "LioPoseReport", callback) satırını ekleyin.
Not: Tarama parametreleri (kayıt modu, tarama modu, montaj türü vb.) için Arayüz Kataloğu · Scan mapping bölümüne bakın. Gerçek zamanlı nokta bulutu ek açma işlemi gerektirir, bkz. Gerçek Zamanlı Veri.
Sonraki Adımlar
- Her modelin bağlantı ve kimlik doğrulama ayrıntıları için Bağlantı ve Kimlik Doğrulama bölümüne bakın.
- Konu kurallarını, başlığı ve kodek yapısını anlamak için Mesaj Modeli ve Kodek bölümüne bakın.
- Tüm arayüz kataloğu (tarama, noktalar, projeler, RTK vb.) için Arayüz Kataloğu bölümüne bakın.
- Daha fazla çalıştırılabilir betik için İstemci Sarmalayıcı ve Araçlar bölümüne bakın.
Bu bölüm XGRIDS'in resmî kullanım kılavuzundan Türkçeye çevrildi; ekran görüntüleri ve arayüz adları özgün haliyle İngilizcedir. İngilizce aslı (yeni sekmede açılır) · Güncelleme:

