はじめに

私の勤めている会社は退勤時にweb上で打刻、もしくは後で退勤時間を記載するという仕組みになっています。
その打刻するサイトのUIがあまりも使いにくく、さらに23時頃に退勤の日とかいちいちwebを開いて打刻するのが超めんどくさいのです。
そこで会社から離れたら自動的に打刻するシステムを作ろうと思ったのでレシピを下記に記述します。

前提条件

Node.jsがローカルPCに入っていること
npm or yarnがローカルPCに入っていること
会社の無線LANに接続できること(有線と同時接続でもOK)
googleApiに登録していること(無料。クレジットカード登録とかもいらない)

仕組み

PCのMACアドレスから現在地を特定して会社にいる場合は時間を記録し続けるという仕組み

作り方

googleApiは下記2つを使用する
Google Maps Geolocation API
Google Maps Geocoding API

googleApiに登録していてAPIキーを取得していれば2つともそのキーで下のソースのAPIを叩けるため特に意識することはないです。

command
mkdir worktimelog
cd worktimelog
mkdir timecard
mkdir logs
npm init

npm initの内容は適当でいいです。(一応サンプル載せます)

command
package name: worktimelog
version: (1.0.0) 1.0.0
description: worktimelog
entry point: (index.js) cron.js
test command: node cron.js
git repository:(エンターキー押してスキップしてください)
keywords: worktimelog
author: taisei_otsuka

npm init完了しましたら

command
npm install date-utils
npm install fs
npm install request
npm install wifi_location
vim cron.js

cron.jsの中身です。

cron.js
#!/usr/bin/env node
require("date-utils");
const fs = require("fs");
const request = require('request');
const wifiLocation = require("wifi_location");
// googleApiのapiキー
const apikey = "apikey";
const date = new Date();
// logsまでの絶対パス
const logFile = "logsまでの絶対パス" + date.toFormat("YYYYMMDD") + "_log.txt";
// timecardまでの絶対パス
const timecardFile = "timecardまでの絶対パス" + date.toFormat("YYYYMMDD") + "_timecard.txt";
// 会社の郵便番号
const address = "000-0000";
const dateFormat = date.toFormat("YYYY-MM-DD HH24:MI");
const timeAndMemory = "time -> " + dateFormat + " memory -> " + process.memoryUsage().rss;
function writeLog(log) {
    fs.appendFile(logFile, "\n" + log, function (err) {
        if (err) {
            throw err;
        }
    });
}
fs.access(timecardFile, fs.constants.R_OK | fs.constants.W_OK, (err) => {
    if (err) fs.writeFile(timecardFile, date.toFormat("YYYY-MM-DD HH24:MI"));
});
fs.access(logFile, fs.constants.R_OK | fs.constants.W_OK, (err) => {
    if (err) fs.writeFile(logFile, date.toFormat("ログを開始します。" + timeAndMemory));
});
wifiLocation.wifiTowers(function(err, obj) {
    if (obj.length === 0) writeLog("MACアドレスを取得できませんでした。" + dateFormat);
    let array = [];
    obj.map((value) => {
        delete value.ssid;
        return array.push({macAddress:value.mac_address,signalStrength:value.signal_strength});
    });
    let optionsPost = {
        url: "https://www.googleapis.com/geolocation/v1/geolocate?key=" + apikey,
        method: "POST",
        body: '{"considerIp": "false","wifiAccessPoints": ' + JSON.stringify(array) + '}',
        headers: {
            "Content-Type": "application/json"
        },
    };
    request(optionsPost, (error, response, body) => {
        if (!error && response.statusCode == 200) {
            body = JSON.parse(body).location;
            latlng = body.lat + "," + body.lng;
            let optionsGet = {
                url: "https://maps.googleapis.com/maps/api/geocode/json",
                qs: {
                    latlng: latlng,
                    key: apikey
                }
            };
            request(optionsGet, (error, response, body) => {
                if (!error && response.statusCode === 200) {
                    let addressBool = false;
                    JSON.parse(body).results[0].address_components.map((value) => {
                        if (value.types[0] === "postal_code") addressBool = value.long_name === address;
                    });
                    if (addressBool) {
                        fs.writeFile(timecardFile, dateFormat);
                        writeLog("書き込みました。" + timeAndMemory);
                    }
                }
            });
        }
    });
});

はい、お気づきかと思いますがローカルpcでcronする必要があります。

command
*/15 0,18-23 * * 1-5  /usr/local/bin/node /hogehoge/worktimelog/cron.js /dev/null 2>&1

月~金の18時~0時までの間15分おきにcron.jsを実行しますという意味です。

cronの設定方法がわからない方は、foreverを使用しcronの処理をデーモン化してみてください。

command
npm install cron time
npm install forever -g

foreverとnpm cronの併用の場合の記述方法

cron.js
const {CronJob} = require("cron");
new CronJob("*/15 0,18-23 * * 1-5", () => {
// ここに上記のcron.jsの内容を突っ込む
}, null, true);
command
forever cron.js

通常のcronの場合はpcがスリープしてても動きますし(なんでだろうw)pcを再起動しても動き続けます。
しかし
foreverでcronを叩いている場合はスリープ中は動かないですし、再起動するとforeverがstopしてしまいます。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.