temporaryなめも帳

だらだらと備忘録とか。誰かの為になることをねがって。

BBBでACR122Uを動かしたい

BBBでACR122U(NFCカードリーダ)つないで、pcsc_scanするまでのメモ

pcscdをインストールする

$ sudo apt-get install pcscd

動作確認(NG)

$ sudo pcscd -d -a -f
00000000 pcscdaemon.c:240:main() pcscd set to foreground with debug send to stdout
00002456 configfile.l:254:DBGetReaderListDir() Parsing conf directory: /etc/reader.conf.d
00001351 configfile.l:307:DBGetReaderList() Parsing conf file: /etc/reader.conf.d/libccidtwin
00001649 configfile.l:266:DBGetReaderListDir() Skipping non regular file: .
00000855 configfile.l:266:DBGetReaderListDir() Skipping non regular file: ..
00002992 pcscdaemon.c:545:main() pcsc-lite 1.8.10 daemon ready.
00022437 hotplug_libudev.c:269:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/001/001
00003044 hotplug_libudev.c:269:get_driver() Looking for a driver for VID: 0x1D6B, PID: 0x0002, path: /dev/bus/usb/001/001
00002742 hotplug_libudev.c:269:get_driver() Looking for a driver for VID: 0x1A40, PID: 0x0101, path: /dev/bus/usb/001/002
00003023 hotplug_libudev.c:269:get_driver() Looking for a driver for VID: 0x0411, PID: 0x01A2, path: /dev/bus/usb/001/003
00002633 hotplug_libudev.c:269:get_driver() Looking for a driver for VID: 0x1A40, PID: 0x0101, path: /dev/bus/usb/001/002
00002614 hotplug_libudev.c:269:get_driver() Looking for a driver for VID: 0x072F, PID: 0x2200, path: /dev/bus/usb/001/004
00001405 hotplug_libudev.c:269:get_driver() Looking for a driver for VID: 0x072F, PID: 0x2200, path: /dev/bus/usb/001/004
00001227 hotplug_libudev.c:321:HPAddDevice() Adding USB device: ACS ACR122U PICC Interface
00001368 readerfactory.c:989:RFInitializeReader() Attempting startup of ACS ACR122U PICC Interface 00 00 using /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux/libccid.so
00003569 readerfactory.c:874:RFBindFunctions() Loading IFD Handler 3.0
00001718 ifdhandler.c:1910:init_driver() Driver version: 1.4.15
00010156 ifdhandler.c:1927:init_driver() LogLevel: 0x0003
00001240 ifdhandler.c:1938:init_driver() DriverOptions: 0x0004
00003629 ifdhandler.c:83:CreateChannelByNameOrChannel() Lun: 0, device: usb:072f/2200:libudev:0:/dev/bus/usb/001/004
00001643 ccid_usb.c:281:OpenUSBByName() Using: /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
00009564 ccid_usb.c:299:OpenUSBByName() ifdManufacturerString: Ludovic Rousseau (ludovic.rousseau@free.fr)
00000993 ccid_usb.c:300:OpenUSBByName() ifdProductString: Generic CCID driver
00001749 ccid_usb.c:301:OpenUSBByName() Copyright: This driver is protected by terms of the GNU Lesser General Public License version 2.1, or (at your option) any later version.
00021725 ccid_usb.c:582:OpenUSBByName() Can't claim interface 1/4: -6
00001490 ccid_usb.c:191:close_libusb_if_needed() libusb_exit
00002553 ifdhandler.c:117:CreateChannelByNameOrChannel() failed
00001181 readerfactory.c:1020:RFInitializeReader() Open Port 0x200000 Failed (usb:072f/2200:libudev:0:/dev/bus/usb/001/004)
00000928 readerfactory.c:312:RFAddReader() ACS ACR122U PICC Interface init failed.
00000907 readerfactory.c:535:RFRemoveReader() UnrefReader() count was: 1
00000795 readerfactory.c:1040:RFUnInitializeReader() Attempting shutdown of ACS ACR122U PICC Interface 00 00.
00000771 readerfactory.c:911:RFUnloadReader() Unloading reader driver.
00001460 hotplug_libudev.c:391:HPAddDevice() Failed adding USB device: ACS ACR122U PICC Interface
00003804 hotplug_libudev.c:269:get_driver() Looking for a driver for VID: 0x1A40, PID: 0x0101, path: /dev/bus/usb/001/002
exit
^C13467170 pcscdaemon.c:726:signal_trap() Received signal: 2
00000160 pcscdaemon.c:745:signal_trap() Preparing for suicide
^C00632125 pcscdaemon.c:726:signal_trap() Received signal: 2
00000189 readerfactory.c:1273:RFCleanupReaders() entering cleaning function
00000103 winscard_svc.c:130:ContextsDeinitialize() remaining threads: 0
00000074 pcscdaemon.c:670:at_exit() cleaning /var/run/pcscd

どうやら、別の何かがデバイスをつかんでいるぽい? https://www.raspberrypi.org/forums/viewtopic.php?f=63&t=57037 ここの「Thu Mar 13, 2014 8:58 am」の書き込みによると、

Also it was not very clear that you need to prevent modprobe from autoload pn533 and nfc modules.
To do that, create /etc/modprobe.d/blacklist-libnfc.conf with this content:
blacklist pn533
blacklist nfc

ということらしい。 lsmodたたいてみると、確かにこのモジュールがロードされてる。 上記の通りブラックリストに指定して再起動かければpcsc_scanでカードが読み込める。

BBBでwifi接続する

BBBにWifiのドングル指して使いたい。 BBBで利用しているイメージはこれ

まず、状態確認

$ sudo lshw -C network
  *-network:0 DISABLED    
       description: Wireless interface
       physical id: 1
       bus info: usb@1:1.1
       logical name: wlan0
       serial: cc:e1:d5:17:9e:f7
       capabilities: ethernet physical wireless
       configuration: broadcast=yes driver=rt2800usb driverversion=3.14.37-ti-r57 firmware=N/A link=no multicast=yes wireless=IEEE 802.11bgn

DISABLED状態になっているので、起こしてあげる

$ sudo ifconfig wlan0 up
$ ifconfig
wlan0     Link encap:Ethernet  HWaddr cc:e1:d5:17:9e:f7  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

apを検索する

$ sudo iwlist wlan0 scan

ap一覧から接続したいapのESSIDをメモっておく pskパスワードを生成する

$ wpa_passphrase SSID WPA_PASS
network={
    ssid="SSID"
    #psk="WPA_PASS"
    psk=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
}

/etc/network/interfacesにネットワーク設定を追記する

$ sudo vi /etc/network/interfaces
auto wlan0
iface wlan0 inet dhcp
    wpa-ssid "SSID"
    wpa-psk  "XXXXXXXXXXXXXXXXXX(さっきのやつ)"

無線LANの有効化

$ sudo ifup wlan0

pingで疎通確認

$ ping google.com
$ ping 8.8.8.8

DNSの設定が上手くいっていない場合は次の設定を行う 192.168.65.1は自宅の環境。8.8.8.8とかにするといいんじゃないかな。

$ sudo vi /etc/resolvconf/resolv.conf.d/tail
# nameserver 192.168.1.1
nameserver 192.168.65.1
$ sudo resolvconf -u
$ cat /etc/resolv.conf 
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver 127.0.0.1
domain localdomain
search localdomain
nameserver 192.168.65.1
$ sudo service networking restart
$ ping google.com

これでつながった。 いろいろ調べていると、/etc/resolvconf/resolv.conf.d/baseにDNSの設定を書き込むのが主流っぽいんだけど、tailにいろいろ予め書かれているからかresolvconf -uしても設定が変更されなかった。 そのため、直接tailをいじってるかんじです。

参考にさせていただいたサイトとか

http://unix.stackexchange.com/questions/128220/how-do-i-set-my-dns-on-ubuntu-14-04 http://qiita.com/Hiroshi-Ito/items/6c870a3bab55bd06cf57 http://bty.sakura.ne.jp/wp/archives/754

virtual boxでSDカード認識したいとき

これが参考になる。

MacBook ProのSDカードスロットをVirtualBoxのrawdiskとして使う in Qiita

VirtualBox側にraw.vmdkを読み込ませるときにエラーになるときは、もう一度参照先のディスクのマウント状態を確認すること。 手元では、作業途中に何度か自動でマウントされていてエラーもらうことがあった。

Macでgoのクロスコンパイルする

RaspPiにFreeBSD乗せて遊んでて、そこ向けにgoのバイナリ作りたい。

goをinstallする。

brew--with-cc-allをつけてインストールした。 この辺を参考に。 GoのソースをMacでクロスコンパイルし、CentOS5でCloudWatchのカスタムメトリクスを取得する

環境がいまいちなのか、記事の通りに行かなかったので以下を追加

こんなエラーが出てた

go build runtime: freebsd/arm must be bootstrapped using make.bash

どうもクロスコンパイル用の環境が整っていないらしい。

以下で環境が整う。 GOOSとGOARCHを変えれば、他環境向けにも対応できる。

$ cd /usr/local/go/src
$ sudo GOOS=freebsd GOARCH=arm CGO_ENABLED=0 ./make.bash --no-clean

この後、helloworldをクロスコンパイルするといけた。

$ GOOS=freebsd GOARCH=arm go build hello.go

PUSHっぽい何かを実現する

あくまでもローカルな環境向け。基本的にはGCMをつかうべきです。 WebSocket覚えたし、使ってみたかってん。ぐらいのなにか。

Android側にPushを受けるサービスを実装する

アプリケーション内にServiceを実装し、ws://IPADDRESS:PORT/path/to/url に対しWebSocketを張る部分を作る。 WebSocketの実装には、 Java-WebSocket というライブラリを利用しました。

まず、build.gradleにライブラリをインポートする部分を書きます。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'org.java-websocket:Java-WebSocket:1.3.0@jar'
}

続いて、Activityの実装。 Activityには2個ボタンを用意して、ServiceのStop,Startの制御とServerへのメッセージを投げる部分をハンドリングしています。

    @Override
    public void onClick(View view) {
        Intent intent = new Intent();
        intent.setClass(getApplicationContext(), PushService.class);
        switch (view.getId()){
            case R.id.button1: {
                if (!isServiceRunning("com.kobashin.sample.PushService")) {
                    isRunning = true;
                    PushService.startForegroundService(getApplicationContext(), SERVER_URI);
                } else {
                    isRunning = false;
                    PushService.stopForegroundService(getApplicationContext());
                }
                break;
            }
            case R.id.button2: {
                PushService.sendMessageToServer(getApplicationContext(), "Hello Server");
            }
        }
    }

    private boolean isServiceRunning(String className){
        boolean ret = false;

        ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
        List<ActivityManager.RunningServiceInfo> services = am.getRunningServices(Integer.MAX_VALUE);

        for(ActivityManager.RunningServiceInfo info : services){
            if(info.service.getClassName().equals(className)){
                ret = true;
            }
        }
        return ret;
    }

isServiceRunning()メソッドはServiceの実行状態の確認用のメソッドです。 Serviceへの通知にはService側にpublic staticで実装したメソッド(PushService.startForegroundServiceなど)を利用しています。

さらに、Service側の実装。ぺたっと全部。

public class PushService extends Service {

    private static String LOG_TAG = "PushService";

    private NotificationManager mNotificationManager;

    private final IBinder mBinder = new LocalBinder();

    private static final String ACTION_START_FOREGROUND
            = "com.kobashin.sample.START_FOREGROUND";

    private static final String ACTION_STOP_FOREGROUND
            = "com.kobashin.sample.STOP_FOREGROUND";

    private static final String ACTION_SEND_MESSAGE_TO_SERVER
            = "com.kobashin.sample.SEND_MESSAGE_TO_SERVER";

    private WebSocketClient mWebSocketClient;

    private HandlerThread mHandlerThread;

    private MsgHandler mMsgHandler;


    private enum NOTIFY_ID {
        NOTIFICATION_STARTED(100),
        NOTIFICATION_END(101),
        NOTIFICATION_RECEIVE_MESSAGE(102);

        NOTIFY_ID(int i) {
            id = i;
        }

        private int id;

        public int getId() {
            return id;
        }
    }


    private class MsgHandler extends Handler {

        public MsgHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0: //init
                    handleInitAction(msg);
                    break;
                case 1: //onMessage
                    handleMessageAction(msg);
                    break;
                case 2: //send message
                    handleSendMessageAction(msg);
                default:
                    break;
            }
        }

        private void handleSendMessageAction(Message msg) {
            try {
                mWebSocketClient.send((String) msg.obj);
            } catch (NotYetConnectedException e) {
                e.printStackTrace();
            }
        }

        private void handleMessageAction(Message msg) {
            showNotification(NOTIFY_ID.NOTIFICATION_RECEIVE_MESSAGE.getId(), "GetMessage",
                    (String) msg.obj, false);
        }

        private void handleInitAction(Message msg) {
            try {
                mWebSocketClient = new WebSocketClient(new URI((String) msg.obj)) {
                    @Override
                    public void onOpen(ServerHandshake handshakedata) {
                        Log.i(LOG_TAG, "[WebSocketClient] onOpen");
                    }

                    @Override
                    public void onMessage(String message) {
                        Log.i(LOG_TAG, "[WebSocketClient] onMessage: " + message);
                        Message msg = mMsgHandler.obtainMessage();
                        msg.what = 1; // onMessage
                        msg.obj = message;
                        mMsgHandler.sendMessage(msg);
                    }

                    @Override
                    public void onClose(int code, String reason, boolean remote) {
                        Log.i(LOG_TAG,
                                "[WebSocketClient] onClose: code(" + code + ") reason(" + reason
                                        + ") remote(" + remote + ")");
                    }

                    @Override
                    public void onError(Exception ex) {
                        Log.i(LOG_TAG, "[WebSocketClient] onError", ex);
                    }
                };
                mWebSocketClient.connect();
            } catch (URISyntaxException e) {
                e.printStackTrace();

                // TODO: stop & notify
            }
        }
    }


    public static void startForegroundService(Context context, String serverUri) {
        Intent intent = new Intent(context, PushService.class);
        intent.putExtra("SERVER_URI", serverUri);
        intent.setAction(ACTION_START_FOREGROUND);
        context.startService(intent);
    }

    public static void stopForegroundService(Context context) {
        Intent intent = new Intent(context, PushService.class);
        intent.setAction(ACTION_STOP_FOREGROUND);
        context.startService(intent);
    }

    public static void sendMessageToServer(Context context, String message) {
        Intent intent = new Intent(context, PushService.class);
        intent.putExtra("SEND_MESSAGE", message);
        intent.setAction(ACTION_SEND_MESSAGE_TO_SERVER);
        context.startService(intent);
    }


    public PushService() {
    }


    public class LocalBinder extends Binder {

        PushService getService() {
            return PushService.this;
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent.getAction().equals(ACTION_START_FOREGROUND)) {
            startForeground(NOTIFY_ID.NOTIFICATION_STARTED.getId(), createNotification(
                    NOTIFY_ID.NOTIFICATION_STARTED.getId(), true));

            mHandlerThread = new HandlerThread("push_service", Process.THREAD_PRIORITY_FOREGROUND);
            mHandlerThread.start();
            mMsgHandler = new MsgHandler(mHandlerThread.getLooper());

            Message msg = mMsgHandler.obtainMessage();
            msg.what = 0; //init
            msg.obj = intent.getStringExtra("SERVER_URI");
            mMsgHandler.sendMessage(msg); // init
        } else if (intent.getAction().equals(ACTION_STOP_FOREGROUND)) {
            stopForeground(true);
            stopSelf();
        } else if (intent.getAction().equals(ACTION_SEND_MESSAGE_TO_SERVER)) {
            Message msg = mMsgHandler.obtainMessage();
            msg.what = 2; //send message
            msg.obj = intent.getStringExtra("SEND_MESSAGE");
            mMsgHandler.sendMessage(msg);
        }
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        cancelNotification(NOTIFY_ID.NOTIFICATION_STARTED.getId());
        mWebSocketClient.close();
        mHandlerThread.quit();
    }

    private void showNotification(int id, String title, String msg, boolean isOnGoing) {
        PendingIntent pendingIntent = PendingIntent
                .getActivity(getApplicationContext(), 0, new Intent(), 0);

        Notification.Builder builder = new Notification.Builder(getApplicationContext())
                .setContentTitle(title)
                .setContentText(msg)
                .setSmallIcon(R.mipmap.ic_notificataion)
                .setColor(0x4fc3f7)
                .setPriority(Notification.PRIORITY_HIGH)
                .setFullScreenIntent(pendingIntent, true)
                .setOngoing(isOnGoing) // can't dismiss
                .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
        mNotificationManager.notify(id, builder.build());
    }

    private Notification createNotification(int id, boolean isOnGoing) {
        PendingIntent pendingIntent = PendingIntent
                .getActivity(getApplicationContext(), 0, new Intent(), 0);

        Notification.Builder builder = new Notification.Builder(getApplicationContext())
                .setContentTitle("PushService")
                .setContentText("push service started")
                .setSmallIcon(R.mipmap.ic_notificataion)
                .setColor(0x4fc3f7)
                .setPriority(Notification.PRIORITY_HIGH)
                .setFullScreenIntent(pendingIntent, true)
                .setOngoing(isOnGoing) // can't dismiss
                .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION));
        return builder.build();
    }

    private void cancelNotification(int id) {
        mNotificationManager.cancel(id);
    }

}

handleInitAction()内でWebsocketのinit処理を行っています。 WebSocketClientはライブラリに用意されたクラスで、作成時にURI(ここでは ws://192.168.11.4:5000/socket_handset/bing)を渡します。 Soceketを閉じるときはWebSocketClient.close()を呼び出します。 作成したSocketにメッセージを受けると、WebSocketClient.onMessage()を受けることができます。

Websocketからメッセージを受けると、Notificationを出すように実装してあるので、Socketにサーバーからメッセージを入れればPUSHっぽいことが実現できます。

Server側の実装

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Flask, request
from flask_sockets import Sockets
from werkzeug.exceptions import abort
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
from geventwebsocket.websocket import WebSocketError

app = Flask(__name__)
sockets = Sockets(app)
ws_list = set()


@sockets.route('/socket_handset/bind')
def bind_sockets(ws):
    '''
    handsetとのwebsocket接続用
    :param ws:
    :return:
    '''
    if not ws:
        abort(400)

    ws_list.add(ws)
    remove = set()
    print 'adding', len(ws_list)

    while True:
        try:
            msg = ws.receive()
            print "get message: ", msg
            for s in ws_list:
                try:
                    s.send(msg)
                except Exception:
                    remove.add(s)
                    break

        except WebSocketError:
            remove.add(ws)
            break

    for s in remove:
        ws_list.remove(s)


@app.route('/send/message', methods=['POST'])
def send_message():
    '''
    JSONがPOSTされたら、つながっているWebsocketにデータを流す
    JSONは以下形式を期待している
    {
        "message": "message to send"
    }

    curlでのJSONのPOSTは以下でできる
    curl -vv -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"message": "message from server"}' http://localhost:5000/send/message
    :param message:
    :return:
    '''
    if request.method == 'POST':
        print "send_message", request.json

        json_data = request.json
        print len(ws_list)

        remove = set()
        for s in ws_list:
            try:
                s.send(json_data["message"])
            except Exception:
                remove.add(s)

        for s in remove:
            ws_list.remove(s)

        return 'ok'
    abort(400)



@app.route('/')
def hello_world():
    return 'Hello World!'


if __name__ == '__main__':
    server = pywsgi.WSGIServer(('', 5000), app, handler_class=WebSocketHandler)
    server.serve_forever()

PUSH確認は以下curlで。

$ curl -vv -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"message": "message from server"}' http://localhost:5000/send/message

Notificationが出たらOK!

python覚えたのでmonkeyrunner試してみる

monkeyrunnerは端末に対して無作為なイベントを送付するmonkeyツールとは異なり、デバイスのキーイベントの送付やスクリーンショットの取得などを実行することができるテスト用のツールです。

うまく使えばframeworkのテストツールとして利用できそうなので、目をつけてたもののPython知らんぜとか思って放置してた。 覚えたついでに調べなおしを。

monkeyrunnerはjthonとして実装されており、用意されているモジュールは3つのみみたい。

  • MonkeyDevice 主にメインに使うことになるクラス。アプリケーションのインストールから、タッチイベントの送付、アクティビティの立ち上げなど、いろいろできる。

  • MonkeyImage 主に画像を扱うときにつかう。2つのイメージの比較などにも利用できるので、実行結果のスクリーンショットと期待値のスクリーンショットの比較とかできる。

  • MonkeyRunner デバイスとの接続などに使う。ここのメソッドを通じてMonkeyDeviceクラスを取得する

アプリケーションを起動する

Settingsアプリを起動してみる。

# -- coding=utf-8 --
author = 'kobashin'

from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice

device = MonkeyRunner.waitForConnection()

def startApp(target): device.startActivity(component=target)

def main(): startApp('com.android.settings/.Settings')

if name == "main": main()

MonkeyDevice.startActivity()を使って、Activityの起動ができる。同様に、以下でHomeのIntentが投げれる。

def actionHome():
    device.startActivity(action="android.intent.action.MAIN", categories=["android.intent.category.HOME"])

アプリケーションをインストールする

単なる1アプリのインストールであれば、以下でOK。 pathにはHOST PC側のapkパスを指定する。

def installApp(path):
    device.installPackage(path)

複数のアプリケーションを一気にインストールするのであれば、以下でいけそう。指定したディレクトリ以下のapkファイルをインストールして回る。

import glob

def installAppInDir(dirpath): files = glob.glob(dirpath + '/*.apk') for apk in files: installApp(apk)

デバイスのキーを押下する

電源ボタンを押下してみる。suspend/resumeの試験とかこれでいんじゃないの?あ、adb走ってたらwakelock握りっぱなしだっけか。

import time

def keyDownAndUp(code): device.press(code, 'DOWN_AND_UP')

def main(): keyDownAndUp('KEYCODE_POWER') time.sleep(2) keyDownAndUp('KEYCODE_POWER')

スクリーンショットを取得する

取るだけなら、以下で。 pathには絶対PATHを指定すること。

def takeScreenShot(path):
    result = device.takeSnapshot()
    result.writeToFile(path, 'png')
    return result

とった結果と比較するときには、以下で行う。 loadImageFromFileを利用すれば、pngファイルからMonkeyImageが取得できるのでsameAsを使って比較すればよい

def compareImages(src, dest):
    if src.sameAs(dest, 0.9):
        print "2 is same"
    else:
        print "2 is different"

def main(): dest = device.takeSnapshot() src = MonkeyRunner.loadImageFromFile('/Users/skobayashi1/workspace/temp/apps/test1.png') compareImages(src, dest)

一旦ここまで。 CTS実施前の端末設定とか、顧客ごとのキッティングとか、これで作ればいいんじゃないかな。

Flaskお勉強中メモ

※メモ書き

hello world

app.route()にルーティングするPathを指定して、直下にメソッドを定義すると、そのPathへのアクセスがあったときにメソッドが呼び出されるようになる。 app.run()を呼べば、サーバーが起動する。debug=Trueを指定すれば、デバッグオプションが有効になりソースコードの変更時に自動的に読み込み直しがかかるようになる。開発時はこれでいいけど、デプロイするときは外すようにする。 そのほかに、port=5678でポートの変更、host='0.0.0.0'でアドレスの変更がかかる。

from flask import Flask

app = Flask(__name__)

if __name__ == "__main__":
    app.run()

routing

変数を使う

@app.route()に<>を使うとURLを引数として利用することができる 例えば、localhost/user/kobashinにアクセスして、hello kobashin!を表示する場合は、

@app.route(&quot;/usr/&lt;username&gt;&quot;)
def show_user(username):
    return &quot;hello &quot; + username + &quot;!\n&quot;

<int:username>とすれば、入力値を限定することができる。

redirectとrul_for

redirectはリダイレクト用のメソッド、url_forはそのメソッドのURLに変換してくれるメソッド(?)

from flask import Flask, url_for, redirect

@app.route(&quot;/&quot;)
def root_index():
    return redirect(&quot;/link&quot;)


@app.route(&quot;/redirect_link&quot;)
def to_link():
    return redirect(url_for(&quot;link&quot;))


@app.route(&quot;/link&quot;)
def link():
    return &quot;link&quot;

htmlのテンプレートを使う

render_templateメソッドを使うと、templates以下のディレクトリの指定したhtmlファイルを探しに行ってくれる。 テンプレートとして利用できる書式については、以下ドキュメントが参照できる http://jinja.pocoo.org/docs/dev/templates/

from flask import Flask, render_template

@app.route(&quot;/&quot;)
def index():
    return render_template(&quot;index.html&quot;)
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head lang=&quot;en&quot;&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;title&gt;&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
hello world!
&lt;/body&gt;
&lt;/html&gt;