树莓派和arduino结合
![IoTWeek_Gray](https://i-blog.csdnimg.cn/blog_migrate/39d7e624f5b2f082f8aa59f3ca219de5.webp?x-image-process=image/format,png)
It’s IoT Week at SitePoint! All week we’re publishing articles focused on the intersection of the internet and the physical world, so keep checking the IoT tag for the latest updates.
这是SitePoint的IoT周! 我们整周都在发布有关互联网与物理世界交汇点的文章,因此请继续检查IoT标签以获取最新更新。
Some of the most interesting programming I’ve done has been in Minecraft. It’s an open-world, sandbox game developed by Mojang, (recently acquired by Microsoft). Minecraft began as a canvas for creative expression, and while I do very different things in it these days, it still is that for me.
我做过的一些最有趣的编程是在Minecraft中进行的 。 这是Mojang (最近被Microsoft收购)开发的开放世界的沙盒游戏。 Minecraft最初是用于表达创意的画布,尽管如今我在其中做着非常不同的事情,但对我而言仍然如此。
I’m going to take you on a journey, as we build a Minecraft mansion, and then secure it with a real-world alarm system. There’s quite a bit of ground to cover, and though I plan for this to be a two-part series, I’m going to have to leave some of the tangential details for you to discover!
我将带您踏上旅途,在我们建造Minecraft豪宅后,再使用真实世界的警报系统对其进行保护。 有足够的基础要介绍,尽管我计划将其分为两个部分,但我将不得不留下一些切线的细节供您发现!
You can find the code for this tutorial at https://github.com/sitepoint-editors/tutorial-php-arduino-and-minecraft
您可以在https://github.com/sitepoint-editors/tutorial-php-arduino-and-minecraft上找到本教程的代码
我的世界编程速成课程 (Crash Course in Minecraft Programming)
Minecraft began as the combination of two simple ideas. The first is that players can harvest resources from the map in which they find themselves. Some of these resources, like food and wood, are common above ground. Others, like gold and stone, require a bit of virtual elbow-grease.
Minecraft最初是两个简单想法的结合。 首先是玩家可以从自己发现的地图中收获资源。 这些资源中的某些资源(例如食物和木材)在地面上很常见。 其他的,例如黄金和石头,需要一点点的肘部润滑脂。
This is where the “mine” (in Minecraft) comes from. One of these resources is called Redstone. It’s found deep underground, and it’s a conductor of sorts. When harvested and placed on the ground, it resembles the silvery lines on the flip side of circuit boards. There are also power emitters, similar to batteries or mains power, which take many forms in the game.
这就是“地雷”(在Minecraft中)的来源。 这些资源之一称为Redstone。 它被发现在地下深处,是各种各样的指挥。 当被收获并放在地面上时,它类似于电路板反面的银色线条。 在游戏中也有类似于电池或市电的发射器。
![In-game screenshot of Redstone](https://i-blog.csdnimg.cn/blog_migrate/331cc70fc5e49b391d7186d1a5f9e320.webp?x-image-process=image/format,png)
Using these harvested resources, players can build dwellings, cook food and even wire up virtual circuitry. This is where the “craft” comes from.
利用这些收获的资源,玩家可以建造房屋,烹饪食物甚至连接虚拟电路。 这就是“手Craft.io品”的来源。
I talk about all of this, as well as basic circuitry and programming, in my conference talk Zombies and Binary. I presented it most recently at php[tek] 2016, but the recording was lost. Here’s a JavaScript-themed version, from FluentConf 2016: https://youtu.be/APJRBZUxADQ.
我在会议演讲《僵尸和二进制》中讨论了所有这些以及基本电路和编程。 我最近在php [tek] 2016上展示了它,但是录音丢失了。 这是来自FluentConf 2016JavaScript主题版本: https ://youtu.be/APJRBZUxADQ。
Imagine we’ve created a sprawling Minecraft mansion…
想象一下,我们创建了一个庞大的Minecraft大厦...
![In-game screenshot of mansion](https://i-blog.csdnimg.cn/blog_migrate/8ce1ae9188c0609ba32519fc2ca7634d.webp?x-image-process=image/format,png)
Now, imagine we want to secure the front door of said mansion…We need a way to check whether the front-door has been opened. To do this, we need to use Redstone, something called a Comparator, and another thing called a Command block:
现在,假设我们要固定所述大厦的前门……我们需要一种方法来检查前门是否已打开。 为此,我们需要使用Redstone(一种叫做Comparator的东西)和另一种称为Command块的东西:
![In-game screenshot of testing for block](https://i-blog.csdnimg.cn/blog_migrate/f51854d6aa7a7a12df572d431832fa1f.webp?x-image-process=image/format,png)
You may notice the switch I’ve connected to the Command block. Switches are one kind of power source, and this one will provide some power to the Command block so that it can perform the open door check. We’ll automate this power source in a bit…
您可能会注意到我已连接到Command块的开关。 开关是一种电源,该开关将为Command块提供一些电源,以便执行开门检查。 我们将稍微自动化该电源...
Command blocks are placeholders which can contain a single server command. Server commands are anything you as a player can do (provided you are a server admin or in single-player mode). They’re like Amazon Dash buttons, in that they can be given a single command to run, at the push of a button.
命令块是占位符,可以包含一个服务器命令。 服务器命令是您作为播放器可以执行的任何操作(前提是您是服务器管理员或处于单人游戏模式)。 它们就像Amazon Dash按钮一样 ,只需按一下按钮 ,就可以给它们一个命令来运行。
We’re going to make the Command block test for an open door. Minecraft maps are coordinate-based, which means the test needs to include coordinates for where the door will be placed. For argument’s sake, let’s say the door is at 191 67 -194
. The command for the test (of an open wooden door) will then be:
我们将对敞开的门进行Command块测试。 Minecraft地图是基于坐标的,这意味着测试需要包括门放置位置的坐标。 为了论证,我们假设门位于191 67 -194
。 (打开的木门的)测试命令将为:
/testforblock 191 67 -194 wooden_door 3
You can find your current map coordinates with fn + alt + F3 (for Mac) and F3 (for Windows). Walk to the block where you’ll place the door, and enter those coordinates in the command.
您可以使用fn + alt + F3(对于Mac)和F3(对于Windows)找到当前地图坐标。 步行到将放置门的块,然后在命令中输入这些坐标。
Different Minecraft blocks (whether crafted or naturally occurring) have unique block names. wooden_door
is the unique block name for an Oak door. 3
is a reference to the orientation of the door, so it might be different in your maps if you place your door in a different orientation. If so, try 0
through 3
until you get the desired result.
不同的Minecraft区块(无论是手工制作还是自然生成)具有唯一的区块名称。 wooden_door
是橡木门的唯一名称。 3
是门的方向的参考,因此如果您将门放置在不同的方向上,则在地图中可能会有所不同。 如果是这样,请尝试0
到3
直到获得所需的结果。
We’ll make the second Command block whisper a message back to us to indicate when the test has found a matching block. When we flick the switch, and the door is still closed, we should see nothing. But when we open the door (and the test matches the open door’s orientation), we should see confirmation of this!
我们将使第二个Command块耳语回传给我们,以指示测试何时找到匹配的块。 轻按开关,但门仍然关闭时,我们什么也看不到。 但是,当我们打开门(测试与打开的门的方向匹配)时,我们应该看到对此的确认!
![In-game moving image of testing for a block](https://i-blog.csdnimg.cn/blog_migrate/560be864e1a4251702136905ecc1ccd7.gif)
Now we have a way to check for an open door. We don’t want to be standing around, to manually run this check though. Let’s set up the programming equivalent of an infinite loop, or the electronic equivalent of a crystal clock.
现在,我们可以检查门是否打开。 我们不想站着,但是手动运行此检查。 让我们设置一个无限循环的编程等效项,或一个晶体时钟的电子等效项。
For this we need two Command blocks, arranged like this:
为此,我们需要两个Command块,如下所示:
![In-game screenshot of clock](https://i-blog.csdnimg.cn/blog_migrate/cd4f0dcdc5c8111594f9f6307ba7e742.webp?x-image-process=image/format,png)
Notice I’ve attached a button to each Command block, so that I can run their commands. These buttons also act as a power source, giving a brief power spike to the blocks they’re connected to.
注意,我已经在每个Command块上附加了一个按钮,以便可以运行它们的命令。 这些按钮也可以用作电源,为它们所连接的模块提供短暂的电源尖峰。
Map coordinates can also be relatively defined. That is, if you need to reference coordinates nearby the Command block, you can use ~-1 ~ ~+1
to mean the Command block’s x coordinate minus 1, the same y coordinate, and it’s z coordinate plus 1.
地图坐标也可以相对定义。 也就是说,如果需要参考Command块附近的坐标,则可以使用~-1 ~ ~+1
表示Command块的x坐标减1,相同的y坐标,z坐标加1。
In this arrangement, we want the top Command block to place a Redstone block just below it:
在这种安排中,我们希望顶部的Command块在其下方放置一个Redstone块:
/setblock ~ ~-1 ~ redstone_block
…And we want the bottom Command block to place a block of air above it:
…并且我们希望底部的Command块在其上方放置一个空气块:
/setblock ~ ~+1 ~ air
Redstone blocks also act as a power source. This arrangement has an interesting side-effect. When the top block places a Redstone block below itself, the Redstone block gives power first to the bottom Command block. It then gives power to the top Command block.
红石块也可以用作电源。 这种安排有一个有趣的副作用。 当顶部的块在其下方放置一个Redstone块时,Redstone块首先为底部的Command块供电。 然后,它为顶部的Command块供电。
In the meantime the bottom Command block has removed the Redstone block. Since the top Command block got a new power signal (from the Redstone block it placed) and the block was then removed by the bottom Command block, it starts the cycle over again.
同时,底部的Command块已删除Redstone块。 由于顶部的Command块获得了新的电源信号(从放置的Redstone块中获得),然后该块被底部的Command块移除,因此它再次开始了循环。
This leads to the infinite loop I spoke about. The loop will persist through server restarts, and if you’re in creative mode you’ll be able to break the Redstone block and see new ones created instantly.
这导致了我所说的无限循环。 该循环将在服务器重新启动后继续存在,如果您处于创作模式,则可以打破Redstone块并立即看到新创建的块。
![In-game animated image of working clock](https://i-blog.csdnimg.cn/blog_migrate/9e4e0ae0e4001363ce93e9b039c3b995.gif)
By default, these Command block actions will be logged and will trigger messages on the server. You can disable these with a couple commands (which you only have to enter once per map): /gamerule logAdminCommands false
and /gamerule commandBlockOutput false
.
默认情况下,这些命令块操作将被记录并触发服务器上的消息。 您可以使用几个命令来禁用这些命令(每个映射只需输入一次): /gamerule logAdminCommands false
和/gamerule commandBlockOutput false
。
If we take power from the clock, and direct it into the testing Command block, the test will run many times a second, giving immediate feedback when the door is opened!
如果我们从时钟获取电源,并将其导入测试Command模块,则测试将每秒运行多次,并在门打开时立即提供反馈!
Newer versions of Minecraft allow Command blocks to power themselves and even repeat themselves. With that, it’s possible for the door check to repeat without the clock. If you’re using an older version of Minecraft, especially when using mod packs, you may still need to make the clock yourself…
较新版本的Minecraft允许Command块自行供电,甚至重复运行。 这样一来,门的检查就可以在没有时钟的情况下重复进行。 如果您使用的是Minecraft的旧版本,尤其是在使用Mod Pack时,您可能仍需要自己动手做时钟…
![In-game animation of working door, opening and closing](https://i-blog.csdnimg.cn/blog_migrate/8a827d6d74262ad6d2fe24ebe4502c99.gif)
It’s also useful to know when the door has been closed, so we can turn the real-world alarm off. For that we can use an inverter (think of it as turning the closed door (false value) to a true value, in much the same way as we would in programming: while (true) if (!$doorOpen) print...
.
知道门何时关闭也很有用,因此我们可以关闭现实世界的警报。 为此,我们可以使用逆变器(将其视为关闭的门(假值)变为真值),这与编程中的方式几乎相同: while (true) if (!$doorOpen) print...
。
![In-game screenshot of inverter](https://i-blog.csdnimg.cn/blog_migrate/38d07b64a60c4db27e6c6f042813a593.webp?x-image-process=image/format,png)
使用PHP监视日志文件 (Watching Log Files with PHP)
All of this is pretty and useless without the ability to see these changes in PHP. We need a way to “hear” when the door has been opened, and react in PHP.
如果没有看到PHP中的这些更改,那么所有这些都是漂亮且无用的。 我们需要一种在门打开时“听”并用PHP做出React的方法。
Fortunately, the whispered messages are all logged. If we can figure out how to watch and interpret the log files, we should have all the information we need…
幸运的是,所有悄悄话都被记录下来了。 如果我们能弄清楚如何监视和解释日志文件,那么我们应该拥有所需的所有信息……
A quick Packagist search provides a file watcher library which looks like it’s up to the task. We can install it with:
快速的Packagist搜索提供了一个文件监视程序库 ,它看起来像由任务决定。 我们可以通过以下方式安装它:
composer require yosymfony/resource-watcher
After that’s done, let’s make a script to watch the log files. We begin by creating a Symfony Finder instance, and pointing it at the directory in which the Minecraft logs are stored:
完成之后,让我们编写一个脚本来监视日志文件。 我们首先创建一个Symfony Finder实例,然后将其指向Minecraft日志存储的目录:
require __DIR__ . "/vendor/autoload.php";
use Symfony\Component\Finder\Finder;
$path = "/path/to/Application Support/minecraft/logs";
$finder = new Finder();
$finder->files()
->name("*.log")
->depth(0)
->in($path);
The path to Application Support
will be different for you – it’s usually in the Library
folder associated with your account. You could also be using a portable version of Minecraft, so you’ll just have to search around a bit, until you find the logs
folder.
对您而言,“ Application Support
”的路径将有所不同–通常在与您的帐户关联的“ Library
文件夹中。 您可能还使用了Minecraft的便携式版本,因此只需要进行一些搜索,直到找到logs
文件夹。
This Finder instance narrows the file watch list to *.log
files in the same directory as the one we’ve specified. The methods are clearly named, so you can expand the criteria for other applications.
这个Finder实例将文件监视列表的范围缩小到与我们指定的目录相同的*.log
文件。 这些方法的名称很明确,因此您可以为其他应用程序扩展条件。
Next we need to define a cache file, and a watcher instance:
接下来,我们需要定义一个缓存文件和一个观察者实例:
use Yosymfony\ResourceWatcher\ResourceCacheFile;
use Yosymfony\ResourceWatcher\ResourceWatcher;
$cache = new ResourceCacheFile(__DIR__ . "/cache.php");
$watcher = new ResourceWatcher($cache);
$watcher->setFinder($finder);
while(true) {
sleep(1);
$watcher->findChanges();
// ...respond to changes
}
This script acts as a long-running process. That is, we want to watch for changes to files, for an indeterminate amount of time. So we create an infinite loop, and use it to constantly probe for file changes.
该脚本是一个长期运行的过程。 也就是说,我们要在不确定的时间内监视文件的更改。 因此,我们创建了一个无限循环,并使用它来不断探测文件更改。
You can sleep for more or less time. I found 1 second was good enough for me…
您可以睡更多或更少的时间。 我发现1秒对我来说已经足够了……
The watcher library provides methods for three kinds of file changes: creation, deletion and updates. We only care about the updates:
监视程序库提供了用于三种文件更改的方法:创建,删除和更新。 我们只关心更新:
while(true) {
sleep(1);
$watcher->findChanges();
// ...respond to changes
$changes = $watcher->getUpdatedResources();
if (count($changes) > 0) {
$first = $changes[0];
$lines = file($first);
for ($i = count($lines) - 1; $i > -1; $i--) {
if (stristr($lines[$i], "CHAT")) {
if (stristr($lines[$i], "closed")) {
print "closed!";
}
if (stristr($lines[$i], "open")) {
print "open!";
}
break;
}
}
}
}
New chat messages are appended to the bottom of the log file, so we need to check if any log files have been modified (we expect only one log file), split the log file into lines and check each line from the bottom of the file to the top.
新的聊天消息将追加到日志文件的底部,因此我们需要检查是否有任何日志文件被修改(我们期望只有一个日志文件),将日志文件分成几行,然后从文件底部检查每一行到顶部。
If we see a log line containing CHAT
, we can assume it is a chat message. If it also contains open
or closed
, we can assume it is caused by the circuit we created.
如果看到包含CHAT
的日志行,我们可以假定它是聊天消息。 如果它还包含open
或closed
,则可以假定它是由我们创建的电路引起的。
![Animated image of PHP and Minecraft working together](https://i-blog.csdnimg.cn/blog_migrate/bcb1dbc74f9f40168ade659cd81cd5b9.gif)
You’re welcome to use more “unique” message formats for open/close events. The approach I’ve chosen is simple but open to abuse and ambiguity (like if someone else whispers “open” to me). The underlying principles are the same though.
欢迎您为打开/关闭事件使用更多“独特”的消息格式。 我选择的方法很简单,但容易受到滥用和模棱两可的影响(例如,如果有人对我说“开放”)。 基本原理是相同的。
This is only half of the experiment. In the followup post we’ll look at how to build an Arduino-based alarm circuit, and connect it to this script. The end result will be an automated, real-world alarm for our Minecraft mansion.
这只是实验的一半。 在后续文章中,我们将研究如何构建基于Arduino的警报电路,并将其连接到此脚本。 最终结果将是为我们的Minecraft豪宅提供一个自动的,真实世界的警报。
If you’ve enjoyed this and/or have questions, please let us know in the comments!
如果您喜欢这个和/或有疑问,请在评论中告诉我们!
翻译自: https://www.sitepoint.com/php-arduino-and-minecraft-combining-minecraft-with-php/
树莓派和arduino结合