LoginSignup
12
8

More than 3 years have passed since last update.

LINEBotからRaspberryPiで写真を撮ってLINEにおくる!

Last updated at Posted at 2020-05-07

はじめに

LINEBotでRaspberryPiで写真を撮って送るという、カメラ装置です。
ハッカソンで作成したねこしぇるじゅ-自慢の猫をとにかく拡散!- | ProtoPediaの一部をupdateしたものです。
2020/05/12追記
完成版追記しました

概要

LINEBotからRaspberryPiを動かして写真を撮り、Gyazoに送って写真をLINEに送るものです。
LINEBotでRaspberryPiを動かしています。
RaspberryPi node.js ngrok Gyazo API という感じです。

できたもの

使い方

RaspberryPiを猫がよくいる場所に置きます。
猫が見たいので LINEBotに「ねこ」と入れます。
(「ねこ」以外のワードには「何が見たいの?」と返してきます。)
写真を撮るのに時間がかかるので、「写真撮ってくるから待っててねー」、とつなぎのワードが入ります。
10秒ほどすると写真が送られてきます。

環境

MacBook Pro macOS Mojave
 Visual Studio Code 1.44.0

RaspberryPi 3B
 Release: 10
 Codename: buster
 Node.js v12.16.3
 npm v6.14.4
Pi camera
洗濯バサミ

Raspberry Piの準備

こちらを参考にnode.jsとnpmの最新版を入れましょう。
Raspberry PiにNode.jsとnpmの最新版をインストールする - Qiita
そのほかで必要なnpmはこちら

//Gyazo API
$ npm i gyazo-api 
// LINEbot SDK
$ npm i @line/bot-sdk express
//ngrok
$ wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-arm.zip 
//ngrokのzipを解凍する
$ unzip ngrok-stable-linux-arm.zip 

コード(promise失敗)

node.js
'use strict';
const express = require('express');
const line = require('@line/bot-sdk');
const PORT = process.env.PORT || 3000;
const Gyazo = require('gyazo-api');
const gyazoclient = new Gyazo('Your access token');
const config = {
  channelSecret: '***',
  channelAccessToken: '***'
};

const app = express();
app.get('/', (req, res) => res.send('Hello LINE BOT!(GET)')); //ブラウザ確認用
app.post('/webhook', line.middleware(config), (req, res) => {
  console.log(req.body.events);
  Promise
    .all(req.body.events.map(handleEvent))
    .then((result) => res.json(result));
});
const client = new line.Client(config);
async function handleEvent(event) {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }
  let mes = event.message.text;
  if (event.message.text.match("ねこ")) {
    await client.replyMessage(event.replyToken, {
      type: "text",
      text: '写真を撮ってくるからちょっと待っててね'
    });
    await nyanpi();
    return nyancoPic(event.source.userId);
  }
  else {
    return client.replyMessage(event.replyToken, {
      type: "text", text: '何が見たいのかな?'
    });
  }
}
//picameraで写真を撮って送る
const nyanpi = async (userId) => {
  const PiCamera = require('pi-camera');
  const myCamera = new PiCamera({
    mode: 'photo',
    output: `${__dirname}/nyan.jpg`,
    width: 640,
    height: 480,
    nopreview: true,
  });
  await myCamera.snap()
    .then((result) => {
      console.log("ok");
      gyazoclient.upload('./nyan.jpg', {
        title: "my picture",
        desc: "upload from nodejs"
      })
        .then((res) => {
          console.log("送った");
        })
        .catch((err) => {
          console.error(err);
          console.log("送レナカッタ");
        });
    })
    .catch((error) => {
      // Handle your error
    });
}
//Gyazoの最新の写真のURLをとってくる
const nyancoPic = async (userId) => {
  let gyazoimgUrl = '';
  await gyazoclient.list()
    .then(function (response) {
      console.log(response.data[0]);
      gyazoimgUrl = `${response.data[0].url}`;
      console.log(gyazoimgUrl);
    })
    .catch(function (err) {
      console.error(err);
    });

  await client.pushMessage(userId, {
    type: 'image',
    originalContentUrl: gyazoimgUrl,
    previewImageUrl: gyazoimgUrl
  });

}
app.listen(PORT);
console.log(`Server running at ${PORT}`);

動いていないところ

最新じゃなくて1個前の写真しか持ってこれない。
await/asyncがうまく使えていない感じ。。。
OKと送ったというconsole.logの間でGyazoに取りに行っちゃう
(ログ↓)

ok
{
  image_id: '***',
  permalink_url: 'https://api.gyazo.com/***',
  url: 'https://i.gyazo.com/f***',
  metadata: {
    app: null,
    title: 'my picture',
    url: null,
    desc: 'upload from nodejs'
  },
  type: 'jpg',
  thumb_url: 'https://thumb.gyazo.***ApieIALnjo-jpg.jpg',
  created_at: '2020-05-07T01:06:27+0000'
}
https://i.gyazo.com/***.jpg
送った

完成した!!!

2020/05/12追記

node.js

'use strict';
const express = require('express');
const line = require('@line/bot-sdk');
const PORT = process.env.PORT || 3000;
const Gyazo = require('gyazo-api');
const gyazoclient = new Gyazo('Your access token');
const config = {
  channelSecret: '***',
  channelAccessToken: '***'
};

const app = express();
app.get('/', (req, res) => res.send('Hello LINE BOT!(GET)')); //ブラウザ確認用
app.post('/webhook', line.middleware(config), (req, res) => {
  console.log(req.body.events);
  Promise
    .all(req.body.events.map(handleEvent))
    .then((result) => res.json(result));
});
const client = new line.Client(config);

async function handleEvent(event) {
  if (event.type !== 'message' || event.message.type !== 'text') {
    return Promise.resolve(null);
  }
  let mes = event.message.text;
  if (event.message.text.match("ねこ")) {

    await client.replyMessage(event.replyToken, {
      type: "text",
      text: '写真を撮ってくるからちょっと待っててね'
    });
    await nyanpi();
    return nyancoPic(event.source.userId);
  }
  else {
    return client.replyMessage(event.replyToken, {
      type: "text", text: '何が見たいのかな?'
    });
  }
}
const nyanpi = async (userId) => {
  const PiCamera = require('pi-camera');
  const myCamera = new PiCamera({
    mode: 'photo',
    output: `${__dirname}/nyan.jpg`,
    width: 640,
    height: 480,
    nopreview: true,
  });
  await myCamera.snap()
  await gyazoclient.upload('./nyan.jpg', {
    title: "my picture",
    desc: "upload from nodejs"
  })
}
const nyancoPic = async (userId) => {
  const response = await gyazoclient.list()
  const gyazoimgUrl = response.data[0].url;

  return client.pushMessage(userId, {
    type: 'image',
    originalContentUrl: gyazoimgUrl,
    previewImageUrl: gyazoimgUrl
  });
}
app.listen(PORT);
console.log(`Server running at ${PORT}`);

RaspberyPiがわ 2つターミナルを開きます

node neko2.js
ngrog http 3000

起動ごとにwebhookおアドレスは変わるので都度 Messaging API settingsでngrokのアドレスを変える

参考サイト

20200504 raspberrypi handson_honpen
Node.jsでラズパイのカメラモジュールを使う – plog
gyazo-api - npm
raspbian(Raspberry Pi)のバージョン確認方法

感想

Piカメラ音がしないのでお猫様をこっそり撮影できて良い〜
スマホのシャッター音に慣れすぎか。

promise難しい。。。

12
8
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
12
8