上一节已经把servo的控制程序写好了,可以通过arduino IDE 中的串口监视器给arduino发送指令来控制开门。

这一节介绍如何远程调用API控制arduino开门。

流程

客户端 -> 调用API -> 发送指令 -> arduino -> 开门

api调用请求经过下面几个步骤:

手机 -> 发送请求 -> 路由器 -> 转发给内网web服务器 -> 服务器执行api,发送指令

硬件环境

客户端 路由器 -> 内网机器 -> arduino -> 舵机

实现

  • 搭建好内网web服务器 不差钱请用台式机,差钱的用闲置的笔记本,付不起电费的,树莓派能拯救你。

    搭建好web服务, 这里使用的是ubuntu + nginx + php

  • 设置虚拟服务器,在路由器设置端口转发,转发某个端口的请求到内网机器

  • 实现php发送指令给arduino

前一节已经介绍了把arduino链接到电脑上,链接后会在/dev目录下产生一个设备文件, 在ubuntu下是/dev/ttyACM0, 系统与arduino的通信都是通过这个文件来实现的, 所以也可以使用php给这个设备发送指令。

之前提过arduino是可以通过串口通信,github上已经有这个实现: PhpSerail

这个类做了两个动作:

  • 通过stty 命令初始化/dev/ttyACM0 为串口设备
  • 使用fwrite向设备发送数据

为了快速实现调用,我毫不犹豫的使用了这个轮子,具体调用代码如下:


<?php
/**
 * operation file
 *
 * communication with arduino by /dev/tty
 *
 * */
include 'PhpSerial.php';
$serial = new PhpSerial;

if (php_sapi_name() == "cli") {
    $action = trim( $argv[1] );  // 获取参数,可能为open或者1
} else {
    exit("Access Denied");
}


// First we must specify the device. This works on both linux and windows (if
// your linux serial device is /dev/ttyS0 for COM1, etc)

$serial->deviceSet("/dev/ttyACM0"); // 这里设置设备路径

// We can change the baud rate, parity, length, stop bits, flow control
$serial->confBaudRate(9600); // 设置波特率,跟servo程序里面的 Serial.begin(9600); 相对应
$serial->confParity("none");
$serial->confCharacterLength(8);
$serial->confStopBits(2);
$serial->confFlowControl("none");

// Then we need to open it
$serial->deviceOpen("w+");

// must sleep at least 2 seconds
// 这里必须延迟至少2秒来保证数据能够被arduino接收
sleep(2);

// To write into
$serial->sendMessage($action, 1);

// Or to read from
$read = $serial->readPort(9600);
//echo $read."\n===\n";
// If you want to change the configuration, the device must be closed
$serial->deviceClose();

?>

如果直接web调用这个文件,arduino偶尔会出现重复操作(开门两次),但是在cli模式下不会出现这个问题,这是个很奇怪的问题,还没有查出具体原因,所以先想了简单的办法解决。

在index.php执行operation.php:

<?php
    exec("php operation.php {$action}");
?>

全部代码:

<?php

if (isset($_GET['action'])) {
  
    $action = trim($_GET['action']);
    // open the door
    if ($action == 'open') //在servo的控制程序使用了open作为开门的指令
    {
        /**
          * visit operation will cause the arduino work inconrrect  ,
          * but work fine if in cli mode 
          * */
        exec("php operation.php {$action}");  // 执行operation.php 
        exit("Opened");
    }

    exit("Failed");
}
?>

现在已经可以直接访问 http://host/index.php?action=open 控制开门了,只要能访问到家里的路由器,就能随时执行开门的动作,awesome!

下一节包括以下内容:

  • 为api加上权限验证
  • 检测路由器IP变化并发送邮件通知的脚本

该主题其他文章: Remote-control-door

相关链接: