水無瀬のプログラミング日記

プログラムの勉強した時のメモ

RaspberrtPi3でSlackBotを動かす設定

はじめに

久しぶりにラズパイでslackbotを動かしたくなったので、設定した内容まとめ。
過去に一度設定したけど、微塵も覚えてないので、まとめついでに一から設定します。
ついでに、前に設定してなかったip固定とかsystemctlに登録とかしときます。

前提

作業しているPC:Mac(Sierra 10.12.6)
ラズパイ:Raspberry Pi 3 Model B

OS設定編(Macでの作業)

前回何設定したか覚えてないので、OS入れ直してついでにIPを固定しておく。
OSはここから好きなものをダウンロードする。
今回はRaspbianのwith Desktopの方を入れる。
※普通にライトで良かったなーと今更思った。

ダウンロードが終わったらSDカードをMacに挿してOSを入れる。
ここの処理を間違えると悲惨なことになるらしいので要注意。

# コピー先を探す
$ diskutil list 

# 一旦外す
$ diskutil unmountDisk /dev/disk6(※今回はたまたまdisk6だった)

# コピーする
$ sudo dd bs=1m if=[入れたいOS] of=/dev/rdisk6

ラズパイを起動する前にSSHの設定をしておく。
予めsshファイルを作って置けば最初からSSHで繋がるようになっているらしい。
やっとかないとあとで設定が必要そう。

# 中身はなくていいから作るだけ作っとく
$ touch /Volumes/boot/ssh

ラズパイ設定編

ラズパイを起動し早速ターミナルでいろいろ設定。

IP固定化

いちいち変わられても接続するのが面倒くさいので固定する。

$ sudo vi /etc/dhcpcd.conf

# 以下内容を追記
interface wlan0
static ip_address=[設定したい固定IPアドレス]/24
static routers=[デフォルトゲートウェイのIPアドレス]
static domain_name_servers=[DNSサーバーのIPアドレス]

# [SSID]と[PASSPHRASE]は環境に合わせて変更
# /etc/wpa_supplicant/wpa_supplicant.confにパスワードが書かれるので、嫌なら消しとく
$ sudo sh -c 'wpa_passphrase [SSID] [PASSPHRASE] >> /etc/wpa_supplicant/wpa_supplicant.conf'

# 最後に再起動
$ reboot

これでipアドレスが固定されればOK。

slackbotを入れて動かす

botPythonで動かすことにする。
Slack側の設定は終わってる前提です。
ライブラリはpip3 install slackbotでインストールしておく。
※ついでにvimも入れとく人はsudo apt-get install vimも叩いとく。

準備が出来たらbotを作成する。
とりあえず最小構成で動くとこまで。
フォルダ構成、ソースは以下の通り。

$ cd '任意のフォルダ'
# bot動かすファイル
$ touch run.py
# botの設定を書くファイル
$ touch slackbot_setting.py
# プラグインを入れとくフォルダ作成
$ mkdir plugins
# プラグインとして認識してもらうために、空ファイルでいいので作成
$ touch ./plugins/__init__.py
# -*- coding: utf-8 -*-

from slackbot.bot import Bot


def main():
    bot = Bot()
    bot.run()


if __name__ == "__main__":
    main()
# -*- coding: utf-8 -*-

API_TOKEN = "slackで確認したTOKEN"

default_reply = "は?何言ってんの?"


PLUGINS = [
    'plugins'
]

ファイルを用意したら、python3 run.pyで起動。
話しかけて、返事してくれればOK。

f:id:minase_mira:20180531225216p:plain

botをサービス化しとく

python3 run.py &とかで動かしておいても問題ないけど、一応ちゃんと設定しておく。
手順とファイルの内容は下記の通り。

# unit定義ファイル作成
$ sudo vim /etc/systemd/system/runUbibot.service

# リストにいることを確認
$ sudo systemctl list-unit-files --type=service | grep runUbibot
# 自動起動設定しておく
$ sudo systemctl enable runUbibot.service
# 起動
$ sudo systemctl start runUbibot.service
[Unit]
Description = 説明

[Service]
ExecStart = ~~/start.sh(絶対パスで)
# 再起動設定
Restart = alwasy
Type = simple

[Install]
WantedBy = multi-user.target
# このファイルに実行権限を与えとく`chmod 0777`とか
#!/bin/bash

# 直接これを指定する方法がわからなかったので、shell経由
python3 run.py

これで動いていればOK。

まとめ

これでいつ、ラズパイが消し飛んでも復活できるはず。
備忘録としてまとめておきます。

ExpressからmongoDBを使う

はじめに

NoSQLのDBを触ったこと無いので、勉強をしてみようと言う回。
ついでにExpressから動かせるようにしてみる。

前提条件

macOS

インストール

homebrewでインストール。

brew update
brew install mongodb

brew install mongodbで下のエラーが出た。

Error: Xcode alone is not sufficient on Sierra.
Install the Command Line Tools:
  xcode-select --install

言われた通りにxcode-select --installを実行。
インストーラー出て来るのでインストール。

動かしてみる

ここを参考にフォルダを作成する。

mkdir -p /data/db

mongodで起動。エラッタ

2018-04-13T20:59:18.279+0900 W NETWORK  [thread1] Failed to connect to 127.0.0.1:27017, in(checking socket for error after poll), reason: Connection refused
2018-04-13T20:59:18.280+0900 E QUERY    [thread1] Error: couldn't connect to server 127.0.0.1:27017, connection attempt failed :
connect@src/mongo/shell/mongo.js:251:13
@(connect):1:6
exception: connect failed

パーミッションも変えてあげないとダメらしい。
多分次のコメントが出ればOK。

waiting for connections on port 27017

使ってみる

mongoでターミナルから使ってみる。

操作方法(一部)

コマンド 説明
show dbs データベースの一覧を表示
use [DB名] [DB名]にデータベースを切り替える。無ければ作成。
db.createCollection([コレクション名]) コレクションの作成
db.[DB名].insert([データ]) データ追加。
db.[DB名].update([変更前データ],[変更後データ]) データ更新。
db.[DB名].insert([データ]) データ削除。
help ヘルプ表示
db.help() データベースへの操作ヘルプ
db.[コレクション名].help() コレクションへの操作ヘルプ

使ってみた感じは下記の通り。

# DB作成
> use test
switched to db test

# コレクション作成
> db.createCollection('testコレクション')
{ "ok" : 1 }

# 作成したものの確認
> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB
test    0.000GB

# データを入れる
> db.test.insert({id:1, name:'test1'})
WriteResult({ "nInserted" : 1 })

# 入れたデータを確認
> db.test.find()
{ "_id" : ObjectId("5ad4a42e31752cb52c3bc118"), "id" : 1, "name" : "test1" }

# まとめても入る
> db.test.insert([{id:2, name:'test2'},{id:3,name:'test3'}])
BulkWriteResult({
        "writeErrors" : [ ],
        "writeConcernErrors" : [ ],
        "nInserted" : 2,
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})

# ホントに入ったか確認
> db.test.find()
{ "_id" : ObjectId("5ad4a42e31752cb52c3bc118"), "id" : 1, "name" : "test1" }
{ "_id" : ObjectId("5ad4a4a131752cb52c3bc11a"), "id" : 2, "name" : "test2" }
{ "_id" : ObjectId("5ad4a4a131752cb52c3bc11b"), "id" : 3, "name" : "test3" }

# 更新してみる
> db.test.update({id:1},{ $set: {name:'test1Update'}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })

> db.test.find()
{ "_id" : ObjectId("5ad4a46831752cb52c3bc119"), "id" : 1, "name" : "test1Update" }
{ "_id" : ObjectId("5ad4a4a131752cb52c3bc11a"), "id" : 2, "name" : "test2" }
{ "_id" : ObjectId("5ad4a4a131752cb52c3bc11b"), "id" : 3, "name" : "test3" }

# データを消してみる
> db.test.remove({id:3})
WriteResult({ "nRemoved" : 1 })

> db.test.find()
{ "_id" : ObjectId("5ad4a46831752cb52c3bc119"), "id" : 1, "name" : "test1Update" }
{ "_id" : ObjectId("5ad4a4a131752cb52c3bc11a"), "id" : 2, "name" : "test2" }

Expressから使ってみる

npm install mongodb --saveでNodeから扱うためのモジュールをインストール。
今回インストールしたバージョンが3.0.6だったので、これを参考にjsを作っていく。

'usestrict'

const MongoClient = require('mongodb').MongoClient;
const test = require('assert');
var db;
var collection;
// 接続先URL
const url = 'mongodb://localhost:27017';
// 接続するDB名
const dbName = 'test';
// MongoDBに接続
const mongoClient = new MongoClient(url);
mongoClient.connect(function(err, client) {
  db = client.db(dbName);
});

var col = function() {
    // とりあえずDB名固定で返す
    return db.collection('test');
}

module.exports.collection = col;

これでDB接続の準備はOKのはず。
Expressから呼び出す為に以前作ったindex.jsを下記のように修正。

'use strict';
// import
const express = require('express');
// 作ったjsインポート
const db = require('./mongodb');
const app = express();

app.use(express.static('./app/'));

app.get('/', (req,res) => {
    console.log('Hello World!');
});

// '/sel'出来た時に一覧を返す
app.get('/sel', (req,res) => {
    db.collection().find().toArray((err,docs) => {
        res.send(docs);
        res.end();
    });
});

app.listen(3000, () => {
    console.log('listen on Port 3000');
});

'localhost:3000/sel'にアクセスすると結果が返ってきた。

[{"_id":"5ad4a46831752cb52c3bc119","id":1,"name":"test1Update"},{"_id":"5ad4a4a131752cb52c3bc11a","id":2,"name":"test2"}]

最後に

とりあえず今回はこれで良しとする。
今後、他の機能を実装できればなーと。

Angular用にExpressサーバを設定する

はじめに

最近Webアプリに関わることが多い水無瀬です。
Angularだけはやったことあるんですが、サーバ側を全くやったことが無いのでExpressでやってこうと思います。

インストール

公式?サイトを参考にコマンドを叩いていきます。
Nodeは入っている前提です。

# サーバ用のフォルダ作成
mkdir server
cd server

# package.json作成
# 色々聞かれるけど、初期設定で良いのでEnter連打
npm init

# Expressをインストール
# 一応 --saveを付けておく
npm install express --save

これで、インストールは問題ないはず。

とりあえず動かしてみる

引き続きサイトを参考にindex.jsを作っていきます。

// 今のところ意味あるかわからないが一応付けとく
'use strict';

// expressインポート
import express from "express";

const app = express();

// '/'来た時返す
app.get('/', (req,res) => {
    res.send('Hello World!');
});

// ポート3000で待受
app.listen(3000, () => {
    console.log('listen on Port 3000');
});

最低限はこれでOKのハズ。。。
node index.jsで起動。

import express from "express";
^^^^^^

SyntaxError: Unexpected token import

だめじゃん!
調べてみたらNodeはES6で書けないっぽい。
仕方ないのでimportはrequireに修正。
下記の様にしました。

'use strict';
const express = require('express');
const app = express();

app.get('/', (req,res) => {
    res.send('Hello World!');
});

app.listen(3000, () => {
    console.log('listen on Port 3000');
});

もう一度実行するとlisten on Port 3000とちゃんと出てきた。
'http://localhost:3000'にアクセスするとHello Worldって出てた。
これでとりあえずOKっぽい。

アプリ置いてみる

さて、一番やりたかったWebサーバとして設定しようと思います。
公式サイト見てもわからなかったので、色々参考にして下記の様になりました。

'use strict';
const express = require('express');
const app = express();

// 変更箇所
app.use(express.static('./app/'));

app.get('/', (req,res) => {
    // 文字返してもしかたないのでconsole.logにしとく
    console.log('Hello World!');
});

app.listen(3000, () => {
    console.log('listen on Port 3000');
});

ちなみに置いているアプリはこれ
アプリについては割愛。一応ここに少し書いてあります。
ng buildで出てきた内容をindex.jsと同じ階層の'app'ディレクトリにおいてあります。

アプリを置いたので、先程のアドレスにアクセス。
無事アプリを表示出来ました!!
出来ましたが、getを消しても動くのでよくわからないです。。。
その内調べたいですが、一旦動いてるので良しとします。

'use strict';
const express = require('express');
const app = express();

// 変更箇所
app.use(express.static('./app/'));

//app.get('/', (req,res) => {
    // 文字返してもしかたないのでconsole.logにしとく
    //console.log('Hello World!');
//});

app.listen(3000, () => {
    console.log('listen on Port 3000');
});