🎉
NodeJSで遠隔操作してみた
暇だったので、nodeで簡単な遠隔操作をしてみることにしました
環境:
OS: MacOS
editor: vscode
デレクトリ:
.
├── test.mp3 <= 3
├── index.html <= 2
└── server.js <= 1
1 directory, 5 files
ソースコード:
index.html
とserver.js
を作成してください
1のコード
main.js
const http = require("http");
const fs = require("fs");
const PORT = 8000;
const html = fs.readFileSync("./index.html", "utf8");
const player = require("play-sound")((opts = {}));
const filePath = "test.mp3";
const { styleText } = require('node:util')
// ユーザー名とパスワードを設定
const USERNAME = "admin";
const PASSWORD = "password";
// isSelectedの状態を保持する
let isRunning = false; // 処理が起動しているかどうかを示すフラグ
let intervalId = null; // 処理を継続するためのID
// HTTP Basic Authenticationをチェック
const authenticate = (req) => {
const auth = req.headers["authorization"];
if (!auth) {
return false; // 認証がない
}
const [username, password] = Buffer.from(auth.split(" ")[1], "base64")
.toString()
.split(":");
return username === USERNAME && password === PASSWORD;
};
// サーバーを作成
const server = http.createServer((req, res) => {
if (!authenticate(req)) {
res.writeHead(401, { "WWW-Authenticate": "Basic" });
res.end("Authorization required");
return;
}
// 認証成功時の処理
if (req.method === "GET") {
const errorMessage = styleText('green', 'GET :');
console.log(errorMessage);
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
res.end(html);
} else if (req.method === "POST" && req.url === "/toggle") {
const errorMessage = styleText('green', 'POST :');
console.log(errorMessage);
let body = "";
req.on("data", (chunk) => {
body += chunk;
});
req.on("end", () => {
try {
const { isSelected } = JSON.parse(body);
handleToggle(isSelected, res);
} catch (error) {
console.error("JSON parsing error:", error);
res.writeHead(400, { "Content-Type": "application/json; charset=utf-8" });
res.end(JSON.stringify({ error: "Invalid JSON" }));
}
});
} else {
res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
res.end("Not Found");
}
});
// 処理の開始または停止
const handleToggle = (isSelected, res) => {
if (isSelected && !isRunning) {
isRunning = true;
const errorMessage = styleText('blue', '開始します');
console.log(errorMessage);
intervalId = setInterval(() => {
const errorMessage = styleText('red', 'StartMp3');
console.log(errorMessage);
player.play(filePath, (err) => {
if (err) {
console.log(`エラーが発生しました: ${err}`);
}
});
}, 1000); // 1秒ごとにログを出力
} else if (!isSelected && isRunning) {
isRunning = false;
const errorMessage = styleText('blue', '停止します');
console.log(errorMessage);
clearInterval(intervalId);
intervalId = null;
}
res.writeHead(200, { "Content-Type": "application/json; charset=utf-8" });
res.end(JSON.stringify({ message: "State received" }));
};
// サーバーを起動
server.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
2のコード
index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>遠隔操作ボタン</title>
<style>
body {
background-color: #1a1a1a;
color: #fff;
font-family: 'Arial', sans-serif;
overflow: hidden;
}
.center {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
position: relative;
}
.toggle-btn {
background-color: #007bff;
color: #fff;
padding: 15px 30px;
border: none;
border-radius: 10px;
cursor: pointer;
font-size: 1.5em;
position: relative;
outline: none;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.8);
transition: transform 0.3s;
z-index: 1;
}
.selected {
background-color: #26ff00;
animation: glow 1s infinite alternate;
}
@keyframes glow {
from {
box-shadow: 0 0 20px rgba(47, 255, 0, 0.5);
}
to {
box-shadow: 0 0 40px rgb(94, 255, 0);
}
}
.error-message {
color: rgb(115, 255, 0);
font-weight: bold;
position: absolute;
top: 0; /* ボタンの上に表示 */
left: 50%;
transform: translateX(-50%);
display: none; /* 初期は非表示 */
z-index: 2;
}
.server-message {
color: blue;
font-weight: bold;
position: absolute;
top: 0; /* ボタンの上に表示 */
left: 50%;
transform: translateX(-50%);
display: none; /* 初期は非表示 */
z-index: 2;
}
.server_err {
background-color: rgb(251, 59, 59);
color: #fff;
padding: 15px 30px;
border: none;
border-radius: 10px;
/*cursor: pointer;*/
font-size: 1.5em;
position: relative;
outline: none;
/*box-shadow: 0 0 10px rgba(0, 0, 0, 0.8);*/
transition: transform 0.3s;
z-index: 1;
}
.server_sf {
background-color: rgb(78, 99, 255);
color: #fff;
padding: 15px 30px;
border: none;
border-radius: 10px;
/*cursor: pointer;*/
font-size: 1.5em;
position: relative;
outline: none;
/*box-shadow: 0 0 10px rgba(0, 0, 0, 0.8);*/
transition: transform 0.3s;
z-index: 1;
}
</style>
</head>
<body>
<div class="center">
<div class="server_sf" id="serverMessage">安全</div>
<div class="server_err" id="errorMessage">エラー</div>
<button class="toggle-btn" id="toggleButton">実行</button>
</div>
<script>
const button = document.getElementById('toggleButton');
const errorMessage = document.getElementById('errorMessage');
const serverMassage = document.getElementById('serverMessage');
let isSelected = false;
errorMessage.style.display = 'none'; // 正常な応答時にエラーメッセージを非表示
serverMassage.style.display = 'block'; // 正常な応答時にエラーメッセージを非表示
button.addEventListener('click', () => {
isSelected = !isSelected;
button.classList.toggle('selected', isSelected);
button.textContent = isSelected ? "運転中..." : "実行";
fetch('/toggle', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ isSelected })
})
.then(response => {
console.log('サーバーの応答:', response); // サーバー応答のデバッグ
if (!response.ok) {
throw new Error("サーバーの応答が不正です");
}
return response.json();
})
.then(data => {
console.log('サーバーからの応答:', data);
errorMessage.style.display = 'none'; // 正常な応答時にエラーメッセージを非表示
serverMassage.style.display = 'block'; // 正常な応答時にエラーメッセージを非表示
})
.catch(error => {
console.error('エラー:', error);
console.error('サーバーからの応答')
errorMessage.style.display = 'block'; // エラー時にエラーメッセージを表示
serverMassage.style.display = 'none'; // 正常な応答時にエラーメッセージを非表示
});
});
</script>
</body>
</html>
3のmp3
mp3のフリー音源を探してきて、作業デレクトリにもっていってtest.mp3と名前を変えればOK
実行
npm install play-sound
node main.js
そしたらhttp://localhost:8000に移動して
あと一応パスワードをつけといたんで、admin
password
ログインできますが
server.jsの一部分
// ユーザー名とパスワードを設定
const USERNAME = "admin";
const PASSWORD = "password";
ここの部分で設定できます
最後に
重要
僕の場合
% ifconfig
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384
options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP>
inet 127.0.0.1 netmask 0xff000000 <= この行!
inet6 ::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1
nd6 options=201<PERFORMNUD,DAD> ...
つまり他のパソコンや端末で動かすためには、
調べたやつ:127.0.0.1
:8000
ということなのでhttp://127.0.0.1:8000に行けばうまくいきます
よくわからない時はGemini
やChatGPT
に聞くとわかったりします
Discussion