반응형

안드로이드 부분(client)

 

activity_main.xml

더보기
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="8dp"
android:weightSum="5"
>
<LinearLayout
android:layout_weight="0.5"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
android:weightSum="2">
<Button
android:id="@+id/connectButton"
android:layout_width="match_parent"
android:layout_height="match_parent"

android:text="연결하기" />
</LinearLayout>

<LinearLayout
android:layout_weight="0.5"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
android:weightSum="2">
<!--
layout_weight="1" 높이
layout_height 높이
weightSum 세로줄


-->

<Button
android:id="@+id/motor00Button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4"
android:text="-" />

<ProgressBar
android:id="@+id/motor0ProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.2"
android:max="180"
android:progress="90"
/>

<Button
android:id="@+id/motor01Button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4"
android:text="+" />
</LinearLayout>

<LinearLayout
android:layout_weight="0.5"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
android:weightSum="2">

<Button
android:id="@+id/motor10Button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4"
android:text="-" />

<ProgressBar
android:id="@+id/motor1ProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.2"
android:max="180"
android:progress="90"
/>

<Button
android:id="@+id/motor11Button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4"

android:text="+" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"
android:orientation="horizontal"
android:weightSum="2">

<Button
android:id="@+id/motor20Button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4"

android:text="-" />

<ProgressBar
android:id="@+id/motor2ProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.2"
android:max="180"
android:progress="90"
/>

<Button
android:id="@+id/motor21Button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4"
android:text="+" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"
android:orientation="horizontal"
android:weightSum="2">

<Button
android:id="@+id/motor30Button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4"

android:text="-" />

<ProgressBar
android:id="@+id/motor3ProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.2"
android:max="180"
android:progress="90"
/>

<Button
android:id="@+id/motor31Button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4"
android:text="+" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"
android:orientation="horizontal"
android:weightSum="2">

<Button
android:id="@+id/motor40Button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4"

android:text="-" />

<ProgressBar
android:id="@+id/motor4ProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.2"
android:max="180"
android:progress="90"
/>

<Button
android:id="@+id/motor41Button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4"
android:text="+" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"
android:orientation="horizontal"
android:weightSum="2">

<Button
android:id="@+id/motor50Button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4"

android:text="-" />

<ProgressBar
android:id="@+id/motor5ProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.2"
android:max="180"
android:progress="90"
/>

<Button
android:id="@+id/motor51Button"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.4"
android:text="+" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"
android:orientation="horizontal">

<EditText
android:id="@+id/inputEditText"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1.5"
app:layout_constraintStart_toStartOf="parent"
tools:layout_editor_absoluteY="301dp" />

<Button
android:id="@+id/sendMsgButton"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.5"
android:text="Send" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.5"
android:orientation="horizontal">

<ScrollView
android:id="@+id/logView"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:id="@+id/logTextView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</ScrollView>


</LinearLayout>
</LinearLayout>

</android.support.constraint.ConstraintLayout>

 

 

 

 

 

MainActivity.java

package com.example.myapplication;


import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.net.Socket;
import java.util.Arrays;
import java.util.LinkedList;

//https://ginjo.tistory.com/2
public class MainActivity extends AppCompatActivity {

    Handler msghandler;
    Socket socket;

    private String ip = "127.0.0.1"; // IP 주소
    private int port = 41000; // PORT번호
    EditText inputText;
    TextView logText;
    int progressCheck;
    int motorCheck;
    ProgressBar motor0ProgressBar;
    ProgressBar motor1ProgressBar;
    ProgressBar motor2ProgressBar;
    ProgressBar motor3ProgressBar;
    ProgressBar motor4ProgressBar;
    ProgressBar motor5ProgressBar;


    //추가
    SocketClient client;
    ReceiveThread receive;
    SendThread send;


    @Override
    protected void onStop() {
        super.onStop();
        try {
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //메인쓰레드와 연결해줌
        msghandler = new Handler() {
            @Override
            public void handleMessage(Message hdmsg) {
                if (hdmsg.what == 1111) {
                    switch (progressCheck){
                        case 0:
                            motor0ProgressBar.setProgress(hdmsg.arg1);
                            break;
                        case 1:
                            motor1ProgressBar.setProgress(hdmsg.arg1);
                            break;
                        case 2:
                            motor2ProgressBar.setProgress(hdmsg.arg1);
                            break;
                        case 3:
                            motor3ProgressBar.setProgress(hdmsg.arg1);
                            break;
                        case 4:
                            motor4ProgressBar.setProgress(hdmsg.arg1);
                            break;
                        case 5:
                            motor5ProgressBar.setProgress(hdmsg.arg1);
                            break;
                        default:
                            break;
                    }

                }
            }
        };


        motor0ProgressBar=(ProgressBar)findViewById(R.id.motor0ProgressBar);
        motor1ProgressBar=(ProgressBar)findViewById(R.id.motor1ProgressBar);
        motor2ProgressBar=(ProgressBar)findViewById(R.id.motor2ProgressBar);
        motor3ProgressBar=(ProgressBar)findViewById(R.id.motor3ProgressBar);
        motor4ProgressBar=(ProgressBar)findViewById(R.id.motor4ProgressBar);
        motor5ProgressBar=(ProgressBar)findViewById(R.id.motor5ProgressBar);
        Button connectButton=(Button)findViewById(R.id.connectButton);
        Button motor00Button=(Button)findViewById(R.id.motor00Button);
        Button motor01Button=(Button)findViewById(R.id.motor01Button);
        Button motor10Button=(Button)findViewById(R.id.motor10Button);
        Button motor11Button=(Button)findViewById(R.id.motor11Button);
        Button motor20Button=(Button)findViewById(R.id.motor20Button);
        Button motor21Button=(Button)findViewById(R.id.motor21Button);
        Button motor30Button=(Button)findViewById(R.id.motor30Button);
        Button motor31Button=(Button)findViewById(R.id.motor31Button);
        Button motor40Button=(Button)findViewById(R.id.motor40Button);
        Button motor41Button=(Button)findViewById(R.id.motor41Button);
        Button motor50Button=(Button)findViewById(R.id.motor50Button);
        Button motor51Button=(Button)findViewById(R.id.motor51Button);



        inputText = (EditText) findViewById(R.id.inputEditText);
        Button sendMsgButton = (Button) findViewById(R.id.sendMsgButton);
        logText = (TextView)findViewById(R.id.logTextView);

        //motor0ProgressBar.setProgress(180);


        connectButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                client = new SocketClient(ip,port);
                progressCheck=0;
                //handler.sendEmptyMessage(0);
                //threadList.add(client);
                client.start();
            }
        });


        motor00Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //네트워킹 사용을 위해 스레드 사용해야됨
                send = new SendThread(socket,"00");
                progressCheck=0;
                send.start();
            }
        });
        motor01Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send = new SendThread(socket,"01");
                progressCheck=0;
                send.start();
            }
        });
        motor10Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send = new SendThread(socket,"10");
                progressCheck=1;
                send.start();
            }
        });
        motor11Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send = new SendThread(socket,"11");
                progressCheck=1;
                send.start();
            }
        });
        motor20Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send = new SendThread(socket,"20");
                progressCheck=2;
                send.start();
            }
        });
        motor21Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send = new SendThread(socket,"21");
                progressCheck=2;
                send.start();
            }
        });
        motor30Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send = new SendThread(socket,"30");
                progressCheck=3;
                send.start();
            }
        });
        motor31Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send = new SendThread(socket,"31");
                progressCheck=3;
                send.start();
            }
        });
        motor40Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send = new SendThread(socket,"40");
                progressCheck=4;
                send.start();
            }
        });
        motor41Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send = new SendThread(socket,"41");
                progressCheck=4;
                send.start();
            }
        });
        motor50Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send = new SendThread(socket,"50");
                progressCheck=5;
                send.start();
            }
        });
        motor51Button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                send = new SendThread(socket,"51");
                progressCheck=5;
                send.start();
            }
        });


    }




    ///////////////////////////////////////////////////////////////////////////////////////////////////
    //소켓연결
    class SocketClient extends Thread {
        boolean threadAlive;
        String ip;
        int port;

        InputStream inputStream = null;
        OutputStream outputStream = null;
        BufferedReader br = null;
        private DataOutputStream output = null;


        public SocketClient(String ip, int port) {
            threadAlive = true;
            this.ip = ip;
            this.port = port;
        }

        @Override
        public void run() {

            try {
                // 연결후 바로 ReceiveThread 시작
                socket = new Socket(ip, port);
                //inputStream = socket.getInputStream();
                output = new DataOutputStream(socket.getOutputStream());
                receive = new ReceiveThread(socket);
                //endian = new Endian();
                receive.start();

            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    //메시지 수신
    class ReceiveThread extends Thread {
        private Socket socket = null;
        DataInputStream input;


        public ReceiveThread(Socket socket) {
            this.socket = socket;
            try{
                input = new DataInputStream(socket.getInputStream());
            }catch(Exception e){
            }
        }

        public void run() {
            try {
                Log.d("=============", "받기전");
                while (input != null) {
                //int read;
                byte[] buffer = new byte[4];
                Arrays.fill(buffer,(byte)0);
                input.read(buffer);


                String bar=new String(buffer).replaceAll("\0","");

                Log.d("=============",  bar);
                Log.d("========",  Integer.toString(progressCheck));

                Message hdmsg = msghandler.obtainMessage();
                hdmsg.what = 1111;

                hdmsg.arg1 = Integer.parseInt(bar);
                msghandler.sendMessage(hdmsg);

                }
            } catch (IOException e) {
                e.printStackTrace();
            }catch(Exception e){

            }
        }
    }
    //메시지발신
    class SendThread extends Thread {
        private Socket socket;
        DataOutputStream output;
        String msg;

        public SendThread(Socket socket,String msg) {
            this.socket = socket;
            this.msg=msg;
            try {
                output = new DataOutputStream(socket.getOutputStream());

            } catch (Exception e) {
            }
        }

        public void run() {

            try {


                 output = new DataOutputStream(socket.getOutputStream());

                 output.writeUTF(msg);
                 //output.writeUTF(new String(msg).replaceAll("\0",""));

            } catch (IOException e) {
                e.printStackTrace();
            } catch (NullPointerException npe) {
                npe.printStackTrace();

            }
        }
    }




}

 

 

라즈베리파이 부분(server)

회로도

 

 

server.py

# -*-coding:utf-8-*-


import socketserver
import threading
import Adafruit_PCA9685
import struct

HOST = ''
PORT = 41000
lock = threading.Lock()  # syncronized 동기화 진행하는 스레드 생성
class ServoMotorManager():

    def __init__(self):
        # PWM 드라이버 사용을 위한 객체 생성
        self.robot_handle = Adafruit_PCA9685.PCA9685()
        self.servoMin = 150  # 서보모터 동작 최소 pulse 값
        self.servoMax = 550  # 서보모터 동작 최대 pulse 값
        # 주파수를 50hz로 지정
        self.robot_handle.set_pwm_freq(50)
        # 서모모터 동작 각도와 pulse 값을 맵핑시켜 주기위한 함수
        self.a_arm = 90
        self.b_arm = 90
        self.c_arm = 90
        self.d_arm = 90
        self.e_arm = 90
        self.f_arm = 90

    #서보모터 펄스
    def map(self,value, min_angle, max_angle, min_pulse, max_pulse):
        angle_range = max_angle - min_angle
        pulse_range = max_pulse - min_pulse
        scale_factor = float(angle_range) / float(pulse_range)
        return min_pulse + (value / scale_factor)

    # 서보모터 각도 이동을 위한 함수
    def set_angle(self,channel, angle):
        angle_range = 180 - 0
        pulse_range = 550 - 150
        scale_factor = float(angle_range) / float(pulse_range)
        pulse=int(150+(angle/scale_factor))
        self.robot_handle.set_pwm(channel, 0, pulse)

    def servoController(self,data):
        if not data:
            return -1
        print(data)
        if data[0] == '0':
            if data[1] == '0' and self.a_arm > 0:
                self.a_arm = self.a_arm - 10
            elif data[1] == '1' and self.a_arm < 180:
                self.a_arm = self.a_arm + 10
            self.set_angle(int(data[0]), self.a_arm)
            return self.a_arm
        elif data[0] == '1':
            if data[1] == '0' and self.b_arm > 0:
                self.b_arm = self.b_arm - 10
            elif data[1] == '1' and self.b_arm < 180:
                self.b_arm = self.b_arm + 10
            self.set_angle(int(data[0]), self.b_arm)
            return self.b_arm
        elif data[0] == '2':
            if data[1] == '0' and self.c_arm > 0:
                self.c_arm = self.c_arm - 10
            elif data[1] == '1' and self.c_arm < 180:
                self.c_arm = self.c_arm + 10
            self.set_angle(int(data[0]), self.c_arm)
            return self.c_arm
        elif data[0] == '3':
            if data[1] == '0' and self.d_arm > 0:
                self.d_arm = self.d_arm - 10
            elif data[1] == '1' and self.d_arm < 180:
                self.d_arm = self.d_arm + 10
            self.set_angle(int(data[0]), self.d_arm)
            return self.d_arm
        elif data[0] == '4':
            if data[1] == '0' and self.e_arm > 0:
                self.e_arm = self.e_arm - 10
            elif data[1] == '1' and self.e_arm < 180:
                self.e_arm = self.e_arm + 10
            self.set_angle(int(data[0]), self.e_arm)
            return self.e_arm
        elif data[0] == '5':
            if data[1] == '0' and self.f_arm > 0:
                self.f_arm = self.f_arm - 10
            elif data[1] == '1' and self.f_arm < 180:
                self.f_arm = self.f_arm + 10
            self.set_angle(int(data[0]), self.f_arm)
            return self.f_arm


#socketserver.BaseRequestHandler 이것은 모든 요청 처리기 객체의 슈퍼 클래스입니다. 아래에 주어진 인터페이스를 정의합니다. 구상 요청 처리기 서브 클래스는 새 handle() 메서드를 정의해야 하며, 다른 메서드를 재정의할 수 있습니다. 각 요청에 대해 서브 클래스의 새 인스턴스가 만들어집니다.
class MyTcpHandler(socketserver.BaseRequestHandler):
    #유저 관리하는 클래스

    servoMotorMan=ServoMotorManager()
    #이 함수는 요청을 서비스하는 데 필요한 모든 작업을 수행해야 합니다. 기본 구현은 아무것도 수행하지 않습니다. 몇 가지 인스턴스 어트리뷰트를 사용할 수 있습니다; 요청은 self.request로 제공됩니다; 클라이언트 주소는 self.client_address로 제공됩니다; 서버별 정보에 액세스해야 하는 경우를 위해 서버 인스턴스는 self.server로 제공됩니다.
    def handle(self):  # 클라이언트가 접속시 클라이언트 주소 출력
        print('[%s] 연결됨' % self.client_address[0])

        try:
            #username = self.registerUsername()#유저생성
            msg = self.request.recv(1024)
            #print(msg)
            msg=msg[2:4]
            print(msg)
            self.request.send(str(self.servoMotorMan.servoController(str(msg.decode()))).encode())
            #self.servoMotorMan.servoController(str(msg.decode()))
            while msg:
                msg = self.request.recv(1024)
                msg=msg[2:4]
                a=str(self.servoMotorMan.servoController(str(msg.decode())))
                print(a)
                self.request.send(a.encode())




        except Exception as e:
            print(e)

        print('[%s] 접속종료' % self.client_address[0])



#socketserver.TCPServer 클라이언트와 서버 간에 연속적인 데이터 스트림을 제공하는 인터넷 TCP 프로토콜을 사용합니다. bind_and_activate가 참이면, 생성자는 자동으로 server_bind()와 server_activate()를 호출하려고 시도합니다. 다른 매개 변수는 BaseServer 베이스 클래스로 전달됩니다.
#socketserver.ThreadingMixIn 비동기 동작을 지원
class ChatingServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
    pass


def runServer():
    print('+++ 채팅 서버를 시작합니다.')
    print('+++ 채텅 서버를 끝내려면 Ctrl-C를 누르세요.')
    #server.serve_forever 명시적인 shutdown() 요청이 있을 때까지 요청을 처리합니다. poll_interval 초마다 shutdown을 확인합니다. timeout 어트리뷰트를 무시합니다. 또한 service_actions()를 호출하는데, 서브 클래스나 믹스인이 주어진 서비스에 특정한 동작을 제공하기 위해 사용할 수 있습니다. 예를 들어, ForkingMixIn 클래스는 service_actions()를 사용하여 좀비 자식 프로세스를 정리합니다.
    try:
        server = ChatingServer((HOST, PORT), MyTcpHandler)
        server.serve_forever()
    except KeyboardInterrupt:
        print('--- 채팅 서버를 종료합니다.')
        server.shutdown()
        server.server_close()


runServer()

 

 

반응형
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기