Browse Source

add SerialPort lib

dev
MTing 2 days ago
parent
commit
261dccc7e5
  1. 1
      lib-serialport/.gitignore
  2. 33
      lib-serialport/build.gradle
  3. 17
      lib-serialport/proguard-rules.pro
  4. 9
      lib-serialport/src/main/AndroidManifest.xml
  5. 9
      lib-serialport/src/main/cpp/CMakeLists.txt
  6. 167
      lib-serialport/src/main/cpp/SerialPort.c
  7. 30
      lib-serialport/src/main/cpp/SerialPort.h
  8. 48
      lib-serialport/src/main/java/com/kongqw/serialportlibrary/Device.java
  9. 54
      lib-serialport/src/main/java/com/kongqw/serialportlibrary/Driver.java
  10. 47
      lib-serialport/src/main/java/com/kongqw/serialportlibrary/SerialPort.java
  11. 66
      lib-serialport/src/main/java/com/kongqw/serialportlibrary/SerialPortFinder.java
  12. 187
      lib-serialport/src/main/java/com/kongqw/serialportlibrary/SerialPortManager.java
  13. 23
      lib-serialport/src/main/java/com/kongqw/serialportlibrary/listener/OnSerialPortDataListener.java
  14. 231
      lib-serialport/src/main/java/com/kongqw/serialportlibrary/thread/SerialPortReadThread.java
  15. 487
      lib-serialport/src/main/java/com/kongqw/serialportlibrary/utils/ByteUtils.java
  16. 3
      lib-serialport/src/main/res/values/strings.xml

1
lib-serialport/.gitignore

@ -0,0 +1 @@
/build

33
lib-serialport/build.gradle

@ -0,0 +1,33 @@
apply plugin: 'com.android.library'
android {
compileSdkVersion 32
defaultConfig {
minSdkVersion 21
targetSdkVersion 32
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
arguments '-DANDROID_TOOLCHAIN=clang'
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}
}
dependencies {
}

17
lib-serialport/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
lib-serialport/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
lib-serialport/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
lib-serialport/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
lib-serialport/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
lib-serialport/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
lib-serialport/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
lib-serialport/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
lib-serialport/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;
}
}

187
lib-serialport/src/main/java/com/kongqw/serialportlibrary/SerialPortManager.java

@ -0,0 +1,187 @@
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.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 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: 没有读写权限");
return false;
}
}
try {
mFd = open(device.getAbsolutePath(), baudRate, 0);
mFileInputStream = new FileInputStream(mFd);
mFileOutputStream = new FileOutputStream(mFd);
Log.i(TAG, "openSerialPort: 串口已经打开 " + mFd);
return true;
} catch (Exception e) {
e.printStackTrace();
}
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;
}
mOnSerialPortDataListener = null;
}
/**
* 添加数据通信监听
*
* @param listener listener
* @return SerialPortManager
*/
public SerialPortManager setOnSerialPortDataListener(OnSerialPortDataListener listener) {
mOnSerialPortDataListener = listener;
return this;
}
/**
* 开启发送消息的线程
*/
public 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();
}
}
}
};
}
/**
* 停止发送消息线程
*/
public void stopSendThread() {
mSendingHandler = null;
if (null != mSendingHandlerThread) {
mSendingHandlerThread.interrupt();
mSendingHandlerThread.quit();
mSendingHandlerThread = null;
}
}
/**
* 开启接收消息的线程
*/
public void startReadThread(int type) {
mSerialPortReadThread = new SerialPortReadThread(mFileInputStream, type) {
@Override
public void onDataReceived(byte[] bytes) {
if (null != mOnSerialPortDataListener) {
mOnSerialPortDataListener.onDataReceived(bytes);
}
}
};
mSerialPortReadThread.startRead();
}
/**
* 停止接收消息的线程
*/
public void stopReadThread() {
if (null != mSerialPortReadThread) {
mSerialPortReadThread.stopRead();
}
}
/**
* 发送数据
*
* @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;
}
}

23
lib-serialport/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);
}

231
lib-serialport/src/main/java/com/kongqw/serialportlibrary/thread/SerialPortReadThread.java

@ -0,0 +1,231 @@
package com.kongqw.serialportlibrary.thread;
import android.util.Log;
import com.kongqw.serialportlibrary.utils.ByteUtils;
import java.io.IOException;
import java.io.InputStream;
/**
* Created by Kongqw on 2017/11/14.
* 串口消息读取线程
*/
public abstract class SerialPortReadThread extends Thread {
public abstract void onDataReceived(byte[] bytes);
private InputStream mInputStream;
private final byte[] mReadBuffer;
public boolean isStopThread = false;
private int type = 0;
public SerialPortReadThread(InputStream inputStream, int type) {
mInputStream = inputStream;
mReadBuffer = new byte[1024];
this.type = type;
}
@Override
public void run() {
super.run();
if (type == 485) {
Log.e("ReadThread", "type 485");
while (!isStopThread) {
try {
if (null == mInputStream) {
return;
}
Log.e("ReadThread", "type 1111");
int size = mInputStream.read(mReadBuffer);
Log.e("ReadThread size", size + "");
if (size <= 0) {
return;
}
Log.e("ReadThread", "type 2222");
byte[] readBytes = new byte[size];
System.arraycopy(mReadBuffer, 0, readBytes, 0, size);
onDataReceived(readBytes);
Log.e("ReadThread", "onDataReceived");
} catch (IOException e) {
e.printStackTrace();
return;
}
}
} else {
int rLen = 0;
int dLen = 0;
byte[] crc = new byte[]{0};
byte[] tmp1 = new byte[]{0};
byte[] tmp2 = new byte[]{0};
while (!isStopThread) {
try {
if (mInputStream == null) {
return;
}
if (!isHead()) {
continue;
}
crc[0] = 0x55;
crc[0] ^= 0xAA;
//接收 cmd
rLen = recvBuffer(tmp1, 1, 600);
if (rLen != 1) {
continue;
}
crc[0] ^= tmp1[0];
if (tmp1[0] == 0x30) {
//接收 数据长度
rLen = recvBuffer(tmp1, 1, 600);
if (rLen != 1) {
continue;
}
//接收 数据长度
rLen = recvBuffer(tmp2, 1, 600);
if (rLen != 1) {
continue;
}
crc[0] ^= tmp1[0];
crc[0] ^= tmp2[0];
dLen = tmp1[0] & 0xff;
dLen |= ((tmp2[0] << 8) & 0xffff);
//dLen = ((uint)(tmp1[0])) | (tmp2[0] << 8);
byte[] data = new byte[dLen];
if (dLen > 0) {
rLen = recvBuffer(data, dLen, 600);
if (rLen != dLen) {
continue;
}
}
//接收 crc
rLen = recvBuffer(tmp1, 1, 600);
if (rLen != 1) {
continue;
}
for (int i = 0; i < dLen; i++) {
crc[0] ^= data[i];
}
//crc校验
if (!ByteUtils.bytesToHexString(tmp1).equals(ByteUtils.bytesToHexString(crc))) {
continue;
}
onDataReceived(data);
} else {
Log.e("idhead", "no 0x30");
}
} catch (Exception e) {
e.printStackTrace();
return;
}
}
}
}
public void startRead() {
isStopThread = false;
start();
}
public void stopRead() {
isStopThread = true;
}
/**
* 关闭线程 释放资源
*/
public void release() {
stopRead();
if (null != mInputStream) {
try {
mInputStream.close();
mInputStream = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
private int recvBuffer(byte[] buffer, int size, int msTimeout) {
long stime = System.currentTimeMillis();
int rLen = 0, offset = 0;
byte[] rBuffer = new byte[1024];
byte[] cache = new byte[1024];
try {
do {
if (mInputStream.available() <= 0) {
Thread.sleep(10);
continue;
}
rLen = mInputStream.read(rBuffer, 0, Math.min(size, rBuffer.length));
if (rLen <= 0) {
Thread.sleep(10);
continue;
}
stime = System.currentTimeMillis();
if (offset + rLen > cache.length) {
byte[] tmp = new byte[offset];
System.arraycopy(cache, 0, tmp, 0, offset);
cache = new byte[(offset + rLen) * 2];
System.arraycopy(tmp, 0, cache, 0, offset);
}
System.arraycopy(rBuffer, 0, cache, offset, rLen);
offset += rLen;
if (offset >= size) {
System.arraycopy(cache, 0, buffer, 0, size);
break;
}
} while (msTimeout > 0 && System.currentTimeMillis() - stime < msTimeout);
} catch (Exception e) {
return offset;
}
return offset;
}
private boolean isHead() {
byte[] head1 = new byte[]{0};
byte[] head2 = new byte[]{0};
while (true) {
if (head1[0] != (byte) 0x55) {
int rLen = recvBuffer(head1, 1, 500);
if (rLen != 1) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
continue;
}
}
int rLen = recvBuffer(head2, 1, 500);
if (rLen != 1) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
continue;
}
if (head1[0] != (byte) 0x55) {
head1[0] = head2[0];
continue;
}
if (head2[0] != (byte) 0xAA) {
head1[0] = head2[0];
continue;
}
return true;
}
}
}

487
lib-serialport/src/main/java/com/kongqw/serialportlibrary/utils/ByteUtils.java

@ -0,0 +1,487 @@
package com.kongqw.serialportlibrary.utils;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
/**
* @author wangsir
* <p>
* 2017年9月21日
*/
public class ByteUtils {
/**
* 将int转为高端字节序排列的byte数组Java内存存放顺序
*
* @param n
* @return
*/
public static byte[] int2ByteArray(int n) {
byte[] byteArray = null;
try {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
DataOutputStream dataOut = new DataOutputStream(byteOut);
dataOut.writeInt(n);
byteArray = byteOut.toByteArray();
Arrays.toString(byteArray);
} catch (IOException e) {
e.printStackTrace();
}
return byteArray;
}
/**
* 将int转为高字节在前低字节在后的byte数组
*
* @param n int
* @return byte[]
*/
public static byte[] int2Hbytes(int n) {
byte[] b = new byte[4];
b[3] = (byte) (n & 0xff);
b[2] = (byte) (n >> 8 & 0xff);
b[1] = (byte) (n >> 16 & 0xff);
b[0] = (byte) (n >> 24 & 0xff);
return b;
}
/**
* 将int转为高字节在前低字节在后的byte数组,一字节
*
* @param n int
* @return byte[]
*/
public static byte[] int2Hbytes1byte(int n) {
byte[] b = new byte[1];
b[0] = (byte) (n & 0xff);
return b;
}
/**
* 将short转为高字节在前低字节在后的byte数组
*
* @param n short
* @return byte[]
*/
public static byte[] short2Hbytes(short n) {
byte[] b = new byte[2];
b[1] = (byte) (n & 0xff);
b[0] = (byte) (n >> 8 & 0xff);
return b;
}
/**
* 以下 是整型数 网络字节序的 byte[] 数组之间的转换
*
* @param n
* @return
*/
public static byte[] long2Hbytes(long n) {
byte[] b = new byte[8];
b[7] = (byte) (n & 0xff);
b[6] = (byte) (n >> 8 & 0xff);
b[5] = (byte) (n >> 16 & 0xff);
b[4] = (byte) (n >> 24 & 0xff);
b[3] = (byte) (n >> 32 & 0xff);
b[2] = (byte) (n >> 40 & 0xff);
b[1] = (byte) (n >> 48 & 0xff);
b[0] = (byte) (n >> 56 & 0xff);
return b;
}
public static byte[] long2H6bytes(long n) {
byte[] b = new byte[6];
b[5] = (byte) (n & 0xff);
b[4] = (byte) (n >> 8 & 0xff);
b[3] = (byte) (n >> 16 & 0xff);
b[2] = (byte) (n >> 24 & 0xff);
b[1] = (byte) (n >> 32 & 0xff);
b[0] = (byte) (n >> 40 & 0xff);
return b;
}
public static byte[] long2H4bytes(long n) {
byte[] b = new byte[4];
b[3] = (byte) (n & 0xff);
b[2] = (byte) (n >> 8 & 0xff);
b[1] = (byte) (n >> 16 & 0xff);
b[0] = (byte) (n >> 24 & 0xff);
return b;
}
public static byte[] unlong2H4bytes(long n) {
byte[] b = new byte[4];
b[0] = (byte) (n & 0xff);
b[1] = (byte) (n >> 8 & 0xff);
b[2] = (byte) (n >> 16 & 0xff);
b[3] = (byte) (n >> 24 & 0xff);
return b;
}
/**
* 合并数组
*
* @param first
* @param rest
* @return
*/
public static byte[] concatBytes(byte[] first, byte[]... rest) {
int totalLength = first.length;
for (byte[] array : rest) {
if (null != array) {
totalLength += array.length;
}
}
byte[] result = Arrays.copyOf(first, totalLength);
int offset = first.length;
for (byte[] array : rest) {
if (null != array) {
System.arraycopy(array, 0, result, offset, array.length);
offset += array.length;
}
}
return result;
}
/**
* byte数组转为十六进制字符串
*
* @param bytes
* @return
*/
public static String byte2Hex(byte[] bytes) {
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(0xff & bytes[i]);
if (hex.length() == 1) {
hexString.append('0');
}
hexString.append(hex);
}
return hexString.toString();
}
/**
* Convert hex string to byte[]
*
* @param hexString the hex string
* @return byte[]
*/
public static byte[] hex2Byte(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase().replace(" ", "");
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}
/**
* Convert char to byte
*
* @param c char
* @return byte
*/
private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
/**
* 输入流转为字节数组
*/
public static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[4096];
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
return output.toByteArray();
}
/**
* bytes字符串转换为Byte值
*
* @param src src Byte字符串每个Byte之间没有分隔符
* @return byte[]
*/
public static byte[] hexStr2Bytes(String src) {
int m = 0, n = 0;
int l = src.length() / 2;
byte[] ret = new byte[l];
for (int i = 0; i < l; i++) {
m = i * 2 + 1;
n = m + 1;
ret[i] = Byte.decode("0x" + src.substring(i * 2, m) + src.substring(m, n));
}
return ret;
}
// /**
// * 字节数组转换成16进制字符串
// * @param bytes 字节数组
// * @return 16进制字符串
// */
// public static String hexEncode(byte[] bytes) {
// if (bytes == null || bytes.length <= 0) {
// return null;
// }
// return new String(Hex.encodeHex(bytes)); //Hex.encodeHex(bytes, false)
// }
//
// /**
// * 16进制字符串转换成字节数组
// * @param hexStr 16进制字符串
// * @return 字节数组
// */
// public static byte[] hexDecode(String hexStr) {
// if (hexStr == null || "".equals(hexStr)) {
// return null;
// }
// try {
// char[] cs = hexStr.toCharArray();
// return Hex.decodeHex(cs);
// } catch (DecoderException e) {
// e.printStackTrace();
// }
// return null;
// }
/**
* 字符串转换成十六进制字符串
*
* @param s s为待转换的ASCII字符串
*/
public static String str2HexStr(String s) {
String str = "";
for (int i = 0; i < s.length(); i++) {
int ch = (int) s.charAt(i);
String s4 = Integer.toHexString(ch);
str = str + s4;
}
return str;
}
public static String int2HexStr(Integer n) {
String str = Integer.toHexString(n);
while (str.length() < 18) {
str = "0" + str;
}
return str.toUpperCase();
}
public static String binaryToHex(String bin) {
String str = Long.toHexString(Long.parseLong(bin, 2));
while (str.length() < 4) {
str = "0" + str;
}
return str.toUpperCase();
}
/**
* 16进制的字符串转byte数组
*
* @param src
* @return
*/
public static byte[] str16ToBytes(String src) {
int w = 0;
byte[] bytes_2 = new byte[src.length() / 2];
for (int i = 0; i < src.length(); i++) {
String zz = src.substring(i, i + 2);
byte aaa = (byte) Integer.parseInt(zz, 16);
bytes_2[w] = aaa;
i++;
w = w + 1;
}
return bytes_2;
}
/**
* 16进制转10进制数字
*
* @param src
* @return
*/
public static int str16ToInt10(String src) {
return Integer.parseInt(src, 16);
}
/**
* 16进制转10进制数字
*
* @param src
* @return
*/
public static long str16ToLong10(String src) {
return Long.parseLong(src, 16);
}
public static String convertStringToHex(String str) {
char[] chars = str.toCharArray();
StringBuffer hex = new StringBuffer();
for (int i = 0; i < chars.length; i++) {
hex.append(Integer.toHexString((int) chars[i]));
}
return hex.toString();
}
public static String convertHexToString(String hex) {
hex = hex.replace(" ", "");
StringBuilder sb = new StringBuilder();
StringBuilder temp = new StringBuilder();
//49204c6f7665204a617661 split into two characters 49, 20, 4c...
for (int i = 0; i < hex.length() - 1; i += 2) {
//grab the hex in pairs
String output = hex.substring(i, (i + 2));
//convert hex to decimal
int decimal = Integer.parseInt(output, 16);
//convert the decimal to character
sb.append((char) decimal);
temp.append(decimal);
}
return sb.toString();
}
/**
* @param
* @ClassName
* @Description : 功能说明
* @Return :
* @Author : li
* @Date : 2021/3/25 13:48
*/
public static byte[] hexStringToByteArray(String hexString) {
hexString = hexString.replaceAll(" ", "");
int len = hexString.length();
byte[] bytes = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
// 两位一组表示一个字节,把这样表示的16进制字符串还原成一个字节
bytes[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character
.digit(hexString.charAt(i + 1), 16));
}
return bytes;
}
/**
* @param
* @ClassName
* @Description : 功能说明
* @Return :
* @Author : li
* @Date : 2021/3/25 13:48
*/
public static String bytesToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(0xFF & bytes[i]);
if (hex.length() == 1) {
sb.append('0');
}
sb.append(hex);
}
return sb.toString();
}
/**
* 从16进制字符串中获取2进制为1的序列号
*
* @param src
* @return
*/
public static ArrayList Str16Get1(String src) {
byte[] b_p = ByteUtils.str16ToBytes(src);
ArrayList list = new ArrayList<>();
int w = 0;
for (int i = 0; i < src.length() / 2; i++) {
for (int j = 7; j >= 0; j--) {
if ((b_p[i] & (1 << j)) != 0) {
int pp = i * 8 + 8 - j;
System.out.println("pppp=======" + pp);
list.add(w, pp);
w = w + 1;
} else {
}
}
}
return list;
}
/**
* 异或校验
*
* @param bytes
* @return
*/
public static byte[] bytesXorCrc(byte[] bytes) {
byte[] crc = new byte[1];// 异或校验
crc[0] = bytes[0];
for (int i = 1; i < bytes.length; i++) {
crc[0] ^= bytes[i];
}
return crc;
}
/**
* 和校验
*
* @param data
* @return
*/
public static String makeChecksum(String data) {
data = data.replace(" ", "");
if (data == null || data.equals("")) {
return "";
}
int total = 0;
int len = data.length();
int num = 0;
while (num < len) {
String s = data.substring(num, num + 2);
total += Integer.parseInt(s, 16);
num = num + 2;
}
/**
* 用256求余最大是255即16进制的FF
*/
int mod = total % 256;
String hex = Integer.toHexString(mod);
len = hex.length();
// 如果不够校验位的长度补0,这里用的是两位校验
if (len < 2) {
hex = "0" + hex;
}
hex = hex.toUpperCase();
if (hex.equals("7E")) {
hex = "7F 01";
} else if (hex.equals("7F")) {
hex = "7F 02";
}
return hex;
}
}

3
lib-serialport/src/main/res/values/strings.xml

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