[PYTHON] I made a Linebot that notifies me of nearby evacuation sites on AWS

Introduction

This article is "Programming to keep you from dying", And I aimed to build almost the same system using AWS as a backend. Please refer to the original article for the detailed contents of the system.

I also want to create a system that will help with disaster countermeasures and evacuation guidance, and will publish articles on "disaster evacuation advisory system using drones" and "evacuation advisory system using smart speakers". I hope you can see it as well.

Target audience

--Those who want to make and learn from the purpose of making a system that actually works --Those who want to develop LINE bot --For AWS † Beginners † who want to use AWS as a backend

Production

友だち追加

In the end, I was thinking of building a drone system, so don't worry about the icon being a drone. When you send location information, the surrounding evacuation sites will be returned. (As of November 13, 2019, only evacuation sites in eastern Japan are supported m_ _m)

Evacuation site data

Data on evacuation sites nationwide is taken from here. Please download in json format. (https://www.geospatial.jp/ckan/dataset/hinanbasho/resource/5fe3d23c-03fb-49ee-8a65-4f7495a8ea40) After that, convert it to a CSV file by referring to the original article. Doing this will make it easier to process later with Pandas in Python.

About backend configuration

A simple configuration diagram of this LINE bot is shown below. スクリーンショット 2019-11-13 0.18.48.png

For those who are new to AWS, here are some important services that are often used on AWS. Amazon API Gateway A way to link AWS with external services. Here you will receive request data webhooked by LINE talk room actions Amazon S3 Storage that stores data. Something like Google drive. Memory in human terms. The CSV data of the evacuation site created earlier will be entered here. AWS lambda A place that processes request data. server. In human terms, it's the brain. The execution timing of lambda can be set, and it can be triggered when a request is sent to API Gateway or when data is added to S3. Here, the location information that came from LINE is returned so that nearby evacuation sites can be displayed on LINE.

All you need to know is these three.

Implementation

First, you need to set up LINE bot, build lambda, and build Gateway. It is a prerequisite that the LINE developer account and AWS account are prepared in advance. The following article is very helpful, and I also use AWS and python for the back end, so I think it's a good idea to make something that works first. https://xp-cloud.jp/blog/2019/06/24/5560/

With reference to this article, I implemented the lambda code as follows.

import json
import boto3
import urllib
import pyproj
import pandas as pd
import re
import os

#Distance calculation between two points
def calc_distance(ido1, kdo1, ido2, kdo2):
    g = pyproj.Geod(ellps='WGS84')
    result = g.inv(kdo1, ido1, kdo2, ido2)
    distance = result[2]
    return round(distance)
 
def lambda_handler(event, context):
    url = "https://api.line.me/v2/bot/message/reply"
    method = "POST"
    headers = {
        'Authorization': 'Bearer ' + os.environ['CHANNEL_ACCESS_TOKEN'],
        'Content-Type': 'application/json'
    }
    if event['events'][0]['message']['type'] == 'location':
        s3 = boto3.client('s3')
        bucket_name = 'japan-shelter-all'
        file_name = 'east.csv' 
        response = s3.get_object(Bucket=bucket_name, Key=file_name)
        df = pd.read_csv(response['Body'])
        
        #Target evacuation sites near your current location
        ido_from = event['events'][0]['message']['latitude'] - 0.05
        ido_to = event['events'][0]['message']['latitude'] + 0.05
        kdo_from = event['events'][0]['message']['longitude'] - 0.05
        kdo_to = event['events'][0]['message']['longitude'] + 0.05
        df_near = df.query(
            f'ido > {ido_from} and ido < {ido_to} and kdo > {kdo_from} and kdo < {kdo_to}'
        )
        
        #Identify the nearest evacuation site from your current location
        min_distance = None
        min_row = None
        for index, row in df_near.iterrows():
            hinan_ido = row['ido']
            hinan_kdo = row['kdo']
            distance = calc_distance(
                event['events'][0]['message']['latitude'], event['events'][0]['message']['longitude'], hinan_ido, hinan_kdo
            )
            if min_distance is None or distance < min_distance:
                min_distance = distance
                min_row = row
        
        if min_distance != None:
            message = [
                {
                    "type": "text",
                    "text": f"{min_row['name']}Let's evacuate to"
                },
                {
                    "type": "location",
                    "title": f"To the evacuation site{min_distance}m",
                    "address": f"{min_row['addr']}",
                    "latitude": f"{min_row['ido']}",
                    "longitude": f"{min_row['kdo']}"
                }
            ]
        else:
            message = [
                {
                    "type": "text",
                    "text": "No shelter found nearby"
                }
            ]
    
    
        params = {
            "replyToken": event['events'][0]['replyToken'],
            "messages": message
        }
        request = urllib.request.Request(url, json.dumps(params).encode("utf-8"), method=method, headers=headers)
        with urllib.request.urlopen(request) as res:
            body = res.read()
    return 0

Even if you try to execute lambda as it is, an error will occur if the external library of pandas or pyproj cannot be loaded. As a solution to this, make it possible to import these additional libraries into lambda in layer format. Install those libraries on EC2 (AWS virtual machine), upload them to S3, and then add them to layer. (If you want to see other methods together, refer to [AWS / Lambda] Python external library loading method) For the procedure, refer to the following youtube video. This is a video from overseas, but it is very easy to understand. Don't forget to install pyproj as well as pandas. https://www.youtube.com/watch?v=zrrH9nbSPhQ

スクリーンショット 2019-11-13 13.29.30.png

After that, if you can import various libraries safely, it is successful.

Summary

I have summarized a simple how-to of LINEbot on AWS with reference to other articles. I don't usually touch AWS myself, so please let me know if you should manage the CSV file in DB. The app itself confirmed the communication and was satisfied, so I will not improve it. As a sequel, we are planning to release "Disaster evacuation advisory system using drone" and "Evacuation advisory system using smart speaker", so please have a look. If you find this article helpful or expect a sequel, please give it a high rating ^ ^

Recommended Posts

I made a Linebot that notifies me of nearby evacuation sites on AWS
I made a slack bot that notifies me of the temperature
I made a SlackBot that notifies me of AtCoder contest information every week
With LINEBot, I made an app that informs me of the "bus time"
I made a github action that notifies Slack of the visual regression test
I made a neural network generator that runs on FPGA
I made a Line-bot using Python!
I made a new AWS S3 bucket
I made a calendar that automatically updates the distribution schedule of Vtuber
[Python] I made a bot that tells me the current temperature when I enter a place name on LINE
I made a Chrome extension that displays a graph on an AMeDAS page
I wrote a Slack bot that notifies delay information with AWS Lambda
I created a Slack bot that confirms and notifies AWS Lambda of the expiration date of an SSL certificate
[Discode Bot] I created a bot that tells me the race value of Pokemon
[Python / C] I made a device that wirelessly scrolls the screen of a PC remotely.
I made a calendar that automatically updates the distribution schedule of Vtuber (Google Calendar edition)
[AWS] I made a reminder BOT with LINE WORKS
I made a twitter app that identifies and saves the image of a specific character on the twitter timeline by pytorch transfer learning
I made a threshold change box of Pepper's Dialog
I made a VM that runs OpenCV for Python
I made a Python3 environment on Ubuntu with direnv.
I made a program to collect images in tweets that I liked on twitter with Python
〇✕ I made a game
A story that stumbled when I made a chatbot with Transformer
I made a LINE BOT that returns parrots with Go
[Python] Create a linebot that draws any date on a photo
I made a class that easily performs unixtime ← → datetime conversion
I made a function to check the model of DCGAN
I made a fucking app that won't let you skip
I made a dot picture of the image of Irasutoya. (part1)
[Introduction to AWS] A memorandum of building a web server on AWS
I made a VGG16 model using TensorFlow (on the way)
I made an anomaly detection model that works on iOS
I made a rigid Pomodoro timer that works with CUI
I made a dot picture of the image of Irasutoya. (part2)
I made a plug-in that can "Daruma-san fell" with Minecraft
[Python3] List of sites that I referred to when I started Python
[AWS] I made a reminder BOT with LINE WORKS (implementation)
I made a Line bot that guesses the gender and age of a person from an image
A story that I had a hard time displaying graphs on top of each other with matplotlib
I made a LINE bot that tells me the type and strength of Pokemon in the Galar region with Heroku + Flask + PostgreSQL (Heroku Postgres)