Yado_tech

旅館+ITとはなんぞ

IPアドレスが変わっても配信し続けるサーバー

いくつかのラズパイのmjpg-streamer経由で画像を配信→HTMLファイルを作ってまとめて閲覧できるようにしていたが、
再起動時にIPアドレスが変わってそのたびにHTMLファイルのIPアドレスを確認、変更するのがめちゃくちゃ億劫だった。

なのでIPアドレスを通知するスクリプトを作って再起動時にIPアドレスをSlackに通知するようにした。

しかし結局Slackの通知を確認してわざわざHTMLを変更するのがめちゃんこメンドイことに気づく。

WEBアプリ化してしまえばよくね?て思った。←今ココ

①HTMLファイル置いているNGINXのサーバーにFlask走らせてPOSTリクエストを受け付けるようにする。

②ラズパイ起動時にCURLIPアドレスをPOSTする。

③合わせてその都度IPアドレスを書き換えるようにする。

まずは準備

①【サーバー側】Flaskの用意

yadotech.hateblo.jp

flaskがちゃんと動いてるか確認する。一番大変なのはスクリプティングよりもポートの開放だったりしたのでここをしっかりできれば後がスゴイ早い

②【ラズパイ側】mjpg-streamerが使えるようにしておく

WEBカメラで動画ストリーミング

こちらでmjpg-streamerを準備する。

こちらでもポートの開放を忘れないようにする

そしてcrontab -e@rebootオプションで起動時にmjpg-streamerとIPアドレススクリプトを走らせるようにしておくこと。

以下ソース

kube.cssjqueryはほぼおまじないです。

【ラズパイ側のスクリプト

以前書いたスクリプトを若干変更する。requestsモジュールを利用するのでもしなければ
pip install requestsしておく。

import slackweb
import ipget
import time
import requests
import re

def post_to_slack():
    try:
        post()

    except:
        time.sleep(10)
        post_to_slack()

def post():
    slack = slackweb.Slack(url = "【slackのWebohookURL】")
    ip = ipget.ipget()
    ipaddress = ip.ipaddr("eth0")
    try:
        ipaddress = ipaddress[:re.search("/",ipaddress).start()]
    except:
        pass
    ips = {"machine":"frontcam","ip":ipaddress}
    slack.notify(text="hello,i am camera RPi and my IP is :%s" % ipaddress)
    try:
        requests.post('【WEBサーバーのIPアドレス】/post',params = ips)
    except:
        print("POST できんかった・・")

if __name__ == '__main__':
    post_to_slack()

【サーバー側のスクリプトなど】

ディレクトリ構造

root/
 ├ app.py
 ├ control/
    ├  __init__.py
    ├  views.py
    ├  config.py
    ├  models.py
    ├  static/
      │    ├ address.db
      │    ├ jquery.js
      │    ├ kube.css
      │    └ kube.js
     └ templates/
          └ layout.html

app.py

from control import app

if __name__ == '__main__':
    app.run(debug=True)

__init__.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config.from_object('control.config')

db = SQLAlchemy(app)
import control.views

config.py

SQLALCHEMY_DATABASE_URI = 'sqlite:///./static/address.db'
SECRET_KEY = '【お好みのKey】'
SQLALCHEMY_TRACK_MODIFICATIONS = True

models.py

from control import db

class Entry(db.Model):
    __tablename__ = 'address'
    __table_args__ = {'extend_existing': True}
    id = db.Column(db.Integer,primary_key = True)
    machine = db.Column(db.Text)
    ipaddress = db.Column(db.Text)
    comment = db.Column(db.Text)

    def __repr__(self):
        return 'entry id = {id} machine = {machine} ipaddress = {ipaddress} comment = {comment}'\
        .format(id = self.id , machine = self.machine , ipaddress=self.ipaddress,comment = self.comment)


def init():
    db.create_all()

views.py

from flask import Flask, render_template, request, url_for,redirect
from control import app,db
from control.models import Entry

@app.route('/')
def index():
    try:
        entry = Entry.query.filter_by(machine = "frontcam").first()
        machine = entry.machine
        address = entry.ipaddress
        return render_template("layout.html",machine = machine,ip = address)

    except:
        return "エラー1"

@app.route('/post',methods =['POST'])
def resisteripaddress():
#    print(request.values.getlist("machine")[0])
    if request.values.getlist("machine")[0] == "frontcam":
        entry = Entry.query.filter_by(machine = "frontcam").first()
        entry.ipaddress = request.values.getlist("ip")[0]
        db.session.add(entry)
        db.session.commit()
        return url_for('index')

    else:
        print("machineじゃなかった")
        return "エラー2"

layout.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!--Import materialize.css-->
  <link type="text/css" rel="stylesheet" href="../static/kube.css"  media="screen,projection"/>
  <title>カメラ</title>
</head>
<br>
<div class = "container">
  <div class = "row gutters">
    <div class = "col col-4">
      <figure>
        <img src="http://{{ip}}:8494/?action=stream" />
        <figcaption>
          フロント
        </figcaption>
      </figure>
    </div>
    <div class = "col col-4">
     <figure>
      <img src="http://{{ip}}:8495/?action=stream" />
      <figcaption></figcaption>
    </figure>
    </div>
  </div>
</div>
</body>
<!--Import jQuery before materialize.js-->
<script type="text/javascript" src="../jquery-3.2.1.js"></script>
<script type="text/javascript" src="../static/kube.js"></script>
<style>
@import url(http://fonts.googleapis.com/earlyaccess/notosansjp.css);

body {
     font-family: 'Noto Sans JP', sans-serif;
     font-size: 100%;
}


div.container{margin:30px}
</style>

</html>