敲门代码python_适用于Linux笔记本电脑的基于敲门的命令
敲门代码python
2003年,IBM开始发布具有集成加速度计和相关软件的ThinkPad膝上型计算机,以在设备跌落时保护硬盘。 来自IBM和其他地方的进取型黑客已致力于为Linux内核开发模块,以利用这些传感器。 屏幕显示方向,桌面切换,甚至游戏控制以及笔记本电脑倾斜度的实时3D模型现在都可用。 本文介绍了一种新的密码-敲码-一种简单的程序,可以在检测到特定的敲码时运行命令。
通过将更新的Linux内核与HDAPS驱动程序配合使用,您可以使用一个名为hitAge的简单程序来生成敲入代码。 您还可以下载并使用Perl脚本来自定义自己的敲门输入环境。 有关链接,请参阅本文底部的“可下载资源”和“ 相关主题”部分,其中包括有关实际使用hitkAge的链接。
硬件要求
轻而易举
你可以通过观看演示视频看(见链接相关主题 ,下同),敲击动作只包括与关节轻轻敲击。 尽管ThinkPad的加速度计旨在保护其免受意外撞击,但过大的力会损坏它。 所以要小心。
2003年或以后生产的许多IBM(现在为Lenovo)ThinkPads具有HDAPS硬件。 如果不确定硬件配置,请在Lenovo网站上查看适合您的型号的技术详细信息。 如果您没有ThinkPad,则此代码将无法在笔记本电脑上运行。
本文是在x86体系结构上编写的。 本文中的代码是在两种不同型号的ThinkPad T42p上开发和测试的。 请参阅“ 相关主题”部分,以获取指向ThinkPad硬件的链接。
如果您有Apple MacBook,则应该具有通过内核访问它们的加速度计和相同的通用方法。 但是,本文中的代码未经Apple硬件测试。
软件需求
HDAPS驱动程序必须包含在内核中才能启用对加速度计的访问。 尝试修补现有内核失败,因此,建议您从自己喜欢的镜像中下载最新的内核。 较新的内核发行版附带了HDAPS驱动程序。
启动您选择的内核配置器,并在配置中包括HDAPS驱动程序。 HDAPS驱动程序位于设备驱动程序>硬件监视支持> IBM硬盘主动保护系统(hdaps)选项下。 进一步的内核配置和安装说明不在本文讨论范围之内,但Web上有大量教程可提供详细帮助;有关详细信息,请参阅本文。 请参阅“ 相关主题”部分,以获取帮助您入门的链接。
本文是在内核级别2.6.15.1上开发和测试的。
创建一个简单的敲除序列
从“可下载资源”部分下载源代码存储库,然后找到kickAge.pl脚本。 这是主要的Perl程序,它使您可以创建敲除序列以及侦听特定的敲除序列并运行命令。 让我们研究一下kickAge.pl程序的用户空间用法和配置,然后我们将回顾其功能。
使用以下命令运行knockAge.pl程序:
perl knockAge.pl -c
这将启动Perl程序,以侦听爆震事件并记录其时间间隔以供以后使用。 程序运行后,对笔记本电脑的外壳施加冲击力。 尽管敲击事件可能会发生滑动,但您无需物理移动ThinkPad即可注册敲击事件,但是如果ThinkPad处于合成表面上,则可能会发生一些滑动。 我建议您用左手将ThinkPad握在铰链附近的左侧,同时用右手敲击显示屏框架侧面LCD面板右下方约三英寸的地方。 请参见“可下载资源”或“ 相关主题”中链接到的演示视频,以获取创建敲门序列的示例。
在敲门时尝试不同的步伐和强度,以感受一下力求解决的问题,而该方法可以击中年龄程序。 这对于创建更复杂的敲门很重要。
您的第一次实际试音应该很简单,两次“敲”之间的间隔为0.5秒。 再次运行perl knockAge.pl -c
,当您看到“输入敲门序列”时,以半秒的延迟将LCD侧面牢固敲两次,然后停止。 自动超时将在4秒钟后发生(可配置),并且类似于以下示例,将打印出您的敲门顺序:
0 540031 _#_ (command here) _#_ <comments here>
让我们剖析该行-敲除序列,定界符,命令区域,定界符和注释区域。 下一步是将该行复制到kickAge.pl程序的默认配置文件{$ HOME} /。knockFile中,该文件可能是/ home / <用户名> /。knockFile。 一旦使用上述敲除序列行创建了.knockFile,就可以修改该行以运行程序。 将(command here)
的(command here)
文本更改为/ bin / echo“双击”,然后将注释区域修改为更具描述性的内容,如下所示:
0 540031 _#_ /bin/echo "double tap" _#_ Double tap event
既然您已经修改了配置文件以打印出通知,请使用以下命令在守护程序模式下运行kickAge脚本:
perl knockAge.pl
该程序将在后台静默监听〜/ .knockFile列表中的任何事件。 尝试以相同的时间间隔双击,您将在屏幕上看到文本“双击”。 如果您想更详细地了解kickAge.pl脚本的功能,请使用以下命令在守护程序模式下运行它:
perl knockAge.pl -v
使用xscreensaver锁定和解锁屏幕
创建一个“密码”序列
使用以下命令以“创建”模式运行knockAge.pl程序:
perl knockAge.pl -c
现在,您需要创建一个解锁密码序列。 我建议使用类似“剃须和理发”的方法。 确保您选择可以始终如一地准确执行的任务。 尽管您可以修改控制输入秘密敲门声的精度的参数,但是匹配精确的时间仍然非常困难。 除了在动画兔子中引起无法控制的唱歌之外,“刮胡子和理发”是屏幕保护程序解锁密码的复杂性与简单性之间的良好结合。 这是“剃须和理发”的敲门顺序示例:
0 564025 1185795 621350 516038 960035 444421 _#_ /bin/echo "shave the haircut" _#_ two bits
在继续下一步之前,您应该使用上述命令和〜/ .knockFile配置文件中的第一个双击进行练习。 这将在稍后运行屏幕保护程序时提供帮助,并且更难检测到您是否正确敲门。
xscreensaver的命令配置
以下设置假定您已登录到窗口管理器,并且xscreensaver程序已由您的userid启动。 例如,如果您正在运行Fedora Core 4并通过gdm登录到KDE,则xscreensaver将自动启动。 因此,要激活它,请从以下位置更改双击命令:
/bin/echo "double tap"
至:
xscreensaver-command -activate &
现在,只要识别出“双击”事件,xscreensaver程序就会以您指定的任何设置激活。 激活屏幕保护程序后,如果配置了密码,则可以通过输入密码来解锁屏幕。 但是,我们真正想做的是用秘密的解锁代码来打动我们的朋友,以禁用屏幕保护程序。 因此,将以下命令替换为〜/ .knockFile中的“秘密密码序列”:
/bin/echo "shave the haircut"
与:
killall xscreensaver ; nohup xscreensaver -nosplash >/dev/null 2>/dev/null &
此命令将杀死当前正在运行的所有xscreensaver程序,然后在后台重新启动xscreensaver。 现在,您只需敲一下机箱的侧面,就可以反复锁定和解锁计算机的屏幕保护程序。 这在某种程度上比设置自定义按键组合更快或更有效吗? 并不是的。 比蓝牙接近锁定更安全或更方便吗? 可能不是。 比较凉吗? 是的
更多例子
HDAPS传感器和kickAge.pl程序提供了额外的用户输入设备,您可以以独特的方式使用它们。 例如:
- 如果打算在飞机上测试新的X配置文件,请更新双击条目以重新启动您的X服务器。 不再需要强制硬重置的键盘锁定。
- 将所需的任何Shell脚本的位置放在命令区域中,然后双击以检查您的电子邮件。
- 从狂热的混音中敲出最新的节拍,然后让ThinkLight眨眼间,就可以看到Kinakuta第二次世界大战时期黄金储藏设施的秘密摩尔斯电码位置。
- 点击摩尔斯电码以避免键盘记录程序。
有关阅读有关游戏,显示工具等的ThinkPad的“倾斜”的一些出色示例,请参阅“ 相关主题”部分。 或直接向前跳过并将Threshold变量设置为15,以便在您踩下ThinkPad时它将自动重新启动。
tickAge.pl代码
历史与策略
Jeff Molofee编写的hdaps-gl.c代码是hitAge.pl代码的基础。 Hdaps-gl.c是一个很好的演示程序,说明如何使用倾斜传感器实时显示有关ThinkPad方向的信息。 这里的实质区别是及时隔离特定事件以创建爆震,以及相关联的代码来创建和侦听爆震序列。
参数配置
让我们从tickAge.pl的顶部开始,输入时序和传感器关键参数:
清单1.主要程序参数
require 'sys/syscall.ph'; # for subsecond timingmy $option = $ARGV[0] || ""; # simple option handling# filename for hdaps sensor reads
my $hdapsFN = "/sys/devices/platform/hdaps/position";my $UPDATE_THRESHOLD = 4; # threshold of force that indicates a knock
my $INTERVAL_THRESHOLD = 100000; # microseconds of time required between knock# events
my $SLEEP_INTERVAL = 0.01; # time to pause between hdaps readsmy $MAX_TIMEOUT_LENGTH = 4; # maximum length in seconds of knock pattern# length
my $MAX_KNOCK_DEV = 100000; # maximum acceptable deviation between recorded# pattern values and knocking valuesmy $LISTEN_TIMEOUT = 2; # timeout value in seconds between knock# events when in listening mode
这些变量及其注释相对简单。 它们的用法和配置选项将在本文后面解释。 以下是全局变量及其说明的其余部分。
清单2.敲模式参数
my @baseKnocks = (); # contains knock intervals currently entered
my %knockHash = (); # contains knock patterns, associated commandsmy $prevInterval = 0; # previous interval of time
my $knockCount = 0; # current number of knocks detectedmy $restX = 0; # `resting' positiong of X axis accelerometer
my $restY = 0; # `resting' positiong of Y axis accelerometer
my $currX = 0; # current position of X axis accelerometer
my $currY = 0; # current position of Y axis accelerometer
my $lastX = 0; # most recent position of X axis accelerometer
my $lastY = 0; # most recent position of Y axis accelerometermy $startTime = 0; # to manage timeout intervals
my $currTime = 0; # to manage timeout intervals
my $timeOut = 0; # perpetual loop variable
my $knockAge = 0; # count of knocks to cycle time interval
子程序
在我们的子例程列表中,首先是一个简单的逻辑块,用于检查加速度计是否可读取:
清单3.检查加速度计子例程
sub checkAccelerometer() {my $ret;$ret = readPosition ();if( $ret ){print "no accelerometer data available - tis bork ed\n";exit(1);}}#checkAccelerometer
Jeff Molofee的hdaps-gl.c代码为hitAge.pl中的所有代码提供了一个很好的起点。 您可以在下面的readPosition
子例程中查看他的注释的痕迹。 该子例程只是打开文件,读取当前的加速度计数据,关闭文件,然后返回不带,
(逗号)字符的数据。
清单4. readPosition子例程
## comments from Jeff Molofee in hdaps-gl.c
#* read_position - read the (x,y) position pair from hdaps.
#*
#* We open and close the file on every invocation, which is lame but due to
#* several features of sysfs files:
#*
#* (a) Sysfs files are seekable.
#* (b) Seeking to zero and then rereading does not seem to work.
##
sub readPosition() {my ($posX, $posY) = "";my $fd = open(FH," $hdapsFN");while( <FH> ){s/\(//g;s/\)//g;($posX, $posY) = split ",";}# while readclose(FH);return( $posX, $posY );}#readPosition
getEpochSeconds
和getEpochMicroSeconds
提供有关爆震模式状态的详细而精确的信息。
清单5.时间分割器
sub getEpochMicroSeconds {my $TIMEVAL_T = "LL"; # LL for microsecondsmy $timeVal = pack($TIMEVAL_T, ());syscall(&SYS_gettimeofday, $timeVal, 0) != -1 or die "micro seconds: $!";my @vals = unpack( $TIMEVAL_T, $timeVal );$timeVal = $vals[0] . $vals[1];$timeVal = substr( $timeVal, 6);my $padLen = 10 - length($timeVal);$timeVal = $timeVal . "0" x $padLen;return($timeVal);
}#getEpochMicroSecondssub getEpochSeconds {my $TIMEVAL_T = "LL"; # LL for microsecondsmy $start = pack($TIMEVAL_T, ());syscall(&SYS_gettimeofday, $start, 0) != -1 or die "seconds: $!";return( (unpack($TIMEVAL_T, $start))[0] );
}#getEpochSeconds
下一步是knockListen
子例程,该例程的前五行读取当前的加速度计数据值,并针对基本值读数进行调整。 如果任一方checkKnock
的加速度计幅度都大于更新阈值, checkKnock
变量设置为1。 若要将程序调整为仅对强烈的爆震事件或类似的加速度值做出响应,请增加更新阈值。 例如,您可以将ThinkPad放在汽车中,并仅在检测到剧烈加速(或减速!)时,让它更改mp3播放列表。
如果您用力敲笔记本电脑,并且已通过更新阈值, getEpochMicroSeconds
调用getEpochMicroSeconds
子例程。 然后将diffInterval
变量分配给爆震事件之间的持续时间。 此值用于将多个大于更新阈值的快速加速度读数压缩为一个事件。 如果没有间隔阈值检查,则随着加速度计在较长时间内继续发出高强度信号,单个硬震击将记录为多个事件。 这种行为与用户在视觉和触觉上的感知都不一致。 敲门对我们来说是敲门,但对HDAPS显然不是。 如果达到间隔阈值,则将爆震间隔记录在baseKnocks
数组中,并重置爆震之间的间隔。
仔细修改这些变量将有助于调整程序以识别您的特定敲音风格。 降低更新阈值并增加间隔阈值以检测相距较远的软爆震。 机械爆震装置或特定的爆震方法可能需要降低间隔阈值以识别不同的爆震事件。
清单6. kickListen子例程
sub knockListen() {my $checkKnock = 0;($currX, $currY) = readPosition();$currX -= $restX; # adjust for rest data state$currY -= $restY; # adjust for rest data state# require a high threshold of acceleration to ignore non-events like# bashing the enter key or hitting the side with the mouseif( abs ($currX) > $UPDATE_THRESHOLD) {$checkKnock = 1;}if( abs ($currY) > $UPDATE_THRESHOLD) {$checkKnock = 1;}if( $checkKnock == 1 ){my $currVal = getEpochMicroSeconds();my $diffInterval = abs($prevInterval - $currVal);# hard knock events can create continuous acceleration across a large time# threshold. requiring an elapsed time between knock events effectively# reduces what appear as multiple events according to sleep_interval and# update_threshold into a singular event.if( $diffInterval > $INTERVAL_THRESHOLD ){if( $knockCount == 0 ){ $diffInterval = 0 }if( $option ){print "Knock: $knockCount ## last: [$currVal] curr: [$prevInterval] ";print "difference is: $diffInterval\n";}push @baseKnocks, $diffInterval;$knockCount++;}# if the difference interval is greater than the threshold$prevInterval = $currVal;}#if checkknock passed}#knockListen
创建敲门图案后,将其放置在〜/ .knockFile文件中,并由以下子例程读取
清单7.读取敲门文件
sub readKnockFile {open(KNCKFILE,"$ENV{HOME}/.knockFile") or die "no knock file: $!";while(<KNCKFILE>){if( !/^#/ ){my @arrLine = split "_#_";$knockHash{ $arrLine[0] }{ cmd } = $arrLine[1];$knockHash{ $arrLine[0] }{ comment } = $arrLine[2];}#if not a comment line}#for each line in fileclose(KNCKFILE);}#readKnockFile
当knockListen
获取敲除模式时,会将其与从readKnockFile
加载的现有敲除模式进行readKnockFile
。 下面的compareKnockSequences
子例程在爆震时间之间执行简单的差异检查。 请注意,击球之间的差异并没有复杂化:在许多击球上错失少量时间不会累积为总比赛失败。
第一个比较是在敲击次数之间,因为没有意义将七敲击序列与两敲击序列进行比较。 如果爆震次数与〜/ .knockFile中现有的爆震序列匹配,且爆震之间的差小于最大爆震偏差,则该爆震为匹配项。 最大的爆震偏差对于允许准确地而非精确地匹配爆震序列至关重要。 您可以增加最大爆震偏差,以使自己在节奏节奏上更加自由,但是请注意,这可能会导致模式错误匹配。 例如,尝试将最大爆震偏差从100000微秒增加到500000微秒。 这将使您的敲门声模式在预期时间之前或之后相差多达半秒,并且仍然引起匹配。 这实际上意味着“剃须和理发”可以与“玛丽有只小羊羔”匹配,因此请谨慎更改此参数。
如果完整模式匹配,则运行〜/ .knockFile中指定的命令,如果启用了详细模式,则打印出结果。 下一步是,如果找不到匹配项,则退出子例程,如果匹配,则重置记录的爆震。 compareKnockSequences
子例程执行以下步骤:
清单8.比较敲除序列
sub compareKnockSequences {my $countMatch = 0; # record how many knocks matched# for each knock sequence in the config filefor( keys %knockHash ){# get the timings between knocksmy @confKnocks = split;# if the count of knocks matchif( $knockCount eq @confKnocks ){my $knockDiff = 0;my $counter = 0;for( $counter=0; $counter<$knockCount; $counter++ ){$knockDiff = abs($confKnocks[$counter] - $baseKnocks[$counter]);my $knkStr = "k $counter b $baseKnocks[$counter] "."c $confKnocks[$counter] d $knockDiff\n";# if it's an exact match, increment the matching counterif( $knockDiff < $MAX_KNOCK_DEV ){if( $option ){ print "MATCH $knkStr" }$countMatch++;# if the knocks don't match, move on to the next pattern in the list}else{if( $option ){ print "DISSONANCE $knkStr" }last;}# deviation check}#for each knock}#if number of knocks matches# if the count of knocks is an exact match, run the commandif( $countMatch eq @confKnocks ){my $cmd = system( $knockHash{"@confKnocks "}{ cmd } );if( $option ){ print "$cmd\n" }last;# otherwise, make the count of matches zero, in order to not reset}else{$countMatch = 0;}}#for keys# if the match count is zero, exit and don't reset variables so a longer# knock sequence can be entered and checkedif( $countMatch == 0 ){ return() }# if a match occurred, reset the variables so it won't match another pattern$knockCount = 0;@baseKnocks = ();}#compareKnockSequences
主程序逻辑
有了子例程,主程序逻辑允许用户创建敲门序列,或者以守护程序模式运行以侦听敲门并执行命令。 当用户为创建模式指定选项-c
,执行第一部分。 一个简单的超时过程用于结束敲除序列。 增加最大超时长度变量,以允许两次敲击之间的暂停时间超过四秒。 如果您将最大超时时间保留为四,程序将结束并打印您当前输入的敲门序列。
清单9.创建序列主要逻辑
if( $option eq "-c" ){print "create a knock pattern:\n";$startTime = getEpochSeconds(); # reset time out startwhile( $timeOut == 0 ){$currTime = getEpochSeconds();# check if there has not been a knock in a whileif( $currTime - $startTime > $MAX_TIMEOUT_LENGTH ){$timeOut = 1; # exit the loop}else{# if a knock has been entered before timeout, reset timers so# more knocks can be enteredif( $knockCount != $knockAge ){$startTime = $currTime; # reset timer for longer delay$knockAge = $knockCount; # synchronize knock counts}# if a new knock came in}# if timer not reachedknockListen();select(undef, undef, undef, $SLEEP_INTERVAL);}#timeOut =0if( @baseKnocks ){print "place the following line in $ENV{HOME}/.knockFile\n\n";for( @baseKnocks ){ print "$_ " }print "_#_ (command here) _#_ <comments here>\n\n";}#if knocks entered
主要逻辑的第二部分侦听无限循环中的敲门声,每个循环中睡眠大约百分之一秒。 在此循环中还使用了基于秒的超时,以在足够的延迟后重置敲除序列。 请注意,在此示例中,爆震监听超时为2秒,而最大超时长度为4秒。 这提供了在爆震创建模式期间的简单测试设置,以及在爆震序列监听模式下的快速重置选项。
清单10.敲听主要代码
}else{# main code loop to listen for knocking and run commandsreadKnockFile();$startTime = getEpochSeconds();while( $timeOut == 0 ){$currTime = getEpochSeconds();if( $currTime - $startTime > $LISTEN_TIMEOUT ){$knockCount = 0;@baseKnocks = ();$startTime = $currTime;if( $option ){ print "listen timeout - resetting knocks \n" }}else{if( $knockCount != $knockAge ){$startTime = $currTime; # reset timer for longer delay$knockAge = $knockCount; # synchronize knock counts}# if a new knock came incompareKnockSequences();}#if not reset timeoutknockListen();select(undef, undef, undef, $SLEEP_INTERVAL);}#main knock listen loop}# if create or listen for knocks
警告,安全
tickAge程序非常适合为系统提供用户输入的其他渠道。 但是,请警惕使用kickAge在系统上执行任何需要身份验证的操作。 是的,它可以击败窃听密码的按键记录器,但是还有许多其他与“敲击身份验证”相关联的变量表明,在任何严重的情况下使用此充其量为时过早。 爆震序列当前存储为〜/ .knockFile中延迟的4-9位数字表示(以微秒为单位)。 读取此“密码”文件相对容易,只需尝试和匹配敲门模式即可访问该系统。 可以通过消除微秒值中的某些精度来使用单向哈希,但是此练习最好留给希望自己评估风险的读者。
在任何恶劣的环境中部署之前,应进行研究以确定用户是否具有足够可变和精确的敲门装置。 例如,我们是否具有时空运动技能来创建并持续输入可接受强度的敲门密码? 一般人的大脑是否有能力直观地处理敲击序列? 还是我们都将使用“剃头和理发”作为我们的密码?
翻译自: https://www.ibm.com/developerworks/opensource/library/l-knockage/index.html
敲门代码python
敲门代码python_适用于Linux笔记本电脑的基于敲门的命令相关推荐
- svn(subversion)代码版本管理在linux下的一些常见使用命令
以下的操作都是默认你的服务器安装有svn的大前提下进行的. 一.创建版本库 我的版本库存放路径为: /var/svn : 下面我们来创建一个名为 svntet 的版本库 注释: svnadmin ...
- linux端口转发到windows,Linux及Windows基于工具的端口转发
Linux及Windows基于工具和命令的端口转发配置 wget http://www.boutell.com/rinetd/http/rinetd.tar.gz&&tar -xvf ...
- linux 版本号 笔记本_2019 年最佳 Linux 笔记本电脑发行版 top10
今天我为你提供一个2019年最佳Linux笔记本电脑发行版top10的Linux发行版列表,数据来源于网络以及参照DistroWarch上相关数据. 01.Deepin Deepin 是一个非常漂亮的 ...
- 2019 年最佳 Linux 笔记本电脑发行版 top10
今天我为你提供一个2019年最佳Linux笔记本电脑发行版top10的Linux发行版列表,数据来源于网络以及参照DistroWarch上相关数据. 01.Deepin Deepin 是一个非常漂亮的 ...
- 适用于 Linux 桌面的 7 大白板应用程序
使用这七个适用于 Linux 的白板应用程序以可视方式展示您的想法或计划事情. 向虚拟会议的过渡使办公室团队能够在家工作,并为学生提供电子学习.鉴于使用技术进行教育.管理工作量和以身作则,一个新时代正 ...
- 最佳Linux笔记本电脑编程
如果你是一名程序员和Linux用户,笔记本电脑可能是你最好的朋友,也可能是你最坏的敌人,这取决于你的选择.选择一台功能强大的机器,你会得到一个可靠的伙伴,你可以带着它去任何地方,用它把你的想法变成成熟 ...
- linux桌面版排行2019_2019 年最佳 Linux 笔记本电脑发行版 top10
2019 年最佳 Linux 笔记本电脑发行版 top10 今天我为你提供一个2019年最佳Linux笔记本电脑发行版top10的Linux发行版列表,数据来源于网络以及参照DistroWarch上相 ...
- notepad linux,适用于Linux的11种最佳Notepad ++替代品
Notepadd ++是一个完全免费的源代码编辑器 ,作为Windows上的 Notepad的替代品而创建 - 基于Scintilla在C ++中编写,并实现了Win32 API和STL,以确保程序大 ...
- linux 版本号 笔记本_观点|2018 年度最佳 Linux 笔记本电脑:来自一位 RHCE 的选购指南...
如果你不具备相关的知识和经验,挑选出最适合 Linux 的笔记本电脑,可能是件很困难的事.并且,看上去你买了一台配置.功能.性能都很棒的电脑,但是,却疲于处理各种 Linux 的问题,太难堪了!因此, ...
最新文章
- 深入微服务 API 网关之架构实践篇
- oracle中escape关键字用法
- 基于3G网络的汽车防盗报警系统视频监控设计[图]
- 让jQuery Tools Scrollable控件在Mobile Web里面支持resize功能
- 天正电气t20电气设定在哪_天正电气CAD布置烟感火灾探测器步骤教程
- 怎样查看Oracle的数据库SID和用户名
- IIS7报“假”正式版随Server 2008发布
- redis 可视化工具_自荐一个有情怀的跨平台Redis可视化客户端工具——RedisViewer...
- SilverLight小游戏
- UVA10679 I Love Strings!!【字符串匹配】
- OpenBlock:针对EveryBlock.com源码的开源拓展项目
- python初级数据分析师薪资_数据分析师的薪酬大约是多少?
- 局域网共享文件的方法
- linux版高德导航软件下载,高德导航下载2021年最新版本_高德导航2021手机版下载-太平洋下载中心...
- 百度地图API基本使用(一)
- Moto Photon4g 电信3G历程
- 国内杀毒软件的发展史
- 每周分享第 31 期
- 第三方App接入微信登录 解读 (微信开放平台)
- 微信公众号(二)每日推送详细教程(AI回复助手)