如何实现XForms与MQTT Websocket的JS集成(XSLTForms+Paho)
XForms + MQTT 集成入站消息处理方案(XSLTForms + Paho JS + Mosquitto)
问题场景
用XSLTForms实现XForms与MQTT的集成,通过WebSocket借助Paho JS库对接Mosquitto消息代理,已能通过xf:load发送静态字符串消息,但无法将MQTT入站消息传入XForms内部。最初尝试在onMessageArrived函数中触发自定义JS事件,再用xf:action响应,但不清楚事件注册与载荷接收的实现方式,最终摸索出三种可行方案。
解决方案
方案1:JS触发隐藏的xf:trigger
在页面中添加一个隐藏的xf:trigger,当MQTT消息到达时,用JS模拟点击该trigger,触发绑定的XForms动作:
<!-- 隐藏的消息触发按钮 --> <xf:trigger id="mqttMsgTrigger" style="display:none"> <xf:label>MQTT消息触发</xf:label> <xf:action ev:event="DOMActivate"> <!-- 更新实例数据存储消息 --> <xf:setvalue ref="instance('mqttData')/msg" value="javascript:getCurrentMqttMsg()"/> </xf:action> </xf:trigger>
对应的JS逻辑:
// 全局变量暂存消息内容 let currentMqttMsg; function onMessageArrived(message) { currentMqttMsg = message.payloadString; // 触发隐藏trigger的点击事件 document.getElementById('mqttMsgTrigger').click(); } function getCurrentMqttMsg() { return currentMqttMsg; }
方案2:直接调度DOMActivate事件
无需额外trigger元素,使用XSLTForms内置的XsltForms_xmlevents.dispatch方法直接调度事件:
<xf:model id="mainModel"> <!-- 绑定DOMActivate事件处理逻辑 --> <xf:action ev:event="DOMActivate" ev:target="mqttMsgHandler"> <xf:setvalue ref="instance('mqttData')/msg" value="javascript:getCurrentMqttMsg()"/> </xf:action> </xf:model>
对应的JS逻辑:
let currentMqttMsg; function onMessageArrived(message) { currentMqttMsg = message.payloadString; // 直接向model调度DOMActivate事件 XsltForms_xmlevents.dispatch( document.getElementById('mainModel'), 'DOMActivate', { targetId: 'mqttMsgHandler' } ); }
方案3:自定义事件绑定到xf:model
为xf:model设置ID作为事件源,创建自定义事件并绑定XForms动作响应:
<xf:model id="mainModel"> <!-- 绑定自定义事件mqtt-message-arrived --> <xf:action ev:event="mqtt-message-arrived"> <!-- 通过event('data')获取事件携带的消息载荷 --> <xf:setvalue ref="instance('mqttData')/msg" value="event('data')"/> </xf:action> </xf:model>
对应的JS逻辑:
function onMessageArrived(message) { const modelNode = document.getElementById('mainModel'); // 创建带消息载荷的自定义事件 const mqttEvent = new CustomEvent('mqtt-message-arrived', { detail: message.payloadString, bubbles: true, cancelable: true }); // 向model分发事件 modelNode.dispatchEvent(mqttEvent); }
从XForms实例传递参数调用JS函数
如果需要从XForms实例中读取数据,调用JS函数发送MQTT消息,可参考以下实现:
<xf:trigger> <xf:label>发送MQTT消息</xf:label> <xf:action ev:event="DOMActivate"> <xf:script> sendMqttMsg(instance('sendData')/content); </xf:script> </xf:action> </xf:trigger>
对应的JS发送函数:
function sendMqttMsg(content) { const message = new Paho.MQTT.Message(content); message.destinationName = "test/topic"; client.send(message); }
完整测试代码
<?xml version="1.0" encoding="UTF-8"?> <?xml-stylesheet href="xsltforms/xsltforms.xsl" type="text/xsl"?> <xf:model xmlns:xf="http://www.w3.org/2002/xforms" id="mainModel"> <xf:instance id="mqttData"> <data> <msg></msg> </data> </xf:instance> <xf:instance id="sendData"> <data> <content>Hello from XForms!</content> </data> </xf:instance> <!-- 方案3的自定义事件响应逻辑 --> <xf:action ev:event="mqtt-message-arrived"> <xf:setvalue ref="instance('mqttData')/msg" value="event('data')"/> </xf:action> </xf:model> <h1>XForms + MQTT 测试页面</h1> <!-- 显示收到的MQTT消息 --> <xf:output ref="instance('mqttData')/msg"> <xf:label>收到的消息:</xf:label> </xf:output> <!-- 发送消息按钮 --> <xf:trigger> <xf:label>发送测试消息</xf:label> <xf:action ev:event="DOMActivate"> <xf:script> sendMqttMsg(instance('sendData')/content); </xf:script> </xf:action> </xf:trigger> <!-- 引入本地Paho JS库(请自行下载放置到对应路径) --> <script src="mqttws31.min.js"></script> <script> // MQTT客户端初始化 const client = new Paho.MQTT.Client("localhost", 9001, "xsltforms-test-client"); client.onConnectionLost = function(responseObj) { console.log("连接断开: " + responseObj.errorMessage); }; client.onMessageArrived = function(message) { // 方案3的事件分发逻辑 const modelNode = document.getElementById('mainModel'); const mqttEvent = new CustomEvent('mqtt-message-arrived', { detail: message.payloadString, bubbles: true, cancelable: true }); modelNode.dispatchEvent(mqttEvent); }; client.connect({ onSuccess: function() { console.log("MQTT连接成功"); client.subscribe("test/topic"); } }); function sendMqttMsg(content) { const message = new Paho.MQTT.Message(content); message.destinationName = "test/topic"; client.send(message); } </script>
内容的提问来源于stack exchange,提问作者monojohnny
相关产品推荐
相关产品推荐

