通过手机端APP建立网络连接
public void Connect(){
new Thread(new Runnable() {
@Override
public void run() {
try {
s = new Socket(ip, port); //手机的IP地址和通信的端口号
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
在手机端APP给树莓派发送指令
public void SendCommand(String command){
new Thread(new Runnable() {
@Override
public void run() {
// showToast("!!!!!!!!!!");
try{
// s.connect(new InetSocketAddress(ip, port), 6000);
while(flag == 1) {
s.setSendBufferSize(1000);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
out.write(command);
out.flush();
Thread.sleep(100);
}
}catch (Exception e){
e.printStackTrace();
}
}
}).start();
}
通过按动手机APP上的按键来实现对摄像头的转动
public void onClick(View v) {
int id = v.getId();
switch(id){
case R.id.buttonCamUp:
up.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
//按住向上的按键,就控制摄像头向上转动
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
flag = 1;
SendCommand("up");
}
if(motionEvent.getAction() == MotionEvent.ACTION_UP){
flag = 0;
}
return false;
}
});
break;
case R.id.buttonCamDown:
down.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
//按住向下的按键,就控制摄像头向下转动
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
flag = 1;
SendCommand("down");
}
if(motionEvent.getAction() == MotionEvent.ACTION_UP){
flag = 0;
}
return false;
}
});
break;
case R.id.buttonCamRight:
right.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
//按住向右的按键,就控制摄像头向右转动
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
flag = 1;
SendCommand("right");
}
if(motionEvent.getAction() == MotionEvent.ACTION_UP){
flag = 0;
}
return false;
}
});
break;
case R.id.buttonCamLeft:
left.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
//按住向左的按键,就控制摄像头向左转动
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
flag = 1;
SendCommand("left");
}
if(motionEvent.getAction() == MotionEvent.ACTION_UP){
flag = 0;
}
return false;
}
});
break;
case R.id.buttonOpen:
//按下连接按钮与树莓派进行网络连接
Connect();
startReceiveThread();
break;
case R.id.buttonClose:
//关闭网络连接
try {
s.close();
} catch (IOException e) {
e.printStackTrace();
}
ss.close();
finish();
break;
case R.id.buttonSure:
buttonSure.setOnTouchListener(new View.OnTouchListener(){
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
flag = 1;
SendCommand("sure");
// imgView.setImageResource(R.drawable.touxiang);
}
if(motionEvent.getAction() == MotionEvent.ACTION_UP){
flag = 0;
}
return false;
}
});
break;
}
}
树莓派接收手机端的指令
def tcpCon():
host = "192.168.43.114"
port = 2025
print('localhost ip :' + host)
tcpServer = socket.socket()
tcpServer.bind((host, port))
# tcpServer.setblocking(0) # Set unblock mode
tcpServer.listen(5)
(client, addr) = tcpServer.accept()
print('accept the client!')
print(addr)
while True:
# client.setblocking(0)
data = client.recv(1024) //接收指令
data = bytes.decode(data) //将接收到的指令进行解码
cameraAction(data) //通过接收指令让摄像头转动
print(data) //打印接收的指令
判断接收的指令并让摄像头转动
def cameraAction(command):
global servo1_face_track, servo2_face_track, key
if command == "sure":
key = 1
elif command == "up" and servo1_face_track >= 520://如果是up命令并且在限位角度区间内
key = 0 //让舵机进行转动,带动摄像头向上转动
servo1_face_track = servo1_face_track - 20 //底层封装的控制舵机工作的函数
PWMServo.setServo(1, servo1_face_track, 20)
PWMServo.setServo(2, servo2_face_track, 20)
elif command == "down" and servo1_face_track <= 1780: //向下转动
key = 0
servo1_face_track = servo1_face_track + 20
PWMServo.setServo(1, servo1_face_track, 20)
PWMServo.setServo(2, servo2_face_track, 20)
elif command == "left" and servo2_face_track <= 2480: //向左转动
key = 0
servo2_face_track = servo2_face_track + 20
PWMServo.setServo(1, servo1_face_track, 20)
PWMServo.setServo(2, servo2_face_track, 20)
elif command == "right" and servo2_face_track >= 520: //向右转动
key = 0
servo2_face_track = servo2_face_track - 20
PWMServo.setServo(1, servo1_face_track, 20)
PWMServo.setServo(2, servo2_face_track, 20)
将摄像头捕捉到的画面回传给手机端APP
HOST = '10.134.184.98'
PORT = 5051
WIDTH = 320
HEIGHT = 240
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # enable broadcast
server.connect((HOST, PORT))
print('now starting to send frames...')
try:
image = frame
frameOpencvDnn = cv2.resize(frame, (160, 120), interpolation=cv2.INTER_CUBIC)
frameHeight = frameOpencvDnn.shape[0]
frameWidth = frameOpencvDnn.shape[1]
blob = cv2.dnn.blobFromImage(frameOpencvDnn, 1, (150, 150), [104, 117, 123], False, False)
result, imgencode = cv2.imencode('.jpg', image, [cv2.IMWRITE_JPEG_QUALITY, 60])
# print(len(imgencode))
print(key)
server.sendall(imgencode)
手机端接收回传的画面
public void startReceiveThread(){
new Thread(){
@Override
public void run() {
try{
ss=new DatagramSocket(5051);
// ss.setSoTimeout(1);
while(true) {
// Message message=new Message();
// message.what=1;
// message.obj=R.drawable.touxiang;
// updateUIHandler.sendMessage(message);
byte[] data = new byte[65536];
DatagramPacket packet = new DatagramPacket(data, data.length);
ss.receive(packet);
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, packet.getLength());
Message message=new Message();
message.what=1;
message.obj=bitmap;
updateUIHandler.sendMessage(message);
// sendFrameToActivity(bitmap);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
public static final int TOAST_TEXT=1;
public static final int CLOSE_OR_SHUTDOWN=2;
public static final int UPDATE_IMAGEVIEW=3;
@SuppressLint("HandlerLeak")
public static Handler updateUIHandler= new Handler(Looper.myLooper()){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case 1:
((OpenActivity)context).imgView.setImageBitmap((Bitmap)msg.obj);
break;
default:
break;
}
}
};
public void sendFrameToActivity(Bitmap bitmap){
Message message=new Message();
message.what=OpenActivity.UPDATE_IMAGEVIEW;
message.obj=bitmap;
updateUIHandler.sendMessage(message);
}
实现效果