学习目录:树莓派学习之路-GPIO Zero

官网地址:http://gpiozero.readthedocs.io/en/stable/recipes.html

环境:UbuntuMeta-16.04

树莓派:3代B型

2、基本方法(Basic Recipes)

下面演示了GPIO Zero库的一些功能,注意的是这些方法都是在python3下编写的,在python2下可能有用也可能没有用!

2.1 导入GPIO Zero

使用GPIO Zero库有两种方式

2.1.1 单独导入GPIO Zero库的某个类

导入 GPIO Zero 的 Button :

from gpiozero import Button

现在 Button 就可以直接在脚本中使用:

button = Button() #2为Button的引脚

2.1.2 完整导入GPIO Zero库

或者,导入整个GPIO Zero库:

import gpiozero

在这种情况下,GPIO Zero中对项目的所有引用都必须加上前缀(gpiozero):

button = gpiozero.Button()    #2为Button的引脚

2.2. Pin 编号

该库使用Broadcom(BCM)引脚编号作为GPIO引脚,而不是物理(BOARD)编号。 与RPi.GPIO库不同,这是不可配置的。

2.3 开关一个LED

不断的打开和关闭LED灯

from gpiozero import LED
from time import sleep red = LED() #led的正极接GPIO17 while True:
red.on() #开灯
sleep()
red.off() #关灯
sleep()

或者也可以两一种写法:

from gpiozero import LED
from signal import pause red = LED() #led的正极接GPIO17
red.blink() #闪烁

pause()

 2.4 改变LED的亮度

任何常规LED都可以使用PWM(脉冲宽度调制)设置其亮度值。 在GPIO Zero中,可以使用PWMLED来实现,PWMLED的值从0到1:

from gpiozero import PWMLED
from time import sleep led = PWMLED() while True:
led.value = # 灭
sleep()
led.value = 0.5 # 半亮
sleep()
led.value = # 全亮
sleep()

类似于连续闪烁,PWMLED可以脉冲(连续淡入和淡出),以下实现呼吸灯的效果:

from gpiozero import PWMLED
from signal import pause led = PWMLED() led.pulse() #呼吸灯的效果 pause()

 2.5 加入一个按钮

按钮的连接如下图

检查是否按下了按钮:

from gpiozero import Button

button = Button()

while True:
if button.is_pressed:
print("按钮已经按下")
else:
print("按钮没有被按下")

一直等待按钮被按下:

from gpiozero import Button

button = Button()

button.wait_for_press()  #等待按钮被按下
print("按钮已经按下")

每次按下按钮的时候运行一个方法:

from gpiozero import Button
from signal import pause def say_hello():
print("Hello!") button = Button() button.when_pressed = say_hello #当被按下时执行 say_hello 方法,注意不能写为say_hello()
pause()

同样的,按钮被释放时也可以执行一个方法:

from gpiozero import Button
from signal import pause def say_hello():
print("Hello!") def say_goodbye():
print("Goodbye!") button = Button() button.when_pressed = say_hello #当被按下时执行 say_hello 方法
button.when_released = say_goodbye #当被释放时执行 say_goodbye 方法
pause()  

2.6 使用一个按钮控制led灯

按下按钮时打开LED:

from gpiozero import LED, Button
from signal import pause led = LED() #定义一个led灯
button = Button() #定义一个button button.when_pressed = led.on #开灯
button.when_released = led.off #关灯 pause()

或者:

from gpiozero import LED, Button
from signal import pause led = LED() #定义一个led灯
button = Button()  #定义一个button
led.source = button.values 

pause()

 2.7 按钮控制摄像头

当按下按钮时触发 PiCamera 拍照,使用 when_pressed = camera.capture 的写法是无效,因为capture()方法需要输出参数。

但是,这可以使用不需要参数的自定义函数来实现:

from gpiozero import Button
from picamera import PiCamera
from datetime import datetime
from signal import pause button = Button()
camera = PiCamera() def capture():
ctime = datetime.now().isoformat()
camera.capture('/home/pi/%s.jpg' % ctime) #保存图片 button.when_pressed = capture pause()

另外可以使用一个按钮来启动和停止相机预览,另一个按钮用来拍照:

from gpiozero import Button
from picamera import PiCamera
from datetime import datetime
from signal import pause left_button = Button()
right_button = Button()
camera = PiCamera() def capture():
ctime = datetime.now().isoformat()
camera.capture('/home/pi/%s.jpg' % ctime) left_button.when_pressed = camera.start_preview
left_button.when_released = camera.stop_preview
right_button.when_pressed = capture pause()

 2.8 实现按钮关机

Button类还提供了在按钮按住一段给定时间后运行函数的功能。

下面的示例是,当按钮按住2秒时,将关闭树莓派:

from gpiozero import Button
from subprocess import check_call
from signal import pause def shutdown():
check_call(['sudo', 'poweroff']) #运行shell shutdown_btn = Button(, hold_time=) #定义按钮,以及持续时间
shutdown_btn.when_held = shutdown pause()

 2.9 LEDBoard(灯组)

可以使用LEDBoard访问LED组合灯:

from gpiozero import LEDBoard
from time import sleep
from signal import pause leds = LEDBoard(, , , , ) #定义一组led灯,该组由引脚分别为5, 6, 13, 19, 26的5个led组成 leds.on()  #全亮
sleep()
leds.off()   #全灭
sleep()
leds.value = (, , , , ) #1,3,5亮,2,4灭
sleep()
leds.blink()  #全部闪烁 pause()

使用带有pwm = True的LEDBoard,可以控制每个LED的亮度:

from gpiozero import LEDBoard
from signal import pause leds = LEDBoard(, , , , , pwm=True) leds.value = (0.2, 0.4, 0.6, 0.8, 1.0)  #单独设置每个led的亮度 pause()

在高级LEDBoard方法中,可以看到更多LEDBoard示例。

2.10 LEDBarGraph(柱状图)

可以使用LEDBarGraph将LED组合为柱状图:

from gpiozero import LEDBarGraph
from time import sleep graph = LEDBarGraph(, , , , , pwm=False)  #定义一组led柱状灯,该组由引脚分别为5, 6, 13, 19, 26的5个led组成,不设置每个灯的亮度

#以下值,类似于电量100%显示
graph.value = / # (0.5, , , , )
sleep()
graph.value = / # (, 0.5, , , )
sleep()
graph.value = -/ # (, , , 0.5, )
sleep()
graph.value = / # (, , , , 0.5)
sleep()
graph.value = / # (, , , , 0.75)
sleep()

可以看到上面的值都是四舍五入的,当pwm = False(默认值)时,LED要么是打开要么是关闭。

但是,使用带有pwm = True的LEDBarGraph可以使用LED亮度获得更精确的值:

from gpiozero import LEDBarGraph
from time import sleep graph = LEDBarGraph(, , , , , pwm=True)  #定义一组led柱状灯,该组由引脚分别为5, 6, 13, 19, 26的5个led组成,设置每个灯的亮度 graph.value = / # (0.5, , , , )
sleep()
graph.value = / # (, 0.5, , , )
sleep()
graph.value = -/ # (, , , 0.5, )
sleep()
graph.value = / # (, , , , 0.5)
sleep()
graph.value = / # (, , , , 0.75)
sleep()

 2.11 Traffic Lights(交通灯)

一个交通灯系统。

使用像Pi-Stop这样的TrafficLights套件:

from gpiozero import TrafficLights
from time import sleep lights = TrafficLights(, , ) #一组交通灯 lights.green.on()  #绿灯亮 while True:
sleep()
lights.green.off()  #绿灯灭
lights.amber.on()  #黄灯亮
sleep()
lights.amber.off()  #黄灯灭
lights.red.on()  #红灯亮
sleep()
lights.amber.on()  #黄灯亮
sleep()
lights.green.on()  #绿灯亮
lights.amber.off()  #黄灯灭
lights.red.off()  #红灯灭

另外;

from gpiozero import TrafficLights
from time import sleep
from signal import pause lights = TrafficLights(, , ) def traffic_light_sequence():
while True:
yield (, , ) # green
sleep()
yield (, , ) # amber
sleep()
yield (, , ) # red
sleep()
yield (, , ) # red+amber
sleep() lights.source = traffic_light_sequence() pause()

使用LED组合:

from gpiozero import LED
from time import sleep red = LED()
amber = LED()
green = LED() green.on()
amber.off()
red.off() while True:
sleep()
green.off()
amber.on()
sleep()
amber.off()
red.on()
sleep()
amber.on()
sleep()
green.on()
amber.off()
red.off()

2.12. Push button stop motion:

每按一次按钮,使用相机模块拍摄一张照片:

from gpiozero import Button
from picamera import PiCamera button = Button()
camera = PiCamera() camera.start_preview()
frame =
while True:
button.wait_for_press()
camera.capture('/home/pi/frame%03d.jpg' % frame)
frame +=

有关完整资源,请参阅 Push Button Stop Motion 。

2.13. Reaction Game(反应游戏):

当你看到灯亮起时,第一个按下按钮的人就赢了!

from gpiozero import Button, LED
from time import sleep
import random  #导入随机库 led = LED() player_1 = Button()
player_2 = Button() time = random.uniform(, )  #随机产生5到10之间的数
sleep(time)
led.on()  #灯亮 while True:
if player_1.is_pressed:
print("Player 1 wins!")
break
if player_2.is_pressed:
print("Player 2 wins!")
break led.off()  #灯灭

有关完整资源,请参阅 Quick Reaction Game

 2.14. GPIO Music Box(GPIO音乐盒):

每一个按钮会发出不一样的声音!

from gpiozero import Button
import pygame.mixer
from pygame.mixer import Sound
from signal import pause pygame.mixer.init() button_sounds = {
Button(): Sound("samples/drum_tom_mid_hard.wav"),
Button(): Sound("samples/drum_cymbal_open.wav"),
} for button, sound in button_sounds.items():
button.when_pressed = sound.play pause()

有关完整资源,请参阅 GPIO Music Box

2.15. All on when pressed(全部打开时按下):

按下按钮时,蜂鸣器和所有指示灯亮起。

FishDish:

from gpiozero import FishDish
from signal import pause fish = FishDish() fish.button.when_pressed = fish.on
fish.button.when_released = fish.off pause()

Ryanteck TrafficHat:

from gpiozero import TrafficHat
from signal import pause th = TrafficHat() th.button.when_pressed = th.on
th.button.when_released = th.off pause()

使用LED,蜂鸣器和按钮组合:

from gpiozero import LED, Buzzer, Button
from signal import pause button = Button()
buzzer = Buzzer()
red = LED()
amber = LED()
green = LED() things = [red, amber, green, buzzer] def things_on():
for thing in things:
thing.on() def things_off():
for thing in things:
thing.off() button.when_pressed = things_on
button.when_released = things_off pause()

2.16. Full color LED(全彩LED):

使用RGBLED产生色彩:

from gpiozero import RGBLED
from time import sleep led = RGBLED(red=, green=, blue=) led.red = # full red
sleep()
led.red = 0.5 # half red
sleep() led.color = (, , ) # full green
sleep()
led.color = (, , ) # magenta
sleep()
led.color = (, , ) # yellow
sleep()
led.color = (, , ) # cyan
sleep()
led.color = (, , ) # white
sleep() led.color = (, , ) # off
sleep() # slowly increase intensity of blue
for n in range():
led.blue = n/
sleep(0.1)

2.17. Motion sensor(运动传感器):

运动传感器检测到运动时点亮LED:

from gpiozero import MotionSensor, LED
from signal import pause pir = MotionSensor()
led = LED() pir.when_motion = led.on
pir.when_no_motion = led.off pause()

 2.18. Light sensor(光敏传感器):

需要有个光敏传感器,可以检测有光和黑暗:

from gpiozero import LightSensor

sensor = LightSensor()

while True:
sensor.wait_for_light()
print("It's light! :)")
sensor.wait_for_dark()
print("It's dark :(")

当光线改变时执行一个函数:

from gpiozero import LightSensor, LED
from signal import pause sensor = LightSensor()
led = LED() sensor.when_dark = led.on
sensor.when_light = led.off pause()

或者根据检测到的光线强弱改变PWMLED的亮度:

from gpiozero import LightSensor, PWMLED
from signal import pause sensor = LightSensor()
led = PWMLED() led.source = sensor.values pause()

2.19. Distance sensor(距离传感器):

注意:在上图中,可以省略从传感器通向面包板的导线; 只需将传感器直接插入边缘的面包板中。

让DistanceSensor可以检测到最近的物体的距离:

from gpiozero import DistanceSensor
from time import sleep sensor = DistanceSensor(, ) while True:
print('Distance to nearest object is', sensor.distance, 'm')
sleep()

当某物接近传感器时执行一个函数:

from gpiozero import DistanceSensor, LED
from signal import pause sensor = DistanceSensor(, , max_distance=, threshold_distance=0.2)
led = LED() sensor.when_in_range = led.on
sensor.when_out_of_range = led.off pause()

2.20. Motors(电机):

向前和向后旋转电机:

from gpiozero import Motor
from time import sleep motor = Motor(forward=, backward=) while True:
motor.forward()
sleep()
motor.backward()
sleep()

 2.21. Robot(机器人)

让机器人在一个大致正方形的区域中四处走动:

from gpiozero import Robot
from time import sleep robot = Robot(left=(, ), right=(, )) for i in range():
robot.forward()
sleep()
robot.right()
sleep()

制作一个带有距离传感器的机器人,当侧得距离小于20厘米时,机器人就会转弯:

from gpiozero import Robot, DistanceSensor
from signal import pause sensor = DistanceSensor(, , max_distance=, threshold_distance=0.2)
robot = Robot(left=(, ), right=(, )) sensor.when_in_range = robot.backward
sensor.when_out_of_range = robot.stop
pause()

2.22. Button controlled robot(使用按钮控制机器人)

使用四个按钮作为机器人的前进/后退/左/右控制键:

from gpiozero import Robot, Button
from signal import pause robot = Robot(left=(, ), right=(, )) left = Button()
right = Button()
fw = Button()
bw = Button() fw.when_pressed = robot.forward
fw.when_released = robot.stop left.when_pressed = robot.left
left.when_released = robot.stop right.when_pressed = robot.right
right.when_released = robot.stop bw.when_pressed = robot.backward
bw.when_released = robot.stop pause()

2.23. Keyboard controlled robot(使用键盘控制机器人)

使用上/下/左/右键来控制机器人:

import curses
from gpiozero import Robot robot = Robot(left=(, ), right=(, ))

actions = {
curses.KEY_UP: robot.forward,
curses.KEY_DOWN: robot.backward,
curses.KEY_LEFT: robot.left,
curses.KEY_RIGHT: robot.right,
} def main(window):
next_key = None
while True:
curses.halfdelay()
if next_key is None:
key = window.getch()
else:
key = next_key
next_key = None
if key != -:
# KEY DOWN
curses.halfdelay()
action = actions.get(key)
if action is not None:
action()
next_key = key
while next_key == key:
next_key = window.getch()
# KEY UP
robot.stop() curses.wrapper(main)

注意:此方法使用的是标准curses模块。 此模需要在Python的终端中运行才能正常工作,因此此方法在IDLE等环境中不起作用。

如果你更喜欢在IDLE下工作的版本,则以下方法应该足够:

from gpiozero import Robot
from evdev import InputDevice, list_devices, ecodes robot = Robot(left=(, ), right=(, )) # Get the list of available input devices
devices = [InputDevice(device) for device in list_devices()]
# Filter out everything that's not a keyboard. Keyboards are defined as any
# device which has keys, and which specifically has keys .. (roughly Esc,
# the numeric keys, the first row of QWERTY plus a few more) and which does
# *not* have key (reserved)
must_have = {i for i in range(, )}
must_not_have = {}
devices = [
dev
for dev in devices
for keys in (set(dev.capabilities().get(ecodes.EV_KEY, [])),)
if must_have.issubset(keys)
and must_not_have.isdisjoint(keys)
]
# Pick the first keyboard
keyboard = devices[] keypress_actions = {
ecodes.KEY_UP: robot.forward,
ecodes.KEY_DOWN: robot.backward,
ecodes.KEY_LEFT: robot.left,
ecodes.KEY_RIGHT: robot.right,
} for event in keyboard.read_loop():
if event.type == ecodes.EV_KEY and event.code in keypress_actions:
if event.value == : # key down
keypress_actions[event.code]()
if event.value == : # key up
robot.stop()

注意:此方法使用第三方evdev模块。 首先使用sudo pip3 install evdev安装此库。 请注意,evdev仅适用于本地输入设备; 这个方法不适用于SSH。

 2.24. Motion sensor robot(运动传感器机器人)

检测到运动时让机器人向前行驶:

from gpiozero import Robot, MotionSensor
from signal import pause robot = Robot(left=(, ), right=(, ))
pir = MotionSensor() pir.when_motion = robot.forward
pir.when_no_motion = robot.stop pause()

或者:

from gpiozero import Robot, MotionSensor
from signal import pause robot = Robot(left=(, ), right=(, ))
pir = MotionSensor() robot.source = zip(pir.values, pir.values) pause()

 2.25. Potentiometer(电位器)

 

连续打印连接到MCP3008模数转换器的电位计值(0到1之间的值):

from gpiozero import MCP3008

pot = MCP3008(channel=)

while True:
print(pot.value)

使用PWM在LED条形图上显示电位计的值,以表示状态不会“填满”LED:

from gpiozero import LEDBarGraph, MCP3008
from signal import pause graph = LEDBarGraph(, , , , , pwm=True)
pot = MCP3008(channel=)
graph.source = pot.values
pause()

2.26. Measure temperature with an ADC(使用ADC测量温度)

将TMP36温度传感器连接到MCP3008模数转换器的第一个引脚:

from gpiozero import MCP3008
from time import sleep def convert_temp(gen):
for value in gen:
yield (value * 3.3 - 0.5) * adc = MCP3008(channel=) for temp in convert_temp(adc.values):
print('The temperature is', temp, 'C')
sleep()

2.27. Full color LED controlled by 3 potentiometers(由3个电位器控制全彩LED)

连接三个电位器(红色,绿色和蓝色)并使用它们的每个值来产生LED的颜色:

from gpiozero import RGBLED, MCP3008

led = RGBLED(red=, green=, blue=)
red_pot = MCP3008(channel=)
green_pot = MCP3008(channel=)
blue_pot = MCP3008(channel=) while True:
led.red = red_pot.value
led.green = green_pot.value
led.blue = blue_pot.value

或者,以下示例产生相同的效果,但使用的是source属性而不是while循环:

from gpiozero import RGBLED, MCP3008
from signal import pause led = RGBLED(, , )
red_pot = MCP3008()
green_pot = MCP3008()
blue_pot = MCP3008() led.source = zip(red_pot.values, green_pot.values, blue_pot.values) pause()

注意:上面的示例需要Python 3的环境。在Python 2中,zip()不支持延迟评估,因此脚本将挂起。

 2.28. Timed heat lamp(定时加热灯)

如果你有宠物(例如乌龟)需要每天开启一定时间的加热灯,您可以使用Energenie Pi-mote远程控制灯,TimeOfDay类来控制时间:

from gpiozero import Energenie, TimeOfDay
from datetime import time
from signal import pause lamp = Energenie()
daytime = TimeOfDay(time(), time()) lamp.source = daytime.values
lamp.source_delay = pause()

2.29. Internet connection status indicator(Internet连接状态指示灯)

你可以使用一对绿色和红色LED展示你的互联网连接是否正常工作。 只需使用PingServer类来确定是否ping通google.com。 如果成功,绿色LED点亮,如果不成功,红色LED点亮:

from gpiozero import LED, PingServer
from gpiozero.tools import negated
from signal import pause green = LED()
red = LED() google = PingServer('google.com') green.source = google.values
green.source_delay =
red.source = negated(green.values) pause()

2.30. CPU Temperature Bar Graph(CPU温度条形图)

你可以使用内置的CPUTemperature类读取Raspberry Pi自己的CPU温度,并在LED的“条形图”上显示:、

from gpiozero import LEDBarGraph, CPUTemperature
from signal import pause cpu = CPUTemperature(min_temp=, max_temp=)
leds = LEDBarGraph(, , , , , , , pwm=True) leds.source = cpu.values pause()

2.31. More recipes(更多方法)

继续:

2、基本方法(Basic Recipes)的更多相关文章

  1. Eigen库矩阵运算使用方法

    Eigen库矩阵运算使用方法 Eigen这个类库,存的东西好多的,来看一下主要的几个头文件吧: ——Core 有关矩阵和数组的类,有基本的线性代数(包含 三角形 和 自伴乘积 相关),还有相应对数组的 ...

  2. 树莓派学习之路-GPIO Zero

    原来用的都是RPi.GPIO模式开发,写程序 今天看到了GPIOZERO的资料,觉得这个API还是很好用的, 唯一的缺点就是官方资料是英文的,而且目前这方面的资料也不多, 所以开始写这篇博文,将自己学 ...

  3. 12、API - 输入设备(API - Input Devices)

    学习目录:树莓派学习之路-GPIO Zero 官网地址:https://gpiozero.readthedocs.io/en/stable/api_input.html 环境:UbuntuMeta-1 ...

  4. 关于如何使用Identity的文献

    有几篇文件,深入浅出地讲解了如何一步一步的使用Identity,感觉十分有用,留下链接,备查. 1. Configuring Db Connection and Code-First Migratio ...

  5. Mastering Web Application Development with AngularJS 读书笔记(三)

    第一章笔记 (三) 一.Factories factory 方法是创建对象的另一种方式,与service相比更灵活,因为可以注册可任何任意对象创造功能.例如: myMod.factory('notif ...

  6. 基于搜狗搜索的微信公众号爬虫实现(C#版本)

    Author: Hoyho Luo Email: luohaihao@gmail.com Source Url:http://here2say.me/11/ 转载请保留此出处 本文介绍基于搜狗的微信公 ...

  7. [转载] Linux curl命令详解

    转载自http://www.linuxdiyf.com/linux/2800.html 命令:curl在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,可以说是一款很强大的htt ...

  8. [Arxiv1706] Few-Example Object Detection with Model Communication 论文笔记

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px "Helvetica Neue"; color: #042eee } p. ...

  9. [Linux][转载]Curl命令详解

    命令:curl 在Linux中curl是一个利用URL规则在命令行下工作的文件传输工具,是一款很强大的http命令行工具,当处在无界面的服务器上的时候,利用curl下载上传文件是较为方便的事情. 语法 ...

随机推荐

  1. Django | 解决“(1146, "Table 'mydb.django_session' doesn't exist")”报错的方法

    我只写了下面一行 就生成了session表 manage.py makemigrations sessions manage.py migrate sessions 参考:https://www.cn ...

  2. 荣耀TCL都玩智慧屏“噱头”,海信却引行业未来方向

    编辑 | 于斌 出品 | 于见(mpyujian) 如今手机联接我们生活方方面面的同时,大家却也由此习惯了低头示人.据美国的一家数据研究中心显示,目前中国智能手机普及率已达到68%,居民日均手机屏幕使 ...

  3. git 基本操作小节操作(一) init clone status add 未完,参考链接在末尾

    1 $ git init 对当前所在目录进行git 管理 在当前目录初始化新仓库 2 $ git clone <url> <position> 从url克隆一个仓库到posti ...

  4. Android 系统签名

    在做android产品开发的时候,很多时候都需要使用系统签名(比如在使用uid,APK升级的时候),所以,android提供给我们自定义签名文件的工具.这里将流程记录下来: 1.进入/android_ ...

  5. lvm磁盘扩容

    LVM实现新挂载磁盘扩容到原有目录 #查看磁盘 fdisk -l #创建pv pvcreate /dev/sdb [root@VM-67-49 ~]# pvcreate /dev/sdb Physic ...

  6. android 代码设置图标背景色(圆形图标)和图标颜色

    原图: 1.改变图标颜色: mImageView.setColorFilter(Color.parseColor("#ff0000")); 效果: 2.改变图标背景色(主要是圆形图 ...

  7. AcWing 104. 货仓选址

    #include <iostream> #include <algorithm> using namespace std; ; int n; int q[N]; int mai ...

  8. PHP Apache/Nginx/IIS等各环境下的伪静态配置

    一.Apache的伪静态配置 1.网站根目录下需要有 .htaccess 文件,没有则自己创建一个,内容如下: <IfModule mod_rewrite.c> RewriteEngine ...

  9. nuxt导入css样式

    全局导入,适用于所有组件 在nuxt.config.js文件引 css:["~样式path"], 如:css:["~assets/css/main.css"], ...

  10. WLC5520分布式端口(数据口)使用1G模块!

    思科WLC5520有两个分布式端口.  在 10G 模式和 1G 模式之间切换•如果在端口 1 上未安装任何内容,则默认情况下主板配置为 10G 模式.因此,要切换到 1G 模式,则必须在端口 1上安 ...