Forráskód Böngészése

<使用风尚版转换盒>

weizhengliang 4 éve
szülő
commit
11b563bee5
38 módosított fájl, 1826 hozzáadás és 89 törlés
  1. 1 1
      .gitignore
  2. 1 0
      AmDemo_R/src/com/vvsip/ansip/IVvsipService.java
  3. 11 0
      AmDemo_R/src/com/vvsip/ansip/VvsipService.java
  4. 1 0
      SerialPortLibrary/.gitignore
  5. 45 0
      SerialPortLibrary/build.gradle
  6. 17 0
      SerialPortLibrary/proguard-rules.pro
  7. 9 0
      SerialPortLibrary/src/main/AndroidManifest.xml
  8. 9 0
      SerialPortLibrary/src/main/cpp/CMakeLists.txt
  9. 167 0
      SerialPortLibrary/src/main/cpp/SerialPort.c
  10. 30 0
      SerialPortLibrary/src/main/cpp/SerialPort.h
  11. 48 0
      SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/Device.java
  12. 54 0
      SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/Driver.java
  13. 47 0
      SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/SerialPort.java
  14. 66 0
      SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/SerialPortFinder.java
  15. 219 0
      SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/SerialPortManager.java
  16. 20 0
      SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/listener/OnOpenSerialPortListener.java
  17. 23 0
      SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/listener/OnSerialPortDataListener.java
  18. 81 0
      SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/thread/SerialPortReadThread.java
  19. 3 0
      SerialPortLibrary/src/main/res/values/strings.xml
  20. 2 2
      app/build.gradle
  21. 1 0
      app/src/main/AndroidManifest.xml
  22. 5 11
      app/src/main/java/com/wdkl/tradition/MyApplication.java
  23. 81 50
      app/src/main/java/com/wdkl/tradition/TraditionActivity.java
  24. 2 0
      app/src/main/java/com/wdkl/tradition/common/Constants.java
  25. 3 4
      app/src/main/java/com/wdkl/tradition/service/APPService.java
  26. 5 0
      app/src/main/java/com/wdkl/tradition/service/IDebugInfoListner.java
  27. 5 0
      app/src/main/java/com/wdkl/tradition/service/ISerialPortListener.java
  28. 138 0
      app/src/main/java/com/wdkl/tradition/service/SerialModel.java
  29. 642 0
      app/src/main/java/com/wdkl/tradition/service/SerialPortService.java
  30. 61 0
      app/src/main/java/com/wdkl/tradition/service/SerialSignalTypeEnum.java
  31. 6 6
      app/src/main/java/com/wdkl/tradition/util/AnalysisUdpUtil.java
  32. 1 2
      app/src/main/java/com/wdkl/tradition/util/AutoRebootUtil.java
  33. 3 3
      app/src/main/java/com/wdkl/tradition/util/SerialPortSendUtil.java
  34. 8 2
      app/src/main/java/com/wdkl/tradition/util/SipUtil/SipHelperUtil.java
  35. 8 0
      app/src/main/java/com/wdkl/tradition/util/StringUtils.java
  36. 1 6
      app/src/main/java/com/wdkl/tradition/util/UdpHelper.java
  37. 1 1
      app/src/main/res/values/strings.xml
  38. 1 1
      settings.gradle

+ 1 - 1
.gitignore

@@ -7,5 +7,5 @@
 /build
 /captures
 .externalNativeBuild
-
+/.idea/
 /AmDemo_R/build/

+ 1 - 0
AmDemo_R/src/com/vvsip/ansip/IVvsipService.java

@@ -19,6 +19,7 @@ public interface IVvsipService {
 	public void initiateOutgoingCall(String target,String macStr);
     public void addListener(IVvsipServiceListener listener); 
     public void removeListener(IVvsipServiceListener listener);
+    public void clearListener();
     public void setAudioNormalMode();
     public void setAudioInCallMode();
     public void setSpeakerModeOff();

+ 11 - 0
AmDemo_R/src/com/vvsip/ansip/VvsipService.java

@@ -130,6 +130,17 @@ public class VvsipService extends Service implements IVvsipService {
 	}
 
 	@Override
+	public void clearListener() {
+		if (mListeners != null) {
+			synchronized (mListeners) {
+				Log.i(mTag, "mListeners -> clearListener");
+				mListeners.clear();
+				Log.i(mTag, "mListeners <- clearListener");
+			}
+		}
+	}
+
+	@Override
 	public void onCreate() {
 		Log.i(mTag, "lifecycle // onCreate");
 		neighborsList = new ArrayList<VvsipNeighbor>();

+ 1 - 0
SerialPortLibrary/.gitignore

@@ -0,0 +1 @@
+/build

+ 45 - 0
SerialPortLibrary/build.gradle

@@ -0,0 +1,45 @@
+apply plugin: 'com.android.library'
+
+android {
+    compileSdkVersion 25
+    buildToolsVersion '25.0.3'
+
+    defaultConfig {
+        minSdkVersion 16
+        targetSdkVersion 25
+        versionCode 1
+        versionName "1.0"
+        externalNativeBuild {
+            cmake {
+                arguments '-DANDROID_TOOLCHAIN=clang'
+            }
+        }
+
+        ndk {
+            abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
+        }
+
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+
+    externalNativeBuild {
+        cmake {
+            path "src/main/cpp/CMakeLists.txt"
+        }
+    }
+}
+
+dependencies {
+    compile fileTree(dir: 'libs', include: ['*.jar'])
+    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
+        exclude group: 'com.android.support', module: 'support-annotations'
+    })
+    compile 'com.android.support.constraint:constraint-layout:1.0.2'
+    testCompile 'junit:junit:4.12'
+
+}

+ 17 - 0
SerialPortLibrary/proguard-rules.pro

@@ -0,0 +1,17 @@
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in D:\Android\sdk/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the proguardFiles
+# directive in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}

+ 9 - 0
SerialPortLibrary/src/main/AndroidManifest.xml

@@ -0,0 +1,9 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.kongqw.serialportlibrary">
+
+    <application android:allowBackup="true" android:label="@string/app_name"
+        android:supportsRtl="true">
+
+    </application>
+
+</manifest>

+ 9 - 0
SerialPortLibrary/src/main/cpp/CMakeLists.txt

@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 3.4.1)
+
+add_library(SerialPort SHARED
+            SerialPort.c)
+
+# Include libraries needed for libserial_port lib
+target_link_libraries(SerialPort
+                      android
+                      log)

+ 167 - 0
SerialPortLibrary/src/main/cpp/SerialPort.c

@@ -0,0 +1,167 @@
+/*
+ * Copyright 2009-2011 Cedric Priscal
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <termios.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <jni.h>
+
+#include "SerialPort.h"
+
+#include "android/log.h"
+static const char *TAG="serial_port";
+#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO,  TAG, fmt, ##args)
+#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
+#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)
+
+static speed_t getBaudrate(jint baudrate)
+{
+	switch(baudrate) {
+	case 0: return B0;
+	case 50: return B50;
+	case 75: return B75;
+	case 110: return B110;
+	case 134: return B134;
+	case 150: return B150;
+	case 200: return B200;
+	case 300: return B300;
+	case 600: return B600;
+	case 1200: return B1200;
+	case 1800: return B1800;
+	case 2400: return B2400;
+	case 4800: return B4800;
+	case 9600: return B9600;
+	case 19200: return B19200;
+	case 38400: return B38400;
+	case 57600: return B57600;
+	case 115200: return B115200;
+	case 230400: return B230400;
+	case 460800: return B460800;
+	case 500000: return B500000;
+	case 576000: return B576000;
+	case 921600: return B921600;
+	case 1000000: return B1000000;
+	case 1152000: return B1152000;
+	case 1500000: return B1500000;
+	case 2000000: return B2000000;
+	case 2500000: return B2500000;
+	case 3000000: return B3000000;
+	case 3500000: return B3500000;
+	case 4000000: return B4000000;
+	default: return -1;
+	}
+}
+
+/*
+ * Class:     android_serialport_SerialPort
+ * Method:    open
+ * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
+ */
+JNIEXPORT jobject JNICALL Java_com_kongqw_serialportlibrary_SerialPort_open
+  (JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags)
+{
+	int fd;
+	speed_t speed;
+	jobject mFileDescriptor;
+
+	/* Check arguments */
+	{
+		speed = getBaudrate(baudrate);
+		if (speed == -1) {
+			/* TODO: throw an exception */
+			LOGE("Invalid baudrate");
+			return NULL;
+		}
+	}
+
+	/* Opening device */
+	{
+		jboolean iscopy;
+		const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);
+		LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags);
+		fd = open(path_utf, O_RDWR | flags);
+		LOGD("open() fd = %d", fd);
+		(*env)->ReleaseStringUTFChars(env, path, path_utf);
+		if (fd == -1)
+		{
+			/* Throw an exception */
+			LOGE("Cannot open port");
+			/* TODO: throw an exception */
+			return NULL;
+		}
+	}
+
+	/* Configure device */
+	{
+		struct termios cfg;
+		LOGD("Configuring serial port");
+		if (tcgetattr(fd, &cfg))
+		{
+			LOGE("tcgetattr() failed");
+			close(fd);
+			/* TODO: throw an exception */
+			return NULL;
+		}
+
+		cfmakeraw(&cfg);
+		cfsetispeed(&cfg, speed);
+		cfsetospeed(&cfg, speed);
+
+		if (tcsetattr(fd, TCSANOW, &cfg))
+		{
+			LOGE("tcsetattr() failed");
+			close(fd);
+			/* TODO: throw an exception */
+			return NULL;
+		}
+	}
+
+	/* Create a corresponding file descriptor */
+	{
+		jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor");
+		jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "<init>", "()V");
+		jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor", "I");
+		mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor);
+		(*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint)fd);
+	}
+
+	return mFileDescriptor;
+}
+
+/*
+ * Class:     cedric_serial_SerialPort
+ * Method:    close
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_kongqw_serialportlibrary_SerialPort_close
+  (JNIEnv *env, jobject thiz)
+{
+	jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);
+	jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor");
+
+	jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd", "Ljava/io/FileDescriptor;");
+	jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I");
+
+	jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);
+	jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);
+
+	LOGD("close(fd = %d)", descriptor);
+	close(descriptor);
+}
+

+ 30 - 0
SerialPortLibrary/src/main/cpp/SerialPort.h

@@ -0,0 +1,30 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+/* Header for class android_serialport_api_SerialPort */
+
+#ifndef _Included_qingwei_kong_serialportlibrary_SerialPort
+#define _Included_qingwei_kong_serialportlibrary_SerialPort
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Class:     android_serialport_api_SerialPort
+ * Method:    open
+ * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
+ */
+JNIEXPORT jobject JNICALL Java_com_kongqw_serialportlibrary_SerialPort_open
+  (JNIEnv *, jclass, jstring, jint, jint);
+
+/*
+ * Class:     android_serialport_api_SerialPort
+ * Method:    close
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_com_kongqw_serialportlibrary_SerialPort_close
+  (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif

+ 48 - 0
SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/Device.java

@@ -0,0 +1,48 @@
+package com.kongqw.serialportlibrary;
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * Created by Kongqw on 2017/11/13.
+ * Device
+ */
+
+public class Device implements Serializable{
+
+    private static final String TAG = Device.class.getSimpleName();
+
+    private String name;
+    private String root;
+    private File file;
+
+    public Device(String name, String root, File file) {
+        this.name = name;
+        this.root = root;
+        this.file = file;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getRoot() {
+        return root;
+    }
+
+    public void setRoot(String root) {
+        this.root = root;
+    }
+
+    public File getFile() {
+        return file;
+    }
+
+    public void setFile(File path) {
+        this.file = file;
+    }
+}

+ 54 - 0
SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/Driver.java

@@ -0,0 +1,54 @@
+package com.kongqw.serialportlibrary;
+
+import android.util.Log;
+
+import java.io.File;
+import java.util.ArrayList;
+
+/**
+ * Created by Kongqw on 2017/11/13.
+ * Driver
+ */
+
+public class Driver {
+
+    private static final String TAG = Driver.class.getSimpleName();
+
+    private String mDriverName;
+    private String mDeviceRoot;
+
+    public Driver(String name, String root) {
+        mDriverName = name;
+        mDeviceRoot = root;
+    }
+
+    public ArrayList<File> getDevices() {
+        ArrayList<File> devices = new ArrayList<>();
+        File dev = new File("/dev");
+
+        if (!dev.exists()) {
+            Log.i(TAG, "getDevices: " + dev.getAbsolutePath() + " 不存在");
+            return devices;
+        }
+        if (!dev.canRead()) {
+            Log.i(TAG, "getDevices: " + dev.getAbsolutePath() + " 没有读取权限");
+            return devices;
+        }
+
+        File[] files = dev.listFiles();
+
+        int i;
+        for (i = 0; i < files.length; i++) {
+            if (files[i].getAbsolutePath().startsWith(mDeviceRoot)) {
+                Log.d(TAG, "Found new device: " + files[i]);
+                devices.add(files[i]);
+            }
+        }
+        return devices;
+    }
+
+    public String getName() {
+        return mDriverName;
+    }
+
+}

+ 47 - 0
SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/SerialPort.java

@@ -0,0 +1,47 @@
+package com.kongqw.serialportlibrary;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.IOException;
+
+public class SerialPort {
+
+    static {
+        System.loadLibrary("SerialPort");
+    }
+
+    private static final String TAG = SerialPort.class.getSimpleName();
+
+    /**
+     * 文件设置最高权限 777 可读 可写 可执行
+     *
+     * @param file 文件
+     * @return 权限修改是否成功
+     */
+    boolean chmod777(File file) {
+        if (null == file || !file.exists()) {
+            // 文件不存在
+            return false;
+        }
+        try {
+            // 获取ROOT权限
+            Process su = Runtime.getRuntime().exec("/system/bin/su");
+            // 修改文件属性为 [可读 可写 可执行]
+            String cmd = "chmod 777 " + file.getAbsolutePath() + "\n" + "exit\n";
+            su.getOutputStream().write(cmd.getBytes());
+            if (0 == su.waitFor() && file.canRead() && file.canWrite() && file.canExecute()) {
+                return true;
+            }
+        } catch (IOException | InterruptedException e) {
+            // 没有ROOT权限
+            e.printStackTrace();
+        }
+        return false;
+    }
+
+    // 打开串口
+    protected native FileDescriptor open(String path, int baudRate, int flags);
+
+    // 关闭串口
+    protected native void close();
+}

+ 66 - 0
SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/SerialPortFinder.java

@@ -0,0 +1,66 @@
+package com.kongqw.serialportlibrary;
+
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.util.ArrayList;
+
+public class SerialPortFinder {
+
+    private static final String TAG = SerialPortFinder.class.getSimpleName();
+    private static final String DRIVERS_PATH = "/proc/tty/drivers";
+    private static final String SERIAL_FIELD = "serial";
+
+    public SerialPortFinder() {
+        File file = new File(DRIVERS_PATH);
+        boolean b = file.canRead();
+        Log.i(TAG, "SerialPortFinder: file.canRead() = " + b);
+    }
+
+    /**
+     * 获取 Drivers
+     *
+     * @return Drivers
+     * @throws IOException IOException
+     */
+    private ArrayList<Driver> getDrivers() throws IOException {
+        ArrayList<Driver> drivers = new ArrayList<>();
+        LineNumberReader lineNumberReader = new LineNumberReader(new FileReader(DRIVERS_PATH));
+        String readLine;
+        while ((readLine = lineNumberReader.readLine()) != null) {
+            String driverName = readLine.substring(0, 0x15).trim();
+            String[] fields = readLine.split(" +");
+            if ((fields.length >= 5) && (fields[fields.length - 1].equals(SERIAL_FIELD))) {
+                Log.d(TAG, "Found new driver " + driverName + " on " + fields[fields.length - 4]);
+                drivers.add(new Driver(driverName, fields[fields.length - 4]));
+            }
+        }
+        return drivers;
+    }
+
+    /**
+     * 获取串口
+     *
+     * @return 串口
+     */
+    public ArrayList<Device> getDevices() {
+        ArrayList<Device> devices = new ArrayList<>();
+        try {
+            ArrayList<Driver> drivers = getDrivers();
+            for (Driver driver : drivers) {
+                String driverName = driver.getName();
+                ArrayList<File> driverDevices = driver.getDevices();
+                for (File file : driverDevices) {
+                    String devicesName = file.getName();
+                    devices.add(new Device(devicesName, driverName, file));
+                }
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return devices;
+    }
+}

+ 219 - 0
SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/SerialPortManager.java

@@ -0,0 +1,219 @@
+package com.kongqw.serialportlibrary;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.util.Log;
+
+import com.kongqw.serialportlibrary.listener.OnOpenSerialPortListener;
+import com.kongqw.serialportlibrary.listener.OnSerialPortDataListener;
+import com.kongqw.serialportlibrary.thread.SerialPortReadThread;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * Created by Kongqw on 2017/11/13.
+ * SerialPortManager
+ */
+
+public class SerialPortManager extends SerialPort {
+
+    private static final String TAG = SerialPortManager.class.getSimpleName();
+    private FileInputStream mFileInputStream;
+    private FileOutputStream mFileOutputStream;
+    private FileDescriptor mFd;
+    private OnOpenSerialPortListener mOnOpenSerialPortListener;
+    private OnSerialPortDataListener mOnSerialPortDataListener;
+
+    private HandlerThread mSendingHandlerThread;
+    private Handler mSendingHandler;
+    private SerialPortReadThread mSerialPortReadThread;
+
+    /**
+     * 打开串口
+     *
+     * @param device   串口设备
+     * @param baudRate 波特率
+     * @return 打开是否成功
+     */
+    public boolean openSerialPort(File device, int baudRate) {
+
+        Log.i(TAG, "openSerialPort: " + String.format("打开串口 %s  波特率 %s", device.getPath(), baudRate));
+
+        // 校验串口权限
+        if (!device.canRead() || !device.canWrite()) {
+            boolean chmod777 = chmod777(device);
+            if (!chmod777) {
+                Log.i(TAG, "openSerialPort: 没有读写权限");
+                if (null != mOnOpenSerialPortListener) {
+                    mOnOpenSerialPortListener.onFail(device, OnOpenSerialPortListener.Status.NO_READ_WRITE_PERMISSION);
+                }
+                return false;
+            }
+        }
+
+        try {
+            mFd = open(device.getAbsolutePath(), baudRate, 0);
+            mFileInputStream = new FileInputStream(mFd);
+            mFileOutputStream = new FileOutputStream(mFd);
+            Log.i(TAG, "openSerialPort: 串口已经打开 " + mFd);
+            if (null != mOnOpenSerialPortListener) {
+                mOnOpenSerialPortListener.onSuccess(device);
+            }
+            // 开启发送消息的线程
+            startSendThread();
+            // 开启接收消息的线程
+            startReadThread();
+            return true;
+        } catch (Exception e) {
+            e.printStackTrace();
+            if (null != mOnOpenSerialPortListener) {
+                mOnOpenSerialPortListener.onFail(device, OnOpenSerialPortListener.Status.OPEN_FAIL);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 关闭串口
+     */
+    public void closeSerialPort() {
+
+        if (null != mFd) {
+            close();
+            mFd = null;
+        }
+        // 停止发送消息的线程
+        stopSendThread();
+        // 停止接收消息的线程
+        stopReadThread();
+
+        if (null != mFileInputStream) {
+            try {
+                mFileInputStream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            mFileInputStream = null;
+        }
+
+        if (null != mFileOutputStream) {
+            try {
+                mFileOutputStream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            mFileOutputStream = null;
+        }
+
+        mOnOpenSerialPortListener = null;
+
+        mOnSerialPortDataListener = null;
+    }
+
+    /**
+     * 添加打开串口监听
+     *
+     * @param listener listener
+     * @return SerialPortManager
+     */
+    public SerialPortManager setOnOpenSerialPortListener(OnOpenSerialPortListener listener) {
+        mOnOpenSerialPortListener = listener;
+        return this;
+    }
+
+    /**
+     * 添加数据通信监听
+     *
+     * @param listener listener
+     * @return SerialPortManager
+     */
+    public SerialPortManager setOnSerialPortDataListener(OnSerialPortDataListener listener) {
+        mOnSerialPortDataListener = listener;
+        return this;
+    }
+
+    /**
+     * 开启发送消息的线程
+     */
+    private void startSendThread() {
+        // 开启发送消息的线程
+        mSendingHandlerThread = new HandlerThread("mSendingHandlerThread");
+        mSendingHandlerThread.start();
+        // Handler
+        mSendingHandler = new Handler(mSendingHandlerThread.getLooper()) {
+            @Override
+            public void handleMessage(Message msg) {
+                byte[] sendBytes = (byte[]) msg.obj;
+
+                if (null != mFileOutputStream && null != sendBytes && 0 < sendBytes.length) {
+                    try {
+                        mFileOutputStream.write(sendBytes);
+                        if (null != mOnSerialPortDataListener) {
+                            mOnSerialPortDataListener.onDataSent(sendBytes);
+                        }
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        };
+    }
+
+    /**
+     * 停止发送消息线程
+     */
+    private void stopSendThread() {
+        mSendingHandler = null;
+        if (null != mSendingHandlerThread) {
+            mSendingHandlerThread.interrupt();
+            mSendingHandlerThread.quit();
+            mSendingHandlerThread = null;
+        }
+    }
+
+    /**
+     * 开启接收消息的线程
+     */
+    private void startReadThread() {
+        mSerialPortReadThread = new SerialPortReadThread(mFileInputStream) {
+            @Override
+            public void onDataReceived(byte[] bytes) {
+                if (null != mOnSerialPortDataListener) {
+                    mOnSerialPortDataListener.onDataReceived(bytes);
+                }
+            }
+        };
+        mSerialPortReadThread.start();
+    }
+
+    /**
+     * 停止接收消息的线程
+     */
+    private void stopReadThread() {
+        if (null != mSerialPortReadThread) {
+            mSerialPortReadThread.release();
+        }
+    }
+
+    /**
+     * 发送数据
+     *
+     * @param sendBytes 发送数据
+     * @return 发送是否成功
+     */
+    public boolean sendBytes(byte[] sendBytes) {
+        if (null != mFd && null != mFileInputStream && null != mFileOutputStream) {
+            if (null != mSendingHandler) {
+                Message message = Message.obtain();
+                message.obj = sendBytes;
+                return mSendingHandler.sendMessage(message);
+            }
+        }
+        return false;
+    }
+}

+ 20 - 0
SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/listener/OnOpenSerialPortListener.java

@@ -0,0 +1,20 @@
+package com.kongqw.serialportlibrary.listener;
+
+import java.io.File;
+
+/**
+ * Created by Kongqw on 2017/11/14.
+ * 打开串口监听
+ */
+
+public interface OnOpenSerialPortListener {
+
+    void onSuccess(File device);
+
+    void onFail(File device, Status status);
+
+    enum Status {
+        NO_READ_WRITE_PERMISSION,
+        OPEN_FAIL
+    }
+}

+ 23 - 0
SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/listener/OnSerialPortDataListener.java

@@ -0,0 +1,23 @@
+package com.kongqw.serialportlibrary.listener;
+
+/**
+ * Created by Kongqw on 2017/11/14.
+ * 串口消息监听
+ */
+
+public interface OnSerialPortDataListener {
+
+    /**
+     * 数据接收
+     *
+     * @param bytes 接收到的数据
+     */
+    void onDataReceived(byte[] bytes);
+
+    /**
+     * 数据发送
+     *
+     * @param bytes 发送的数据
+     */
+    void onDataSent(byte[] bytes);
+}

+ 81 - 0
SerialPortLibrary/src/main/java/com/kongqw/serialportlibrary/thread/SerialPortReadThread.java

@@ -0,0 +1,81 @@
+package com.kongqw.serialportlibrary.thread;
+
+import android.util.Log;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+
+/**
+ * Created by Kongqw on 2017/11/14.
+ * 串口消息读取线程
+ */
+
+public abstract class SerialPortReadThread extends Thread {
+
+    public abstract void onDataReceived(byte[] bytes);
+
+    private static final String TAG = SerialPortReadThread.class.getSimpleName();
+    private InputStream mInputStream;
+    private byte[] mReadBuffer;
+
+    public SerialPortReadThread(InputStream inputStream) {
+        mInputStream = inputStream;
+    }
+
+    @Override
+    public void run() {
+        super.run();
+
+        while (!isInterrupted()) {
+            try {
+                Thread.sleep(100);
+                if (mInputStream == null) {
+                    return;
+                }
+                int count = mInputStream.available();
+                if (count <= 0) {
+                    continue;
+                }
+
+                //Log.i(TAG, "run: ");
+                mReadBuffer = new byte[count];
+                int size = mInputStream.read(mReadBuffer);
+
+                Log.d("wzl", "received data size: " + size + ", data: " + Arrays.toString(mReadBuffer));
+
+                byte[] readBytes = new byte[size];
+                System.arraycopy(mReadBuffer, 0, readBytes, 0, size);
+                onDataReceived(readBytes);
+
+                Thread.sleep(150);
+
+            } catch (Exception e) {
+                e.printStackTrace();
+                return;
+            }
+        }
+    }
+
+    @Override
+    public synchronized void start() {
+        super.start();
+    }
+
+    /**
+     * 关闭线程 释放资源
+     */
+    public void release() {
+        interrupt();
+
+        if (null != mInputStream) {
+            try {
+                mInputStream.close();
+                mInputStream = null;
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+
+    }
+}

+ 3 - 0
SerialPortLibrary/src/main/res/values/strings.xml

@@ -0,0 +1,3 @@
+<resources>
+    <string name="app_name">SerialPortLibrary</string>
+</resources>

+ 2 - 2
app/build.gradle

@@ -36,7 +36,7 @@ android {
         minSdkVersion 16
         targetSdkVersion 26
         versionCode 1
-        versionName "1.34"
+        versionName "10.1"
         testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
 
         buildConfigField "String", "BUILD_TIME", getDate()
@@ -72,7 +72,7 @@ dependencies {
     compile 'com.android.support.constraint:constraint-layout:1.0.2'
     testCompile 'junit:junit:4.12'
     compile project(path: ':AmDemo_R')
-    compile project(path: ':traditionlib')
+    compile project(path: ':SerialPortLibrary')
 
     //seekbar
     compile 'org.adw.library:discrete-seekbar:1.0.1'

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

@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
+    android:sharedUserId="android.uid.system"
     package="com.wdkl.tradition">
 
     <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />

+ 5 - 11
app/src/main/java/com/wdkl/tradition/MyApplication.java

@@ -15,8 +15,7 @@ import android.util.Log;
 
 import com.wdkl.tradition.common.Constants;
 import com.wdkl.tradition.service.APPService;
-import com.wdkl.tradition.util.LogUtil;
-import com.wdkl.tradition.util.SerialPortSendUtil;
+import com.wdkl.tradition.service.SerialPortService;
 import com.wdkl.tradition.util.SharedPreferencesUtil;
 import com.wdkl.tradition.util.SilentUpdateUtil;
 import com.wdkl.tradition.util.UdpHelper;
@@ -32,7 +31,6 @@ import java.util.TimerTask;
 import java.util.concurrent.TimeUnit;
 
 import okhttp3.OkHttpClient;
-import serialporttest.utils.SerialPortUtil;
 
 /**
  * Created by 胡博文 on 2017/8/17.
@@ -65,8 +63,7 @@ public class MyApplication extends Application {
     private static Context sAppContext;
     //是否关闭心跳(20180104)
     public volatile static boolean HEARTBEAT = true;
-    //串口工具类
-    public static SerialPortUtil serialPortUtil;
+
     //udp接收类
     public static UdpHelper helper;
 
@@ -84,9 +81,9 @@ public class MyApplication extends Application {
     public void onCreate() {
         super.onCreate();
         sAppContext = this;
-        //新建串口,打开串口
-        serialPortUtil = new SerialPortUtil();
-        serialPortUtil.openSerialPort();
+        //打开串口
+        SerialPortService.getInstance().openSerialPort();
+
         //初始化ok http
         initClient();
         //初始化 udp
@@ -213,9 +210,6 @@ public class MyApplication extends Application {
      */
     public static void closeHeart() {
         HEARTBEAT = false;
-        if (null != serialPortUtil) {
-            serialPortUtil.closeHeart();
-        }
     }
 
     private void closeConnectWifiHost() {

+ 81 - 50
app/src/main/java/com/wdkl/tradition/TraditionActivity.java

@@ -9,8 +9,10 @@ import android.content.SharedPreferences;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.net.wifi.WifiManager;
+import android.os.CountDownTimer;
 import android.os.Handler;
 import android.os.Message;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.View;
 import android.widget.RadioButton;
@@ -27,12 +29,15 @@ import com.wdkl.tradition.entity.InitDataEntity;
 import com.wdkl.tradition.entity.MessageEvent;
 import com.wdkl.tradition.entity.RoomEntity;
 import com.wdkl.tradition.entity.UdpEntity;
+import com.wdkl.tradition.service.ISerialPortListener;
+import com.wdkl.tradition.service.SerialModel;
+import com.wdkl.tradition.service.SerialPortService;
+import com.wdkl.tradition.service.SerialSignalTypeEnum;
 import com.wdkl.tradition.util.AutoRebootUtil;
 import com.wdkl.tradition.util.CutSerialPortUtil;
 import com.wdkl.tradition.util.LogUtil;
 import com.wdkl.tradition.util.MediaPlayerManger;
 import com.wdkl.tradition.util.NetUtil;
-import com.wdkl.tradition.util.SerialPortSendUtil;
 import com.wdkl.tradition.util.SharedPreferencesUtil;
 import com.wdkl.tradition.util.SipUtil.SipCallBackI;
 import com.wdkl.tradition.util.SipUtil.SipHelperUtil;
@@ -53,10 +58,10 @@ import org.json.JSONObject;
 
 import java.lang.ref.WeakReference;
 import java.net.InetAddress;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 
 import okhttp3.Call;
-import serialporttest.utils.SerialPortUtil;
 
 import static com.wdkl.tradition.common.Constants.EVENT_BROADCAST;
 import static com.wdkl.tradition.common.Constants.EVENT_CALL_OUT;
@@ -77,7 +82,7 @@ import static com.wdkl.tradition.util.ethernetwifiwithsipconnectstatus.WifiBindS
  * Created by 胡博文 on 2018/1/29.
  */
 
-public class TraditionActivity extends BaseActivity implements SerialPortUtil.ISerialPortBedOnclickEvent, IVvsipServiceListener, SipCallBackI, MediaPlayerManger.PlayMusicCompleteListener {
+public class TraditionActivity extends BaseActivity implements ISerialPortListener, IVvsipServiceListener, SipCallBackI, MediaPlayerManger.PlayMusicCompleteListener {
 
     private TextView tvSipState, tvMac, tvIp, tvState, tvEth, tvCallState, tvSerialReceive, tvSerialSend, tvVersionname;
 
@@ -113,8 +118,6 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
      */
     String macAddress = "";
 
-    //串口工具类
-    public SerialPortUtil serialPortUtil;
 
     private WifiBindSipStatusConnector wac;
     private WifiManager wifiManager;
@@ -163,11 +166,11 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
                 switch (checkedId) {
                     case R.id.rb_calling_mode_dual:
                         SharedPreferencesUtil.putIntSp(TraditionActivity.this, Constants.MSG_SP, SharedPreferencesUtil.CallingMode, 0);
-                        SerialPortSendUtil.changeCallingMode("0");
+                        SerialPortService.getInstance().setCallMode(0);
                         break;
                     case R.id.rb_calling_mode_single:
                         SharedPreferencesUtil.putIntSp(TraditionActivity.this, Constants.MSG_SP, SharedPreferencesUtil.CallingMode, 1);
-                        SerialPortSendUtil.changeCallingMode("1");
+                        SerialPortService.getInstance().setCallMode(1);
                         break;
                 }
             }
@@ -191,8 +194,7 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
             }
         });
 
-        serialPortUtil = ((MyApplication) this.getApplication()).serialPortUtil;
-        serialPortUtil.setOnDataReceiveListener(this);
+        SerialPortService.getInstance().setSerialPortListener(this);
 
         wardInformationList = new ArrayList<>();
 
@@ -240,8 +242,7 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
     @Override
     protected void onNewIntent(Intent intent) {
         super.onNewIntent(intent);
-        serialPortUtil = ((MyApplication) this.getApplication()).serialPortUtil;
-        serialPortUtil.setOnDataReceiveListener(this);
+        SerialPortService.getInstance().setSerialPortListener(this);
     }
 
     @Override
@@ -257,10 +258,10 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
         int callMode = SharedPreferencesUtil.getIntSp(TraditionActivity.this, Constants.MSG_SP, SharedPreferencesUtil.CallingMode);
 
         if (callMode == 1) {
-            SerialPortSendUtil.changeCallingMode("1");
+            SerialPortService.getInstance().setCallMode(1);
             rbSingleMode.setChecked(true);
         } else {
-            SerialPortSendUtil.changeCallingMode("0");
+            SerialPortService.getInstance().setCallMode(0);
             rbDualMode.setChecked(true);
         }
 
@@ -492,7 +493,6 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
                 setSystemTime(initDataEntity);
             }
             if (!isMacRegister) {
-                SerialPortSendUtil.changeRegisterState();
                 isMacRegister = true;
             }
             //当网络
@@ -627,15 +627,15 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
                 switch (state) {
                     case REGISTERING:
                         tvSipState.setBackgroundResource(R.color.yellow_color);
-                        SerialPortSendUtil.sipRegistering();
+                        //SerialPortSendUtil.sipRegistering();
                         break;
                     case REGISTERFAIL:
                         tvSipState.setBackgroundResource(R.color.red_color);
-                        SerialPortSendUtil.sipRegisterFail();
+                        //SerialPortSendUtil.sipRegisterFail();
                         break;
                     case REGISTERCOM:
                         tvSipState.setBackgroundResource(R.color.green);
-                        SerialPortSendUtil.sipRegisterCom();
+                        //SerialPortSendUtil.sipRegisterCom();
                         break;
                 }
             }
@@ -649,43 +649,55 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
         super.onDestroy();
         //=============================================SIP关闭服务===================================//
         SipHelperUtil.getInstance(this).unRegisterSip();
-        serialPortUtil.closeSerialPort();
+        SerialPortService.getInstance().closeSerialPort();
     }
 
     /***********************************串口回调**********************************************/
     @Override
-    public void serialPortBedOnclick(String str) {
+    public void onSerialReceived(SerialModel model) {
         try {
-            String newStr = CutSerialPortUtil.delHeadAndEnd(str, "$", "#");
-            String content[] = newStr.split(",");
-            LogUtil.d("serialPortBedOnclick", "newStr==" + newStr);
+            SerialSignalTypeEnum serialSignalTypeEnum = SerialSignalTypeEnum.getEnum(model.getDataType());
+            if (serialSignalTypeEnum == null) {
+                return;
+            }
+
+            String uartAddr = SerialPortService.getUAddr(model.getSlaveAddH(), model.getSlaveAddL());
+            LogUtil.d("onSerialReceived", "addr==" + uartAddr);
             if (isMacRegister) {
-                switch (content[0]) {
-                    case "A":
+                switch (serialSignalTypeEnum) {
+                    case MCU_MSG_CALLIN_REQ:
                         //分机呼叫主机
-                        EventBus.getDefault().post(new MessageEvent(content[1].substring(0, content[1].length() - 1), EVENT_CALL_OUT));
+                        EventBus.getDefault().post(new MessageEvent(uartAddr, EVENT_CALL_OUT));
                         break;
-                    case "B":
+                    case MCU_MSG_CALLOFF_REQ:
                         //分机挂断主机
-                        EventBus.getDefault().post(new MessageEvent(content[1].substring(0, content[1].length() - 1), EVENT_HANG_UP));
-                        break;
-                    case "C":
-                        EventBus.getDefault().post(new MessageEvent(content[1].substring(0, content[1].length() - 1), EVENT_EMERGENCY_CALL));
+                        EventBus.getDefault().post(new MessageEvent(uartAddr, EVENT_HANG_UP));
                         break;
-                    case "D":
-                        UdpSendUtil.sendRegister(content[1].substring(0, 4));
+                    case MCU_MSG_SOSON_REQ:
+                        EventBus.getDefault().post(new MessageEvent(uartAddr, EVENT_EMERGENCY_CALL));
                         break;
-                    case "V":
-                        Constants.MCU_VERSION_NUMBER = content[1].substring(0, 17);
+                    case MCU_MSG_VERSION_INFO:
+                        byte[] versionInfo = model.getData();
+                        if (TextUtils.isEmpty(Constants.MCU_VERSION_NUMBER) && versionInfo.length > 0) {
+                            Constants.MCU_VERSION_NUMBER = new String(versionInfo, StandardCharsets.US_ASCII);
+                        }
                         LogUtil.d("serialPortBedOnclick", "Constants.MCU_VERSION_NUMBER==" + Constants.MCU_VERSION_NUMBER);
                         break;
+                    case MCU_MSG_INQUIRE_RES:
+                        //分机状态回复
+                        break;
+                    case MCU_MSG_CALLMODE_RES:  //通话模式状态请求
+                        int callMode = SharedPreferencesUtil.getIntSp(TraditionActivity.this, Constants.MSG_SP, SharedPreferencesUtil.CallingMode);
+                        SerialPortService.getInstance().setCallMode(callMode);
+                        break;
                 }
             } else {//这里实际上是执行了“E”指令
-                UdpSendUtil.sendOnlyId(content[1].substring(0, 4), content[1].substring(4, 19));//后来增加了字符
-                //UdpSendUtil.sendRegister(content[1].substring(0, 4));
+                //UdpSendUtil.sendOnlyId(content[1].substring(0, 4), content[1].substring(4, 19));//后来增加了字符
+                UdpSendUtil.sendRegister(uartAddr);
             }
         } catch (Exception e) {
-            LogUtil.d("serialPortBedOnclick", "Exception==");
+            LogUtil.d("onSerialReceived", "Exception==");
+            e.printStackTrace();
         }
     }
 
@@ -727,16 +739,17 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
                     if (MediaPlayerManger.getInstance().isPlaying()) {
                         MediaPlayerManger.getInstance().stopMediaPlayer();
                         //关闭广播通道
-                        SerialPortSendUtil.closeSoundChannel("FFFF");
+                        SerialPortService.getInstance().stopBroadcast();
                     }
                 }
                 EventBus.getDefault().post(new MessageEvent("", Constants.EVENT_SIP_CALL_OUT));
                 //打开声音通道
-                SerialPortSendUtil.openSoundChannel(call.macStr);
+                //SerialPortSendUtil.openSoundChannel(call.macStr);
+                SerialPortService.getInstance().startCall(call.macStr);
                 //自动接听
                 SipHelperUtil.getInstance(TraditionActivity.this).getmSipCallBackI().autoTalking();
-                Constants.CALLING_MAC = call.macStr;
 
+                Constants.CALLING_MAC = call.macStr;
                 isConversation = true;
                 break;
             case 1:
@@ -748,7 +761,8 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
                     EventBus.getDefault().post(new MessageEvent(call.macStr, Constants.EVENT_SIP_HANG_UP));
                     //关闭声音通道
                     Constants.CALLING_MAC = "";
-                    SerialPortSendUtil.closeSoundChannel(call.macStr);
+                    //SerialPortSendUtil.closeSoundChannel(call.macStr);
+                    SerialPortService.getInstance().stopCall(call.macStr);
                     isConversation = false;
                 }
                 break;
@@ -856,7 +870,8 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
                             @Override
                             public void run() {
                                 //关闭广播通道
-                                SerialPortSendUtil.closeSoundChannel("FFFF");
+                                //SerialPortSendUtil.closeSoundChannel("FFFF");
+                                SerialPortService.getInstance().stopBroadcast();
                             }
                         }, 100);
 
@@ -888,7 +903,8 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
                     //发送sendUpRemove udp
                     UdpSendUtil.sendHangUp(wardInformation_hangUp, device_mac);
 
-                    SerialPortSendUtil.closeSoundChannel(device_mac);
+                    //SerialPortSendUtil.closeSoundChannel(device_mac);
+                    SerialPortService.getInstance().stopCall(device_mac);
                     setDoorLamp("8", device_mac);//20191108 waderson
 
                 }
@@ -906,9 +922,11 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
                             }
                         }
                         if (!deviceMAC.equals(Constants.CALLING_MAC)) {
-                            SerialPortSendUtil.closeEmergency(deviceMAC);
+                            //SerialPortSendUtil.closeEmergency(deviceMAC);
+                            SerialPortService.getInstance().sendSOSOffCmd(deviceMAC);
                         }
-                        SerialPortSendUtil.closeSoundChannel(deviceMAC);
+                        //SerialPortSendUtil.closeSoundChannel(deviceMAC);
+                        SerialPortService.getInstance().stopCall(deviceMAC);
                         setDoorLamp("8", deviceMAC);//20190604 waderson
                         break;
                     case "call_change_sip_voice": //护士主机改变子机SIP协议栈的通话音量
@@ -930,7 +948,7 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
                             String callMode = udpEntity.getLevel();
                             LogUtil.d("wzl", "set callMode: " + callMode);
                             SharedPreferencesUtil.putIntSp(TraditionActivity.this, Constants.MSG_SP, SharedPreferencesUtil.CallingMode, StringUtils.parseInt(callMode));
-                            SerialPortSendUtil.changeCallingMode(callMode);
+                            SerialPortService.getInstance().setCallMode(StringUtils.parseInt(callMode));
                         }
                         break;
                     case "tradition_check":
@@ -1020,7 +1038,8 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
                                     MediaPlayerManger.getInstance().stopMediaPlayer();
 
                                     //打开广播通道
-                                    SerialPortSendUtil.openBroadcast();
+                                    //SerialPortSendUtil.openBroadcast();
+                                    SerialPortService.getInstance().startBroadcast();
 
                                     //=====================播放廣播===================//
                                     MediaPlayerManger.getInstance()
@@ -1050,7 +1069,8 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
                                 isBroadcastPlay = false;
                                 tvCallState.setText("通话状态:");
                                 //关闭广播通道
-                                SerialPortSendUtil.closeSoundChannel("FFFF");
+                                //SerialPortSendUtil.closeSoundChannel("FFFF");
+                                SerialPortService.getInstance().stopBroadcast();
                             }
                         } catch (Exception e) {
                             e.printStackTrace();
@@ -1085,16 +1105,26 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
      * 门灯操作
      */
     public void setDoorLamp(String type, String macStr) {
+        //type: "7"-开启, "8"-关闭
         if (!StringUtils.notEmpty(macStr) || null == wardInformationList) return;
         try {
             RoomEntity.WardInformation wardInformation = WardInformationUtil.getWardInformation(wardInformationList, macStr);
             ArrayList<RoomEntity.WardInformation> list_doorLamp = WardInformationUtil.getDoorLightWardInformation(wardInformationList, wardInformation.getRoomID());
             for (int i = 0; i < list_doorLamp.size(); i++) {
-                if (null != serialPortUtil) {
+                /*if (null != serialPortUtil) {
                     serialPortUtil.doorLamp(type, list_doorLamp.get(i).getDeviceMAC());
                 } else {
                     MyApplication.serialPortUtil.doorLamp(type, list_doorLamp.get(i).getDeviceMAC());
+                }*/
+
+                if ("7".equals(type)) {
+                    //开启门灯
+                    SerialPortService.getInstance().sendDoorLedOnCmd(list_doorLamp.get(i).getDeviceMAC());
+                } else if ("8".equals(type)) {
+                    //关闭门灯
+                    SerialPortService.getInstance().sendDoorLedOffCmd(list_doorLamp.get(i).getDeviceMAC());
                 }
+
             }
         } catch (Exception e) {
             e.printStackTrace();
@@ -1104,7 +1134,8 @@ public class TraditionActivity extends BaseActivity implements SerialPortUtil.IS
     /********************************************EVENTBUS 回调******************************************/
     @Override
     public void playMusicComplete(int position) {
-        SerialPortSendUtil.closeSoundChannel("FFFF");
+        //SerialPortSendUtil.closeSoundChannel("FFFF");
+        SerialPortService.getInstance().stopBroadcast();
         //播放广播恢复默认状态
         Constants.IN_TIME_BROADCAST = "";
     }

+ 2 - 0
app/src/main/java/com/wdkl/tradition/common/Constants.java

@@ -207,4 +207,6 @@ public class Constants {
      * 单片机版本号  add by waderson 20190708
      */
     public static String MCU_VERSION_NUMBER = "";
+
+    public static boolean showLog = false;
 }

+ 3 - 4
app/src/main/java/com/wdkl/tradition/service/APPService.java

@@ -13,7 +13,6 @@ import com.wdkl.tradition.MyApplication;
 import java.util.Timer;
 import java.util.TimerTask;
 
-import static com.wdkl.tradition.MyApplication.serialPortUtil;
 
 
 /**
@@ -27,7 +26,7 @@ public class APPService extends Service {
     @Override
     public void onCreate() {
         super.onCreate();
-        sendHeartbeat();
+        //sendHeartbeat();
     }
 
     @Override
@@ -59,11 +58,11 @@ public class APPService extends Service {
         timerTask = new TimerTask() {
             @Override
             public void run() {
-                if (MyApplication.HEARTBEAT) {
+                /*if (MyApplication.HEARTBEAT) {
                     serialPortUtil.startHeart();
                 } else {
                     serialPortUtil.closeHeart();
-                }
+                }*/
             }
         };
         timer.schedule(timerTask, 0, 5000);

+ 5 - 0
app/src/main/java/com/wdkl/tradition/service/IDebugInfoListner.java

@@ -0,0 +1,5 @@
+package com.wdkl.tradition.service;
+
+public interface IDebugInfoListner {
+    void onDebugInfo(String info);
+}

+ 5 - 0
app/src/main/java/com/wdkl/tradition/service/ISerialPortListener.java

@@ -0,0 +1,5 @@
+package com.wdkl.tradition.service;
+
+public interface ISerialPortListener {
+    void onSerialReceived(SerialModel model);
+}

+ 138 - 0
app/src/main/java/com/wdkl/tradition/service/SerialModel.java

@@ -0,0 +1,138 @@
+package com.wdkl.tradition.service;
+
+import java.util.List;
+
+public class SerialModel {
+    private byte headCode = (byte) 0x2E;
+    private byte hostAdd = (byte)0xC0;
+    private byte slaveAddH;
+    private byte slaveAddL;
+    private byte dataType;
+    private byte length;
+    private byte[] data;
+    private byte checkSum;
+
+    public SerialModel(){}
+
+    public SerialModel(byte slaveAddH, byte slaveAddL, byte dataType, byte... data){
+        this.slaveAddH = slaveAddH;
+        this.slaveAddL = slaveAddL;
+        this.dataType = dataType;
+        this.data = data;
+    }
+
+    public byte getHeadCode() {
+        return headCode;
+    }
+
+    public void setHeadCode(byte headCode) {
+        this.headCode = headCode;
+    }
+
+    public byte getHostAdd() {
+        return hostAdd;
+    }
+
+    public void setHostAdd(byte hostAdd) {
+        this.hostAdd = hostAdd;
+    }
+
+    public byte getSlaveAddH() {
+        return slaveAddH;
+    }
+
+    public void setSlaveAddH(byte slaveAddH) {
+        this.slaveAddH = slaveAddH;
+    }
+
+    public byte getSlaveAddL() {
+        return slaveAddL;
+    }
+
+    public void setSlaveAddL(byte slaveAddL) {
+        this.slaveAddL = slaveAddL;
+    }
+
+    public byte getDataType() {
+        return dataType;
+    }
+
+    public void setDataType(byte dataType) {
+        this.dataType = dataType;
+    }
+
+    public byte getLength() {
+        return length;
+    }
+
+    public void setLength(byte length) {
+        this.length = length;
+    }
+
+    public byte[] getData() {
+        return data;
+    }
+
+    public void setData(byte[] data) {
+        this.data = data;
+    }
+
+    public byte getCheckSum() {
+        return checkSum;
+    }
+
+    public void setCheckSum(byte checkSum) {
+        this.checkSum = checkSum;
+    }
+
+    public byte[] getSendBytes(){
+        //init
+        byte[] beforeCheckSum = new byte[5+data.length];
+        beforeCheckSum[0] = hostAdd;
+        beforeCheckSum[1] = slaveAddH;
+        beforeCheckSum[2] = slaveAddL;
+        beforeCheckSum[3] = dataType;
+        beforeCheckSum[4] = (byte) data.length;
+        for (int i = 0; i < data.length; i++) {
+            beforeCheckSum[5+i] = data[i];
+        }
+
+        //cal checkSum
+        byte checkSum = 0;
+        for(byte bt:beforeCheckSum){
+            checkSum+=bt;
+        }
+        checkSum^=0xff;
+
+        //result
+        byte[] withCheckSum = new byte[2+beforeCheckSum.length];
+        withCheckSum[0]=headCode;
+        withCheckSum[1+beforeCheckSum.length]=checkSum;
+        for (int i = 0; i < beforeCheckSum.length; i++) {
+            withCheckSum[i+1] = beforeCheckSum[i];
+        }
+        return withCheckSum;
+    }
+
+    public static SerialModel getSerialModel(List<Byte> receivedSignal){
+        if (receivedSignal.size()<8){
+            return null;
+        }
+        SerialModel serialModel = new SerialModel();
+//        serialModel.headCode = receivedSignal[0];
+        serialModel.slaveAddH = receivedSignal.get(1);
+        serialModel.slaveAddL = receivedSignal.get(2);
+        serialModel.hostAdd = receivedSignal.get(3);
+        serialModel.dataType = receivedSignal.get(4);
+        serialModel.length = receivedSignal.get(5);
+        serialModel.checkSum = receivedSignal.get(receivedSignal.size()-1);
+        byte[] data = new byte[serialModel.length];
+        for (int i = 0; i < serialModel.length; i++) {
+            if (i+6 < receivedSignal.size()) {
+                data[i] = receivedSignal.get(i + 6);
+            }
+        }
+        serialModel.data = data;
+        return serialModel;
+    }
+}

+ 642 - 0
app/src/main/java/com/wdkl/tradition/service/SerialPortService.java

@@ -0,0 +1,642 @@
+package com.wdkl.tradition.service;
+
+import android.os.CountDownTimer;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.kongqw.serialportlibrary.Device;
+import com.kongqw.serialportlibrary.SerialPortFinder;
+import com.kongqw.serialportlibrary.SerialPortManager;
+import com.kongqw.serialportlibrary.listener.OnOpenSerialPortListener;
+import com.kongqw.serialportlibrary.listener.OnSerialPortDataListener;
+import com.wdkl.tradition.common.Constants;
+
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.TimerTask;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class SerialPortService implements OnOpenSerialPortListener {
+    private static final String TAG = SerialPortService.class.getSimpleName();
+
+    private volatile static SerialPortService serialPortService = null;
+
+    private SerialPortManager mSerialPortManager;
+    private Device device;
+    private Boolean portOpened = false;
+    private static SerialModel heartModel = null;
+
+
+    private IDebugInfoListner debugInfoListner;
+    private ISerialPortListener serialPortListener;
+
+    public Device getDevice() {
+        return device;
+    }
+
+    private SerialPortService() {
+        init();
+    }
+
+    public static SerialPortService getInstance() {
+        if (serialPortService == null) {
+            synchronized (SerialPortService.class) {
+                if (serialPortService == null) {
+                    serialPortService = new SerialPortService();
+                }
+            }
+        }
+        return serialPortService;
+    }
+
+    private void init() {
+        SerialPortFinder serialPortFinder = new SerialPortFinder();
+        ArrayList<Device> devices = serialPortFinder.getDevices();
+        Device device = null;
+        for (Device device1 : devices) {
+            File file = device1.getFile();
+            boolean canRead = file.canRead();
+            boolean canWrite = file.canWrite();
+            //boolean canExecute = file.canExecute();
+            if (canRead && canWrite) {
+                device = device1;
+            }
+        }
+
+        if (null == device) {
+            return;
+        }
+
+        this.device = device;
+    }
+
+    public void reOpenSerialPort() {
+        init();
+        openSerialPort();
+    }
+
+
+    public void openSerialPort() {
+        if (this.device == null) {
+            Log.d(TAG, "未找到设备");
+            return;
+        }
+        mSerialPortManager = new SerialPortManager();
+        // 打开串口
+        try {
+            boolean openSerialPort = mSerialPortManager
+                    .setOnSerialPortDataListener(new OnSerialPortDataListener() {
+                        @Override
+                        public void onDataReceived(byte[] bytes) {
+                            //接收的数据有多帧时有问题
+                            byte[] buf = checkData(bytes);
+                            if (buf.length < 8) {
+                                //Log.d("wzl", "invalid data, return.");
+                                return;
+                            }
+                            //Log.d("wzl", "after check data, the new data = " + bytesToHexString(buf));
+                            List<Byte> buffer = new ArrayList<>();
+                            for(byte bt:buf){
+                                buffer.add(bt);
+                            }
+                            try {
+                                handleReceived(buffer);
+                            } catch (Exception e) {
+                                e.printStackTrace();
+                            }
+                        }
+
+                        @Override
+                        public void onDataSent(byte[] bytes) {
+                            //Log.i(TAG, "onDataSent byte: " + Arrays.toString(bytes)+ " hex:"+bytesToHexString(bytes));
+                        }
+                    })
+                    .openSerialPort(this.device.getFile(), 115200);
+            if (openSerialPort) {
+                Log.d(TAG, "串口打开成功");
+                portOpened = true;
+                //发送心跳包建立连接
+                TimerTask timerTask = new TimerTask() {
+                    @Override
+                    public void run() {
+                        sendSignal(getHeartModel());
+                    }
+                };
+                ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
+                executor.scheduleAtFixedRate(timerTask,0,10*1000L, TimeUnit.MILLISECONDS);
+                Log.d(TAG, "============= 心跳定时任务设置完成 ==========");
+            } else {
+                Log.d(TAG, "串口打开失败");
+                portOpened = false;
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+            portOpened = false;
+        }
+    }
+
+    public void closeSerialPort(){
+        if (null != mSerialPortManager && portOpened) {
+            mSerialPortManager.closeSerialPort();
+            mSerialPortManager = null;
+        }
+    }
+
+    private byte[] buffer = new byte[256];
+    private int writeIndex = 0;
+
+    private byte[] checkData(byte[] data) {
+        if (data.length < 8) {
+            if (data[0] == 0x2E) {  //同步头
+                writeIndex = 0;
+                for (int i = 0; i < data.length; i++) {
+                    buffer[writeIndex] = data[i];
+                    writeIndex++;
+                }
+                //Log.d("wzl", "checkData: 11111111111-----writeIndex = " + writeIndex);
+            } else {
+                //Log.d("wzl", "checkData: 22222222222-----writeIndex = " + writeIndex);
+                if (writeIndex > 0) {
+                    for (int j = 0; j < data.length; j++) {
+                        buffer[writeIndex] = data[j];
+                        writeIndex++;
+                    }
+                    int newSize = writeIndex;
+                    //Log.d("wzl", "checkData: 3333333333-----writeIndex = " + writeIndex + ", newSize=" + newSize);
+                    if (newSize >= 8) {
+                        byte[] readBytes = new byte[newSize];
+                        System.arraycopy(buffer, 0, readBytes, 0, newSize);
+                        writeIndex = 0;
+                        return readBytes;
+                    }
+                }
+            }
+        }
+
+        return data;
+    }
+
+    public void setDebugInfoListner(IDebugInfoListner listner) {
+        debugInfoListner = listner;
+    }
+
+    public void setSerialPortListener(ISerialPortListener listener) {
+        serialPortListener = listener;
+    }
+
+    private void handleReceived(List<Byte> bytePkg){
+        SerialModel serialModel = SerialModel.getSerialModel(bytePkg);
+        if (serialModel==null){
+            return;
+        }
+        SerialSignalTypeEnum serialSignalTypeEnum = SerialSignalTypeEnum.getEnum(serialModel.getDataType());
+        if (serialSignalTypeEnum == null) {
+            return;
+        }
+        Log.d(TAG," <<<<<<<<<<<<< 收到包: "+serialSignalTypeEnum.getDesc());
+
+        if (Constants.showLog && debugInfoListner != null && serialSignalTypeEnum != SerialSignalTypeEnum.MCU_MSG_VERSION_INFO) {
+            String log = serialSignalTypeEnum.getDesc() + ", uart addr: " + getUAddr(serialModel.getSlaveAddH(), serialModel.getSlaveAddL())
+                    + ", data: " + bytesToHexString(serialModel.getData());
+            debugInfoListner.onDebugInfo(log);
+        }
+
+        if (serialPortListener != null) {
+            serialPortListener.onSerialReceived(serialModel);
+        }
+
+    }
+
+    private SerialModel getHeartModel(){
+        if (heartModel == null){
+            heartModel = new SerialModel(
+                    (byte) 0x00, (byte) 0x00,
+                    SerialSignalTypeEnum.APP_MSG_CONNECT_CHK.getDataType(), (byte) 0x01
+            );
+        }
+        return heartModel;
+    }
+
+    private void sendSignal(SerialModel signal) {
+        SerialSignalTypeEnum serialSignalTypeEnum = SerialSignalTypeEnum.getEnum(signal.getDataType());
+        //if (serialSignalTypeEnum != SerialSignalTypeEnum.APP_MSG_CONNECT_CHK) {
+            Log.d(TAG, " >>>>>>>>>>>> 发送包: " + serialSignalTypeEnum.getDesc());
+        //}
+        if (mSerialPortManager != null) {
+            mSerialPortManager.sendBytes(signal.getSendBytes());
+        }
+    }
+
+    public void sendSignal(byte[] sendContentBytes, String successMsg, String failedMsg) {
+        boolean sendBytes = mSerialPortManager.sendBytes(sendContentBytes);
+        //Log.i(TAG, "onSend: sendBytes = " + sendBytes);
+    }
+
+    //向MCU注册设备
+/*    public void initMCUDeviceAddr(String uAddr){
+        byte[] slaveAdd = SerialPortService.hexToByteArray(uAddr);
+        SerialModel serialModel = new SerialModel(
+                (byte) 0x00, (byte) 0x00,
+                SerialSignalTypeEnum.APP_MSG_DEVICEMAC_INFO.getDataType(),
+                (byte)0x01,(byte)0x01,slaveAdd[0],slaveAdd[1]
+        );
+        sendSignal(serialModel);
+        Log.d(TAG,"向MCU注册设备,地址:"+uAddr);
+    }*/
+
+    private void initMCUDevice(String uAddr, int id, int count){
+        if (uAddr != null) {
+            byte num = (byte) (count & 0xff);
+            byte index = (byte) (id & 0xff);
+            byte[] slaveAddr = hexToByteArray(uAddr);
+            SerialModel serialModel = new SerialModel(
+                    (byte) 0x00, (byte) 0x00,
+                    SerialSignalTypeEnum.APP_MSG_DEVICEMAC_INFO.getDataType(),
+                    num, /* 设备数 */
+                    index, /* 设备序号 */
+                    slaveAddr[0], slaveAddr[1] /* 设备地址 */
+            );
+            sendSignal(serialModel);
+            Log.d(TAG,"向MCU注册设备,地址:"+ uAddr);
+        }
+    }
+
+    //查询MCU版本号
+    public void checkMCUVersion(String uAddr) {
+        if (uAddr != null && !uAddr.isEmpty()) {
+            byte[] slaveAdd = SerialPortService.hexToByteArray(uAddr);
+            SerialModel serialModel = new SerialModel(
+                    slaveAdd[0], slaveAdd[1],
+                    SerialSignalTypeEnum.APP_MSG_INQUIRE_REQ.getDataType(),
+                    (byte) 0x02
+            );
+            sendSignal(serialModel);
+        }
+    }
+
+    //查询分机状态
+    private CheckStatusCallback mCallback = null;
+    public interface CheckStatusCallback {
+        void onCheckCompleted(String uAddr, int status);
+    }
+
+    public void checkSlaveStatus(String uAddr, CheckStatusCallback callback){
+        mCallback = callback;
+        checkSlaveStatus(uAddr);
+    }
+
+    public void checkSlaveStatus(String uAddr){
+        if (uAddr != null && !uAddr.isEmpty()) {
+            byte[] slaveAdd = SerialPortService.hexToByteArray(uAddr);
+            SerialModel serialModel = new SerialModel(
+                    slaveAdd[0], slaveAdd[1],
+                    SerialSignalTypeEnum.APP_MSG_INQUIRE_REQ.getDataType(),
+                    (byte) 0x01
+            );
+            sendSignal(serialModel);
+        }
+    }
+
+
+    public interface CallingCheckCallback {
+        void onCallingCheckComplete(String uAddr, int status);
+    }
+
+    public void removeCallbacks() {
+        mCallback = null;
+    }
+
+    //主机主动或回应呼叫
+    public void startCall(String addr) {
+        byte[] slaveAdd = SerialPortService.hexToByteArray(addr);
+        SerialModel serialModel = new SerialModel(
+                slaveAdd[0], slaveAdd[1],
+                SerialSignalTypeEnum.APP_MSG_CALL_IN_RES.getDataType(), (byte) 0x00
+        );
+        sendSignal(serialModel);
+    }
+
+    public void stopCall(String addr){
+        byte[] slaveAdd = SerialPortService.hexToByteArray(addr);
+        SerialModel serialModel = new SerialModel(
+                slaveAdd[0],slaveAdd[1],
+                SerialSignalTypeEnum.APP_MSG_CALL_OFF_REQ.getDataType(), (byte) 0x00
+        );
+        sendSignal(serialModel);
+    }
+
+    //通话模式设置
+    public void setCallMode(int mode) {
+        SerialModel serialModel = new SerialModel(
+                (byte) 0x00, (byte) 0x00,
+                SerialSignalTypeEnum.APP_MSG_CALLMODE_SET.getDataType(),
+                (byte) (mode & 0xff)
+        );
+        sendSignal(serialModel);
+    }
+
+    /* 分机呼叫请求,门灯亮红灯
+     * 颜色值:G,R,B -- 0: 灯灭, 1: 常亮  2: 闪烁
+     */
+    public void sendDoorLedOnCmd(String addr) {
+        if (addr != null && !addr.isEmpty()) {
+            byte[] slaveAdd = hexToByteArray(addr);
+            SerialModel serialModel = new SerialModel(slaveAdd[0], slaveAdd[1],
+                    SerialSignalTypeEnum.APP_MSG_DOORLED_SET.getDataType(),
+                    (byte) 0x00, (byte) 0x01, (byte) 0x00);
+            sendSignal(serialModel);
+        }
+    }
+
+    public void sendDoorLedOffCmd(String addr) {
+        if (addr != null && !addr.isEmpty()) {
+            byte[] slaveAdd = hexToByteArray(addr);
+            SerialModel serialModel = new SerialModel(slaveAdd[0], slaveAdd[1],
+                    SerialSignalTypeEnum.APP_MSG_DOORLED_SET.getDataType(),
+                    (byte) 0x00, (byte) 0x00, (byte) 0x00);
+            sendSignal(serialModel);
+        }
+    }
+
+    //通知MCU关闭紧急按钮呼叫
+    public void sendSOSOffCmd(String addr) {
+        if (addr != null && !addr.isEmpty()) {
+            byte[] slaveAdd = hexToByteArray(addr);
+            SerialModel serialModel = new SerialModel(slaveAdd[0], slaveAdd[1],
+                    SerialSignalTypeEnum.APP_MSG_SOSOFF_REQ.getDataType(), (byte) 0x00);
+            sendSignal(serialModel);
+        }
+    }
+
+    //开始广播,固定发送[2E C0 FF FF 87 01 01 B8]
+    public void startBroadcast() {
+        SerialModel serialModel = new SerialModel((byte) 0xFF, (byte) 0xFF,
+                SerialSignalTypeEnum.APP_MSG_BROADCAST_REQ.getDataType(), (byte) 0x01);
+        sendSignal(serialModel);
+    }
+
+    //停止广播,固定发送[2E C0 FF FF 86 01 01 B9]
+    public void stopBroadcast() {
+        SerialModel serialModel = new SerialModel((byte) 0xFF, (byte) 0xFF,
+                SerialSignalTypeEnum.APP_MSG_CALL_OFF_REQ.getDataType(), (byte) 0x00);
+        sendSignal(serialModel);
+    }
+
+    //设置主机和分机音量
+    //分免提和手柄状态,总共8项,数值在0x00~0xff之间
+    public void setMCUVolumes(int[] volumes) {
+        //float rate = 255/100f;
+        //for (int i = 0; i < volumes.length; i++) {
+        //    volumes[i] = (int) (volumes[i] * rate);
+        //}
+        SerialModel serialModel = new SerialModel(
+                (byte) 0x00, (byte) 0x00,
+                SerialSignalTypeEnum.APP_MSG_PHONEVOL_SET.getDataType(),
+                (byte) (volumes[0] & 0xff),
+                (byte) (volumes[1] & 0xff),
+                (byte) (volumes[2] & 0xff),
+                (byte) (volumes[3] & 0xff),
+                (byte) (volumes[4] & 0xff),
+                (byte) (volumes[5] & 0xff),
+                (byte) (volumes[6] & 0xff),
+                (byte) (volumes[7] & 0xff)
+        );
+        sendSignal(serialModel);
+    }
+
+    @Override
+    public void onSuccess(File file) {
+        Log.d(TAG, String.format("串口 [%s] 打开成功", file.getPath()));
+        portOpened = true;
+    }
+
+    @Override
+    public void onFail(File file, Status status) {
+        switch (status) {
+            case NO_READ_WRITE_PERMISSION:
+                Log.d(TAG, "没有读写权限");
+                break;
+            case OPEN_FAIL:
+            default:
+                Log.d(TAG, "串口打开失败");
+                break;
+        }
+        portOpened = false;
+    }
+
+    public static byte getCheckSum(List<Byte> byteList){
+        byte[] beforeCheckSum = new byte[6+byteList.get(5).intValue()];
+        beforeCheckSum[0] = byteList.get(1);    //slaveAddH
+        beforeCheckSum[1] = byteList.get(2);    //slaveAddL
+        beforeCheckSum[2] = byteList.get(3);    //hostAdd
+        beforeCheckSum[3] = byteList.get(4);    //dataType
+        beforeCheckSum[4] = byteList.get(5);    //dataLength
+        for (int i = 0; i < byteList.get(5).intValue(); i++) {
+            beforeCheckSum[6+i] = byteList.get(6+i);
+        }
+
+        //cal checkSum
+        byte checkSum = 0;
+        for(byte bt:beforeCheckSum){
+            checkSum+=bt;
+        }
+        checkSum^=0xff;
+        return checkSum;
+    }
+
+    public Boolean getPortOpened() {
+        return portOpened;
+    }
+
+    public static String getUAddr(byte slaveAddH, byte slaveAddL){
+        byte[] slaveAdd = {slaveAddH, slaveAddL};
+        return bytesToHexString(slaveAdd);
+    }
+
+    /**
+     * Hex字符串转byte
+     *
+     * @param inHex 待转换的Hex字符串
+     * @return 转换后的byte
+     */
+    public static byte hexToByte(String inHex) {
+        return (byte) Integer.parseInt(inHex, 16);
+    }
+
+    /**
+     * hex字符串转byte数组
+     *
+     * @param inHex 待转换的Hex字符串
+     * @return 转换后的byte数组结果
+     */
+    public static byte[] hexToByteArray(String inHex) {
+        int hexlen = inHex.length();
+        byte[] result;
+        if (hexlen % 2 == 1) {
+            // 奇数
+            hexlen++;
+            result = new byte[(hexlen / 2)];
+            inHex = "0" + inHex;
+        } else {
+            // 偶数
+            result = new byte[(hexlen / 2)];
+        }
+        int j = 0;
+        for (int i = 0; i < hexlen; i += 2) {
+            result[j] = hexToByte(inHex.substring(i, i + 2));
+            j++;
+        }
+        return result;
+    }
+
+    /**
+     * 数组转换成十六进制字符串
+     *
+     * @param bArray
+     * @return HexString
+     */
+    public static final String bytesToHexString(byte[] bArray) {
+        StringBuffer sb = new StringBuffer(bArray.length);
+        String sTemp;
+        for (int i = 0; i < bArray.length; i++) {
+            sTemp = Integer.toHexString(0xFF & bArray[i]);
+            if (sTemp.length() < 2)
+                sb.append(0);
+            sb.append(sTemp.toUpperCase());
+        }
+        return sb.toString();
+    }
+
+    private static byte[] buildSignal(byte data){
+        byte head = (byte)0x2E;
+        // 2E0000C03201000C
+        byte[] signalBody = {(byte)0x00,(byte)0x00,(byte)0xC0,(byte)0x32,(byte)0x01,data};
+        byte checkSum = 0;
+        for(byte bt:signalBody){
+            checkSum+=bt;
+        }
+        checkSum^=0xff;
+        byte[] signal = new byte[8];
+        signal[0]=head;
+        for (int i = 0; i < signalBody.length; i++) {
+            signal[i+1]=signalBody[i];
+        }
+        signal[7]=checkSum;
+        return signal;
+    }
+
+    public static void main(String[] args) {
+        byte[] signal = {(byte)0x22,(byte)0x4E};
+        byte[] signal1 = buildSignal((byte)0x00);
+        byte[] signal2 = buildSignal((byte)0x24);
+
+        byte[] temp = byteMerger(signal,signal1);
+        byte[] si = byteMerger(temp,signal2);
+
+        List<Byte> ttt = new ArrayList<>();
+        for(byte bt:si){
+            ttt.add(bt);
+        }
+        System.out.println(" >>> "+ttt);
+
+        List<Byte> x = new ArrayList<>();
+
+        for (int i = 0; i < si.length; i++) {
+            x.add(si[i]);
+            if (i==4){
+                dataReceived(listTobyte(x));
+                x=new ArrayList<>();
+            }
+            if (i==12){
+                dataReceived(listTobyte(x));
+                x=new ArrayList<>();
+            }
+            if (i==si.length-1){
+                dataReceived(listTobyte(x));
+                x=new ArrayList<>();
+            }
+        }
+    }
+
+    private static byte[] byteMerger(byte[] bt1, byte[] bt2){
+        byte[] bt3 = new byte[bt1.length+bt2.length];
+        int i=0;
+        for(byte bt: bt1){
+            bt3[i]=bt;
+            i++;
+        }
+
+        for(byte bt: bt2){
+            bt3[i]=bt;
+            i++;
+        }
+        return bt3;
+    }
+
+    private static byte[] listTobyte(List<Byte> list) {
+        if (list == null || list.size() < 0)
+            return null;
+        byte[] bytes = new byte[list.size()];
+        int i = 0;
+        Iterator<Byte> iterator = list.iterator();
+        while (iterator.hasNext()) {
+            bytes[i] = iterator.next();
+            i++;
+        }
+        return bytes;
+    }
+
+
+    static List<Byte> buffer1 = new ArrayList<>();
+    public static void dataReceived(byte[] bytes) {
+
+        for (int i = 0; i < bytes.length; i++) {
+            buffer1.add(bytes[i]);
+        }
+
+        System.out.println(" --- "+buffer1);
+        System.out.println("长度当前:"+buffer1.size());
+
+        //8位以上并且包含起始标识可能是个整包
+        if (buffer1.size()>=8 && buffer1.contains((byte)0x2E)){
+            int index= buffer1.indexOf((byte)0x2E);
+            System.out.println("有起始:"+index);
+
+            //是否有数据长度位
+            if (buffer1.size()-index>=6){
+                int dataLen = buffer1.get(index+(6-1));  //下标由0开始,减1
+                //有一个完整的包
+                if (buffer1.size()-index>=(6+dataLen+1)){
+                    System.out.println("进入核验");
+                    //获取的核验位
+                    byte receivedCheckSum = buffer1.get(index+(6-1)+dataLen+1);    //下标由0开始,减1
+                    //计算检验位,由第2位至(末位-1)得到
+                    List<Byte> forCheckSum = buffer1.subList(index,index+(6-1)+dataLen+1);
+                    byte calculateCheckSum = getCheckSum(forCheckSum);
+                    System.out.println("核验包:"+forCheckSum);
+                    System.out.println("rcs:"+receivedCheckSum+" --- ccs:"+calculateCheckSum);
+                    if (receivedCheckSum == calculateCheckSum){
+                        List<Byte> pkgSignal = buffer1.subList(index,index+(6-1)+dataLen+1+1);
+
+                        System.out.println("整包:"+pkgSignal.toString());
+
+                        //重置buffer
+                        List<Byte> afterBytes = buffer1.subList(index+(6-1)+dataLen+1+1,buffer1.size());
+                        buffer1 = afterBytes;
+
+                        System.out.println(""+buffer1);
+                        System.out.println("长度当前:"+buffer1.size());
+                    }
+                }
+            }
+        } else {
+            System.out.println("未包含0x2E");
+        }
+        System.out.println(" ");
+    }
+}

+ 61 - 0
app/src/main/java/com/wdkl/tradition/service/SerialSignalTypeEnum.java

@@ -0,0 +1,61 @@
+package com.wdkl.tradition.service;
+
+public enum SerialSignalTypeEnum {
+    /**
+     * HOST -> SLAVE (主机向mcu发送的指令请求类型)
+     */
+    APP_MSG_CONNECT_CHK((byte)0x80, "启动连接检查和心跳包功能"),
+    APP_MSG_INQUIRE_REQ((byte)0x81, "APP发送设备查询命令"),
+    APP_MSG_SYSREST_REQ((byte)0x82,"APP发送系统复位请求"),
+    APP_MSG_DOORLED_SET((byte)0x83, "门灯控制"),
+    APP_MSG_CALL_IN_RES((byte)0x85, "主机呼叫请求和响应"),
+    APP_MSG_CALL_OFF_REQ((byte)0x86, "主机呼叫挂断请求"),
+    APP_MSG_BROADCAST_REQ((byte)0x87, "主机发送广播请求"),
+    APP_MSG_SOSOFF_REQ((byte)0x88, "主机关闭防水紧急按钮呼叫"),
+    APP_MSG_DEVICEID_REQ((byte)0x8A, "主机请求设备ID"),
+    APP_MSG_DEVICEMAC_INFO((byte)0x8B, "主机发送设备MAC地址列表"),
+    APP_MSG_PHONEVOL_SET((byte)0x8C, "音量调节"),
+    APP_MSG_CALLMODE_SET((byte)0x8D, "通话模式切换设置"),
+    APP_MSG_UPGRADE_REQ((byte)0xE1, "MCU升级请求"),
+    APP_MSG_UPGRADE_DATA((byte)0xE3, "MCU升级数据包"),
+    /**
+     * SLAVE -> HOST(mcu向主机发送的指令请求类型)
+     */
+    MCU_MSG_KEY_INFO((byte)0x01, "主机接听按键信息"),
+    MCU_MSG_HANDLE_STATE((byte)0x02, "主机手柄插簧开关按键状态"),
+    MCU_MSG_CALLIN_REQ((byte)0x03, "分机呼叫请求"),
+    MCU_MSG_CALLOFF_REQ((byte)0x04, "分机呼叫挂断请求"),
+    MCU_MSG_SOSON_REQ((byte)0x05, "防水紧急按钮呼叫请求"),
+    MCU_MSG_VERSION_INFO((byte)0x07, "MCU软件版本"),
+    MCU_MSG_INQUIRE_RES((byte)0x31, "查询设备连接状态"),
+    MCU_MSG_DEVICEMAC_RES((byte)0x32, "已注册设备MAC地址确认"),
+    MCU_MSG_CALLMODE_RES((byte)0x33, "通话模式切换状态请求"),
+    MCU_MSG_UPGRADE_START((byte)0xE2, "MCU升级状态反馈"),
+    MCU_MSG_UPGRADE_DATA((byte)0xE4, "MCU升级数据包反馈");
+
+
+    private final byte dataType;//指令类型值
+    private final String desc;//指令类型描述
+
+    public byte getDataType() {
+        return dataType;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    SerialSignalTypeEnum(byte dataType, String desc) {
+        this.dataType = dataType;
+        this.desc = desc;
+    }
+
+    public static SerialSignalTypeEnum getEnum(byte dataType){
+        for (SerialSignalTypeEnum typeEnum: SerialSignalTypeEnum.values()){
+            if (typeEnum.getDataType() == dataType){
+                return typeEnum;
+            }
+        }
+        return null;
+    }
+}

+ 6 - 6
app/src/main/java/com/wdkl/tradition/util/AnalysisUdpUtil.java

@@ -10,7 +10,6 @@ import com.wdkl.tradition.entity.UdpEntity;
 
 import org.greenrobot.eventbus.EventBus;
 
-import serialporttest.utils.SerialPortUtil;
 
 
 /**
@@ -18,7 +17,7 @@ import serialporttest.utils.SerialPortUtil;
  */
 
 public class AnalysisUdpUtil {
-    private static SerialPortUtil serialPortUtil;
+    //private static SerialPortUtil serialPortUtil;
 
     private AnalysisUdpUtil() {
 
@@ -26,9 +25,9 @@ public class AnalysisUdpUtil {
 
     public static void AnalysisUdp(String udpMsg, Context context) {
         LogUtil.d("wzlll", "1===udpMsg==" + udpMsg);
-        if (null == serialPortUtil) {
+        /*if (null == serialPortUtil) {
             serialPortUtil = ((MyApplication) context.getApplicationContext()).serialPortUtil;
-        }
+        }*/
         try {
             //判断是否为美元符号开头,如果是则是android 端的命令
             if ("$".equals(udpMsg.substring(0, 1))) {
@@ -235,14 +234,15 @@ public class AnalysisUdpUtil {
                         break;
                     case "MGR_SYSTEM_RESET":
                         if (data[1].equals(Constants.MAC_ADDRESS)) {
-                            ((MyApplication) context.getApplicationContext()).serialPortUtil.systemRestart();
+                            //((MyApplication) context.getApplicationContext()).serialPortUtil.systemRestart();
+                            AutoRebootUtil.reboot(MyApplication.getAppContext());
                         }
                         break;
                     case "MGR_REG_Q": //给出设备信息
                         try {
                             String content[] = data[1].split("$");
                             if (content[0].equals(Constants.MAC_ADDRESS)) {
-                                SerialPortSendUtil.register(content[1]);
+                                //SerialPortSendUtil.register(content[1]);
                             }
                         } catch (ArrayIndexOutOfBoundsException e) {
                             e.printStackTrace();

+ 1 - 2
app/src/main/java/com/wdkl/tradition/util/AutoRebootUtil.java

@@ -8,7 +8,6 @@ import com.wdkl.tradition.MyApplication;
 
 import java.util.Calendar;
 
-import serialporttest.utils.SerialPortUtil;
 
 import static com.wdkl.tradition.common.Constants.NET_ERROR_FIVE_AFTER_TOAST;
 
@@ -73,7 +72,7 @@ public class AutoRebootUtil {
 
     public static void ethreboot() {
         try {
-            if (SerialPortUtil.systemVersionIsO()) {// android8.1 //wuyq modify
+            if (StringUtils.systemVersionIsO()) {// android8.1 //wuyq modify
                 //SystemProperties.set("persist.sys.ethreboot", "1");
             } else {
                 Process proc = Runtime.getRuntime().exec(new String[]{"su", "-c", "ifconfig eth0 down"});

+ 3 - 3
app/src/main/java/com/wdkl/tradition/util/SerialPortSendUtil.java

@@ -1,12 +1,12 @@
 package com.wdkl.tradition.util;
 
-import static com.wdkl.tradition.MyApplication.serialPortUtil;
+//import static com.wdkl.tradition.MyApplication.serialPortUtil;
 
 /**
  * Created by 胡博文 on 2018/4/3.
  */
 
-public class SerialPortSendUtil {
+/*public class SerialPortSendUtil {
 
 
     public static void sipRegistering() {
@@ -65,4 +65,4 @@ public class SerialPortSendUtil {
         serialPortUtil.send(serialPortUtil.C_HEARD + "F" + serialPortUtil.C_SEPARATE + "FFFF" + mode + serialPortUtil.C_END);
     }
 
-}
+}*/

+ 8 - 2
app/src/main/java/com/wdkl/tradition/util/SipUtil/SipHelperUtil.java

@@ -153,8 +153,12 @@ public class SipHelperUtil implements EthernetWifiCallBackI {
 //        LogUtil.i(SipInfoTag, "lifecycle // onDestroy");
 
         IVvsipService sipservice = VvsipService.getService();
-        if (contexts instanceof IVvsipServiceListener && sipservice != null) {
-            sipservice.removeListener((IVvsipServiceListener) contexts);
+        //if (contexts instanceof IVvsipServiceListener && sipservice != null) {
+        //    sipservice.removeListener((IVvsipServiceListener) contexts);
+        //}
+
+        if (sipservice != null) {
+            sipservice.clearListener();
         }
         getSipServiceStartHandler().removeCallbacks(getSipServiceStartRunnable());
         sipRegisterHandler.removeCallbacks(sipRegisterRunnable);
@@ -185,6 +189,7 @@ public class SipHelperUtil implements EthernetWifiCallBackI {
         }
         IVvsipService sipService = VvsipService.getService();
         if (sipService != null) {
+            sipService.clearListener();
             sipService.addListener((IVvsipServiceListener) contexts);
             sipService.setMessageHandler(messageHandler);
         } else {
@@ -567,6 +572,7 @@ public class SipHelperUtil implements EthernetWifiCallBackI {
                     public void onServiceConnected(ComponentName name, IBinder service) {
                         IVvsipService sipservice = ((VvsipServiceBinder) service).getService();
                         if (contexts instanceof IVvsipServiceListener) {
+                            sipservice.clearListener();
                             sipservice.addListener((IVvsipServiceListener) contexts);
 //                            LogUtil.i(SipInfoTag, "Connected!");
                             SipHelperUtil.getInstance(contexts).obtainSipInfo();//Sip信息获取

+ 8 - 0
app/src/main/java/com/wdkl/tradition/util/StringUtils.java

@@ -1096,4 +1096,12 @@ public class StringUtils {
         }
         return sb.toString();
     }
+
+    public static boolean systemVersionIsO() {
+        if (android.os.Build.VERSION.SDK_INT >= 24) {//7.1以上的系统
+            return true;
+        } else {
+            return false;
+        }
+    }
 }

+ 1 - 6
app/src/main/java/com/wdkl/tradition/util/UdpHelper.java

@@ -10,14 +10,13 @@ import java.net.InetAddress;
 import java.net.SocketException;
 import java.net.UnknownHostException;
 
-import serialporttest.utils.SerialPortUtil;
 
 /**
  * UdpHelper帮助类
  *
  * @author 陈喆榕
  */
-public class UdpHelper implements Runnable, SerialPortUtil.ISerialPortBedOnclickEvent {
+public class UdpHelper implements Runnable{
     public Boolean IsThreadDisable = false;//指示监听线程是否终止
     private static WifiManager.MulticastLock lock;
     private Context context;
@@ -106,8 +105,4 @@ public class UdpHelper implements Runnable, SerialPortUtil.ISerialPortBedOnclick
         }.start();
     }
 
-    @Override
-    public void serialPortBedOnclick(String str) {
-        send(str);
-    }
 }

+ 1 - 1
app/src/main/res/values/strings.xml

@@ -1,3 +1,3 @@
 <resources>
-    <string name="app_name">Tradition</string>
+    <string name="app_name">Tradition_New</string>
 </resources>

+ 1 - 1
settings.gradle

@@ -1 +1 @@
-include ':app', ':traditionlib', ':AmDemo_R'
+include ':app', ':SerialPortLibrary', ':AmDemo_R'