缘由:因为带钥匙实在麻烦,市面上的智能锁虽好,但是有点小贵,于是我们就想着能不能自己做一个用手机语音助手加上自己搭的客户端和服务端加上电机,做一个简易版低成本的智能门锁。
功能及应用流程介绍:用户只需要用手机语音助手下达开关门指令(需要在手机端设置命令),门锁服务端接收到移动客户端发送的指令,发送指令给门锁客户端并发送网页反馈,门锁客户端接收服务端命令并驱动电机执行开关门。
话不多说,我们来看一下门锁服务端代码实现吧~
import os,sys
import socket,time
#定义命令函数
def order(data):
#将接收到的数据以“换行符”分割并放入列表之中
datalist = data.split("\n")
#下一行代码不能删,不用的时候就注释掉,用于检查datalist里面的元素
#print(datalist)
#遍历datalist,若遍历到移动端的特定指令元素(key)就执行相应的指令
for i in datalist:
if(i=='Upgrade-Insecure-Requests: 1\r'):
print("open the door for master")
#客户端发指令给门锁客户端
msg = 'open'
door_sock.send(msg.encode('gbk'))
#客户端给移动端发送网页反馈
http_response = """\
HTTP/1.1 200 OK
Hello, World!
"""
sock.sendall(http_response.encode("utf-8"))
sock.close()
break
if(i=='close'):
print("close the door for master")
break
#本地信息
HOST,PORT ='',4000
#创建socket用于服务移动客户端
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
#绑定
s.bind((HOST,PORT))
#设置服务对象数
s.listen(5)
#创建第二个socket用于服务门锁客户端
m = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
m.bind((HOST, 5000))
m.listen(5)
#等待门锁客户端连接
while True:
try:
print('Waiting for door_client connection...')
door_sock,door_addr = m.accept()
except:
continue
while True:
try:
recv_data = door_sock.recv(1024)
#接收门锁客户端发过来的信息以保证门锁客户端一直连接
#若收到的数据不为空
if recv_data:
print('Waiting for connection...')
#创建一个列表用于存放移动客户端发送的数据
datalist = [ ]
#等待移动客户端连接
sock,addr = s.accept()
print('Accept new connection from client')
#将移动客户端发送的数据存到变量data里
while True:
data = sock.recv(1024).decode()
order(data)
break
#若门锁服务端发送数据为空,关闭套接字并跳出循环再次尝试连接
else:
door_sock.close()
break
#若门锁服务端连接失败,关闭套接字并跳出循环再次尝试连接
except:
door_sock.close()
break
#关闭socket,结束进程
sock.close()
door_sock.close()
print('Connection from %s:%s closed.' % addr)
注意:门锁客户端需要一直给服务端发送信息以检测是否掉线,同时也需要一直接收客户端发送过来的指令,于是需要用到多线程。
简易门锁客户端搭建:
import socket
import threading
def send_date(socket_tcp_client): #发送数据
while True:
server_date = 'connected'
socket_tcp_client.send(server_date.encode("gbk")) #发数据,enconde为编码 gbk为编码方式
socket_tcp_client.close() #关闭套接字
def recv_date(socket_tcp_client): #接收数据
while True:
recv_date = socket_tcp_client.recv(1024) #接收信息,每次最大为1024
print("接收到的数据为:", recv_date.decode("gbk")) #decode为解码,gbk为解码方式
#下面需要加入判断语句执行驱动电机的开关门命令
def main():
socket_tcp_client=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #创建一个套接字
server_ip= '10.161.42.184'
server_port = 5000
server_addr=(server_ip,server_port)
socket_tcp_client.connect(server_addr)# 2.绑定连接
send_tcp_date=threading.Thread(target=send_date,args=(socket_tcp_client,)) #定义两个线程,分别为发送和接收
recv_tcp_date=threading.Thread(target=recv_date,args=(socket_tcp_client,))
send_tcp_date.start()
recv_tcp_date.start() #开启这两个线程
if __name__ =='__main__':
main()
移动端可用浏览器模拟
看一下运行效果:
大概就是这样的。
小白入门在代码书写上可能还不够简洁、不够优美,还需要继续努力…