在树莓派上实现人脸识别

介绍

预计在不久后的将来,人脸识别和身份认证技术将在我们的日常生活中扮演一个非常重要的角色。这项技术为我们开辟了一个全新的世界,它几乎适用于我们生活的方方面面。面部识别/身份认证的使用案例包括安全系统、认证系统、个性化智能家居和家庭护理助理等。

我们将搭建什么?

本教程将帮助你建立一个可以训练 HARASCALDES 模型的树莓派,该模型可用于检测已识别的/未识别过的人,使用监控摄像头进行实时监控,并利用物联网 JumpWay 来发送传感和警告消息,进而允许你的设备利用其他物联网 JumpWay 网与其他设备进行通信。

本教程将利用 TechBubble Technologies 物联网 JumpWay Python MQTT 库进行通信,利用 OpenCV 实现计算机视觉,在本地端口上建造移动 Web 流和安全的 NGNX 服务器,以便可以安全地从外部访问视频流。

这个例子是我们最初的 TASS 版本,因为我们的进步依靠了很多更先进的计算机视觉库和框架,所以我们决定将代码进行开源。

Python 版本

2.7 版本

3.4 或更高版本

软件要求

Jessie

TechBubble IoT JumpWay Python MQTT Client(https://github.com/TechBubbleTechnologies/IoT-JumpWay-Python-MQTT-Clients)

Linux 驱动

Nginx

硬件要求

树莓派

Linux 兼容摄像头

准备工作

在开始之前,有几个教程你应该看一下,尤其是如果这是你第一次按照我们的树莓派教程,或者如果这是你第一次使 TekBaseIO-JavaWoW 开发程序。如果这是你第一次在物联网项目中使用 TechBubble IoT JumpWay,在你创建 IOT 设备之前需要注册开发帐户,并在进行一些基本的设置。访问下面的物联网 JumpWay 开发者使用文档(5-10 分钟阅读/设置 https://github.com/TechBubbleTechnologies/IoT-JumpWay-Docs/),并查看引导来进行注册并设置你的位置、区域、设备和应用程序(大约 5 分钟)。

物联网 JumpWay 开发者程序文档 (5-10 分钟 阅读/设置 https://github.com/TechBubbleTechnologies/IoT-JumpWay-Docs/)

准备你的树莓派(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/1-Raspberry-Pi-Prep.md)

设置区域名字 & 树莓派的 SSL(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/3-Raspberry-Pi-Domain-And-SSL.md)

在你的树莓派上配置 OpenCV(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/2-Installing-OpenCV.md)

在你的树莓派上配置 Linux 驱动(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/5-Installing-Motion.md)

在树莓派上为 Linux 驱动安装(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/6-Secure-Nginx-Server-For-Motion.md)

用 IPTables 确保树莓派的安全(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/4-Securing-Your-Raspberry-Pi-With-IPTables.md)

准备你的树莓派

花一些时间来确保你的树莓派的硬件和包都是最新的,并且确保你的准备过程严格按照树莓派 3 的教程文件(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/1-Raspberry-Pi-Prep.md),设备是安全的。

复制 Repo

你将需要将 echBubble IoT JumpWay (https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples)树莓派实例 Examples 示例库下载到你的树莓派上,并导航到你想下载的目录,以下命令是将其下载到主目录最简单的方式。

git clone https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples.git

安装要求

接下来,你需要将计算机视觉库导航到目录并按照要求进行安装,如果你已经将库复制到你的主目录上,那么这一部分的命令如下:

cd IoT-JumpWay-RPI-Examples/Computer-Vision/Python pip install –upgrade pip pip install -r requirements.txt

安装 OpenCV

OpenCV 需要遵循树莓派教程(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/2-Installing-OpenCV.md)进行安装,它是我们将使用的一种计算机视觉库。

安装 Linux 驱动

我们将使用 Linux 驱动把视频流传送到树莓派本地端口上,OpenCV 在这里连接到视频流并从中读取图像帧。为了建立 Linux 驱动,遵循安装教程(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/5-Installing-Motion.md)在你的树莓派教上安装 Linux 驱动。

这里有一些修改,在驱动安装教程的第 9 部分中,它告诉你如何修改媒体的保存目录,在本教程中,你应该将这些设置更改为:

/home/YOURUSERNAME/IoT-JumpWay-RPI-Examples/Computer-Vision/Python/media

不要忘记注意第 10 部分中关于关闭图像保存来节省磁盘空间的问题。

设置域名和 SSL

我们希望我们提供的教程可以确保帮助人们学会创建安全的项目。为了使视频流安全工作,你需要设置指向你的树莓派域名,你也需要设置 SSL 证书来确保用于视频流的服务器是安全的。树莓派域名和 SSL 设置教程(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/3-Raspberry-Pi-Domain-And-SSL.md)会向你详细解释如何做到这一点,如果有疑问,你可以让你的注册员或主机来协助你。如果你将这个存储库复制到你的主目录中,你需要使用如下的 CSR 和密钥生成的路径:

/etc/nginx/key.key /etc/nginx/csr.csr

一旦你从证书颁发机构收到你的签名 crt.crt 和 ca.crt 文件,你需要将它们上传到:

/etc/nginx/ca.crt /etc/nginx/crt.crt

为 Linux 驱动安装安全的 NGINX 服务器

我们将使用 NGNIX 作为我们的服务器解决方案,并在 QualSS-SSL 实验室 SSL 报告中将其设置为 A 级+ SSL 等级。为了做到这一点,我们提供了一个可以在 RasBuriPi 上的 Linux 驱动上安装 NGINX 服务器的指南(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/6-Secure-Nginx-Server-For-Motion.md)。在开始这一步之前,你需要在你的树莓派上安装 Linux 驱动(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/5-Installing-Motion.md),并为你的树莓派设置域名和 SSL(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/3-Raspberry-Pi-Domain-And-SSL.md)。

用 IPTables 保证树莓派的安全

下一个你应该采取的安全步骤是设置 IPTABLE。遵循 Securing Your Raspberry Pi With IPTables 文件(https://github.com/TechBubbleTechnologies/IoT-JumpWay-RPI-Examples/blob/master/_DOCS/4-Securing-Your-Raspberry-Pi-With-IPTables.md)来实现这一点。

视频流

如果你遵循了以上步骤,如果它们还没有运行,你需要按照下面的步骤操作。

sudo service motion start 或 sudo /etc/init.d/motion start 启动 NGINX sudo service nginx start 或 sudo /etc/init.d/nginx start

重要的是:这种流式传输是一个新的特性,我们仍然在消除一些扭结,如果你想让 OpenCV 直接访问网络摄像头,而不需要驱动/NGNIX 流,那么在 TASS.py 重取消注释 43 行,注释 44 行和 45 行。

连接证书和传感设置

下一步是在互联网 JumpWay 开发者控制台中安装设备实例。遵循 IoT JumpWay Location Device Doc (https://github.com/TechBubbleTechnologies/IoT-JumpWay-Docs/blob/master/4-Location-Devices.md)来设置你的设备。你将需要设置一个有闭路监控的设备,并且添加了传感器/执行器部分。

检索你的连接证书并用新的连接证书和相机 ID 设置更新配置文件 JSON 文件(你需要在创建它之后进入设备页面以获得正确的摄像头 ID)。

“IoTJumpWaySettings”: { “SystemLocation”: 0, “SystemZone”: 0, “SystemDeviceID”: 0, “SystemDeviceName” : “Your Device Name”, “SystemCameraID”:0 } “IoTJumpWayMQTTSettings”: { “username”: “Your MQTT Username”, “password”: “Your MQTT Password” }

训练你的数据

现在基本构架已经搭建好,是时候用你自己的照片训练你的模型了。当你下载这个 RPO 时,在那个被处理的文件夹中已经有一个经过训练的模型和被处理的图像,但是这个模型不会识别你。你需要选择自己在不同的位置和灯光下的照片。你训练模型的照片越多,它就越精确,如果你的设备没有识别你,你只需要用更多的图像来训练它。

你可以添加你喜欢的图片(这取决于你的树莓派 3 可用的空间),有很多像你这样人。为了将训练数据导航到训练文件夹中并创建目录,目录应该是一个数字,而且不是那个已处理文件夹中的数字。

一旦你建立了图像的文件夹,进入 Tas.Py 文件改变第 34 行(self.train = 0)为 self.train = 1,并启动程序。程序将循环检测你的图像,如果它检测到脸部,它将以模型所需的格式重新创建一个图像,将其保存到匹配文件夹处理后的目录中中,并删除原始图像以节省空间。如果它没有检测到面部,它将简单地删除原始图像,因为它是无效的面部识别。

一旦处理阶段完成,你的新模型将自动开始训练,训练完成后,它将自动运行主面部识别程序。把你的脸放在你连接的摄像头前面,看着程序的输出你是谁。

注意:从处理目录中删除 read me 文件。

执行程序

sudo python/python3 TASS.py

自主物联网通信

当你的设备每次检测到一个人时,设备会把传感器数据传送到 TechBubble IoT JumpWay(https://iot.techbubbletechnologies.com/),当运动传感器检测到入侵者时会发出警报。你可以使用传感器值和警告消息与连接到 IoT JumpWay Location 的其他设备实现自主通信。

在「设备编辑」页面上,向下滚动到「执行器/传感器」下的「创建规则」部分。你可以在这里利用下拉菜单创建规则,允许你的设备发电子邮件给你,或者在状态更新、传感器数据和警告的情况下自主地与其网络上的其他设备进行通信。

查看数据

每次你的设备检测到一个人或一个入侵者,它将发送数据到 TechBubble IoT JumpWay。你将能够访问 TechBubble IoT JumpWay 开发区中的数据(https://iot.techbubbletechnologies.com/developers/dashboard/)。一旦登录到开发区,访问 TechBubble IoT JumpWay Location Devices Page 页面(https://iot.techbubbletechnologies.com/developers/location-devices),找到你的设备,然后访问传感器/执行器页和警告页,查看从你的设备发送的数据。物联网 JumpWay 树莓派计算机视觉实例缺陷/问题

当你在运行物联网 JumpWay 树莓派计算机视觉实例遇到困难时请保持一种释然,当你遇到麻烦时你也可以在提问区寻求帮助。

物联网 JumpWay 树莓派实例贡献者

TechBubble 科技公司创始人:Adam Milton Barker(https://github.com/AdamMiltonBarker)

TechBubble Technologies Dev 公司:Andrej Petelin(https://github.com/AndrejPetelin)

原文链接:https://www.hackster.io/AdamMiltonBarker/facial-recognition-identification-on-raspberry-pi-1c7495

转自雷锋网:https://club.leiphone.com/page/TextTranslation/624

用树莓派自制 MIDI 键盘

MAKER:midiIdentifier/译:趣无尽 Cherry(转载请注明出处)

本教程将手把手教你从零开始自制属于你自己的 MIDI/钢琴/音乐/歌曲键盘。这是一个基于树莓派的开源项目,其中所需的文件在本项目文件库中可以找到。

如果你是70后、80后,你会认出部分的设计。我们的灵感主要来自Apple II。标志性的特点有底部正面略微向上的角度,以及略微向上倾斜的键盘(如图)。

物件清单

1、树莓派3B型 × 1

2、电容式触摸显示屏7寸× 1(Waveshare 树莓派 3.5英寸触摸屏 TFT LCD(A)320 * 480)

3、扬声器 × 2

4、Midi USB 键盘 × 1

5、胶合板 × 若干(约3mm厚)

6、热熔胶 × 1

软件依赖

在为midiIdentifier安装实际软件之前,首先需要安装许多依赖项。其中大部分都可以使用“apt-get”工具进行安装,该工具预装在每个Raspbian OS发行版上。在下面你可以找到安装相应依赖项所需的特定命令,包括依赖项功能的简要说明。

依赖项说明如下:

1、一个干净的Raspbian OS

2、Fluidsynth合成软件(播放音乐的音频输出和音频生成所需):

sudo apt-get install fluidsynth

从以下URL下载Fluidsynth声音字体:

https://sourceforge.net/p/fluidsynth/wiki/SoundFont/

SOUNDFONT,顾名思义,就是“声音字体”。档案储存为 .SF 或 .SF2。 它是几年前 ( 2000年 & 2001年第二版本 ) 由 新加坡创新公司 Creative Technology 在中档声卡上 (EMU SoundBlaster)使用的音色库技术。它是用字符合成的,一个Sound Fond表现出一组音乐符号。用MIDI键盘输入乐符时,会自动记下MIDI的参数,最后在Sound Fond中查找,当你需要它时,就下载到声卡上。

设置Fluidsynth自动启动:

crontab -e

添加以下行:

@reboot /usr/bin/screen -dm /usr/bin/fluidsynth -a alsa -m alsa_seq -i -s -o “shell.port=9988″ -g 2 /FluidR3_GM.sf2

3、安装Py-Audio(各种声音输入和输出功能所需):

sudo apt-get install python3-pyaudio

4、Telnet(需要连接到负责音频输出的Fluidsynth服务器):

sudo apt-get install telnet

5、Screen(作为后台任务所运行的应用程序):

sudo apt-get install screen

6、Git(需要下载midiIdentifier软件/克隆代码库)

sudo apt-get install git

显示设置

需要对 Raspbian OS 初始配置,以便支持触摸屏。具体需要对启动配置文件进行各种更改。请注意,对这些配置文件的随意的更改可能会使树莓派无法正常启动。

1、使用文本编辑器(nano)打开启动配置文件。需要root权限(sudo)才能对文件进行更改。用于打开和编辑文件的命令如下:

sudo nano /boot/config.txt

添加以下行(如果已存在,请删除现有行)

max_usb_current=1 hdmi_group=2 hdmi_mode=87 hdmi_cvt 1024 600 60 6 0 0 0 hdmi_drive=1

请注意不要在“=”符号前后包含任何空格。

保存并关闭文件。如果你使用的是nano,请执行以下操作:

Press CTRL + X

Type “Y” and press Enter

2、将显示器随机连接到HDMI和树莓派的USB端口上。

3、打开背光(开关在显示屏的背面)。

4、重启树莓派。

MidiIdentifier 软件

在下文中,我们假设应用程序将在名为“pi”的用户下运行。如果不是这种情况,则需要相应地调整目录路径(/home/[你的用户名])。

1、使用以下命令从Github克隆midiIdentifier仓库:

git clone https://github.com/Andreas-Scholz/midiIdentifier.git

2、将仓库添加到Pythonpath。

打开文件~/.bashrc(使用 nano,方法参考上一步)。

添加以下行:

PYTHONPATH=”${PYTHONPATH}:/home/pi/workspace/midiIdentifier/src”

保存文件,然后使用以下命令重新加载它:

. ~/.bashrc

注意命令中的空格,重启树莓派。

3、设置应用程序的自动启动。

在主目录中创建一个名为“start_gui.sh”的文件,并添加以下行:

#!/bin/bash sleep 3 cd /home/pi/workspace/midiIdentifier/src/guiMI python3 /home/pi/workspace/midiIdentifier/src/guiMI/gui.py sleep 30

打开文件 ~/.config/lxsession/LXDE-pi/autostart 并添加以下行:

@lxterminal -e /home/pi/start_gui.sh

4、为了让 midiIdentifier 跑起来,需要将一组midi文件手动复制到midi目录中。为避免侵犯版权,我们的git仓库中不包含这些文件。但是,可以通过Google搜索从各种在线资源下载它们。下载文件后,需要将它们复制到以下目录中:

/home/pi/workspace/midiIdentifier/files/new_midi

在此之后,需要使用以下命令解析midi文件:

python3 /home/pi/workspace/midiIdentifier/src/converterMI/midiToText.py

5、重启树莓派。

恭喜你,你做到了!到现在为止,midiIdentifier 应该能正常运行啦!

制作外壳

如果你有激光切割机,这部分将非常简单。

外壳尺寸为:450mm x 100mm x 300mm(宽/高/长),因此你需要一个至少能够切割450mm x 250mm(这是最大的单件尺寸)的激光切割机。

或者,你可以将一些零件拆分成子零件,这样你就可以使用更小的激光切割机来构建壳体。

此外,如果你使用较小的键盘,你通常可以使用较小的构建。在这个项目中,我们使用3毫米厚的胶合板。你需要设置好激光切割机的速度和功率才能获得良好的效果。

切割屏幕框和整个案例所需的所有文件都可以在本项目文件库中下载到。

http://make.quwj.com/project/67

可选:如果你想修改我们的构建模型或者你只是对设计激光切割机文件的过程感兴趣,请继续阅读:

在纸上绘制基本草图以便了解尺寸,我们使用Adobe Illustrator设计激光切割机的文件(你可以从网站获得1周的测试版本)。然而,我们没有绘制每一个凹槽,这里有一个很棒的免费在线工具可以帮助你,Joinery。我们将AI文件导出为SVG并将其导入Joinery,我们将不同的边缘相互连接。 Joinery允许你定义不同角度的配置文件,以便稍后重复使用,并允许保存项目。

因此,Joinery资料和切割资料如下。如果你想对我们的设计进行微小的更改,这些特别有用,当涉及到切割的公差等时,它们比adobe illustrator文件更容易更改。

midiIdentifier_lasercutter_files.zip

midiIdentifier_joinery_files.zip

将所有一切组合在一起

安装好树莓派上的软件(并测试它是否正常工作)并切割所有胶合板,你就可以开始组合软件和硬件了。

1、首先,除了背面的板子外,你应该将整个外壳组合在一起。此外,不要连接屏幕盒,这将是最后一步。如果你想用胶水加固,你可以试试。

2、将钢琴键从后面嵌入到外壳,确保将其嵌入成功。将它靠在木头上并测量需要切割的部件的高度以将其固定到位。切割这些碎片(2到3片)并将它们固定在钢琴键和盒子的底座上,将钢琴键保持在应该放置的位置,并确保按下琴键后不会移动。

3、安装完板子后,随后将扬声器的活动铰链放在主箱体内。你可以使用热熔胶或胶水。在下面放一些木块做支撑,这样即使稍后放置盒子,它们也会保持水平。

4、将整个屏幕盒(内部屏幕,通过盒子底部孔突出的电缆)通过活动铰链连接到主体箱上。

5、在主体箱内部添加一个木块,以便在折叠到主体箱时,屏幕盒仍可以保持水平位置(如图)。支撑木块的地方可以用一段铁管支撑屏幕,以便屏幕可以在不同的角度直立。

6、将扬声器安装到木板上(我们使用双面胶)。为了方便运输,屏幕和盒子可以折回到主箱体内!

7、最后,将所有电缆连接到树莓派。

就是这样,完成了!希望你喜欢我们的教程!

via

用树莓派自制 MIDI 键盘

用树莓派制作带谷歌日历的日程时钟

MAKER:samvanhook/译:趣无尽 Cherry(转载请注明出处)

在不同的平台上频繁的查看日程安排(例如手机日历、电子邮件、协同工作平台等)常常会分散人们的注意力。有没有办法把这些零碎的日程统一展示在一个小设备上呢?答案是肯定的!

下面将创建一个时钟项目,来解决这个问题。当我想要确认日程安排时,简单地看一看墙壁,看看墙上显示的未来12小时的Google日历就行(墙内使用的话当然也可以换用其他平台的API,来接入其他日程管理系统替代Google日历)。这种方式可以让我迅速的回到工作状态而不是去查看详细的信息。当我对日历感到好奇时,轻轻一瞥就行。当我的思绪在别处时,它的出现也不会有违和感。

如果你想学习如何制作,请按照以下方法来操作吧!

材料清单:

10平方英寸椴木板 × 1

亚克力板 × 1(白色或透明)

树莓派 Zero W × 1

NeoPixels LED 灯条 × 若干

时钟机芯套件 × 1

电线 × 若干(用于焊接)

USB接口供电线 × 1

切割时钟的面板

使用CNC数控机床来切割出时钟的面板。

你可以使用此模型:http://make.quwj.com/file/90/download

大多数CNC数控机床都可以,因为使用的是椴木板。

打磨圆形边缘

通过砂光机打磨圆形边缘,完成时钟的主题部分。椴木板打磨出来的效果非常不错。此外,在主体中心钻一个孔,以便将机芯安装在后面。

切割并安装亚克力板

使用激光切割机,直接切割出从3D CAD模型中获取的形状。只需要打磨,它们就可以贴合在一起而不需要使用任何粘合剂(你可以在这里找到一些所需文件https://github.com/swoolf/enchantedObjects/tree/master/calClock

现在,你可以制作并安装表示12,3,6,9钟点的十字架。我用了一块薄薄的桃花心木,并用超级胶水粘贴。

电子部分

将NeoPixels LED灯安装到一块背板上。手动将24个灯焊接在一起。安装时会有些乏味,但能掌握了技巧也不错。

接下来,将树莓派焊接到位并合上外壳。

如果你有多余的亚克力板,你可以为给时钟添加一个漂亮的装饰。

你可以在这里找到我使用的软件程序(Python):https://github.com/swoolf/enchantedObjects/tree/master/calClock

你还要对Google Calendar python API进行一些操作(需要自备梯子):https://developers.google.com/calendar/quickstart/python

最后,设置你的树莓派,让程序开机自动运行就完成了!

用树莓派制作带谷歌日历的日程时钟

五周年纪念:树莓派 HiFi DAC Zero 扩展板开售

今天是个特别的日子,五年前的今天(2013年8月24日)树莓派开始在中国流行,我们建立了树莓派实验室网站,最初的名字是“树莓派笔记”。在树莓派爱好者们的关注和陪伴下一路走到现在,沉淀了丰富的树莓派教程和资讯,在此向大家表示感谢!

除了感谢之外,在五周年的纪念日里,我们决定推出一款小玩意 —— HiFiDAC Zero,这是之前发布的 HiFiBox DAC 扩展板的缩小版,功能和兼容性与大版一样,仅在尺寸上做了缩小,完美适配树莓派 Zero W 的尺寸。

我们将所有元件设计在扩展板的背面,这样安装在树莓派上之后,扩展板同时起到了上盖的作用。

同时我们还制作了一套底壳,作为附件提供。

下面是和树莓派 Zero W 组合之后的样子!方便小巧,带上充电宝就可以出街了有没有!

详细介绍链接:

树莓派 HiFi DAC Zero 扩展板

购买点这里。

趣无尽微信公众号(quwjcom)粉丝在我店购买我们的 DAC 系列扩展板,订单下留言“五周年生快”即可获得“GPIO 参考卡片(黑金版)”一块,送完即止。

最后,期待在未来的时间能推出更多好玩的东西和有趣的内容给大家,祝各位周末愉快!

树莓派 VNC Viewer 远程桌面配置教程

树莓派实验室在之前介绍过《直接用Windows远程桌面连接树莓派的方法》,使用的是微软的“远程桌面(Remote Desktop Connection)”作为客户端登录树莓派。下面我们介绍使用树莓派官方认证的 RealVNC 客户端登录树莓派的方法。

在开始之前,你需要已经登录树莓派,进入到树莓派命令窗口,通过接上显示器和键鼠直接操作或通过 SSH 登录都可以。

启用树莓派 VNC 服务

在终端输入以下命令进入配置界面。

sudo raspi-config

依次操作:Interfacing Options -> VNC -> Yes。之后系统会提示你是否要安装 VNC 服务,输入 y 之后回车,等待系统自动下载安装完成,一切顺利的话 VNC 服务就启动了!

安装 VNC 客户端

下面去 RealVNC 官网下载 RealVNC Viewer,它是 RealVNC 的客户端,跨平台。下载你需要的平台的客户端版本即可。

Viewer

登录远程桌面

运行 RealVNC Viewer 之后输入树莓派的 IP 地址,通过 ifconfig 命令可以查看。选择连接之后输入树莓派的登录用户名密码,初始用户名 pi,密码为 raspberry。确认之后即可进入树莓派的远程桌面!

如果要修改树莓派的分辨率,可以在终端运行 sudo raspi-config 进入设置界面设置操作。

用树莓派 DIY 180度小球追踪摄像头

MAKER: yusuf_ /译:趣无尽 Cherry(转载请注明出处)

在比赛直播或一些需要实时追踪目标物体的拍摄场合,有一台智能化的摄像设备将是非常有用的。本教程将简单说明如何用树莓派、摄像头和机械设备来 DIY 一套具有180度跟踪拍摄小球功能的智能摄像头。

先看一段最终的效果视频。

材料清单

1、树莓派

2、L298N H-Bridge 电机驱动板

3、电机齿轮箱

4、USB网络摄像头

5、跳线

6、螺母螺丝

7、齿轮

8、环氧胶/热熔胶

9、激光发射器(可选)

组装配件

1、用一块木料(我的这块木头还算不错),将电机安装到上面,不要安装到中间的位置。然后,在电机上安装一个小齿轮。齿轮上的孔可能需要扩大以便与电机配件匹配。

2、下一步将安装大齿轮(可以松动),使其大齿轮的齿与小齿轮的相连接。为加强粘合性,用砂纸打磨木板,然后使用热熔胶将其安装到位。

3、将网络摄像头安装到大齿轮上。在这里,我已将网络摄像头的外壳移除,并仅使用网络摄像头的核心电路板,以便安装。使用环氧胶将网络摄像头粘合起来,加强牢固性。

4、最后安装的组件是可选项——L298N H-Bridge 电机驱动板。只需在电路板上钻四个孔并使用机械螺钉和六角螺母安装到电路板上即可。

连线

现在将所有东西用线串起来。

1、将电机的两根电线直接连接到电路板左侧或右侧两个端口连接器之一的 L298N H-Bridge 电机驱动板上(我选择了左侧)。

2、使用两根导线将L298NH的5V和接地线与树莓派的5V和接地线与电源相连接。

3、使用两根母对母跳线将L298N分别连接到树莓派的引脚17和18上。

4、将网络摄像头连接到其中一个树莓派的USB端口上。

这就是所有的布线过程了。

部署程序

这个部分是整个项目最具挑战性的地方。

我用 Python 的 OpenCV 库来实时跟踪小球。先安装这个库。

sudo apt-get update sudo apt-get install python-opencv

本程序还利用树莓派附带的 gpiozero 库,根据 OpenCV 库确定球的 x 坐标来转动电机。该代码能够根据黄色来确定球的位置,所以黄色是背景中独一无二的,否则无效。向程序提供较低和较高的颜色范围,以便确定球的位置。

OpenCV 使用以下参数调用 .inRange() 函数:当前帧(来自网络摄像头)以及下部和上部颜色边界。确定框架上球的坐标后,如果球不在中心(640 像素宽框架中 x 坐标范围为 240-400),程序将告诉电机转动。如果球偏离中心,则马达将加快转动,而当球更靠近中心时,马达将减少转动。

这就是代码的工作原理。

注意:如果你使用该代码,则必须安装 OpenCV。此外,如果电机转向错误,只需将 L289N 的电线反转,或反转控制 gpio 连接到树莓派的线。

所用的源代码文件在本项目文件库中可以下载。

http://make.quwj.com/project/71

运行

用树莓派 DIY 180度小球追踪摄像头

via

基于树莓派的多舵机控制的定位拍照云台

MAKER:mjrovai/译:Cherry(转载请注明出处)

在本教程中,我们将探讨如何在树莓派上使用Python控制多个舵机。 我们的目标是制作一个支持多自由度定位拍照的云台。在这里,你可以看到我们的成品是如何工作的。

主要材料

1、树莓派3 X1

2、摄像头模块 X1

3、9G 180°微型舵机 X2

4、迷你平移/倾斜照相机平台 防振照相机支架(2个舵机)

5、电阻1K欧姆 X2(可选)

6、金属部件

7、固定带等(用于构建云台平台)

你可以购买一个成品的云台平台舵机或自己制作。

PWM如何工作

树莓派不能直接输出模拟电信号,但我们可以使用PWM(脉宽调制)方法来模拟这一点。我们制作一个固定频率的数字信号,在那里我们将改变脉冲宽度,将“转换”改为“平均”输出电压的电平,如下图所示:

我们可以使用这个“平均”电压水平来控制LED亮度,例如:

请注意频率本身不是重点,而是“占空比”,即脉冲“高”的时间除以波周期之间的关系。例如,假设我们在树莓派的 GPIO上产生一个50Hz的脉冲频率。周期(p)将是频率的倒数或20ms(1 / f)。如果我们的LED达到“半”亮度,我们的占空比必须为50%,这意味着“脉冲”将是10ms的“高”。

这个原理对于我们来说非常重要,一旦使用“占空比”来定义舵机位置,如下所示,它用于控制舵机的位置。

安装部件

舵机将连接到外部5V电源,其数据引脚(我的项目中,黄色接线)连接到树莓派GPIO如下:

GPIO 17 ==>仰角舵机

GPIO 27 ==>平移舵机

不要忘记将GND连接在一起 ==> 树莓派 – 舵机 – 外部电源。

你可以在树莓派的GPIO和服务器数据输入引脚之间串联一个1K欧姆的电阻。 如果发生舵机故障,这将保护你的树莓派。

舵机的校准

1、首先你要弄清楚你购买到的舵机的主要特点。在这个项目中,我使用的是Power Pro SG90。

以下是它的数据表,我们可以参考一下:

范围:180°

电源:4.8V(外部可使用USB 5VDC电源)

工作频率:50Hz(周期:20 ms)

脉冲宽度:从1ms到2ms

2、理论上,舵机运转的位置

初始位置(0°):1ms脉冲到数据终端。

中间位置(90°):1.5ms脉冲到数据终端。

最终位置(180°):2 ms脉冲到数据终端。

3、使用Python编写舵机位置,了解上述位置相应的“占空比”非常重要,我们来做一些计算:

初始位置==>(0°)脉冲宽度==> 1ms ==>占空比= 1ms / 20ms ==> 2.0%

中间位置(90°)==> 1.5 ms的脉冲宽度==>占空比= 1.5ms / 20ms ==> 7.5%

最终位置(180°)==> 2 ms的脉冲宽度==>占空比= 2ms / 20ms ==> 10%

所以占空比应该在2%到10%的范围内变化。

4、单独测试舵机

打开树莓派终端并以“sudo”启动你的 Python 3 shell 编辑器(你可能是“超级用户”来处理GPIO):

sudo python3

在Python Shell上导入RPI.GPIO模块并作为GPIO:

import RPi.GPIO as GPIO

定义你自己想要使用引脚编号方案(BCM或BOARD)。我用BOARD做了这个测试,所以我使用的引脚为物理引脚(GPIO 17 =引脚11和GPIO 27引脚13)。对我来说,很容易识别它们,并且在测试过程中不会犯错误(在最终的程序中,我将使用BCM)。按照自己的喜好来选择:

GPIO.setmode(GPIO.BOARD)

定义你要使用的舵机引脚:

tiltPin = 11

如果你已经使用了BCM方案,相反的,将最后2个命令应该替换为:

GPIO.setmode(GPIO.BCM) tiltPin = 17

现在,我们必须指定这个引脚将为“输出”

GPIO.setup(tiltPin, GPIO.OUT)

而且,这个引脚上产生的频率,对于我们的舵机来说应该是50Hz:

tilt = GPIO.PWM(tiltPin, 50)

现在,让我们开始在引脚上设置一个初始占空比(我们将它保持为“0”)的PWM信号:

tilt = start(0)

现在,你可以输入不同的占空比值,观察舵机的运动。让我们从2%开始,看看会发生什么(我们观察舵机从“零位”开始):

tilt.ChangeDutyCycle(2)

我项目的情况是,当我将占空比改为3%时,舵机进入零位。我观察到舵机停留在同一位置,开始以大于3%的占空比移动。所以,3%是我的初始位置(o°)。同样的情况发生在10%,我的舵机超过这个数值,最终达到13%。所以对于这个舵机,最终结果是:

0°==>占空比3%

90°==>占空比8%

180°==>占空比13%

完成测试后,你必须停止PWM并清理GPIO:

tilt= stop() GPIO.cleanup()

上面终端将打印出屏幕显示的数据,我两个舵机的结果非常的相似。你的范围可以不同。

创建 Python 脚本

正如我们在上一步所看到的那样,发送到我们舵机的PWM命令要与“占空比”相对应。但通常情况下,我们必须以角度作为参数来控制舵机。因此,我们必须将“角度”转换为我们工作周期中比较常见的常量,要被Pi所理解的。

怎么做?很简单!我们知道占空比范围从3%到13%,这相当于从0到180度范围内的角度。另外,我们知道这些变化是线性的,所以我们可以构建一个如上所示的比例模式。所以,给定一个角度,我们可以有一个相应的工作周期:

dutycycle = angle/18 + 3

保存这个公式。 我们将在下一个代码中使用它。

我们来创建一个Python脚本来进行测试。 基本上,我们将重复我们之前在Python Shell上做的事情:

from time import sleep import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) def setServoAngle(servo, angle): pwm = GPIO.PWM(servo, 50) pwm.start(8) dutyCycle = angle / 18. + 3. pwm.ChangeDutyCycle(dutyCycle) sleep(0.3) pwm.stop() if __name__ == ‘__main__’: import sys servo = int(sys.argv[1]) GPIO.setup(servo, GPIO.OUT) setServoAngle(servo, int(sys.argv[2])) GPIO.cleanup()

上述代码的核心是设置舵机和角度的函数。 该函数接收参数、舵机、 GPIO编号和舵机必须定位的角度值。 一旦这个函数的输入是“角度”,我们必须使用之前开发的公式将其转换为百分比的占空比。

脚本执行时,必须输入参数,舵机GPIO和角度。

例如:

sudo python3 angleServoCtrl.py 17 45

上述命令会将舵机连接到GPIO 17并且以“仰角”45度定位。 一个类似的命令可以用于平移伺服控制(在“方位角”中位置为45度):

sudo python angleServoCtrl.py 27 45

文件 angleServoCtrl.py 可以在我的 GitHub 下载。

平台移动机制

“平板”舵机将“水平”移动摄像机(“方位角”),而我们的“仰角”舵机将“垂直移动”(仰角)。

下图显示了云台机制的工作原理:

在项目进行过程中,我们不会走向“极端”,我们只能使用30到150度的云台机制。 这个范围足够用于相机。

平台机械结构

现在将两个舵机作为云台进行组装。 你可以在这里做两件事。 购买一个平台或根据您的需求构建自己的平台机制。

我做了一个样板出来,只是将两个舵机捆绑在一起,并用上图中所示的旧玩具的小金属件搭建起来。

组装电动云台组件

组装好云台机制后,请按照图片进行全面电气连接。

1、关闭你的Pi。

2、进行所有电气连接。

3、仔细检查它。

4、首先打开你的Pi。

5、如果一切正常,请给舵机供电。

本教程中我们不会将如何设置相机进行展开。

Python 脚本

让我们创建一个Python脚本来同时控制两个舵机:

from time import sleep import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) pan = 27 tilt = 17 GPIO.setup(tilt, GPIO.OUT) # white => TILT GPIO.setup(pan, GPIO.OUT) # gray ==> PAN def setServoAngle(servo, angle): assert angle >=30 and angle <= 150 pwm = GPIO.PWM(servo, 50) pwm.start(8) dutyCycle = angle / 18. + 3. pwm.ChangeDutyCycle(dutyCycle) sleep(0.3) pwm.stop() if __name__ == '__main__': import sys if len(sys.argv) == 1: setServoAngle(pan, 90) setServoAngle(tilt, 90) else: setServoAngle(pan, int(sys.argv[1])) # 30 ==> 90 (middle point) ==> 150 setServoAngle(tilt, int(sys.argv[2])) # 30 ==> 90 (middle point) ==> 150 GPIO.cleanup()

脚本执行时,必须输入参数,平移角度和倾斜角度。 例如:

sudo python3 servoCtrl.py 45 120

上述命令将使“水平/倾斜”平台在“方位角”(水平角)和120度“仰角”(倾斜角)方向上定位为45°。 请注意,如果未输入任何参数,则默认平移和倾斜角度均为90°。

文件servoCtrl.py可以在我的GitHub下载。

服务器的环路测试

现在让我们创建一个Python脚本来自动测试所有的舵机:

from time import sleep import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) pan = 27 tilt = 17 GPIO.setup(tilt, GPIO.OUT) # white => TILT GPIO.setup(pan, GPIO.OUT) # gray ==> PAN def setServoAngle(servo, angle): assert angle >=30 and angle <= 150 pwm = GPIO.PWM(servo, 50) pwm.start(8) dutyCycle = angle / 18. + 3. pwm.ChangeDutyCycle(dutyCycle) sleep(0.3) pwm.stop() if __name__ == '__main__': for i in range (30, 160, 15): setServoAngle(pan, i) setServoAngle(tilt, i) for i in range (150, 30, -15): setServoAngle(pan, i) setServoAngle(tilt, i) setServoAngle(pan, 100) setServoAngle(tilt, 90) GPIO.cleanup() 程序将自动从30°到150°两个角度进行循环。 结果如下: 我只连接了一台示波器来说明如前所述的PWM理论。 以上源代码 servoTest.py 可以在GitHub下载。 结语 一如既往,我希望这个项目能够帮助他人进入激动人心的电子世界! 有关详细信息和最终代码,请访问我的 GitHub 仓库:RPi-Pan-Tilt-Servo-Control MAKER 趣无尽项目主页:http://make.quwj.com/project/56 via

使用树莓派 Zero 实现带回显的新型 Bad USB

本文转自 strcpy.me,封面图为配图:安装了 Zero Quick Plug 的树莓派 Zero。

小编按:USB中间人是什么?USB HID设备是如何工作的?下面带你了解 BADUSB 在树莓派上的实现。文中所列举的案例仅供理解需要,请勿不当使用此类技术。

某天小黑以修理网络的名义潜入某公司办公室,想窃取一位运维台式机上的某个私钥文件,根据之前的信息收集,该公司电脑不能连接外网,而且有 DLP 产品监控的 agent,插入优盘后会提示,如果向优盘复制文件,会立即报警,文件也会被加密,无线网卡类设备也也不可以,只有键盘鼠标可以随便使用。办公环境下有一个 SSID 和密码已知的 guest 网络,可以访问外网。这种情况下怎么窃取私钥,并尽可能长时间的维持权限呢?

现有的 BadUSB 设备的缺点

底层硬件和驱动修改复杂

BadUSB 火了有几年了,网上的教程也是花式繁多,主要分为 Teensy 系列和 USB Rubber Ducky 系列,它们是使用 Arduino 或者优盘实现的,相对来说制作的难度比较大,因为宽泛来说都是属于”嵌入式编程”了,而且因为很多固件并不是真正开源的,是通过各种 Hack 实现的。还有一点就是这个硬件平台都是很简化的,想增加功能,还受到硬件的限制。

单向数据传递,没有回显,无法更新 Paylaod

黑客在进行渗透测试的时候,很是很讨厌没有回显的洞的,因为看不到是否执行成功,甚至看不到执行结果,只能靠运气和人品。而且设备插上之后,是否成功就已经决定了,即使执行失败,也没有办法去更新和修复自己的 Payload,不是一个持久化的方案。我们希望的是能实现攻击者、BadUSB 和受害者三部分两条链路的长时间的双向通信。

遇到密码就懵逼

如果你的 Payload 会弹出 UAC 或者需要 root 权限,那基本上避免不了需要输入密码了。有几个办法可以尝试下,首先是通过社工尝试收集密码字典然后暴力尝试,其次是自带一个提权脚本,很多洞的提权脚本并不长,而且很好用,最后那就是寄希望于人品了,如果对方直接就是使用的高权限用户,那就是人品大爆发了。这个问题的解决方案我们会放在展望章节中,并不在这一次的文章中解决。

树莓派也可以做 BadUSB?

一般来说,USB 设备有两种,一种是 Host,比如电脑,可以去读取其他 USB 设备的数据,另外一种是 Device,比如键盘鼠标优盘。所以从根本上来说,制作一个 Bad USB 核心要求只有一个,就是自身可以作为 USB Device。参考 https://electronics.stackexchange.com/questions/49140/what-exactly-are-the-difference-between-a-usb-host-and-device

市面上稍早些的树莓派,比如树莓派2B,树莓派3等,它们都只支持作为 Host,而迷你的树莓派 Zero 和 Zero w 同时支持作为 Host 和 Device。

和 Zero 比,Zero w 主要是增加了 WiFi 和蓝牙,所以以下都是用的这个型号,官方价10刀,某宝大约需要25刀才能买到。缺点是体积稍大,长度略长,而宽度就是正常优盘的两倍多了。

电脑怎么知道我是一个键盘的

http://www.usb.org/developers/hidpage/Hut1_12v2.pdf 是 HID 设备(人机交互设备)的部分通信协议,不需要看的太仔细,有大致印象,需要的时候会再回来翻阅。

树莓派中运行的是更加熟悉的 Linux,系统已经集成了很多底层驱动,不用接触硬件细节,想声明自己是一个键盘也非常简单。

声明 USB HID 设备

USB Gadget 实现了 USB 协议定义的设备端的软件功能,它需要一些配置,比如声明设备类型,序列号等。如果要创建一个 USB Gadget,就需要先配置那些信息。

Linux 中一切皆文件,配置也是,使用创建文件和目录的方式就可以操作 configfs,告诉内核相关的配置,这一段就是围绕着这个来的。

在 https://www.kernel.org/doc/Documentation/usb/gadget_configfs.txt 也有相关的配置说明。

首先,每个 gadget 都有一个独立的文件夹,先创建一个

cd /sys/kernel/config/usb_gadget/ mkdir -p g1 cd g1

然后需要 vender id 和 product id 等信息,这里我们用别人的id

echo 0x1d6b > idVendor # Linux Foundation echo 0x0104 > idProduct # Multifunction Composite Gadget echo 0x0100 > bcdDevice # v1.0.0 echo 0x0200 > bcdUSB # USB2

每个设备还需要序列号,制造商等信息,Linux 要求的是在一个子文件夹中存储

mkdir -p strings/0x409 echo “fedcba9876543210” > strings/0x409/serialnumber echo “Valentin Brosseau” > strings/0x409/manufacturer echo “Keyboard-dev” > strings/0x409/product

接下来是创建配置了,都是在 configs/. 中的

C=1 mkdir -p configs/c.$C/strings/0x409 echo “Config $C” > configs/c.$C/strings/0x409/configuration echo 1000 > configs/c.$C/MaxPower

然后是需要创建一些功能的描述,是在 functions/. 中的

mkdir -p functions/hid.$N echo 1 > functions/hid.usb0/protocol echo 1 > functions/hid.usb0/subclass echo 8 > functions/hid.usb0/report_length echo -ne \\x05\\x01\\x09\\x06\\xa1\\x01\\x05\\x07\\x19\\xe0\\x29\\xe7\\x15\\x00\\x25\\x01\\x75\\x01\\x95\\x08\\x81\\x02\\x95\\x01\\x75\\x08\\x81\\x03\\x95\\x05\\x75\\x01\\x05\\x08\\x19\\x01\\x29\\x05\\x91\\x02\\x95\\x01\\x75\\x03\\x91\\x03\\x95\\x06\\x75\\x08\\x15\\x00\\x25\\x65\\x05\\x07\\x19\\x00\\x29\\x65\\x81\\x00\\xc0 > functions/hid.usb0/report_desc

最后是关联配置和功能的文件夹和启用设备

ln -s functions/hid.$N configs/c.$C/ ls /sys/class/udc > UDC

其中在创建功能描述的时候,有一些 Magic number,这些都是需要参考 USB 输入设备的协议规定的。

对于 HID 设备来说, protocol 和 subclass 都是1, report_length 是8,然后 report_desc 是比较复杂的结构。暂时不用关心,后面才会用到。

大家可以参考 https://github.com/c4software/pi-as-keyboard 的初始化脚本。

这就做完了

注意:树莓派 Zero 有两个 micro USB,一个标记 USB,一个标记 PWR,要使用标记 USB 的那个(题图红框区域),否则只能供电。

Linux 上 lsusb 就可以看到这个设备

Bus 001 Device 011: ID 1d6b:0104 Linux Foundation Multifunction Composite Gadget

Mac上显示是这样的

我们先简单的测试下,在树莓派上把

for run in {1..10} do echo -ne “\x00\x00\x00\x17\x00\x00\x00\x00” > /dev/hidg0 echo -ne “\x00\x00\x00\x00\x00\x00\x00\x00” > /dev/hidg0 done

保存为 test.sh ,然后使用 root 权限运行,如果看到看到自动输出了一堆字母 t ,那就说明成功了一大半了。但是字符串是怎么转换为上面的一堆指令的呢?这时候要引入 KeyCode 的概念。

KeyCode 顾名思义就是一个键就是一个编号,告诉系统对应的编号就可以。具体的实现是

[modifier, reserved, Key1, Key2, Key3, Key4, Key6, Key7]

的结构,第一位是代表一些特殊的按键,比如 Ctrl、Shift 等,后面的6位就是指哪些键被按下了,它最多支持键盘上同时按下6个键。

在上文提到的 USB 协议 PDF 的 10 Keyboard/keypad page(0x07) 章节规定了所有的 KeyCode,可以查阅,网上也有一些转换脚本。然后通过输入连续的8个 null 数据,代表按键结束了。

在协议中,大小写字母还有部分数字和符号的 KeyCode 是一样的,这个时候,需要修改第一个位为 Shift,和平时使用键盘是一样的。比如

# t \x00\x00\x00\x17\x00\x00\x00\x00 # T \x02\x00\x00\x17\x00\x00\x00\x00

如果使用 Python 实现的话,就是

with open(“/dev/hidg0”, “wb”) as f: for item in s: s, k = letter_to_keycode(item) f.write(s + “\x00” + k + “\x00” * 5) f.write(“\x00″ * 8) f.flush()

至此,如果我们将对应的指令修改为创建后门(下载文件执行、上传文件到网络等等)的命令,然后插入后自动运行脚本,那市面上常见的 BadUSB 就制作完成了。

树莓派安装小贴士

如果 systemctl status enable_hid 出现 enable_hid.sh[623]: /usr/bin/enable_hid.sh: line 27: 636 Segmentation fault ls /sys/class/udc > UDC ,请降级系统,这个问题目前已经修复但是没有发布。可以使用命令 rpi-update 2ca627126e49c152beb1bf7abd7122ce076dcc65 回退到和我一样的版本。

出现 ,请降级系统,这个问题目前已经修复但是没有发布。可以使用命令 回退到和我一样的版本。 树莓派写存储卡镜像之后,在存储卡根目录创建一个 wpa_supplicant.conf 的文件,内容是 network={ ssid=”WiFi SSID” psk=”WiFi 密码” key_mgmt=WPA-PSK }

然后创建一个 ssh 文件,内容为空,这样树莓派启动之后会自动联网和开启 ssh,默认用户名密码是 pi:raspberry 。

下面才是重点

但是我们不能满足于此,上面提到的问题一个都没解决呢。

自带网卡和蓝牙的树莓派

相对其他 BadUSB 的平台,树莓派 Zero w 自带网卡和蓝牙,这样我们就可以实现远程的交互了。比如可以使用蓝牙在实施攻击的初期进行配置,比如 WiFi 密码和 Payload 类型,之后就可以使用 client,通过 socket 远程加密连接到控制端,如果发现 Payload 有 bug 或者有更好的 Payload 就可以随时更新了,是不是很棒。

黑夜中的那盏灯

键盘特点是用来输出,很多人认为 Host 无法给键盘写入数据,其实并不是的。

键盘上按下 Caps Lock,再打开了系统自带的软键盘,点击软键盘的 Caps Lock,这个灯是会熄灭的,也就是键盘上的 LED 灯也是可以被软件控制的,主机也会发送信号给键盘的。

回归原始的0和1

还记得使用硬盘灯进行边信道攻击的新闻么 ,虽然看起来有些魔幻,但是确实有人能做到,所以我们也要做到。

在 Linux 上,可以使用 Input 子系统 Event Interface 来控制 LED 灯或者使用 sysfs 控制,但是系统怎么知道我们有多少个灯呢,怎么知道我们支持哪些灯呢?这就要回到开头的 HID report_desc 和协议 11 LED Page (0x08) 章节了,在那一长串数据中隐藏了 LED 灯的秘密。

我们的定义是

0x95, 0x05, // Report Count (5) 0x75, 0x01, // Report Size (1) 0x05, 0x08, // Usage Page (LEDs) 0x19, 0x01, // Usage Minimum (Num Lock) 0x29, 0x05, // Usage Maximum (Kana)

但是通过测试发现下面两个 “feature” ,让这个用法变得困难

Linux 只能最多展示控制5个灯的状态(这是我 descriptor 写的不对还是特性?)

每个灯发送的控制指令和上一次的不一致才可以收到这个信号

图的上半部分是声明了3个 LED 灯,下半部分是声明了6个 LED 灯,但是实际只能显示出5个。

向 input7::capslock/brightness 写入0或者1可以改变对应灯的状态,但是这里一次只能改变一个,而且重复写入相同的状态,在树莓派上是收不到的。可以在树莓派上使用脚本读取 /dev/hidg0 设备查看。

这种 “feature” 就阻碍了数据的传输,因为这是一次可以传递 n bit (n 为灯的数量)数据的带宽,但是现在的情况下到底还能不能传递数据了呢?答案是肯定的,那就是使用两个 bit 代表一个 bit 的数据。

使用 00 和 01 状态代表数据0,使用 10 和 11 状态代表数据1,假设初始状态为 00 ,如果下一位是1,则使用 10 状态,只改变第一个灯的开关,如果下一位还是0,那使用 01 状态,以此类推,就可以发现,无论下一位是什么状态,总可以只改变一个灯的状态,这一点和数字电路中的格雷码有点像。

state_table = [[0b01, 0b10], [0b00, 0b11], [0b00, 0b11], [0b01, 0b10]] last_state = 0 def write_data(data): global last_state for item in data: cur_value = int(item != “0”) last_state = state_table[last_state][cur_value] # print “data”, item, “cur value”, cur_value, “cur_state”, last_state for i in range(2): # print “write led”, i, “value”, int((last_state & (i + 1)) != 0) write_led(i, int((last_state & (i + 1)) != 0))

这个在代码层面上就是写对应的 brightness 文件或者使用 Input Event 实现,其中 LED 的 code 是 EV_LED 。使用 Python 实现的简化代码如下

# 写 sysfs if led == 0: path = “/sys/class/leds/input23::numlock/brightness” else: path = “/sys/class/leds/input23::capslock/brightness” with open(path, “w”) as f: f.write(str(value)) time.sleep(0.001) # Input Event fd = os.open(device_path, os.O_WRONLY) now = time.time() sec = int(now) usec = int((now – sec) * 1.0E6) data = struct.pack(‘@llHHI’, sec, usec, 0x11, led, value) os.write(fd, data) os.close(fd)

经过测试,写 sysfs 要比 Input Event 快一些,但是每次 write 之间最好 sleep 1毫秒,否则可能出现一些奇怪的数据(黑人问号,我也不知道为啥啊)。总体上可以实现也就比 56k 猫才慢百倍的带宽。

美中不足的是:

需要 BadUSB 输入一个脚本或者可执行文件,然后才可以与键盘交互。这也是所有 BadUSB 存在的问题。 bit 传递数据太暴力了,如果中间有一位丢失或者发生错误,可能导致整个数据乱掉,如果想实现一些更高级的校验,就会进一步的降低带宽。 Linux 上操作 sysfs 和使用 Input Event 都需要 root 权限。

控制键盘 LED 的代码,Mac版本的实现在 https://developer.apple.com/library/content/samplecode/HID_LED_test_tool/Introduction/Intro.html,Windows版本的实现在 https://github.com/dnet/usbpwn-host,并没有测试这两个平台上的权限情况。

大道至简

虽然实现了交互,但是这个速度并不能让人满意。我们需要去更底层上去操作设备,从而规避上面的这些问题,那就是 hidraw 。在内核的相关文档中, 提到说这个接口是底层的底层接口,部分非标准的设备可以使用它传递原始数据。

hidapi https://github.com/signal11/hidapi 库实现了三平台上的向 HID 设备写 raw 数据的 API hid_write 。(Linux 上需要 root 权限,据说 Windows 上不需要特殊权限?)

以 Linux 为例,其实逻辑非常非常简单,使用 Python 描述就是

fd = os.open(“/dev/hidraw1”, os.O_RDWR) os.write(fd, data) os.close(fd)

而且这个是可读的,也就是你在树莓派中向 /dev/hidg0 写入的数据,这里可以直接读取到,而且不会再触发输入动作。除了第一步写 client,之后就再也不需要使用键盘打开 shell,输入,然后快速关闭 shell 的流程了,可以在后台完成一切的操作。这个也大大的降低了被发现的几率。

我们发现事情是越做越简单了,而且这个接口速度要快的多,一般的命令执行结果,都几乎可以实时读取到。

攻击小 tips

在插入 BadUSB 设备之后,不要立即调用键盘输入,毕竟人坐在电脑前面还是能注意到一个一闪而过的黑框的,可以先模拟按下大写锁定键,如果发现很快就切换回了小写状态,那用户很可能正在使用电脑,如果长期没有响应,那可能用户不在电脑前面。

展望

USB 中间人

还记得某宝上的硬件 USB 键盘记录器么

但是这种键盘记录器只能被动的记录,无法传输记录的内容,如果我们的 BadUSB 和这种 keyLogger 结合在一起就大有作为了。

一种场景是先默默的记录键盘输入,然后自动或者人工筛选可能是密码的值,比如 sudo $command 后面跟的一串奇怪的字符串,之后使用密码获取更高权限植入传输脚本和传输数据。

在某宝上还有一种带 GPS 和 SIM 卡的 USB 数据线,相信把 BadUSB 做成这样的体积也不难。

使用优盘启动

在2016年 Geekpwn 上,有一个环节叫”机器人挑战赛”,来自哈尔滨理工大学的选手薛恩鹏实现了使用机器人给电脑插入优盘窃取资料,但是我并不清楚实现的细节,可能是在 BIOS 中设置为优盘启动(类似安装操作系统的流程),在硬盘没有加密的情况下就可以完全绕过主机里面的 DLP 产品。BadUSB 也可以使用相同的思路,因为我们的树莓派也是完全可以将自己模拟为一个优盘的。

Bad Bridge

其实薛恩鹏的机器人还可以做的更多,比如使用机器拔掉电脑的网线,然后植入 Throwing Star LAN Tap 类似的流量抓包工具,360也有一款类似的产品,原理都很简单,就是 Hub。

可以使用树莓派作为抓包端,兼顾 BadUSB,就可以实现实时的流量中转了。

防范

安全意识,不要随便插来历不明的 USB 设备,不仅仅是优盘,包括键盘鼠标。

USB 白名单,DLP 产品应该使用更加严格的 USB 限制策略。

全盘加密,对开机密码、root密码等引入多因素认证。

8月3日,Red Hat 发表文章,声称 Red Hat Enterprise Linux 7.4 版本开始集成 USBGuard 软件框架,利用黑白名单等技术抵御流氓 USB 设备的攻击。

感谢

树莓派+Flask实现视频流媒体WEB服务器

在这个项目中我们将主要学习两个模块。

流式传输视频

将视频集成到Web服务器上

材料清单

1、树莓派V3 X1

2、树莓派3 B型带NoIR夜间相机 X1

3、DHT22温度传感器 X1

4、DHT22相对湿度传感器 X1

5、电阻4K7欧姆 X1

在这个项目中,我使用的是夜间相机,你也可使用普通的树莓派相机(或任何USB相机)来替代。DHT22为可选。在教程中,我将演示如何将视频流传输到WEB页面,并用传感器来显示历史数据。

安装摄像机

1、关闭树莓派,将相机安装在其特定端口上,如下所示:

2、打开你的树莓派并转到树莓派配置工具的主菜单上,并确认相机接口是否开启:

如果你需要开启它,请按[确定]并重新启动你的树莓派。

做一个简单的测试来验证一切是否正常:

raspistill -o /Desktop/image.png

你会看到,在到你树莓派桌面上会出现一个图像图标。 点击打开它。 如果出现图像,说明已准备好流式传输视频!如果你想获得更多关于相机的信息,可点击 Getting started with picamera.。

安装FLASK

有好几种方法可以流式传输视频。我认为最好的(也是“更轻松”)方法是使用Miguel Grinberg开发的Flask。有关Flask如何执行此操作的详细说明,请参阅他的精彩教程:flask-video-streaming-revisited。

在我这个教程中:Python Web服务器将借助Flask和树莓派。我们要更详细地了解了Flask是如何工作、如何实现Web服务器以及从传感器上捕获数据并在网页上显示其状态。在本教程中的第一部分就是发送到我们前端的数据的视频流。

创建一个Web服务器环境:

首先要做的是在你的树莓派上安装Flask。 如果没有,去终端并输入:

sudo apt-get install python3-flask

当你开始一个新项目时,最好的办法就是创建一个文件夹来保存你的文件。 例如:

回到主页,到你的工作目录:

cd Documents

新建文件夹,例如:

mkdir camWebServer

按照上面的命令,创建一个名为“camWebServer”的文件夹,并在这里保存我们的python脚本:

/home/pi/Document/ camWebServer

现在,在这个文件夹上,我们将创建两个子文件夹:静态的CSS、最终的JavaScript文件以及HTML文件的模板。 转到你的新创建的文件夹:

cd camWebServer

并创建2个新的子文件夹:

mkdir static

mkdir templates

最终的目录“树”,如下所示:

├── Documents ├── camWebServer ├── templates └── static

完成!让我们在创建好的的环境下,用Python Web 服务器应用程序来流式传输视频。

创建视频流媒体服务器

首先,下载Miguel Grinberg的树莓派相机软件包:camera_pi.py并将其保存在创建的目录camWebServer上。 这是我们项目的核心,Miguel的安装包相当的不错。

现在,使用Flask,让我们调整原始的Miguel的web服务器应用程序(app.py),创建一个特定的python脚本来渲染我们的视频。 我们可以命名为appCam.py:

from flask import Flask, render_template, Response # Raspberry Pi camera module (requires picamera package, developed by Miguel Grinberg) from camera_pi import Camera app = Flask(__name__) @app.route(‘/’) def index(): “””Video streaming home page.””” return render_template(‘index.html’) def gen(camera): “””Video streaming generator function.””” while True: frame = camera.get_frame() yield (b’–frame\r

‘ b’Content-Type: image/jpeg\r

\r

‘ + frame + b’\r

‘) @app.route(‘/video_feed’) def video_feed(): “””Video streaming route. Put this in the src attribute of an img tag.””” return Response(gen(Camera()), mimetype=’multipart/x-mixed-replace; boundary=frame’) if __name__ == ‘__main__’: app.run(host=’0.0.0.0′, port =80, debug=True, threaded=True)

以上脚本将你的摄像机视频流式传输到index.html页面上,如下所示:

MJRoBot Lab Live Streaming

MJRoBot Lab Live Streaming


@2018 Developed by MJRoBot.org

index.html最重要的一行是:

视频将会在这里“反馈”到我们的网页上。

你还必须在静态目录中包含style.css文件,以便以这种形式获得上述结果。

所有文件都可以从我的GitHub仓库下载获得:camWebServer。

确保所有的文件都在正确的位置,所有数据更新后,检查一下我们的环境:

├── Documents ├── camWebServer ├── camera_pi.py ├── appCam.py ├── templates | ├── index.html └── static ├── style.css

现在,在终端上运行python脚本:

sudo python3 appCam.py

转到你的网络中的任何浏览器,并输入 http://树莓派的IP地址/

注意:如果你不能确定你的树莓派IP地址,请在你的终端上运行:

ifconfig

在wlan0:部分你会找到它。

就是这样了!从现在开始,唯一的问题是需要一个复杂的页面,将你的视频嵌入到另一个页面等。

安装温度和湿度传感器

让我们创建一个使用真实数据记录的页面,其中如包含空气温度和相对湿度数据。因此我们将使用旧的、功能完好的DHT22。

要点概述

低成本的DHT温度和湿度传感器具有一般的基础功能、速度不快,但对于进行基本数据记录的爱好者来说非常适合。DHT传感器由两部分组成,即电容式湿度传感器和热敏电阻。 内部还有一个非常基本的芯片,它可以进行一些模数转换,并能读取温度和湿度的数字信号。 数字信号很容易用任何微控制器读取。

DHT22主要特点:

低成本

3至5V电源和I/O

转换期间最大电流为2.5mA

适用于0-100%湿度读数,精度为2-5%

适用于-40至125°C温度读数,精度为±0.5°C

不超过0.5 Hz的采样率(每2秒一次)

尺寸15.1mm x 25mm x 7.7mm

0.1″间距带4个引脚

一般情况下,你会在距离小于20米的地方使用传感器,在数据引脚和VCC引脚之间连接一个4K7欧姆的电阻。DHT22输出数据引脚将连接到树莓派的GPIO16。检查传感器连接到树莓派引脚的电路表,如下:

1、引脚1 – Vcc ==> 3.3V

2、引脚2 – 数据 ==> GPIO 16

3、引脚3 – 未连接

4、引脚4 – Gnd ==> Gnd

一旦传感器连接好,我们必须在树莓派上安装它的库。

安装DHT库:

在你的树莓派上,从/home 到 /Documents

cd Documents

创建一个目录来安装库并移至此处:

mkdir DHT22_Sensor cd DHT22_Sensor

在你的浏览器上,转到Adafruit GitHub仓库:

https://github.com/adafruit/Adafruit_Python_DHT

通过下载zip link下载该库,并在你的树莓派最近创建的文件夹中解压缩文件。然后转到库的目录(当你解压缩文件时自动创建的子文件夹),然后执行以下命令:

sudo python3 setup.py install

从我的GitHub仓库中打开一个测试程序(DHT22_test.py)。

import Adafruit_DHT DHT22Sensor = Adafruit_DHT.DHT22 DHTpin = 16 humidity, temperature = Adafruit_DHT.read_retry(DHT22Sensor, DHTpin) if humidity is not None and temperature is not None: print(‘Temp={0:0.1f}*C Humidity={1:0.1f}%’.format(temperature, humidity)) else: print(‘Failed to get reading. Try again!’)

使用以下命令执行程序:

python3 DHT22_test.py

下面的终端打印屏幕显示的结果。

为数据和视频显示创建一个Web服务器应用程序

让我们用Flask创建另一个python 网络服务器,它将处理传感器和视频流捕获的数据。

一旦我们的代码变得越来越复杂,我建议用Geany作为集成开发环境,你可以同时处理不同类型的文件(.py,.html和.css)

下面的代码是在我们的Web服务器上使用的python脚本:

from flask import Flask, render_template, Response app = Flask(__name__) # Raspberry Pi camera module (requires picamera package) from camera_pi import Camera import Adafruit_DHT import time # get data from DHT sensor def getDHTdata(): DHT22Sensor = Adafruit_DHT.DHT22 DHTpin = 16 hum, temp = Adafruit_DHT.read_retry(DHT22Sensor, DHTpin) if hum is not None and temp is not None: hum = round(hum) temp = round(temp, 1) return temp, hum @app.route(“/”) def index(): timeNow = time.asctime( time.localtime(time.time()) ) temp, hum = getDHTdata() templateData = { ‘time’: timeNow, ‘temp’: temp, ‘hum’ : hum } return render_template(‘index.html’, **templateData) @app.route(‘/camera’) def cam(): “””Video streaming home page.””” timeNow = time.asctime( time.localtime(time.time()) ) templateData = { ‘time’: timeNow } return render_template(‘camera.html’, **templateData) def gen(camera): “””Video streaming generator function.””” while True: frame = camera.get_frame() yield (b’–frame\r

‘ b’Content-Type: image/jpeg\r

\r

‘ + frame + b’\r

‘) @app.route(‘/video_feed’) def video_feed(): “””Video streaming route. Put this in the src attribute of an img tag.””” return Response(gen(Camera()), mimetype=’multipart/x-mixed-replace; boundary=frame’) if __name__ == ‘__main__’: app.run(host=’0.0.0.0′, port =80, debug=True, threaded=True)

你可以从我的GitHub仓库获得python脚本appCam2.py。

以上代码主要内容:

每当有人点击 “clicks””on “”/”,即我们网页的主页面(index.html),就会生成请求;

通过此请求,代码中的第一件事是使用函数从DHT读取传感器数据。

接下来,从系统中检索用的实际时间。

通过手头的数据,我们的脚本返回到网页(index.html):时间,温度和湿度对之前的请求的反馈。

另外,当用户想要看到视频流时,可以调用页面“/相机”。在这种情况下,3个路径都会在最后一步中显示。并渲染camera.html。

因此,我们来看看将用于构建前端的index.html,camera.html和style.css文件:

index.html

MJRoBot Lab Sensor Data

MJRoBot Lab Sensor Data

TEMPERATURE ==> {{ temp }} oC

HUMIDITY (Rel.) ==> {{ hum }} %


Last Sensors Reading: {{ time }} ==> REFRESH


MJRoBot Lab Live Streaming ==> LIVE


@2018 Developed by MJRoBot.org

你可以在我的GitHub仓库中获得 index. html。

camera.html

基本上,这个页面与我们之前创建的页面相同,只是我们添加了一个按钮来返回到主页面。

MJRoBot Lab Live Streaming

MJRoBot Lab Live Streaming

{{ time }}


Return to main page ==> RETURN


@2018 Developed by MJRoBot.org

You can get the file camera.html from my GitHub style.css body{ background: blue; color: yellow; padding:1% } .button { font: bold 15px Arial; text-decoration: none; background-color: #EEEEEE; color: #333333; padding: 2px 6px 2px 6px; border-top: 1px solid #CCCCCC; border-right: 1px solid #333333; border-bottom: 1px solid #333333; border-left: 1px solid #CCCCCC; }

你可以从我的GitHub仓库中获取camera.html。

style.css

body{ background: blue; color: yellow; padding:1% } .button { font: bold 15px Arial; text-decoration: none; background-color: #EEEEEE; color: #333333; padding: 2px 6px 2px 6px; border-top: 1px solid #CCCCCC; border-right: 1px solid #333333; border-bottom: 1px solid #333333; border-left: 1px solid #CCCCCC; }

你可以从我的GitHub仓库中获取style.cs。

创建网络服务器环境

这些文件必须以这样方式放在你的目录中:

├── camWebServer2 ├── camera_pi.py └─── appCam2.py ├── templates │ ├── index.html │ ├── camera.html └── static └──── style.css

现在,在终端上运行python脚本:

sudo python3 appCam2.py

可在以前的项目中添加视频流 (可选)

让我们在以前开发的项目中添加视频流**

让我们使用我们以前的教程开发的内容:FROM DATA TO GRAPH. A WEB JOURNEY WITH FLASK AND SQLITE.

记住,在该项目中,我们在数据库中记录了数据(温度和湿度),在网页上显示实际和历史数据:

我们这样做了,使用2个python脚本,一个用于在数据库上记录数据(logDHT.py),另一个用于通过Flask网络服务器(appDhtWebServer.py)在网页上显示数据:

创建网络服务器环境:

下面是我的目录图。 Sensor_Database在我的树莓派中的/ Documents下:

├── Sensors_Database ├── sensorsData.db ├── logDHT.py └── dhtWebHistCam ├── appDhtWebHistCam.py ├── camera_pi.py └─── appCam2.py ├── templates │ ├── index.html │ ├── camera.html └── static ├── justgage.js ├── raphael-2.1.4.min.js └──── style.css

这些文件可以在我的GitHub仓库上找到:dhtWebHistCam

结果如下:

结语

一如既往,我希望这个项目能够帮助他人进入激动人心的电子世界!

有关详细信息和最终代码,请访问我的GitHub仓库,Video-Streaming-with-Flask。

树莓派使用 Nokia 5110 屏幕显示网速温度

Nokia 5110

长上图这样。

驱动

PCD8544

资料

Google 一搜各种博客都有介绍,毕竟我不是学硬件的,底层什么的就不说了。好玩就行。

引脚

rst:外部复位引脚

ce:显示屏使能引脚

dc:数据/命令引脚

din:串行数据输入端

clk:串行时钟输入端

vcc:电源引脚

bl: 亮度调节

gnd:接地

先看看驱动代码

修改自(Adafruit),这里用的是 BCM 编码。

# coding:utf-8 import time import Adafruit_GPIO as GPIO import Adafruit_GPIO.SPI as SPI LCDWIDTH = 84 LCDHEIGHT = 48 ROWPIXELS = LCDHEIGHT//6 PCD8544_POWERDOWN = 0x04 PCD8544_ENTRYMODE = 0x02 PCD8544_EXTENDEDINSTRUCTION = 0x01 PCD8544_DISPLAYBLANK = 0x0 PCD8544_DISPLAYNORMAL = 0x4 PCD8544_DISPLAYALLON = 0x1 PCD8544_DISPLAYINVERTED = 0x5 PCD8544_FUNCTIONSET = 0x20 PCD8544_DISPLAYCONTROL = 0x08 PCD8544_SETYADDR = 0x40 PCD8544_SETXADDR = 0x80 PCD8544_SETTEMP = 0x04 PCD8544_SETBIAS = 0x10 PCD8544_SETVOP = 0x80 FONT = { ‘ ‘: [0x00, 0x00, 0x00, 0x00, 0x00], ‘!’: [0x00, 0x00, 0x5f, 0x00, 0x00], ‘”‘: [0x00, 0x07, 0x00, 0x07, 0x00], ‘#’: [0x14, 0x7f, 0x14, 0x7f, 0x14], ‘$’: [0x24, 0x2a, 0x7f, 0x2a, 0x12], ‘%’: [0x23, 0x13, 0x08, 0x64, 0x62], ‘&’: [0x36, 0x49, 0x55, 0x22, 0x50], “‘”: [0x00, 0x05, 0x03, 0x00, 0x00], ‘(‘: [0x00, 0x1c, 0x22, 0x41, 0x00], ‘)’: [0x00, 0x41, 0x22, 0x1c, 0x00], ‘*’: [0x14, 0x08, 0x3e, 0x08, 0x14], ‘+’: [0x08, 0x08, 0x3e, 0x08, 0x08], ‘,’: [0x00, 0x50, 0x30, 0x00, 0x00], ‘-‘: [0x08, 0x08, 0x08, 0x08, 0x08], ‘.’: [0x00, 0x60, 0x60, 0x00, 0x00], ‘/’: [0x20, 0x10, 0x08, 0x04, 0x02], ‘0’: [0x3e, 0x51, 0x49, 0x45, 0x3e], ‘1’: [0x00, 0x42, 0x7f, 0x40, 0x00], ‘2’: [0x42, 0x61, 0x51, 0x49, 0x46], ‘3’: [0x21, 0x41, 0x45, 0x4b, 0x31], ‘4’: [0x18, 0x14, 0x12, 0x7f, 0x10], ‘5’: [0x27, 0x45, 0x45, 0x45, 0x39], ‘6’: [0x3c, 0x4a, 0x49, 0x49, 0x30], ‘7’: [0x01, 0x71, 0x09, 0x05, 0x03], ‘8’: [0x36, 0x49, 0x49, 0x49, 0x36], ‘9’: [0x06, 0x49, 0x49, 0x29, 0x1e], ‘:’: [0x00, 0x36, 0x36, 0x00, 0x00], ‘;’: [0x00, 0x56, 0x36, 0x00, 0x00], ‘<': [0x08, 0x14, 0x22, 0x41, 0x00], '=': [0x14, 0x14, 0x14, 0x14, 0x14], '>‘: [0x00, 0x41, 0x22, 0x14, 0x08], ‘?’: [0x02, 0x01, 0x51, 0x09, 0x06], ‘@’: [0x32, 0x49, 0x79, 0x41, 0x3e], ‘A’: [0x7e, 0x11, 0x11, 0x11, 0x7e], ‘B’: [0x7f, 0x49, 0x49, 0x49, 0x36], ‘C’: [0x3e, 0x41, 0x41, 0x41, 0x22], ‘D’: [0x7f, 0x41, 0x41, 0x22, 0x1c], ‘E’: [0x7f, 0x49, 0x49, 0x49, 0x41], ‘F’: [0x7f, 0x09, 0x09, 0x09, 0x01], ‘G’: [0x3e, 0x41, 0x49, 0x49, 0x7a], ‘H’: [0x7f, 0x08, 0x08, 0x08, 0x7f], ‘I’: [0x00, 0x41, 0x7f, 0x41, 0x00], ‘J’: [0x20, 0x40, 0x41, 0x3f, 0x01], ‘K’: [0x7f, 0x08, 0x14, 0x22, 0x41], ‘L’: [0x7f, 0x40, 0x40, 0x40, 0x40], ‘M’: [0x7f, 0x02, 0x0c, 0x02, 0x7f], ‘N’: [0x7f, 0x04, 0x08, 0x10, 0x7f], ‘O’: [0x3e, 0x41, 0x41, 0x41, 0x3e], ‘P’: [0x7f, 0x09, 0x09, 0x09, 0x06], ‘Q’: [0x3e, 0x41, 0x51, 0x21, 0x5e], ‘R’: [0x7f, 0x09, 0x19, 0x29, 0x46], ‘S’: [0x46, 0x49, 0x49, 0x49, 0x31], ‘T’: [0x01, 0x01, 0x7f, 0x01, 0x01], ‘U’: [0x3f, 0x40, 0x40, 0x40, 0x3f], ‘V’: [0x1f, 0x20, 0x40, 0x20, 0x1f], ‘W’: [0x3f, 0x40, 0x38, 0x40, 0x3f], ‘X’: [0x63, 0x14, 0x08, 0x14, 0x63], ‘Y’: [0x07, 0x08, 0x70, 0x08, 0x07], ‘Z’: [0x61, 0x51, 0x49, 0x45, 0x43], ‘[‘: [0x00, 0x7f, 0x41, 0x41, 0x00], ‘\\’: [0x02, 0x04, 0x08, 0x10, 0x20], ‘]’: [0x00, 0x41, 0x41, 0x7f, 0x00], ‘^’: [0x04, 0x02, 0x01, 0x02, 0x04], ‘_’: [0x40, 0x40, 0x40, 0x40, 0x40], ‘`’: [0x00, 0x01, 0x02, 0x04, 0x00], ‘a’: [0x20, 0x54, 0x54, 0x54, 0x78], ‘b’: [0x7f, 0x48, 0x44, 0x44, 0x38], ‘c’: [0x38, 0x44, 0x44, 0x44, 0x20], ‘d’: [0x38, 0x44, 0x44, 0x48, 0x7f], ‘e’: [0x38, 0x54, 0x54, 0x54, 0x18], ‘f’: [0x08, 0x7e, 0x09, 0x01, 0x02], ‘g’: [0x0c, 0x52, 0x52, 0x52, 0x3e], ‘h’: [0x7f, 0x08, 0x04, 0x04, 0x78], ‘i’: [0x00, 0x44, 0x7d, 0x40, 0x00], ‘j’: [0x20, 0x40, 0x44, 0x3d, 0x00], ‘k’: [0x7f, 0x10, 0x28, 0x44, 0x00], ‘l’: [0x00, 0x41, 0x7f, 0x40, 0x00], ‘m’: [0x7c, 0x04, 0x18, 0x04, 0x78], ‘n’: [0x7c, 0x08, 0x04, 0x04, 0x78], ‘o’: [0x38, 0x44, 0x44, 0x44, 0x38], ‘p’: [0x7c, 0x14, 0x14, 0x14, 0x08], ‘q’: [0x08, 0x14, 0x14, 0x18, 0x7c], ‘r’: [0x7c, 0x08, 0x04, 0x04, 0x08], ‘s’: [0x48, 0x54, 0x54, 0x54, 0x20], ‘t’: [0x04, 0x3f, 0x44, 0x40, 0x20], ‘u’: [0x3c, 0x40, 0x40, 0x20, 0x7c], ‘v’: [0x1c, 0x20, 0x40, 0x20, 0x1c], ‘w’: [0x3c, 0x40, 0x30, 0x40, 0x3c], ‘x’: [0x44, 0x28, 0x10, 0x28, 0x44], ‘y’: [0x0c, 0x50, 0x50, 0x50, 0x3c], ‘z’: [0x44, 0x64, 0x54, 0x4c, 0x44], ‘{‘: [0x00, 0x08, 0x36, 0x41, 0x00], ‘|’: [0x00, 0x00, 0x7f, 0x00, 0x00], ‘}’: [0x00, 0x41, 0x36, 0x08, 0x00], ‘~’: [0x10, 0x08, 0x08, 0x10, 0x08], ‘\x7f’: [0x00, 0x7e, 0x42, 0x42, 0x7e], } X = 13 Y = 5 class PCD8544(object): “””Nokia 5110/3310 PCD8544-based LCD display.””” def __init__(self, dc, rst, sclk=None, din=None, cs=None, gpio=None, spi=None, vcc=None, bl=None): self._sclk = sclk self._din = din self._dc = dc self._cs = cs self._rst = rst self._gpio = gpio self._spi = spi self._buffer = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFF, 0xFC, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0xC0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xC7, 0xC7, 0x87, 0x8F, 0x9F, 0x9F, 0xFF, 0xFF, 0xFF, 0xC1, 0xC0, 0xE0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xE0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF1, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x0F, 0x0F, 0x87, 0xE7, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0x3F, 0xF9, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x0F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7E, 0x3F, 0x3F, 0x0F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0xE0, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x1F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x1F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ] if self._gpio is None: self._gpio = GPIO.get_platform_gpio() self._gpio.setup(vcc, GPIO.OUT) self._gpio.setup(bl, GPIO.OUT) self._gpio.output(vcc, 1) self._gpio.output(bl, 1) if self._rst is not None: self._gpio.setup(self._rst, GPIO.OUT) # Default to bit bang SPI. if self._spi is None: self._spi = SPI.BitBang(self._gpio, self._sclk, self._din, None, self._cs) # Set pin outputs. self._gpio.setup(self._dc, GPIO.OUT) # Initialize buffer to Adafruit logo. def command(self, c): “””Send command byte to display.””” # DC pin low signals command byte. self._gpio.set_low(self._dc) self._spi.write() def extended_command(self, c): “””Send a command in extended mode””” # Set extended command mode self.command(PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION) self.command(c) # Set normal display mode. self.command(PCD8544_FUNCTIONSET) self.command(PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL) def begin(self, contrast=40, bias=4): “””Initialize display.””” self.reset() # Set LCD bias. self.set_bias(bias) self.set_contrast(contrast) def reset(self): “””Reset the display””” if self._rst is not None: # Toggle RST low to reset. self._gpio.set_low(self._rst) time.sleep(0.1) self._gpio.set_high(self._rst) def display(self): “””Write display buffer to physical display.””” # TODO: Consider support for partial updates like Arduino library. # Reset to position zero. self.command(PCD8544_SETYADDR) self.command(PCD8544_SETXADDR) # Write the buffer. self._gpio.set_high(self._dc) self._spi.write(self._buffer) def clear(self): “””Clear contents of image buffer.””” self._buffer = [0] * (LCDWIDTH * LCDHEIGHT // 8) def set_contrast(self, contrast): “””Set contrast to specified value (should be 0-127).””” contrast = max(0, min(contrast, 0x7f)) # Clamp to values 0-0x7f self.extended_command(PCD8544_SETVOP | contrast) def set_bias(self, bias): “””Set bias””” self.extended_command(PCD8544_SETBIAS | bias) def draw_str(self, y, s): “””修改显示数据,y 为第几行,s 为要显示的数据””” if (y >= Y ) or (y < 0): return False x = 0 for c in s[0:14]: try: self._buffer[y*84+x*6: y*84+x*6 + 6] = FONT + [0] except KeyError: pass x += 1 def draw_char(self, x, y): pass def quit(self): self._gpio.cleanup() 接线(BCM) dc 13 rst 5 sclk 26 din 19 cs 6 vcc 20 bl 21 gnd 0v 显示信息 网速 显示路由器的网速,电脑网速就没必要了。 我用的是老毛子固件,所以用这个固件的可以参考我的代码。 代码量不大,我就没写注释了。 # coding:utf-8 import requests import time from math import fabs from base64 import b64encode # from demjson import decode class RaspberryMonitorNetSpeed: url = 'http://192.168.123.1/update.cgi?output=netdev' headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8', 'Cache-Control': 'max-age=0', # 'Connection':'keep-alive', 'Connection': 'close', 'Cookie': 'n56u_cookie_bw_rt_tab=WAN', 'Host': '192.168.123.1', 'Upgrade-Insecure-Requests': '1', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36', } # 最近一次请求时间 last_time = 0 # 最近一次请求的下行数据总量 last_rbytes = 0 # 最近一次请求的上行数据总量 last_tbytes = 0 def __init__(self, username, passwd): self.headers['Authorization'] = 'Basic '+b64encode((username+':'+passwd).encode()).decode() data = self.__get_wan_rx_and_tx() self.last_rbytes = data[0] self.last_tbytes = data[1] self.last_time = data[2] def set_auth(self, username, passwd): self.headers['Authorization'] = 'Basic '+b64encode((username+':'+passwd).encode()).decode() def __get_wan_rx_and_tx(self): text = requests.get(self.url, headers=self.headers).text try: rx = int(text.split(',')[25].lstrip('rx:').strip(), 16) tx = int(text.split(',')[26].lstrip('tx:').rstrip('} ').strip(), 16) new_time = time.time() except (IndexError, ValueError, TypeError): return False return [rx, tx, new_time] def get_human_speed(self): """这里返回的是 M/s 这种网速,[下载,上传]""" data = self.__get_wan_rx_and_tx() if data: down_speed = 0 up_speed = 0 try: down_speed = self.__bytes_to_humanspeed((data[0] - self.last_rbytes) / (data[2] - self.last_time)) up_speed = self.__bytes_to_humanspeed((data[1] - self.last_tbytes) / (data[2] - self.last_time)) except ZeroDivisionError: pass self.last_rbytes = data[0] self.last_tbytes = data[1] self.last_time = data[2] return down_speed, up_speed def __bytes_to_humanspeed(self, B): absval = fabs(B) / 1024 megabyte = 1024 gigabyte = megabyte * 1024 terabyte = gigabyte * 1024 # petabyte = terabyte * 1024 if absval < megabyte: return str(round(absval, 2)) + ' KB/s' elif absval < gigabyte: return str(round(absval / megabyte, 2)) + ' M/s' else: return str(round(absval / gigabyte, 2)) + ' G/s' def get_bits_speed(self): """这里返回的是 Mbps 这种网速,[下载,上传]""" data = self.__get_wan_rx_and_tx() if data: down_speed = self.__bytes_to_bitrate((data[0] - self.last_rbytes) / (data[2] - self.last_time)) up_speed = self.__bytes_to_bitrate((data[1] - self.last_tbytes) / (data[2] - self.last_time)) self.last_rbytes = data[0] self.last_tbytes = data[1] self.last_time = data[2] return down_speed, up_speed def __bytes_to_bitrate(self, B): bits = B * 8 absval = fabs(bits) kilobit = 1000 megabit = kilobit * 1000 gigabit = megabit * 1000 if absval < megabit: return str(round(bits / kilobit, 2)) + ' Kbps' elif absval < gigabit: return str(round(bits / megabit, 2)) + ' Mbps' else: return str(round(bits / gigabit, 2)) + ' Gbps' if __name__ == '__main__': from lcd1602 import LCD1602 a = RaspberryMonitorNetSpeed('username', 'password') lcd = LCD1602() while True: tmp = a.get_human_speed() lcd.lcd_string('u:' + tmp[1], lcd.LCD_LINE_1) lcd.lcd_string('d:' + tmp[0], lcd.LCD_LINE_2) time.sleep(2) 温度 这里用的是 DTH11,驱动同样参考这个(Adafruit)。 开始显示 代码量同样不大,没写注释。 import time import datetime from PCD8544 import PCD8544 as lcd import threading import Adafruit_DHT from speed import RaspberryMonitorNetSpeed as rmn ns = [-1, -1] th = [-2, -2] def main(): a = lcd(dc=13, rst=5, sclk=26, din=19, cs=6, vcc=20, bl=21) a.begin(contrast=60) tmp = threading.Thread(target=network_speed) tmp.setDaemon(True) tmp.start() tmp = threading.Thread(target=temperature_humidity) tmp.setDaemon(True) tmp.start() while True: try: a.clear() # 上传速度 a.draw_str(0, 'U: ' + str(ns[1])) # 下载速度 a.draw_str(1, 'D: ' + str(ns[0])) # 温度 a.draw_str(2, 'T: ' + str(th[1]) + ' C') # 湿度 a.draw_str(3, 'H: ' + str(th[0]) + '%') # 时间 a.draw_str(4, datetime.datetime.now().__str__()[5:].lstrip('0').split('.')[0]) a.display() time.sleep(1) except KeyboardInterrupt: a.quit() exit(0) def network_speed(): global ns b = rmn('bankroft', '123456') while True: time.sleep(1) ns = b.get_human_speed() def temperature_humidity(): global th pin = 25 while True: time.sleep(10) th = Adafruit_DHT.read_retry(11, 25) if __name__ == '__main__': main() 运行 依赖 python3 安装 Python 库 Adafruit_GPIO Adafruit_DHT requests 运行 python main.py 成果 作者:简书 Bankroft

树莓派官方系统新特性以及启动配置

树莓派官方系统 Raspbian 2018-06-17 新版本更新已经有数周了,新版本主要加入了全新的启动配置向导,自动引导用户设置开机密码、WiFi、本地化等设置。同时加入了更成熟等应用安装管理工具。下面我们具体来看看。(下文摘自这里)

1. 添加了新的启动配置向导,真正实现了傻瓜化的配置道路。

设置国家

设置用户的密码

选择 wifi 网络

检查更新

配置完成后重启。

2. 添加了推荐软件安装器

3. Bluej,Greenfoot,NodeRED,Claws Mail,VNC Viewer 已经被从镜像移除,可以通过推荐应用进行安装。

4. Qpdfview PDF viewer 集成在系统中用来取代Xpdf,看 PDF 更加给力了!

5. 系统原生包含Version 65.0 的Chromium浏览器,并支持最新的 Flash 播放器,意味着如果看优酷视频也不会因为播放器不兼容而不好用了,系统烧录完直接打开浏览器就看世界杯了。

6. 音量的调节可以以5%的幅度进行增减了,并且可以选择输出设备了。

7. 网络的插件可以对以前输入过的网络密码进行记忆了,当重连的时候会提示密码信息.方便了不少。

8. 串口和串口控制台能够在树莓派配置中进行切换。

9. Lxkeymap 键盘语言设置移除 – 替换为在 Raspberry Pi Configuration的对话设置中了。

10. Wifi 国家及键盘语言设置对话框可以被其他应用调用了,就意味着如果其他的应用程序需要修改语言或者键盘映射类型就可以直接调用管理控制台完成设置了。

11. 新版本的PiBOTO字体包括在某些恶意应用程序中以正确的权重渲染。

12. 在重新启动时,自动重新连接到蓝牙音频设备. 你如果有蓝牙音箱的应用就非常舒服了。

13. 如果选择了”单击启用” ,请在文件管理器中”禁用单击以重命名文件”

14. “外观设置对话框”对某些QT文件进行配置更改,以匹配选定主题。

15. 改进的MIME文件类型关联

16. 多个桌面管理选项取消了鼠标中键作用。

17. 修改了树莓派Pi网站的菜单快捷方式,使得访问更加清晰,帮助就是帮助,项目就是项目.一目了然。

18. 删除了Python 2 idle 的菜单链接,看来要全面支持 python3了。

19. MAGPI PDF安装在/home/pi/MagPi 中,更加方便查看 magpi 杂志。

20. 应用各种小调整、错误修复和外观更改

21. 蓝牙更新,连接速度更快更有效.并且具有蓝牙4.2特性的固件,虽然我的蓝牙无法支持4.2,但是固件升级了肯定增加很多新特性。

22.通过bthelper.serivce添加了对 SCO 配置的支持。

23. 内核方面的升级: Linux内核4.1450+

完。

MAKER的衣柜:树莓派+RFID实现智能衣柜

MAKER:dar_sissau/译:趣无尽 Cherry(转载请注明出处)

懒是人类文明进步的驱动力,本期的 MAKER 正因为懒于每次一件件翻遍衣柜,才有动手制作这个项目的动力。

这是一个基于RFID的存储系统的衣柜,可以方便地记录衣物的使用情况,方便地通过终端查看柜子里面的衣物列表!请看下面的短片。

该项目的制作者 dar_sissau 表示:一切源于我在打包行李箱时的手足无措。我不得不回宿舍整理,但我根本不记得还有多少件T恤或袜子。所以我决定通过制作一个基于RFID的存储系统让我的生活变得更轻松,该系统可以追踪衣柜里所有衣服的位置。

我们的项目是基于树莓派或Arduino的,通过传感器收集数据并将其存储在MySQL数据库中。 在这个教程中,我将指导你完成每个步骤,你完全可以按照教程自己制作一个一摸一样甚至更完美的衣柜!

材料清单

树莓派3B × 1

电源5V/2.5A × 1

16 GB microSD卡 × 1

排针电源转接口2×20 公 × 1

RC522 rfid读写器 × 1

RFID 电子标签 频率125 Khz × 若干

LCD液晶屏 1602A-5V × 1

T型GPIO扩展板 × 1

电缆连接器 × 1

洞洞板 × 1

无源蜂鸣器 × 1

十字螺丝 × 若干

魔术贴条(可选) × 若干

烙铁 × 1

十字螺丝刀 × 1

剪刀 × 1

3D打印机 × 1

该项目的操作步骤简单但琐碎,请各位 MAKERS 多一些的耐心。看看究竟如何改变这个世界多一点。干货来啦!

准备工作

下载并安装 Raspbian 系统。

将安装好系统的SD卡放入电脑,进入下一个步骤。

启用SSH

要远程访问你的树莓派,我们必须启用SSH然后用PUTTY连接到树莓派。下面到方法是众多方法中的一种,当然你可以访问树莓派实验室的新手开箱教程了解其他类似的方法,总之能通过SSH登录到树莓派就行。

在计算机上打开文件资源管理器,查找名为“boot(E:)”或其他字母命名(如上图所示)的microSD卡。

使用记事本打开文件“cmdline.txt”。将“ip = 169.254.10.1”添加到当前内容。注意一切都必须码在一条线上!保存文件,如上图所示。

在你的树莓派上启动ssh,只需在“boot(E:)”中添加一个空文件,命名为“ssh”,不带扩展名。然后安全地移除microSD并将其放回树莓派中。

使用网线连接计算机和树莓派。现在为你的树莓派供电并等待几分钟确保它通电。

安装Putty

现在可以通过ssh访问你的树莓派了。

在你的计算机上安装putty。打开putty并与树莓派建立ssh连接。用于连接树莓派的ip与我们填写cmdline.txt(169.254.10.1)的IP相同。端口是22(如图所示)。

一旦你点击打开,在第一次连接时会收到警告。你可以忽略它,只需单击是。

使用以下凭证立即登录:

用户名:pi

密码:raspberry

如果一切正确,你应该看到终端(如图所示)。

注意:如果你想在终端中使用数字键盘,请在putty配置类别终端中选择“特性”并选中“Disable application keypad mode”禁用应用键盘模式,然后在单选按钮上选择“Empty string”(如图所示)。

更改你的密码和主机名

在终端中执行以下步骤:

在终端输入 sudo raspi-config。

转到选项1(更改用户密码)并输入新密码。最好记在你的小本本上。

转到选项3(Boot选项)并设置:

在Desktop / CLI,选择第一个选项“Console”。

禁用“开机时等待网络”。

选择“启动界面”并禁用此选项。

转到选项4(本地化选项)和:

设置正确的时区。

选择你所在国家/地区的WiFi。

关闭raspi-config。在终端中使用此命令更改主机名 sudo nano /etc/hostname。在文件中将名称更改为唯一的名称。写在小本本上哦!

用ctrl-x保存文件,并按y键确认。最后,使用 sudo reboot 命令重新启动树莓派。

网络配置

我们在“cmdline.txt”中添加的IP地址,现在将其设置为静态IP。但是,我们喜欢模仿Windows的操作。我更喜欢DHCP,只有在DHCP不可用时才配置APIPA地址。

终端输入 sudo nano /etc/dhcpcd.conf。

添加以下内容(其中大部分应该已经位于最底层,您只需将其从注释中删除并更改IP地址。):

# define static profile profile static_eth0 static ip_address=169.254.10.1/16 # fallback to static profile on eth0 interface eth0 fallback static_eth0

用ctrl-x保存文件,并按y键确认。

使用命令 sudo nano /boot/cmdline.txt 现在删除 /boot/cmdline.txt 中的静态IP并保存文件。

现在重启网络服务。

将树莓派连接到Wifi

通过以太网端口,我们现在可以连接到树莓派,但我们还没有上网。为此,我们现在将树莓派连接到WiFi网络。 Raspbian使用wpa_supplicant来管理WiFi连接。

命令 sudo -i 暂时变为root,将prompt更改为root @ host#。

现在我们可以使用以下命令添加网络(填写密码和wifi的SSID)

echo “password” | wpa_passphrase “SSID” >> /etc/wpa_supplicant/wpa_supplicant.conf

并验证网络是否已添加成功。仔细检查并确保设置了正确的国家/地区(COUNTRY=你的国家/地区的初始状态),并可选择删除带有密码的注释行并保存文件。

输入以下指令:

sudo wpa_cli scan scan_results list_networks reconfigure status quit

检查 ip addr show dev wlan0,是否是可用的IP地址,并最终使用 wget google.com 测试网络连接。

Bonjour

现在我们已连接到无线网络,如果我们可以通过它建立SSH连接,而不常常使用UTP电缆连接树莓派,那将非常有用。但是,有时候会遇到了问题,我们不知道通过DHCP分配树莓派的IP地址。幸运的是我们有 Bonjour。

Bonjour过去可以单独从Apple下载,但最新版本仅作为iTunes的一部分提供。但是,我们可以通过一个技巧来实现:如果你没有启动iTunes安装文件,而是将其作为ZIP存档打开(例如使用7-zip),你会发现Bonjour有一个单独的文件。解压缩此文件并通过双击安装它。

然后,您应该能够通过在后面添加.local来连接到树莓派的主机名。这就是为什么在raspi-config中设置一个唯一的主机名的重要性。

注意:你必须与APIPA一样在同一个网络上才能开始使用Bonjour!

建立自己的用户

创建一个你所需的用户名的变量:

user=me

将用户添加到特定组:

groups=$(id pi -Gn | sed ‘s/^pi //g’ | sed ‘s/ /,/g’) sudo useradd ${user} -s /bin/bash -m -G ${groups} sudo sed “s/^pi/${user}/” /etc/sudoers.d/010_pi-nopasswd | sudo tee “/etc/sudoers.d/011_${user}-nopasswd” sudo passwd ${user}

现在登录:

su – me

安装Pycharm

现在,在您的计算机上下载并安装pycharm。

准备工作

安装包

sudo apt update sudo apt install -y python3-venv python3-pip python3-mysqldb mariadb-server uwsgi nginx uwsgi-plugin-python3

虚拟环境

python3 -m pip install –upgrade pip setuptools wheel virtualenv mkdir project1 && cd project1 python3 -m venv –system-site-packages env source env/bin/activate python -m pip install mysql-connector-python argon2-cffi Flask Flask-HTTPAuth Flask-MySQL mysql-connector-python passlib spidev RPi.GPIO

下载项目代码

打开pycharm

转到VCS>从版本控制导入> GitHub并克隆启动项目。或者在本项目的文件库下载部署。

为创建的目录设置目录,例如/home/me/project1。单击“应用”

转到解析器设置并配置/选择刚刚创建的虚拟环境,例如 /home/me/project1/env/bin/python。

检查解析器下是否填写了路径映射字段,并引用了正确的目录。

现在将整个内容从PyCharm上传到树莓派并验证。如上图所示。

创建用户+数据库和分配权限

因为当前没有SQL用户,所以必须以sudo mariadb为用户启动客户端一次。

sudo mariadb sudo mariadb < sql/wardrobe.sql 注意:如果您想要标准化数据库的模型,你可以看上图中我包含的文件。 通过Pycharm连接 单击右侧的“数据库”选项卡(no tab? Menu View > Tool Windows > Database),然后单击绿色+添加连接。

选择数据源> MySQL,然后单击下面的下载驱动程序链接(如果可用)。

首先转到SSH / SSL选项卡并检查SSH。完成你日常使用的PuTTY的数据(主机/用户/密码)。如果尚未输入端口,则必须输入22.检查记住密码。

返回“常规”选项卡并完成数据库的数据:

主机仍为localhost(因为通过SSH连接)。

此示例中的数据库是衣柜。使用project1-admin凭证并单击“测试连接”。

如果连接正常,请转到Schemas选项并确保正确,检查一下衣柜。你可能需要先刷新。

最后,将名称更改为更符合实际情况的内容,例如project1 @ rpi-ssh,然后单击OK。

配置文件

在目录conf中,你要首先找到需要调整的4个文件,然后放在正确的位置(通过pycharm执行此操作)。你必须将4个文件中任何位置出现的用户名和相应的主目录都进行更改。

uWSGI

参数模块引用Flask应用程序。之前:表述文件名,后面则是对象的名称。在示例中,你将在web.py行中找到 app = Flask(),因此 module = web:app。

Virtualenv能够对它进行说明。

剩下的如果正确的,文件可以保持原样。

Systemd

这两个.service文件是systemd的单元文件。除了描述之外,你还必须根据你的实际情况调整[Service]下的4个参数。请注意,使用正确的Python解析器(在virtualenv中)并始终使用绝对路径(starting from /)。

注意:在继续之前,请务必将这些更改上传到树莓派。

将所有内容复制到正确的位置

cd project1 sudo cp/conf/project1-flask.service /etc/systemd/system sudo cp/conf/project1-sensor.service /etc/systemd/system sudo systemctl daemon-reload sudo systemctl start project1-flask.service sudo systemctl start project1-sensor.service sudo systemctl status project1-flask.service sudo systemctl statusproject1-sensor.service

如图所示,输出的格式是这样的。

nginx

sudo cp conf/nginx /etc/nginx/sites-available/project1 sudo rm /etc/nginx/sites-enabled/default sudo ln -s /etc/nginx/sites-available/project1 /etc/nginx/sites-enabled/project1 sudo systemctl restart nginx.service sudo systemctl status nginx.service wget -qO – localhost

如果一切正常,你应该回到html。

自动启动

MariaDB和nginx自动启动,你自己的服务尚未启动。

sudo systemctl enable project1-flask.service sudo systemctl enable project1-sensor.service

电路图

如图所示连接电线。或者将元件焊接到PCB上。

液晶屏:

2 * 16 LCD可以显示Web服务器的IP地址。或者它显示进入或退出系统的rfid标签。

VSS – > GND

VDD – > 5V

V0 – >电位计

RS – > GPIO 22

RW – > GND

E – > GPIO 27

D4 – > GPIO 5

D5 – > GPIO 6

D6 – > GPIO 13

D7 – > GPIO 19

A – > 5V

K – > GND

RFID-RC522:

用于标注服装进出的RFID阅读器。

SDA – > GPIO 8

SCK – > GPIO 11

MOSI – > GPIO 10

MISO – > GPIO 9

IRQ – > GPIO 24

GND – > GND

RST – > GPIO 25

3.3V – > 3V3

无源蜂鸣器:

检测到RFID标签时发出声音。

正极 – > GPIO 21

负极 – > GND

3D打印盒子

打印我们项目所需的盒子。文件中包含了我所使用的3D模型。盒子上的字母N,我用一张纸和一些胶水。

将所有东西安装在一起

拿起螺丝刀,用螺钉和螺栓将这些零件安装在一起。按照下面的说明进行操作。

1、屏幕正面。

2、盒子前面的Rfid阅读器。

3、带屏幕的树莓派(不要忘记在电源关闭的情况下将电源线放入树莓派中)。

4、盖上前面的壳子。

现在将它安装到您的衣柜,你可以选择使用螺丝还是魔术贴。我在这里选择用魔术贴。

现在你已经完成了所有的步骤,你的原型应该也能正常运行。只需打开电源,等到ip地址在液晶屏上显示并上网。

MAKER 趣无尽页面:http://make.quwj.com/project/62

via

在未经修改的NES主机上玩SNES游戏

模拟器一般是运行在较新的设备上的,用来模拟较旧的设备上的软件。但来自宾夕法尼亚州匹兹堡的计算机科学家Tom Murphy VII通过“逆向模拟”SNES来改变这一过程。他在一个NES设备上成功模拟SNES游戏的运行,其中的关键是通过将树莓派嵌入到NES游戏卡带中来,树莓派模仿SNES游戏,并将图形转换为NES硬件可以显示的形式。至于这么做有什么实际意义?可能并不大,研究纯属好奇和好玩,这就足够了!

汤姆在这个引人入胜的视频中解释了他必须解决的许多技术问题:

该项目需要一个定制的电路板,包括一块树莓派、一个重新编程的NES PPU芯片和一个Nintendo CIC内容保护芯片。

汤姆逆向模拟的关键在于以某种方式欺骗未经修改的NES运行SNES发布冠军超级马里奥世界,他通过将树莓派嵌入到NES游戏卡带中来实现。树莓派模仿SNES游戏,并将图形转换为NES硬件可以显示的形式。

下面的视频制作,更详细地解释了该项目:

via

用本地网络控制的树莓派摄影云台

MAKER:Mjrovai/译:趣无尽 Cherry(转载请注明出处)

在前两期的教程中,我们一起学习由多个舵机控制的云台和视频流媒体网站服务器这两个项目。我们学习到如何使用相机(或其他设备)捕捉画面和如何在互联网上流式传输视频。在本教程中,我们将结合之前所学,通过互联网来控制摄像头位置。

如图所示:

画面显示相机由按钮控制,预编程中固定了云台倾斜角度。 在本教程中,我们还将探索通过互联网控制带摄像头云台的其他替代方案。

项目框架图:

材料清单

1、树莓派3 X1

2、摄像头模块 X1

3、9G 180°微型舵机X2

4、迷你平移/倾斜摄像机平台防振照相机支架(2个舵机)

5、电阻1K欧姆X2(可选)

6、金属部件

7、固定带等(用于构建云台平台)

你可以购买一个平台舵机或自己制作。

该项目中的前三个步骤(安装树莓派照相机、安装FLASK和创建视频流媒体服务器 )与视频流媒体网站服务器的教程如出一辙。具体细节大家可回顾前期内容,小编不在重复复述。请你点击树莓派+Flask实现视频流媒体WEB服务器。

请依次进行安装树莓派照相机、安装FLASK和创建视频流媒体服务器,我们接着下一步。

平台移动机制

我们的相机可以操作,我们的Flask互联网服务器可以播放视频流,现在让我们安装云台移动机制来远程定位相机。有关详细信息,请访问前期教程:基于树莓派的多舵机控制的定位拍照云台。

具体回顾其中安装部件和创建 Python 脚本这两个部分。

舵机将连接到外部5V电源,其数据引脚(我的项目中,黄色接线)连接到树莓派GPIO如下:

GPIO 17 ==>仰角舵机

GPIO 27 ==>平移舵机

不要忘记将GND连接在一起 ==> 树莓派 – 舵机 – 外部电源

你可以在树莓派的GPIO和服务器数据输入引脚之间串联一个1K欧姆的电阻。 如果发生舵机故障,这将保护你的树莓派。

我们也可以利用这个机会在虚拟Python环境中测试我们的舵机。

让我们使用Python脚本在驱动程序中进行测试:

from time import sleep import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) def setServoAngle(servo, angle): pwm = GPIO.PWM(servo, 50) pwm.start(8) dutyCycle = angle / 18. + 3. pwm.ChangeDutyCycle(dutyCycle) sleep(0.3) pwm.stop() if __name__ == ‘__main__’: import sys servo = int(sys.argv[1]) GPIO.setup(servo, GPIO.OUT) setServoAngle(servo, int(sys.argv[2])) GPIO.cleanup()

上述代码的核心是设置舵机和角度的函数。 该函数接收参数、舵机、 GPIO编号和舵机必须定位的角度值。 一旦这个函数的输入是“角度”,我们必须使用之前开发的公式将其转换为百分比的占空比。

脚本执行时,必须输入参数,舵机GPIO和角度。

例如:

sudo python angleServoCtrl.py 17 45

上述命令会将舵机连接到GPIO 17并且以“仰角”45度定位。 一个类似的命令可以用于平移伺服控制(在“方位角”中位置为45度):

sudo python angleServoCtrl.py 27 45

文件 angleServoCtrl.py可以在我的 GitHub 仓库下载。

通过网络使用按钮来控制摄像头位置

我们开始创建一个新目录:

mkdir PanTiltControl1

在这个目录树中,我们应该创建环境和文件:

├── Documents └── PanTiltControl1 ├── camera_pi.py ├── angleServoCtrl.py ├── appCamPanTilt1.py ├── templates | └── index.html └── static └── style.css

camera_pi.py文件是之前使用过的Miguel脚本和angleServoCtrl.py文件。你可以从我的GitHub仓库中下载。

现在我们需要appCamPanTilt1.py,index.html和style.css。你可以从我的GitHub仓库下载这些文件,请点击相关链接。注意它们在你的目录上的位置是否正确。

我们来看看index.html:

MJRoBot Lab Live Streaming

MJRoBot Lab Live Streaming


PAN: 30 45 60 75 90 105 120 135 150 ==> Angle: [ {{ panServoAngle }} ]

TILT: 30 45 60 75 90 105 120 135 150 ==> Angle: [ {{ tiltServoAngle }} ]


@2018 Developed by MJRoBot.org

index.html是从之前创建过的文件,在流式传输视频时使用过。在这个新建的文件中,每一行代码与页面上显示的按钮有关。

我们来分析其中之一:

30

这是一个简单的HTML超链接,我们将其设计为一个按钮链接。(作为按钮在style.css中描述)。当我们点击这个链接时,我们生成一个“GET//”,其中是“pan”,是“30度”。这些参数将传递给网络服务器的应用程序中。(appCamPanTilt1.py)。

让我们来看看appCamPanTilt1.py上的这部分代码:

@app.route(“//“) def move(servo, angle): global panServoAngle global tiltServoAngle if servo == ‘pan’: panServoAngle = int(angle) os.system(“python3 angleServoCtrl.py ” + str(panPin) + ” ” + str(panServoAngle)) if servo == ’tilt’: tiltServoAngle = int(angle) os.system(“python3 angleServoCtrl.py ” + str(tiltPin) + ” ” + str(tiltServoAngle)) templateData = { ‘panServoAngle’ : panServoAngle, ’tiltServoAngle’ : tiltServoAngle } return render_template(‘index.html’, **templateData)

在这个例子中,“servo”等于“pan”,下列两行将被执行:

panServoAngle = int(angle) os.system(“python3 angleServoCtrl.py ” + str(panPin) + ” ” + str(panServoAngle))

我们在这里所做的与我们在树莓派终端上测试舵机位置时所做是一样的。云台用“27”表示和云台舵机角度用“30”表示。该应用程序将生成命令:

python3 angleServoCtrl 27 30

请注意,在这种情况下,我们不需要使用“sudo”,因为该应用程序已经开始使用“sudo”。

这个视频将显示项目如何工作以及如何在树莓派终端上的接受请求:

使用增量/减量角度按钮

有时我们只需要几个按钮就可以逐步移动我们的舵机:

平移:向左/向右

倾斜:向上/向下

我们也可以使用+/-按钮(增量 /减少角度),你自己去选择。让我们创建一个新目录:

mkdir PanTiltControl2

在这个目录中,我们将创建以下环境和文件:

├── Documents └── PanTiltControl2 ├── camera_pi.py ├── angleServoCtrl.py ├── appCamPanTilt2.py ├── templates | └── index.html └── static └── style.css

camera_pi.py和angleServoCtrl.py文件与之前使用的文件相同。你可以从我的GitHub仓库下载这两个文件,请点击相关链接或以上相同链接。

现在我们需要appCamPanTilt2.py,index.html和style.css。你可以从我的GitHub仓库下载,请点击相关链接。注意它们在你的目录上的位置是否正确。

我们来看一下新的 index.html:

MJRoBot Lab Live Streaming

MJRoBot Lab Live Streaming


PAN Angle: [ {{ panServoAngle }} ] +

TILT Angle: [ {{ tiltServoAngle }} ] +


@2018 Developed by MJRoBot.org

index.html与上一个非常相似。在这个index.html中代码仅被2行代替,在这里我们只有4个按钮平移 [+],平移 [ – ],倾斜 [+]和倾斜 [ – ]。

我们来分析其中一个按钮:

这也是一个简单的HTML超链接,我们将其设计为一个按钮链接(作为按钮在style.css中描述)。当我们点击这个链接时,我们产生一个“GET / / ”,其中是“平移”,< – >是“减小角度”。这些参数将被传送到网络服务器应用程序中(appCamPanTilt2.py)。

让我们来看看appCamPanTilt2.py上的这部分代码:

@app.route(“//“) def move(servo, angle): global panServoAngle global tiltServoAngle if servo == ‘pan’: if angle == ‘+’: panServoAngle = panServoAngle + 10 else: panServoAngle = panServoAngle – 10 os.system(“python3 angleServoCtrl.py ” + str(panPin) + ” ” + str(panServoAngle)) if servo == ’tilt’: if angle == ‘+’: tiltServoAngle = tiltServoAngle + 10 else: tiltServoAngle = tiltServoAngle – 10 os.system(“python3 angleServoCtrl.py ” + str(tiltPin) + ” ” + str(tiltServoAngle)) templateData = { ‘panServoAngle’ : panServoAngle, ’tiltServoAngle’ : tiltServoAngle } return render_template(‘index.html’, **templateData)

在这个例子中,“servo”等于“平移”,下面将被执行:

if angle == ‘+’: panServoAngle = panServoAngle + 10 else: panServoAngle = panServoAngle – 10 os.system(“python3 angleServoCtrl.py ” + str(panPin) + ” ” + str(panServoAngle))

一旦“角度”等于“ – ”,我们将平台舵机角度减10,并将此参数传递给我们的指令。假设实际的平台舵机的角度是90。新参数将是80。

因此,云台用“27”表示,云台舵机角度用“80”表示。该应用程序将生成命令:

python3 angleServoCtrl 27 80

请注意,在这种情况下,我们不需要使用“sudo”,因为该应用程序已经开始使用“sudo”。

网页的工作:

使用“POST”方法

有时可能会发送特定的角度命令,如:

平移角度==> 35度

倾斜角度==> 107度

这就意味,或者你会在最后一步将你的增量定义为“1”,需要花费很多时间才能达到想要的位置,或者你从网页创建一个POST。让我们探讨这一步的可能性。

我们再来创建一个新目录:

mkdir PanTiltControl3

在这个目录中,我们创建以下环境和文件:

camera_pi.py和angleServoCtrl.py文件与之前使用的文件相同。你可以从我的GitHub仓库下载这两个文件,请点击相关链接或以上相同链接。

现在我们需要appCamPanTilt3.py,index.html和style.css。你可以从我的GitHub仓库下载这些文件,请点击相关链接。注意它们在你的目录上的位置是否正确。

我们来看看新建的 index.html:

MJRoBot Lab Live Streaming

MJRoBot Lab Live Streaming

Enter Pan Tilt Servo Angle:

PAN: TILT:


@2018 Developed by MJRoBot.org

index.html现在与之前的有点不同。我们将在这里创建一个“表单”,用POST的方法。一个HTML表单输入标签将被用来作为平移/倾斜角度值的参数上传到用户。当按下“提交”按钮时,这些参数将被传递到网络服务器应用程序(appCamPanTilt3.py)。

我们来看看appCamPanTilt3.py上的这部分代码:

@app.route(‘/’, methods=[‘POST’]) def my_form_post(): global panServoAngle global tiltServoAngle panNewAngle = int(request.form[‘panServoAngle’]) if (panNewAngle != panServoAngle): panServoAngle = panNewAngle os.system(“python3 angleServoCtrl.py ” + str(panPin) + ” ” + str(panServoAngle)) tiltNewAngle = int(request.form[’tiltServoAngle’]) if (tiltNewAngle != tiltServoAngle): tiltServoAngle = tiltNewAngle os.system(“python3 angleServoCtrl.py ” + str(tiltPin) + ” ” + str(tiltServoAngle)) templateData = { ‘panServoAngle’ : panServoAngle, ’tiltServoAngle’ : tiltServoAngle } return render_template(‘index.html’, **templateData)

我们要做的是检查角度发生了变化,是否完成相对应的的指令。

结语

一如既往,我希望这个项目能够帮助他人进入激动人心的电子世界!

有关详细信息和最终代码,请访问我的GitHub仓库:WebCam-Pan-Tilt-Control-via-Flask,或本项目文件库。

via

用 Ngrok 和树莓派绕过防火墙访问内网

绝大多数安全研究人员所面临的一个常见问题,就是如何在目标网络部署了严格的企业级防火墙或路由器时,如何访问目标企业网络内的办公计算机或者本地设备。在很多情况下,我们的办公室电脑会在防火墙的保护下接入互联网。那么问题就来了,在默认情况下,它并不会允许来自外部网络的流量进入内网。这也就意味着,你可以使用办公室电脑与互联网中的外部主机进行通信,但远程设备却无法与你的办公室电脑连接。

PS:本文仅用于技术讨论与分享,严禁用于任何非法用途

如果你想用家里的电脑访问办公室电脑中的文件或其他资料的话,这就非常令人头疼了。那现在该怎么办呢?我们有没有什么办法去访问路由器或防火墙背后的联网设备呢?

我们能想到的有如下四种方法:

1. 添加防火墙规则,并允许指定的远程IP绑定指定端口来访问办公室电脑

2. 端口转发

3. 反向SSH

4. Ngrok

Ngrok

Ngrok这种服务允许我们利用外部端口转发并通过任何网络来连接任意设备(LAN/WAN)。Ngrok最大的一个优势就在于,如果你想访问某个网络中的设备时,你并不需要让自己的设备同样处于同一本地网络之中。在Ngrok的帮助下,你可以通过SSH、FTP或Web服务器来访问目标设备。(Ngrok 参考资料)

既然我们已经了解了Ngrok的功能,那么接下来我们会使用Ngrok来设置办公室电脑来接受远程设备的SSH连接。我们会给大家提供一个简单的Ngrok使用样例,我会在公司内网的办公室电脑中开启一台SSH服务器(端口22),并设置Ngrok,然后使用Ngrok链接从外网访问这台办公室电脑。

第一步:设置账号

访问 ngrok.com 创建一个Ngrok账号。

完成了账号注册之后,你将会得到一个认证令牌,你需要使用这个令牌来连接你的树莓派和Ngrok账号,这个需要注意。

第二步:下载Ngrok

使用下列命令在你的树莓派上下载Ngrok:

sudo wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip

接下来,使用下列命令提取文件:

unzip ngrok-stable-linux-amd64.zip

如果一切顺利的话,你将会看到一个名叫“ngrok”的文件:

第三步:创建你的账号

使用下列命令来设置你的认证令牌(authtoken):

./ngrok authtoken 4BSL861jeVz9wt7AM91QM_aksO43YvcKgmtC4pxv

第四步:运行Ngrok

现在你可以使用下列命令运行Ngrok(端口22):

./ngrok TCP 22

现在,你将会看到如下所示的信息:

Web Interface http://127.0.0.1:4040 Forwarding tcp://0.tcp.ngrok.io:36428 -> localhost:22

上面的数据表示,任何指向‘0.tcp.ngrok.io’(端口36428)的链接都将被重定向到目标设备(端口22)上。

第五步:使用远程PC访问你的办公室电脑

现在,你可以使用下列命令从远程PC上访问你的办公室设备了:

ssh user@0.tcp.ngrok.io -p 36428

没错,一切就是这么简单,你可以使用这种方法随时访问你的办公室电脑。

转自 freebuf.com,作者 Alpha_h4ck