匿名
未登录
登录
丢石头百科
搜索
查看“树莓派智能车AlphaBot教程11:Python 网络编程”的源代码
来自丢石头百科
名字空间
页面
讨论
更多
更多
页面选项
查看
查看源代码
历史
←
树莓派智能车AlphaBot教程11:Python 网络编程
因为以下原因,您没有权限编辑本页:
您所请求的操作仅限于该用户组的用户使用:
用户
您可以查看与复制此页面的源代码。
前面都是介绍通过web网页控制小车,这一章介绍通过App控制小车。 Python网络编程主要基于socket实现,socket在本质上与文件句柄、文件描述符、管道描述符等都是一个概念,都可以对其进行I/O处理。 什么是 Socket? Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。 好吧,说了你也不懂,直接上程序。新建一个serve.py文件,输入如下代码 python简单网络编程 服务端: 新建一个serve.py文件,输入如下代码 === cpp代码: ===<syntaxhighlight lang="python"> #!/usr/bin/python # -*- coding: UTF-8 -*- # file:server.py import socket s = socket.socket() # creat socket host = ‘192.168.8.1’ # set ip port = 2001 # Set port s.bind((host, port)) # Bind the port s.listen(5) # Wait for the client to connect while True: c, addr = s.accept() # Create a client connection. print 'connect address:', addr c.send('Hello World!') c.close() # Close the connection</syntaxhighlight> 分析: 程序中首先使用socket模块的socket()函数来创建一个socket对象。socket 对象可以通过调用其他函数来设置一个 socket 服务。通过调用 bind(hostname, port) 函数来指定服务的 port(端口)。 接着调用 socket 对象的 accept 方法。该方法等待客户端的连接,并返回 connection 对象,表示已连接到客户端。最后调用recv()接受客户端发送的字符,调用send()发送hello world给客户端并用close()关闭连接。 客户端: === cpp代码: ===<syntaxhighlight lang="python"> #!/usr/bin/python # -*- coding: UTF-8 -*- # file:client.py import socket s = socket.socket() # creat socket host = '192.168.8.1' # set ip port = 2001 # Set port s.connect((host, port)) # connect serve print s.recv(1024) # recieve data s.close() # Close the connection</syntaxhighlight> 分析: 程序中首先使创建一个socket对象。通过connect()函数连接到服务端。ip地址和port端口都需要和服务端设置一置。接着接收服务端发过来的数据并显示,最后断开连接。 现在打开两个终端,第一个终端先执行服务端server.py程序 sudo python server.py 第二个终端执行客户端clien.py程序 sudo python clien.py 此时第一个终端会显示如下信息。 connect address: ('192.168.10.235', 33788) 第二个终端会显示hello world Hello World! python多线程网络编程 上面介绍 的只是简单的网络编程,通过循环阻塞的方式等等客户端链接。而且不能多个客户端同时连接。 下面介绍通过多线程非阻塞的方式实现网络编程。 服务端 === cpp代码: ===<syntaxhighlight lang="python"> import SocketServer from SocketServer import StreamRequestHandler as SRH from time import ctime host = '192.168.8.1' port = 2001 addr = (host,port) class Servers(SRH): def handle(self): print 'got connection from ',self.client_address self.wfile.write('connection %s:%s at %s succeed!' % (host,port,ctime())) while True: data = self.request.recv(1024) if not data: break print data self.request.send(data) print 'server is running....' server = SocketServer.ThreadingTCPServer(addr,Servers) server.serve_forever() </syntaxhighlight> 分析: SocketServer是python网络编程的一个高级模块,ThreadingTCPServer实现的Soket服务器内部会为每个client创建一个"线程",该线程用来和客户端进行交换。类中必须定义一个handle的方法 (因为父类即SocketServer.BaseRequestHandler中的handle方法为空)。程序最后启动ThreadingTCPServer。 在handle方法中,程序线打印客户端地址,发送连接程序信息给客服端。最后不断接受客户端发来的信息显示并发送会给客户端。 客户端 === cpp代码: ===<syntaxhighlight lang="python"> from socket import * host = '192.168.8.1' port = 2001 bufsize = 1024 addr = (host,port) client = socket(AF_INET,SOCK_STREAM) client.connect(addr) while True: data = raw_input() if not data or data=='exit': break client.send('%s\r\n' % data) data = client.recv(bufsize) if not data: break print data.strip() client.close() </syntaxhighlight> 分析: 客户端程序和上面的程序类似,创建一个socket对象,并连接服务端,程序中将键盘输入的信息发送到服务端, 接受服务端发过来的数据 并显示。 首先打开第一个终端先执行服务端程序 sudo python server.py 第二个终端执行客户端程序 sudo python clien.py 此时第一个终端会显示如下信息。 connect address: ('192.168.10.235', 33788) 第二个终端输入字符串并按确定键服务端会显示接受到的信息。另外多开几个终端运行客户端程并发送信息,可以看到服务端同样会接收到信息,换局域网内其他ip地址一样可以和服务端通讯。 通过软件控制小车。 要现实软件控制小车,小车必须作为服务端,接受客户端发送过来的命令,然后做出相应的动作。 废话不多说,直接上程序。 === cpp代码: ===<syntaxhighlight lang="python"> import threading import SocketServer import RPi.GPIO as GPIO from SocketServer import StreamRequestHandler as SRH from AlphaBot import AlphaBot from PCA9685 import PCA9685 from time import ctime Ab = AlphaBot() pwm = PCA9685(0x40) pwm.setPWMFreq(50) BUZ = 4 GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(BUZ,GPIO.OUT) #Set the Horizontal servo parameters HPulse = 1500 #Sets the initial Pulse HStep = 0 #Sets the initial step length pwm.setServoPulse(0,HPulse) #Set the vertical servo parameters VPulse = 1500 #Sets the initial Pulse VStep = 0 #Sets the initial step length pwm.setServoPulse(1,VPulse) host = '192.168.10.235' port = 8000 addr = (host,port) def beep_on(): GPIO.output(BUZ,GPIO.HIGH) def beep_off(): GPIO.output(BUZ,GPIO.LOW) class Servers(SRH): def handle(self): global HStep,VStep print 'got connection from ',self.client_address self.wfile.write('connection %s:%s at %s succeed!' % (host,port,ctime())) while True: data = self.request.recv(1024) if not data: break if data == "Stop": HStep = 0 VStep = 0 Ab.stop() elif data == "Forward": Ab.forward() elif data == "Backward": Ab.backward() elif data == "TurnLeft": Ab.left() elif data == "TurnRight": Ab.right() elif data == "Up": VStep = -5 elif data == "Down": VStep = 5 elif data == "Left": HStep = 5 elif data == "Right": HStep = -5 elif data == "BuzzerOn": beep_on() elif data == "BuzzerOff": beep_off() else: value = 0 try: value = int(data) if(value >= 0 and value <= 100): print(value) Ab.setPWMA(value); Ab.setPWMB(value); except: print("Command error") print data #print "recv from ", self.client_address[0] self.request.send(data) def timerfunc(): global HPulse,VPulse,HStep,VStep,pwm if(HStep != 0): HPulse += HStep if(HPulse >= 2500): HPulse = 2500 if(HPulse <= 500): HPulse = 500 #set channel 2, the Horizontal servo pwm.setServoPulse(0,HPulse) if(VStep != 0): VPulse += VStep if(VPulse >= 2500): VPulse = 2500 if(VPulse <= 500): VPulse = 500 #set channel 3, the vertical servo pwm.setServoPulse(1,VPulse) global t #Notice: use global variable! t = threading.Timer(0.02, timerfunc) t.start() t = threading.Timer(0.02, timerfunc) t.setDaemon(True) t.start() print 'server is running....' server = SocketServer.ThreadingTCPServer(addr,Servers) server.serve_forever() </syntaxhighlight> 分析: ThreadingTCPServer实现的Soket服务器内部会为每个client创建一个"线程"。handle()方法中接受客户端发过来的信息,并判断是已定义的命令,如果是则完成相应的动作。timerfunc()为定时器任务,控制舵机的。前面章节已经介绍过。 手机打开App可以连接小车控制。 电脑端打开AlphaBot.exe程序,输入IP地址,mjpg-stream的端口号,小车Soket服务端的端口号, 点击Viedeo Connet连接视频,按键变绿色即连接成功,点击Cmd Connect,连接小车服务端。如果按键变绿则连接成功。左边的按键控制小车移动,右边按键控制摄像头舵机转动。 [[File:114203n7e9znrg3tqqa0nr.png]]
返回至
树莓派智能车AlphaBot教程11:Python 网络编程
。
导航
导航
首页
最近更改
随机页面
MediaWiki帮助
首页
首页
树莓派
主机
配件包
外壳
键鼠
电源
扩展板
显示屏
墨水屏
摄像模块
通信模块
继电器
电机驱动板
游戏机
产品分类
树莓派
Arduino
micro:bit
STM32
Espressif
WiFi模块
蓝牙模块
无线模块
LoRa模块
4G模块
GSM
GPRS
以太网
导航模块
北斗卫星
GPS
LCD
墨水屏
OLED
摄像头
USB模块
串口模块
RS232
RS485
CAN
传感器
温度模块
湿度模块
气压模块
继电器
电机模块
指纹模块
电平转换
音频模块
编程器
Wiki工具
Wiki工具
特殊页面
页面工具
页面工具
用户页面工具
更多
链入页面
相关更改
页面信息
页面日志