物联网宠儿mqtt.js那些事儿

使用MQTT.JS创建一个网页版的MQTT客户端 MQTT.js 是一个开源的 MQTT 协议的客户端库,使用 JavaScript 编写,主要用于 Node.js 和 浏览器环境中。是JavaScript 环境下的 MQTT 客户端库。可以用于微信小程序、支付宝小程序等定制浏览器环境。 阅读详情

在这里插入图片描述

常见的mq有Kafka,RocketMQ和RabbitMQ,大家也很常见。 前者很常见,属于微服务间的mq。
那么MQTT是什么呢?MQTT属于IoT也就是物联网的概念。

快来和使用mqtt.js开发IM功能2年的作者一探究竟吧~

先来看下MQTT在物联网领域的应用场景:

mqtt.js是MQTT在nodejs端的实现。

通过npm package.json包管理,现代vue技术栈下的前端也可用,比如用vue-cli,create-react-app等等构建的项目。

mqtt.js官方为微信小程序和支付宝小程序也做了支持。微信小程序的MQTT协议名为wxs,支付宝小程序则是alis。

如果还是一脸懵逼,那么就跟随我通过mqtt.js去认识一下这个物联网领域的宠儿吧。

  • 什么是微消息队列?
  • MQTT关键名词解释
  • P2P消息和Pub/Sub消息
  • 封装的mqtt.js通用class
  • 客户端发包函数sendPacket
  • 客户端连接 mqtt.connect()
  • 订阅topic mqtt.Client#subscribe()
  • 发送消息 mqtt.Client#publish()
  • 接收消息 mqtt.Client#“message”事件

什么是微消息队列?

消息队列一般分为两种:

  • 微服务消息队列(微服务间信息传递,典型代表有RabbitMQ,Kafka,RocketMQ)
  • 物联网消息队列(物联网端与云端消息传递,代表有MQTT)

目前我实践过的,也就是我们本篇博文深入分析的,是物联网消息队列的mqtt.js。

传统的消息队列(微服务间信息传递)

传统的微服务间(多个子系统服务端间)消息队列是一种非常常见的服务端间消息传递的方式。

典型代表有:RabbitMQ,Kafka,RocketMQ。
阿里云官网拥有AMQP(兼容RabbitMQ),Kafka,和RocketMQ这三种微服务消息队列,对于我们今后在实际项目中落地提供了很大的帮助。

使用场景多种多样:

  • 高并发:秒杀、抢票(FIFO)
  • 共享型:积分兑换(多子系统共用积分模块)
  • 通信型:服务端间消息传递(nodejs,java,python,go等等)
MQTT消息队列(物联网端与云间消息传递)

MQTT是一个物联网MQTT协议,主要解决的是物联网IoT网络情况复杂的问题。

阿里云有MQTT消息队列服务。通信协议支持MQTT,STOMP,GB-808等。数据传输层支持TCP长连接、SSL加密、Websocket等。

使用场景主要为数据传输:

  1. 车联网(远程控制,汽车数据上传)
  2. IM通讯(1对1单聊,1对多朋友圈)
  3. 视频直播(弹幕通知,聊天互动)
  4. 智能家居(电器数据上传,遥控指令)

目前我手上负责的运行了2年的聊天系统就是使用的这个服务,我们主要按照设备<->server<->PC的方式,MQTT协议,Websocket传输协议进行设备与PC间的数据通信。

MQTT关键名词解释

实例(Instance)

每个MQTT实例都对应一个全局唯一的服务接入点。
肉眼可见的区别就是在通过mqtt.connect(url)与server(broker)建立连接时,broker的url都是一致的。
假设有saleman1,salesman2···他们本地的前端与服务端间建立连接的url都是统一的,只是在clientId进行区分即可。

客户端Id(Client ID)

MQTT的Client ID是每个客户端的唯一标识,要求全局都是唯一的,使用同一个Client ID连接会被拒绝。
阿里云的ClientID由两部分组成<GroupID>@@@<DeviceID>。
通常情况下Group ID是多前端统一的,比如PC端,安卓移动端,ios移动端,DeviceID也是多前端统一的。
那么如何区分多端呢?可以对Client ID中间的@@@做修改。
比如:

let CID_PC = `<GroupID>@@@-PC<DeviceID>`
let CID_Android = `<GroupID>@@@-Android<DeviceID>`
let CID_IOS = `<GroupID>@@@-IOS<DeviceID>`
组Id(Group ID)

用于指定一组逻辑功能完全一致的节点公用的组名,代表的是一类相同功能的设备。

Device ID

每个设备独一无二的标识。这个需要保证全局唯一,可以是每个传感器设备的序列号,可以是登录PC的userId。

父主题(Parent Topic)

MQTT协议基于Pub/Sub模型,任何消息都属于一个Topic。
Topic可以存在多级,第一级为父级Topic。
需要控制台单独创建。

子主题(Subtopic)

MQTT可以有二级Topic,也可以有三级Topic。
无需创建,代码中直接写即可。

P2P消息和Pub/Sub消息

Pub/Sub消息就是订阅和发布的模式,类似事件监听和广播。
如果对发布订阅不理解,可以去看Webhook到底是个啥?
MQTT除了支持Pub/Sub的模式,还支持P2P的模式。

什么是P2P消息?
  • P2P,全称为(Point to Point)。
  • 一对一的消息收发模式,只有一个消息发送者和一个消息接收者。
  • P2P模式下,消息发送者明确知道消息的预期接收者,并且这个消息只能被这个特定的客户端消费。
  • 发送者发送消息时,通过Topic指定接收者,接收者无需订阅即可获得该消息。
  • P2P 模式不仅降低注册订阅的成本,而且因为对链路有优化,所以降低推送延迟。
P2P模式和Pub/Sub模式的区别

发送消息时

  • Pub/Sub模式下,发送者需要按照与接受者约定好的Topic发送消息
  • P2P模式下,发送者无需按照Tpic发送,可以直接按照规范进行发送

接收消息时

  • Pub/Sub模式下,接收者需要提前订阅topic才能接消息
  • P2P模式下无需订阅即可接收消息
nodejs发送P2P消息
const p2pTopic =topic+"/p2p/GID_xxxx@@@DEVICEID_001";
mqtt.client.publish(p2pTopic);

封装的mqtt.js通用class

  • 客户端连接 initClient(config)
  • 订阅topic subscribeTopic(topic, config)
  • 发送消息 publishMessage(message)
  • 接收消息 handleMessage(callback)
import mqtt from 'mqtt';
import config from '@/config';

export default class MQTT {
  constructor(options) {
    this.name = options.name;
    this.connecting = false;
  }
  /**
   * 客户端连接
   */
  initClient(config) {
    const { url, groupId, key, password, topic: { publish: publishTopic }} = config;
    return new Promise((resolve) => {
      this.client = mqtt.connect(
        {
          url,
          clientId: `${groupId}@@@${deviceId}`,
          username: key,
          password,
        }
      );
      this.client.on('connect', () => {
        this.connecting = true;
        resolve(this);
      });
    });
  }

  /**
   * 订阅topic
   */
  subscribeTopic(topic, config) {
    if (this.connecting) {
      this.client.subscribe(topic, config);
    }
    return this;
  }

  /**
   * 发送消息
   */
  publishMessage(message) {
    this.client.publish(publishTopic, message, { qos: 1 });
  }

  /**
   * 接收消息
   */
  handleMessage(callback) {
    if (!this.client._events.message) {
      this.client.on('message', callback);
    }
  }

}

客户端发包函数sendPacket

mqtt-packet生成一个可传输buffer
var mqtt = require('mqtt-packet')
var object = {
  cmd: 'publish',
  retain: false,
  qos: 0,
  dup: false,
  length: 10,
  topic: 'test',
  payload: 'test' // Can also be a Buffer
}
var opts = { protocolVersion: 4 } // default is 4. Usually, opts is a connect packet

console.log(mqtt.generate(object))
// Prints:
//
// <Buffer 30 0a 00 04 74 65 73 74 74 65 73 74>
//
// Which is the same as:
//
// new Buffer([
//   48, 10, // Header (publish)
//   0, 4, // Topic length
//   116, 101, 115, 116, // Topic (test)
//   116, 101, 115, 116 // Payload (test)
// ])
sendPacket函数

发出packetsend事件并且通过mqtt.writeToStream将packet写入client的stream中。

var mqttPacket = require('mqtt-packet')

function sendPacket (client, packet) {
  client.emit('packetsend', packet)
  mqttPacket.writeToStream(packet, client.stream, client.options)
}
_sendPack方法
MqttClient.prototype._sendPacket = function (packet) {
     sendPacket(this, packet);
}

客户端连接 mqtt.connect()

mqtt client建立与mqtt server(broker)的连接,通常是通过给定一个’mqtt’, ‘mqtts’, ‘tcp’, ‘tls’, ‘ws’, ‘wss’, ‘wxs’ , 'alis’为协议的url进行连接。

mqtt.connect([url], options)

官方说明:

  • 通过给定的url和配置连接到一个broker,并且返回一个Client。
  • url可以遵循以下协议:‘mqtt’, ‘mqtts’, ‘tcp’, ‘tls’, ‘ws’, ‘wss’, ‘wxs’ , ‘alis’。(mqtt.js支持微信小程序和支付宝小程序,协议分别为wxs和alis。)
  • url也可以是通过URL.parse()返回的对象。
  • 可以传入一个单对象,既包含url又包含选项。

再来看一下我手上项目的连接配置,连接结果。
敏感信息已通过foo,bar,baz或者xxxx的组合进行数据脱敏处理。

连接配置
 {
    key: 'xxxxxxxx',
    secret: 'xxxxxxxx',
    url: 'wss://foo-bar.mqtt.baz.com/mqtt',
    groupId: 'FOO_BAR_BAZ_GID',
    topic: {
      publish: 'PUBLISH_TOPIC',
      subscribe: ['SUBSCRIBE_TOPIC/noticePC/', 'SUBSCRIBE_TOPIC/p2p'],
      unsubscribe: 'SUBSCRIBE_TOPIC/noticeMobile/',
    },
}
  • key 账号
  • secret 密码
  • url 用于建立client与server(broker)mqtt连接的链接
  • groupId 组id
  • topic 发送消息的topic,订阅的topic,取消订阅的topic
连接结果

包括总览,响应头和请求头。

General
Request URL: wss://foo-bar.mqtt.baz.com
Request Method: GET
Status Code: 101 Switching Protocols
Response Header
HTTP/1.1 101 Switching Protocols
upgrade: websocket
connection: upgrade
sec-websocket-accept: xxxxxxx
sec-websocket-protocol: mqtt
Request Header
GET wss://foo-bar.mqtt.baz.com/ HTTP/1.1
Host: foo-bar.mqtt.baz.com
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36
Upgrade: websocket
Origin: https://xxx.xxx.com
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6
Sec-WebSocket-Key: xxxxxxxxx
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
Sec-WebSocket-Protocol: mqtt
源码分析

下面来看这段mqtt连接的代码。

this.client = mqtt.connect(
  {
    url,
    clientId: `${groupId}@@@${deviceId}`,
    username: key,
    password,
  }
);
function parseAuthOptions (opts) {
  var matches
  if (opts.auth) {
    matches = opts.auth.match(/^(.+):(.+)$/)
    if (matches) {
      opts.username = matches[1]
      opts.password = matches[2]
    } else {
      opts.username = opts.auth
    }
  }
}
/**
 * connect - connect to an MQTT broker.
 *
 * @param {String} [brokerUrl] - url of the broker, optional
 * @param {Object} opts - see MqttClient#constructor
 */
function connect (brokerUrl, opts) {
  if ((typeof brokerUrl === 'object') && !opts) {
    //  可以传入一个单对象,既包含url又包含选项
    opts = brokerUrl
    brokerUrl = null
  }
  opts = opts || {}
  // 设置username和password
  parseAuthOptions(opts)
  if (opts.query && typeof opts.query.clientId === 'string') {
    // 设置Client Id
    opts.clientId = opts.query.clientId
  }
  function wrapper (client) {
   ...
    return protocols[opts.protocol](client, opts)
  }
  // 最终返回一个mqtt client实例
  return new MqttClient(wrapper, opts)
}

订阅topic mqtt.Client#subscribe()

实际代码
const topic =  {
      subscribe: ['SUBSCRIBE_TOPIC/noticePC/', 'SUBSCRIBE_TOPIC/p2p'],
      unsubscribe: 'SUBSCRIBE_TOPIC/noticeMobile/',
};
const config = { qos:1 };
this.client.subscribe(topic.subscribe, config)
源码分析
MqttClient.prototype.subscribe = function () {
  var packet
  var args = new Array(arguments.length)
  for (var i = 0; i < arguments.length; i++) {
    args[i] = arguments[i]
  }
  var subs = []
   // obj为订阅的topic列表
  var obj = args.shift()
  // qos等配置
  var opts = args.pop()
  var defaultOpts = {
    qos: 0
  }
  opts = xtend(defaultOpts, opts)
  // 数组类型的订阅的topic列表  
  if (Array.isArray(obj)) {
    obj.forEach(function (topic) {
      if (!that._resubscribeTopics.hasOwnProperty(topic) ||
        that._resubscribeTopics[topic].qos < opts.qos ||
          resubscribe) {
        var currentOpts = {
          topic: topic,
          qos: opts.qos
        }
        // subs是最终的订阅的topic列表
        subs.push(currentOpts)
      }
    })
  }
  // 这个packet很重要
  packet = {
    // 发出订阅命令
    cmd: 'subscribe',
    subscriptions: subs,
    qos: 1,
    retain: false,
    dup: false,
    messageId: this._nextId()
  }
  // 发出订阅包
  this._sendPacket(packet)
  return this
}

发送消息 mqtt.Client#publish()

实际代码
const topic = {
      publish: 'PUBLISH_TOPIC',
};
const messge = {
   foo: '',
   bar: '',
   baz: '',
   ...
}
const msgStr = JSON.stringify(message);
this.client.publish(topic.publish, msgStr);

注意publish的消息需要使用JSON.stringify进行序列化,然后再发到指定的topic。

源码分析
MqttClient.prototype.publish = function (topic, message, opts, callback) {
  var packet
  var options = this.options
  var defaultOpts = {qos: 0, retain: false, dup: false}
  opts = xtend(defaultOpts, opts)

  // 将消息传入packet的payload
  packet = {
    cmd: 'publish',
    topic: topic,
    payload: message,
    qos: opts.qos,
    retain: opts.retain,
    messageId: this._nextId(),
    dup: opts.dup
  }
  // 处理不同qos
  switch (opts.qos) {
    case 1:
    case 2:
       // 发出publish packet
       this._sendPacketI(packet);
        ...
    default:
       this._sendPacket(packet);
        ...
  }
  return this
}

接收消息 mqtt.Client “message”事件

实际代码
this.client.on('message', callback);

数据以callback的方式接收。

function (topic, message, packet) {}

topic代表接收到的topic,buffer则是具体的数据。
message是接收到的数据,谨记通过JSON.parse()对buffer做解析。

handleMessage(callback) {
    this.client.on('message', callback);
}
this.client.handleMessage((topic, buffer) => {
  let receiveMsg = null;
  try {
   receiveMsg = JSON.parse(buffer.toString());
  } catch (e) {
   receiveMsg = null;
  }
  if (!receiveMsg) {
    return;
  }
  ...do something with receiveMsg...
});
源码分析

MqttClient继承了EventEmitter。
从而进行可以使用on监听“message”事件。

inherits(MqttClient, EventEmitter)

那么到底是在哪里间发出message事件的呢?>emit the message event

  1. 基于websocket-stream建立websocket连接
  2. 使用pipe连接基于readable-stream.Writable创建的可写流
  3. nextTick调用_handlePacket
  4. 在handlePacket中调用handlePublish发出message事件
1.基于websocket-stream建立websocket连接
this.stream = this.streamBuilder(this)
function streamBuilder (client, opts) {
  return createWebSocket(client, opts)
}
var websocket = require('websocket-stream')
function createWebSocket (client, opts) {
  var websocketSubProtocol =
    (opts.protocolId === 'MQIsdp') && (opts.protocolVersion === 3)
      ? 'mqttv3.1'
      : 'mqtt'

  setDefaultOpts(opts)
  var url = buildUrl(opts, client)
  return websocket(url, [websocketSubProtocol], opts.wsOptions)
}
2. 使用pipe连接基于readable-stream.Writable创建的可写流
var Writable = require('readable-stream').Writable
var writable = new Writable();
this.stream.pipe(writable);
3.nextTick调用_handlePacket
writable._write = function (buf, enc, done) {
    completeParse = done
    parser.parse(buf)
    work()
}
function work () {
    var packet = packets.shift()
    if (packet) {
      that._handlePacket(packet, nextTickWork)
    }
}
function nextTickWork () {
    if (packets.length) {
      process.nextTick(work)
    } else {
      var done = completeParse
      completeParse = null
      done()
    }
}
4. 在handlePacket中调用handlePublish发出message事件
MqttClient.prototype._handlePacket = function (packet, done) {
  switch (packet.cmd) {
    case 'publish':
      this._handlePublish(packet, done)
      break
   ...
}
// emit the message event
MqttClient.prototype._handlePublish = function (packet, done) {
  switch (qos) {
    case 1: {
      // emit the message event
        if (!code) { that.emit('message', topic, message, packet) }
    }
}

参考资料:

  • https://cloud.tencent.com/developer/news/313537
  • https://github.com/mqttjs/MQTT.js
  • https://help.aliyun.com/document_detail/42420.html?spm=a2c4g.11186623.4.5.7bd4d07a16OtMV
  • https://help.aliyun.com/document_detail/96176.html?spm=a2c4g.11186623.2.13.4a6571d7y9NyuA#concept-96176-zh

期待和大家交流,共同进步,欢迎大家加入我创建的与前端开发密切相关的技术讨论小组:

  • SegmentFault专栏:[趁你还年轻,做个优秀的前端工程师](https://segmentfault.com/blog/chennihainianqing
  • Github博客: 趁你还年轻233的个人博客
  • 微信公众号: 大大大前端 / excellent_developers

努力成为优秀前端工程师!

嵌入式JavaScript混合开发:C与JS高效互调实践指南 在嵌入式系统开发中,跨语言编程是连接底层硬件控制与上层应用逻辑的关键技术。其核心原理在于通过桥接机制实现不同语言运行时环境间的安全通信,涉及类型转换、内存管理和线程安全等底层交互。这项技术的核心价值在于充分发挥C语言对硬件的直接操控能力与JavaScript快速开发迭代的优势,从而在资源受限的嵌入式平台上构建出既稳定高效又灵活可扩展的应用。典型的应用场景包括需要复杂用户交互的物联网设备、智能硬件以及工业人机界面(HMI)。本文聚焦于嵌入式JavaScript混合开发中的核心挑战,深入探讨了在微控制器上实现C 阅读详情

相关推荐

使用JavaScript获取设备的唯一ID

在JavaScript中,我们可以使用不同的方法获取设备的唯一ID。这个唯一ID可以用于识别设备、跟踪用户或进行其他设备相关的操作。下面是一种常见的方法来获取设备的唯一ID。中的,如果用户清除了浏览器的缓存或使用隐私模式访问网站,设备ID可能会丢失。因此,在使用设备ID进行重要操作时,最好采取其他更可靠的方法来确保唯一性。这种方法的优点是简单且快速,但并不是完全唯一的。请注意,由于浏览器的安全性限制,JavaScript无法直接访问设备的硬件信息来获取唯一ID。需要注意的是,由于设备ID是存储在。

TechNovaX的博客 3995

MQTT.js 入门教程

简介 MQTT.js 是一个开源的 MQTT 协议的客户端库,使用 JavaScript 编写,主要用于 Node.js 和 浏览器环境中。是目前 JavaScript 生态中使用最为广泛的 MQTT 客户端库。 MQTT 是一种基于发布/订阅模式的轻量级物联网消息传输协议,可以用极少的代码和带宽为联网设备提供实时可靠的消息服务,它广泛应用于物联网、移动互联网、智能硬件、车联网、电力能源等行业。 由于 JavaScript 单线程特性,MQTT.js 是全异步 MQTT 客户端,MQTT.js 支持 M

emqx_broker的博客 1万+

rocketmq-client-nodejs:Apache RocketMQ Node.js客户端

适用于Node.js的RocketMQ客户端 这个官方的Node.js客户端是围绕 (一种经过微调的CPP客户端)的轻量级包装。 注意1:此客户端仍处于dev版本。 在生产中请谨慎使用。 注意2:该SDK现在仅支持macOS和Ubuntu 14.04 。 不支持Ubuntu 16+,尚未对CentOS进行测试。 安装 $ npm install --save apache-rocketmq 例子 您可以查看和以获得快速。 用法 首先需要此软件包。 const { Producer , PushConsumer } = require ( "apache-rocketmq" ) ; 制片人 建设者 new Producer ( groupId [ , instanceName ] [ , options ] ) ; Producer的构造函数接收三个参数: groupId :生产

JS 连接MQTT的方法(mqtt.js的使用方法)

本文章是介绍 mqtt.js 的使用方法 本文章使用的版本是 4.1.x ,没用最新版的原因是 4.2.x 以上版本会报错,具体报错可以看我的另一篇文章。 使用的 4.1.x 版本地址:https://cdn.bootcdn.net/ajax/libs/mqtt/4.1.0/mqtt.min.js 如果遇到 无法连接/错误提示 WebSocket connection to …… 的问题,请看我另一篇文章,其中记录了我多次用到,遇见的连接问题。

qq_17627195的博客 3万+

智能车竞赛新手必看:用AD21从零画一块英飞凌TC264核心板(附开源PCB文件)

本文详细介绍了使用Altium Designer 21(AD21)从零开始设计英飞凌TC264核心板的完整流程,涵盖原理图绘制、PCB布线到最终DRC检查的全过程。针对智能车竞赛新手,提供了实用的硬件设计技巧和开源PCB文件,帮助快速掌握TC264核心板开发。

weixin_27017211的博客 246

从FinFET到NanoSheet:一文看懂TSMC制程技术的架构革命与性能飞跃

本文深入解析了TSMC从FinFET到NanoSheet的制程技术架构革命。FinFET通过三维立体结构解决了短沟道效应,而NanoSheet采用环绕栅极设计,实现了更强的静电控制与设计灵活性,结合EUV光刻技术,共同推动了芯片性能与能效的飞跃,为下一代AI与高性能计算奠定基石。

i3j4k5的博客 288

mqtt 发送消息过多_物联网宠儿mqtt.js那些事儿

常见的mq有Kafka,RocketMQ和RabbitMQ,大家也很常见。 前者很常见,MQTT是什么呢?MQTT属于IoT也就是物联网的概念。常见的mq有Kafka,RocketMQ和RabbitMQ,大家也很常见。MQTT是什么呢?Kafka,RocketMQ和RabbitMQ属于微服务间的mq,而MQTT则属于IoT也就是物联网的概念。mqtt.js是MQTT在nodejs端的实现。vue技...

weixin_39661881的博客 993

基于DE2-115红外解码实验

基于DE2-115红外解码实验   一、   功能描述 在同一个遥控电路中通常要使用实现不同的遥控功能或区分不同的机器类型, 这样就要求信号按一定的编码传送,编码则会由编码芯片或电路完成。对应于编码芯片通常会有相配对的解码芯片或包含解码模块的应用芯片。在实际的产品设计或业余电子制作中,编码芯片并一定能完成我们要求的功能,这时我们就需要了解所使用的编码芯片到底是如何编码的。只有知道编码方式,我...

乘风的博客 2515

js获取pc唯一标识_物联网宠儿mqtt.js那些事儿

常见的mq有Kafka,RocketMQ和RabbitMQ,大家也很常见。 前者很常见,属于微服务间的mq。那么MQTT是什么呢?MQTT属于IoT也就是物联网的概念。 快来和使用mqtt.js开发IM功能2年的作者一探究竟吧~先来看下MQTT在物联网领域的应用场景: mqtt.js是MQTT在nodejs端的实现。通过npm package.json包管理,现代vue技术栈下的前端也可用,比如...

weixin_30306285的博客 1066

基于STM32与HRTIM的四开关Buck-Boost双向DC-DC电源设计实战(附源码、仿真与设计解析)

本文详细介绍了基于STM32F334的HRTIM高分辨率定时器实现四开关Buck-Boost双向DC-DC电源的设计实战。通过精准的PWM控制、双环PID算法和智能模式切换逻辑,解决了电压震荡与效率优化等关键问题,并提供了完整的源码、PSIM仿真及参数计算,为高性能电源设计提供了实用参考。

7z8x2c4v6b9的博客 299

华为的LTC(Lead to Cash,从线索到现金)流程是其销售管理体系的核心,覆盖了从发现销售线索到最终收回现金的全过程,强调端到端的业务贯通和以客户为中心的运营理念

华为LTC流程是覆盖销售全周期的管理体系,包含四大阶段:线索转机会(LTO)、机会转订单(OTO)、订单转交付(OTD)、交付转现金(DTC)。其核心采用"铁三角"团队模式(AR/SR/FR协作),通过多部门联合评审把控关键节点,实现端到端业务贯通。该流程与IPD、MTL、ITR等体系高效协同,结合iSales平台实现数字化管理,有效提升销售效率、客户满意度和资金回笼速度。

金牌架构师 1720

MQTT.js 简述

MQTT是一种轻量级的消息传输协议,常用于物联网(IoT)设备间的通信。mqtt.js是一个 JavaScript 库,支持在 Node.js 和浏览器中使用,用于通过 MQTT 协议与 MQTT Broker 进行通信。

m0_67793437的博客 3587

麒麟V10安装图形化界面

在配置VNC时发现,原本麒麟V10系统最小化安装,导致无图形化界面,先需要对其进行安装。 首先确保无图形化界面,可以在终端输入startX命令查看是否报错。 安装介绍: 1、 安装图形化界面 yum grouplist //查看可用yum安装组 注:这里一般会有缺少包或者出现包不符合的问题 导入软件包分组信息文件xxxx-comps.xml arm: 将此文件传送到源服务器, 然后createrepo -g导入到arm的base目录和updates目录 createrepo -g e33dc

Pro_jhf的博客 8071

学习笔记:MQTT.js 入门教程

如果不同的设备使用相同的clientID同时连接物联网平台,那么先连接的那个设备会被强制断开。不能相同,服务器连接的客户端clientID必须唯一,不然就会挤掉其他的客户端。(1)两个客户端(mqtt.jsMQTTX)连接到同一个服务器。2、在VSCode中打开,新开一个。(3)【MQTTX客户端】的。,和【mqtt.js客户端】的。,在【mqttx.js客户端】........................

long_steve的博客 3310

5-EP4CE10F17C8-引脚配置

EP4CE10F17C8-引脚配置

weixin_44479192的博客 719

基于NSGA2算法的无人机三维路径规划MATLAB实现

传统的路径规划方法多采用启发式搜索算法,然而这些方法往往带着局限性,不能有效地克服无人机飞行任务中所遇到的复杂环境与约束。而基于遗传算法的NSGA2(Non-dominated Sorting Genetic Algorithm II)方法则可以在优化目标之间找到最好的平衡点,是一种十分优秀的解决方案。本文介绍了基于NSGA2算法的无人机三维路径规划MATLAB实现。NSGA2算法是一种多目标优化算法,通过非支配排序和拥挤度距离来评估个体的适应度和选择新个体,从而产生一组非支配解。3.选择新个体组成P1;

CyberLynxX的博客 982

js 获取设备或浏览器唯一标识的方式

网上的一些回复有很多,反正就是获取不到h5的机器码,或者mac地址,所以只能获取浏览器唯一标识。 fingerprint获取的方式,代码: const fpPromise = new Promise((resolve, reject) => { const script = document.createElement('script') script.onload = resolve script.onerror = reject script.async =

PrimaryColor 1万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

JavaScript使用MQTT

提供mqtt在javascript上的应用实例。

baidu_34785556的博客 8900

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

mqtt.js

什么是MQTT协议 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的“轻量级”通讯协议,该协议构建于TCP/IP协议上,由IBM在1999年发布。 MQTT特点 MQTT是一个基于客户端-服务器的消息发布/订阅传输协议,最大优点在于,用极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。 做为一种低开销、低带宽占用的即时通讯协议,使其在物联网、小型设备、移动应用等方面有较广泛的

qq_42179237的博客 6478

JS生成浏览器唯一标识解决方案

浏览器唯一摘要

gltncx11的博客 1万+

【亲测免费】 探秘 MQTT.js:一款强大的 MQTT 客户端库

MQTT.js 是一个由 Adam R. Vaughn 开发并维护的 JavaScript 库,它为 Web 和 Node.js 平台提供了轻量级、高效的 MQTT 协议客户端实现。让你可以直接查看源代码和参与社区。MQTT.js 允许开发者轻松地在各种应用中集成 MQTT 发布/订阅消息传递协议,从而实现设备间的实时通信。 ## 技术分析 ### MQTT 协议 MQTT(Message ...

gitblog_00013的博客 706

什么是MQTT协议与JS使用MQTT

官方的说法:轻量级的物联网通信协议,基于发布/订阅模式,支持QoS级别,适用于低带宽高延迟的网络环境。在MQTT中,有三个核心角色扮演着重要的角色:代理服务器(Broker)、订阅者(Subscriber)和发布者(Publisher)。举个栗子:以B站为例,B站本身就是一个Broker黑马程序员,他每天都会更新发布视频,黑马程序员就是一个Publisher,而你作为B站用户觉得黑马程序员的视频讲的很不错,就关注了他,此时你这个B站用户就是Subscriber。

fakeend的博客 2893

MQTT:前端js客户端库MQTT.js ----亲测有效

MQTT.js (opens new window)是 JavaScript 编写的,实现了 MQTT 协议客户端功能的模块,可以在浏览器 和 Node.js 环境中使用。浏览器环境:MQTT over WebSocket(包括微信小程序、支付宝小程序等定制浏览器环境)Node.js 环境:MQTT、MQTT over WebSocket。不同环境里除了少部分连接参数不同,其他 API 均是相同的。MQTT:前端js客户端库MQTT.js。

qq_44170358的博客 1244

MQTT.js

mqtt.js是一个开源的MQTT协议的客户端库,使用 JavaScript 编写,主要用于 Node.js 和 浏览器环境中。是目前 JavaScript 生态中使用最为广泛的 MQTT 客户端库。MQTT 是一种基于发布/订阅模式的轻量级物联网消息传输协议,可以用极少的代码和带宽为联网设备提供实时可靠的消息服务。

qq_48192192的博客 1471

Mqtt.js 文档

MQTT.js is a client library for the MQTT protocol, written in JavaScript for node.js and the browser. Upgrade notes Installation Example Command Line Tools API Browser Weapp About QoS TypeScript Con...

python_LC_nohtyp的博客 5204
上一篇: 如何处理浏览器的断网情况?
下一篇: 前端通信那些事儿
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

趁你还年轻233

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值