本帖最后由 kingwood 于 2017-2-13 20:59 编辑
先要把wifi热点搞起来,要改/etc/network/interface 其实network下面好多interfaces.xxx,照着改就行了 root@orangepizero:/etc/network# cat interfaces auto lo iface lo inet loopback
auto eth0 address 192.168.1.13 netmask 255.255.255.0 gateway 192.168.1.1
auto wlan0 iface wlan0 inet manual
auto br0 iface br0 inet static address 192.168.10.1 netmask 255.255.255.0 broadcast 192.168.10.255 bridge_ports wlan0 #hwaddress ether # will be added at first boot
改好后设置hostapd.conf, root@orangepizero:/etc/network# cat /etc/hostapd/hostapd.conf interface=/var/run/hostapd macaddr_acl=0 auth_algs=1 driver=nl80211 interface=wlan0 bridge=br0 hw_mode=g ieee80211n=1 channel=1 ssid=opi-zero macaddr_acl=0 auth_algs=1 ignore_broadcast_ssid=0 wpa=3 wpa_passphrase=876543210 wpa_key_mgmt=WPA-PSK wpa_pairwise=TKIP rsn_pairwise=CCMP
还要装dnsmasq,apt-get install dnsmasq即可。 #sudo vim /etc/dnsmasq.conf interface=wlan0 listen-address=192.168.10.1 #no-dhcp-interface= dhcp-range=192.168.10.50,192.168.10.150,12h server=/google/8.8.8.8
接下了重启,hostapd -B /etc/hostapd/hostapd.conf就有热点了。如果做路由还要做nat, iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE 在/etc/rc.local里面设置自启动,iptales 设置好nat。下面红色行。 #160;
server=/google/8.8.8.8
rc.local echo 1 > /proc/sys/net/ipv4/ip_forward iptables-restore < /etc/iptables.conf hostapd -B /etc/hostapd/hostapd.conf /usr/local/bin/mjpg_streamer -i "input_uvc.so" -o "output_http.so -p 8080 -w /dev/shm/" >/root/mjpg.log & ls /dev/ >/root/ls.log & python /root/www/https.py & #/root/py/air_quality.py >>/root/py/air.log & exit 0
接下里安装mjpg_streamer.安装好了后启动运行就能看到图片了。比motion要快。
摄像头传图做好了后就是控制。前面有人做过智能小车,直接gpio控制。我把zero当上位置。通过串口控制下位机。不想写远程控制软件了。直接用网页控制。但是网页控制要装好多东西,直接用python改了别人的简单的网页服务器。用网页控制,显示摄像头传来的画面。网页服务器接收命令,通过串口传给下位机。Https.py的逻辑是如果是正常的网页请求(不带参数),就给传给客户端index.html。如果是带参数的网页命令,解释命令,然后写入串口,同时回传命令数值,和命令类型。index.html里面的按钮通过ajax向https.py发送命令请求,请求的命令如果服务器有回应,那么就将该命令的最新数据显示出来,要不说明掉线了。
Mjpg_streamer自启动有点问题。
图片上传上去了,但是没有插入的选项,所以这次没有图片了。要看界面直接浏览器打开index.html就行了。源代码文件也传上去了,但是插入不了。我直接贴吧: https.py,index.html。这两个放一个文件夹。运行https.py然后浏览器访问就行。index.html是网页界面,需要html5支持。有些 手机浏览器好像不支持滑块。 https.py文件 ------------------------------------------------------------------------------------------------------------------- #!/usr/bin/python
# encoding:utf-8
import serial
import socket
import signal
import errno
import datetime
import fcntl
import struct
from time import sleep
import sys
reload(sys)
sys.setdefaultencoding("utf8")
def getip(ethname):
s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
return socket.inet_ntoa(fcntl.ioctl(s.fileno(), 0X8915, struct.pack('256s', ethname[:15]))[20:24])
def get_ip():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# doesn't even have to be reachable
s.connect(('10.255.255.255', 0))
IP = s.getsockname()[0]
except:
IP = '127.0.0.1'
finally:
s.close()
return IP
def bit16_2_bit8(a):
high=a>>8
low=a&0xff
return high,low
def get_cmd(s):
global dic
s=s.split(',')
print "get cmd:",s
s[1]=int(s[1]) #s[1] 1,0
s[2]=int(s[2]) #s[2] val
try:
last_val=dic[s[0]][1]
except Exception,ex:
return '',[]
flag=s[0]
print 'last_val:',last_val
dic[s[0]][1]=s[1]*last_val+s[2]
if dic[s[0]][1]>dic[s[0]][3]:
dic[s[0]][1]=dic[s[0]][3]
if dic[s[0]][1]
dic[s[0]][1]=dic[s[0]][2]
val=dic[s[0]][1]
if val<0:#为负值,说明是油门,需要改变,其中一个高位置1
val=dic[s[0]][3]+val+0x8000
cmd_lst=[dic[s[0]][0],val]
return flag,cmd_lst
def web2ser(cmd_lst,ser):
high,low=bit16_2_bit8(cmd_lst[1])
ser_lst=[0xff,0xff,cmd_lst[0],high,low]
print 'ser_lst:',ser_lst
begin = datetime.datetime.now()
for e in ser_lst:
ser.write(chr(e))
end = datetime.datetime.now()
print "run time:",end-begin
#ser.flushOutput()
def HttpResponse(header,whtml):
f = file(whtml)
contxtlist = f.readlines()
context = ''.join(contxtlist)
response = "%s %dnn%snn" % (header,len(context),context)
return response
def jsonRespose(header,lst):
#response="%s %dnn%snn"%(header,len(str(lst)),lst)
response="%snn%snn"%(header,lst)
print "json response:",response
return response
def sigIntHander(signo,frame):
print 'get signo# ',signo
global runflag
runflag = False
global lisfd
lisfd.shutdown(socket.SHUT_RD)
dic={'t':[1,0,-1023,1023],'y':[2,1500,500,2500],'p':[3,1500,500,2500],'i':[]} #'t'油门,'t':[1,0,-1023,1023],后面的数组1是写给下位机的命令类型,0是存在服务器的油门数值,-1023,1023是油门信号的范围
#y,p是两个舵机y是水平,p是垂直。'y':[2,1500,500,2500] 2是写个下位机的命令类型,1500是存在服务器的数值,舵机初始是中位1500.500和2500是舵机信号的最大最小值
#strHost = getip('wlan0')
strHost =get_ip()
if '127.0.0.1'==strHost:
print "network unwork"
strHost=getip('br0') #lan ip
strHost=getip('br0') #wifi 热点的ip
print strHost
HOST = strHost #socket.inet_pton(socket.AF_INET,strHost)
PORT = 80 #webserver的端口
httpheader = '''
HTTP/1.1 200 OK
Context-Type: text/html
Server: python
Context-Length: ''' jsonheader='''
HTTP/1.1 200 OK
Content-type: application/json
'''
lisfd = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
lisfd.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #address reused
lisfd.bind((HOST, PORT))
lisfd.listen(2)
ser=serial.Serial('/dev/ttyS1',9600)
signal.signal(signal.SIGINT,sigIntHander)
runflag = True
while runflag:
try:
confd,addr = lisfd.accept()
except socket.error as e:
if e.errno == errno.EINTR:
print 'get a except EINTR'
else:
raise
continue
if runflag == False:
break;
data = confd.recv(1024)
if not data: #没有传来数据,继续
print "no data"
continue
lst=data.split("n") #有数据传来,解释
#print "data[0]:",lst[0]
lst=lst[0].split(' ')
arg=lst[1][1:] #得到传来的参数
#print "connect by ",addr
#print "arg:",arg
if not arg: #没有参数,说明请求的是整个网页index.html
confd.send(HttpResponse(httpheader,'index.html'))
elif arg!="favicon.ico":#有参数的请求,过滤掉 favicon.ico请求filter favicon.ico request
flag,cmd_lst=get_cmd(arg) #处理参数,得到写入命令参数
if not cmd_lst: #有命令
print "no such command:",arg
confd.send(jsonRespose(jsonheader,[])) #发送json数据给客服端
continue
web2ser(cmd_lst,ser) #写入命令道下位机
print "response json:",cmd_lst
confd.send(jsonRespose(jsonheader,dic[flag][0:2]))#不能用cmd_lst因为油门可能为负值,get_cmd处理了
confd.close()
else:
print 'runflag#',runflag
ser.close()
lisfd.close()
print 'runflag#1',runflag
print 'Done'
-----------------------------------------------------------
https.py结束 下面是index.html -----------------------------------------------------------
function sendSer(order,val_type,val,name){ //order:'t','y','p' 那个舵机,或油门的标志,val_type:0,1增量或者直接的数字,val传输的数字,name html ID,显示接收webserver返回数字的html 元素名字
var link="./"+order+","+val_type+","+val;
ajax(link,function(str){
json_lst=eval(str);
document.getElementById("show_"+name).value=json_lst[1];
if(name=="throttle")//从slider直接读取的数字,如果是油门的数据,需要反向
document.getElementById(name).value=-1*json_lst[1];
else
document.getElementById(name).value=json_lst[1];
});
}
function send_cmd(name,order){ //从slider直接读取的数字,如果是油门的数据,需要反向
var num=document.getElementById(name);
var val=num.value;
if(name=="throttle")
val=val*-1;
if(name.slice(0,5)=="show_")
name=name.slice(5);
sendSer(order,0,val,name);
}
function ajax(url, fnSucc, fnFaild){
//1.创建对象
var oAjax = null;
if(window.XMLHttpRequest){
oAjax = new XMLHttpRequest();
}else{
oAjax = new ActiveXObject("Microsoft.XMLHTTP");
}
//2.连接服务器
oAjax.open('GET', url, true); //open(方法, url, 是否异步)
//3.发送请求
oAjax.send();
//4.接收返回
oAjax.onreadystatechange = function(){ //OnReadyStateChange事件
if(oAjax.readyState == 4){ //4为完成
if(oAjax.status == 200){ //200为成功
fnSucc(oAjax.responseText)
}else{
if(fnFaild){
fnFaild();
}
}
}
};
}
function ajax(url, fnSucc, fnFaild){
//1.创建对象
var oAjax = null;
if(window.XMLHttpRequest){
oAjax = new XMLHttpRequest();
}else{
oAjax = new ActiveXObject("Microsoft.XMLHTTP");
}
//2.连接服务器
oAjax.open('GET', url, true); //open(方法, url, 是否异步)
//3.发送请求
oAjax.send();
//4.接收返回
oAjax.onreadystatechange = function(){ //OnReadyStateChange事件
if(oAjax.readyState == 4){ //4为完成
if(oAjax.status == 200){ //200为成功
fnSucc(oAjax.responseText)
}else{
if(fnFaild){
fnFaild();
}
}
}
};
}
function change(name,show){
var num=document.getElementById(name);
var location=document.getElementById(show);
if(name=="throttle")
location.value=num.value*-1;
else
location.value=num.value
}
|