はじめに
前回の投稿記事で一応実用可能なセンサーが完成し、しばらく運用してみたところいくつか改良したい点がでてきた
- ポップアップがダサい
- ポップアップ表示と同時に音を出したい
- 複数クライアントに対応したい
1.については当初から思っていた点で、Windowsの標準ポップアップはとにかく見た目がイモいので、なんとか今風のおしゃれな見た目にしたいと思った
2.については、フルスクリーンでゲームなどしているとポップアップが表示されないので、音で気づけるようにしないとまずいなと身をもって体験したため
3.は、自分の部屋に複数PCがあるため、どちらのPCでも使える状況にしたかった
ポップアップ改良
知人に相談したところ、growlがいいのでは?と提案してもらった
Windowsでも使えて、コマンドラインから簡単に操作でき、見た目は今風でかっこいい、且つ、音も出るとのことで使ってみることにした
このサイトを参考にバッチファイルから実行する形にした
growl設定
まず、growl for windowsをインストールし、パスを通す
(終わった後に気付いたが、バッチファイルでフルパスを書けばパスを通さなくてもいいような気がする)
あとはgrowlの設定画面からパスワード、見た目、音の設定をして完了
(このサイトの通りなので割愛)
バッチファイル作成
ポップアップさせるためのバッチファイルを作成する
growlnotify.exe /t:"Emergency!" /s:False /pass:"password" 退避してください
/s:Trueにすると、クリックしないとポップアップが消えなくなるのだが、連続でくると面倒なのでFalseにした
これを実行するとなんなくポップアップが表示されたが、バッチファイル実行時にコマンドプロンプトが一瞬表示されてしまう
色々調べたところ、vbsからバッチファイルを呼ぶ方法が王道らしい(本当にそうかわからないけど)
なので、ちょっと腑に落ちなかったが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をスクリプトから実行することにする
スクリプト変更
前回作成したポップアップを出す部分
def popup(): #Windows画面にメッセージを出す
user32 = windll.user32
user32.MessageBoxA( 0, "Enemy Will Come Here!!", "Caution!!", 0x00000030)
下記のように変更
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
全体としてはこうなった
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()
以上で完了
求めていたおしゃれなポップアップが実現できた
複数クライアント対応
やり方を色々検討して候補を挙げてみた
- TCPからUDPに変えてブロードキャストにする
- 送信部分をマルチスレッドにする
- クラウドでごにょごにょしてうまくやる
1.のブロードキャスト化が簡単そうで、且つ、個々のIPアドレスをソースに書かなくてよくなるので試してみたが、どうにもこうにもなんとでもうまくいかず挫折した
悔しいのでそのうち誰かに聞くなりしてリベンジしたい
3.については、全体的な仕様を見直したり、クラウド選んで契約してとか手間がかかるので保留
不本意だが2.で、とりあえずは対応することにした
で、変更したのが下記
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を初めて触ったりしてテンションが上がって結構のめりこんだ
冬休みにクラウド化も試してみたい
あと、ほぼコピペなのでソースの中身はひどい内容なんだろうな、もう少しちゃんと調べながら作らないと身にならないので、少しずつでも精進していきたいと思う
指摘とか指導とかあれば、是非ともお願いします