このwebページは2022年前期に私がゼミで取り組んだ内容を説明するものである。

1.ミニディスプレイに文字、QRコード表示

aruduino unoを使ってOLEDディスプレイに文字やQRコード、画像などを表示させることに取り組みました。他のシステムでもQRコードを使う機会が多いので、他のシステムに応用できる汎用性の高い技術であると私は考えている。

*画像をタップすれば詳しく見れます

・ソースコード

コードを表示する
#include "qrcode.h" //https://github.com/ricmoo/qrcode/
#include "U8glib.h"
    
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE | U8G_I2C_OPT_DEV_0);   // I2C / TWI

    
void display_qrcode(char *text) {   
    QRCode qrcode;
    uint8_t qrcodeData[qrcode_getBufferSize(4)];
    qrcode_initText(&qrcode, qrcodeData, 4, ECC_LOW, text);
    
    u8g.firstPage();
    do {
        u8g.setColorIndex(1);
        u8g.setFont(u8g_font_unifont);
        u8g.drawStr( 10, 25, "coffee");
        u8g.drawStr( 10, 40, "100");
        u8g.setColorIndex(1);
        u8g.drawBox(64, 0, 64, 64); //塗りつぶし
        u8g.setColorIndex(0);
        for (uint8_t y = 0; y < qrcode.size; y++) {
            for (uint8_t x = 0; x < qrcode.size; x++) {
                if (qrcode_getModule(&qrcode, x, y))
                    u8g.drawBox(79 + x, 15 + y, 1, 1);
            }
        }
    } while ( u8g.nextPage() );
}
    
void setup() {
    if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {
    u8g.setColorIndex(255);     // white
    }
    else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
        u8g.setColorIndex(3);         // max intensity
    }
    else if ( u8g.getMode() == U8G_MODE_BW ) {
        u8g.setColorIndex(1);         // pixel on
    }
    else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
        u8g.setHiColorByRGB(255,255,255);
    }
    pinMode(8, OUTPUT);
    u8g.begin();
    display_qrcode("https://programresource.net");
    }
    
void loop() {
}

2.入札機で電子マネーをチャージするシステム

電子マネープロジェクトで運用している独自の電子マネーを1000円札でチャージするシステムを開発しました。開発には、pyhton、javascriptなどを使用している。入札機は日本コンラックスNB-MBシリーズを使用している。操作の手順としては、入札機に1000円札を挿入する。挿入後、入札機についているQRコードを読み取り、操作手順に従って電子マネーをチャージする。このQRコードのサイトには一人しか入れないようにしており、誰か操作中の時は他の人はアクセスできない。また、一定時間操作がなかったら、操作を停止してお札を返金する。

・デモ動画

・操作の全体図


・操作時のスマホ画面

・ソースコード

JavaScriptのソースコードやサーバー側のCGIのソースコードは多いので省略する。ここでは、入札機の制御、サーバーとの通信をするソースコードのみを載せる。

コードの中身
#モジュール定義
import serial
import requests
import json
from email.mime.text import MIMEText
from smtplib import SMTPException
import smtplib
from email.header import Header
import time
import sys
#コマンドデータを定義
state_command = ["---"]
acceptance_command = ["---"]
no_acceptance_command = ["---"]
revenue_command = ["---"]
refund_command = ["---"]
reset_command = ["---"]
#入札機の制御
def serial_request(Request_command):
ser = serial.Serial('/dev/ttyUSB0', 9600,timeout=0.1)
send_binary = bytes(Request_command)
ser.write(send_binary)
data = ser.readall()
byte_data = data.hex()
print(byte_data)
ser.close()
return byte_data
#サーバーのディレクトリをリセット
def server_dir_reset():
r = requests.post('https://www.48v.me/~yuto211007/cgi-bin/"---".py', 
                data={"---"})
data = r.text
return data
#サーバーのディレクトリの有無を確認
def server_dir_check():
r = requests.post('https://www.48v.me/~yuto211007/cgi-bin/"---".py', 
                data={"---"})

data = r.text
return data
#メールアドレスが入力されたか確認
def mail_num_check():
r = requests.post('https://www.48v.me/~yuto211007/cgi-bin/"---".py', 
                json={"---"})

mail_adress = r.text
return mail_adress
#サーバーからメールアドレス取得
def mail_address_req():
r = requests.post('https://www.48v.me/~yuto211007/cgi-bin/"---".py', 
                json={"---"})

mail_adress = r.text
return mail_adress
#サーバーからVATurl取得
def make_vaturl():
r = requests.post('https://www.48v.me/~ec/cgi-bin/"---".py', 
                data={
                    "tid": "---",
                    "token": "---",
                    "value_id": "---",
                    "value_points": "---",
                    "issue_count": "---",
                    "price": "---",
                    "memo": "---"})
data = json.loads(r.text)
url_data = data["issues"]
url = url_data[0]["url"]
return url
#返金動作
def Refund():
Escrow_No_acceptance_data = serial_request(no_acceptance_command)
if Escrow_No_acceptance_data == "---":
    time.sleep(0.1)
    state_data = serial_request(state_command)
    if state_data == "---":
        time.sleep(0.1)
        Refund_data = serial_request(refund_command)
        if Refund_data == "---":
            time.sleep(0.1)
            Refund_state_data = serial_request(state_command)
            if Refund_state_data == "---" or "---":
                Escrow_acceptance_data = serial_request(acceptance_command)
                if Escrow_acceptance_data == "---":
                    time.sleep(0.1)
                    state_acceptance_data = serial_request(state_command)
                    if state_acceptance_data == "---" or "---" or "---":
                        return 1
                    else:
                        sys.exit()
                else:
                    sys.exit()
            else:
                sys.exit()
        else:
            sys.exit()
    else:
        sys.exit()
else:
    sys.exit()
#メール送信関数
def mail_send(url,to_ad):
smtp_host = 'smtp.gmail.com'
smtp_port = 465
username = '32045081@fukuchiyama.ac.jp'
password = 'ionoaluthjvgoknd'
from_address = '32045081@fukuchiyama.ac.jp'
to_address = str(to_ad.strip())
subject = 'VAT_confirmation mail'
body = str(url)
message = ("From: %s\r\nTo: %s\r\nSubject: %s\r\n\r\n%s" %
            (from_address, to_address, subject, body))
    
smtp = smtplib.SMTP_SSL(smtp_host, smtp_port)
smtp.login(username, password)
result = smtp.sendmail(from_address, to_address, message)
return 1
#url送信関数
def url_send(url):
r = requests.post('https://www.48v.me/~yuto211007/cgi-bin/"---".py', 
                data={
                    "url": url,})
#お札集金
def print_req(mail_data):
escrow_no_acceptance_data = serial_request(no_acceptance_command)
if escrow_no_acceptance_data == "---":
    state_data = serial_request(state_command)
    if state_data == "---":
        revenue_data = serial_request(revenue_command)
        if revenue_data == "---":
            url = make_vaturl()
            mail_send(url,mail_data)
            url_send(url)
            server_dir_reset()
            Revenue_state_data = serial_request(state_command)
            if Revenue_state_data == "---":
                Escrow_acceptance_data = serial_request(acceptance_command)
                if Escrow_acceptance_data == "---":
                    time.sleep(0.1)
                    state_acceptance_data = serial_request(state_command)
                    if state_acceptance_data == "---":
                        return 1
                    else:
                        sys.exit()
                else:
                    sys.exit()
            else:
                sys.exit()
        else:
            sys.exit()
    else:
        sys.exit()
else:
    sys.exit()

def access_dir_make():
r = requests.post('https://www.48v.me/~yuto211007/cgi-bin/"---".py', 
                data={"---"})

data = r.text
return data

def access_dir_rem():
r = requests.post('https://www.48v.me/~yuto211007/cgi-bin/"---".py', 
                data={"---"})

data = r.text
return data

serial_request(state_command)
time.sleep(1)
serial_request(acceptance_command)

while True:
state_data = serial_request(state_command)
if state_data == "---":
    time.sleep(1)
    access_dir_make()
    server_dir_reset()
    time.sleep(2)

elif state_data == "---":
    time.sleep(1)
    access_dir_make()
    server_dir_reset()
    time.sleep(2)

elif state_data == "---":
    time.sleep(1)
    access_dir_make()
    server_dir_reset()
    time.sleep(2)

elif state_data == "---":
    time.sleep(1)
    access_dir_make()
    server_dir_reset()
    time.sleep(2)

elif state_data == "---":
    access_dir_rem()
    i = 0
    flg = False
    for ii in range(30):
        i+=1
        print(i)
        time.sleep(1)
        if flg == True:
            break
        elif server_dir_check().strip() == "0":
            j = 0
            for jj in range(60):
                j+=1
                print(j)
                time.sleep(1)
                num_data = mail_num_check().strip()
                if num_data == "1":
                    address_data = mail_address_req().strip()
                    data_req = print_req(address_data)
                    if data_req == 1:
                        print("ok")
                        time.sleep(0.1)
                        flg = True
                        break
                    else:
                        sys.exit()
                elif j == 40:
                    data = Refund()
                    print(data)
                    access_dir_make()
                    if data == 1:
                        server_dir_reset()
                        time.sleep(1)
                        flg = True
                        break
                    else:
                        sys.exit()
                else:
                    pass
        elif i == 30:
            data = Refund()
            access_dir_make()
            print(data)
            if data == 1:
                server_dir_reset()
                time.sleep(1)
            else:
                sys.exit()
        else:
            pass
else:
    pass
        

・今後の課題

  • QRを読み込んでからお札を入れる仕様に変える
  • 無人で実際に運用できるようにエラーなどに対応する

3.厨房にメニューを伝えるシステム(オープンキャンパス用)

オープンキャンパスでは、サークル団体であるサービスビジネス研究会がフロートを売る話が持ち上がった。そこで、山本ゼミがオープンキャンパスで企画している脱出ゲームのクリア報酬をフロートの割引券にする方針で決まった。報酬の受け取りやカフェのテント設営の場所などが原因で、フロートの受付と厨房の場所を別にしなければいけなくなった。しかし、それでは厨房に客の注文を伝えられない問題が発生しました。そこで、厨房に注文を伝える簡易的なシステムを開発した。受付側はボタンを押すだけで厨房に注文を送ることができる。厨房側は、客に商品を提供した後、「確認しました」というボタンを押すことで、終わったオーダーを把握することができる。
これは山本ゼミの水野君と共同で作ったため、私が作成した部分のソースコードのみを掲載する。

・受付側の画面(画像をタップすれば詳しく見れます)
・厨房側の画面(画像をタップすれば詳しく見れます)

・ソースコード

コードの中身(webページ表示の関係上一部省略)
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

from datetime import date
import sys
import csv
import cgi
import datetime
from numpy import product
form = cgi.FieldStorage()



# 数字かどうかを判断する関数

def csv_upload(data):
    date = datetime.datetime.now()
    product = data['product'].value
    with open("../../cafe_log/db/cafelog_num.csv", 'r',encoding='utf-8') as f:
        reader = csv.reader(f)
        logList=[row for row in reader]
        logList = logList[0][0]
        f.close()
        number = int(logList)
    
    if number == 200:
        with open("../../cafe_log/db/cafelog_num.csv", 'w',encoding='utf-8') as f:
            f.write(str(1))
        with open("../../cafe_log/db/cafe_log.csv", 'a',encoding='utf-8') as f:
            f.write(str(date) + ",")
            f.write(product + ",")
            f.write(str(number)+"\n")
            f.close()
            return 1

    else:
        with open("../../cafe_log/db/cafelog_num.csv", 'w',encoding='utf-8') as f:
            f.write(str(number+1))
            f.close()
        with open("../../cafe_log/db/cafe_log.csv", 'a',encoding='utf-8') as f:
            f.write(str(date) + ",")
            f.write(product + ",")
            f.write(str(number)+"\n")
            f.close()
            return 1

if csv_upload(form) == 1: 
    result = 1
    print('Content-Type: text/html; charset=utf-8\n\n')
    print(form["product"].value)
    print("が購入されました。")
    print('
') print('戻る') else: result = 0 print('Content-type: text/html\n') print("NO")

4.その他の活動

・電子マネーシステムのバグだし
・クレジットカード決済プログラムの作成(*未完成*進行中)
*クレジットカード決済プログラムはここで見れるよ

5.参考文献