本文介绍了一种,如何通过树莓派采集企业内部无线网络质量,将树莓派变成无线探针,并在PRTG网络监控平台上进行显示的方法。

可以监控我们感兴趣的无线网络的各项指标,包括

无线丢包

ping测试最大、最小,平均,抖动

设备温度

无线信道

无线协商速率

无线连接质量

射频信号功率

通过这个监控机制,企业网络管理者可以直观的获取无线探针所在区域的无线质量。及时发现诸如无线信道跳频,延迟增大,丢包,信号衰减等事件。

实现原理

树莓派运行了基于Debian的Linux系统。通过iwconfig,ping,ifconfig,iproute等linux常见命令获取设备当前的网络连接情况,并通过Python格式化数据后,转换成PRTG系统可以识别的XML格式的数据文件。

部署方法

一、树莓派无线网络连接

目前的树莓派常见的有Raspberry Pi 4,3+,3三个主要流行的版本。具体支持的无线情况如下:

型号

支持的无线频段

Raspberry Pi 4B

5Ghz+2.4GHz

Raspberry Pi 3B+

5Ghz+2.4GHz

Raspberry Pi 3B

Only 2.4GHz

由于4B的各版本目前刚刚发布,大批量部署性价比不合适。3B版本不支持5G。

这样看来的话,使用3B+版本+POE模块其实刚刚好。

树莓派无线网络连接比较简单,编辑

/etc/wpa_supplicant/wpa_supplicant.conf

该文件记录了树莓派WIFI的相关配置

network={

ssid="无线网络名字"

psk="无线密码"

key_mgmt=WPA-PSK

}

配置完成之后重启网络服务

service networking restart

由于我们的目标是这个树莓派不管插在任何一个网口上,甚至是不连接有线直接通过无线连接上报采集的数据,因此需要同时启用eth和wlan网口,并配置缺省路由的优先级,eth缺省路由优先级较高。编辑文件

cat /etc/network/interfaces

auto eth0

iface eth0 inet dhcp

metric 10

#eth0的metric为10 ,如果存在eth0为下一跳的缺省路由,优选此条缺省路由。

allow-hotplug wlan0

auto wlan0

iface wlan0 inet dhcp

metric 100

#wlan的metric跳数配置比eth0高

pre-up wpa_supplicant -B w -D wext -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf

post-down killall -q wpa_supplicant

#关联WPA_Supplicat文件

配置完成后,重启网络服务,重启无线网卡接口。嫌麻烦的的可以直接重启设备。

service networking restart

ifdown wlan0

ifup eth0

正常联网的情况下,我们检查一下设备的路由表和网卡地址,确认是否正常。

二、编写shell脚本

#!/bin/bash

PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

cd /home/pi

if [ -f checkresult.txt ]; then

#echo "remove old checkresult.txt file ... "

rm -f checkresult.txt

fi

if [ -f $HOSTNAME-WIFI_Check_result.txt ]; then

#echo "$HOSTNAME-WIFI_Check_result.txt file ... "

rm -f $HOSTNAME-WIFI_Check_result.txt

fi

if [ -f IP-WIFI-Check-$HOSTNAME.txt ]; then

#echo IP-WIFI-Check-$HOSTNAME.txt file ... "

rm -f IP-WIFI-Check-$HOSTNAME.txt

fi

#删除可能存在的历史文件

wlangwip=$(route | grep wlan0 | grep default)

wlangwip=${wlangwip##*default}

wlangwip=${wlangwip%%0.0.0.0*}

#这一顿骚操作,是为了获取目前无线网络的网关IP地址

#我们尽可能的保证这个脚本的普适性,因此需要自动获取当前无线网络的网关IP

# route | grep wlan0 | grep default like this:

#default 10.0.192.1 0.0.0.0 UG 100 0 0 wlan0

# ↑就是为了获取这个字段

#-------------------------------------------------------------------

ping -c 200 -i 0.1 $wlangwip >> checkresult.txt

#100ms间隔快速ping网关IP,结果写入checkresult.txt文件

iwconfig wlan0 >> checkresult.txt

#iwconfig命令是无线网卡的状态,将状态写入checkresult.txt文件

#-------------------------------------------------------------------

echo '' >> checkresult.txt

cat /sys/class/thermal/thermal_zone0/temp >> checkresult.txt

echo '' >> checkresult.txt

#将树莓派当前温度写入checkresult.txt文件

#-------------------------------------------------------------------

echo '' >> checkresult.txt

ifconfig eth0 | grep "inet " | awk '{print $2}' >> checkresult.txt

echo '' >> checkresult.txt

#-------------------------------------------------------------------

echo '' >> checkresult.txt

ifconfig wlan0 | grep "inet " | awk '{print $2}' >> checkresult.txt

echo '' >> checkresult.txt

#将有线网卡,无线网卡当前获取的IP地址写入checkresult.txt文件

NIC=$(route -n | grep UG | awk '{print $8}'| awk 'NR==1')

ifconfig $NIC | grep "inet " | awk '{print $2}' >> IP-WIFI-Check-$HOSTNAME.txt

#这两句详细解释一下

#第一句,获取当年设备缺省路由表第一行的记录,并提取其中的网卡设备名

#第二句,获取此网卡目前的IP地址

#这个地址是目前树莓派与服务器通信的主地址。仅连接无线的情况为wlan0 IP地址,同时连接有线无线的时候为eth0 IP地址

#这个地址,之后集中下发脚本的时候用得到

#-------------------------------------------------------------------

python checknetwork.py checkresult.txt $HOSTNAME-WIFI_Check_result.txt $HOSTNAME

#通过Python,格式化checkresult.txt的内容,并输出一个已HOSTNAME命名的XML文件

#-------------------------------------------------------------------

tftp 10.0.20.178 << !

put $HOSTNAME-WIFI_Check_result.txt

put IP-WIFI-Check-$HOSTNAME.txt

quit

!

tftp 10.0.20.20 << !

put IP-WIFI-Check-$HOSTNAME.txt

quit

!

#通过TFTP上传前面生成的文件,直接传递到PRTG服务器上是最方便的,也可选择使用scp,FTP或者其他的方式,自选。

#-------------------------------------------------------------------

rm -f checkresult.txt

rm -f $HOSTNAME-WIFI_Check_result.txt

rm -f IP-WIFI-Check-$HOSTNAME.txt

删除刚才生成的一堆临时文件

#-------------------------------------------------------------------

每行代码的功能我都注释好了,够贴心了吧,0基础保证你能看得懂。

我们现在来看一下checkresult.txt文件,这里面基本包含了我们关心的各项数据。下一步,我们通过Python对这些数据进行简单的处理。

三、编写Python

encoding=utf-8

import re

import os

import sys

import datetime

#-------------------------------------------------------------------

#定义一个读文件的函数,读取之前shell脚本生成的checkresult文件

def read_file_as_str(file_path):

# 判断路径文件存在

if not os.path.isfile(file_path):

raise TypeError(file_path + " does not exist")

all_the_text = open(file_path).read()

# print type(all_the_text)

return all_the_text

#-------------------------------------------------------------------

#定义一个按照关键字查找关键字前后固定长度的函数

def find_str_as_keyword(str_all,keyword,start,end):

start=int(start)

end=int(end)

len_start=str_all.find(keyword)+start

len_end=str_all.find(keyword)+end

#print len_start

#print len_end

echo_str=str_all[len_start:len_end]

return echo_str

#-------------------------------------------------------------------

#定义一个按照两个关键字查找关键字之间内容的函数

def between_str_as_keyword(str_all,keyword1,keyword2,keyword1_start=0,keyword2_end=0):

keyword1_start=int(keyword1_start)

keyword2_end=int(keyword2_end)

len_start=str_all.find(keyword1)+keyword1_start

len_end=str_all.find(keyword2)+keyword2_end

#print len_start

#print len_end

echo_str=str_all[len_start:len_end]

return echo_str

#-------------------------------------------------------------------

def main(input_file_path,output_file_path,hostname):

checkresult=read_file_as_str(input_file_path)

#注意:

#搜索结果=find_str_as_keyword(待搜索字符串,关键字,搜索结果起始长度,搜索结束长度)

#搜索keyword保证不能重复,尽可能搜索长的关键字

#起始和结束长度从keyword第一个字符串算起,且包含keyword本身长度

#packetloss=find_str_as_keyword(checkresult,"packet loss",-3,11)

packetloss=between_str_as_keyword(checkresult,"received,","% packet loss",10)

#注意丢包率长度会变-使用between函数查找区间

minavgmaxmdev=between_str_as_keyword(checkresult,"min/avg/max/mdev","wlan0",19,-1)

PingMin=minavgmaxmdev[0:minavgmaxmdev.find("/")]

minavgmaxmdev=minavgmaxmdev[minavgmaxmdev.find("/")+1:]

PingAvg=minavgmaxmdev[0:minavgmaxmdev.find("/")]

minavgmaxmdev=minavgmaxmdev[minavgmaxmdev.find("/")+1:]

PingMax=minavgmaxmdev[0:minavgmaxmdev.find("/")]

minavgmaxmdev=minavgmaxmdev[minavgmaxmdev.find("/")+1:]

PingMdev=minavgmaxmdev[0:minavgmaxmdev.find(" ms")]

#抖动值字符串多次截取/与/之间的内容,原文格式类似于:2.103/9.325/29.067/8.392 ms

totaltime=between_str_as_keyword(checkresult,"loss, time","rtt min/",11,-3)

#注意总时间字符串长度会变-使用between函数查找区间

AccessPoint=find_str_as_keyword(checkresult,"Access Point:",14,31)

Frequency=between_str_as_keyword(checkresult,"Frequency:"," GHz",10)

#注意信道选择字符串长度会变-使用between函数查找区间

BitRate=between_str_as_keyword(checkresult,"Bit Rate="," Mb/s Tx-Power",9)

#注意连接速率长度会变

LinkQuality=between_str_as_keyword(checkresult,"Link Quality=","/70 Signal level",13)

#注意连接质量长度--可能--会变

Signallevel=between_str_as_keyword(checkresult,"Signal level=","Rx invalid",13,-17)

WlanGWIP=between_str_as_keyword(checkresult,"--- "," ping statistics ---",4)

DeviceTemp=between_str_as_keyword(checkresult,"","",14,-1)

DeviceTemp=float(DeviceTemp)/1000

Eth0_IP=between_str_as_keyword(checkresult,"","",16,-1)

WLAN_IP=between_str_as_keyword(checkresult,"","",16,-1)

write_file_as_path(output_file_path,packetloss,PingMin,PingAvg,PingMax,PingMdev,totaltime,AccessPoint,Frequency,BitRate,LinkQuality,Signallevel,hostname,WlanGWIP,DeviceTemp,Eth0_IP,WLAN_IP)

if __name__ == '__main__':

main(sys.argv[1],sys.argv[2],sys.argv[3])

下面是XML文档生成的代码,先看一下,之后我们详细讲解PRTG的XML文件字段届时

#-------------------------------------------------------------------

#下面这一大段是生成xml文件的函数

def write_file_as_path(file_path,write_packetloss,write_PingMin,write_PingAvg,write_PingMax,write_PingMdev,write_totaltime,write_AccessPoint,write_Frequency,write_BitRate,write_LinkQuality,write_Signallevel,write_hostname,write_WlanGWIP,write_DeviceTemp,write_Eth0_IP,write_WLAN_IP):

f=open(file_path,'w')

#with open(file_path,'w',encoding='gbk') as f:

f.write('<?xml version="1.0" encoding="Windows-1252" ?>\n')

f.write('\n')

f.write(' \n')

f.write(' Packet loss\n')

f.write(' Percent\n')

f.write(' Absolute\n')

f.write(' 20\n')

f.write(' 10\n')

f.write(' '+write_packetloss+'\n')

f.write(' \n')

f.write(' \n')

f.write(' Ping Min Time\n')

f.write(' ms\n')

f.write(' Absolute\n')

f.write(' 1\n')

f.write(' '+write_PingMin+'\n')

f.write(' \n')

f.write(' \n')

f.write(' Ping Max Time\n')

f.write(' ms\n')

f.write(' Absolute\n')

f.write(' 1\n')

f.write(' 500\n')

f.write(' 200\n')

f.write(' '+write_PingMax+'\n')

f.write(' \n')

f.write(' \n')

f.write(' Ping Avg Time\n')

f.write(' ms\n')

f.write(' Absolute\n')

f.write(' 1\n')

f.write(' 100\n')

f.write(' 50\n')

f.write(' '+write_PingAvg+'\n')

f.write(' \n')

f.write(' \n')

f.write(' Ping Mean Deviation Time\n')

f.write(' ms\n')

f.write(' Absolute\n')

f.write(' 1\n')

f.write(' '+write_PingMdev+'\n')

f.write(' \n')

f.write(' \n')

f.write(' Ping Total Time\n')

f.write(' ms\n')

f.write(' Absolute\n')

f.write(' 1\n')

f.write(' '+write_totaltime+'\n')

f.write(' \n')

f.write(' \n')

f.write(' Radio Frequency\n')

f.write(' GHz\n')

f.write(' Absolute\n')

f.write(' 1\n')

f.write(' '+write_Frequency+'\n')

f.write(' \n')

f.write(' \n')

f.write(' Radio BitRate\n')

f.write(' Mb/s\n')

f.write(' Absolute\n')

f.write(' 1\n')

f.write(' 50\n')

f.write(' 70\n')

f.write(' '+write_BitRate+'\n')

f.write(' \n')

f.write(' \n')

f.write(' Radio LinkQuality\n')

f.write(' /70\n')

f.write(' Absolute\n')

f.write(' '+write_LinkQuality+'\n')

f.write(' \n')

f.write(' \n')

f.write(' Radio Signallevel\n')

f.write(' dBm\n')

f.write(' Absolute\n')

f.write(' '+write_Signallevel+'\n')

f.write(' \n')

f.write(' \n')

f.write(' Probe Temperature\n')

f.write(' Temperature\n')

f.write(' Absolute\n')

f.write(' 1\n')

f.write(' 60\n')

f.write(' 55\n')

f.write(' '+str(write_DeviceTemp)+'\n')

f.write(' \n')

f.write(' Updatetime:'+datetime.datetime.now().strftime('%H:%M:%S')+' Eth0_IP:'+write_Eth0_IP+' Wlan_IP:'+write_WLAN_IP+' WLAN Gateway IP:'+write_WlanGWIP+' AccessPoint:'+write_AccessPoint+'\n')

f.write('\n')

f.close()

四、PRTG系统配置

在PRTG探针所在的操作系统里编写如下脚本。

由于树莓派送过来的XML文件的命名格式都是:主机名-WIFI_Check_result.txt

所以我们的BAT脚本可以通过%1传入的参数来打印对应主机名设备的上报信息

@echo off

chcp 65001

type "C:\00-tftp\%1-WIFI_Check_result.txt"

保存到

C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXEXML

然后,在PRTG系统里面,添加传感器,搜索“EXE”,选择“高级EXE/脚本”

![在这里插入图片描述](https://img-blog.csdnimg.cn/20200308212054936.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3l0bHpxMDIyOA==,size_16,color_FFFFFF,t_70 =600x)

EXE/脚本选择刚才保存的bat文件

参数填入树莓派的主机名,这样本地的脚本带入参数后,会获取你指定的树莓派的上报信息

互斥名称尽量跟参数保持一致。PRTG将逐一执行 (并非同时执行)拥有相同互斥名称的所有 EXE/脚本传感器。如果您拥有大量传感器并想要避免由同时运行进程所引起的资源高度使用,这十分有用。

到这基本就搞定了,你可以在这个传感器内看到刚才树莓派收集到的各种信息。

五、树莓派shell脚本配置定时执行

定时执行配置很简单

crontab -e

打开定时任务执行列表,在最后添加上一句

*/1 * * * * sh /home/pi/checknetwork.sh

脚本地址就是我们刚才写好的shell脚本。

注意,crontab运行脚本的时候是不带系统变量的,所以我们之前的脚本里已经提前写了PATH变量。

PATH=/etc:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

当然还有一种办法,你再写个脚本,来调这个脚本。比如随便在root目录下写个脚本,就写一句话,调用checknetwork.sh。这样也可以避免PATH不同步的情况。

#!/bin/bash

/home/pi/checknetwork.sh

进阶提高

看到这里,基本功能都实现了,但是接下来我们还有一些高阶的应用

一、多个树莓派自动更新脚本

对于网内所有的树莓派,如果shell脚本或者python程序出现迭代更新,我们设计了一个办法统一下发新版本的shell脚本和python到所有的树莓派。这对于网内有几十个树莓派的时候,非常有用。

找一台linux主机做版本服务器,写个下面的脚本

#!/bin/bash

TFTPPATH="/root/tftp_file"

IPLISTPATH="/root/PRTG_WIFI_Probe/IPlist"

rm -f $IPLISTPATH/*

mv $TFTPPATH/IP-WIFI* $IPLISTPATH/

find $IPLISTPATH/ -mmin +2 -name "IP-WIFI*" -exec rm {} \;

#保留最近2分钟内更新过的IP-WIFI-*****.txt文件,之前的删除掉

cat $IPLISTPATH/IP-WIFI* > /root/PRTG_WIFI_Probe/IPlist_all.txt

#合并所有的IP-WIFI-*****.txt

for ip in `cat /root/PRTG_WIFI_Probe/IPlist_all.txt | tr -d "\r" `

do

echo "sent file to "$ip

scp /root/PRTG_WIFI_Probe/programfile/checknetwork.py $ip:/home/pi

scp /root/PRTG_WIFI_Probe/programfile/checknetwork.sh $ip:/home/pi

done

#全部下发一遍文件

这里面,就涉及到了之前在树莓派上的一段骚操作。

NIC=$(route -n | grep UG | awk '{print $8}'| awk 'NR==1')

ifconfig $NIC | grep "inet " | awk '{print $2}' >> IP-WIFI-Check-$HOSTNAME.txt

#这两句详细解释一下

#第一句,获取当年设备缺省路由表第一行的记录,并提取其中的网卡设备名

#第二句,获取此网卡目前的IP地址

#这个地址是目前树莓派与服务器通信的主地址。仅连接无线的情况为wlan0 IP地址,同时连接有线无线的时候为eth0 IP地址

#这个地址,之后集中下发脚本的时候用得到

是不是突然想发出~ 哦~的一声赞叹,赞叹这个设计的精妙。

为了更方便,可以提前把这台服务器的SSH-Keygen公钥发送到所有树莓派上,这样scp完全无密码下发文件

二、树莓派保活探测

本例中,PRTG系统会读取生成的XML文件,只要这个文件存在,系统就不会告警。

因此,如果某个树莓派出现异常,不继续更新上报信息的时候。我们需要一个机制来探测,XML文件是否一直在正常更新

在PRTG探针所在的服务器上,编写以下BAT脚本

@echo off&setlocal enabledelayedexpansion

for /f "tokens=1 delims=" %%i in ('dir C:\00-tftp /tw ^| find /i "%1-WIFI_Check_result.txt" ') do set timeresult=%%i

set ma=%timeresult:~15,2%

set mb=%time:~3,2%

set /a ma=1%ma%-100

set /a mb=1%mb%-100

#以上两句是去除分钟为08时的异常。BAT脚本对于08xxx的数字会认为是8进制

set /a mc=%mb%-%ma%

if %mc% gtr 2 (echo %mc%:Error Time Out) else (echo %mc%:Active)

然后,放到如下的路径下

C:\Program Files (x86)\PRTG Network Monitor\Custom Sensors\EXE

好了,去PRTG添加一个自定义传感器,使用这个脚本,传参为设备名。XML文件超过2分钟没更新就告警咯。

三、PRTG XML格式自定义传感器XML解释

来个示例

XML Return Format: Minimum Example:

通道1名称

通道值

通道2名称

通道值

自定义文本传递

自定义错误消息

搞定!

python wifi探针_【逗老师带你学IT】PRTG监控系统配合树莓派采集企业内部无线网络质量...相关推荐

  1. 【逗老师带你学IT】PRTG监控系统配合树莓派采集企业内部无线网络质量

    目录 本文介绍了一种,如何通过树莓派采集企业内部无线网络质量,将树莓派变成无线探针,并在PRTG网络监控平台上进行显示的方法. 实现原理 部署方法 一.树莓派无线网络连接 二.编写shell脚本 三. ...

  2. 【逗老师带你学IT】PRTG监控通过Python+Modbus RTU获取温湿度传感器数据

    前文[逗老师带你学IT]PRTG监控通过Python+TCP Modbus获取温湿度传感器数据中我们讲了如何通过Python读取支持TCP Modbus的传感器数据.本章我们讲解下如何读取Modbus ...

  3. 【逗老师带你学IT】HUAWEI华为防火墙自动化运维Python ssh管理网络设备

    本文,介绍一种.通过Django框架,搭建API服务器,并通过此API服务器管理华为防火墙.并以此衍生出,通过Django+Python+ssh的方式管理网络设备的方法. 关于Django环境的搭建, ...

  4. 【逗老师带你学IT】PRTG监控通过Python通过串口监控UPS运行状态,PRTG值查询功能定义

    本文主要介绍,如何通过串口获取UPS主机的运行状态,并通过PRTG统计监控和告警. 不同UPS主机厂的串口通信协议不同,但是市面上有一种比较通用的协议,如果你使用的是EATON,山特等等国产UPS,大 ...

  5. 【逗老师带你学IT】PRTG监控通过Python+TCP Modbus获取温湿度传感器数据

    本文介绍,Python如何通过TCP Modbus协议获取温湿度传感器数据.并在PRTG监控系统中呈现. 本文主要涉及知识点: 1.Python的ModbusTCP客户端实现 2.常见温湿度传感器中, ...

  6. python累加求和_李老师带你学Python-第二课 如何编写Python程序

    Python语言是一种解释型编程语言,它的程序结构由多条语句从上到下书写而成,每一行书写一条指令.如以下代码完成了从键盘读入两个整数,并输出它们的和. 在任何编程语言中,数据都要放置到变量中才能被指令 ...

  7. 【逗老师带你学IT】PRTG安装教程-部署简单功能强大的监控软件

    一.PRTG简介 个人总结PRTG的优点: 1.脑残化部署,Windows下直接双击安装,剩下的全靠点点点. 2.脑残化使用,全程点点点即可完成添加加设备.加监控点. 3.强大的性能,支持数万个传感器 ...

  8. 【逗老师带你学IT】PRTG获取HUAWEI FusionServer iBMC传感器状态

    本文介绍如何使PRTG获取HUAWEI FusionServer iBMC传感器状态.以及衍生出如何通过ipmi通用协议监控所有服务器的带外管理状态. 本文主要涉及的技术点: 1.服务器ipmi命令行 ...

  9. 【逗老师带你学IT】PRTG监控系统通过阿里云API获取云产品运行状况

    本文介绍如何使PRTG监控系统通过阿里云监控API获取阿里云产品监控数据.例如网络带宽,ECS性能,RDS产品性能等. 本文主要涉及的技术点: 1.PRTG监控系统高级自定义传感器的使用 2.PRTG ...

最新文章

  1. BZOJ4292 : [PA2015]Równanie
  2. java unlimited_具有无限参数的Java方法(Java method with unlimited arguments)
  3. JS—图片压缩上传(单张)
  4. 专有云传统HSF升级Pandora Boot开发
  5. python onenet_使用Python2.7 POST 数据到 onenet 平台
  6. 求平方根sqrt()函数的底层算法效率问题
  7. Windows XP SP3?转自作者: 孤单的鸽子,  出处:天极yesky, 责任编辑: 袁绍龙
  8. python enumerate函数_关于python中enumerate和zip函数的用法及举例
  9. 2017.4.23 税收与补贴问题 思考记录
  10. SpringBoot从入门到精通教程
  11. 适用于物联网数据共享的区块链节点存储优化方案
  12. DOSBox指令全 汇编指令大全 debug
  13. 绝地反击 我的战胜贫困的经历01 转载 整理
  14. 区域生长算法及其实现
  15. 火水未濟 (易經大意 韓長庚)
  16. 无法定位程序输入点(cmake opencv_contrib,并配置后)
  17. android高德地图截屏,高德地图-地图截屏
  18. 怎样在苹果电脑上用移动硬盘(使用NTFS格式硬盘)?
  19. 【软著】申请软件著作权流程资料及方法
  20. 谷歌为AI再上“紧箍咒”:道德团队审查产品,确保AI不作恶

热门文章

  1. ESD测试手法和对应的测试电压及实际案例
  2. 如何打开Hierarchy Viewer ?
  3. 餐饮消防安全知识培训PPT模板
  4. 自己写富文本编辑器jss_JSS选择器和语法规则
  5. PS 滤镜——素描算法(二)
  6. 软件需求分析案列_软件需求分析(案例)
  7. 高效的5G ASN.1编解码工具
  8. 天气预报API(三):免费接口测试(“旧编码”)
  9. 微信旅游景区景点评论小程序系统设计与实现
  10. 跟波利亚学解题---1