Raspberry Pi 3 & Python 開発ブログ☆彡

Raspberry Pi 3の使い方、設定をわかりやすく解説。Raspberry Pi3 Model B(Element14版)、Raspbian 8.0(NOOBS Ver1.9.2)を使用して開発中。

【スポンサーリンク】

SwampDragonの使い方 (その2)

【スポンサーリンク】

前回でswampdragonのプロジェクトの作成ができましたので、今回は実際にWebアプリを作って行きたいと思います。djangoと同じ部分が多いので理解しやすいと思います。

"Djangoの使い方 (その2)"のページと同じコードの場合、本ページでは説明を省略していますので、併せてご覧ください。

 

Modelの作成 (djtest→webpi→models.pyファイルの編集)

データのモデルを作成します。djangoモジュールのmodels.Modelに加え、swampdragonのSelfPublishModelを継承したPiDataクラスを作ります。また、swampdragonを使用するためには serializer_classという変数にSerializerクラスを代入します。PiDataSerializerクラスはこの後作成します。

models.pyを下記のように編集します。

from django.db import models
from swampdragon.models import SelfPublishModel
from .serializers import PiDataSerializer

class PiData(SelfPublishModel, models.Model):
    serializer_class = PiDataSerializer    
    pidata1 = models.CharField('pi1', max_length=255)
    pidata2 = models.CharField('pi2', max_length=255)
    pidata3 = models.CharField('pi3', max_length=255)
    pidata4 = models.CharField('pi4', max_length=255)
    pidata5 = models.CharField('pi5', max_length=255)

Serializerの作成(djtest→webpi→serializers.py(新規作成))

PiDataSerializerというクラスを作成し、modelという変数にアプリ名+モデルクラス名を代入します。pubuilsh_fields、update_fieldsという変数にモデルクラスの変数を代入します。

from swampdragon.serializers.model_serializer import ModelSerializer

class PiDataSerializer(ModelSerializer):
    class Meta:
        model = 'webpi.PiData'
        publish_fields = ['pidata1','pidata2','pidata3','pidata4','pidata5']
    update_fields = ['pidata1','pidata2','pidata3','pidata4','pidata5']

Routersの作成(djtest→webpi→routers.pyファイルの編集)

PiDataRouterというクラスを作成し、モデルクラスとシリアライズクラスをimportします。valid_verbsはこのRouterで使用する関数名を記載します。route_nameはhtmlでデータを受信したときに付与される名前(IDのような感じ)として使われます。

from swampdragon import route_handler
from swampdragon.route_handler import ModelPubRouter
from .models import PiData
from .serializers import PiDataSerializer

class PiDataRouter(ModelPubRouter):
    valid_verbs = ['subscribe','update']
    route_name = 'pidata_router'
    model = PiData
    serializer_class = PiDataSerializer

    def get_object(self, **kwargs):
        return self.model.objects.get(pk=kwargs['id'])

    def get_query_set(self, **kwargs):
        return self.model.objects.all()

route_handler.register(PiDataRouter)

Viewの作成(djtest→webpi→views.pyファイルの編集)

views.pyは下記の"Djangoの使い方 (その2)”で紹介しているコードと同じになります。解説も下記ページを参照してください。

Djangoの使い方 (その2)

from django.shortcuts import render
from webpi.models import PiData

def pidata_list(request):

    pidatas = PiData.objects.all().order_by('id')
    return render(request,
                  'webpi/pidata.html',    
                  {'pidatas': pidatas})  

HTMLファイルの作成

djangoの時と構成は同じですが、内容が若干異なります。

・djtest→webpi→templates(新規作成)→base.html(新規作成)
・djtest→webpi→templates(新規作成)→webpi(新規作成)→pidata.html(新規作成))

base.htmlファイルを新規作成し、下記のコードを記載します。base.htmlでswampdragon.min.jsとpidatas.jsを読み込んでいます。pidatas.jsは後で作成します。

 

※文字コードは必ずUTF-8を使用してください。

{% load swampdragon_tags %}
<!DOCTYPE html>
<html lang="{{ LANGUAGE_CODE|default:"en-us" }}">
<head>
<meta charset="UTF-8">
<title>{% block title %}My books{% endblock %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/static/css/bootstrap.min.css" rel="stylesheet">
<link href="/static/css/bootstrap-theme.min.css" rel="stylesheet">
<script src="/static/js/jquery-3.1.1.min.js"></script>
<script src="/static/js/bootstrap.min.js"></script>

{% block extrahead %}{% endblock %}
</head>
<body>
  <div class="container">
    {% block content %}
      {{ content }}
    {% endblock %}
  </div>

{% swampdragon_settings %}
<script type="text/javascript" src="/static/swampdragon.min.js"></script>
<script type="text/javascript" src="/static/pidatas.js"></script>
 
</body>
</html>

このbase.htmlを継承して、Webアプリのhtmlファイル(pidata.html)を作成することができます。書き換えたい箇所、不足箇所だけをpidata.htmlに記載していきます。{% block xxx %}~{% endblock %}でbase.htmlの内容を上書きすることができます。

pidata.htmlファイルを新規作成し、下記のコードを記載します。

{% extends "base.html" %}

{% block title %}センサーの一覧{% endblock title %}

{% block extrahead %}
<style>
table {
  margin-top: 8px;
}
</style>
{% endblock %}

{% block content %}
<h3 class="page-header">ラズベリーパイデータの一覧</h3>
<table id="table1" class="table table-striped table-bordered">
  <thead>
    <tr>
      <th>場所</th>
      <th>ラズパイ1</th>
      <th>ラズパイ2</th>
      <th>ラズパイ3</th>
      <th>ラズパイ4</th>
      <th>ラズパイ5</th>
    </tr>
  </thead>
  <tbody>
    <tr>        
      <td>場所 </td>
      <td>{{ pidatas.0.pidata1 }}</td>
      <td>{{ pidatas.0.pidata2 }}</td>
      <td>{{ pidatas.0.pidata3 }}</td>
      <td>{{ pidatas.0.pidata4 }}</td>
      <td>{{ pidatas.0.pidata5 }}</td>
    </tr>
  </tbody>
</table>

{% endblock content %}

pidata.jsの作成(djtest→staticm→pidata.jsファイルの編集))

 データベースを更新した時に、データが通知されます。そのデータを受け取り、Webのテーブルタグに値を代入する処理をjavascriptで作成します。

// Ask the browser for permission to show notifications
// Taken from https://developer.mozilla.org/en-US/docs/Web/API/Notification/Using_Web_Notifications
window.addEventListener('load', function () {
    Notification.requestPermission(function (status) {
        // This allows to use Notification.permission with Chrome/Safari
        if (Notification.permission !== status) {
            Notification.permission = status;
        }
    });
});

// Subscribe once swampdragon is connected router channel
swampdragon.open(function () {
    swampdragon.subscribe('pidata_router', 'ch_pidata' , null);    
});

// New channel message received
swampdragon.onChannelMessage(function (channels, message) {
    // Add the notification       
    if (message.action == "created") {
        addNotification(message.data, channels);
    }
    
    if (message.action == 'updated') {
        addNotification(message.data, channels);
    }
});

// Add new notifications
function addNotification(data,channels) {
    // If we have permission to show browser notifications
    // we can show the notifiaction
    if (window.Notification && Notification.permission === "granted") {      
        new Notification(data.toSource());

        var keys = Object.keys(data);        
        for (var i = 0, len = keys.length; i < len; i++) {
            if ( (keys[i] != 'id') && (keys[i] != '_type') ){
                pname = keys[i];
                pnum = pname.match(/-?[0-9]+\.?[0-9]*/g);
        t = document.getElementById('table1');
        var c = t.rows[1].cells[Number(pnum)];
        c.innerHTML = data[pname];  
            }
        }
    }       
}

実際にブラウザで指定するURLの設定(djtest→webpi→urls.pyファイル(新規作成)の編集)

urls.pyは下記の"Djangoの使い方 (その2)”で紹介しているコードと同じになります。解説も下記ページを参照してください。

Djangoの使い方 (その2)

from django.conf.urls import url
from webpi import views

urlpatterns = [
    url(r'^webpi/$', views.pidata_list, name='webpi'),

]

また、djtest→urls.pyに上記で作成したurls.pyを登録します。import includeが必要ですので注意してください。

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
                      
    url(r'^', include('webpi.urls', namespace='webpi')),
    url(r'^admin/', include(admin.site.urls)),
]

データベースの再構築

Modelでデータベースの内容を追加しているので、下記コマンドでデータベースを再構築します。

python3 manage.py makemigrations
python3 manage.py migrate

動作確認

ターミナルを2つ立ち上げます。各ターミナルで下記のコマンドを実行し、Webサーバーを起動します。

ターミナル1:python3 manage.py runserver xxx.xxx.xxx.xxx:8000
ターミナル2:python3 manage.py runsd


Webページを開いて、動作確認をしてみましょう。ブラウザのURLにhttp://[Raspberry PiのIPアドレス]:8000/webpiと入力します。テーブルビューが表示されたと思います。データベースに値を何も入れていないので、値は何も表示されていないはずです。

次回は、djangoシステムからデータベースに値を入れる方法を紹介します。