在 MQTT 中,设备在线和设备与 MQTT 服务器保持连接是相关但不完全相同的概念。
设备在线通常指设备处于活动状态且可通过网络访问。它表示设备当前能够与其他设备或服务器进行通信,包括 MQTT 服务器。设备在线意味着设备能够执行各种操作,如订阅主题、发布消息等。设备在线状态通常与设备的实际连接状态和网络连接状态相关。
设备与 MQTT 服务器保持连接表示设备与 MQTT 服务器之间建立了持久的网络连接。当设备与 MQTT 服务器成功建立连接后,设备可以保持连接并保持与服务器之间的通信通道打开,而不需要频繁地重新建立连接。这种持久连接的好处包括减少了连接建立和断开的开销,提供更高的通信效率和可靠性。
在 MQTT 中,设备需要在连接到 MQTT 服务器后保持连接,以便能够订阅主题、发布消息和接收来自服务器的消息。设备与 MQTT 服务器保持连接通常意味着设备在线,但并不意味着设备在线状态下一定要与 MQTT 服务器保持连接。设备可以处于在线状态,但暂时与 MQTT 服务器断开连接,然后重新连接以恢复通信。
因此,设备在线和设备与 MQTT 服务器保持连接是相关的概念,但在具体的 MQTT 实现中可能有细微的差别。具体取决于 MQTT 客户端库和服务器配置,以及应用程序对设备在线状态和连接状态的要求。
MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅消息传输协议。在 MQTT 中,设备需要连接到 MQTT 代理服务器(也称为 MQTT 服务端)来进行通信。
首先,设备需要连接到 MQTT 代理服务器,以建立与代理服务器的通信通道。设备通过发送连接请求和提供认证凭据(如果需要)来进行连接。这样设备就可以与代理服务器进行交互,包括订阅主题、发布消息等操作。
一旦设备成功连接到 MQTT 代理服务器,并订阅了感兴趣的主题,设备就可以接收来自代理服务器的消息,而不需要一直保持在线状态。当有新的消息发布到设备订阅的主题时,代理服务器会将消息传递给设备,即使设备暂时处于离线状态。
然而,设备需要保持在线状态的原因可能包括:
发布消息:如果设备希望通过 MQTT 发布消息,设备必须保持在线以便将消息发送到代理服务器。离线设备无法发布消息。
心跳保持连接:为了确保设备与代理服务器之间的连接处于活动状态,有些 MQTT 实现会使用心跳机制。设备需要定期发送心跳消息以保持连接。如果设备离线一段时间,代理服务器可能会认为设备已断开连接并关闭连接。
消息传递保证:MQTT 提供了三种消息传递质量等级(QoS),其中 QoS 1 和 QoS 2 提供了消息传递的可靠性保证。这些等级要求设备在发布和接收消息时保持在线,以确保消息的可靠传递。
总结起来,设备在连接到 MQTT 代理服务器后,可以订阅主题并接收消息,而不需要一直保持在线状态。然而,特定的操作(如发布消息)可能要求设备保持在线。此外,心跳机制和消息传递保证也可能需要设备保持连接以确保可靠的通信。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CFX;
using CFX.Transport;
using CFX.Structures;
using CFX.Properties;
using CFX.Production;
using CFX.Materials.Management;
using CFX.InformationSystem.UnitValidation;
using CFX.Utilities;
using CFX.ResourcePerformance;
using CFX.Production.Processing;
using CFX.Production.TestAndInspection;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using System.Threading;
namespace CFXTEST
{
public partial class Form1 : Form
{
//DCFX服务连接参数
private static Broker broker = new Broker("4.193.102.148", MqttPort.tcp);
//mqtt格式
private static DeviceSettings dSettings;
//设备实例化
private static DCFX_Device device1;
private static Guid uniqueID;
//是否连接
bool isconnect = false;
private DeviceRetainMsg deviceRetainMsg;
private DevicePosition devicePosition;
private CFXEnvelope env;
private string machineID;
public Form1()
{
InitializeComponent();
}
private void Button1_Click(object sender, EventArgs e)
{
machineID = textBox1.Text;
if (string.IsNullOrEmpty(machineID))
{
MessageBox.Show("机床编号为空", "警告", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
dSettings = new DeviceSettings(broker, UsageMode.final, "WJ5", "S01", machineID, "0");
device1 = new DCFX_Device(dSettings);
var result = Task.Run(() => device1.MqttConnect());
int ret = result.Result;
if (ret == 0)
{
label2.Text = "连接成功";
isconnect = true;
Controls.Add(label2);
}
else
{
label2.Text = "服务器未连接成功";
Controls.Add(label2);
}
}
private void Button2_Click(object sender, EventArgs e)
{
if (!isconnect)
{
MessageBox.Show("设备未连接", "警告", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
devicePosition = new DevicePosition
{
Factory = "WJ5",
Line = "S01",
Station = machineID
};
deviceRetainMsg = new DeviceRetainMsg
{
DeviceType = DeviceType.Unknown,
Position = devicePosition,
RetainStatus = RetainStatus.設備連綫,
Functions = new List<String>()
};
//设备透明情景
//设备连线加到list当中去
deviceRetainMsg.Functions.Add("DeviceRetainMsg");
//设备属性上报
// deviceRetainMsg.Functions.Add("DevicePropertiesReport");
//操作员上下岗
// deviceRetainMsg.Functions.Add("OperatorActivated");
// deviceRetainMsg.Functions.Add("OperatorDeactivated");
//产品途程校验
deviceRetainMsg.Functions.Add("ValidateUnitsRequest");
//生产过程上报
deviceRetainMsg.Functions.Add("UnitsArrived");
deviceRetainMsg.Functions.Add("WorkStarted");
deviceRetainMsg.Functions.Add("WorkCompleted");
deviceRetainMsg.Functions.Add("UnitsBlocked");
deviceRetainMsg.Functions.Add("UnitsBlockReleased");
deviceRetainMsg.Functions.Add("UnitsDeparted");
//生产数据上报
deviceRetainMsg.Functions.Add("UnitsProcessed");
deviceRetainMsg.Functions.Add("UnitsInspected");
deviceRetainMsg.Functions.Add("UnitsTested");
//设备异常上报
deviceRetainMsg.Functions.Add("FaultOccurred");
deviceRetainMsg.Functions.Add("FaultCleared");
//材料用料信息上报
// deviceRetainMsg.Functions.Add("UnitMaterialMsg");
//AOI检测结果信息上报
// deviceRetainMsg.Functions.Add("UnitAOIMsg");
//锁螺丝结果信息上报
// deviceRetainMsg.Functions.Add("UnitScrewingMsg");
//生产控制情景DeviceOnResponse
//开机启动
//deviceRetainMsg.Functions.Add("DeviceOnResponse");
//设备自检
deviceRetainMsg.Functions.Add("DeviceSelfCheckReport");
//自动关机
// deviceRetainMsg.Functions.Add("DeviceOffResponse");
//自动换线
deviceRetainMsg.Functions.Add("ChangeLineResponse");
deviceRetainMsg.Functions.Add("ChangeLineReady");
deviceRetainMsg.Functions.Add("LockStationResponse");
deviceRetainMsg.Functions.Add("UpdateRecipeResponse");
deviceRetainMsg.Functions.Add("ActivateRecipeResponse");
deviceRetainMsg.Functions.Add("RecipeActivated");
deviceRetainMsg.Functions.Add("UnlockStationResponse");
//设备属性修改
// deviceRetainMsg.Functions.Add("GetDevicePropertyResponse");
// deviceRetainMsg.Functions.Add("SetDevicePropertyResponse");
env = new CFXEnvelope(deviceRetainMsg)
{
Source = device1.ClientID,
Target = "",
RequestID = ""
};
//发布
var result = Task.Run(() => device1.Publish(env));
int ret = result.Result;
if (ret == 0)
{
label3.Text = "上线成功";
isconnect = true;
Controls.Add(label3);
}
else
{
label3.Text = "上线失败";
isconnect = false;
Controls.Add(label3);
}
//这个订阅主题
device1.StartReceivedMsg += SubscriptinMsg;
}
static void SubscriptinMsg(object sender, ReceivedMsgEventArgs e)
{
//处理收到的消息
string topic = e.receivedMsg.Topic;
string pd = e.receivedMsg.payload;
if (topic.Contains("ChangeLineRequest"))
{
CFXEnvelope cfx = CFXJsonSerializer.DeserializeObject<CFXEnvelope>(pd);
Guid uniqueID = cfx.UniqueID;
ChangeLineRequest changeLineRequest = CFXJsonSerializer.DeserializeObject<ChangeLineRequest>(pd);
ChangeLineResponse changeLineResponse = new ChangeLineResponse()
{
Result = new RequestResult
{
Result = StatusResult.Success,
ResultCode = 0,
Message = "OK"