[IoT] OPEN THE DOOR スマホでドアを開ける [ESP8266]Wi-Fiモジュール [arduino IDE]
背景
会社の事務所の玄関ドアがめっちゃ古くてICカードも使えず鍵しか使えない、あるいはインタホンで室内の人呼び出し、ドアを開けてあげる。今Iotの時代がやって来て、こんなに面倒な入室システムは時代に遅れている、改造していきたいと思います。(物理的な破壊ぜず、今の入室システム影響無いように改造する)。
設計
ユースケース:入室しようとする人が玄関でルーム番号入力し「呼び出す」を押すと室内のインタホンが鳴り始めて、受話器を取って解除ボタンを押してドアが開く。
受話器の取り上げと解除ボタンの押下を自動的にすれば、実現できるはずです。
システム設計図:
機械調達
社内サーバーを用意します。
ebayにて購入したESP8266マイコンボードも無事に届きました。
コントローラーの設計
部品:
- ESP8266ボード X 1
- 基盤X1
- トランジスター(NPN) X 2
- 5Vリレー X 2
- ジャンパーワイヤー 若干
回路図:
半田付け後実物:
ESP8266ボードの開発:
usbシリアル変換ドライバのインストール、ARDUINO IDEのインストール、ESP8266ボードの追加など略にします。(GOOGLEで検索すれば、出るはずです。)
ソースコード:
#include
#include
const char* ssid = "xxxxxxxxxxx";
const char* password = "xxxxxxxxx";
WiFiUDP Udp;
unsigned int localUdpPort = 4242; // local port to listen on
char incomingPacket[255]; // buffer for incoming packets
char replyPacket[] = "Hi there! Got the message :-)"; // a reply string to send back
void setup() {
Serial.begin(115200);
delay(10);
// prepare GPIO2
pinMode(2, OUTPUT);
digitalWrite(2, 0);
// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_AP_STA);
WiFi.softAP(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN,HIGH);
// not working DC Current per I/O Pin: 40 mA
digitalWrite(LED_BUILTIN,LOW);
// Print the IP address
Serial.println(WiFi.localIP());
Udp.begin(localUdpPort);
}
void loop() {
int packetSize = Udp.parsePacket();
if (packetSize)
{
// receive incoming UDP packets
Serial.printf("Received %d bytes from %s, port %d\n", packetSize, Udp.remoteIP().toString().c_str(), Udp.remotePort());
int len = Udp.read(incomingPacket, 255);
if (len > 0)
{
incomingPacket[len] = 0;
}
Serial.printf("UDP packet contents: %s\n", incomingPacket);
if (String(incomingPacket) == "open the door")
{
Serial.printf("begin");
// Set GPIO2 according to the request
digitalWrite(2, 1);
Serial.printf("sleep 1 s");
delay(1000);
digitalWrite(2, 0);
Serial.printf("end");
}
// send back a reply, to the IP address and port we got the packet from
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
Udp.write(replyPacket);
Udp.endPacket();
}
}
スマホ画面の設計
ボタン一個だけでとてもシンプルなデザインです。(シンプルイズザベスト)
AJAX HTML:
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/css/bootstrap.min.css" integrity="sha384-Smlep5jCw/wG7hdkwQ/Z5nLIefveQRIY9nfy6xoR1uRYBtpZgI6339F5dgvm/e9B" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.1/css/all.css" integrity="sha384-O8whS3fhG2OnA5Kas0Y9l3cfpmYjapjI0E4theH4iuMD+pLhbf6JI0jIMfYcK3yZ" crossorigin="anonymous">
<title>UENO</title>
<style>
@charset "UTF-8";
html,
body {
height: 100%;
}
body {
display: -ms-flexbox;
display: flex;
-ms-flex-align: center;
align-items: center;
vertical-align: middle;
}
div {
width: 100%;
margin: auto;
}
.btn{
display: inline-block;
text-decoration: none;
color: rgba(255, 0, 0, 0.8);/*アイコン色*/
width: 80px;
height: 80px;
line-height: 80px;
font-size: 40px;
border-radius: 50%;
text-align: center;
vertical-align: middle;
overflow: hidden;
font-weight: bold;
background-image: -webkit-linear-gradient(#e8e8e8 0%, #d6d6d6 100%);
background-image: linear-gradient(#e8e8e8 0%, #d6d6d6 100%);
text-shadow: 1px 1px 1px rgba(255, 255, 255, 0.66);
box-shadow: inset 0 2px 0 rgba(255,255,255,0.5), 0 2px 2px rgba(0, 0, 0, 0.19);
border-bottom: solid 0px #b5b5b5;
}
.btn .fa {
line-height: 80px;
}
.btn:active {/*押したとき*/
background-image: -webkit-linear-gradient(#efefef 0%, #d6d6d6 100%);
box-shadow: inset 0 1px 0 rgba(255,255,255,0.5), 0 2px 2px rgba(0, 0, 0, 0.19);
border-bottom: none;
}
</style>
</head>
<body class="text-center">
<div>
<a href="#" class="btn"><i class="fa fa-power-off"></i></a>
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js" integrity="sha384-o+RDsa0aLu++PJvFqy8fFScvbHFLtbvScb8AjopnFD+iEQ7wo/CG0xlczd+2O/em" crossorigin="anonymous"></script>
</body>
<script type="text/javascript">
<!--
$(function(){
$( ".btn" ).click(function() {
$.post("open",
{ t: new Date().getTime() },
function(data, status){ console.log("Data: " + data + "\nStatus: " + status); }
);
});
});
//-->
</script>
</html>
バックエンド設計
java servletのソースコード:
package web;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Objects;
import java.util.logging.FileHandler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class OpenTheDoor
*/
public class OpenTheDoor extends HttpServlet {
private static final long serialVersionUID = 1L;
private Logger logger = Logger.getLogger(OpenTheDoor.class.getName());
/**
* Default constructor.
*/
public OpenTheDoor() {
try {
logger.setUseParentHandlers(false);
FileHandler fh = new FileHandler("/data/log/ueno.log");
logger.addHandler(fh);
SimpleFormatter formatter = new SimpleFormatter();
fh.setFormatter(formatter);
logger.info("The server are started.");
} catch (Exception e) {}
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getRequestDispatcher("WEB-INF/index.jsp").forward(request, response);
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
service();
logger.info("Some one opened the door.");
}
private void service() {
short port = 4242;
DatagramSocket socket = null;
try {
byte[] buf = "open the door".getBytes();
socket = new DatagramSocket();
socket.setBroadcast(true);
// Maybe the Router does not work.
// Change to local broadcasting ip ex. 192.168.1.255
//InetAddress address = InetAddress.getByName("255.255.255.255");
//InetAddress address = InetAddress.getByName("192.168.1.255");
//DatagramPacket packet = new DatagramPacket(buf, buf.length, address, port);
//socket.send(packet);
List broadcastAddress = this.listAllBroadcastAddresses();
for (InetAddress inetAddress : broadcastAddress) {
socket.send(new DatagramPacket(buf, buf.length, inetAddress, port));
}
} catch (Exception e) {
} finally {
if (socket != null)
socket.close();
}
}
List listAllBroadcastAddresses() throws SocketException {
List broadcastList = new ArrayList();
Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
if (networkInterface.isLoopback() || !networkInterface.isUp()) {
continue;
}
networkInterface.getInterfaceAddresses().stream().map(a -> a.getBroadcast()).filter(Objects::nonNull)
.forEach(broadcastList::add);
}
return broadcastList;
}
}
オートロックの分解、分析
既存のオートロック分解してハイキングします。
取り付け
コントローラー取り付けした様子です。
完成
検証してみると上手くできました。
Comments
Post a Comment