RaspberryPiで作った人感センサーを改良

# はじめに

[前回の投稿記事](http://qiita.com/inaBowBow/items/dca01622d086f113db00)で一応実用可能なセンサーが完成し、しばらく運用してみたところいくつか改良したい点がでてきた　　

1. ポップアップがダサい
2. ポップアップ表示と同時に音を出したい
3. 複数クライアントに対応したい  

1.については当初から思っていた点で、Windowsの標準ポップアップはとにかく見た目がイモいので、なんとか今風のおしゃれな見た目にしたいと思った  

2.については、フルスクリーンでゲームなどしているとポップアップが表示されないので、音で気づけるようにしないとまずいなと身をもって体験したため  

3.は、自分の部屋に複数PCがあるため、どちらのPCでも使える状況にしたかった  

# ポップアップ改良

知人に相談したところ、[growl](http://growl.info/)がいいのでは？と提案してもらった
Windowsでも使えて、コマンドラインから簡単に操作でき、見た目は今風でかっこいい、且つ、音も出るとのことで使ってみることにした  
[このサイト](http://qiita.com/rohinomiya/items/5e485d6700eac256af9f)を参考にバッチファイルから実行する形にした  

## growl設定

まず、[growl for windows](http://www.growlforwindows.com/gfw/)をインストールし、パスを通す
（終わった後に気付いたが、バッチファイルでフルパスを書けばパスを通さなくてもいいような気がする）
あとはgrowlの設定画面からパスワード、見た目、音の設定をして完了
([このサイト](http://qiita.com/rohinomiya/items/5e485d6700eac256af9f)の通りなので割愛)

## バッチファイル作成

ポップアップさせるためのバッチファイルを作成する

```none:popup.bat
growlnotify.exe /t:"Emergency!" /s:False /pass:"password" 退避してください
```

/s:Trueにすると、クリックしないとポップアップが消えなくなるのだが、連続でくると面倒なのでFalseにした  

これを実行するとなんなくポップアップが表示されたが、バッチファイル実行時にコマンドプロンプトが一瞬表示されてしまう
色々調べたところ、vbsからバッチファイルを呼ぶ方法が王道らしい(本当にそうかわからないけど)
なので、ちょっと腑に落ちなかったがvbsを作成した  

```vbnet:popup.vbs
Dim oShell
Dim path

Set oShell = WScript.CreateObject ("WSCript.shell")

path = oShell.CurrentDirectory
path = path & "\PopUp.bat"

oShell.run path,0

Set oShell = Nothing
```

一応希望通りの動作になったので、このvbsをスクリプトから実行することにする

## スクリプト変更

前回作成したポップアップを出す部分

```py:
def popup(): #Windows画面にメッセージを出す
  user32 = windll.user32
  user32.MessageBoxA( 0, "Enemy Will Come Here!!", "Caution!!", 0x00000030)
```

下記のように変更

```py
def growl(): #growlを表示するvbsを実行する
  path = os.path.abspath(os.path.dirname(__file__))
  filename = "popup.vbs"
  path = os.path.join(path,filename)
  os.system(path) h
```

全体としてはこうなった

```py:sencer_server.py
from __future__ import print_function
import socket
import time
import os

from contextlib import closing
from ctypes import *


def main():
  while True:
    print('listen,start')
    recv()
    time.sleep(1)

def recv():
  host = '192.168.1.xx'
  port = 8080
  backlog = 10
  bufsize = 4096
  socket.timeout(1)
  
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  try:
    with closing(sock):
      sock.bind((host, port))
      sock.listen(backlog)
      conn, address = sock.accept() 
      msg = conn.recv(bufsize) 
      if (msg == 'raspberry'):
        print('recieve')
        growl()
        
  except socket.timeout:
    print('connect,timeout')
  except socket.error:
    print('connect,error')

def growl():
  path = os.path.abspath(os.path.dirname(__file__))
  filename = "popup.vbs"
  path = os.path.join(path,filename)
  os.system(path)
  
if __name__ == '__main__':
  main()
```

以上で完了
求めていたおしゃれなポップアップが実現できた

# 複数クライアント対応

やり方を色々検討して候補を挙げてみた
1. TCPからUDPに変えてブロードキャストにする
2. 送信部分をマルチスレッドにする
3. クラウドでごにょごにょしてうまくやる  

1.のブロードキャスト化が簡単そうで、且つ、個々のIPアドレスをソースに書かなくてよくなるので試してみたが、どうにもこうにもなんとでもうまくいかず挫折した
悔しいのでそのうち誰かに聞くなりしてリベンジしたい

3.については、全体的な仕様を見直したり、クラウド選んで契約してとか手間がかかるので保留  

不本意だが2.で、とりあえずは対応することにした  

で、変更したのが下記  

```py:sencer_cliant.py
from __future__ import print_function
import socket
import time

import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.IN)

from contextlib import closing
import threading

def main():
  print('start,waiting')
  while True:
    inputValue = GPIO.input(25)
    host = ['192.168.1.xx','192.168.1.yy']
    if (inputValue == True):
      print('inputTrue')
      for ip in host:
        thread = threading.Thread(target=send, args=(ip,))
        thread.start()
      time.sleep(5)

def send(host):
  port = 8080
  bufsize = 4096
  
  sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  sock.settimeout(1)
  
  with closing(sock):
    try:
      sock.connect((host, port))
      sock.send('raspberry')
      print(host + ' send')
    except socket.timeout:
      print(host + ' socketTimeout')
    except socket.error:
      print(host + ' socketError')
  return

if __name__ == '__main__':
  main()
```

以上で完了

# 所感

我が家の環境において実用上の不満点はほぼ解消し、快適なマイルーム生活が送れている
不純な動機で変なおもちゃを作っただけだが、pythonを初めて触ったりしてテンションが上がって結構のめりこんだ
冬休みにクラウド化も試してみたい
あと、ほぼコピペなのでソースの中身はひどい内容なんだろうな、もう少しちゃんと調べながら作らないと身にならないので、少しずつでも精進していきたいと思う

指摘とか指導とかあれば、是非ともお願いします