プロジェクト型演習 #4 (シリアル通信, DB操作)

# 前提
https://qiita.com/kawanishi291/items/acae192ed2a22c2977a4

https://qiita.com/kawanishi291/items/50b6d803e40b42639c8e

https://qiita.com/kawanishi291/items/15ef1013393c08598bb9

上記事３つを参考に、環境構築及び必要プログラム作成済み

# 手順
1. em board側の送信プログラム作成
1. RaspberryPi側の受信プログラム作成
1. DB接続関数作成
1. テキストファイル読み込み関数作成
1. DB格納 mainプログラム作成
1. Python呼び出し用シェルスクリプト作成
1. 一旦実行(em board, RaspberyPi両方とも)
1. result.txtの権限変更
1. 再度実行


# 作成ファイル一覧
+ RS232C_em_board.c (em board側 : 送信プログラム)
+ RS232C_raspberry_pi.c (RaspberyPi側 : 受信プログラム)
+ CallPython.sh (Python呼び出し用シェルスクリプト)
+ db_insert.py (DB格納 mainプログラム)
+ read_text.py (テキストファイル読み込み関数)
+ db_connect.py (DB接続関数)
+ result.txt (受信データ格納テキストファイル)

# 実装

#### RS232C_em_board.c
em board側 : 送信プログラム
※ ひとまず今回は手動で配列を作成。

```
pi@raspberry:~ $ nano RS232C_em_board.c
```
```c:RS232C_em_board.c
#include <machine.h>
#include "iodefine.h"
#include "initBASE.h"

#define DATALEN 15

void main(void);

void main(void)
{	
	volatile int cnt = 0;
	volatile unsigned char str;
	volatile char list[DATALEN] = {'0', '0', '2', ',', '0', '0', '1', ',', '0', '0', '0', ',', '0', '3', '9'};
	volatile int i = 0;
	volatile int delay = 0;
	
	/* CMTO初期化 */
	SYSTEM.PRCR.WORD = 0xA502;
	MSTP(CMT0) = 0;
	SYSTEM.PRCR.WORD = 0xA500;
	CMT0.CMCR.WORD = 0x00C2;
	CMT0.CMCNT = 1;
	CMT0.CMCOR = 374;
	IR(CMT0, CMI0) = 0;
	CMT.CMSTR0.BIT.STR0 = 1;
	
	/* クロック初期化 */
	initBASE();
	
	/* SCI2 */
	SYSTEM.PRCR.WORD = 0xA502;
	MSTP(SCI2) = 0;
	SYSTEM.PRCR.WORD = 0xA500;
	
	MPC.PWPR.BIT.B0WI = 0;
	MPC.PWPR.BIT.PFSWE = 1;
	MPC.P50PFS.BYTE = 0x0A;
	MPC.P52PFS.BYTE = 0x0A;
	MPC.PWPR.BIT.PFSWE = 0;
	MPC.PWPR.BIT.B0WI = 1;
	
	PORT5.PMR.BIT.B0 = 1;
	PORT5.PMR.BIT.B2 = 1;
	SCI2.SMR.BYTE = 0x00;
	SCI2.BRR = 155;
	
	SCI2.SCR.BYTE = 0x30;
	
	
	while(1){
		while (IR(CMT0, CMI0) == 0) {
			;
		}
		IR(CMT0, CMI0) = 0;
		while (cnt < 1000000) {
			cnt ++;
		}
		cnt = 0;
		SCI2.TDR = 's';
		if (SCI2.SSR.BIT.RDRF == 1) {
			SCI2.TDR = list[i];
			SCI2.SSR.BIT.RDRF = 0;
			i++;
		}
		if (i == DATALEN) {
			break;
		}
	}
	
}

```
#### RS232C_raspberry_pi.c
RaspberyPi側 : 受信プログラム

```
pi@raspberry:~ $ nano RS232C_raspberry_pi.c
```
```c:RS232C_raspberry_pi.c
#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <wiringSerial.h>

#define DATALEN 15

void setFile(char *p);

int main(void){
    int indat, count;
    int fd;
    char buf[17];
    char tmp[DATALEN];
    int i = 0;

    fd = serialOpen("/dev/ttyUSB0", 9600);
    if (fd < 0) {
        printf("serialOpen error!!\n");

        return -1;
    }

    printf("fd = %d\n", fd);
    serialFlush(fd);
    while (1) {
        printf("\n");
        serialPuts(fd, buf);
        //delay(100);
        while (!(count = serialDataAvail(fd)));
        /* 受信開始 */
        while (count--) {
            /* 1文字づつ格納 */
            indat = serialGetchar(fd);
            printf("%c", indat);
	        serialPrintf(fd, "r");
            if (i < DATALEN) {
                tmp[i] = indat;
                i ++;
            } else {
                tmp[i] = indat;
                setFile(tmp);
                i = 0;
                delay(100);
                system("./CallPython.sh");
            }
        }
        /* 受信終了 */
    }
    printf("bye");
    serialClose(fd);

    return 0;
}


void setFile(char *p){
	int i;
	FILE *fp;

	fp = fopen("result.txt", "w");
    if (fp == NULL){
            printf("error\n");
            exit(1);
    } else {
        printf("\n");
    }
	for (i = 0; i < DATALEN; i++) {
		fprintf(fp, "%c", p[i+1]);
	}
	fclose(fp);
}

```
```
pi@raspberry:~ $ gcc -o RS232C_raspberry_pi RS232C_raspberry_pi.c -lwiringPi
```
#### db_insert.py
DB格納 mainプログラム

```
pi@raspberry:~ $ nano db_insert.py
```
```python:db_insert.py
import mysql.connector as mydb
import datetime
from read_text import ReadText
from db_connect import mysqlConnector


dt_now = datetime.datetime.now()
time = dt_now.strftime('%Y-%m-%d %H:%M:%S')

path = "./result.txt"
data_list = ReadText(path)

id = data_list[0]
great = data_list[1]
good = data_list[2]
bad = data_list[3]
score = (great * 10) + (good * 5)

user = 'pi'
password = 'raspberry'
host = 'localhost'
db = 'sample_db'

conn = mysqlConnector(host, 3306, user, password, db)
cur = conn.cursor()

try:
    cur.execute("INSERT INTO score VALUES (num, %(id)s, %(score)s, %(great)s, %(good)s, %(bad)s, %(datetime)s)",
{'id': id, 'score': score, 'great': great, 'good': good, 'bad': bad, 'datetime': time})
    conn.commit()
except:
    conn.rollback()
    raise

cur.close()
conn.close()
```
#### read_text.py
テキストファイル読み込み関数

```
pi@raspberry:~ $ nano read_text.py
```
```python:read_text.py
def ReadText(path):
    with open(path) as f:
        data = f.read()

    sum = 0
    data_list = []
    for i in data:
        if (i == ','):
            data_list.append(sum)
            sum = 0
        else:
            sum = (sum * 10) + int(i)
    data_list.append(sum)


    return data_list
```
#### db_connect.py
DB接続関数

```
pi@raspberry:~ $ nano db_connect.py
```
```python:db_connect.py
import mysql.connector as mydb
import sys

def mysqlConnector(_host, _port, _user, _passwd, _dbname):
    try:
        resconn = mydb.connect(
        host=_host,
        port=_port,
        user=_user,
        password=_passwd,
        database=_dbname
        )
    except Exception as e:
        print('[DB Connection Error]', e)
        sys.exit(1)

    # 接続が切れた場合に自動的に再接続する
    resconn.ping(reconnect=True)

    # 接続できているかどうか確認
    print(resconn.is_connected())

    return resconn
```
#### CallPython.sh
Python呼び出し用シェルスクリプト

```
pi@raspberry:~ $ nano CallPython.sh
pi@raspberry:~ $ chmod 777 CallPython.sh
```

```CallPython.sh
python ./db_insert.py
exit 0
```
#### result.txt
受信データを格納するテキストファイル
※ 空のファイルを生成し、ファイルの権限設定

```
pi@raspberry:~ $ touch result.txt
pi@raspberry:~ $ chmod 777 result.txt
```
# 実行と結果
RaspberryPi側

```
pi@raspberry:~ $ ./RS232C_raspberry_pi
fb = 3

s
0
0 
2 
, 
0 
0 
1 
, 
0 
0 
0 
, 
0 
3 
9
True

```

> [webサイトの確認 >>](http://raspberrypi/index.php)

# 今後
+ メンバー作成物とくっつける
+ RS232C_em_board.c のリスト生成の関数を作成