这是个有趣的话题!
先来聊几个小故事。
我在人生第一个IoT项目里,第一次接触到MQTT协议。
我很快就理解了这个协议。因为,它和企业开发用的MQ产品实在是太像了。
在我职业生涯早期,是的,20年前,当时做一个银行的项目,就用过MQ这东西,那个项目使用了IBM MQ。随着工作经验的增加,在另外一些项目中,也会接触使用到MQ产品。
后来,我在做国产中间件的公司里开发中间件,当时我们有个团队,专门在做MQ产品。
所以,当我第一次读MQTT资料的时候,我心里立马浮现出了这样的看法:这不就是一个轻量级的、给IoT应用使用的MQ吗。
我和XMPP之间的故事要复杂很多。
那是中国电信的一个项目,电信想在手机里集成融合通信软件。运营商的思路也很直白,微信你不是牛逼吗,你用互联网短信来代替我的电信网短信、用互联网音视频来取代我的电信通话网络,夺取我的生意,抢夺我的通道。我们运营商必须反击,我们必须要有应对的解决方案!
当时中国电信想到的解决方案之一,就是手机内置融合通信软件。
简单点说,运营商每年要送出很多的手机,办套餐送手机,这是运营商常用的营销套路。运营商的思路,如果这个送的手机,用户拿到手里的时候,它就已经自带了微信所有的功能了,那为啥还要另外再安装一个微信呢?
在手机里预置电信运营商开发的一个软件,这个软件具有微信所有的功能,功能被直接紧密集成在手机电话簿里,用来和联系人来发信息、聊天、语音和视频了,走互联网通道。
这个电信运营商想内置在手机里替代微信的软件,被叫做融合通讯软件。
因为要做中国电信的这个项目,我第一次接触到了XMPP协议。
后面的故事不出所料,融合通讯软件并未能掀起风浪,微信依然被安装在每一台手机上。
是的,我和XMPP的情缘,从那时候开始了。
在这个电信的项目中,我使用了Openfire XMPP Server,这应该是Java界最出名的一个开源XMPP服务器了。
Openfire作为一个标准的XMPP Server,其实它还挺可以的。在开发项目过程中,我当然会读它的代码,我会时不时发出感慨:老外写代码还真是挺认真的!
老外写东西,真的是认真!但是Openfire开源XMPP服务器,它并不能让我满意。
融合通信软件,当然会有不少需要定制的功能。但是,看看下面这段摘自Openfire的源码,就应该会明白,为啥我并不是那么的满意。
以下代码,来自Openfire项目src/main/java/org/jivesoftware/openfire/XMPPServer.java文件。
... ...
private void loadModules() {
// Load boot modules
loadModule(RoutingTableImpl.class.getName());
loadModule(AuditManagerImpl.class.getName());
loadModule(RosterManager.class.getName());
loadModule(PrivateStorage.class.getName());
// Load core modules
loadModule(PresenceManagerImpl.class.getName());
loadModule(SessionManager.class.getName());
loadModule(PacketRouterImpl.class.getName());
loadModule(IQRouter.class.getName());
loadModule(MessageRouter.class.getName());
loadModule(PresenceRouter.class.getName());
loadModule(MulticastRouter.class.getName());
loadModule(PacketTransporterImpl.class.getName());
loadModule(PacketDelivererImpl.class.getName());
loadModule(TransportHandler.class.getName());
loadModule(OfflineMessageStrategy.class.getName());
loadModule(OfflineMessageStore.class.getName());
loadModule(VCardManager.class.getName());
// Load standard modules
loadModule(IQBindHandler.class.getName());
loadModule(IQSessionEstablishmentHandler.class.getName());
loadModule(IQPingHandler.class.getName());
loadModule(IQBlockingHandler.class.getName());
loadModule(IQPrivateHandler.class.getName());
loadModule(IQRegisterHandler.class.getName());
loadModule(IQRosterHandler.class.getName());
loadModule(IQEntityTimeHandler.class.getName());
loadModule(IQvCardHandler.class.getName());
loadModule(IQVersionHandler.class.getName());
loadModule(IQLastActivityHandler.class.getName());
loadModule(PresenceSubscribeHandler.class.getName());
loadModule(PresenceUpdateHandler.class.getName());
loadModule(IQOfflineMessagesHandler.class.getName());
loadModule(IQPEPHandler.class.getName());
loadModule(IQPEPOwnerHandler.class.getName());
loadModule(MulticastDNSService.class.getName());
loadModule(IQSharedGroupHandler.class.getName());
loadModule(AdHocCommandHandler.class.getName());
loadModule(IQPrivacyHandler.class.getName());
loadModule(DefaultFileTransferManager.class.getName());
loadModule(FileTransferProxy.class.getName());
loadModule(MediaProxyService.class.getName());
loadModule(PubSubModule.class.getName());
loadModule(IQDiscoInfoHandler.class.getName());
loadModule(IQDiscoItemsHandler.class.getName());
loadModule(UpdateManager.class.getName());
loadModule(InternalComponentManager.class.getName());
loadModule(MultiUserChatManager.class.getName());
loadModule(IQMessageCarbonsHandler.class.getName());
loadModule(ArchiveManager.class.getName());
loadModule(CertificateStoreManager.class.getName());
loadModule(EntityCapabilitiesManager.class.getName());
loadModule(SoftwareVersionManager.class.getName());
loadModule(SoftwareServerVersionManager.class.getName());
// Load this module always last since we don't want to start listening for clients
// before the rest of the modules have been started
loadModule(ConnectionManagerImpl.class.getName());
loadModule(ClusterMonitor.class.getName());
// Keep a reference to the internal component manager
componentManager = getComponentManager();
}
... ...
服务器装载的模块功能(Modules),居然是被硬编码写死的!!!
好吧,我承认,在那个项目中,我改过Openfire的源码,为了把项目定制的功能加到服务器中去。
帮客户做项目嘛,能够达到项目目标,能够按期交付,把款收回来就可以了啊!你还想干嘛?
我还想干嘛,是的,我还想干嘛?
在那个疯狂的年月,我想说,这个行业里,人人都会有个互联网英雄梦!
我也有梦,我有个社交领域的创业梦,我想去试试做这件事,干这事需要使用实时通讯技术。
于是,我开始开始读XMPP规范,我读RFC3920(XMPP Core)、RFC3921(XMPP IM)、XEP-045(Multi-User Chat)… …
读了一些规范之后,我得出这样的结论,Openfire恐怕达不到我的创业要求,我最好是自己来写一个XMPP Server。
当然,凭我的技术能力,只要我愿意,我可以去改Openfire的代码,最终也可以实现创业项目的功能需求。
问题是,在那时,对,这时候说的那时,已经是在10年前。在那时,我还是如此的理想化,如此对未来充满了憧憬,我觉得自己可以干翻一切,何况只是需要去实现一个实时通讯协议标准和产品。
我可以搞定,我会做得很好!就这样定了,自己动手写一个。
于是,有了Basalt、Chalk、Granite这一系列XMPP基础架构项目。
2年后,我去尝试了自己的梦,使用XMPP来做自己的社交App项目。
项目最终失败了,这些XMPP的代码,也暂时被封存在了代码仓库里。
春去秋来,潮起潮落,时光飞逝。
2018年,我来到了一家做IoT的创业公司做CTO。我是第一次做IoT项目,我认真上网查资料,理解技术,设计系统。
由于是第一次做IoT项目,我非常谨慎的选择了技术方案。在网关到互联网服务器之间的互联网通讯协议选择上,我选择了使用MQTT,看上去这是一个大众流行的,也比较安全的解决方案。
产品做出来了,我们开始做推广,完善产品,继续融资,扩大推广。
其实那次,我们已经有点接近成功了。我们部署了3.5k智能锁节点,融了Pre-A轮1600w。机构方说,你们下一阶段的工作,就是1w个节点,然后融A轮,公司A轮估值不低于2亿,后续融资的事你们不用管,我们会搞定一切,你们就专心努力完成业绩要求。
然而,在经历一系列的决策错误后,创业最终失败了… …
我又在思索了,在自己做社交创业失败后,我又呆了两家创业公司,做技术合伙人。一家做到A轮,一家做到Pre-A轮。然而,这两家公司最终都失败了。
因为这两家创业公司,我放弃了去阿里巴巴的工作机会,也放弃了到一家银行工作的机会(给的offer总包年薪超100w)。
我在重新思考自己的方向,毕竟年龄也不小了,我应该寻求稳定不是吗?
我选择了一家上市公司的中央研究院,他们的项目,又是IoT,做智慧城市里的智慧路灯杆。
我和IoT之间,情缘未了!
我对MQTT还是非常熟悉的,我用它做过IoT应用,开发过IoT产品。
我对XMPP应该说算是精通了,我写过XMPP基础开发库、XMPP服务器、实现过XMPP的各种标准,并基于XMPP做了了IoT开发平台。
我尝试客观的来评价这两种协议,如果抛开我更擅长XMPP,以及Lithosphere基于XMPP技术开发的主观立场,我如何评价这两种协议呢?
以下两种协议的对比,包括对两种协议的优劣点评价,以及针对协议缺点的解决方案讨论,都基于我个人观点。受个人知识面和经验的限制,如果有评价不准确,没找对好的解决方案思路等问题,请网友们给予批评指正。
交流,就是想跟大家交流,分析问题,寻求答案,不在于争论对错,而是想找到对两种协议客观、正确的理解。
轻量级,性能好
MQTT协议被设计得轻巧且高性能,最小MQTT的协议包尺寸为2字节。
内置QoS支持
MQTT协议内置3种QoS:
简单、容易学习
我大概看了一下午的资料后,就基本上理解清楚了MQTT协议,然后开始分析设计在IoT项目里该怎样用它了。
缺少P2P通讯机制
MQTT客户端并没有一个全局的、持久性的唯一Client ID,MQTT客户端的Client ID在每次连接到Broker时,由客户端指定或由Broker来自动生成。
那么,当我们想想做特定客户端的指令控制类型操作时,就会比较不方便了,因为:
解决方案讨论:
比较常见的解决方案是,为每个客户端,创建一个和客户端Client ID相关的,私有专用的消息接收Topic,用于接收发送给这个客户端的的消息。
例如,我们约定,当客户端程序连接Broker成功后,客户端程序会立即开始监听名为Clients/
在这个约定下,一个客户端连接成功后,如果它的Client ID是"1234567890",那么客户端连接成功后,这个客户端就开始监听名为"Clients/1234567890"的Topic。那么往这个Topic里publish的消息,这个客户端就可以收到。
需要考虑的一个问题是安全性问题,因为我没有在MQTT的规范里,读到有关于主题订阅的权限限制的内容。那么,一个客户端在理论上,是可以监听到其它客户端的私有专用消息通道的。也许可以考虑给私有消息都用私钥加密,来提供更好的安全性。
没有应用层协议
MQTT提供了一条通讯层的通道,你可以用这个通道来传输任何格式的数据。
这个东西有利有弊吧,有利的地方在于灵活性,开发者可以自由的定义任何格式的应用层协议,不受任何规则限制。不利的地方在于,大部分应用开发者,其实并没有足够的知识和经验,可以设计出足够好的应用层协议。
实时性差
消息实时性和数据可靠性,这两个特性看上去是鱼与熊掌,往往需要我们做出选择与权衡。
在MQTT中,设置了QoS.AT_LEAST_ONCE和QoS.EXACTLY_ONCE的消息,实时性会比较差。
我们在智能锁的项目里,曾做过以下的测试。
我们保持移动端和服务器端之间的通讯畅通,断开服务器到锁终端设备之间的通讯通道。
然后我们从App端发送开锁指令给锁终端,由于通讯线路被断开,这时锁是不能被打开的。
2分钟之后,我们将和服务器端和锁终端设备之间的通讯线路恢复正常,这时候,锁被打开了。
解决方案讨论:
提供P2P通讯机制
在XMPP网络中,任何需要连接到XMPP服务器的节点(Node),无论它是人(User)或者是物(Thing),都需要有一个全局的XMPP账号。在XMPP概念里,这个账号叫做Jabber ID。
使用联系人/物的Jabber ID,就可以给它发送直接消息(前提为权限允许,例如:联系人在好友列表中)。
对于远程控制类型的IoT应用来说,这简直太方便了。
实时性强
XMPP就是一个实时通讯协议,实时性强是它的协议特征。
在一些IoT应用场合,我们就是需要更好的消息实时性。
我一条控制指令发过去,指令正确到达且正确执行了,你就返回正常执行确认;如果执行失败,你就返回对应错误码;如果不能确认执行结果,请告诉我超时了,让程序来处理超时逻辑。
无论啥情况,请立马告诉我,而不是2分钟后再突然执行指令。Ok,这就是我们需要的实时性。
以下的代码来自Lithosphere的sand-demo,它示范了这种实时性需求。
... ...
private static class RemotingActionCallback implements IRemoting.Callback {
... ...@Override
public void executed(Object xep) {
// Code for action has executed correctly.
activity.runOnUiThread(() -> Toast.makeText(activity,
"Action has executed.",
Toast.LENGTH_LONG).show());
}
@Override
public void occurred(StanzaError error) {
// Code for error occurred.
String errorText = "Action execution error: " +
(error.getText() == null ? error.toString() : error.getText().getText());
remotingErrorOccurred(activity, error, errorText);
}
@Override
public void timeout() {
// Processing logic for timeout.
activity.runOnUiThread(() -> Toast.makeText(activity,
"Action execution timeout.",
Toast.LENGTH_LONG).show());
}
}
协议扩展性强,内置应用层通讯协议基础规则
XMPP和MQTT的设计思路有些区别。
MQTT协议的关注点,在于如何在网络层提供一条可信赖通道。然后吧,你愿意在这个通道上做啥就做啥,我协议是不管你任何应用层的事情的。
XMPP的协议特征之一,是具有很强的可扩展性。XMPP全称Extensible Message and Presence Protocol。XMPP里的X,是Extensiable(可扩展)的意思,表达了XMPP协议的这个协议特征。
XMPP协议被分成两部分,一部分是核心标准规范,包括XMPP Core(RFC3920)和XMPP IM(RFC3921)。
另一部分是XMPP的扩展协议,XEPs(XMPP Extension Protocols)。XEPs协议族里,包含了大概300多个协议,这些协议覆盖的内容范围,简直包罗万象。这当然证明了XMPP协议的超强扩展性特征。
XMPP协议族覆盖的内容很多,既包含了网络层的协议,也包括应用层协议。
例如,User Avatar(XEP-0084)。这个协议当然是一个应用层协议,这个规范定义了在实时通讯系统中,用户虚拟身份使用的解决方案。
在XMPP的标准规范XMPP Core(RFC3920)中,定义了XMPP协议的一堆基础规则,包括:
好吧,你当然可以认为,这么多规则,严重限制了开发者的想象力嘛!
我会这样认为,这是设计出色的应用层通讯协议的一个良好基础。
基于XML,通讯效率差
这应该是XMPP协议受到最多攻击的一个问题了。XMPP太重了,XMPP不适合移动互联网,更不适合物联网。
解决方案讨论:
在通讯中,使用流压缩协议
可以考虑实现官方XEPs协议里的Stream Compression(XEP-0138),或者实现自己的流压缩私有协议。
实现二进制XMPP
这是目前我能看到的最佳解决方案。
一个公司给我们做出了最佳示范!是的,WhatsApp使用标准XMPP的二进制变种(WhatsApp公司把这个二进制变种协议叫做FunXMPP)来提供全球20亿用户的IM服务。
好吧,就我知道的,还有另外一个公司,也使用了二进制XMPP。Apple公司使用XMPP的二进制变种协议来提供APNs(Apple Push Notification service),为全球IPhone手机提供服务器端推送服务。
请问开源二进制XMPP实现?
开源二进制XMPP实现,请考虑使用Lithosphere平台里的Basalt,Chalk,Granite。
好吧,我知道的就只有这么多了,如果其他网友知道其它开源项目的二进制XMPP协议支持,还请不吝赐教!
缺少内置的QoS支持
MQTT是一个轻量级的MQ,QoS基本上是MQ软件的标配,MQTT也不例外。
XMPP由RFC标准协议加上XEPs组成,在RFC标准协议中,并没有要求提供QoS支持。
对于数据上报类型的IoT应用,QoS是非常必要的。
解决方案讨论:
实现QoS协议
XMPP的XEPs里,目前还缺少关于QoS的正式标准。
可以看到有一个草稿标准Quality of Service(XEP-xxxx)。需要注意的是,这个标准目前的状态,还是XEPs的草稿标准(ProtoXEP)状态,这表示这个规范还未能通过XSF(XMPP Standards Foundation/XMPP标准基金会)的标准审批过程。
我读了一下这个XMPP的QoS草稿标准,这个规范里的XMPP QoS实现,看上去和MQTT规范里要求的QoS实现,几乎没有什么区别。
区别只在于,两个协议的QoS控制指令的术语叫法不一样。比如:
虽然这只是一个草稿标准,但是由于这个XMPP标准对应的QoS处理逻辑,看上去和MQTT标准里的QoS实现逻辑,几乎没有什么区别。理论上,可以认为,实现这个XMPP草稿规范后,就可以为你的XMPP实现提供QoS支持了。
缺少IoT相关规范和开源产品实现
XMPP社区的伙计们,有在积极的探索XMPP在IoT领域的应用,我们可以看到社区在这个方向上的一些工作,比如:
但是目前的状况看上去,XMPP虽然在实时通讯领域取得了很大的成功,但是在IoT应用领域,XMPP还是小众技术。
IoT方向上相关的标准规范,都还是草稿状态,并没有进入正式的标准化过程。
在开源产品实现上,做了IoT支持的开源产品还比较少,而且实现都还比较不完善。我能看到的,以下XMPP开源产品有提供IoT相关的功能:
实现较为复杂,学习成本高
XMPP和MQTT,在协议的设计思路上,有着比较大的差异。
MQTT:Hi,朋友!我会给你一个速度快、简单好用、安全可靠的通讯通道。Ok,我的工作做完了!你愿意在上面干嘛就干嘛,我是不管的,请别再来找我了。
XMPP:我们会提供一个灵活、强大的网络通讯协议,它的灵活性来自高扩展性,它的强大来自我们提供了几百个实时通讯相关标准。我们希望这一把能彻底搞定实时通讯领域的各种问题!
什么,还缺少IoT相关标准?缺少IoT开源产品实现?目前就是这状况哦!请你深刻理解XMPP技术,自行定义私有IoT通讯协议来解决问题。可以做到的!你放心,XMPP技术相当灵活!可以做到的!我们对你有信心!
和MQTT的完全自由有所不同,如果你使用XMPP协议,你需要遵循协议标准中的一些规则和要求。由于XMPP协议较MQTT协议复杂,功能更多,正常来说,会需要更多的入门学习时间。
从另外一个角度来看,如果是已有的XMPP协议规范,如果是第三方产品中已经实现了的XMPP扩展协议功能呢?那可是现成的东西直接拿来用起,爽不爽?
解决方案讨论:
等待
耐心等待XMPP开源项目为产品添加IoT相关的功能;期待XSF(XMPP Standards Foundation)能推动各种XMPP IoT协议的标准化。
自己动手干
已经有一些商业公司在用XMPP来干IoT了。例如,Google云通过Firebase Cloud Messaging (FCM) 来提供IoT云服务。它使用的就是XMPP协议。
大家都急切期待着功能强大的开源产品实现?
好吧,Lithosphere开源项目正在加油努力中… …
两个协议都可以用于IoT应用。这两个协议存在着明显的差异,不能说哪个是更好的,需要结合应用需求,团队技术能力和技术积累等各种因素,对技术选型进行综合考虑。
MQTT协议非常适合用在传感器网络为主,数据上报类型的应用中。MQTT的Public-Subscribe模式,以及QoS支持,似乎就是专门为这类型的应用来设计的。
所有的传感器设备,在上报数据中,只需要带上设备身份标识,带上数据采集时的时间戳,统一上报到数据处理的Topic通道去。
其它事,让服务器去干。
够用、简单好用,很爽!
XMPP的优势在于它的灵活性以及实时性。
如果你的IoT应用,会有复杂的通讯控制逻辑,以及有很高的实时性通讯需求,值得考虑XMPP。
MQTT最大优势,应该是它的简单易用性。能不能不要花那么多时间来学习通讯技术了,能不能尽快开始编码开搞应用需求?
MQTT的短板,似乎是它的基础架构只提供了较单一的通讯机制,当我们碰到一些通讯上的复杂需求时,我们需要做更多工作来解决问题。当然,我们可以:
可以在上层应用层,做一些辅助工作,来帮助解决应用的通讯复杂性。
MQTT目前在IoT这个方向上,是一个主流的协议。
各个使用MQTT协议的IoT服务厂商,会提供各种问题的设计模式、解决方案、甚至写好的开发组件来帮助客户。
应用开发商可以寻求IoT服务厂商的商业解决方案支持。
XMPP的优势在于它的灵活性。如果我有很复杂的通讯逻辑需要处理;如果我想在通讯层上面提供一个更易用的组件开发模型,XMPP可以帮你实现这些复杂需求。
但是需要考虑问题是,你真正理解和学会XMPP了吗,你能在自研的或者第三方XMPP基础件上,自由的开发XMPP扩展协议了吗?
两者都还不够好!
标准的MQTT,标准的XMPP,在IoT应用中都还不够好!不够用!不能够覆盖到IoT里各种复杂应用需求。我们往往需要在标准协议之上,再做很多的工作来解决问题。
连接万物,哪有这么简单!
都不够好,不够用
标准MQTT,标准XMPP,对于连接万物的IoT来说,都还不够好!不够用!
MQTT对于传感器数据上报类型的应用,把数据安全传输到服务器端,然后服务器端一步去做数据分析,去做大数据,搞AI。对于这种类型的应用来说,MQTT够用的。
对于一些更复杂的IoT通讯需求,MQTT的通讯机制太单一了,不够用,举两例子吧:
IoT本地网通讯
按照MQTT Specification里的说法,目前MQTT协议只能跑在TCP/IP(可选WebScoket)网路上。在IoT本地网如LoRa,Bluetooth… …这些协议上,MQTT跑不了。
下图截自MQTT 3.1.1 Specification
音视频流媒体通讯
由于在我做过的两个IoT应用中,都有实时流媒体的通讯需求。我会假设对实时流媒体通讯的支持,是IoT应用的刚性需求。
标准MQTT协议并不支持这个事,在MQTT协议上做这个事,也比较难做实现。
标准XMPP,也不够好!也不够用!缺少IoT标准,市场上的开源产品普遍缺少IoT功能的支持。
XMPP扩展性更好,更容易在协议层去做扩展功能
XMPP的协议特征之一,就是高扩展性。如果要选其中一个协议来做协议层的扩展,XMPP看上去会方便很多。
基于我自己写的XMPP开源基础件,我可以用XMPP做到任何事
这个肯定是最重要的因素了,最终决定了Lithosphere的通讯协议技术选型。
如果我当年不是因为想做社交App创业,去写了XMPP库,XMPP服务器。如果当年因为机缘巧合,我写了MQTT的开源项目,那我现在会怎么选择?
人生没有如果!
假设一下嘛,哈哈。
我想,我应该会选择做基于MQTT的IoT解决方案。
人生没有如果!我现在就是写了XMPP开源基础件,我就用这些XMPP基础件,写了Lithosphere。
XMPP太重了,不适合物联网?
那我做二进制XMPP支持。
XMPP标准中缺少QoS支持?
那我实现QoS扩展协议,MQTT可以有,为啥XMPP不可以有?
XMPP里缺少IoT的标准
这不叫事,XMPP可以写标准协议,也可以写私有协议。
Lithosphere目前已实现的部分IoT扩展通讯协议:
设备注册
TUXP:IBTR Protocol - 智能物件在线注册协议。
事件通知
TUXP:Notification Protocol - 智能物件事件通知协议。
远程指令控制
TUXP:Execution Protocol - 智能物件远程命令执行协议。
数据上报
TUXP:Report Protocol - 智能物件数据上报协议。
LoRa动态地址分配
TUXP:LoRa-DAC protocol - LoRa网络动态地址分配协议
实时视频监控
LEPs:WebRTC:Signaling Protocol - 基于WebRTC的实时流信号协议
… …
XMPP产品目前缺少对IoT本地网络协议的支持
就是让XMPP跑在LoRa上、跑在Bluetooth上、跑在Mudbus上,跑在… …上嘛,是吧?
没问题,别的产品不支持,Lithosphere来支持。Mud库就是用来干这事的。
Lithosphere是全栈的开发框架,不仅在互联网网关端到服务器端,Lithosphere还尝试对IoT应用中所有端提供支持。
基于统一的TUXP协议,Lithosphere可以覆盖到IoT应用的通讯所有端。
目前版本做了WiFi、LoRa协议实现,后续版本会陆续支持其它本地IoT网络协议。敬请期待!
不是狂,我可以用XMPP做到任何事情!
使用XMPP的效果如何?
哈哈,可以看看我写的Hello,Lithosphere系列教程,你来做评价。
如果是想要评估Lithosphere的功能和技术效果,建议看这两篇教程。
这个教程里覆盖了IoT协议的整个通讯流程,包括IoT终端设备集成(MCU板)、IoT LPWAN协议通讯(LoRa通讯协议)、IoT通讯网关、IoT通讯服务器端处理。
使用封装好的WebRTC的Webcam插件,做一个实时监控摄像头,这事还挺简单的。
关于MQTT vs. XMPP的话题,就聊这么多了!
手机扫一扫
移动阅读更方便
你可能感兴趣的文章