4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Wi-Fi接続先アクセスポイントのMACアドレスをcurlでAPIサーバーに送信する

Posted at

はじめに

事務所をフリーアドレス化した際に有線LANからWi-Fiの無線LANに移行しました。
100人規模の事務所ですが、誰がどこにいるのか探すのが面倒なので、PCがどのアクセスポイントに繋がっているかで大まかな座席位置がわかるシステムを構築しました。

仕様

Windows10の netsh コマンドで取得したMACアドレス情報をcurlコマンドでAPIサーバーに送信し、受信したデータをMySQLデータベースにインサートします。
なお、集めたMACアドレスの利用方法についてはこの記事に記述していません。
PC利用者とWi-FiアダプタのMACアドレスを紐付けるテーブル、および、アクセスポイントのMACアドレスのテーブルが別途必要になります。

動作した環境

項目 内容
APサーバー node.js + Express
DBサーバー MySQL
クライアント Windows10

サーバーのディレクトリ構成

.
├── app.js
└── routes
    └── v1
       ├── index.js
       └── api_pcwosagasu.js

ソースコード

※稼働中のプログラムの一部をコピペしたもので、このサンプルが動作するかの検証は行っていません。

Expressアプリ

app.js
const express    = require('express');
const app        = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(function(req, res, next) {
    res.header('Access-Control-Allow-Origin',  '*');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept');
    next();
});

const port = process.env.PORT || 3000;
const router1 = require('./routes/v1/');
app.use('/app/v1/', router1);
app.listen(port);

ルーティング

index.js
var express = require('express');
var router = express.Router();
router.use('/pcwosagasu', require('./api_pcwosagasu.js'));
module.exports = router;

API本体

api_pcwosagasu.js
const express = require("express");
const router = express.Router();
const mysql = require("mysql");
const util = require('util');
module.exports = router;

async function execQuery(sql) {
    const pool = mysql.createPool({
        host     : 'localhost',
        port     : 3306,
        user     : 'user',
        password : 'password',
        database : 'pcwosagasu',
        timezone: 'jst',
        multipleStatements: true
    })
    pool.query = util.promisify(pool.query)
    try {
        const records = await pool.query(sql);
        pool.end();
        return records;
    } catch (err) {
        throw new Error(err)
    }
}

router.post("/", async (req, res) => {
    const macs = JSON.stringify(req.body).match(/(?:[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}/g);
    const results = await execQuery('INSERT INTO macs (mac_client,mac_ap) VALUES ("' + macs[0] + '","' + macs[1] + '")' );
    res.send(results);
});

Windowsコマンドの実行結果はShift-JISですがUTF-8の体でPOSTされます。
サーバー側では全角文字が文字化けしていますが欲しいのはMACアドレスだけなので、文字化けを無視して正規表現でMACアドレスを抜き出しています。

APIサーバーの起動

node ./app.js

Google Chromeでデバッグする場合は以下のコマンドで

node --inspect --inspect-brk ./app.js

MySQLデータベース定義

CREATE DATABASE IF NOT EXISTS `pcwosagasu`;
USE `pcwosagasu`;
DROP TABLE IF EXISTS `macs`;
CREATE TABLE IF NOT EXISTS `macs` (
  `mac_client` varchar(17) DEFAULT NULL,
  `mac_ap` varchar(17) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

MACアドレス情報のAPIサーバーへの送信

postmac.bat
netsh wlan show interfaces | curl -X POST -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" --data @- 192.168.123.45:3000/app/v1/pcwosagasu

このバッチファイルを「Bat_To_Exe_Converter」で非表示のEXEファイルに変換し、ADサーバーのログオンスクリプトに設定すれば、出社時にPCの電源を入れて接続したWi-Fiアクセスポイントが記録されます。

まとめ

作ってはみたものの、ひとつのアクセスポイントのカバー範囲が広すぎて大雑把なエリアしか分からず目視で探すのとあまり変わらないという結果になりました。
アクセスポイントの配置を最初に確認して実装に着手すべきでした。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?