Raspberry Piの共有フォルダにファイルが置かれると処理を実行させる

#Raspberry Piの共有フォルダにファイルが置かれると処理を実行する

1.ラズパイに共有フォルダをつくる
2.共有フォルダの状態を監視
3.フォルダに更新があったら、処理を実行
　この例では、
　　・ラズパイの共有フォルダにExcelファイル(xls,xlsx)が置かれると
　　　matplotlibでグラフを描いてEPS出力
　　・さらにeps→emf形式に変換したファイルを出力する

実行する処理のサンプルはここまでメモってきたプログラムです。
　(1)[Excelデータをmatplotlibでグラフ化する（１）](http://qiita.com/gitytm15/items/13bacd27fa4b37707b3a)
　(2)[matplotlibのグラフをemfファイル形式に変換]
(http://qiita.com/gitytm15/items/418ddcd8f58555d7433b)
　(3)[ラズパイのInkscapeを0.48から0.92にしてみた](http://qiita.com/gitytm15/items/6452743fae9b96fc8c58)

ラズパイなのでずっと起動してても、それほど気にすることはないというのが気に入っています。

#1.ラズパイに共有フォルダをつくる

共有の[DATA]フォルダ内にxlsx,xlsファイルをいれるとプログラムが実行されるようにするために、まずはどこからでもアクセスできる共有フォルダを作成します。


[share]　←共有フォルダ
　│
　└[DATA]  ここにxlsx,xlsをおくと変換プログラムが実行されるようにする
　　│
　　├[eps]　epsファイル保存
　　└[emf]　emfファイル保存
　

参考にするところは検索でもたくさんでてきますがラズパイのsambaによる共有方法は、ここを参考にしました。

[hiramine.com]
(http://www.hiramine.com/physicalcomputing/raspberrypi3/samba_installconfigconnect.html)

ここでは```/home/pi```を共有化されていますが、pi以下が丸見えだと困るので、さらにその下に```[share]```フォルダを作ることにしました。
はじめは、この```[share]```と```path=/home/share```のフォルダ名を合わせていなくて、共有がうまくいかず、しばらく悩んでいました。おおざっぱな流れはつぎのようになります。

インストール

```
sudo apt-get update
sudo apt-get install samba
```

設定ファイルの書き換え(最後の行に追記)

```
sudo nano /etc/samba/smb.conf
```

```smb.conf
#最後に追加
[share]
path = /home/pi/share
read only = No
guest ok = Yes
force user = pi
```

```
sudo service smbd restart
```
これでWindows,Mac,Ubuntuからアクセスできるようになりました。





#2.共有フォルダの状態を監視

監視する方法と実際の処理について具体的なコードですが、すでにわかりやすい記事があります。しっかり参考にさせていただきました。つかったものは```watchdog```です

・[ファイル監視にwatchdogがかなり便利な件]
(http://qiita.com/PyYoshi@github/items/9744a138c018734c69db)
・[Pythonで作るLaTex自動コンパイル環境]
(http://qiita.com/syutaro/items/414fc12eeb8960b3c29b)
・[watchdog 0.8.3　Example API Usage]
(https://pypi.python.org/pypi/watchdog)


watchdogは```pip install watchdog```でインストールできます。念の為。


#3.更新があったら実行

コードは下のsample1.pyを参照してください。これが監視して実行するメインの部分となります。

簡単な説明
watchdogまわりのimportに加えて実行用のモジュールをimportします。

```py
import sample2
```

ここではsample2.pyのなかのコードを実行するためにこうしています。
(この部分を任意の実行ファイルに置き換える)

sample2.pyは、下の2つのコードをまとめています。
　[Excelデータをmatplotlibでグラフ化する（１）](http://qiita.com/gitytm15/items/13bacd27fa4b37707b3a)
　[matplotlibのグラフをemfファイル形式に変換]
(http://qiita.com/gitytm15/items/418ddcd8f58555d7433b)



ファイル更新の監視対象は、ここではExcelファイルなので、拡張子をこのように設定します。

```py
# 監視対象のファイル
observed_file_type = ('.xls','.xlsx')
```

さきほど作成したラズパイの共有フォルダをBASEDIRに設定します。
元々は、BASEDIRは、ファイル本体の場所を示す

```py
#BASEDIR = os.path.abspath(os.path.dirname(__file__))
```
になっていますが、ここではコメントアウトしています。今回はラズパイの共有フォルダのアドレスを次のように指定しています。

```py
BASEDIR ='/home/pi/share/DATA'
```

つぎにイベント発生時の実行部分です。このコードがイベント毎に入ります。更新のあったExcelファイルのパスを投げています。

```py
sample2.plot(event.src_path) #ファイル作成時に実行
```

sample1.pyを実行するとラズパイ君が指定フォルダの監視モードに入ります。
指定のフォルダにExcelファイルを移動したり、編集して保存するとその都度実行されます。
このExcelファイルはXY軸プロットでA1にX、B1にYをいれる構造に対応しています。![excel.png](https://qiita-image-store.s3.amazonaws.com/0/110861/efb25b8c-a267-7900-c118-5ab7896b737d.png)



```sample1.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
import os
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer
import sample2 #←更新にあわせて実行するモジュール(ここでは仮にsample2)

# 監視対象のファイル
observed_file_type = ('.xls','.xlsx')

# 設定
#BASEDIR = os.path.abspath(os.path.dirname(__file__))
#→このプログラムファイルが置かれている場所を監視する場合はこれ

#ラズパイの共有フォルダを指定
#共有フォルダ[share]内に、[DATA]フォルダを配置した
BASEDIR ='/home/pi/share/DATA'

# 変更したファイルが監視対象であるかを調べる
def match(path):
    return any([path.endswith(ft) for ft in observed_file_type])

# 変更時のイベントハンドラ
class ChangeHandler(FileSystemEventHandler):
    def on_create(self, event):
        if event.is_directory:
            return
        if match(event.src_path):
            print('Create',event.src_path)
            sample2.plot(event.src_path) #ファイル作成時に実行

    def on_modified(self, event):
        if event.is_directory:
            return
        if match(event.src_path):
            print('Modified',event.src_path)
            sample2.plot(event.src_path) #ファイル変更時に実行

    def on_deleted(self, event):
        if event.is_directory:
            return
        if match(event.src_path):
            print('delete',event.src_path)
            #ファイルが消された時はなにもしない


if __name__ in '__main__':
    event_handler = ChangeHandler()
    observer = Observer()
    observer.schedule(event_handler, BASEDIR, recursive=True)
    print('start dir=',BASEDIR)
    observer.start()
    try:
        while True:
            time.sleep(0.1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()
```

#4.プロットとファイル変換用のモジュール

Excelファイルの更新や新規にファイルが作成されたタイミングで呼びだされます。

Excelのパスが投げられてきますので、このExcelファイルを読み込みグラフ化します。
そのあと、グラフ描画を行い、eps形式で保存すると同時にsvgからemfファイルへ変換を行い保存します。元のsvgファイルは削除します。

必要なモジュールは以下のとおりです。
・pandas
・matplotlib
・subprocess


```sample2.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties
import subprocess
import os

# フォントファイルの場所を指定 ubuntu　　(C:\Windows\Fonts\任意のFont)
fp = FontProperties(fname="/usr/share/fonts/truetype/fonts-japanese-gothic.ttf") 

def dataload(path):    #Pandas DataFrameに読込み
    df=pd.read_excel(path)
    return df

def graph(df):

    #データフレームからx軸とY軸データを読み込む
    #列で指定
    x=df[[0]]
    y=df[[1]]

    #Graph
    fig = plt.figure()
    ax1 = fig.add_subplot(111)
    ax1.set_yscale('linear')
    
    #ax1.set_yscale('log')
    #ax1.set_ylim(-1.1, 1.1)
    #ax1.set_xlim(0,360)

    ax1.set_title("グラフ sample",fontdict = {"fontproperties": fp},fontsize=12)
    ax1.set_xlabel("x軸",fontdict = {"fontproperties": fp},fontsize=12)
    ax1.set_ylabel("y軸",fontdict = {"fontproperties": fp},fontsize=12)

    ax1.scatter(x, y,s=1,c='r',label='sin')
    ax1.legend(loc="upper right")


def graph_save(path):
    
    SAVEDIR=os.path.dirname(path) #ファイルパス
    fname, ext = os.path.splitext( os.path.basename(path) ) #ファイル名のみ
    
    plt.savefig(SAVEDIR+'/eps/'+fname+".eps") #eps保存
    plt.savefig(SAVEDIR+fname+".svg") #emf変換のためにsvgで保存
    
    call_cmd='inkscape ' + SAVEDIR+fname + '.svg -M ' + SAVEDIR+'/emf/'+fname +'.emf'
    subprocess.call(call_cmd,shell=True)
    
    os.remove(SAVEDIR+fname+".svg") #svgはいらないので削除する


def plot(path):

    #監視用プログラムから呼び出される

    df=dataload(path) #Excelをpandasデータフレームとして読み込む
    graph(df) #matplotでグラフ描画
    graph_save(path) #グラフを保存・変換する

if __name__ == '__main__':
    SAVEDIR='/home/pi/share/DATA/'
    path='/home/pi/Desktop/sample.xlsx'
    plot(path)


```

以上