ZigBee技术概述

ZigBee技术的特点

  1. 数据传输率低,大约在20~250kbps;
  2. 网络容量大,一个主节点最多可以管理254个子节点,子节点还可以由上一层网络节点管理,可以组成拥有65000个节点的大网;
  3. 成本低、功耗低,只需1毫安,仅需2节5号电池即可维持6个月到24个月左右的使用时间;
  4. 安全、可靠,提供了数据包完整检查功能,避免数据的碰撞和冲突;
  5. 网络速度快、时延短,激活的时延仅为15毫秒。

ZigBee技术的适用条件

  1. 设备成本很低,传输的数据量很小;
  2. 设备体积很小,不便放置较大的充电电池或者电源模块;
  3. 没有充足的电源支持,只能使用一次性电池;
  4. 频繁地更换电池或者反复地充电无法做到或者很困难;
  5. 用于监测或控制且通信覆盖较大范围的网络。

ZigBee技术的应用实例

将ZigBee技术运用于传统农业中,可以使传统农业转变为以现代信息技术为中心的精准农业模式,让农业种植全面实现智能化网络化、自动化,从而进一步提高农业生产的效率。采用ZigBee技术进行组网,利用传感器采集土壤湿度、氮浓度、PH值、降水量、气温、气压、光照强度等信息;经由ZigBee网络传送到中央控制设备,并能对环境因子进行控制。

image-20240919165001333

ZigBee协议栈

ZigBee协议栈包含四个层次,即物理层、数据链路层、网络层和应用层,物理层和数据链路层由IEEE 802.15.4标准定义,网络层和应用层标准由ZigBee联盟制定。

物理层

物理层的任务是通过无线信道进行安全、有效的数据通信,为数据链路层提供服务。物理层的频段和信道如下图所示。

image-20240919165639260

image-20240919165642241

物理层通过射频固件和射频硬件提供了一个从MAC层到物理层无线信道的接口。在物理层中有数据服务接入点PD-SAP物理层管理实体服务接入点PLME-SAP,通过PD-SAP为物理层数据提供服务,通过PLME-SAP为物理层管理提供服务。

**介质接入控制层(media access control layer,简称MAC Layer)**在开放系统互连(OSI)模型的数据链路层中,负责多台计算机如何共享与网络的物理连接的子层。 在开放系统互连(OSI)模型的数据链路层中,负责多台计算机如何共享与网络的物理连接的子层

image-20240919172742634

数据链路层

数据链路层分为逻辑链路控制(LLC)子层介质接入控制(MAC)子层。LLC子层进行数据包的分段与重组以及确保数据包按顺序传输,MAC子层为两个ZigBee设备的MAC层实体之间提供可靠的数据链路。

image-20240919172916705

网络层

网络层是ZigBee协议栈的核心部分,其主要功能是确保 MAC 层的正确工作,同时为应用层提供服务。 具体包括网络维护、网络层数据的发送与接收、路由的选择、广播通信和多播通信等。

image-20240919173119782

应用层

应用层由应用支持子层(APS)厂商定义的应用对象(AF)、**ZigBee设备对象(ZDO)**三部分组成。ZigBee应用层除了为网络层提供必要的服务接口和函数,还允许应用这自定义应用对象

APS主要用于绑定ZigBee设备之间的传送信息并维护绑定信息;ZDO位于应用框架和APS之间,通过使用网络层和应用支持子层的服务原语来执行终端设备、路由器和协调器功能。

ZigBee协议栈

ZigBee协议栈由各层定义的协议组成,以函数库的形式实现,为编程人员提供应用层API。

Z-Stack协议栈采用分层的软件结构;硬件抽象层(HAL) 提供各种硬件模块的驱动;操作系统抽象层(OSAL)实现类似操作系统的某些功能;用户也可以调用OSAL提供的相关API进行多任务编程。

image-20240919173822723

ZigBee协议按照开放系统互联的7层模型将协议分成了一系列的层结构,各层之间通过相应的服务访问点来提供服务。ZigBee协议为了实现层与层之间的关联,采用了称为服务“原语”的操作。

ZigBee原语有四种类型:request请求原语;indication指示原语;response响应原语;confirm确认原语。

image-20240919174106982

ZigBee网络的拓扑结构

ZigBee设备类型

  1. 全功能设备

全功能设备(Full Function Device,FFD)具备控制器的功能,可设置网络。FFD可以和FFD、RFD通信,FFD不仅可以发送和接收数据,还具备路由器的功能。

  1. 精简功能设备

精简功能设备(Reduced-Function Device,RFD)负责将采集的数据信息发送给协调器,并不具备数据转发、路由发现和路由维护等功能,而RFD只能和FFD通信,RFD之间需要通信时只能通过FFD转发。

ZigBee节点类型

  1. 协调器节点

协调器节点也称作PAN协调器节点,在无线传感器网络中可以作为汇聚节点。协调器节点必须是全功能设备,在一个网络中只能有一个,用于建立新的网络、设定网络参数、管理网络中的节点、存储网络中节点信息等。

image-20240919181228927

协调器在ZigBee系统中的作用是建立并管理网络,自动允许其他节点加入网络的请求,收集终端节点传来的数据,并通过串口同上位机进行通信。

image-20240919181734188
  1. 路由器节点

路由器节点是全功能设备可以参与路由发现、消息转发、通过连接别的节点来扩展网络的覆盖范围等。ZigBee路由器节点可以在它的操作空间中充当普通协调器节点,但普通协调器节点与ZigBee协调器节点不同,它仍然受ZigBee协调器节点的控制。

image-20240919181615170

在ZigBee系统中,路由器节点的主要作用是路由选择和数据转发

image-20240919181819772
  1. 终端节点

终端节点可以是全功能设备或者精简功能设备,通过协调器节点或者路由器节点连接到网络,不允许其他任何节点通过终端节点加入网络,终端节点能够以非常低的功率运行。

image-20240919181910848

终端节点在ZigBee系统中的作用是采集数据,并通过与协调器建立“绑定”将数据发送给协调器,同时接收协调器发来的控制命令。在终端节点以终端的身份启动并加入网络后,即开始与协调器建立绑定。一旦一个绑定被创建,终端节点就可以在不需要知道明确的目的地址的情况下发送数据。

image-20240919182052401

拓扑结构类型

  1. 星型拓扑结构

星型拓扑结构是最简单的一种拓扑形式,其包含一个协调器结点和一系列的终端节点。ZigBee协调器节点位于网络的中心负责发起建立和维护整个网络,如果需要在两个终端节点之间进行通信必须通过协调器节点转发。这种拓扑结构的缺点是协调器结点故障将致使整个网络瘫痪。

image-20240919182524330

实例:基于ZigBee技术采用星状拓扑结构组建智能电源监控系统的无线传感器网络,解决传统电源监控系统中安装困难、布线繁琐及维护不便等问题。

image-20240919183250470
  1. 树状拓扑结构

树状网络由星状网络连接形成,通过多个星状网络的连接使网络覆盖范围更大,每一个节点都只能和他的父节点或子节点进行通信如果需要从一个节点向另一个节点发送数据,那么信息将沿着树的路径向上传递到最近的祖先节点然后再向下传递到目标节点。这种拓扑结构的优点是可实现网络范围内多跳信息服务,具有一定的稳定性和可扩展性;缺点是不能很好适应外部动态环境,任意节点中断或故障将会使部分节点脱离网络。

image-20240919182853147

实例:基于ZigBee技术采用树状拓扑结构组建智能家居内部无线网络,通过ZigBee无线传感器网络节点的设计,实现对各种传感器信息的采集、传输和控制功能。

image-20240919183327762
  1. 网状拓扑结构

网状拓扑结构的优点是具有自组织,自愈的功能,具有更加灵活的信息路由规则;缺点是需要复杂的路由算法,实现复杂,对网络中节点的计算处理能力要求也较高。

image-20240919183652250

实例:基于ZigBee技术采用网状拓扑结构设计智能电源监控系统。

image-20240919183719298

ZigBee网络的路由协议

路由技术主要作用是为数据以最佳路径通过通信子网到达目的节点提供服务。在传统的OSI参考模型中,网络层实现路由功能。

ZigBee路由协议不同于传统的无线传感器网络。传统的传感器网络中除了汇聚节点是一个增强功能的传感器节点外,其它传感器节点功能基本相同,都兼具终端和路由器双重功能,除了能够进行本地信息收集和数据处理外,还要处理其它节点转发来的数据。

而在ZigBee传感器网络中,除了ZigBee协调点在网络中具有与汇聚节点相似的功能和地位外,其余节点功能并不相同。为了达到节约成本,节省能量消耗的设计目标,ZigBee网络中的一部份节点的功能被简化,这些节点只能进行简单的收发,而不能充当路由器。

网络层地址分配机制

ZigBee网络中的每一个节点都有一个16bit网络短地址和一个64bit IEEE扩展地址,加入ZigBee网络的节点通过关联过程组成一棵逻辑树。当网络中的节点允许一个新节点通过它加入网络时,它们之间就形成了父子关系。每个进入网络的节点都会得到父节点为其分配的一个在此网络中唯一16bit网络地址。

image-20240919185933468

设备地址的类型:

  1. 64-bit IEEE扩展地址: 类似于MAC地址,节点唯一标识 ;
  2. 16-bit网络短地址:节点加入网络时由其父节点动态分配;用于路由机制和网络中的数据传输。

节点的网络深度:从节点到根节点协调器的最短跳数,标识节点在网络拓扑图中的层次位置。 当协调器建立一个新的网络后,首先将自己的16bit网络地址初始化为0,网络深度初始化为0。

16bit网络短地址的分配原则:规定每个父节点最多可连接C个子节点,这些子节点中最多可以有R个路由节点,网络的最大深度为L,Cskip(d)是网络深度为d的父节点为其子节点分配的地址之间的偏移量,其计算标准如下:
C s k i p ( d ) = { 1 + C ⋅ ( L − d − 1 ) , R = 1 1 + C − R − C ⋅ R L − d − 1 1 − R , otherwise Cskip(d)= \begin{cases} 1+C\cdot (L-d-1), & R=1\\ \frac{1+C-R-C\cdot R^{L-d-1}}{1-R}, & \text{otherwise} \end{cases} Cskip(d)={1+C(Ld1),1R1+CRCRLd1,R=1otherwise
当Cskip(d)为0时,表明父节点不具备为子节点分配地址的能力,即它不能够再使别的节点通过它加入网络; 当Cskip(d)大于0时,表明父节点可以接受其它节点为其子节点,并为子节点分配网络地址。父节点会为第一个与它关联的路由节点分配比自己大1的地址,之后与之关联的路由节点的地址之间都相隔偏移量Cskip(d)

终端节点的地址分配原则:为终端节点分配地址与为路由节点分配地址不同,假设父节点的地址为 A p A_p Ap,则第n个与之关联的终端子节点地址 A n A_n An为:
A n = A p + C s k i p ( d ) ⋅ R + n , 1 ≤ n ≤ ( C − R ) A_n=A_p+Cskip(d)\cdot R+n, \quad 1\le n\le (C-R) An=Ap+Cskip(d)R+n,1n(CR)

在图中所示的网络中,共有11个节点。其中,中间的深色节点为ZigBee协调器节点,其他节点是与协调器相连的路由器节点和终端节点。假设在当前的网络结构中,每个父节点最多可以连接4个子节点(C=4),且这些子节点中最多可以有4个路由器节点(R=4),当前网络的最大深度为3(L=3)。计算各个节点的网络地址。

image-20240919191258379

Step1 计算地址偏移量

dCskip(d)
021
15
21
30

Step2 计算各个节点的网络地址

1号节点深度为0,且为协调器节点,因此偏移量为21,地址为0;

2、3、4、5号节点均为1号节点的子节点,深度为1,假设第一个与1号节点连接的子节点是2号节点,故2号节点的偏移量为5,地址为0+1=1。3、4、5号节点的偏移量依次加21,故分别为22、43、64,偏移量均为5;

6号节点为2号节点的子节点,深度为2,故6号节点的偏移量为1,地址为1+1=2;

7号节点和8号节点均为3号节点的子节点,深度为2,故7号节点的偏移量为1,地址为21+1=23,8号节点的偏移量也为1,地址为23+5=28;

对于9、10、11号节点同理。

节点编号网络深度 (d)偏移量(Cskip)地址(Addr)
10210
2151
31522
41543
51564
6212
72123
82128
92165
102170
113066
image-20240919192703988

ZigBee网络路由的数据结构

路由表:ZigBee协调器节点和ZigBee路由器节点都保存一张路由表用来转发数据分组,为网络中的其它节点保存一个路由表条目。 路由表格式如下:

16bit3bit16bit
Destination addressStatusNext—hop address

Destination address:此条路由的目的节点地址;Status:此条路由的状态信息;Next—hop address:通往目的节点的下一跳节点地址。

路由发现表:ZigBee协调器节点和路由器节点保存路由发现表,表中条目用来储存路由发现过程中的一些临时路由信息。 路由发现表格式如下:

8bit16bit16bit8bit8bit16bit
Route request IDSource addressSender addressForward costResidual costExpiration time

Route request ID:发起路由请求的节点产生的序列号;Source address:发起路由发现的节点地址;Sender address:路由请求分组发送给此节点的节点地址;Forward cost:发起路由发现的节点到此节点路径开销;Residual cost:此节点到目的节点的开销;Expiration time:路由建立过程的有效时间。

邻居节点列表:ZigBee网络中的每个节点都保存一张邻居节点列表,用来存储此节点传输范围内其它节点的信息

16bit64bit16bit8bit8bit
PAN IDExtended addressNetwork addressDevice typeRelationship

PAN Id:邻节点PAN标识符;Extended address:邻节点的64bit IEEE扩展地址;Network address:邻节点16bit网络地址;Device type:邻节点类型;Relationship:邻节点与当前节点的关系。

路由请求分组(RREQ):具有路由功能的节点可以向周围邻节点广播一个RREQ分组,目的是为了找到一条通往它希望到达的目的节点的有效路径

8bit8bit8bit16bit8bit
Command frame identifierCommand optionsRoute request IDDestination addressPath cost

Command frame identifier:指出此控制分组的类型;Command options:指出此路由请求分组是否是在路由修复过程中产生;Route request ID:发起路由请求的节点产生的序列号;Destination address:发起路由请求的节点希望建立的路径的目的地址;Path cost:指从RREQ的发起节点到当前接收RREQ的节点的路径开销。

路由应答分组(RREP):分组希望到达的目的节点收到RREQ后向RREQ分组的发起节点回复一个RREP分组 。

8bit8bit8bit16bit16bit8bit
Command frame identifierCommand optionsRoute request IDOriginator addressResponder addressPath cost

Originator address:发起路由请求的节点的网络地址;Responder address:该条路由的目的节点地址,即响应RREQ的节点的网络地址。

路由出错分组(RERR):当节点转发数据分组失败时将产生一个RERR分组,目的是为了通知此数据分组的源节点分组转发失败

8bit8bit16bit
Command frame identifierError codeDestination address

Command frame identifier:指出此控制分组的类型(Ox01 RREQ,0x02 RKEP,0x03 RERR);Error code:指出路由出错的原因;Destination address:指被转发失败的数据分组的目的地址。

ZigBee网络的路由算法

AODVjr路由算法

AODV(Ad-Hoc On-Demand Distance Vector)是按需距离矢量路由,利用扩展环搜索的办法来限制搜索发现过的目的节点的范围,支持组播,可以实现在ZigBee节点间动态的、自发的路由,使节点很快的获得通向所需目的地址的路由。ZigBee网络中使用一种简化版本的AODV协议,AODVjr路由只有在路由节点接收到网络数据包,并且网络数据包的目的地址不在节点的路由表中时才会进行路由发现过程。其过程如下:

  1. 路由发现过程

对于一个具有路由能力的节点,当接收到一个从网络层的更高层发出的发送数据帧的请求,且路由表中没有和目的节点对应的条目时,就会发起路由发现过程。源节点首先创建一个路由请求分组(RREQ),并使用多播的方式向周围节点进行广播,建立相应的路由表条目和路由发现表条目,状态设置为路由发现中。任何一个节点都可能从不同的邻居节点处接收到广播的RREQ,接收到RREQ后,节点将进行分析

  1. 反向路由建立

当RREQ消息最终到达了目的节点,节点验证RREQ中的目的地址为自己的地址之后,目的节点就会产生RREP消息,作为一个对RREQ消息的应答。当RREQ消息从一个源节点转发到不同的目的地时,沿途所经过的节点都要自动建立到源节点的反向路由。由于之前已经建立了明确的反向路由,因此RREP无需进行广播,只需按照反向路由的指导,采取单播的方式即可把RREP消息传送给源节点

  1. 正向路由建立

在RREP以单播方式转发回源节点的过程中,沿着这条路径上的每一个节点都会根据RREP的指导建立到目的节点的路由。也即确定到目的地址节点的下一跳。通过记录RREP从哪个节点传播而来,然后将该邻居节点写入路由表中的路由表项,一直到RREP传送到源节点。

描述以下路由建立过程。

image-20240919195101192

RFD设备J要发送数据给D

J先把数据发送给具有路由功能父节点G

G查找自身路由表,没有发现一条到D的有效路径,于是发起一个路由发现过程,构建并广播RREQ消息;

D选择最先到达的RREQ消息的传送路径G-C-D,并返回RREP消息

G收到D发来的RREP信号,路由路径建立,G就会按这条路径来发送缓存的数据

同时D定期发送KEEP-ALIVE包,以维护路由信息。

Cluster-Tree路由算法

树型网络结构路由算法,Cluster-Tree算法包括地址的分配与寻址路由两部分。包括子节点的16位网络短地址的分配,以及根据目的节点的网络地址来计算下一跳(寻址)的算法。

当一个网络地址为A,网络深度为d的路由节点(FFD)收到目的地址为D的转发数据包时,路由节点首先要判断目的地址D是否为自身的一个子节点,然后根据判断的结果采取不同的方式来处理这个数据。

若地址D满足以下判别式,则可以判断D地址节点是A地址节点的一个后代节点:
A < D < A + C s k i p ( d − 1 ) A<D<A+Cskip(d-1) A<D<A+Cskip(d1)
如果D不在这个范围之内,则D地址节点是A地址节点的父节点。

数据包转发措施:目的节点是自身的一个后代节点,则下一跳(next hop)的节点地址为:
N = { D , EndDevice A + 1 + [ D − ( A + 1 ) C s k i p ( d ) × C s k i p ( d ) ] , otherwise N= \begin{cases} D, & \text{EndDevice}\\ A+1+[\frac{D-(A+1)}{Cskip(d)}\times Cskip(d)], & \text{otherwise} \end{cases} N={D,A+1+[Cskip(d)D(A+1)×Cskip(d)],EndDeviceotherwise

两种路由算法的优缺点

AODVjr算法相对于有线网络的路由协议而言,它不需要周期性的路由信息广播,节省了一定的网络资源,并降低网络功耗。但缺点是在需要时才发起路由寻找过程,会增加数据到达目的地址的时间。

Cluster-Tree算法使不具有路由功能的节点间通过与各自的父节点间的通信仍然可以发送数据分组和控制分组。但缺点是效率不高。

为实现低成本、低功耗、高可靠性等设计目标,ZigBee网络中采用了树型网络结构路由按需距离矢量路由相结合的路由算法。

ZigBee网络的路由机制

ZigBee网络中存在RN+和RN-两种类型的节点。RN+节点是具有足够的存储空间和能力执行AODvjr路由协议的节点;RN-节点的存储空间和能力却是相对有限的,它不能够执行AODvjr路由协议,但它可以使用Cluster-Tree算法帮助转发控制分组

图中所示为一个包含10个节点的ZigBee网络,图中黄色节点为RN+节点,蓝色节点为RN-节点,节点0为ZigBee协调器节点。假设节点2要向节点9发送数据分组,请描述下图过程。

image-20240919200136066

路由表中没有到达节点9的路由。节点2是一个RN+节点,将发起路由建立过程。

节点2创建并向周围节点广播一个RREQ分组,若收到RREQ的节点是RN-,则按Cluster-Tree路由转发此分组;若收到RREQ的节点是RN+,则根据RREQ中的信息建立路由发现表条目路由表条目并继续广播此分组。

如下图所示,0、1、3节点会受到RREQ,建立节点2的反向路由,并继续广播RREQ。节点在转发RREQ之前,计算将RREQ发送给它的邻节点与本节点之间的链路开销,将它加到RREQ中存储的链路开销上,然后将更新后的链路开销存入路由发现表条目中。

image-20240919201500930

由于节点5是RN-节点,不具有路由功能,因此它受到RREQ后发现自己不是目的节点,只有将其发送给它的父节点(节点3),但节点3已经转发过此RREQ分组,因此不再进行转发。节点6发现目的节点是它的一个子节点,它便代替此目的节点沿着刚刚建立的反向路径向RREQ的源节点(节点2)回复一个RREP,受到RREP的节点建立到目的节点(节点9)的正向路由。

image-20240919201746139

节点在转发RREP前会计算反向路径中下一跳节点与本节点之间的链路开销;将它加到RREP中存储的链路开销上;当RREP到达相应RREQ的发起节点时,路由建立过程结束,数据分组沿着刚刚发现的路径2-3-6-9传输。

image-20240919201831158

路由维护过程:

  1. 如果在数据传输中发生链路中断,将由中断链路的上游节点激活路由维护过程;
  2. 如果检测到链路失效的是RN+节点,它将采用本地修复方式来维护路由,即缓存来自源节点的数据分组并广播
  3. 如果检测到链路失效的是RN-节点,它将直接向源节点发送RERR由源节点重建路由
  4. 如果一个RFD终端节点与父节点通信中断将发起孤立通知过程,尝试重新加入网络并恢复与父节点的通信。

ZigBee网络的组建

任何一个ZigBee网络其实质都是由若干个终端节点一定数量的路由器节点协调器节点按照一定的拓扑结构组建而成。通常组建一个完整的ZigBee网络主要包括两个步骤:一是网络的初始化,二是节点入网。

image-20240919203013697

ZigBee网络的初始化

ZigBee网络的建立由协调器发起,组建网络的ZigBee节点须满足两个条件:节点必须是全功能设备该节点未与其他网络连接

具体网络初始化流程主要包括三个步骤:

  1. 确定网络协调器:FFD节点1->发送信标请求命令->设置扫描期限->建立ZigBee网络
image-20240919203138683
  1. 进行信道扫描:能量扫描->排除干扰->根据信道能量测量值对信道进行递增排序;主动扫描->寻找最优信道->返回的PAN描述符列表。

  2. 设置网络ID:选择信道->设置网络ID。网络ID可以由设备随机选择、可以在网络形成的请求原语里指定、但ID在所使用的信道中必须唯一、不能为广播地址0xFFFF。

设备节点加入ZigBee网络

在经过网络初始化后,ZigBee网络已经由协调器节点组建好,接下来就是如何将路由器节点、终端节点加入网络中。节点入网时将选择检测范围内信号最强的父节点(当然包括协调器)加入网络,成功后将得到一个网络短地址并通过这个地址进行数据的发送和接收。

通过协调器加入网络

首先由设备的应用层向网络层提出执行允许设备加入网络请求原语;然后设备的网络层和MAC层之间通过执行属性设置请求原语和确认原语,完成设备的属性设置;最后网络层向应用层回复一个允许设备入网的确认原语,至此网络允许设备加入。

image-20240919203605973

节点通过主动扫描查找网络协调器;若检测到信标,节点可向协调器发送关联请求命令;协调器收到后立即回复一个确认帧;节点进入等待状态。

image-20240919203655732

在响应时间内同意加入,给节点分配16位短地址,产生包含新地址和连接成功状态的连接响应命令并存储;当响应时间过后,节点向协调器发送数据请求命令,协调器收到后回复确认帧,将存储的关联响应命令发送给节点;节点收到后,向协调器回复一个确认帧,表明入网成功。

image-20240919203753235

通过已有节点加入网络

当靠近协调器的全功能节点(FFD)和协调器关联成功后网络范围内的其他节点就可以以FFD节点作为父节点加入网络具体加入网络有两种方式:一种是通过关联方式,也即由待加入的节点发起加入网络;另一种是直接方式,也即指定将待加入的节点加入到某个节点下,作为该节点的子节点。其中关联方式是ZigBee网络中新节点加入网络的主要途径。

image-20240919203928680

曾加入过网络,但却与其父节点失去联系,将这样的节点称为孤儿节点;孤儿节点在其相应的数据结构中仍存有原父节点的信息,可以直接给原父节点发送入网请求;若父节点同意其加入,直接获得以前分配的网络地址,入网成功;若父节点拒绝其加入,则该节点只能以新节点身份重新申请入网。

新节点查找其周围的网络,寻找父节点,并将找到的父节点的信息进行存储;在所有的父节点中选择一个深度最小的节点,对其发出入网请求;若请求被批准,父节点会分配16位网络地址给该节点,此时入网成功。

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐