wuhb il y a 2 ans
Parent
commit
b512e2fea3

+ 5 - 0
app/src/main/AndroidManifest.xml

@@ -64,6 +64,11 @@
         <activity
             android:name=".activity.ControlActivity"
             android:configChanges="keyboardHidden|screenSize" />
+
+        <service
+            android:name=".receiver.SocketService"
+            android:enabled="true"
+            android:exported="false" />
     </application>
 
 </manifest>

+ 34 - 1
app/src/main/java/com/qy/agv/activity/ControlActivity.java

@@ -4,8 +4,12 @@ import static com.qy.agv.util.Constant.CACHE_BIND_CONTROL;
 import static com.qy.agv.util.Constant.user;
 
 import android.annotation.SuppressLint;
+import android.content.ComponentName;
 import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
 import android.os.Bundle;
+import android.os.IBinder;
 import android.view.View;
 import android.widget.AdapterView;
 
@@ -18,6 +22,7 @@ import com.qy.agv.activity.model.TaskModel;
 import com.qy.agv.comm.BaseActivity;
 import com.qy.agv.comm.CacheService;
 import com.qy.agv.databinding.QyRobotBinding;
+import com.qy.agv.receiver.SocketService;
 import com.qy.agv.util.Constant;
 import com.qy.agv.util.DataUtil;
 import com.qy.agv.util.DateUtil;
@@ -46,6 +51,9 @@ public class ControlActivity extends BaseActivity {
     private QyRobotBinding binding;
     private RobotModel robotModel;
     private final Map<Integer, String> statusMap = new HashMap<Integer, String>();
+    public ServiceConnection sc;
+    public SocketService socketService;
+    private Intent socketIntent;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -148,7 +156,7 @@ public class ControlActivity extends BaseActivity {
        String bindRobotID = CacheService.getInstance(context).getCache(CACHE_BIND_CONTROL, "ROBOT_ID");
        if(!StringUtils.isEmpty(bindRobotID)){
            binding.robotNo.setText(bindRobotID);
-           parserRobot(bindRobotID);
+           parserRobot("02-" + bindRobotID);
        }
     }
 
@@ -179,11 +187,14 @@ public class ControlActivity extends BaseActivity {
                         if (rs.getBoolean("success")) {
                             Object data_o = rs.get("data");
                             robotModel = new Gson().fromJson(data_o.toString(), RobotModel.class);
+                            Constant.robotModel = robotModel;
+                            Constant.robotModel.setPort(Constant.SOCKET_PORT);
                             binding.robotNo.setText(robotModel.getRobotId());
                             Integer robot_status = robotModel.getRobotStatus();
                             binding.robotState.setText(statusMap.get(robot_status));
                             CacheService.getInstance(context).saveCache("BIND_CONTROL", "ROBOT_ID", robotModel.getRobotId());
                             ToastUtils.showToast(context, "绑定成功");
+                            bindSocketService();
                         }
                     }
                 } catch (JSONException e) {
@@ -261,6 +272,22 @@ public class ControlActivity extends BaseActivity {
         statusMap.put(5, "等待中");
     }
 
+    protected void bindSocketService() {
+        sc = new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
+                SocketService.SocketBinder binder = (SocketService.SocketBinder) iBinder;
+                socketService = binder.getService();
+            }
+            @Override
+            public void onServiceDisconnected(ComponentName componentName) {
+            }
+        };
+        socketIntent = new Intent(getApplicationContext(), SocketService.class);
+        startService(socketIntent);
+        bindService(socketIntent, sc, BIND_AUTO_CREATE);
+    }
+
     @Override
     protected String getCommonTopTitle() {
         return "单机控制";
@@ -274,5 +301,11 @@ public class ControlActivity extends BaseActivity {
     @Override
     protected void onDestroy() {
         super.onDestroy();
+        if(socketIntent != null) {
+            stopService(socketIntent);
+        }
+        if(sc!=null) {
+            unbindService(sc);
+        }
     }
 }

+ 5 - 0
app/src/main/java/com/qy/agv/activity/MainActivity.java

@@ -314,6 +314,11 @@ public class MainActivity extends BaseActivity {
             sendMsg[3] = barcode.split("-")[1];
             if(shelf!=null)shelf.setText(sendMsg[3]);
             return;
+        }else if(barcode.startsWith("05-")){
+            String loginName = barcode.split("-")[1];
+            String[] login_password = loginName.split(",");
+            checkToken(login_password[0], login_password[1]);
+            return;
         }else{
             ToastUtils.showToast(context, "无效码");
             return;

+ 9 - 0
app/src/main/java/com/qy/agv/activity/model/RobotModel.java

@@ -14,6 +14,7 @@ public class RobotModel {
     private Integer robotStatus;
     private String robotVersion;
     private String remark;
+    private Integer port;
 
     public String getRobotId() {
         return robotId;
@@ -118,4 +119,12 @@ public class RobotModel {
     public void setRemark(String remark) {
         this.remark = remark;
     }
+
+    public Integer getPort() {
+        return port;
+    }
+
+    public void setPort(Integer port) {
+        this.port = port;
+    }
 }

+ 339 - 0
app/src/main/java/com/qy/agv/receiver/SocketService.java

@@ -0,0 +1,339 @@
+package com.qy.agv.receiver;
+
+import static com.qy.agv.util.Constant.TIME_FORMATE;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Looper;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.qy.agv.util.Constant;
+import com.qy.agv.util.DateUtil;
+import com.qy.agv.util.StringUtils;
+
+import org.apache.log4j.Logger;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.ConnectException;
+import java.net.InetSocketAddress;
+import java.net.NoRouteToHostException;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.nio.charset.StandardCharsets;
+import java.util.Timer;
+import java.util.TimerTask;
+
+
+/**
+ * <p>
+ * socket连接服务
+ */
+public class SocketService extends Service {
+
+    /*socket*/
+    private Socket socket;
+    /*连接线程*/
+    private Thread connectThread;
+    private Timer timer = new Timer();
+    private OutputStream outputStream;
+
+    private final SocketBinder sockerBinder = new SocketBinder();
+    private TimerTask task;
+
+    /*默认重连*/
+    private boolean isReConnect = true;
+    private final Handler handler = new Handler(Looper.getMainLooper());
+    public static Logger mylog =Logger.getLogger(SocketService.class);
+    private final Intent intent = new Intent(Constant.RECEIVER_MSG);
+    private Long lastTime = 0L;
+    private int socket_port;
+
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return sockerBinder;
+    }
+
+    public class SocketBinder extends Binder {
+        /*返回SocketService 在需要的地方可以通过ServiceConnection获取到SocketService  */
+        public SocketService getService() {
+            return SocketService.this;
+        }
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        /*初始化socket*/
+        try {
+            if(Constant.robotModel != null
+                    && !StringUtils.isEmpty(Constant.robotModel.getRobotIp())) {
+                initSocket();
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    /*初始化socket*/
+    private void initSocket() {
+        if (socket == null && connectThread == null) {
+            connectThread = new Thread(new Runnable() {
+                @Override
+                public void run() {
+
+                    socket = new Socket();
+                    try {
+                        /*超时时间为2秒*/
+                        socket.connect(new InetSocketAddress(Constant.robotModel.getRobotIp(), Constant.robotModel.getPort()), 5000);
+                        /*连接成功的话  发送心跳包*/
+                        if (socket.isConnected()) {
+                            /*因为Toast是要运行在主线程的  这里是子线程  所以需要到主线程哪里去显示toast*/
+                            toastMsg("网络连接成功");
+                            System.out.println("==========注册信息==========");
+                            sendOrder("register:" + Constant.robotModel.getRobotId());
+                            /*发送心跳数据*/
+                            System.out.println("==========发送心跳==========");
+                            lastTime = System.currentTimeMillis();
+                            sendBeatData();
+
+                            new Thread(new Runnable() {
+                                @Override
+                                public void run() {
+                                    rec();
+                                }
+                            }).start();
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        if (e instanceof SocketTimeoutException) {
+                            mylog.error("连接超时,正在重连");
+                            showMsg("连接失败");
+                            try {
+                                Thread.sleep(1000);
+                            } catch (InterruptedException ex) {
+                                return;
+                            }
+                            releaseSocket();
+
+                        } else if (e instanceof NoRouteToHostException) {
+                            mylog.error("地址不存在,请检查");
+                            showMsg("连接失败");
+                            stopSelf();
+
+                        } else if (e instanceof ConnectException) {
+                            mylog.error("连接异常或被拒绝,请检查");
+                            showMsg("连接失败");
+                            try {
+                                Thread.sleep(5000);
+                            } catch (InterruptedException ex) {
+                                return;
+                            }
+                            releaseSocket();
+                        }
+                    }
+                }
+            });
+            /*启动连接线程*/
+            connectThread.start();
+        }
+    }
+
+    private void showMsg(String msg){
+//        intent.putExtra("msg", msg);
+//        intent.putExtra("json","");
+//        sendBroadcast(intent);
+    }
+
+    private void showCommand(String msg){
+        intent.putExtra("json", msg);
+        sendBroadcast(intent);
+    }
+
+    /*因为Toast是要运行在主线程的   所以需要到主线程哪里去显示toast*/
+    private void toastMsg(final String msg) {
+        handler.post(new Runnable() {
+            @Override
+            public void run() {
+                Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
+            }
+        });
+    }
+
+    public void sendToRobot(String toRobot, String msg){
+        msg = toRobot + ":" + msg;
+        sendOrder(msg);
+    }
+
+    public void sendToServer(String msg){
+        msg = "execute:" + msg;
+        sendOrder(msg);
+    }
+
+    /*发送数据*/
+    public void sendOrder(final String json) {
+        if (socket != null && socket.isConnected()) {
+            /*发送指令*/
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    try {
+                        tcpClient(json, 0);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }).start();
+        } else {
+            toastMsg("机器人连接错误,请重试");
+        }
+    }
+
+    /*定时发送数据*/
+    private void sendBeatData() {
+        if (timer == null) {
+            timer = new Timer();
+        }
+
+        if (task == null) {
+            task = new TimerTask() {
+                @Override
+                public void run() {
+                    try {
+                        outputStream = socket.getOutputStream();
+                        /*这里的编码方式根据你的需求去改*/
+                        long longTime = System.currentTimeMillis() - lastTime;
+                        if(longTime > 70000){
+                            releaseSocket();
+                        }
+                        String msg = "ping:" + DateUtil.getCurrDate(TIME_FORMATE);
+                        outputStream.write((msg+"\n").getBytes(StandardCharsets.UTF_8));
+                        outputStream.flush();
+                        showMsg("连接成功");
+                    } catch (Exception e) {
+                        /*发送失败说明socket断开了或者出现了其他错误*/
+                        toastMsg("连接断开,正在重连");
+                        showMsg("连接中断");
+                        /*重连*/
+                        releaseSocket();
+                        e.printStackTrace();
+                    }
+                }
+            };
+        }
+        timer.schedule(task, 0, 10000);
+    }
+
+    public void rec(){
+        try{
+            while (true) {
+                if(socket!=null && !socket.isInputShutdown()) {
+                    try {
+                        BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+                        String inMsg = in.readLine();//服务器返回的数据
+                        if (StringUtils.isEmpty(inMsg)) {
+                            socket = null;
+                            return;
+                        }
+                        inMsg = inMsg + System.getProperty("line.separator");
+                        inMsg = inMsg.replace("\n", "");
+                        if (inMsg.equals("pong")
+                                || inMsg.equals("ok")) {
+                            lastTime = System.currentTimeMillis();
+                            continue;
+                        }
+                        mylog.info("received: " + inMsg);
+                        if (!StringUtils.isEmpty(inMsg)) {
+                            showCommand(inMsg);
+                        }
+                    }catch (Exception ex){
+                        mylog.error(ex);
+                        ex.printStackTrace();
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public void tcpClient(String json, int flag){
+        try{
+            outputStream = socket.getOutputStream();
+            outputStream.write((json+"\n").getBytes(StandardCharsets.UTF_8));
+            outputStream.flush();
+            mylog.info("发送数据有效");
+        }catch (SocketException ex){
+            System.out.println("发送异常,重新连接网络");
+            releaseSocket();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /*释放资源*/
+    private void releaseSocket() {
+
+        if (task != null) {
+            task.cancel();
+            task = null;
+        }
+        if (timer != null) {
+            timer.purge();
+            timer.cancel();
+            timer = null;
+        }
+
+        if (outputStream != null) {
+            try {
+                outputStream.close();
+
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            outputStream = null;
+        }
+
+        if (socket != null) {
+            try {
+                socket.close();
+
+            } catch (IOException e) {
+            }
+            socket = null;
+        }
+
+        if (connectThread != null) {
+            connectThread = null;
+        }
+
+        /*重新初始化socket*/
+        if (isReConnect) {
+            initSocket();
+        }
+
+    }
+
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        Log.i("SocketService", "onDestroy");
+        isReConnect = false;
+        releaseSocket();
+    }
+}
+
+

+ 3 - 0
app/src/main/java/com/qy/agv/util/Constant.java

@@ -1,5 +1,6 @@
 package com.qy.agv.util;
 
+import com.qy.agv.activity.model.RobotModel;
 import com.qy.agv.activity.model.UserModel;
 
 public class Constant {
@@ -25,6 +26,8 @@ public class Constant {
     public static final String CACHE_LOGIN_KEY = "LOGIN";
     public static final String CACHE_BIND_CONTROL = "BIND_CONTROL";
     public static UserModel user;
+    public static RobotModel robotModel;
+    public static int SOCKET_PORT = 1128;
 
     public final static String LOG_IN = "blade-auth/oauth/token";
     public final static String PUSH_TASK = "blade-dispatchpool/scan/request";