Browse Source

增加串口0数据透传功能代码,暂时不用

weizhengliang 3 years ago
parent
commit
d27583c7e4

+ 1 - 1
app/src/main/code/com/wdkl/app/ncs/application/Application.kt

@@ -90,7 +90,7 @@ class Application : BaseApplication() {
 
         //open serial port
         if (Build.MODEL.equals("rk3128")) {
-            SerialPortUtil.getInstance().openSerialPort();
+            SerialPortUtil.getInstance().openSerialPort()
         }
 
         // 初始化网络请求

+ 48 - 3
conversion_box/src/main/java/com/wdkl/app/ncs/conversion_box/activity/MainActivity.kt

@@ -56,6 +56,9 @@ import kotlinx.android.synthetic.main.view_title_layout.*
 import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
+import rs485.ByteUtil
+import rs485.Rs485Calling
+import serialporttest.utils.SerialPort485Util
 import serialporttest.utils.SerialPortUtil
 import java.util.*
 import java.util.UUID
@@ -63,7 +66,8 @@ import kotlin.collections.ArrayList
 
 
 @Router(path = "/conversion_box/main")
-class MainActivity :BaseActivity<MainActivityPresenter, MainActivityLayoutBinding>(), MainActivityContract.View, SerialPortUtil.ISerialPortBedOnclickEvent, IUserState, CallSession.CallSessionCallback {
+class MainActivity :BaseActivity<MainActivityPresenter, MainActivityLayoutBinding>(), MainActivityContract.View,
+    SerialPortUtil.ISerialPortBedOnclickEvent, SerialPort485Util.ISerialPortData, IUserState, CallSession.CallSessionCallback {
 
     private lateinit var receiver: TimeReceiver
     private lateinit var curFragment: String
@@ -146,6 +150,11 @@ class MainActivity :BaseActivity<MainActivityPresenter, MainActivityLayoutBindin
         tv_version.setText("V" + BuildConfig.VERSION_NAME + "_" + BuildConfig.VERSION_CODE)
 
         //initCallTimer()
+
+        //rs485
+        /*Thread {
+            startRs485()
+        }.start()*/
     }
 
     override fun userLogin() {
@@ -208,6 +217,26 @@ class MainActivity :BaseActivity<MainActivityPresenter, MainActivityLayoutBindin
         SerialPortUtil.getInstance().startHeartBeat()
     }
 
+    private fun startRs485() {
+        SerialPort485Util.getInstance().openSerialPort {
+            /*var list = ""
+            for (device in it) {
+                if ("ttyS1".equals(device.name) || "ttyS0".equals(device.name)) {
+                    val file = device.file
+                    val canRead = file.canRead()
+                    val canWrite = file.canWrite()
+                    val name = "name: " + device.name + ", 可读=" + canRead + ", 可写=" + canWrite + "\r\n"
+                    list += name
+                }
+            }
+
+            runOnUiThread {
+                tv_serial_device.text = list
+            }*/
+        }
+        SerialPort485Util.getInstance().setOnDataReceiveListener(this)
+    }
+
     fun checkAppVersion() {
         Constant.APP_PATH = ""
         //获取APP版本信息
@@ -225,6 +254,9 @@ class MainActivity :BaseActivity<MainActivityPresenter, MainActivityLayoutBindin
         Constant.CALL_STATE = Constant.CALL_STANDBY
         SerialPortUtil.getInstance().closeHeart()
         SerialPortUtil.getInstance().closeSerialPort()
+
+        //rs485
+        //SerialPort485Util.getInstance().closeSerialPort()
     }
 
     //数据加载错误
@@ -316,6 +348,7 @@ class MainActivity :BaseActivity<MainActivityPresenter, MainActivityLayoutBindin
         }
 
         view_title_layout_tv_hospital_name.text = deviceInfo.hospitalName + deviceInfo.partName
+        view_title_layout_tv_no.text = "设备ID: " + deviceInfo.id
         initialized = true
 
         EventBus.getDefault().post(MessageEvent("updateCustom", Constant.EVENT_UPDATE_CUSTOM))
@@ -454,6 +487,12 @@ class MainActivity :BaseActivity<MainActivityPresenter, MainActivityLayoutBindin
         unregisterReceiver(receiver)
     }
 
+    override fun onSerialPortData(data: ByteArray) {
+        //val hexStr = SerialPort485Util.bytesToHexString(data)
+        //updateUart0Info(hexStr)
+        //Log.d("onSerialPortData", " rs485 data: $hexStr")
+    }
+
     //串口处理
     override fun serialPortBedOnclick(str: String) {
         try {
@@ -741,15 +780,21 @@ class MainActivity :BaseActivity<MainActivityPresenter, MainActivityLayoutBindin
         }
     }
 
+    private fun updateUart0Info(str: String) {
+        runOnUiThread {
+            tv_uart0_info.setText("串口0: $str")
+        }
+    }
+
     private fun updateUartInfo(str: String) {
         runOnUiThread {
-            tv_uart_info.setText("串口: " + str)
+            tv_uart_info.setText("串口1: $str")
         }
     }
 
     private fun updateTcpInfo(str: String) {
         runOnUiThread {
-            tv_tcp_info.setText("Received TCP: " + str)
+            tv_tcp_info.setText("Received TCP: $str")
         }
     }
 

+ 22 - 5
conversion_box/src/main/res/layout/main_activity_layout.xml

@@ -108,7 +108,8 @@
                 android:layout_height="wrap_content"
                 android:textColor="@color/color_red"
                 android:textSize="20sp"
-                android:text="MCU:"/>
+                android:text="MCU:"
+                android:visibility="gone"/>
             <TextView
                 android:id="@+id/tv_device_status"
                 android:layout_width="wrap_content"
@@ -116,7 +117,7 @@
                 android:layout_marginTop="10dp"
                 android:textSize="20sp"
                 android:textColor="@color/main_color"
-                android:text="设备状态:"/>
+                android:text="设备状态:" />
             <TextView
                 android:id="@+id/tv_call_state"
                 android:layout_width="wrap_content"
@@ -124,7 +125,15 @@
                 android:layout_marginTop="10dp"
                 android:textSize="20sp"
                 android:textColor="@color/main_color"
-                android:text="呼叫状态: 待机中"/>
+                android:text="呼叫状态: 待机中" />
+            <TextView
+                android:id="@+id/tv_uart0_info"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp"
+                android:textSize="20sp"
+                android:textColor="@color/main_color"
+                android:text="串口0:" />
             <TextView
                 android:id="@+id/tv_uart_info"
                 android:layout_width="wrap_content"
@@ -132,7 +141,7 @@
                 android:layout_marginTop="10dp"
                 android:textSize="20sp"
                 android:textColor="@color/main_color"
-                android:text="串口:"/>
+                android:text="串口1:" />
             <TextView
                 android:id="@+id/tv_tcp_info"
                 android:layout_width="wrap_content"
@@ -140,7 +149,15 @@
                 android:layout_marginTop="10dp"
                 android:textSize="20sp"
                 android:textColor="@color/main_color"
-                android:text="TCP:"/>
+                android:text="TCP:" />
+            <TextView
+                android:id="@+id/tv_serial_device"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="10dp"
+                android:textSize="20sp"
+                android:textColor="@color/main_color"
+                android:text=""/>
         </LinearLayout>
 
         <!--通话界面-->

+ 1 - 1
conversion_box/src/main/res/layout/view_title_layout.xml

@@ -46,7 +46,7 @@
         android:layout_centerVertical="true"
         android:layout_marginRight="10dp"
         android:layout_toLeftOf="@+id/view_title_layout_ll_right"
-        android:text=""
+        android:text="设备ID:"
         android:textColor="@color/main_color"
         android:textSize="@dimen/font_size_20" />
 

+ 2 - 0
traditionlib/build.gradle

@@ -40,4 +40,6 @@ dependencies {
     })
     compile 'com.android.support.constraint:constraint-layout:1.0.2'
     testCompile 'junit:junit:4.12'
+
+    compile 'com.fasterxml.jackson.core:jackson-databind:2.9.5'
 }

+ 48 - 0
traditionlib/src/main/java/android_serialport_api/Device.java

@@ -0,0 +1,48 @@
+package android_serialport_api;
+
+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
traditionlib/src/main/java/android_serialport_api/Driver.java

@@ -0,0 +1,54 @@
+package android_serialport_api;
+
+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;
+    }
+
+}

+ 18 - 1
traditionlib/src/main/java/android_serialport_api/SerialPort.java

@@ -9,6 +9,7 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.io.PrintWriter;
 
 public class SerialPort {
 
@@ -23,12 +24,28 @@ public class SerialPort {
         if (!device.canRead() || !device.canWrite()) {
             try {
                 //通过挂载到linux的方式,修改文件的操作权限
-                Process su = Runtime.getRuntime().exec("/system/xbin/su");
+                /*Process su = Runtime.getRuntime().exec("/system/xbin/su");
                 String cmd = "chmod 777 " + device.getAbsolutePath() + "\n" + "exit\n";
                 su.getOutputStream().write(cmd.getBytes());
 
                 if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
                     throw new SecurityException();
+                }*/
+
+
+                Process process;
+                PrintWriter printWriter;
+                try {
+                    process = Runtime.getRuntime().exec("su");
+                    printWriter = new PrintWriter(process.getOutputStream());
+                    String cmd = "chmod 777 " + device.getAbsolutePath() + "\n" + "exit\n";
+                    printWriter.println(cmd);
+                    printWriter.flush();
+                    printWriter.close();
+                    int res = process.waitFor();
+                    Log.e(TAG, "exec command res: " + res);
+                } catch (Exception e) {
+                    e.printStackTrace();
                 }
             } catch (Exception e) {
                 e.printStackTrace();

+ 89 - 0
traditionlib/src/main/java/android_serialport_api/SerialPort485.java

@@ -0,0 +1,89 @@
+package android_serialport_api;
+
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+public class SerialPort485 {
+
+    private static final String TAG = "SerialPort485";
+    private FileDescriptor mFd;
+    private FileInputStream mFileInputStream;
+    private FileOutputStream mFileOutputStream;
+
+    public SerialPort485(File device, int baudrate, int flags) throws SecurityException, IOException {
+        //检查访问权限,如果没有读写权限,进行文件操作,修改文件访问权限
+        if (!device.canRead() || !device.canWrite()) {
+            try {
+                //通过挂载到linux的方式,修改文件的操作权限
+                //Process su = Runtime.getRuntime().exec("/system/xbin/su");
+                //String cmd = "chmod 777 " + device.getAbsolutePath() + "\n" + "exit\n";
+                //su.getOutputStream().write(cmd.getBytes());
+                //if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+                //    throw new SecurityException();
+                //}
+
+                Process process;
+                PrintWriter printWriter;
+                try {
+                    process = Runtime.getRuntime().exec("su");
+                    printWriter = new PrintWriter(process.getOutputStream());
+                    String cmd = "chmod 777 " + device.getAbsolutePath() + "\n" + "exit\n";
+                    printWriter.println(cmd);
+                    printWriter.flush();
+                    printWriter.close();
+                    int res = process.waitFor();
+                    Log.e(TAG, "exec command res: " + res);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new SecurityException();
+            }
+        }
+
+        mFd = open(device.getAbsolutePath(), baudrate, flags);
+
+        if (mFd == null) {
+            Log.e(TAG, "native open returns null");
+            throw new IOException();
+        }
+
+        mFileInputStream = new FileInputStream(mFd);
+        mFileOutputStream = new FileOutputStream(mFd);
+    }
+
+    // Getters and setters
+    public InputStream getInputStream() {
+        return mFileInputStream;
+    }
+
+    public OutputStream getOutputStream() {
+        return mFileOutputStream;
+    }
+
+
+    // JNI(调用java本地接口,实现串口的打开和关闭)
+/**串口有五个重要的参数:串口设备名,波特率,检验位,数据位,停止位
+ 其中检验位一般默认位NONE,数据位一般默认为8,停止位默认为1*/
+    /**
+     * @param path     串口设备的据对路径
+     * @param baudrate 波特率
+     * @param flags    校验位
+     */
+    private native static FileDescriptor open(String path, int baudrate, int flags);
+    public native void close();
+
+    static {//加载jni下的C文件库
+        System.loadLibrary("serial_port");
+    }
+}

+ 66 - 0
traditionlib/src/main/java/android_serialport_api/SerialPortFinder.java

@@ -0,0 +1,66 @@
+package android_serialport_api;
+
+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;
+    }
+}

+ 344 - 0
traditionlib/src/main/java/rs485/ByteUtil.java

@@ -0,0 +1,344 @@
+package rs485;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+
+public class ByteUtil {
+    private static ByteBuffer buffer = ByteBuffer.allocate(8);
+    /**
+     * int转byte
+     * @param x
+     * @return
+     */
+    public static byte intToByte(int x) {
+        return (byte) x;
+    }
+    /**
+     * byte转int
+     * @param b
+     * @return
+     */
+    public static int byteToInt(byte b) {
+        //Java的byte是有符号,通过 &0xFF转为无符号
+        return b & 0xFF;
+    }
+
+    /**
+     * byte[]转int
+     * @param b
+     * @return
+     */
+    public static int byteArrayToInt(byte[] b) {
+        return   b[3] & 0xFF |
+                (b[2] & 0xFF) << 8 |
+                (b[1] & 0xFF) << 16 |
+                (b[0] & 0xFF) << 24;
+    }
+    public static int byteArrayToInt(byte[] b, int index){
+        return   b[index+3] & 0xFF |
+                (b[index+2] & 0xFF) << 8 |
+                (b[index+1] & 0xFF) << 16 |
+                (b[index+0] & 0xFF) << 24;
+    }
+    /**
+     * int转byte[]
+     * @param a
+     * @return
+     */
+    public static byte[] intToByteArray(int a) {
+        return new byte[] {
+                (byte) ((a >> 24) & 0xFF),
+                (byte) ((a >> 16) & 0xFF),
+                (byte) ((a >> 8) & 0xFF),
+                (byte) (a & 0xFF)
+        };
+    }
+    /**
+     * short转byte[]
+     *
+     * @param b
+     * @param s
+     * @param index
+     */
+    public static void byteArrToShort(byte b[], short s, int index) {
+        b[index + 1] = (byte) (s >> 8);
+        b[index + 0] = (byte) (s >> 0);
+    }
+    /**
+     * byte[]转short
+     *
+     * @param b
+     * @param index
+     * @return
+     */
+    public static short byteArrToShort(byte[] b, int index) {
+        return (short) (((b[index + 0] << 8) | b[index + 1] & 0xff));
+    }
+    /**
+     * 16位short转byte[]
+     *
+     * @param s
+     *            short
+     * @return byte[]
+     * */
+    public static byte[] shortToByteArr(short s) {
+        byte[] targets = new byte[2];
+        for (int i = 0; i < 2; i++) {
+            int offset = (targets.length - 1 - i) * 8;
+            targets[i] = (byte) ((s >>> offset) & 0xff);
+        }
+        return targets;
+    }
+    /**
+     * byte[]转16位short
+     * @param b
+     * @return
+     */
+    public static short byteArrToShort(byte[] b){
+        return byteArrToShort(b,0);
+    }
+
+    /**
+     * long转byte[]
+     * @param x
+     * @return
+     */
+    public static byte[] longToBytes(long x) {
+        buffer.putLong(0, x);
+        return buffer.array();
+    }
+    /**
+     * byte[]转Long
+     * @param bytes
+     * @return
+     */
+    public static long bytesToLong(byte[] bytes) {
+        buffer.put(bytes, 0, bytes.length);
+        buffer.flip();//need flip
+        return buffer.getLong();
+    }
+    /**
+     * 从byte[]中抽取新的byte[]
+     * @param data - 元数据
+     * @param start - 开始位置
+     * @param end - 结束位置
+     * @return 新byte[]
+     */
+    public static byte[] getByteArr(byte[]data,int start ,int end){
+        byte[] ret=new byte[end-start];
+        for(int i=0;(start+i)<end;i++){
+            ret[i]=data[start+i];
+        }
+        return ret;
+    }
+
+    /**
+     * 流转换为byte[]
+     * @param inStream
+     * @return
+     */
+    public static byte[] readInputStream(InputStream inStream) {
+        ByteArrayOutputStream outStream = null;
+        try {
+            outStream = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            byte[] data = null;
+            int len = 0;
+            while ((len = inStream.read(buffer)) != -1) {
+                outStream.write(buffer, 0, len);
+            }
+            data = outStream.toByteArray();
+            return data;
+        }catch (IOException e) {
+            return null;
+        } finally {
+            try {
+                if (outStream != null) {
+                    outStream.close();
+                }
+                if (inStream != null) {
+                    inStream.close();
+                }
+            } catch (IOException e) {
+                return null;
+            }
+        }
+    }
+    /**
+     * byte[]转inputstream
+     * @param b
+     * @return
+     */
+    public static InputStream readByteArr(byte[] b){
+        return new ByteArrayInputStream(b);
+    }
+    /**
+     * byte数组内数字是否相同
+     * @param s1
+     * @param s2
+     * @return
+     */
+    public static boolean isEq(byte[] s1,byte[] s2){
+        int slen=s1.length;
+        if(slen==s2.length){
+            for(int index=0;index<slen;index++){
+                if(s1[index]!=s2[index]){
+                    return false;
+                }
+            }
+            return true;
+        }
+        return  false;
+    }
+    /**
+     * byte数组转换为Stirng
+     * @param s1 -数组
+     * @param encode -字符集
+     * @param err -转换错误时返回该文字
+     * @return
+     */
+    public static String getString(byte[] s1, String encode, String err){
+        try {
+            return new String(s1,encode);
+        } catch (UnsupportedEncodingException e) {
+            return err==null?null:err;
+        }
+    }
+    /**
+     * byte数组转换为Stirng
+     * @param s1-数组
+     * @param encode-字符集
+     * @return
+     */
+    public static String getString(byte[] s1, String encode){
+        return getString(s1,encode,null);
+    }
+    //测试
+    public static void main(String[]args){
+        System.err.println(isEq(new byte[]{1,2},new byte[]{1,2}));
+    }
+    /**
+     * 字节数组转16进制字符串
+     * @param b
+     * @return
+     */
+    public static String byteArrToHexString(byte[] b){
+        String result="";
+        for (int i=0; i < b.length; i++) {
+            result += Integer.toString( ( b[i] & 0xff ) + 0x100, 16).substring(1);
+        }
+        return result;
+    }
+
+    /**
+     * 16进制字符创转int
+     * @param hexString
+     * @return
+     */
+    public static int hexStringToInt(String hexString){
+        return Integer.parseInt(hexString,16);
+    }
+    /**
+     * 十进制转二进制
+     * @param i
+     * @return
+     */
+    public static String intToBinary(int i){
+        return Integer.toBinaryString(i);
+    }
+
+
+    /**
+     * 16进制字符串转换成byte数组  这个转的多了会报错
+     * */
+    public static byte[] Hex2Bytes(String hexString){
+        byte[] arrB = hexString.getBytes();
+        int iLen = arrB.length;
+        byte[] arrOut = new byte[iLen / 2];
+        String strTmp = null;
+        for (int i = 0; i < iLen; i += 2)
+        {
+            strTmp = new String(arrB, i, 2);
+            arrOut[(i / 2)] = ((byte) Integer.parseInt(strTmp, 16));
+        }
+        return arrOut;
+    }
+
+    /**
+     * 16进制字符串转换成byte数组
+     * @param hexStr
+     * @return
+     */
+    public static byte[] hexToByteArr(String hexStr) {
+       String HexStr = "0123456789abcdef";
+        char[] charArr = hexStr.toCharArray();
+        byte btArr[] = new byte[charArr.length / 2];
+        int index = 0;
+        for (int i = 0; i < charArr.length; i++) {
+            int highBit = HexStr.indexOf(charArr[i]);
+            int lowBit = HexStr.indexOf(charArr[++i]);
+            btArr[index] = (byte) (highBit << 4 | lowBit);
+            index++;
+        }
+        return btArr;
+    }
+
+
+
+
+    /**
+     * 16进制字符串转换成byte数组
+     * */
+    public static byte[] String2Byte(String s) {
+        s = s.replace(" ", "");
+        s = s.replace("#", "");
+        byte[] baKeyword = new byte[s.length() / 2];
+        for (int i = 0; i < baKeyword.length; i++) {
+            try {
+                baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(i * 2, i * 2 + 2), 16));
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return baKeyword;
+    }
+
+    public static String hexStr2Str(String hexStr) {
+        String str = "0123456789abcdef";
+        char[] hexs = hexStr.toCharArray();
+        byte[] bytes = new byte[hexStr.length() / 2];
+        int n;
+
+        for (int i = 0; i < bytes.length; i++) {
+            n = str.indexOf(hexs[2 * i]) * 16;
+            n += str.indexOf(hexs[2 * i + 1]);
+            bytes[i] = (byte) (n & 0xff);
+        }
+        return new String(bytes);
+    }
+
+    /**
+     * 字符串转换成为16进制(无需Unicode编码)
+     * @param str
+     * @return
+     */
+    public static String str2HexStr(String str) {
+        char[] chars = "0123456789abcdef".toCharArray();
+        StringBuilder sb = new StringBuilder("");
+        byte[] bs = str.getBytes();
+        int bit;
+        for (int i = 0; i < bs.length; i++) {
+            bit = (bs[i] & 0x0f0) >> 4;
+            sb.append(chars[bit]);
+            bit = bs[i] & 0x0f;
+            sb.append(chars[bit]);
+            // sb.append(' ');
+        }
+        return sb.toString().trim();
+    }
+}
+

+ 127 - 0
traditionlib/src/main/java/rs485/CRC32.java

@@ -0,0 +1,127 @@
+package rs485;
+
+public class CRC32 {
+
+
+    public static String getCRC32(String str) {
+        int[] table = {
+                0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+                0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+                0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+                0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+                0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+                0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+                0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+                0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+                0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+                0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+                0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+                0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+                0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+                0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+                0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+                0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+                0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+                0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+                0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+                0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+                0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+                0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+                0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+                0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+                0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+                0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+                0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+                0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+                0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+                0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+                0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+                0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
+        };
+
+
+//
+        byte[] bytes = ByteUtil.String2Byte(str);
+
+        int crc = 0xffffffff;
+        for (byte b : bytes) {
+            crc = (crc >>> 8 ^ table[(crc ^ b) & 0xff]);
+        }
+        crc = crc ^ 0xffffffff;
+        return Integer.toHexString(crc).toLowerCase();
+    }
+
+    /*
+    public static void main(String[] args) {
+
+        String str = "00000";
+//        String str = "F02F4B0000000000197B2022616374696F6E223A202268656C7022207D";
+        System.out.println("CRC32:" + getCRC32(str));
+
+         //Java自带的crc32算法
+        java.util.zip.CRC32 crc32 = new java.util.zip.CRC32();
+        crc32.update(str.getBytes());//这里没用十六进制模式
+        System.out.println("CRC32:" + Long.toHexString(crc32.getValue()));
+    }
+    */
+
+
+    /******************************************************************************
+     * Name:    CRC-32  x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
+     * Poly:    0x4C11DB7
+     * Init:    0xFFFFFFF
+     * Refin:   True
+     * Refout:  True
+     * Xorout:  0xFFFFFFF
+     * Alias:   CRC_32/ADCCP
+     * Use:     WinRAR,ect.
+     *****************************************************************************/
+    public static int crc32(byte[] data, int offset,int length){
+        byte i;
+        int crc = 0xffffffff;        // Initial value
+        length += offset;
+        for(int j=offset;j<length;j++) {
+            crc ^= data[j];
+            for (i = 0; i < 8; ++i){
+                if ((crc & 1) != 0)
+                    crc = (crc >> 1) ^ 0xEDB88320;// 0xEDB88320= reverse 0x04C11DB7
+                else
+                    crc = (crc >> 1);
+            }
+        }
+        return ~crc;
+    }
+
+
+    /******************************************************************************
+     * Name:    CRC-32/MPEG-2  x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
+     * Poly:    0x4C11DB7
+     * Init:    0xFFFFFFF
+     * Refin:   False
+     * Refout:  False
+     * Xorout:  0x0000000
+     * Note:
+     *****************************************************************************/
+    public static int crc32_mpeg_2(byte[] data,int offset, int length){
+        byte i;
+        int crc = 0xffffffff;  // Initial value
+        length += offset;
+        for(int j=offset;j<length;j++) {
+            crc ^= data[j] << 24;
+            for (i = 0; i < 8; ++i){
+                if ( (crc & 0x80000000) != 0)
+                    crc = (crc << 1) ^ 0x04C11DB7;
+                else
+                    crc <<= 1;
+            }
+        }
+        return crc;
+    }
+
+
+
+}
+
+
+
+

+ 45 - 0
traditionlib/src/main/java/rs485/JsonUtil.java

@@ -0,0 +1,45 @@
+package rs485;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+
+/**
+ * JSON 相关操作
+ * @author Sylow
+ * 需要GJSON
+ * 2015-07-14 
+ */
+public class JsonUtil {
+
+	public static String objectToJson(Object object){
+		
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.getFactory().configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true);
+		String jsonStr = "";
+		try {
+			jsonStr  = mapper.writeValueAsString(object);
+			
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return jsonStr;
+	}
+
+	/*public static void main(String[] args){
+		String json = "[{'name':'1'},{'name':'2'}]";
+		List<Map> list = new ArrayList<Map>();
+		JsonArray jsonArray = parseJsonArray(json);
+		for (int i = 0; i < jsonArray.size(); i++) {
+			Object value = jsonArray.get(i);
+			Map<String,Object> map = toMap(value.toString());
+			list.add(map);
+		}
+
+		for(Map map : list){
+			System.out.println(map.get("name"));
+		}
+
+	}*/
+
+}

+ 230 - 0
traditionlib/src/main/java/rs485/Rs485Calling.java

@@ -0,0 +1,230 @@
+package rs485;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.PropertyNamingStrategy;
+import com.fasterxml.jackson.databind.annotation.JsonNaming;
+
+import java.io.Serializable;
+
+/**
+ * 描述
+ *
+ * @author allen
+ * 2021-09-02 19:41
+ */
+@JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
+public class Rs485Calling implements Serializable {
+    private Boolean counter;
+
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private String helpButtonStyle;
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private Boolean helpButtonValid;
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private String helpButtonText;
+
+
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private String callButtonStyle;
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private Boolean callButtonValid;
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private String callButtonText;
+
+    //@JsonInclude(JsonInclude.Include.NON_NULL)
+    private String statusText;
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private String statusFgColor;
+    @JsonInclude(JsonInclude.Include.NON_NULL)
+    private String statusBgColor;
+
+    private Integer state;
+
+    public Boolean getCounter() {
+        return counter;
+    }
+
+    public void setCounter(Boolean counter) {
+        this.counter = counter;
+    }
+
+    public String getHelpButtonStyle() {
+        return helpButtonStyle;
+    }
+
+    public void setHelpButtonStyle(String helpButtonStyle) {
+        this.helpButtonStyle = helpButtonStyle;
+    }
+
+    public Boolean getHelpButtonValid() {
+        return helpButtonValid;
+    }
+
+    public void setHelpButtonValid(Boolean helpButtonValid) {
+        this.helpButtonValid = helpButtonValid;
+    }
+
+    public String getHelpButtonText() {
+        return helpButtonText;
+    }
+
+    public void setHelpButtonText(String helpButtonText) {
+        this.helpButtonText = helpButtonText;
+    }
+
+    public String getCallButtonStyle() {
+        return callButtonStyle;
+    }
+
+    public void setCallButtonStyle(String callButtonStyle) {
+        this.callButtonStyle = callButtonStyle;
+    }
+
+    public Boolean getCallButtonValid() {
+        return callButtonValid;
+    }
+
+    public void setCallButtonValid(Boolean callButtonValid) {
+        this.callButtonValid = callButtonValid;
+    }
+
+    public String getCallButtonText() {
+        return callButtonText;
+    }
+
+    public void setCallButtonText(String callButtonText) {
+        this.callButtonText = callButtonText;
+    }
+
+    public String getStatusText() {
+        return statusText;
+    }
+
+    public void setStatusText(String statusText) {
+        this.statusText = statusText;
+    }
+
+    public String getStatusFgColor() {
+        return statusFgColor;
+    }
+
+    public void setStatusFgColor(String statusFgColor) {
+        this.statusFgColor = statusFgColor;
+    }
+
+    public String getStatusBgColor() {
+        return statusBgColor;
+    }
+
+    public void setStatusBgColor(String statusBgColor) {
+        this.statusBgColor = statusBgColor;
+    }
+
+    public Integer getState() {
+        return state;
+    }
+
+    public void setState(Integer state) {
+        this.state = state;
+    }
+
+
+    public static String buildVoice485Msg(Integer state, String addr) {
+        Rs485Calling model = new Rs485Calling();
+
+        switch (state){
+            case 0: //初始状态
+                model.setCounter(false);
+
+                model.setCallButtonStyle("light");
+                model.setCallButtonValid(true);
+                StringBuilder sb = new StringBuilder();
+                
+                sb.append("\uf879").append(" ").append("呼叫");
+                model.setCallButtonText(sb.toString());
+                //model.setCallButtonText("呼叫");
+
+                model.setHelpButtonStyle("light");
+                model.setHelpButtonValid(true);
+                sb = new StringBuilder();
+
+                sb.append("\uf0c0").append(" ").append("增援");
+                model.setHelpButtonText(sb.toString());
+
+                //model.setHelpButtonText("增援");
+
+                model.setStatusText("");
+                model.setStatusFgColor("#2f9df1");
+                model.setStatusBgColor("#FFFFFF");
+                model.setState(0);
+                break;
+            case 1: //等待接听
+                model.setCounter(true);
+
+                model.setHelpButtonStyle("light");
+                model.setHelpButtonValid(true);
+                model.setHelpButtonText("\uf0c0 增援");
+                //model.setHelpButtonText("增援");
+
+                model.setCallButtonStyle("danger");
+                model.setCallButtonValid(true);
+                model.setCallButtonText("\uf3dd 取消");
+                //model.setCallButtonText("取消");
+                model.setStatusText("等待接听");
+                model.setStatusFgColor("#FFFFFF");
+                model.setStatusBgColor("#FF8c00");
+                model.setState(1);
+                break;
+            case 2:
+                model.setCounter(true);
+
+                // model.setHelpButtonStyle("light");
+                // model.setHelpButtonValid(true);
+                // model.setHelpButtonText("\uf0c0 增援");
+                //model.setHelpButtonText("增援");
+
+                model.setCallButtonStyle("danger");
+                model.setCallButtonValid(true);
+                model.setCallButtonText("\uf3dd 挂断");
+                //model.setCallButtonText("挂断");
+
+                model.setStatusText("通话中");
+                model.setStatusFgColor("#ffffff");
+                model.setStatusBgColor("#33cc00");
+                model.setState(2);
+                break;
+            case 3:
+                model.setCounter(true);
+
+                model.setCallButtonStyle("primary");
+                model.setCallButtonValid(true);
+                model.setCallButtonText("\uf879 接听");
+                //model.setCallButtonText("接听");
+
+                model.setHelpButtonStyle("danger");
+                model.setHelpButtonValid(true);
+                model.setHelpButtonText("\uf3dd 拒绝");
+                //model.setHelpButtonText("拒绝");
+
+                model.setStatusText("来电");
+                model.setStatusFgColor("#FFFFFF");
+                model.setStatusBgColor("#FF8c00");
+                model.setState(3);
+                break;
+        }
+        
+        String rs485msg = TransDto.buildMsg("0000", addr, JsonUtil.objectToJson(model));
+
+        return rs485msg;
+    }
+
+    public static String unicodeToString(String unicode) {
+        StringBuffer sb = new StringBuffer();
+        String[] hex = {unicode};
+        for (int i = 1; i < hex.length; i++) {
+          int index = Integer.parseInt(hex[i], 16);
+          sb.append((char) index);
+        }
+        return sb.toString();
+      }
+}

+ 34 - 0
traditionlib/src/main/java/rs485/Rs485Decoder.java

@@ -0,0 +1,34 @@
+package rs485;
+
+public class Rs485Decoder {
+
+    public 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();
+    }
+
+    public static String toHexString1(byte[] b) {
+        StringBuffer buffer = new StringBuffer();
+        for (int i = 0; i < b.length; ++i) {
+            buffer.append(toHexString1(b[i]));
+        }
+        return buffer.toString();
+    }
+
+    public static String toHexString1(byte b) {
+        String s = Integer.toHexString(b & 0xFF);
+        if (s.length() == 1) {
+            return "0" + s;
+        } else {
+            return s;
+        }
+    }
+
+}

+ 16 - 0
traditionlib/src/main/java/rs485/Rs485Encoder.java

@@ -0,0 +1,16 @@
+package rs485;
+
+
+public class Rs485Encoder {
+
+    public static byte[] hexString2Bytes(String src) {
+        int l = src.length() / 2;
+        byte[] ret = new byte[l];
+        for (int i = 0; i < l; i++) {
+            ret[i] = (byte) Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
+        }
+        return ret;
+
+    }
+
+}

+ 163 - 0
traditionlib/src/main/java/rs485/TransDto.java

@@ -0,0 +1,163 @@
+package rs485;
+
+import java.io.Serializable;
+
+public class TransDto implements Serializable {
+    private String header;
+    private String fromAddr;
+    private String toAddr;
+    private Integer size;
+    private String sizeStr;
+    private String jsonStr;
+    private String crcStr;
+
+    public String getHeader() {
+        return header;
+    }
+
+    public void setHeader(String header) {
+        this.header = header;
+    }
+
+    public String getFromAddr() {
+        return fromAddr;
+    }
+
+    public void setFromAddr(String fromAddr) {
+        this.fromAddr = fromAddr;
+    }
+
+    public String getToAddr() {
+        return toAddr;
+    }
+
+    public void setToAddr(String toAddr) {
+        this.toAddr = toAddr;
+    }
+
+    public Integer getSize() {
+        return size;
+    }
+
+    public void setSize(Integer size) {
+        this.size = size;
+    }
+
+    public String getSizeStr() {
+        return sizeStr;
+    }
+
+    public void setSizeStr(String sizeStr) {
+        this.sizeStr = sizeStr;
+    }
+
+    public String getJsonStr() {
+        return jsonStr;
+    }
+
+    public void setJsonStr(String jsonStr) {
+        this.jsonStr = jsonStr;
+    }
+
+    public String getCrcStr() {
+        return crcStr;
+    }
+
+    public void setCrcStr(String crcStr) {
+        this.crcStr = crcStr;
+    }
+
+    //-------------------------- method
+    public static TransDto trans2Dto(String hexString){
+        TransDto transDto = new TransDto();
+        transDto.setHeader(hexString.substring(0,2));
+        transDto.setFromAddr(hexString.substring(2,6));
+        transDto.setToAddr(hexString.substring(6,10));
+        String sizeStr = hexString.substring(10,18);
+        Integer size = Integer.parseInt(sizeStr,16);
+        transDto.setSize(size*2);
+        //7B20 2261 6374 696F 6E22 3A20 2263 616C 6C22 207D 00 ---> 21
+        //7B2022616374696F6E223A20226375742063616C6C22207D00
+
+        transDto.setJsonStr(hexString.substring(18,18+transDto.getSize()-8));
+        transDto.setCrcStr(hexString.substring(hexString.length()-8));
+
+        //String crc32CheckStr = hexString.substring(0,hexString.length()-8);
+        //String crc32ResultStr = CRC32.getCRC32(crc32CheckStr);
+
+        //System.out.println(crc32CheckStr + "   ->CRC32:" + crc32ResultStr);
+
+        //System.out.println(transDto.getJsonStr() + " " + ByteUtil.hexStr2Str(transDto.getJsonStr()) + " crc32 " + transDto.getCrcStr());
+        return transDto;
+    }
+
+/*    public static void main(String[] args) {
+        Rs485SystemSetting rs485SystemSetting = new Rs485SystemSetting();
+        rs485SystemSetting.setNvmemSync(true);
+        rs485SystemSetting.setVoiceAddr("1293");
+        String msg = buildMsg("eb79", JsonUtil.objectToJson(rs485SystemSetting));
+    }*/
+
+    public String getDtoHexStr(){
+        return (this.header + this.fromAddr + this.toAddr + this.sizeStr + this.jsonStr + this.crcStr).toLowerCase();
+    }
+
+    /**
+     *
+     * @param c
+     * @param length
+     * @param content
+     * @return
+     */
+    public static String paddingLeft(char c, long length, String content){
+        String str = "";
+        String cs = "";
+        if (content.length() > length){
+            str = content;
+        }else{
+            for (int i = 0; i < length - content.length(); i++){
+                cs = c + cs;
+            }
+        }
+        str = cs + content;
+        return str;
+    }
+
+    public static String buildMsg(String toAddr, String jsonStr){
+        return buildMsg("0000", toAddr, jsonStr);
+    }
+
+    public static String buildMsg(String fromAddr, String toAddr, String jsonStr){
+        TransDto transDto = new TransDto();
+        transDto.setHeader("f0");
+        transDto.setFromAddr(fromAddr);
+        transDto.setToAddr(toAddr);
+        String hexJsonStr = ByteUtil.str2HexStr(jsonStr)+"00";
+        transDto.setJsonStr(hexJsonStr);
+        System.out.println( "send json msg >>> " + jsonStr);
+        //calculate size
+        Integer size = hexJsonStr.length() + 8;
+        transDto.setSize(size/2);
+        //calculate crc32 string
+        String sizeHexStr = Integer.toHexString(transDto.size).toLowerCase();
+        transDto.sizeStr = paddingLeft('0',8,sizeHexStr);
+        String crc32CheckString = (transDto.header + transDto.fromAddr + transDto.toAddr + transDto.sizeStr + transDto.jsonStr).toLowerCase();
+        String hexCrc32Str = CRC32.getCRC32(crc32CheckString);
+
+        transDto.setCrcStr(hexCrc32Str);
+
+        String msg = transDto.getDtoHexStr();
+        System.out.println( "send hex msg >>> " + msg);
+        return msg;
+    }
+
+    public static byte[] hexString2Bytes(String src) {
+        int l = src.length() / 2;
+        byte[] ret = new byte[l];
+        for (int i = 0; i < l; i++) {
+            ret[i] = (byte) Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
+        }
+        return ret;
+
+    }
+}

+ 290 - 0
traditionlib/src/main/java/serialporttest/utils/SerialPort485Util.java

@@ -0,0 +1,290 @@
+package serialporttest.utils;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import android_serialport_api.Device;
+import android_serialport_api.SerialPort;
+import android_serialport_api.SerialPortFinder;
+import rs485.Rs485Encoder;
+
+public class SerialPort485Util {
+    private String TAG = "SerialPort485Util";
+
+    public SerialPort serialPort = null;
+    public InputStream inputStream = null;
+    public OutputStream outputStream = null;
+
+    private ISerialPortData onDataReceiveListener = null;
+    public boolean isOpenSerialPortUtil = false;
+
+    private HandlerThread mSendingHandlerThread;
+    private Handler mSendingHandler;
+    public Thread receiveThread = null;
+
+    public static SerialPort485Util instance = null;
+
+    public SerialPort485Util() {
+    }
+
+    public static SerialPort485Util getInstance() {
+        if (instance == null) {
+            synchronized (SerialPort485Util.class) {
+                if (instance == null) {
+                    instance = new SerialPort485Util();
+                }
+            }
+        }
+        return instance;
+    }
+
+    /**
+     * 打开串口的方法
+     */
+    public void openSerialPort(ISerialDevice callback) {
+        try {
+            serialPort = new SerialPort(new File("/dev/ttyS0"), 19200, 0);
+            //获取打开的串口中的输入输出流,以便于串口数据的收发
+            inputStream = serialPort.getInputStream();
+            outputStream = serialPort.getOutputStream();
+            isOpenSerialPortUtil = true;
+            receiveSerialPort();
+            // 开启发送消息的线程
+            startSendThread();
+            Log.i(TAG, "打开串口ttyS0: 成功");
+        } catch (IOException e) {
+            Log.e(TAG, "打开串口ttyS0: 失败");
+            e.printStackTrace();
+        }
+
+        SerialPortFinder serialPortFinder = new SerialPortFinder();
+        ArrayList<Device> devices = serialPortFinder.getDevices();
+        for (Device device1 : devices) {
+            File file = device1.getFile();
+            boolean canRead = file.canRead();
+            boolean canWrite = file.canWrite();
+            //boolean canExecute = file.canExecute();
+
+            Log.e(TAG, "serial device: " + device1.getFile().getAbsolutePath() + ", canRead=" + canRead + ", canWrite=" + canWrite);
+        }
+
+        if (callback != null) {
+            callback.onDevice(devices);
+        }
+    }
+
+    /**
+     * 接收串口数据的方法
+     */
+    private byte[] buffer;
+
+    public void receiveSerialPort() {
+        Log.i(TAG, "接收串口数据");
+        if (receiveThread != null)
+            return;
+        //buffer = new byte[1024];
+        receiveThread = new Thread() {
+            @Override
+            public void run() {
+                while (isOpenSerialPortUtil) {
+                    /*try {
+                        if (inputStream == null) {
+                            return;
+                        }
+
+                        int size = inputStream.read(buffer);
+                        if (size > 0) {
+                            byte[] data = new byte[size];
+                            System.arraycopy(buffer, 0, data, 0, size);
+                            Log.d(TAG, "received data size==" + size);
+                            if (null != onDataReceiveListener) {
+                                onDataReceiveListener.onSerialPortData(data);
+                            }
+                        }
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }*/
+
+                    try {
+                        //Thread.sleep(100);
+                        if (inputStream == null) {
+                            return;
+                        }
+                        int count = inputStream.available();
+                        if (count <= 0) {
+                            continue;
+                        }
+
+                        //Log.i(TAG, "run: ");
+                        byte[] readBuffer = new byte[count];
+                        int size = inputStream.read(readBuffer);
+
+                        Log.d(TAG, "received data size: " + size + ", data: " + Arrays.toString(readBuffer));
+
+                        //byte[] readBytes = new byte[size];
+                        //System.arraycopy(mReadBuffer, 0, readBytes, 0, size);
+                        //onDataReceived(readBytes);
+
+                        if (null != onDataReceiveListener) {
+                            onDataReceiveListener.onSerialPortData(readBuffer);
+                        }
+
+                        //Thread.sleep(150);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                        return;
+                    }
+                }
+            }
+        };
+
+        //启动接收线程
+        receiveThread.start();
+    }
+
+    /**
+     * 关闭串口的方法
+     * 关闭串口中的输入输出流
+     * 然后将flag的值设为flag,终止接收数据线程
+     */
+    public void closeSerialPort() {
+        Log.i(TAG, "关闭串口");
+        try {
+            if (inputStream != null) {
+                inputStream.close();
+            }
+            if (outputStream != null) {
+                outputStream.close();
+            }
+            if (receiveThread != null && receiveThread.isAlive()) {
+                receiveThread.interrupt();
+                receiveThread = null;
+            }
+            stopSendThread();
+            isOpenSerialPortUtil = false;
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+    }
+
+
+    /**
+     * 发送串口数据的方法
+     *
+     * @param command 要发送的数据
+     */
+    public void sendStringData(String command) {
+        try {
+            if (isOpenSerialPortUtil) {
+                byte[] sendData = command.getBytes();
+                outputStream.write(sendData);
+                Log.i(TAG, "串口数据发送成功:" + command);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            Log.i(TAG, "串口数据发送失败");
+        }
+    }
+
+    /**
+     * 发送串口数据的方法
+     *
+     * @param data 要发送的数据
+     */
+    public void sendByteData(byte[] data) {
+        if (isOpenSerialPortUtil && outputStream != null) {
+            if (null != mSendingHandler) {
+                Message message = Message.obtain();
+                message.obj = data;
+                mSendingHandler.sendMessage(message);
+            }
+        }
+    }
+
+    public void sendSerialHexString(String msg) {
+        Log.e(TAG, "sendHexString: " + msg);
+
+        sendByteData(Rs485Encoder.hexString2Bytes(msg));
+    }
+
+    /**
+     * 开启发送消息的线程
+     */
+    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 != outputStream && null != sendBytes && 0 < sendBytes.length) {
+                    try {
+                        outputStream.write(sendBytes);
+                        //Log.e(TAG, "send rs485 data: " + bytesToHexString(sendBytes));
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        };
+    }
+
+    /**
+     * 停止发送消息线程
+     */
+    private void stopSendThread() {
+        mSendingHandler = null;
+        if (null != mSendingHandlerThread) {
+            mSendingHandlerThread.interrupt();
+            mSendingHandlerThread.quit();
+            mSendingHandlerThread = null;
+        }
+    }
+
+    public void setOnDataReceiveListener(ISerialPortData dataReceiveListener) {
+        onDataReceiveListener = dataReceiveListener;
+    }
+
+    public interface ISerialPortData {
+        void onSerialPortData(byte[] str);
+    }
+
+    public interface ISerialDevice {
+        void onDevice(ArrayList<Device> device);
+    }
+
+    public static byte[] hexString2Bytes(String src) {
+        int l = src.length() / 2;
+        byte[] ret = new byte[l];
+        for (int i = 0; i < l; i++) {
+            ret[i] = (byte) Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
+        }
+        return ret;
+    }
+
+    public static String bytesToHexString(byte[] bArray) {
+        StringBuilder sb = new StringBuilder(bArray.length);
+        String sTemp;
+        for (byte b : bArray) {
+            sTemp = Integer.toHexString(0xFF & b);
+            if (sTemp.length() < 2)
+                sb.append(0);
+            //sb.append(sTemp.toUpperCase());
+            sb.append(sTemp);
+        }
+        return sb.toString();
+    }
+}