إنتقل إلى المحتوى الرئيسي

MQTT

MQTT هو الخيار المعتاد للبرنامج الثابت (firmware) الذي تكتبه بنفسك: اتصال واحد يبقى مفتوحاً، وعملية نشر كلما توفّرت لديك قراءة.

قبل أن تبدأ، اجمع معرّف الجهاز UUID وموضوع MQTT وبيانات اعتماد MQTT من تفاصيل الجهاز؛ راجع ما تحتاجه من المنصة أولاً.

إعدادات الاتصال

الإعدادالقيمة
المضيفmqtt.sensocan.com
المنفذ8883 مع TLS، و1883 مع TCP العادي
معرّف العميلمعرّف الجهاز UUID بالضبط
اسم المستخدماسم مستخدم MQTT من تفاصيل الجهاز (يبدو على هيئة device- متبوعاً بمعرّف الجهاز UUID)
كلمة المروركلمة مرور MQTT من تفاصيل الجهاز
الجلسة النظيفة (clean session)نعم
QoS0 أو 1. استخدم 1 على وصلة غير موثوقة
keep-aliveحسب اختيارك؛ القيم الأقصر تكشف انقطاع الوصلة في وقت أبكر

استخدم المنفذ 8883 في بيئة الإنتاج. أما المنفذ 1883 فينقل كلمة مرور جهازك بنص واضح، وهو موجود للعمل المخبري على شبكة تتحكم بها.

الجلسة النظيفة كل ما تحتاجه: الأجهزة تنشر فقط. أما الاشتراكات فمرفوضة، فلا توجد حالة جلسة تستحق الاستئناف.

مربع حوار بيانات اعتماد MQTT مفتوحاً في صفحة تفاصيل الجهاز لجهاز قياسي (غير بوابة)، ويظهر فيه حقلا اسم المستخدم وكلمة المرور مع زرَّي النسخ الخاصين بهما وزر نسخ الكل.
مربع حوار بيانات اعتماد MQTT مفتوحاً في صفحة تفاصيل الجهاز لجهاز قياسي (غير بوابة)، ويظهر فيه حقلا اسم المستخدم وكلمة المرور مع زرَّي النسخ الخاصين بهما وزر نسخ الكل.

تُخزَّن كلمة المرور مشفَّرة. وفتح مربع الحوار مرة أخرى يعرض كلمة المرور نفسها؛ إذ لا توجد طريقة لتدويرها من الواجهة، ولا تُصدَر كلمة مرور جديدة تلقائياً إلا إذا فُقدت بيانات الاعتماد المخزّنة أو تعذّر فك تشفيرها.

قاعدة معرّف العميل

يجب أن يكون معرّف العميل هو معرّف الجهاز UUID

يُرفض أي اتصال يحمل معرّف عميل غير ذلك، مهما كان اسم المستخدم وكلمة المرور. وهذا أكثر أسباب الفشل شيوعاً بعد تغيير البرنامج الثابت، لأن كثيراً من مكتبات MQTT تخترع لك معرّف عميل: فمكتبة PubSubClient تستخدم ما تمرره إلى connect()، ومكتبات أخرى تلجأ افتراضياً إلى سلسلة عشوائية أو إلى عنوان MAC. عيّنه صراحةً.

ويجب ألا يتشارك جهازان معرّف عميل واحداً أبداً. فإذا حدث ذلك، طرد كل اتصالٍ الآخر: تُسقَط الجلسة الأقدم في كل مرة يعيد فيها الجهاز الآخر الاتصال، ويظل الجهازان يتأرجحان بين متصل وغير متصل بلا نهاية. وإذا نسخت البرنامج الثابت إلى وحدة ثانية، فأنشئ لها سجل جهاز خاصاً بها ومعرّف UUID خاصاً بها.

المواضيع

هناك ثلاثة مواضيع (topics) للنشر، والموضوع الذي تستخدمه يحدد كيف تُقرأ الحمولة (payload).

1. قراءة واحدة لمستشعر واحد

tenant/{tenant_id}/device/{device_uuid}/sensor/{sensor_identifier}
{
"data": {
"value": 24.5,
"timestamp": "2026-09-03T10:00:00Z"
},
"battery_voltage": 3.7
}

2. عدة قراءات لمستشعر واحد

لاحظ صيغة الجمع sensors. استخدم هذا الموضوع لتفريغ الذاكرة المؤقتة لمستشعر واحد.

tenant/{tenant_id}/device/{device_uuid}/sensors/{sensor_identifier}
{
"data": [
{ "value": 24.0, "timestamp": "2026-09-03T09:00:00Z" },
{ "value": 24.2, "timestamp": "2026-09-03T09:15:00Z" },
{ "value": 24.4, "timestamp": "2026-09-03T09:30:00Z" }
]
}

3. قراءات لعدة مستشعرات

هذا هو الموضوع على مستوى الجهاز، وهو المعروض في صفحة تفاصيل الجهاز. وهو الخيار الأكفأ عندما يحمل الجهاز أكثر من مستشعر واحد.

tenant/{tenant_id}/device/{device_uuid}
{
"data": [
{ "sensor_slug": "temp_01", "value": 24.5 },
{ "sensor_slug": "humidity_01", "value": 45.2 },
{ "sensor_uuid": "7a8b9c0d-1234-5678-90ab-cdef12345678", "value": 100 }
],
"battery_voltage": 3.7
}

يحدد كل عنصر مستشعره إما بـsensor_slug وإما بـsensor_uuid. ويُهمَل أي عنصر لا يحمل أياً منهما.

و{sensor_identifier} في الموضوعين الأولين هو أيضاً إما المعرّف النصي (slug) للمستشعر وإما معرّفه UUID؛ وكلاهما معروض في صفحة المستشعر، والمطابقة تامة وتراعي حالة الأحرف.

ويمكنك أيضاً نشر جهد البطارية وحده، دون أي مفتاح data، على أي من المواضيع الثلاثة:

{ "battery_voltage": 3.7 }

لا تركّب المواضيع يدوياً

تعرض صفحة تفاصيل الجهاز الموضوع على مستوى الجهاز كاملاً مع زر نسخ، ويفتح زر أمثلة حمولة MQTT المجاور له المواضيع الثلاثة كلها وحمولاتها المطابقة، معبّأة سلفاً بمؤسسة هذا الجهاز ومعرّفه UUID وأول مستشعر فيه.

مربع حوار أمثلة حمولة MQTT في صفحة تفاصيل الجهاز وعلامة التبويب مفرد محددة، ويظهر فيه الموضوع المولَّد وحمولة JSON لجهاز له مستشعر واحد على الأقل.
مربع حوار أمثلة حمولة MQTT في صفحة تفاصيل الجهاز وعلامة التبويب مفرد محددة، ويظهر فيه الموضوع المولَّد وحمولة JSON لجهاز له مستشعر واحد على الأقل.

لا يُسمح لك بالنشر إلا تحت موضوع جهازك. وأي عملية نشر يحمل موضوعها معرّف UUID لجهاز آخر، أو معرّفك أنت تحت مؤسسة غير صحيحة، يرفضها الاتصال ولا يتجاهلها بصمت.

غلاف data

الحمولة الخالية من data تُقبل ثم تُهمَل

تعيش القراءات تحت مفتاح data في المستوى الأعلى. وإذا نشرت {"value": 24.5} فستصل الرسالة، ويُسجَّل جهازك على أنه متصل، ولن تُنشأ أي قراءة على الإطلاق. ولا يعود إليك شيء ليخبرك، لأن النشر عبر MQTT بلا رد.

وإذا كانت رسائلك تصل بوضوح، أي أن الجهاز يظهر متصلاً وأن آخر اتصال يتقدم باستمرار، ولا تظهر أي قيم، فافحص الغلاف أولاً.

مثال: ESP32 / Arduino

#include <PubSubClient.h>

const char* mqtt_server = "mqtt.sensocan.com";
const int mqtt_port = 8883; // TLS — pass a WiFiClientSecure to PubSubClient
// for this port; 1883 takes a plain WiFiClient

// All three come from Device Details. The client ID must be the Device UUID;
// the username and password are the MQTT credentials shown on that page.
const char* device_uuid = "a1b2c3d4-e5f6-7890-abcd-ef1234567890";
const char* mqtt_user = "device-a1b2c3d4-e5f6-7890-abcd-ef1234567890";
const char* mqtt_password = "your-device-mqtt-password";

// Copy the topic from Device Details rather than assembling it here.
const char* topic = "tenant/123/device/a1b2c3d4-e5f6-7890-abcd-ef1234567890/sensor/temp_01";

void setup() {
client.setServer(mqtt_server, mqtt_port);
client.setBufferSize(512); // the default is too small for batches
client.connect(device_uuid, mqtt_user, mqtt_password);
}

void loop() {
if (!client.connected()) {
client.connect(device_uuid, mqtt_user, mqtt_password);
}
client.loop();

// The data envelope is required.
const char* payload = "{\"data\":{\"value\":25.3}}";
client.publish(topic, payload);
delay(60000); // once a minute
}

تُسقط PubSubClient بصمت أي عملية نشر تتجاوز حجم ذاكرتها المؤقتة، وهي 256 بايت افتراضياً: يكفي ذلك لحمولة القراءة الواحدة أعلاه، ولا يكفي لدفعة. استدعِ setBufferSize() قبل إرسال الدفعات.

استكشاف الأعطال وإصلاحها

الاتصال مرفوض

راجع هذه القائمة بالترتيب:

  1. معرّف العميل: يجب أن يكون معرّف الجهاز UUID بالضبط. اطبع ما أرسلته مكتبتك فعلياً.
  2. اسم المستخدم وكلمة المرور: انسخهما مرة أخرى من مربع حوار بيانات اعتماد MQTT؛ فالمربع يعرض دائماً كلمة المرور نفسها التي لا تتغير.
  3. حالة الجهاز: لا يُسمح بالاتصال لجهاز تظهر حالته خطأ في تفاصيل الجهاز. أعد ضبط حالته من صفحة الجهاز.
  4. حالة الحساب: تُرفض أجهزة الحساب الموقوف أو غير النشط. تواصل مع أحد المسؤولين.

الجهاز يتصل ثم ينقطع كلما اتصل جهاز آخر

جهازان يتشاركان معرّف عميل واحداً. راجع قاعدة معرّف العميل.

الجهاز متصل لكن لا تظهر أي قيم

افحص ذلك من صفحة تفاصيل الجهاز. يخبرك آخر اتصال وشارة الحالة بأن الرسائل تصل، ويعرض جدول المستشعرات القيمة الحالية وآخر تحديث لكل مستشعر.

  • آخر اتصال يتقدم لكن المستشعرات لا تعرض بيانات: الرسالة تصل لكن لا تُنشأ أي قراءة. افحص غلاف data، ثم تأكد من وجود value في كل كائن قراءة.
  • بعض المستشعرات تُحدَّث وبعضها لا: معرّف المستشعرات التي تبقى فارغة لا يطابق أي مستشعر على هذا الجهاز. قارنه حرفاً بحرف بالمعرّف النصي وبمعرّف UUID في صفحة المستشعر.
  • كل شيء يبدو صحيحاً ومع ذلك لا شيء: القراءات تُقبل وتُمرَّر إلى سلسلة القواعد، والسلسلة تُهملها. ويجب أن تحتوي السلسلة على خطوة حفظ حتى تظهر القيم. راجع الإدارة ← سلاسل القواعد.
  • آخر اتصال لا يتقدم: الرسالة لا تصل أصلاً. قارن الموضوع بالموضوع المعروض في صفحة تفاصيل الجهاز، وتأكد من أن حمولتك JSON صالحة.

القيمة تصل مرة واحدة ثم تتوقف عن التحديث

إذا كان جهازك يرسل القيمة نفسها مراراً، فإن التكرار خلال ثوانٍ قليلة يُكبَح في بعض أنواع المستشعرات. غيّر القيمة أو انتظر انقضاء الفترة للتأكد من سلامة الوصلة.