简单WiFi控制小车系统(树莓派+python+web控制界面)

简介: 好丑😂 对不对 ,不过反正可以蛇皮走位就行。 蛇皮走位演示视频: 只需要 一个 index.html 和Index.py 就可以实现 简单WiFi 控制小车。你需要准备的有

网络异常,图片无法展示
|

好丑😂 对不对 ,不过反正可以蛇皮走位就行。

蛇皮走位演示视频: 手机QQ视频_20190105152514.mp4_免费高速下载|百度网盘-分享无限制

只需要 一个 index.html  和Index.py 就可以实现 简单WiFi 控制小车。

你需要准备的有

 python 环境

bottle 库

安装bottle命令

pip install bottle

网络异常,图片无法展示
|

树莓派控制界面(web客户端)

index.html源码

<!DOCTYPE html><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>遥控树莓派</title><linkhref="http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"rel="stylesheet"media="screen"><scriptsrc="http://cdn.staticfile.org/jquery/2.2.4/jquery.min.js"></script><styletype="text/css">#front {
margin-left: 55px;
margin-bottom: 3px;
        }
#rear{
margin-top: 3px;
margin-left: 55px;
        }
.btn{
background: #62559f;
            }
</style><script>$(function(){
$("button").click(function(){
$.post("/cmd",this.id,function(data,status){});
            });
        });
</script></head><body><divid="container"class="container"><div><buttonid="front"class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-up"></button></div><div><buttonid='leftFront'class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-left"></button><buttonid='stop'class="btn btn-lg btn-primary glyphicon glyphicon-stop"></button><buttonid='rightFront'class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-right"></button></div><div><buttonid='rear'class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-down"></button></div><div><buttonid='leftRear'class="btn btn-lg btn-primary glyphicon">左后转</button><buttonid='rightRear'class="btn btn-lg btn-primary glyphicon">右后转</button></div></div><scriptsrc="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script></body></html>

js脚本解释:

<script>$(function(){
$("button").click(function(){
$.post("/cmd",this.id,function(data,status){});
//表示 按钮对应的id值 会被传入树莓派服务器中,就如同 你在树莓派的命令行(cmd)中输入 id 的值            });
        });
</script>

树莓派小车控制程序(web服务端)

index.py 源码

#!/usr/bin/env python3# -*- coding:utf-8 -*-frombottleimportget,post,run,request,templateimportRPi.GPIOasGPIOimporttimeimportsys####  定义Car类classCar(object):
def__init__(self):
self.enab_pin= [5,6,13,19]
####  self.enab_pin是使能端的pinself.inx_pin= [21,22,23,24]
####  self.inx_pin是控制端in的pinself.RightAhead_pin=self.inx_pin[0]
self.RightBack_pin=self.inx_pin[1]
self.LeftAhead_pin=self.inx_pin[2]
self.LeftBack_pin=self.inx_pin[3]
####  分别是右轮前进,右轮退后,左轮前进,左轮退后的pinself.setup()
####  setup函数初始化端口defsetup(self):
print ("begin setup ena enb pin")
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
forpininself.enab_pin: 
GPIO.setup(pin,GPIO.OUT)
GPIO.output(pin,GPIO.HIGH)
####  初始化使能端pin,设置成高电平pin=Noneforpininself.inx_pin:
GPIO.setup(pin,GPIO.OUT)
GPIO.output(pin,GPIO.LOW)
####  初始化控制端pin,设置成低电平print ("setup ena enb pin over")
####  fornt函数,小车前进deffront(self):
self.setup()
GPIO.output(self.RightAhead_pin,GPIO.HIGH)
GPIO.output(self.LeftAhead_pin,GPIO.HIGH)
####  leftFront函数,小车左拐弯defleftFront(self):
self.setup()
GPIO.output(self.RightAhead_pin,GPIO.HIGH)
####  rightFront函数,小车右拐弯defrightFront(self):
self.setup()
GPIO.output(self.LeftAhead_pin,GPIO.HIGH)
####  rear函数,小车后退defrear(self):
self.setup()
GPIO.output(self.RightBack_pin,GPIO.HIGH)
GPIO.output(self.LeftBack_pin,GPIO.HIGH)
####  leftRear函数,小车左退defleftRear(self):
self.setup()
GPIO.output(self.RightBack_pin,GPIO.HIGH)
####  rightRear函数,小车右退defrightRear(self):
self.setup()
GPIO.output(self.LeftBack_pin,GPIO.HIGH)
####  定义main主函数defmain(status):
car=Car()
ifstatus=="front":
car.front()
elifstatus=="leftFront":
car.leftFront()
elifstatus=="rightFront":
car.rightFront()
elifstatus=="rear":
car.rear()
elifstatus=="leftRear":
car.leftRear()
elifstatus=="rightRear":
car.rightRear()
elifstatus=="stop":
car.setup()      
@get("/")
defindex():
returntemplate("index")
@post("/cmd")
defcmd():
adss=request.body.read().decode()
print("按下了按钮:"+adss)
main(adss)
return"OK"run(host="0.0.0.0")

web服务端 实际就这点代码, 主要是 bottle 库的强大,(实际控制的小车的代码 根据自己的需求改就行了)

frombottleimportget,post,run,request,template@get("/")
defindex():
returntemplate("index") 
#### 这个是 客户端请求 服务端就发给一个 index.html 控制界面给客户端@post("/cmd")
defcmd():
adss=request.body.read().decode()#### 接收到 客户端 发过来的数据print("按下了按钮:"+adss)
main(adss)  #### 传值到主函数 实现对应功能return"OK"run(host="0.0.0.0")  #### 开启服务端

运行 index.py 开启服务器:

网络异常,图片无法展示
|

然后打开浏览器(手机浏览器也可以但必须在同一个局域网内) 输入 树莓派的ip

我的是 http://192.168.191.4:8080

有可能 打开比较慢  10分钟内吧 😁(我第一次打开 就用了好久 都以为没有成功)

网络异常,图片无法展示
|

手机端输入ip

网络异常,图片无法展示
|

在后台可以查看到相应的操作日志

网络异常,图片无法展示
|

当然如果你有更为复杂的需求,可以采用 websocket 的方式,下面奉上代码

先运行服务端代码 car.py,然后再 运行 car.html

 car.py 代码

#coding=utf8importstruct, socket, sysimporthashlibimportthreading, randomimporttimefrombase64importb64encode, b64decodeimportRPi.GPIOasGPIOimportsysGPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(17,GPIO.OUT)
p=GPIO.PWM(17,600)
p_pin=35p.start(p_pin)
####  定义Car类classCar(object):
def__init__(self):
self.inx_pin= [19,26,5,6]
####  self.inx_pin是控制端in的pinself.RightAhead_pin=self.inx_pin[0]
self.LeftAhead_pin=self.inx_pin[1]
self.RightBack_pin=self.inx_pin[2]
self.LeftBack_pin=self.inx_pin[3]
####  分别是右轮前进,左轮前进,右轮退后,左轮退后的pinself.RightP_pin=17self.LeftP_pin=27self.setup()
####  setup函数初始化端口defsetup(self):
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
####  初始化使能端pin,设置成高电平pin=Noneforpininself.inx_pin:
GPIO.setup(pin,GPIO.OUT)
GPIO.output(pin,GPIO.LOW)
####  初始化控制端pin,设置成低电平print ("setup ena enb pin over")
####  fornt函数,小车前进deffront(self):
self.setup()
GPIO.output(self.RightAhead_pin,GPIO.HIGH)
GPIO.output(self.LeftAhead_pin,GPIO.HIGH)
####  leftFront函数,小车左拐弯defleftFront(self):
self.setup()
GPIO.output(self.RightAhead_pin,GPIO.HIGH)
####  rightFront函数,小车右拐弯defrightFront(self):
self.setup()
GPIO.output(self.LeftAhead_pin,GPIO.HIGH)
####  rear函数,小车后退defrear(self):
self.setup()
GPIO.output(self.RightBack_pin,GPIO.HIGH)
GPIO.output(self.LeftBack_pin,GPIO.HIGH)
####  leftRear函数,小车左退defleftRear(self):
self.setup()
GPIO.output(self.RightBack_pin,GPIO.HIGH)
####  rightRear函数,小车右退defrightRear(self):
self.setup()
GPIO.output(self.LeftBack_pin,GPIO.HIGH)
####  定义main主函数defmain(status):
car=Car()
ifstatus=="front":
car.front()
elifstatus=="leftFront":
car.leftFront()
elifstatus=="rightFront":
car.rightFront()
elifstatus=="rear":
car.rear()
elifstatus=="leftRear":
car.leftRear()
elifstatus=="rightRear":
car.rightRear()
elifstatus=="stop":
car.setup()      
#p.stop()elifstatus=="q1":
p.ChangeDutyCycle(35)
elifstatus=="q2":
p.ChangeDutyCycle(50)
elifstatus=="q3":
p.ChangeDutyCycle(75)
elifstatus=="q4":
p.ChangeDutyCycle(90)
elifstatus=="q5":
p.ChangeDutyCycle(100)
##socketconnectionlist= {}
defdecode(data):
ifnotlen(data):
returnFalse# 用数据包的第二个字节,与127作与位运算,拿到前七位。length=data[1] &127# 这七位在数据头部分成为payload,如果payload等于126,就要再扩展2个字节。# 如果等于127,就要再扩展8个字节。# 如果小于等于125,那它就占这一个字节。iflength==126:
extend_payload_len=data[2:4]
mask=data[4:8]
decoded=data[8:]
eliflength==127:
extend_payload_len=data[2:10]
mask=data[10:14]
decoded=data[14:]
else:
extend_payload_len=Nonemask=data[2:6]
decoded=data[6:]
byte_list=bytearray()
print(mask)
print(decoded)
# 当payload确定之后,再往后数4个字节,这4个字节成为masking key,再之后的内容就是接收到的数据部分。# 数据部分的每一字节都要和masking key作异或位运算,得出来的结果就是真实的数据内容。foriinrange(len(decoded)):
chunk=decoded[i] ^mask[i%4]
byte_list.append(chunk)
new_str=str(byte_list, encoding="utf-8")
print(new_str)
returnnew_strdefencode(data):  
data=str.encode(data)
head=b'\x81'iflen(data) <126:
head+=struct.pack('B', len(data))
eliflen(data) <=0xFFFF:
head+=struct.pack('!BH', 126, len(data))
else:
head+=struct.pack('!BQ', 127, len(data))
returnhead+datadefsendMessage(message):
globalconnectionlistforconnectioninconnectionlist.values():
connection.send(encode(message))
defdeleteconnection(item):
globalconnectionlistdelconnectionlist['connection'+item]
classWebSocket(threading.Thread):
GUID="258EAFA5-E914-47DA-95CA-C5AB0DC85B11"def__init__(self,conn,index,name,remote, path="/"):
threading.Thread.__init__(self)
self.conn=connself.index=indexself.name=nameself.remote=remoteself.path=pathself.buffer=""defrun(self):
print('Socket%s Start!'%self.index)
headers= {}
self.handshaken=FalsewhileTrue:
try: 
ifself.handshaken==False:
print ('Socket%s Start Handshaken with %s!'% (self.index,self.remote))
self.buffer+=bytes.decode(self.conn.recv(1024))
ifself.buffer.find('\r\n\r\n') !=-1:
header, data=self.buffer.split('\r\n\r\n', 1)
forlineinheader.split("\r\n")[1:]:
key, value=line.split(": ", 1)
headers[key] =valueheaders["Location"] = ("ws://%s%s"%(headers["Host"], self.path))
key=headers['Sec-WebSocket-Key']
token=b64encode(hashlib.sha1(str.encode(str(key+self.GUID))).digest())
handshake="HTTP/1.1 101 Switching Protocols\r\n"\
"Upgrade: websocket\r\n"\
"Connection: Upgrade\r\n"\
"Sec-WebSocket-Accept: "+bytes.decode(token)+"\r\n"\
"WebSocket-Origin: "+str(headers["Origin"])+"\r\n"\
"WebSocket-Location: "+str(headers["Location"])+"\r\n\r\n"self.conn.send(str.encode(str(handshake)))
self.handshaken=Trueprint('Socket%s Handshaken with %s success!'%(self.index, self.remote))
sendMessage('Welcome, '+self.name+' !')
else:
msg=decode(self.conn.recv(1024))
main(msg)
ifmsg=='quit':
print ('Socket%s Logout!'% (self.index))
nowTime=time.strftime('%H:%M:%S',time.localtime(time.time()))
sendMessage('%s %s say: %s'% (nowTime, self.remote, self.name+' Logout'))                  
deleteconnection(str(self.index))
self.conn.close()
breakelse:
#print('Socket%s Got msg:%s from %s!' % (self.index, msg, self.remote))nowTime=time.strftime('%H:%M:%S',time.localtime(time.time()))
sendMessage('%s %s say: %s'% (nowTime, self.remote, msg))       
self.buffer=""exceptExceptionase:
self.conn.close()
classWebSocketServer(object):
def__init__(self):
self.socket=Nonedefbegin(self):
print( 'WebSocketServer Start!')
self.socket=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.bind(("172.19.8.102", 8081))
self.socket.listen(50)
globalconnectionlisti=0whileTrue:
connection, address=self.socket.accept()
username=address[0]     
newSocket=WebSocket(connection,i,username,address)
newSocket.start()
connectionlist['connection'+str(i)]=connectioni=i+1if__name__=="__main__":
server=WebSocketServer()
server.begin()

car.html  代码:

<!DOCTYPE html><htmllang="zh-cn"><head><metahttp-equiv="Content-Type"content="text/html; charset=utf-8"/><metaname="viewport"content="width=device-width, initial-scale=1.0"><title>遥控树莓派</title><linkhref="http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"rel="stylesheet"media="screen"><scriptsrc="http://cdn.staticfile.org/jquery/2.2.4/jquery.min.js"></script><styletype="text/css">#front {
margin-left: 55px;
margin-bottom: 3px;
        }
#rear{
margin-top: 3px;
margin-left: 55px;
        }
.btn{
background: #62559f;
            }
</style><script>varsocket;
functioninit() {
varhost="ws://192.168.1.111:8081/";
try {
socket=newWebSocket(host);
socket.onopen=function () {
                };
socket.onmessage=function () {
                };
socket.onclose=function () {
                };
            }
catch (ex) {
            }
        }
functionsend(msg) {
try {
socket.send(msg);
            } catch (ex) {
            }
        }
window.onbeforeunload=function () {
try {
socket.send('quit');
socket.close();
socket=null;
            }
catch (ex) {
            }
        };
</script></head><bodyonload="init()"><divid="container"class="container"><div><buttonid="front"class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-up"onclick="send('front')"></button></div><div><buttonid='leftFront'class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-left"onclick="send('leftFront')"></button><buttonid='stop'class="btn btn-lg btn-primary glyphicon glyphicon-stop"onclick="send('stop')"></button><buttonid='rightFront'class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-right"onclick="send('rightFront')"></button></div><divstyle="height:50px;"><buttonid='rear'class="btn btn-lg btn-primary glyphicon glyphicon-circle-arrow-down"onclick="send('rear')"></button></div><divstyle="height:20px;"></div><divstyle="height:50px;"><buttonid='leftRear'class="btn btn-lg btn-primary glyphicon"onclick="send('leftRear')">左后转</button><buttonid='rightRear'class="btn btn-lg btn-primary glyphicon"onclick="send('rightRear')">右后转</button></div><divstyle="height:20px;"></div><divstyle="height:50px;"><buttonid='q1'class="btn btn-lg btn-primary glyphicon"onclick="send('q1')">P1</button><buttonid='q2'class="btn btn-lg btn-primary glyphicon"onclick="send('q2')">P2</button><buttonid='q3'class="btn btn-lg btn-primary glyphicon"onclick="send('q3')">P3</button><divstyle="height:20px;"></div><buttonid='q4'class="btn btn-lg btn-primary glyphicon"onclick="send('q4')">P4</button><buttonid='q5'class="btn btn-lg btn-primary glyphicon"onclick="send('q5')">P5</button></div></div><scriptsrc="//cdn.bootcss.com/bootstrap/3.3.5/js/bootstrap.min.js"></script></body></html>

注意: host 端口号要匹配哦

相关实践学习
Serverless极速搭建Hexo博客
本场景介绍如何使用阿里云函数计算服务命令行工具快速搭建一个Hexo博客。
目录
相关文章
|
19天前
|
机器学习/深度学习 传感器 存储
使用 Python 实现智能地震预警系统
使用 Python 实现智能地震预警系统
105 61
|
3天前
|
弹性计算 数据管理 数据库
从零开始构建员工管理系统:Python与SQLite3的完美结合
本文介绍如何使用Python和Tkinter构建一个图形界面的员工管理系统(EMS)。系统包括数据库设计、核心功能实现和图形用户界面创建。主要功能有查询、添加、删除员工信息及统计员工数量。通过本文,你将学会如何结合SQLite数据库进行数据管理,并使用Tkinter创建友好的用户界面。
从零开始构建员工管理系统:Python与SQLite3的完美结合
|
11天前
|
存储 消息中间件 缓存
构建互联网高性能WEB系统经验总结
构建互联网高性能WEB系统经验总结
|
7天前
|
机器学习/深度学习 数据采集 存储
使用Python实现智能农业灌溉系统的深度学习模型
使用Python实现智能农业灌溉系统的深度学习模型
45 6
|
8天前
|
负载均衡 监控 算法
论负载均衡技术在Web系统中的应用
【11月更文挑战第4天】在当今高并发的互联网环境中,负载均衡技术已经成为提升Web系统性能不可或缺的一环。通过有效地将请求分发到多个服务器上,负载均衡不仅能够提高系统的响应速度和处理能力,还能增强系统的可扩展性和稳定性。本文将结合我参与的一个实际软件项目,从项目概述、负载均衡算法原理以及实际应用三个方面,深入探讨负载均衡技术在Web系统中的应用。
36 2
|
11天前
|
机器学习/深度学习 数据采集 算法框架/工具
使用Python实现智能生态系统监测与保护的深度学习模型
使用Python实现智能生态系统监测与保护的深度学习模型
41 4
|
22天前
|
机器学习/深度学习 API 计算机视觉
基于Python_opencv人脸录入、识别系统(应用dlib机器学习库)(下)
基于Python_opencv人脸录入、识别系统(应用dlib机器学习库)(下)
18 2
|
22天前
|
Python
Python实现系统基础信息
Python实现系统基础信息
28 0
|
25天前
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
86 3
|
6天前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
79 44