自作ドアシステムのコード

Pythonを用いたドアシステムの開発。NFCカードを用いて認証を行う。認証に失敗したときは失敗した人物の写真を撮影し、Discordに送信する。認証できた場合は、サーボモーターを回転させて鍵の解錠・施錠をする。

開発環境
 Raspberry Pi4
 Genny
 サーボモーター(MG996R)
 Webカメラ(EMEET C960)
 NFCカードリーダー(RC-S380)
 ラズパイに接続するスクリーン、キーボード、マウス

importしたもの(pip install xxxのような)
使い方は、調べてください。
 datetime
 pigpiod
 binascii
 nfc
 discord
 siohttp
 cv2

main.py

import datetime
import os
import pigpio
import DoorTest

start = datetime.time(6,0,0)
end = datetime.time(14,23,0)
dt_now = datetime.datetime.now()
nowtime = dt_now.time()
cr = DoorTest.MyCardReader()
Print_I = False
while True:
  
    #最初に表示
    print(str(nowtime))
    #タッチ待ち
    cr.read_id()
    if Print_I == True and nowtime >= start and nowtime <end:
        #sys.stdout = open("DoorSystem.log", "a")
        print(str(nowtime) + "システム名:レーニン起動します")
        #sys.stdout = sys.__stdout__
        Print_I = False
    else:
        print("システムは停止いたしました")
        Print_I = True

後述のプログラムを動かすためのプログラム
DoorTest.pyを取得してファイル内の関数を実行している。

DoorTest.py

import pigpio
import sys
import binascii
import datetime
import json
import time
import nfc
SERVO_PIN = 18
pi = pigpio.pi()

def set_angle(angle):
	assert 0 <= angle <= 180. 
	pulse_width = (angle / 180) * (2500 - 500) + 500
	pi.set_servo_pulsewidth(SERVO_PIN, pulse_width)

class MyCardReader(object):
	def __init__(self):
		self.is_door_open = False

	def on_connect(self, tag):
		
		sys.stdout = open("DoorSystem.log", "a")
		idm = binascii.hexlify(tag._nfcid)
		print("Get IDm")
		dt_now = datetime.datetime.now()
		print(dt_now)
		start = datetime.time(6,0,0)
		end = datetime.time(14,23,0)
		now = dt_now.time()
		if now >= start and now <end:
			json_open = open('Pass_ID.json', 'r')
		else:
			json_open = open('Master.json', 'r')
		Pass_data = json.load(json_open)
		id_list = [obj["id"] for obj in Pass_data["user"]]
		PassData_list = Pass_data["user"]
		if str(idm) in id_list:
			if self.is_door_open:
				set_angle(95)
				time.sleep(1)
				message_door="施錠"
			else:
				set_angle (0)
				message_door="解錠"
			Name = [UserData["name"] for UserData in PassData_list if str(idm)==UserData["id"]]
			print ("同志" + Name[0] + "は認証されたユーザーです。ドアを" + message_door + "します。\n")    
			self.is_door_open= not self.is_door_open
		else:
			print ("認証されていないユーザーです。" + str(idm) + "\n")
			for a in range(1):
				import Camera
			
			sys.stdout = sys.__stdout__
		return True

	def read_id(self):
		clf = nfc.ContactlessFrontend('usb')
		try:
			clf.connect(rdwr={'on-connect': self.on_connect})
		finally:
			clf.close()

Pass_ID.jsonとMaster.jsonに入っている情報を元にNFCカード、Suicaの認証を行う。時間によって参照するファイルを変えることによってマスターキーを作成している。認証開始の時間はstartとendの()内の数字を変更することで変更できる。左から時、分、秒となっている。
例)(15 , 0 ,0 )→15時0分0秒
※Pass_ID.jsonには登録者全員を登録する。Master.jsonにはマスターキーとして使うカードを登録する。
IDmなどを登録する方法は後日アップする。
複数のusbケーブルを接続している場合は、usbのIDを入力する必要がある。clfの定義のところに入力する。
例)clf = nfc.ContactlessFrontend('usb: 000:000')
ログをファイルに出力しているため、ターミナルには表示されない。
サーボモーターの角度は個体差があるのでそれぞれの環境で調整してください。
set_angle( )の()内の数字を変更することで調整できる。

Camera.py

from discord import Webhook
import discord
import aiohttp
import asyncio
import cv2
import time
import datetime
import cv2 as cv

webhook_url = "discord_webhook_url"

#カメラで撮影用
camera = cv2.VideoCapture(0)
#タイトルの管理
id=0
count_number = 0

while count_number == 0:
	ret,frame =camera.read()
	motion_detected = False
	if not ret:
		break
	dt_now = datetime.datetime.now() #データを取得した時刻

    #ファイル名と、画像中に埋め込む日付時刻
	dt_format_string = dt_now.strftime('%Y-%m-%d %H:%M:%S') 

    # 動き検出していれば画像を保存する
	if 1+1 == 2:
		title="image"+str(id)+".jpeg"
		cv2.imwrite(title, frame)
		print(title)
		dt_now = datetime.datetime.now()
		
		#メッセージの詳細
		username = "守護天使"
		title = (dt_now.strftime('%Y年%m月%d日 %H:%M:%S'))
		description = "ID認証に失敗しました"
		color_hex = "ff0000"
		image_path = "image"+str(id)+".jpeg"
		pathid = "image"+str(id)+".jpeg"
		
		#discordに画像を送信する
		file = discord.File(image_path, filename="image"+str(id)+".jpeg")
		embed = discord.Embed(
			title=title, description=description, color=int(color_hex, 16)
		).set_image(url="attachment://"+pathid)
		async def foo():
			async with aiohttp.ClientSession() as session:
				webhookdata = Webhook.from_url(webhook_url, session=session)
				await webhookdata.send(username=username, embed=embed, file=file)
		asyncio.run(foo())
		
		#タイトルの変更
		id +=1
		count_number +=1
	
	key = cv2.waitKey(1)

	if key == 27:
		break

count_number -=1
print(count_number)

camera.release()
cv2.destroyAllWindows()

このコードはDiscordに画像を送信するためのもの。Door.pyの中で使用するコード。現状では一度しか作動しないため後日修正する。
discord_webhook_urlはDiscordのWebhook URL(そのまんま)を取得して入力する。これがないと画像を送信することができない。

この記事が気に入ったらサポートをしてみませんか?