0
0

Raspiメモ

Posted at

背景

RaspberryPiを運用し始めました。
以下のことを実現したい。
・イベントのメール配信
・配信の元ネタはSQLiteDBに登録されているイベント情報
・イベント情報が手動でWebのフォームから登録する

メール配信は、いろいろ調べたが、以下の所でいろいろ引っかかって

  1. crontabの制限
  2. サービス環境整備
  3. タイマー関連

最終構成

  1. python scheduleを使用
  2. サービス使用

サービスの中身:

[Unit]
Description=JOB
After=network.target

[Service]
User=pi
WorkingDirectory=/home/pi/MatplotlibForFlask
Environment="PYTHONPATH=/home/pi/.local/lib/python3.9/site-packages"
ExecStart=/usr/bin/python3 /home/pi/MatplotlibForFlask/without_flask_app.py

[Install]
WantedBy=multi-user.target

更新したら以下のコマンドを実行し反映させる

$ sudo systemctl daemon-reload
$ sudo systemctl restart job.service

配信用メインPG:

#!/usr/bin/env python3
from flask_sqlalchemy import SQLAlchemy
from db_controller import Event_info, db
from flask import Flask
import os
from send_mail import pymail
from datetime import date
import schedule
import time

# 仮想のFlaskアプリケーションコンテキストを作成します。
class DummyApp(Flask):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.config.update({
            'SQLALCHEMY_DATABASE_URI': "sqlite:///" + os.path.join(
            os.getcwd(), "settings", "health_db.db"),
            'SQLALCHEMY_TRACK_MODIFICATIONS': False
        })

# Flask-SQLAlchemyを初期化します。
def initialize_sqlalchemy(app):
    db.init_app(app)

def clean_data(data):
    result = ''
    for d in data:
        # print(d.event_date)
        tmp = '' + d.event_date.strftime("%Y-%m-%d") + '\n' + d.event_name + '\n' + d.discription +'\n\n'
        result = result+tmp
    return result 


# データベースに接続します。
def connect_to_database():
    app = DummyApp(__name__)
    initialize_sqlalchemy(app)
    with app.app_context():
        db.create_all()
        # ここでデータベースを使用した操作を行います。
        res = Event_info.get_today_event()
        r = clean_data(res)
        ins = pymail()
        dt = date.today().strftime("%Y-%m-%d")
        ins.send_mail(f'{dt}】のイベント情報:', r)


schedule.every().day.at("06:55").do(connect_to_database)

# データベースに接続します。
# connect_to_database()

while True:
    schedule.run_pending()
    time.sleep(1)

メール送信用:

import smtplib
from email.mime.text import MIMEText
from settings import Sql_Param

class pymail:
    def __init__(self) -> None:
        self.app_password = Sql_Param.mail_passwd
        self.sender_email = Sql_Param.mail_from
        self.receiver_email = Sql_Param.mail_to

    def send_mail(self, subject, discription):
        #本文
        body = discription
        msg = MIMEText(body)
        #メールの件名
        msg["Subject"]=subject
        #あなたのGmailアドレス
        msg["From"]=self.sender_email
        #メールの送信先
        msg["To"]=self.receiver_email

        # SMTPサーバーに接続してメールを送信
        try:
            smtp_server = smtplib.SMTP_SSL("smtp.gmail.com", 465)
            smtp_server.login(self.sender_email, self.app_password)
            smtp_server.sendmail(self.sender_email, self.receiver_email, msg.as_string())
            smtp_server.quit()
            print("Email sent successfully!")
        except smtplib.SMTPAuthenticationError as e:
            print("SMTP Authentication Error:", e)
        except Exception as e:
            print("An error occurred:", e)

if __name__ == '__main__':
    ins = pymail()
    ins.send_mail('test','test body \n hello world...')

DB接続クラスは一部のみ

from flask_sqlalchemy import SQLAlchemy
from datetime import datetime, date, timedelta
from pytz import timezone
from sqlalchemy import case, func, cast, Integer
from werkzeug.security import generate_password_hash
from settings import Sql_Param

db = SQLAlchemy()


# ユーザテーブル定義
class User_info(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    regist_time = db.Column(
        db.DateTime,
        default=datetime.now(timezone("Asia/Tokyo")),
    )
    name = db.Column(db.String(100), nullable=False)
    mail_address = db.Column(db.String(255), unique=True, nullable=False)
    hash_key = db.Column(db.String(255), unique=True, nullable=False)
    is_admin = db.Column(db.Boolean, default=True)

    @classmethod
    def insert_data(cls, request):
        entry = cls(
            name=request.form.get('username'),
            mail_address=request.form.get('mail_address'),
            hash_key=generate_password_hash(request.form.get('password'), salt_length=8)
        )
        db.session.add(entry)
        db.session.commit()
        print("finish insert")

結論

これで任意のサイクルで任意のタイミングで任意の宛先にRaspberryPiから自動送信が可能となる

今後Line配信も考えている。返信したら、DBデータ更新できるようになったら、便利になる。
応用としては、
システムからメッセージ「薬飲んだ?」
「はい」と返信すると
DBが薬を飲んだことを記録できるようになったらうれしい。

0
0
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
0
0