diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
new file mode 100644
index 0000000..c7229ad
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
@@ -0,0 +1,100 @@
+package com.casic.detector.base
+
+import android.os.Bundle
+import android_serialport_api.SerialPort
+import androidx.appcompat.app.AppCompatActivity
+import com.pengxh.kt.lite.extensions.show
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.security.InvalidParameterException
+
+
+abstract class SerialPortActivity : AppCompatActivity() {
+
+ private var serialPort: SerialPort? = null
+ var outputStream: OutputStream? = null
+ private var inputStream: InputStream? = null
+ private var readThread: ReadThread? = null
+
+ inner class ReadThread : Thread() {
+ override fun run() {
+ super.run()
+ while (!isInterrupted) {
+ var size: Int
+ try {
+ val buffer = ByteArray(64)
+ if (inputStream == null) return
+ size = inputStream!!.read(buffer)
+ if (size > 0) {
+ onDataReceived(buffer, size)
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(initLayoutView())
+ setupTopBarLayout()
+ initData(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ try {
+ serialPort = BaseApplication.get().getSerialPort()
+ outputStream = serialPort?.outputStream
+ inputStream = serialPort?.inputStream
+
+ readThread = ReadThread()
+ readThread?.start()
+ } catch (e: SecurityException) {
+ "您没有串口的读写权限!".show(this)
+ } catch (e: IOException) {
+ "因为不明原因,串口无法打开!".show(this)
+ } catch (e: InvalidParameterException) {
+ "请检查串口!".show(this)
+ }
+ }
+
+ /**
+ * 初始化xml布局
+ */
+ abstract fun initLayoutView(): Int
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initData(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ /**
+ * 串口读数
+ * */
+ abstract fun onDataReceived(buffer: ByteArray?, size: Int)
+
+ override fun onDestroy() {
+ readThread?.interrupt()
+ BaseApplication.get().closeSerialPort()
+ serialPort = null
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
new file mode 100644
index 0000000..c7229ad
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
@@ -0,0 +1,100 @@
+package com.casic.detector.base
+
+import android.os.Bundle
+import android_serialport_api.SerialPort
+import androidx.appcompat.app.AppCompatActivity
+import com.pengxh.kt.lite.extensions.show
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.security.InvalidParameterException
+
+
+abstract class SerialPortActivity : AppCompatActivity() {
+
+ private var serialPort: SerialPort? = null
+ var outputStream: OutputStream? = null
+ private var inputStream: InputStream? = null
+ private var readThread: ReadThread? = null
+
+ inner class ReadThread : Thread() {
+ override fun run() {
+ super.run()
+ while (!isInterrupted) {
+ var size: Int
+ try {
+ val buffer = ByteArray(64)
+ if (inputStream == null) return
+ size = inputStream!!.read(buffer)
+ if (size > 0) {
+ onDataReceived(buffer, size)
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(initLayoutView())
+ setupTopBarLayout()
+ initData(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ try {
+ serialPort = BaseApplication.get().getSerialPort()
+ outputStream = serialPort?.outputStream
+ inputStream = serialPort?.inputStream
+
+ readThread = ReadThread()
+ readThread?.start()
+ } catch (e: SecurityException) {
+ "您没有串口的读写权限!".show(this)
+ } catch (e: IOException) {
+ "因为不明原因,串口无法打开!".show(this)
+ } catch (e: InvalidParameterException) {
+ "请检查串口!".show(this)
+ }
+ }
+
+ /**
+ * 初始化xml布局
+ */
+ abstract fun initLayoutView(): Int
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initData(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ /**
+ * 串口读数
+ * */
+ abstract fun onDataReceived(buffer: ByteArray?, size: Int)
+
+ override fun onDestroy() {
+ readThread?.interrupt()
+ BaseApplication.get().closeSerialPort()
+ serialPort = null
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/utils/GpioManager.java b/app/src/main/java/com/casic/detector/utils/GpioManager.java
new file mode 100644
index 0000000..0f54f1a
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/GpioManager.java
@@ -0,0 +1,121 @@
+package com.casic.detector.utils;
+
+
+public class GpioManager {
+
+ private static final int MT6761 = 0;
+ private int selected;
+ private final MT6761Gpio mt6761;
+
+ public GpioManager(int selected) {
+ this.selected = selected;
+ mt6761 = new MT6761Gpio();
+ }
+
+ public GpioManager() {
+ mt6761 = new MT6761Gpio();
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ this.selected = selected;
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳叆
+ * *********************************************************************/
+ public void setGpioInput(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioInput();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭楂�
+ * *********************************************************************/
+ public void setGpioHigh(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioHigh();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭浣�
+ * *********************************************************************/
+ public void setGpioLow(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioLow();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO鏃犱笂涓嬫媺
+ * *********************************************************************/
+ public void setNotPen(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setNotPen();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓嬫媺
+ * *********************************************************************/
+ public void setPullDown(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullDown();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓婃媺
+ * *********************************************************************/
+ public void setPullUp(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullUp();
+ }
+ }
+
+ /************************************************************************
+ * 璇诲彇鍗曚釜GPIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireSingleGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioSingle();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireAllGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioAll();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬佹爣棰�
+ * *********************************************************************/
+ public String readGpioTitle() {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ status = mt6761.readGpioTitle();
+ }
+ return status;
+ }
+}
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
new file mode 100644
index 0000000..c7229ad
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
@@ -0,0 +1,100 @@
+package com.casic.detector.base
+
+import android.os.Bundle
+import android_serialport_api.SerialPort
+import androidx.appcompat.app.AppCompatActivity
+import com.pengxh.kt.lite.extensions.show
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.security.InvalidParameterException
+
+
+abstract class SerialPortActivity : AppCompatActivity() {
+
+ private var serialPort: SerialPort? = null
+ var outputStream: OutputStream? = null
+ private var inputStream: InputStream? = null
+ private var readThread: ReadThread? = null
+
+ inner class ReadThread : Thread() {
+ override fun run() {
+ super.run()
+ while (!isInterrupted) {
+ var size: Int
+ try {
+ val buffer = ByteArray(64)
+ if (inputStream == null) return
+ size = inputStream!!.read(buffer)
+ if (size > 0) {
+ onDataReceived(buffer, size)
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(initLayoutView())
+ setupTopBarLayout()
+ initData(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ try {
+ serialPort = BaseApplication.get().getSerialPort()
+ outputStream = serialPort?.outputStream
+ inputStream = serialPort?.inputStream
+
+ readThread = ReadThread()
+ readThread?.start()
+ } catch (e: SecurityException) {
+ "您没有串口的读写权限!".show(this)
+ } catch (e: IOException) {
+ "因为不明原因,串口无法打开!".show(this)
+ } catch (e: InvalidParameterException) {
+ "请检查串口!".show(this)
+ }
+ }
+
+ /**
+ * 初始化xml布局
+ */
+ abstract fun initLayoutView(): Int
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initData(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ /**
+ * 串口读数
+ * */
+ abstract fun onDataReceived(buffer: ByteArray?, size: Int)
+
+ override fun onDestroy() {
+ readThread?.interrupt()
+ BaseApplication.get().closeSerialPort()
+ serialPort = null
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/utils/GpioManager.java b/app/src/main/java/com/casic/detector/utils/GpioManager.java
new file mode 100644
index 0000000..0f54f1a
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/GpioManager.java
@@ -0,0 +1,121 @@
+package com.casic.detector.utils;
+
+
+public class GpioManager {
+
+ private static final int MT6761 = 0;
+ private int selected;
+ private final MT6761Gpio mt6761;
+
+ public GpioManager(int selected) {
+ this.selected = selected;
+ mt6761 = new MT6761Gpio();
+ }
+
+ public GpioManager() {
+ mt6761 = new MT6761Gpio();
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ this.selected = selected;
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳叆
+ * *********************************************************************/
+ public void setGpioInput(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioInput();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭楂�
+ * *********************************************************************/
+ public void setGpioHigh(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioHigh();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭浣�
+ * *********************************************************************/
+ public void setGpioLow(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioLow();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO鏃犱笂涓嬫媺
+ * *********************************************************************/
+ public void setNotPen(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setNotPen();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓嬫媺
+ * *********************************************************************/
+ public void setPullDown(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullDown();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓婃媺
+ * *********************************************************************/
+ public void setPullUp(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullUp();
+ }
+ }
+
+ /************************************************************************
+ * 璇诲彇鍗曚釜GPIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireSingleGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioSingle();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireAllGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioAll();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬佹爣棰�
+ * *********************************************************************/
+ public String readGpioTitle() {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ status = mt6761.readGpioTitle();
+ }
+ return status;
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
new file mode 100644
index 0000000..d9d394f
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
@@ -0,0 +1,157 @@
+package com.casic.detector.utils;
+
+import java.io.BufferedReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class MT6761Gpio {
+
+ private final String filePath = "/sys/devices/platform/1000b000.pinctrl/mt_gpio";
+ private String pin;
+
+ public void setGpioHigh() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "1");
+ }
+
+ public void setGpioLow() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "0");
+ }
+
+ public void setGpioInput() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "0");
+ }
+
+ public void setNotPen() {
+ setGpioPen(pin, "0");
+ }
+
+ public void setPullUp() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "1");
+ }
+
+ public void setPullDown() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "0");
+ }
+
+ public void setCtrlPin(String gpio) {
+ pin = gpio;
+ }
+
+ public String readGpioTitle() {
+ return read(filePath, "PIN:");
+ }
+
+ public String readGpioSingle() {
+ int gpio = 0;
+ if (pin.isEmpty()) {
+ return "";
+ }
+ try {
+ gpio = Integer.parseInt(pin);
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+
+ String str = String.format("%3d", gpio).replace(" ", "0");
+ return read(filePath, pin + ":");
+ }
+
+ public String readGpioAll() {
+ return read_all(filePath);
+ }
+
+ private void setGpioMode(String pin, String value) {
+ nm_write("mode " + pin + " " + value);
+ }
+
+ private void setGpioDir(String pin, String value) {
+ nm_write("dir " + pin + " " + value);
+ }
+
+ private void setGpioOut(String pin, String value) {
+ nm_write("out " + pin + " " + value);
+ }
+
+ private void setGpioPen(String pin, String value) { //1:浣胯兘涓婁笅鎷� 0:绂佹涓婁笅鎷�
+ nm_write("pullen " + pin + " " + value);
+ }
+
+ private void setGpioPsel(String pin, String value) { //1:璁剧疆涓婃媺 0:璁剧疆涓嬫媺
+ nm_write("pullsel " + pin + " " + value);
+ }
+
+ private void nm_write(String value) {
+ if (value.isEmpty()) {
+ return;
+ }
+ FileWriter fw;
+ try {
+ fw = new FileWriter(filePath);
+ fw.write(value);
+ fw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public String read(String sys_path, String value) {
+ if (value.isEmpty()) {
+ return null;
+ }
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+
+ String line;
+ while (null != (line = br.readLine())) {
+ if (line.contains(value)) {
+ return line;
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public String read_all(String sys_path) {
+ StringBuilder value = new StringBuilder();
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+
+ while (null != (line = br.readLine())) {
+ value.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return value.toString();
+ }
+}
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
new file mode 100644
index 0000000..c7229ad
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
@@ -0,0 +1,100 @@
+package com.casic.detector.base
+
+import android.os.Bundle
+import android_serialport_api.SerialPort
+import androidx.appcompat.app.AppCompatActivity
+import com.pengxh.kt.lite.extensions.show
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.security.InvalidParameterException
+
+
+abstract class SerialPortActivity : AppCompatActivity() {
+
+ private var serialPort: SerialPort? = null
+ var outputStream: OutputStream? = null
+ private var inputStream: InputStream? = null
+ private var readThread: ReadThread? = null
+
+ inner class ReadThread : Thread() {
+ override fun run() {
+ super.run()
+ while (!isInterrupted) {
+ var size: Int
+ try {
+ val buffer = ByteArray(64)
+ if (inputStream == null) return
+ size = inputStream!!.read(buffer)
+ if (size > 0) {
+ onDataReceived(buffer, size)
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(initLayoutView())
+ setupTopBarLayout()
+ initData(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ try {
+ serialPort = BaseApplication.get().getSerialPort()
+ outputStream = serialPort?.outputStream
+ inputStream = serialPort?.inputStream
+
+ readThread = ReadThread()
+ readThread?.start()
+ } catch (e: SecurityException) {
+ "您没有串口的读写权限!".show(this)
+ } catch (e: IOException) {
+ "因为不明原因,串口无法打开!".show(this)
+ } catch (e: InvalidParameterException) {
+ "请检查串口!".show(this)
+ }
+ }
+
+ /**
+ * 初始化xml布局
+ */
+ abstract fun initLayoutView(): Int
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initData(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ /**
+ * 串口读数
+ * */
+ abstract fun onDataReceived(buffer: ByteArray?, size: Int)
+
+ override fun onDestroy() {
+ readThread?.interrupt()
+ BaseApplication.get().closeSerialPort()
+ serialPort = null
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/utils/GpioManager.java b/app/src/main/java/com/casic/detector/utils/GpioManager.java
new file mode 100644
index 0000000..0f54f1a
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/GpioManager.java
@@ -0,0 +1,121 @@
+package com.casic.detector.utils;
+
+
+public class GpioManager {
+
+ private static final int MT6761 = 0;
+ private int selected;
+ private final MT6761Gpio mt6761;
+
+ public GpioManager(int selected) {
+ this.selected = selected;
+ mt6761 = new MT6761Gpio();
+ }
+
+ public GpioManager() {
+ mt6761 = new MT6761Gpio();
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ this.selected = selected;
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳叆
+ * *********************************************************************/
+ public void setGpioInput(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioInput();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭楂�
+ * *********************************************************************/
+ public void setGpioHigh(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioHigh();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭浣�
+ * *********************************************************************/
+ public void setGpioLow(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioLow();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO鏃犱笂涓嬫媺
+ * *********************************************************************/
+ public void setNotPen(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setNotPen();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓嬫媺
+ * *********************************************************************/
+ public void setPullDown(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullDown();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓婃媺
+ * *********************************************************************/
+ public void setPullUp(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullUp();
+ }
+ }
+
+ /************************************************************************
+ * 璇诲彇鍗曚釜GPIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireSingleGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioSingle();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireAllGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioAll();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬佹爣棰�
+ * *********************************************************************/
+ public String readGpioTitle() {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ status = mt6761.readGpioTitle();
+ }
+ return status;
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
new file mode 100644
index 0000000..d9d394f
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
@@ -0,0 +1,157 @@
+package com.casic.detector.utils;
+
+import java.io.BufferedReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class MT6761Gpio {
+
+ private final String filePath = "/sys/devices/platform/1000b000.pinctrl/mt_gpio";
+ private String pin;
+
+ public void setGpioHigh() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "1");
+ }
+
+ public void setGpioLow() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "0");
+ }
+
+ public void setGpioInput() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "0");
+ }
+
+ public void setNotPen() {
+ setGpioPen(pin, "0");
+ }
+
+ public void setPullUp() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "1");
+ }
+
+ public void setPullDown() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "0");
+ }
+
+ public void setCtrlPin(String gpio) {
+ pin = gpio;
+ }
+
+ public String readGpioTitle() {
+ return read(filePath, "PIN:");
+ }
+
+ public String readGpioSingle() {
+ int gpio = 0;
+ if (pin.isEmpty()) {
+ return "";
+ }
+ try {
+ gpio = Integer.parseInt(pin);
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+
+ String str = String.format("%3d", gpio).replace(" ", "0");
+ return read(filePath, pin + ":");
+ }
+
+ public String readGpioAll() {
+ return read_all(filePath);
+ }
+
+ private void setGpioMode(String pin, String value) {
+ nm_write("mode " + pin + " " + value);
+ }
+
+ private void setGpioDir(String pin, String value) {
+ nm_write("dir " + pin + " " + value);
+ }
+
+ private void setGpioOut(String pin, String value) {
+ nm_write("out " + pin + " " + value);
+ }
+
+ private void setGpioPen(String pin, String value) { //1:浣胯兘涓婁笅鎷� 0:绂佹涓婁笅鎷�
+ nm_write("pullen " + pin + " " + value);
+ }
+
+ private void setGpioPsel(String pin, String value) { //1:璁剧疆涓婃媺 0:璁剧疆涓嬫媺
+ nm_write("pullsel " + pin + " " + value);
+ }
+
+ private void nm_write(String value) {
+ if (value.isEmpty()) {
+ return;
+ }
+ FileWriter fw;
+ try {
+ fw = new FileWriter(filePath);
+ fw.write(value);
+ fw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public String read(String sys_path, String value) {
+ if (value.isEmpty()) {
+ return null;
+ }
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+
+ String line;
+ while (null != (line = br.readLine())) {
+ if (line.contains(value)) {
+ return line;
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public String read_all(String sys_path) {
+ StringBuilder value = new StringBuilder();
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+
+ while (null != (line = br.readLine())) {
+ value.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return value.toString();
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
index ee56adf..09c5ae1 100644
--- a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
@@ -4,28 +4,30 @@
import android.app.DatePickerDialog
import android.content.Context
import android.content.Intent
+import android.media.AudioManager
+import android.media.SoundPool
+import android.os.Bundle
+import android.os.Handler
import android.provider.Settings
+import android.util.Log
import android.view.View
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.detector.R
import com.casic.detector.adapter.EditableImageAdapter
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.bean.LabelBean
import com.casic.detector.callback.ILocationListener
import com.casic.detector.callback.OnImageCompressListener
import com.casic.detector.callback.OnItemSelectedListener
import com.casic.detector.extensions.*
-import com.casic.detector.utils.DataBaseManager
-import com.casic.detector.utils.LoadingDialogHub
-import com.casic.detector.utils.LocaleConstant
-import com.casic.detector.utils.LocationHub
+import com.casic.detector.utils.*
import com.casic.detector.vm.TaskViewModel
import com.gyf.immersionbar.ImmersionBar
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.SaveKeyValues
import com.pengxh.kt.lite.vm.LoadState
@@ -36,10 +38,11 @@
import kotlinx.android.synthetic.main.include_install_label_object.*
import kotlinx.android.synthetic.main.include_install_label_open_camera.*
import java.io.File
+import java.io.IOException
import java.util.*
@SuppressLint("SetTextI18n")
-class InstallLabelActivity : KotlinBaseActivity() {
+class InstallLabelActivity : SerialPortActivity() {
private val kTag = "InstallLabelActivity"
private val context: Context = this@InstallLabelActivity
@@ -54,8 +57,10 @@
private var identifierTypeSelectedItem = ""
private var colorSelectedItem = ""
private lateinit var taskViewModel: TaskViewModel
+ private lateinit var soundPool: SoundPool
+ private val gpioManager by lazy { GpioManager() }
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
imageAdapter = EditableImageAdapter(this, 3, 3f)
addImageRecyclerView.adapter = imageAdapter
@@ -73,6 +78,9 @@
ownerView.setText("ownerView".getDefaultValue())
identifierDeepView.setText("identifierDeepView".getDefaultValue())
personDeptView.setText("personDeptView".getDefaultValue())
+
+ soundPool = SoundPool(10, AudioManager.STREAM_SYSTEM, 5)
+ soundPool.load(this, R.raw.ring4, 1)
}
override fun initEvent() {
@@ -331,12 +339,64 @@
//TODO 搜索标识器
readLabelButton.setOnClickListener {
- LoadingDialogHub.show(this, "正在搜索标识器,请稍后...")
- identifierIdView.text = "123456789"
- LoadingDialogHub.dismiss()
+ reception = "0"
+ gpioManager.setGpioHigh("18")
+
+ // 1000ms后发送读标识器或搜索信号
+ Handler().postDelayed({ // 发送读标识器或搜索信号
+ try {
+ outputStream?.write(0x02)
+ outputStream?.flush()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }, 1000)
}
}
+ private var reception = ""
+
+
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+ Log.d(kTag, "onDataReceived => " + buffer.contentToString())
+ if (buffer != null) {
+ reception = String.format(
+ "%010d", hex2Str(
+ byte2hex(buffer).substring(6, 22)
+ ).toLong(16)
+ )
+ Log.d(kTag, "onDataReceived => $reception")
+ }
+ }
+
+ private fun byte2hex(buffer: ByteArray): String {
+ var h = ""
+ for (i in buffer.indices) {
+ var temp = Integer.toHexString(buffer[i].toInt() and 0xFF)
+ if (temp.length == 1) {
+ temp = "0$temp"
+ }
+ h += temp
+ }
+ return h
+ }
+
+ private fun hex2Str(hex: String): String {
+ val sb = StringBuilder()
+ val temp = StringBuilder()
+ run {
+ var i = 0
+ while (i < hex.length - 1) {
+ val output = hex.substring(i, i + 2)
+ val decimal = output.toInt(16)
+ sb.append(decimal.toChar())
+ temp.append(decimal)
+ i += 2
+ }
+ }
+ return sb.toString()
+ }
+
private fun takePicture() {
PictureSelector.create(this).openCamera(SelectMimeType.ofImage())
.forResult(object : OnResultCallbackListener {
@@ -429,4 +489,9 @@
.init()
initLayoutImmersionBar(rootView)
}
+
+ override fun onDestroy() {
+ gpioManager.setGpioLow("18")
+ super.onDestroy()
+ }
}
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
new file mode 100644
index 0000000..c7229ad
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
@@ -0,0 +1,100 @@
+package com.casic.detector.base
+
+import android.os.Bundle
+import android_serialport_api.SerialPort
+import androidx.appcompat.app.AppCompatActivity
+import com.pengxh.kt.lite.extensions.show
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.security.InvalidParameterException
+
+
+abstract class SerialPortActivity : AppCompatActivity() {
+
+ private var serialPort: SerialPort? = null
+ var outputStream: OutputStream? = null
+ private var inputStream: InputStream? = null
+ private var readThread: ReadThread? = null
+
+ inner class ReadThread : Thread() {
+ override fun run() {
+ super.run()
+ while (!isInterrupted) {
+ var size: Int
+ try {
+ val buffer = ByteArray(64)
+ if (inputStream == null) return
+ size = inputStream!!.read(buffer)
+ if (size > 0) {
+ onDataReceived(buffer, size)
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(initLayoutView())
+ setupTopBarLayout()
+ initData(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ try {
+ serialPort = BaseApplication.get().getSerialPort()
+ outputStream = serialPort?.outputStream
+ inputStream = serialPort?.inputStream
+
+ readThread = ReadThread()
+ readThread?.start()
+ } catch (e: SecurityException) {
+ "您没有串口的读写权限!".show(this)
+ } catch (e: IOException) {
+ "因为不明原因,串口无法打开!".show(this)
+ } catch (e: InvalidParameterException) {
+ "请检查串口!".show(this)
+ }
+ }
+
+ /**
+ * 初始化xml布局
+ */
+ abstract fun initLayoutView(): Int
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initData(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ /**
+ * 串口读数
+ * */
+ abstract fun onDataReceived(buffer: ByteArray?, size: Int)
+
+ override fun onDestroy() {
+ readThread?.interrupt()
+ BaseApplication.get().closeSerialPort()
+ serialPort = null
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/utils/GpioManager.java b/app/src/main/java/com/casic/detector/utils/GpioManager.java
new file mode 100644
index 0000000..0f54f1a
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/GpioManager.java
@@ -0,0 +1,121 @@
+package com.casic.detector.utils;
+
+
+public class GpioManager {
+
+ private static final int MT6761 = 0;
+ private int selected;
+ private final MT6761Gpio mt6761;
+
+ public GpioManager(int selected) {
+ this.selected = selected;
+ mt6761 = new MT6761Gpio();
+ }
+
+ public GpioManager() {
+ mt6761 = new MT6761Gpio();
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ this.selected = selected;
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳叆
+ * *********************************************************************/
+ public void setGpioInput(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioInput();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭楂�
+ * *********************************************************************/
+ public void setGpioHigh(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioHigh();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭浣�
+ * *********************************************************************/
+ public void setGpioLow(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioLow();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO鏃犱笂涓嬫媺
+ * *********************************************************************/
+ public void setNotPen(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setNotPen();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓嬫媺
+ * *********************************************************************/
+ public void setPullDown(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullDown();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓婃媺
+ * *********************************************************************/
+ public void setPullUp(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullUp();
+ }
+ }
+
+ /************************************************************************
+ * 璇诲彇鍗曚釜GPIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireSingleGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioSingle();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireAllGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioAll();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬佹爣棰�
+ * *********************************************************************/
+ public String readGpioTitle() {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ status = mt6761.readGpioTitle();
+ }
+ return status;
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
new file mode 100644
index 0000000..d9d394f
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
@@ -0,0 +1,157 @@
+package com.casic.detector.utils;
+
+import java.io.BufferedReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class MT6761Gpio {
+
+ private final String filePath = "/sys/devices/platform/1000b000.pinctrl/mt_gpio";
+ private String pin;
+
+ public void setGpioHigh() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "1");
+ }
+
+ public void setGpioLow() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "0");
+ }
+
+ public void setGpioInput() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "0");
+ }
+
+ public void setNotPen() {
+ setGpioPen(pin, "0");
+ }
+
+ public void setPullUp() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "1");
+ }
+
+ public void setPullDown() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "0");
+ }
+
+ public void setCtrlPin(String gpio) {
+ pin = gpio;
+ }
+
+ public String readGpioTitle() {
+ return read(filePath, "PIN:");
+ }
+
+ public String readGpioSingle() {
+ int gpio = 0;
+ if (pin.isEmpty()) {
+ return "";
+ }
+ try {
+ gpio = Integer.parseInt(pin);
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+
+ String str = String.format("%3d", gpio).replace(" ", "0");
+ return read(filePath, pin + ":");
+ }
+
+ public String readGpioAll() {
+ return read_all(filePath);
+ }
+
+ private void setGpioMode(String pin, String value) {
+ nm_write("mode " + pin + " " + value);
+ }
+
+ private void setGpioDir(String pin, String value) {
+ nm_write("dir " + pin + " " + value);
+ }
+
+ private void setGpioOut(String pin, String value) {
+ nm_write("out " + pin + " " + value);
+ }
+
+ private void setGpioPen(String pin, String value) { //1:浣胯兘涓婁笅鎷� 0:绂佹涓婁笅鎷�
+ nm_write("pullen " + pin + " " + value);
+ }
+
+ private void setGpioPsel(String pin, String value) { //1:璁剧疆涓婃媺 0:璁剧疆涓嬫媺
+ nm_write("pullsel " + pin + " " + value);
+ }
+
+ private void nm_write(String value) {
+ if (value.isEmpty()) {
+ return;
+ }
+ FileWriter fw;
+ try {
+ fw = new FileWriter(filePath);
+ fw.write(value);
+ fw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public String read(String sys_path, String value) {
+ if (value.isEmpty()) {
+ return null;
+ }
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+
+ String line;
+ while (null != (line = br.readLine())) {
+ if (line.contains(value)) {
+ return line;
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public String read_all(String sys_path) {
+ StringBuilder value = new StringBuilder();
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+
+ while (null != (line = br.readLine())) {
+ value.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return value.toString();
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
index ee56adf..09c5ae1 100644
--- a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
@@ -4,28 +4,30 @@
import android.app.DatePickerDialog
import android.content.Context
import android.content.Intent
+import android.media.AudioManager
+import android.media.SoundPool
+import android.os.Bundle
+import android.os.Handler
import android.provider.Settings
+import android.util.Log
import android.view.View
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.detector.R
import com.casic.detector.adapter.EditableImageAdapter
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.bean.LabelBean
import com.casic.detector.callback.ILocationListener
import com.casic.detector.callback.OnImageCompressListener
import com.casic.detector.callback.OnItemSelectedListener
import com.casic.detector.extensions.*
-import com.casic.detector.utils.DataBaseManager
-import com.casic.detector.utils.LoadingDialogHub
-import com.casic.detector.utils.LocaleConstant
-import com.casic.detector.utils.LocationHub
+import com.casic.detector.utils.*
import com.casic.detector.vm.TaskViewModel
import com.gyf.immersionbar.ImmersionBar
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.SaveKeyValues
import com.pengxh.kt.lite.vm.LoadState
@@ -36,10 +38,11 @@
import kotlinx.android.synthetic.main.include_install_label_object.*
import kotlinx.android.synthetic.main.include_install_label_open_camera.*
import java.io.File
+import java.io.IOException
import java.util.*
@SuppressLint("SetTextI18n")
-class InstallLabelActivity : KotlinBaseActivity() {
+class InstallLabelActivity : SerialPortActivity() {
private val kTag = "InstallLabelActivity"
private val context: Context = this@InstallLabelActivity
@@ -54,8 +57,10 @@
private var identifierTypeSelectedItem = ""
private var colorSelectedItem = ""
private lateinit var taskViewModel: TaskViewModel
+ private lateinit var soundPool: SoundPool
+ private val gpioManager by lazy { GpioManager() }
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
imageAdapter = EditableImageAdapter(this, 3, 3f)
addImageRecyclerView.adapter = imageAdapter
@@ -73,6 +78,9 @@
ownerView.setText("ownerView".getDefaultValue())
identifierDeepView.setText("identifierDeepView".getDefaultValue())
personDeptView.setText("personDeptView".getDefaultValue())
+
+ soundPool = SoundPool(10, AudioManager.STREAM_SYSTEM, 5)
+ soundPool.load(this, R.raw.ring4, 1)
}
override fun initEvent() {
@@ -331,12 +339,64 @@
//TODO 搜索标识器
readLabelButton.setOnClickListener {
- LoadingDialogHub.show(this, "正在搜索标识器,请稍后...")
- identifierIdView.text = "123456789"
- LoadingDialogHub.dismiss()
+ reception = "0"
+ gpioManager.setGpioHigh("18")
+
+ // 1000ms后发送读标识器或搜索信号
+ Handler().postDelayed({ // 发送读标识器或搜索信号
+ try {
+ outputStream?.write(0x02)
+ outputStream?.flush()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }, 1000)
}
}
+ private var reception = ""
+
+
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+ Log.d(kTag, "onDataReceived => " + buffer.contentToString())
+ if (buffer != null) {
+ reception = String.format(
+ "%010d", hex2Str(
+ byte2hex(buffer).substring(6, 22)
+ ).toLong(16)
+ )
+ Log.d(kTag, "onDataReceived => $reception")
+ }
+ }
+
+ private fun byte2hex(buffer: ByteArray): String {
+ var h = ""
+ for (i in buffer.indices) {
+ var temp = Integer.toHexString(buffer[i].toInt() and 0xFF)
+ if (temp.length == 1) {
+ temp = "0$temp"
+ }
+ h += temp
+ }
+ return h
+ }
+
+ private fun hex2Str(hex: String): String {
+ val sb = StringBuilder()
+ val temp = StringBuilder()
+ run {
+ var i = 0
+ while (i < hex.length - 1) {
+ val output = hex.substring(i, i + 2)
+ val decimal = output.toInt(16)
+ sb.append(decimal.toChar())
+ temp.append(decimal)
+ i += 2
+ }
+ }
+ return sb.toString()
+ }
+
private fun takePicture() {
PictureSelector.create(this).openCamera(SelectMimeType.ofImage())
.forResult(object : OnResultCallbackListener {
@@ -429,4 +489,9 @@
.init()
initLayoutImmersionBar(rootView)
}
+
+ override fun onDestroy() {
+ gpioManager.setGpioLow("18")
+ super.onDestroy()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
index 3297c76..ae56b26 100644
--- a/app/src/main/java/com/casic/detector/view/LoginActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
@@ -4,6 +4,7 @@
import com.amap.api.navi.NaviSetting
import com.casic.detector.R
import com.casic.detector.extensions.initLayoutImmersionBar
+import com.casic.detector.utils.GpioManager
import com.casic.detector.utils.LoadingDialogHub
import com.casic.detector.utils.LocaleConstant
import com.casic.detector.vm.UserViewModel
@@ -18,8 +19,10 @@
class LoginActivity : KotlinBaseActivity() {
private lateinit var userViewModel: UserViewModel
+ private val gpioManager by lazy { GpioManager() }
override fun initData() {
+ gpioManager.setGpioLow("18")
//先把导航隐私政策声明,后面导航会用到
NaviSetting.updatePrivacyShow(this, true, true)
NaviSetting.updatePrivacyAgree(this, true)
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
new file mode 100644
index 0000000..c7229ad
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
@@ -0,0 +1,100 @@
+package com.casic.detector.base
+
+import android.os.Bundle
+import android_serialport_api.SerialPort
+import androidx.appcompat.app.AppCompatActivity
+import com.pengxh.kt.lite.extensions.show
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.security.InvalidParameterException
+
+
+abstract class SerialPortActivity : AppCompatActivity() {
+
+ private var serialPort: SerialPort? = null
+ var outputStream: OutputStream? = null
+ private var inputStream: InputStream? = null
+ private var readThread: ReadThread? = null
+
+ inner class ReadThread : Thread() {
+ override fun run() {
+ super.run()
+ while (!isInterrupted) {
+ var size: Int
+ try {
+ val buffer = ByteArray(64)
+ if (inputStream == null) return
+ size = inputStream!!.read(buffer)
+ if (size > 0) {
+ onDataReceived(buffer, size)
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(initLayoutView())
+ setupTopBarLayout()
+ initData(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ try {
+ serialPort = BaseApplication.get().getSerialPort()
+ outputStream = serialPort?.outputStream
+ inputStream = serialPort?.inputStream
+
+ readThread = ReadThread()
+ readThread?.start()
+ } catch (e: SecurityException) {
+ "您没有串口的读写权限!".show(this)
+ } catch (e: IOException) {
+ "因为不明原因,串口无法打开!".show(this)
+ } catch (e: InvalidParameterException) {
+ "请检查串口!".show(this)
+ }
+ }
+
+ /**
+ * 初始化xml布局
+ */
+ abstract fun initLayoutView(): Int
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initData(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ /**
+ * 串口读数
+ * */
+ abstract fun onDataReceived(buffer: ByteArray?, size: Int)
+
+ override fun onDestroy() {
+ readThread?.interrupt()
+ BaseApplication.get().closeSerialPort()
+ serialPort = null
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/utils/GpioManager.java b/app/src/main/java/com/casic/detector/utils/GpioManager.java
new file mode 100644
index 0000000..0f54f1a
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/GpioManager.java
@@ -0,0 +1,121 @@
+package com.casic.detector.utils;
+
+
+public class GpioManager {
+
+ private static final int MT6761 = 0;
+ private int selected;
+ private final MT6761Gpio mt6761;
+
+ public GpioManager(int selected) {
+ this.selected = selected;
+ mt6761 = new MT6761Gpio();
+ }
+
+ public GpioManager() {
+ mt6761 = new MT6761Gpio();
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ this.selected = selected;
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳叆
+ * *********************************************************************/
+ public void setGpioInput(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioInput();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭楂�
+ * *********************************************************************/
+ public void setGpioHigh(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioHigh();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭浣�
+ * *********************************************************************/
+ public void setGpioLow(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioLow();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO鏃犱笂涓嬫媺
+ * *********************************************************************/
+ public void setNotPen(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setNotPen();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓嬫媺
+ * *********************************************************************/
+ public void setPullDown(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullDown();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓婃媺
+ * *********************************************************************/
+ public void setPullUp(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullUp();
+ }
+ }
+
+ /************************************************************************
+ * 璇诲彇鍗曚釜GPIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireSingleGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioSingle();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireAllGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioAll();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬佹爣棰�
+ * *********************************************************************/
+ public String readGpioTitle() {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ status = mt6761.readGpioTitle();
+ }
+ return status;
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
new file mode 100644
index 0000000..d9d394f
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
@@ -0,0 +1,157 @@
+package com.casic.detector.utils;
+
+import java.io.BufferedReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class MT6761Gpio {
+
+ private final String filePath = "/sys/devices/platform/1000b000.pinctrl/mt_gpio";
+ private String pin;
+
+ public void setGpioHigh() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "1");
+ }
+
+ public void setGpioLow() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "0");
+ }
+
+ public void setGpioInput() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "0");
+ }
+
+ public void setNotPen() {
+ setGpioPen(pin, "0");
+ }
+
+ public void setPullUp() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "1");
+ }
+
+ public void setPullDown() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "0");
+ }
+
+ public void setCtrlPin(String gpio) {
+ pin = gpio;
+ }
+
+ public String readGpioTitle() {
+ return read(filePath, "PIN:");
+ }
+
+ public String readGpioSingle() {
+ int gpio = 0;
+ if (pin.isEmpty()) {
+ return "";
+ }
+ try {
+ gpio = Integer.parseInt(pin);
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+
+ String str = String.format("%3d", gpio).replace(" ", "0");
+ return read(filePath, pin + ":");
+ }
+
+ public String readGpioAll() {
+ return read_all(filePath);
+ }
+
+ private void setGpioMode(String pin, String value) {
+ nm_write("mode " + pin + " " + value);
+ }
+
+ private void setGpioDir(String pin, String value) {
+ nm_write("dir " + pin + " " + value);
+ }
+
+ private void setGpioOut(String pin, String value) {
+ nm_write("out " + pin + " " + value);
+ }
+
+ private void setGpioPen(String pin, String value) { //1:浣胯兘涓婁笅鎷� 0:绂佹涓婁笅鎷�
+ nm_write("pullen " + pin + " " + value);
+ }
+
+ private void setGpioPsel(String pin, String value) { //1:璁剧疆涓婃媺 0:璁剧疆涓嬫媺
+ nm_write("pullsel " + pin + " " + value);
+ }
+
+ private void nm_write(String value) {
+ if (value.isEmpty()) {
+ return;
+ }
+ FileWriter fw;
+ try {
+ fw = new FileWriter(filePath);
+ fw.write(value);
+ fw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public String read(String sys_path, String value) {
+ if (value.isEmpty()) {
+ return null;
+ }
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+
+ String line;
+ while (null != (line = br.readLine())) {
+ if (line.contains(value)) {
+ return line;
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public String read_all(String sys_path) {
+ StringBuilder value = new StringBuilder();
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+
+ while (null != (line = br.readLine())) {
+ value.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return value.toString();
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
index ee56adf..09c5ae1 100644
--- a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
@@ -4,28 +4,30 @@
import android.app.DatePickerDialog
import android.content.Context
import android.content.Intent
+import android.media.AudioManager
+import android.media.SoundPool
+import android.os.Bundle
+import android.os.Handler
import android.provider.Settings
+import android.util.Log
import android.view.View
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.detector.R
import com.casic.detector.adapter.EditableImageAdapter
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.bean.LabelBean
import com.casic.detector.callback.ILocationListener
import com.casic.detector.callback.OnImageCompressListener
import com.casic.detector.callback.OnItemSelectedListener
import com.casic.detector.extensions.*
-import com.casic.detector.utils.DataBaseManager
-import com.casic.detector.utils.LoadingDialogHub
-import com.casic.detector.utils.LocaleConstant
-import com.casic.detector.utils.LocationHub
+import com.casic.detector.utils.*
import com.casic.detector.vm.TaskViewModel
import com.gyf.immersionbar.ImmersionBar
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.SaveKeyValues
import com.pengxh.kt.lite.vm.LoadState
@@ -36,10 +38,11 @@
import kotlinx.android.synthetic.main.include_install_label_object.*
import kotlinx.android.synthetic.main.include_install_label_open_camera.*
import java.io.File
+import java.io.IOException
import java.util.*
@SuppressLint("SetTextI18n")
-class InstallLabelActivity : KotlinBaseActivity() {
+class InstallLabelActivity : SerialPortActivity() {
private val kTag = "InstallLabelActivity"
private val context: Context = this@InstallLabelActivity
@@ -54,8 +57,10 @@
private var identifierTypeSelectedItem = ""
private var colorSelectedItem = ""
private lateinit var taskViewModel: TaskViewModel
+ private lateinit var soundPool: SoundPool
+ private val gpioManager by lazy { GpioManager() }
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
imageAdapter = EditableImageAdapter(this, 3, 3f)
addImageRecyclerView.adapter = imageAdapter
@@ -73,6 +78,9 @@
ownerView.setText("ownerView".getDefaultValue())
identifierDeepView.setText("identifierDeepView".getDefaultValue())
personDeptView.setText("personDeptView".getDefaultValue())
+
+ soundPool = SoundPool(10, AudioManager.STREAM_SYSTEM, 5)
+ soundPool.load(this, R.raw.ring4, 1)
}
override fun initEvent() {
@@ -331,12 +339,64 @@
//TODO 搜索标识器
readLabelButton.setOnClickListener {
- LoadingDialogHub.show(this, "正在搜索标识器,请稍后...")
- identifierIdView.text = "123456789"
- LoadingDialogHub.dismiss()
+ reception = "0"
+ gpioManager.setGpioHigh("18")
+
+ // 1000ms后发送读标识器或搜索信号
+ Handler().postDelayed({ // 发送读标识器或搜索信号
+ try {
+ outputStream?.write(0x02)
+ outputStream?.flush()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }, 1000)
}
}
+ private var reception = ""
+
+
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+ Log.d(kTag, "onDataReceived => " + buffer.contentToString())
+ if (buffer != null) {
+ reception = String.format(
+ "%010d", hex2Str(
+ byte2hex(buffer).substring(6, 22)
+ ).toLong(16)
+ )
+ Log.d(kTag, "onDataReceived => $reception")
+ }
+ }
+
+ private fun byte2hex(buffer: ByteArray): String {
+ var h = ""
+ for (i in buffer.indices) {
+ var temp = Integer.toHexString(buffer[i].toInt() and 0xFF)
+ if (temp.length == 1) {
+ temp = "0$temp"
+ }
+ h += temp
+ }
+ return h
+ }
+
+ private fun hex2Str(hex: String): String {
+ val sb = StringBuilder()
+ val temp = StringBuilder()
+ run {
+ var i = 0
+ while (i < hex.length - 1) {
+ val output = hex.substring(i, i + 2)
+ val decimal = output.toInt(16)
+ sb.append(decimal.toChar())
+ temp.append(decimal)
+ i += 2
+ }
+ }
+ return sb.toString()
+ }
+
private fun takePicture() {
PictureSelector.create(this).openCamera(SelectMimeType.ofImage())
.forResult(object : OnResultCallbackListener {
@@ -429,4 +489,9 @@
.init()
initLayoutImmersionBar(rootView)
}
+
+ override fun onDestroy() {
+ gpioManager.setGpioLow("18")
+ super.onDestroy()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
index 3297c76..ae56b26 100644
--- a/app/src/main/java/com/casic/detector/view/LoginActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
@@ -4,6 +4,7 @@
import com.amap.api.navi.NaviSetting
import com.casic.detector.R
import com.casic.detector.extensions.initLayoutImmersionBar
+import com.casic.detector.utils.GpioManager
import com.casic.detector.utils.LoadingDialogHub
import com.casic.detector.utils.LocaleConstant
import com.casic.detector.vm.UserViewModel
@@ -18,8 +19,10 @@
class LoginActivity : KotlinBaseActivity() {
private lateinit var userViewModel: UserViewModel
+ private val gpioManager by lazy { GpioManager() }
override fun initData() {
+ gpioManager.setGpioLow("18")
//先把导航隐私政策声明,后面导航会用到
NaviSetting.updatePrivacyShow(this, true, true)
NaviSetting.updatePrivacyAgree(this, true)
diff --git a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
index 8bca233..3140bc3 100644
--- a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
@@ -1,14 +1,15 @@
package com.casic.detector.view
+import android.os.Bundle
import com.casic.detector.R
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.extensions.initLayoutImmersionBar
import com.gyf.immersionbar.ImmersionBar
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import kotlinx.android.synthetic.main.activity_search_label.*
-class SearchLabelActivity : KotlinBaseActivity() {
+class SearchLabelActivity : SerialPortActivity() {
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
}
@@ -16,6 +17,10 @@
leftBackView.setOnClickListener { finish() }
}
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+
+ }
+
override fun initLayoutView(): Int = R.layout.activity_search_label
override fun observeRequestState() {
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
new file mode 100644
index 0000000..c7229ad
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
@@ -0,0 +1,100 @@
+package com.casic.detector.base
+
+import android.os.Bundle
+import android_serialport_api.SerialPort
+import androidx.appcompat.app.AppCompatActivity
+import com.pengxh.kt.lite.extensions.show
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.security.InvalidParameterException
+
+
+abstract class SerialPortActivity : AppCompatActivity() {
+
+ private var serialPort: SerialPort? = null
+ var outputStream: OutputStream? = null
+ private var inputStream: InputStream? = null
+ private var readThread: ReadThread? = null
+
+ inner class ReadThread : Thread() {
+ override fun run() {
+ super.run()
+ while (!isInterrupted) {
+ var size: Int
+ try {
+ val buffer = ByteArray(64)
+ if (inputStream == null) return
+ size = inputStream!!.read(buffer)
+ if (size > 0) {
+ onDataReceived(buffer, size)
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(initLayoutView())
+ setupTopBarLayout()
+ initData(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ try {
+ serialPort = BaseApplication.get().getSerialPort()
+ outputStream = serialPort?.outputStream
+ inputStream = serialPort?.inputStream
+
+ readThread = ReadThread()
+ readThread?.start()
+ } catch (e: SecurityException) {
+ "您没有串口的读写权限!".show(this)
+ } catch (e: IOException) {
+ "因为不明原因,串口无法打开!".show(this)
+ } catch (e: InvalidParameterException) {
+ "请检查串口!".show(this)
+ }
+ }
+
+ /**
+ * 初始化xml布局
+ */
+ abstract fun initLayoutView(): Int
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initData(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ /**
+ * 串口读数
+ * */
+ abstract fun onDataReceived(buffer: ByteArray?, size: Int)
+
+ override fun onDestroy() {
+ readThread?.interrupt()
+ BaseApplication.get().closeSerialPort()
+ serialPort = null
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/utils/GpioManager.java b/app/src/main/java/com/casic/detector/utils/GpioManager.java
new file mode 100644
index 0000000..0f54f1a
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/GpioManager.java
@@ -0,0 +1,121 @@
+package com.casic.detector.utils;
+
+
+public class GpioManager {
+
+ private static final int MT6761 = 0;
+ private int selected;
+ private final MT6761Gpio mt6761;
+
+ public GpioManager(int selected) {
+ this.selected = selected;
+ mt6761 = new MT6761Gpio();
+ }
+
+ public GpioManager() {
+ mt6761 = new MT6761Gpio();
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ this.selected = selected;
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳叆
+ * *********************************************************************/
+ public void setGpioInput(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioInput();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭楂�
+ * *********************************************************************/
+ public void setGpioHigh(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioHigh();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭浣�
+ * *********************************************************************/
+ public void setGpioLow(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioLow();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO鏃犱笂涓嬫媺
+ * *********************************************************************/
+ public void setNotPen(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setNotPen();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓嬫媺
+ * *********************************************************************/
+ public void setPullDown(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullDown();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓婃媺
+ * *********************************************************************/
+ public void setPullUp(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullUp();
+ }
+ }
+
+ /************************************************************************
+ * 璇诲彇鍗曚釜GPIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireSingleGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioSingle();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireAllGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioAll();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬佹爣棰�
+ * *********************************************************************/
+ public String readGpioTitle() {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ status = mt6761.readGpioTitle();
+ }
+ return status;
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
new file mode 100644
index 0000000..d9d394f
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
@@ -0,0 +1,157 @@
+package com.casic.detector.utils;
+
+import java.io.BufferedReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class MT6761Gpio {
+
+ private final String filePath = "/sys/devices/platform/1000b000.pinctrl/mt_gpio";
+ private String pin;
+
+ public void setGpioHigh() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "1");
+ }
+
+ public void setGpioLow() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "0");
+ }
+
+ public void setGpioInput() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "0");
+ }
+
+ public void setNotPen() {
+ setGpioPen(pin, "0");
+ }
+
+ public void setPullUp() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "1");
+ }
+
+ public void setPullDown() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "0");
+ }
+
+ public void setCtrlPin(String gpio) {
+ pin = gpio;
+ }
+
+ public String readGpioTitle() {
+ return read(filePath, "PIN:");
+ }
+
+ public String readGpioSingle() {
+ int gpio = 0;
+ if (pin.isEmpty()) {
+ return "";
+ }
+ try {
+ gpio = Integer.parseInt(pin);
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+
+ String str = String.format("%3d", gpio).replace(" ", "0");
+ return read(filePath, pin + ":");
+ }
+
+ public String readGpioAll() {
+ return read_all(filePath);
+ }
+
+ private void setGpioMode(String pin, String value) {
+ nm_write("mode " + pin + " " + value);
+ }
+
+ private void setGpioDir(String pin, String value) {
+ nm_write("dir " + pin + " " + value);
+ }
+
+ private void setGpioOut(String pin, String value) {
+ nm_write("out " + pin + " " + value);
+ }
+
+ private void setGpioPen(String pin, String value) { //1:浣胯兘涓婁笅鎷� 0:绂佹涓婁笅鎷�
+ nm_write("pullen " + pin + " " + value);
+ }
+
+ private void setGpioPsel(String pin, String value) { //1:璁剧疆涓婃媺 0:璁剧疆涓嬫媺
+ nm_write("pullsel " + pin + " " + value);
+ }
+
+ private void nm_write(String value) {
+ if (value.isEmpty()) {
+ return;
+ }
+ FileWriter fw;
+ try {
+ fw = new FileWriter(filePath);
+ fw.write(value);
+ fw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public String read(String sys_path, String value) {
+ if (value.isEmpty()) {
+ return null;
+ }
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+
+ String line;
+ while (null != (line = br.readLine())) {
+ if (line.contains(value)) {
+ return line;
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public String read_all(String sys_path) {
+ StringBuilder value = new StringBuilder();
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+
+ while (null != (line = br.readLine())) {
+ value.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return value.toString();
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
index ee56adf..09c5ae1 100644
--- a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
@@ -4,28 +4,30 @@
import android.app.DatePickerDialog
import android.content.Context
import android.content.Intent
+import android.media.AudioManager
+import android.media.SoundPool
+import android.os.Bundle
+import android.os.Handler
import android.provider.Settings
+import android.util.Log
import android.view.View
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.detector.R
import com.casic.detector.adapter.EditableImageAdapter
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.bean.LabelBean
import com.casic.detector.callback.ILocationListener
import com.casic.detector.callback.OnImageCompressListener
import com.casic.detector.callback.OnItemSelectedListener
import com.casic.detector.extensions.*
-import com.casic.detector.utils.DataBaseManager
-import com.casic.detector.utils.LoadingDialogHub
-import com.casic.detector.utils.LocaleConstant
-import com.casic.detector.utils.LocationHub
+import com.casic.detector.utils.*
import com.casic.detector.vm.TaskViewModel
import com.gyf.immersionbar.ImmersionBar
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.SaveKeyValues
import com.pengxh.kt.lite.vm.LoadState
@@ -36,10 +38,11 @@
import kotlinx.android.synthetic.main.include_install_label_object.*
import kotlinx.android.synthetic.main.include_install_label_open_camera.*
import java.io.File
+import java.io.IOException
import java.util.*
@SuppressLint("SetTextI18n")
-class InstallLabelActivity : KotlinBaseActivity() {
+class InstallLabelActivity : SerialPortActivity() {
private val kTag = "InstallLabelActivity"
private val context: Context = this@InstallLabelActivity
@@ -54,8 +57,10 @@
private var identifierTypeSelectedItem = ""
private var colorSelectedItem = ""
private lateinit var taskViewModel: TaskViewModel
+ private lateinit var soundPool: SoundPool
+ private val gpioManager by lazy { GpioManager() }
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
imageAdapter = EditableImageAdapter(this, 3, 3f)
addImageRecyclerView.adapter = imageAdapter
@@ -73,6 +78,9 @@
ownerView.setText("ownerView".getDefaultValue())
identifierDeepView.setText("identifierDeepView".getDefaultValue())
personDeptView.setText("personDeptView".getDefaultValue())
+
+ soundPool = SoundPool(10, AudioManager.STREAM_SYSTEM, 5)
+ soundPool.load(this, R.raw.ring4, 1)
}
override fun initEvent() {
@@ -331,12 +339,64 @@
//TODO 搜索标识器
readLabelButton.setOnClickListener {
- LoadingDialogHub.show(this, "正在搜索标识器,请稍后...")
- identifierIdView.text = "123456789"
- LoadingDialogHub.dismiss()
+ reception = "0"
+ gpioManager.setGpioHigh("18")
+
+ // 1000ms后发送读标识器或搜索信号
+ Handler().postDelayed({ // 发送读标识器或搜索信号
+ try {
+ outputStream?.write(0x02)
+ outputStream?.flush()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }, 1000)
}
}
+ private var reception = ""
+
+
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+ Log.d(kTag, "onDataReceived => " + buffer.contentToString())
+ if (buffer != null) {
+ reception = String.format(
+ "%010d", hex2Str(
+ byte2hex(buffer).substring(6, 22)
+ ).toLong(16)
+ )
+ Log.d(kTag, "onDataReceived => $reception")
+ }
+ }
+
+ private fun byte2hex(buffer: ByteArray): String {
+ var h = ""
+ for (i in buffer.indices) {
+ var temp = Integer.toHexString(buffer[i].toInt() and 0xFF)
+ if (temp.length == 1) {
+ temp = "0$temp"
+ }
+ h += temp
+ }
+ return h
+ }
+
+ private fun hex2Str(hex: String): String {
+ val sb = StringBuilder()
+ val temp = StringBuilder()
+ run {
+ var i = 0
+ while (i < hex.length - 1) {
+ val output = hex.substring(i, i + 2)
+ val decimal = output.toInt(16)
+ sb.append(decimal.toChar())
+ temp.append(decimal)
+ i += 2
+ }
+ }
+ return sb.toString()
+ }
+
private fun takePicture() {
PictureSelector.create(this).openCamera(SelectMimeType.ofImage())
.forResult(object : OnResultCallbackListener {
@@ -429,4 +489,9 @@
.init()
initLayoutImmersionBar(rootView)
}
+
+ override fun onDestroy() {
+ gpioManager.setGpioLow("18")
+ super.onDestroy()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
index 3297c76..ae56b26 100644
--- a/app/src/main/java/com/casic/detector/view/LoginActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
@@ -4,6 +4,7 @@
import com.amap.api.navi.NaviSetting
import com.casic.detector.R
import com.casic.detector.extensions.initLayoutImmersionBar
+import com.casic.detector.utils.GpioManager
import com.casic.detector.utils.LoadingDialogHub
import com.casic.detector.utils.LocaleConstant
import com.casic.detector.vm.UserViewModel
@@ -18,8 +19,10 @@
class LoginActivity : KotlinBaseActivity() {
private lateinit var userViewModel: UserViewModel
+ private val gpioManager by lazy { GpioManager() }
override fun initData() {
+ gpioManager.setGpioLow("18")
//先把导航隐私政策声明,后面导航会用到
NaviSetting.updatePrivacyShow(this, true, true)
NaviSetting.updatePrivacyAgree(this, true)
diff --git a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
index 8bca233..3140bc3 100644
--- a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
@@ -1,14 +1,15 @@
package com.casic.detector.view
+import android.os.Bundle
import com.casic.detector.R
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.extensions.initLayoutImmersionBar
import com.gyf.immersionbar.ImmersionBar
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import kotlinx.android.synthetic.main.activity_search_label.*
-class SearchLabelActivity : KotlinBaseActivity() {
+class SearchLabelActivity : SerialPortActivity() {
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
}
@@ -16,6 +17,10 @@
leftBackView.setOnClickListener { finish() }
}
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+
+ }
+
override fun initLayoutView(): Int = R.layout.activity_search_label
override fun observeRequestState() {
diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk
new file mode 100644
index 0000000..f4ce1c3
--- /dev/null
+++ b/app/src/main/jni/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright 2009 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+TARGET_PLATFORM := android-3
+LOCAL_MODULE := serial_port
+LOCAL_SRC_FILES := SerialPort.c
+LOCAL_LDLIBS := -llog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
new file mode 100644
index 0000000..c7229ad
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
@@ -0,0 +1,100 @@
+package com.casic.detector.base
+
+import android.os.Bundle
+import android_serialport_api.SerialPort
+import androidx.appcompat.app.AppCompatActivity
+import com.pengxh.kt.lite.extensions.show
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.security.InvalidParameterException
+
+
+abstract class SerialPortActivity : AppCompatActivity() {
+
+ private var serialPort: SerialPort? = null
+ var outputStream: OutputStream? = null
+ private var inputStream: InputStream? = null
+ private var readThread: ReadThread? = null
+
+ inner class ReadThread : Thread() {
+ override fun run() {
+ super.run()
+ while (!isInterrupted) {
+ var size: Int
+ try {
+ val buffer = ByteArray(64)
+ if (inputStream == null) return
+ size = inputStream!!.read(buffer)
+ if (size > 0) {
+ onDataReceived(buffer, size)
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(initLayoutView())
+ setupTopBarLayout()
+ initData(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ try {
+ serialPort = BaseApplication.get().getSerialPort()
+ outputStream = serialPort?.outputStream
+ inputStream = serialPort?.inputStream
+
+ readThread = ReadThread()
+ readThread?.start()
+ } catch (e: SecurityException) {
+ "您没有串口的读写权限!".show(this)
+ } catch (e: IOException) {
+ "因为不明原因,串口无法打开!".show(this)
+ } catch (e: InvalidParameterException) {
+ "请检查串口!".show(this)
+ }
+ }
+
+ /**
+ * 初始化xml布局
+ */
+ abstract fun initLayoutView(): Int
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initData(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ /**
+ * 串口读数
+ * */
+ abstract fun onDataReceived(buffer: ByteArray?, size: Int)
+
+ override fun onDestroy() {
+ readThread?.interrupt()
+ BaseApplication.get().closeSerialPort()
+ serialPort = null
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/utils/GpioManager.java b/app/src/main/java/com/casic/detector/utils/GpioManager.java
new file mode 100644
index 0000000..0f54f1a
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/GpioManager.java
@@ -0,0 +1,121 @@
+package com.casic.detector.utils;
+
+
+public class GpioManager {
+
+ private static final int MT6761 = 0;
+ private int selected;
+ private final MT6761Gpio mt6761;
+
+ public GpioManager(int selected) {
+ this.selected = selected;
+ mt6761 = new MT6761Gpio();
+ }
+
+ public GpioManager() {
+ mt6761 = new MT6761Gpio();
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ this.selected = selected;
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳叆
+ * *********************************************************************/
+ public void setGpioInput(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioInput();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭楂�
+ * *********************************************************************/
+ public void setGpioHigh(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioHigh();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭浣�
+ * *********************************************************************/
+ public void setGpioLow(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioLow();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO鏃犱笂涓嬫媺
+ * *********************************************************************/
+ public void setNotPen(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setNotPen();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓嬫媺
+ * *********************************************************************/
+ public void setPullDown(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullDown();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓婃媺
+ * *********************************************************************/
+ public void setPullUp(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullUp();
+ }
+ }
+
+ /************************************************************************
+ * 璇诲彇鍗曚釜GPIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireSingleGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioSingle();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireAllGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioAll();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬佹爣棰�
+ * *********************************************************************/
+ public String readGpioTitle() {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ status = mt6761.readGpioTitle();
+ }
+ return status;
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
new file mode 100644
index 0000000..d9d394f
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
@@ -0,0 +1,157 @@
+package com.casic.detector.utils;
+
+import java.io.BufferedReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class MT6761Gpio {
+
+ private final String filePath = "/sys/devices/platform/1000b000.pinctrl/mt_gpio";
+ private String pin;
+
+ public void setGpioHigh() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "1");
+ }
+
+ public void setGpioLow() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "0");
+ }
+
+ public void setGpioInput() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "0");
+ }
+
+ public void setNotPen() {
+ setGpioPen(pin, "0");
+ }
+
+ public void setPullUp() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "1");
+ }
+
+ public void setPullDown() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "0");
+ }
+
+ public void setCtrlPin(String gpio) {
+ pin = gpio;
+ }
+
+ public String readGpioTitle() {
+ return read(filePath, "PIN:");
+ }
+
+ public String readGpioSingle() {
+ int gpio = 0;
+ if (pin.isEmpty()) {
+ return "";
+ }
+ try {
+ gpio = Integer.parseInt(pin);
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+
+ String str = String.format("%3d", gpio).replace(" ", "0");
+ return read(filePath, pin + ":");
+ }
+
+ public String readGpioAll() {
+ return read_all(filePath);
+ }
+
+ private void setGpioMode(String pin, String value) {
+ nm_write("mode " + pin + " " + value);
+ }
+
+ private void setGpioDir(String pin, String value) {
+ nm_write("dir " + pin + " " + value);
+ }
+
+ private void setGpioOut(String pin, String value) {
+ nm_write("out " + pin + " " + value);
+ }
+
+ private void setGpioPen(String pin, String value) { //1:浣胯兘涓婁笅鎷� 0:绂佹涓婁笅鎷�
+ nm_write("pullen " + pin + " " + value);
+ }
+
+ private void setGpioPsel(String pin, String value) { //1:璁剧疆涓婃媺 0:璁剧疆涓嬫媺
+ nm_write("pullsel " + pin + " " + value);
+ }
+
+ private void nm_write(String value) {
+ if (value.isEmpty()) {
+ return;
+ }
+ FileWriter fw;
+ try {
+ fw = new FileWriter(filePath);
+ fw.write(value);
+ fw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public String read(String sys_path, String value) {
+ if (value.isEmpty()) {
+ return null;
+ }
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+
+ String line;
+ while (null != (line = br.readLine())) {
+ if (line.contains(value)) {
+ return line;
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public String read_all(String sys_path) {
+ StringBuilder value = new StringBuilder();
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+
+ while (null != (line = br.readLine())) {
+ value.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return value.toString();
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
index ee56adf..09c5ae1 100644
--- a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
@@ -4,28 +4,30 @@
import android.app.DatePickerDialog
import android.content.Context
import android.content.Intent
+import android.media.AudioManager
+import android.media.SoundPool
+import android.os.Bundle
+import android.os.Handler
import android.provider.Settings
+import android.util.Log
import android.view.View
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.detector.R
import com.casic.detector.adapter.EditableImageAdapter
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.bean.LabelBean
import com.casic.detector.callback.ILocationListener
import com.casic.detector.callback.OnImageCompressListener
import com.casic.detector.callback.OnItemSelectedListener
import com.casic.detector.extensions.*
-import com.casic.detector.utils.DataBaseManager
-import com.casic.detector.utils.LoadingDialogHub
-import com.casic.detector.utils.LocaleConstant
-import com.casic.detector.utils.LocationHub
+import com.casic.detector.utils.*
import com.casic.detector.vm.TaskViewModel
import com.gyf.immersionbar.ImmersionBar
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.SaveKeyValues
import com.pengxh.kt.lite.vm.LoadState
@@ -36,10 +38,11 @@
import kotlinx.android.synthetic.main.include_install_label_object.*
import kotlinx.android.synthetic.main.include_install_label_open_camera.*
import java.io.File
+import java.io.IOException
import java.util.*
@SuppressLint("SetTextI18n")
-class InstallLabelActivity : KotlinBaseActivity() {
+class InstallLabelActivity : SerialPortActivity() {
private val kTag = "InstallLabelActivity"
private val context: Context = this@InstallLabelActivity
@@ -54,8 +57,10 @@
private var identifierTypeSelectedItem = ""
private var colorSelectedItem = ""
private lateinit var taskViewModel: TaskViewModel
+ private lateinit var soundPool: SoundPool
+ private val gpioManager by lazy { GpioManager() }
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
imageAdapter = EditableImageAdapter(this, 3, 3f)
addImageRecyclerView.adapter = imageAdapter
@@ -73,6 +78,9 @@
ownerView.setText("ownerView".getDefaultValue())
identifierDeepView.setText("identifierDeepView".getDefaultValue())
personDeptView.setText("personDeptView".getDefaultValue())
+
+ soundPool = SoundPool(10, AudioManager.STREAM_SYSTEM, 5)
+ soundPool.load(this, R.raw.ring4, 1)
}
override fun initEvent() {
@@ -331,12 +339,64 @@
//TODO 搜索标识器
readLabelButton.setOnClickListener {
- LoadingDialogHub.show(this, "正在搜索标识器,请稍后...")
- identifierIdView.text = "123456789"
- LoadingDialogHub.dismiss()
+ reception = "0"
+ gpioManager.setGpioHigh("18")
+
+ // 1000ms后发送读标识器或搜索信号
+ Handler().postDelayed({ // 发送读标识器或搜索信号
+ try {
+ outputStream?.write(0x02)
+ outputStream?.flush()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }, 1000)
}
}
+ private var reception = ""
+
+
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+ Log.d(kTag, "onDataReceived => " + buffer.contentToString())
+ if (buffer != null) {
+ reception = String.format(
+ "%010d", hex2Str(
+ byte2hex(buffer).substring(6, 22)
+ ).toLong(16)
+ )
+ Log.d(kTag, "onDataReceived => $reception")
+ }
+ }
+
+ private fun byte2hex(buffer: ByteArray): String {
+ var h = ""
+ for (i in buffer.indices) {
+ var temp = Integer.toHexString(buffer[i].toInt() and 0xFF)
+ if (temp.length == 1) {
+ temp = "0$temp"
+ }
+ h += temp
+ }
+ return h
+ }
+
+ private fun hex2Str(hex: String): String {
+ val sb = StringBuilder()
+ val temp = StringBuilder()
+ run {
+ var i = 0
+ while (i < hex.length - 1) {
+ val output = hex.substring(i, i + 2)
+ val decimal = output.toInt(16)
+ sb.append(decimal.toChar())
+ temp.append(decimal)
+ i += 2
+ }
+ }
+ return sb.toString()
+ }
+
private fun takePicture() {
PictureSelector.create(this).openCamera(SelectMimeType.ofImage())
.forResult(object : OnResultCallbackListener {
@@ -429,4 +489,9 @@
.init()
initLayoutImmersionBar(rootView)
}
+
+ override fun onDestroy() {
+ gpioManager.setGpioLow("18")
+ super.onDestroy()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
index 3297c76..ae56b26 100644
--- a/app/src/main/java/com/casic/detector/view/LoginActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
@@ -4,6 +4,7 @@
import com.amap.api.navi.NaviSetting
import com.casic.detector.R
import com.casic.detector.extensions.initLayoutImmersionBar
+import com.casic.detector.utils.GpioManager
import com.casic.detector.utils.LoadingDialogHub
import com.casic.detector.utils.LocaleConstant
import com.casic.detector.vm.UserViewModel
@@ -18,8 +19,10 @@
class LoginActivity : KotlinBaseActivity() {
private lateinit var userViewModel: UserViewModel
+ private val gpioManager by lazy { GpioManager() }
override fun initData() {
+ gpioManager.setGpioLow("18")
//先把导航隐私政策声明,后面导航会用到
NaviSetting.updatePrivacyShow(this, true, true)
NaviSetting.updatePrivacyAgree(this, true)
diff --git a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
index 8bca233..3140bc3 100644
--- a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
@@ -1,14 +1,15 @@
package com.casic.detector.view
+import android.os.Bundle
import com.casic.detector.R
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.extensions.initLayoutImmersionBar
import com.gyf.immersionbar.ImmersionBar
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import kotlinx.android.synthetic.main.activity_search_label.*
-class SearchLabelActivity : KotlinBaseActivity() {
+class SearchLabelActivity : SerialPortActivity() {
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
}
@@ -16,6 +17,10 @@
leftBackView.setOnClickListener { finish() }
}
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+
+ }
+
override fun initLayoutView(): Int = R.layout.activity_search_label
override fun observeRequestState() {
diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk
new file mode 100644
index 0000000..f4ce1c3
--- /dev/null
+++ b/app/src/main/jni/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright 2009 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+TARGET_PLATFORM := android-3
+LOCAL_MODULE := serial_port
+LOCAL_SRC_FILES := SerialPort.c
+LOCAL_LDLIBS := -llog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/app/src/main/jni/Application.mk b/app/src/main/jni/Application.mk
new file mode 100644
index 0000000..a252a72
--- /dev/null
+++ b/app/src/main/jni/Application.mk
@@ -0,0 +1 @@
+APP_ABI := all
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
new file mode 100644
index 0000000..c7229ad
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
@@ -0,0 +1,100 @@
+package com.casic.detector.base
+
+import android.os.Bundle
+import android_serialport_api.SerialPort
+import androidx.appcompat.app.AppCompatActivity
+import com.pengxh.kt.lite.extensions.show
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.security.InvalidParameterException
+
+
+abstract class SerialPortActivity : AppCompatActivity() {
+
+ private var serialPort: SerialPort? = null
+ var outputStream: OutputStream? = null
+ private var inputStream: InputStream? = null
+ private var readThread: ReadThread? = null
+
+ inner class ReadThread : Thread() {
+ override fun run() {
+ super.run()
+ while (!isInterrupted) {
+ var size: Int
+ try {
+ val buffer = ByteArray(64)
+ if (inputStream == null) return
+ size = inputStream!!.read(buffer)
+ if (size > 0) {
+ onDataReceived(buffer, size)
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(initLayoutView())
+ setupTopBarLayout()
+ initData(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ try {
+ serialPort = BaseApplication.get().getSerialPort()
+ outputStream = serialPort?.outputStream
+ inputStream = serialPort?.inputStream
+
+ readThread = ReadThread()
+ readThread?.start()
+ } catch (e: SecurityException) {
+ "您没有串口的读写权限!".show(this)
+ } catch (e: IOException) {
+ "因为不明原因,串口无法打开!".show(this)
+ } catch (e: InvalidParameterException) {
+ "请检查串口!".show(this)
+ }
+ }
+
+ /**
+ * 初始化xml布局
+ */
+ abstract fun initLayoutView(): Int
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initData(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ /**
+ * 串口读数
+ * */
+ abstract fun onDataReceived(buffer: ByteArray?, size: Int)
+
+ override fun onDestroy() {
+ readThread?.interrupt()
+ BaseApplication.get().closeSerialPort()
+ serialPort = null
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/utils/GpioManager.java b/app/src/main/java/com/casic/detector/utils/GpioManager.java
new file mode 100644
index 0000000..0f54f1a
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/GpioManager.java
@@ -0,0 +1,121 @@
+package com.casic.detector.utils;
+
+
+public class GpioManager {
+
+ private static final int MT6761 = 0;
+ private int selected;
+ private final MT6761Gpio mt6761;
+
+ public GpioManager(int selected) {
+ this.selected = selected;
+ mt6761 = new MT6761Gpio();
+ }
+
+ public GpioManager() {
+ mt6761 = new MT6761Gpio();
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ this.selected = selected;
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳叆
+ * *********************************************************************/
+ public void setGpioInput(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioInput();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭楂�
+ * *********************************************************************/
+ public void setGpioHigh(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioHigh();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭浣�
+ * *********************************************************************/
+ public void setGpioLow(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioLow();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO鏃犱笂涓嬫媺
+ * *********************************************************************/
+ public void setNotPen(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setNotPen();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓嬫媺
+ * *********************************************************************/
+ public void setPullDown(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullDown();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓婃媺
+ * *********************************************************************/
+ public void setPullUp(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullUp();
+ }
+ }
+
+ /************************************************************************
+ * 璇诲彇鍗曚釜GPIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireSingleGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioSingle();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireAllGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioAll();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬佹爣棰�
+ * *********************************************************************/
+ public String readGpioTitle() {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ status = mt6761.readGpioTitle();
+ }
+ return status;
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
new file mode 100644
index 0000000..d9d394f
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
@@ -0,0 +1,157 @@
+package com.casic.detector.utils;
+
+import java.io.BufferedReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class MT6761Gpio {
+
+ private final String filePath = "/sys/devices/platform/1000b000.pinctrl/mt_gpio";
+ private String pin;
+
+ public void setGpioHigh() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "1");
+ }
+
+ public void setGpioLow() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "0");
+ }
+
+ public void setGpioInput() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "0");
+ }
+
+ public void setNotPen() {
+ setGpioPen(pin, "0");
+ }
+
+ public void setPullUp() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "1");
+ }
+
+ public void setPullDown() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "0");
+ }
+
+ public void setCtrlPin(String gpio) {
+ pin = gpio;
+ }
+
+ public String readGpioTitle() {
+ return read(filePath, "PIN:");
+ }
+
+ public String readGpioSingle() {
+ int gpio = 0;
+ if (pin.isEmpty()) {
+ return "";
+ }
+ try {
+ gpio = Integer.parseInt(pin);
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+
+ String str = String.format("%3d", gpio).replace(" ", "0");
+ return read(filePath, pin + ":");
+ }
+
+ public String readGpioAll() {
+ return read_all(filePath);
+ }
+
+ private void setGpioMode(String pin, String value) {
+ nm_write("mode " + pin + " " + value);
+ }
+
+ private void setGpioDir(String pin, String value) {
+ nm_write("dir " + pin + " " + value);
+ }
+
+ private void setGpioOut(String pin, String value) {
+ nm_write("out " + pin + " " + value);
+ }
+
+ private void setGpioPen(String pin, String value) { //1:浣胯兘涓婁笅鎷� 0:绂佹涓婁笅鎷�
+ nm_write("pullen " + pin + " " + value);
+ }
+
+ private void setGpioPsel(String pin, String value) { //1:璁剧疆涓婃媺 0:璁剧疆涓嬫媺
+ nm_write("pullsel " + pin + " " + value);
+ }
+
+ private void nm_write(String value) {
+ if (value.isEmpty()) {
+ return;
+ }
+ FileWriter fw;
+ try {
+ fw = new FileWriter(filePath);
+ fw.write(value);
+ fw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public String read(String sys_path, String value) {
+ if (value.isEmpty()) {
+ return null;
+ }
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+
+ String line;
+ while (null != (line = br.readLine())) {
+ if (line.contains(value)) {
+ return line;
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public String read_all(String sys_path) {
+ StringBuilder value = new StringBuilder();
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+
+ while (null != (line = br.readLine())) {
+ value.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return value.toString();
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
index ee56adf..09c5ae1 100644
--- a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
@@ -4,28 +4,30 @@
import android.app.DatePickerDialog
import android.content.Context
import android.content.Intent
+import android.media.AudioManager
+import android.media.SoundPool
+import android.os.Bundle
+import android.os.Handler
import android.provider.Settings
+import android.util.Log
import android.view.View
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.detector.R
import com.casic.detector.adapter.EditableImageAdapter
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.bean.LabelBean
import com.casic.detector.callback.ILocationListener
import com.casic.detector.callback.OnImageCompressListener
import com.casic.detector.callback.OnItemSelectedListener
import com.casic.detector.extensions.*
-import com.casic.detector.utils.DataBaseManager
-import com.casic.detector.utils.LoadingDialogHub
-import com.casic.detector.utils.LocaleConstant
-import com.casic.detector.utils.LocationHub
+import com.casic.detector.utils.*
import com.casic.detector.vm.TaskViewModel
import com.gyf.immersionbar.ImmersionBar
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.SaveKeyValues
import com.pengxh.kt.lite.vm.LoadState
@@ -36,10 +38,11 @@
import kotlinx.android.synthetic.main.include_install_label_object.*
import kotlinx.android.synthetic.main.include_install_label_open_camera.*
import java.io.File
+import java.io.IOException
import java.util.*
@SuppressLint("SetTextI18n")
-class InstallLabelActivity : KotlinBaseActivity() {
+class InstallLabelActivity : SerialPortActivity() {
private val kTag = "InstallLabelActivity"
private val context: Context = this@InstallLabelActivity
@@ -54,8 +57,10 @@
private var identifierTypeSelectedItem = ""
private var colorSelectedItem = ""
private lateinit var taskViewModel: TaskViewModel
+ private lateinit var soundPool: SoundPool
+ private val gpioManager by lazy { GpioManager() }
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
imageAdapter = EditableImageAdapter(this, 3, 3f)
addImageRecyclerView.adapter = imageAdapter
@@ -73,6 +78,9 @@
ownerView.setText("ownerView".getDefaultValue())
identifierDeepView.setText("identifierDeepView".getDefaultValue())
personDeptView.setText("personDeptView".getDefaultValue())
+
+ soundPool = SoundPool(10, AudioManager.STREAM_SYSTEM, 5)
+ soundPool.load(this, R.raw.ring4, 1)
}
override fun initEvent() {
@@ -331,12 +339,64 @@
//TODO 搜索标识器
readLabelButton.setOnClickListener {
- LoadingDialogHub.show(this, "正在搜索标识器,请稍后...")
- identifierIdView.text = "123456789"
- LoadingDialogHub.dismiss()
+ reception = "0"
+ gpioManager.setGpioHigh("18")
+
+ // 1000ms后发送读标识器或搜索信号
+ Handler().postDelayed({ // 发送读标识器或搜索信号
+ try {
+ outputStream?.write(0x02)
+ outputStream?.flush()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }, 1000)
}
}
+ private var reception = ""
+
+
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+ Log.d(kTag, "onDataReceived => " + buffer.contentToString())
+ if (buffer != null) {
+ reception = String.format(
+ "%010d", hex2Str(
+ byte2hex(buffer).substring(6, 22)
+ ).toLong(16)
+ )
+ Log.d(kTag, "onDataReceived => $reception")
+ }
+ }
+
+ private fun byte2hex(buffer: ByteArray): String {
+ var h = ""
+ for (i in buffer.indices) {
+ var temp = Integer.toHexString(buffer[i].toInt() and 0xFF)
+ if (temp.length == 1) {
+ temp = "0$temp"
+ }
+ h += temp
+ }
+ return h
+ }
+
+ private fun hex2Str(hex: String): String {
+ val sb = StringBuilder()
+ val temp = StringBuilder()
+ run {
+ var i = 0
+ while (i < hex.length - 1) {
+ val output = hex.substring(i, i + 2)
+ val decimal = output.toInt(16)
+ sb.append(decimal.toChar())
+ temp.append(decimal)
+ i += 2
+ }
+ }
+ return sb.toString()
+ }
+
private fun takePicture() {
PictureSelector.create(this).openCamera(SelectMimeType.ofImage())
.forResult(object : OnResultCallbackListener {
@@ -429,4 +489,9 @@
.init()
initLayoutImmersionBar(rootView)
}
+
+ override fun onDestroy() {
+ gpioManager.setGpioLow("18")
+ super.onDestroy()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
index 3297c76..ae56b26 100644
--- a/app/src/main/java/com/casic/detector/view/LoginActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
@@ -4,6 +4,7 @@
import com.amap.api.navi.NaviSetting
import com.casic.detector.R
import com.casic.detector.extensions.initLayoutImmersionBar
+import com.casic.detector.utils.GpioManager
import com.casic.detector.utils.LoadingDialogHub
import com.casic.detector.utils.LocaleConstant
import com.casic.detector.vm.UserViewModel
@@ -18,8 +19,10 @@
class LoginActivity : KotlinBaseActivity() {
private lateinit var userViewModel: UserViewModel
+ private val gpioManager by lazy { GpioManager() }
override fun initData() {
+ gpioManager.setGpioLow("18")
//先把导航隐私政策声明,后面导航会用到
NaviSetting.updatePrivacyShow(this, true, true)
NaviSetting.updatePrivacyAgree(this, true)
diff --git a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
index 8bca233..3140bc3 100644
--- a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
@@ -1,14 +1,15 @@
package com.casic.detector.view
+import android.os.Bundle
import com.casic.detector.R
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.extensions.initLayoutImmersionBar
import com.gyf.immersionbar.ImmersionBar
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import kotlinx.android.synthetic.main.activity_search_label.*
-class SearchLabelActivity : KotlinBaseActivity() {
+class SearchLabelActivity : SerialPortActivity() {
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
}
@@ -16,6 +17,10 @@
leftBackView.setOnClickListener { finish() }
}
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+
+ }
+
override fun initLayoutView(): Int = R.layout.activity_search_label
override fun observeRequestState() {
diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk
new file mode 100644
index 0000000..f4ce1c3
--- /dev/null
+++ b/app/src/main/jni/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright 2009 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+TARGET_PLATFORM := android-3
+LOCAL_MODULE := serial_port
+LOCAL_SRC_FILES := SerialPort.c
+LOCAL_LDLIBS := -llog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/app/src/main/jni/Application.mk b/app/src/main/jni/Application.mk
new file mode 100644
index 0000000..a252a72
--- /dev/null
+++ b/app/src/main/jni/Application.mk
@@ -0,0 +1 @@
+APP_ABI := all
diff --git a/app/src/main/jni/SerialPort.c b/app/src/main/jni/SerialPort.c
new file mode 100644
index 0000000..84748a7
--- /dev/null
+++ b/app/src/main/jni/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
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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_android_1serialport_1api_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, "", "()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_android_1serialport_1api_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);
+}
+
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
new file mode 100644
index 0000000..c7229ad
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
@@ -0,0 +1,100 @@
+package com.casic.detector.base
+
+import android.os.Bundle
+import android_serialport_api.SerialPort
+import androidx.appcompat.app.AppCompatActivity
+import com.pengxh.kt.lite.extensions.show
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.security.InvalidParameterException
+
+
+abstract class SerialPortActivity : AppCompatActivity() {
+
+ private var serialPort: SerialPort? = null
+ var outputStream: OutputStream? = null
+ private var inputStream: InputStream? = null
+ private var readThread: ReadThread? = null
+
+ inner class ReadThread : Thread() {
+ override fun run() {
+ super.run()
+ while (!isInterrupted) {
+ var size: Int
+ try {
+ val buffer = ByteArray(64)
+ if (inputStream == null) return
+ size = inputStream!!.read(buffer)
+ if (size > 0) {
+ onDataReceived(buffer, size)
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(initLayoutView())
+ setupTopBarLayout()
+ initData(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ try {
+ serialPort = BaseApplication.get().getSerialPort()
+ outputStream = serialPort?.outputStream
+ inputStream = serialPort?.inputStream
+
+ readThread = ReadThread()
+ readThread?.start()
+ } catch (e: SecurityException) {
+ "您没有串口的读写权限!".show(this)
+ } catch (e: IOException) {
+ "因为不明原因,串口无法打开!".show(this)
+ } catch (e: InvalidParameterException) {
+ "请检查串口!".show(this)
+ }
+ }
+
+ /**
+ * 初始化xml布局
+ */
+ abstract fun initLayoutView(): Int
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initData(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ /**
+ * 串口读数
+ * */
+ abstract fun onDataReceived(buffer: ByteArray?, size: Int)
+
+ override fun onDestroy() {
+ readThread?.interrupt()
+ BaseApplication.get().closeSerialPort()
+ serialPort = null
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/utils/GpioManager.java b/app/src/main/java/com/casic/detector/utils/GpioManager.java
new file mode 100644
index 0000000..0f54f1a
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/GpioManager.java
@@ -0,0 +1,121 @@
+package com.casic.detector.utils;
+
+
+public class GpioManager {
+
+ private static final int MT6761 = 0;
+ private int selected;
+ private final MT6761Gpio mt6761;
+
+ public GpioManager(int selected) {
+ this.selected = selected;
+ mt6761 = new MT6761Gpio();
+ }
+
+ public GpioManager() {
+ mt6761 = new MT6761Gpio();
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ this.selected = selected;
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳叆
+ * *********************************************************************/
+ public void setGpioInput(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioInput();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭楂�
+ * *********************************************************************/
+ public void setGpioHigh(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioHigh();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭浣�
+ * *********************************************************************/
+ public void setGpioLow(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioLow();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO鏃犱笂涓嬫媺
+ * *********************************************************************/
+ public void setNotPen(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setNotPen();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓嬫媺
+ * *********************************************************************/
+ public void setPullDown(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullDown();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓婃媺
+ * *********************************************************************/
+ public void setPullUp(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullUp();
+ }
+ }
+
+ /************************************************************************
+ * 璇诲彇鍗曚釜GPIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireSingleGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioSingle();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireAllGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioAll();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬佹爣棰�
+ * *********************************************************************/
+ public String readGpioTitle() {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ status = mt6761.readGpioTitle();
+ }
+ return status;
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
new file mode 100644
index 0000000..d9d394f
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
@@ -0,0 +1,157 @@
+package com.casic.detector.utils;
+
+import java.io.BufferedReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class MT6761Gpio {
+
+ private final String filePath = "/sys/devices/platform/1000b000.pinctrl/mt_gpio";
+ private String pin;
+
+ public void setGpioHigh() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "1");
+ }
+
+ public void setGpioLow() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "0");
+ }
+
+ public void setGpioInput() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "0");
+ }
+
+ public void setNotPen() {
+ setGpioPen(pin, "0");
+ }
+
+ public void setPullUp() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "1");
+ }
+
+ public void setPullDown() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "0");
+ }
+
+ public void setCtrlPin(String gpio) {
+ pin = gpio;
+ }
+
+ public String readGpioTitle() {
+ return read(filePath, "PIN:");
+ }
+
+ public String readGpioSingle() {
+ int gpio = 0;
+ if (pin.isEmpty()) {
+ return "";
+ }
+ try {
+ gpio = Integer.parseInt(pin);
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+
+ String str = String.format("%3d", gpio).replace(" ", "0");
+ return read(filePath, pin + ":");
+ }
+
+ public String readGpioAll() {
+ return read_all(filePath);
+ }
+
+ private void setGpioMode(String pin, String value) {
+ nm_write("mode " + pin + " " + value);
+ }
+
+ private void setGpioDir(String pin, String value) {
+ nm_write("dir " + pin + " " + value);
+ }
+
+ private void setGpioOut(String pin, String value) {
+ nm_write("out " + pin + " " + value);
+ }
+
+ private void setGpioPen(String pin, String value) { //1:浣胯兘涓婁笅鎷� 0:绂佹涓婁笅鎷�
+ nm_write("pullen " + pin + " " + value);
+ }
+
+ private void setGpioPsel(String pin, String value) { //1:璁剧疆涓婃媺 0:璁剧疆涓嬫媺
+ nm_write("pullsel " + pin + " " + value);
+ }
+
+ private void nm_write(String value) {
+ if (value.isEmpty()) {
+ return;
+ }
+ FileWriter fw;
+ try {
+ fw = new FileWriter(filePath);
+ fw.write(value);
+ fw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public String read(String sys_path, String value) {
+ if (value.isEmpty()) {
+ return null;
+ }
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+
+ String line;
+ while (null != (line = br.readLine())) {
+ if (line.contains(value)) {
+ return line;
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public String read_all(String sys_path) {
+ StringBuilder value = new StringBuilder();
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+
+ while (null != (line = br.readLine())) {
+ value.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return value.toString();
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
index ee56adf..09c5ae1 100644
--- a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
@@ -4,28 +4,30 @@
import android.app.DatePickerDialog
import android.content.Context
import android.content.Intent
+import android.media.AudioManager
+import android.media.SoundPool
+import android.os.Bundle
+import android.os.Handler
import android.provider.Settings
+import android.util.Log
import android.view.View
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.detector.R
import com.casic.detector.adapter.EditableImageAdapter
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.bean.LabelBean
import com.casic.detector.callback.ILocationListener
import com.casic.detector.callback.OnImageCompressListener
import com.casic.detector.callback.OnItemSelectedListener
import com.casic.detector.extensions.*
-import com.casic.detector.utils.DataBaseManager
-import com.casic.detector.utils.LoadingDialogHub
-import com.casic.detector.utils.LocaleConstant
-import com.casic.detector.utils.LocationHub
+import com.casic.detector.utils.*
import com.casic.detector.vm.TaskViewModel
import com.gyf.immersionbar.ImmersionBar
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.SaveKeyValues
import com.pengxh.kt.lite.vm.LoadState
@@ -36,10 +38,11 @@
import kotlinx.android.synthetic.main.include_install_label_object.*
import kotlinx.android.synthetic.main.include_install_label_open_camera.*
import java.io.File
+import java.io.IOException
import java.util.*
@SuppressLint("SetTextI18n")
-class InstallLabelActivity : KotlinBaseActivity() {
+class InstallLabelActivity : SerialPortActivity() {
private val kTag = "InstallLabelActivity"
private val context: Context = this@InstallLabelActivity
@@ -54,8 +57,10 @@
private var identifierTypeSelectedItem = ""
private var colorSelectedItem = ""
private lateinit var taskViewModel: TaskViewModel
+ private lateinit var soundPool: SoundPool
+ private val gpioManager by lazy { GpioManager() }
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
imageAdapter = EditableImageAdapter(this, 3, 3f)
addImageRecyclerView.adapter = imageAdapter
@@ -73,6 +78,9 @@
ownerView.setText("ownerView".getDefaultValue())
identifierDeepView.setText("identifierDeepView".getDefaultValue())
personDeptView.setText("personDeptView".getDefaultValue())
+
+ soundPool = SoundPool(10, AudioManager.STREAM_SYSTEM, 5)
+ soundPool.load(this, R.raw.ring4, 1)
}
override fun initEvent() {
@@ -331,12 +339,64 @@
//TODO 搜索标识器
readLabelButton.setOnClickListener {
- LoadingDialogHub.show(this, "正在搜索标识器,请稍后...")
- identifierIdView.text = "123456789"
- LoadingDialogHub.dismiss()
+ reception = "0"
+ gpioManager.setGpioHigh("18")
+
+ // 1000ms后发送读标识器或搜索信号
+ Handler().postDelayed({ // 发送读标识器或搜索信号
+ try {
+ outputStream?.write(0x02)
+ outputStream?.flush()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }, 1000)
}
}
+ private var reception = ""
+
+
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+ Log.d(kTag, "onDataReceived => " + buffer.contentToString())
+ if (buffer != null) {
+ reception = String.format(
+ "%010d", hex2Str(
+ byte2hex(buffer).substring(6, 22)
+ ).toLong(16)
+ )
+ Log.d(kTag, "onDataReceived => $reception")
+ }
+ }
+
+ private fun byte2hex(buffer: ByteArray): String {
+ var h = ""
+ for (i in buffer.indices) {
+ var temp = Integer.toHexString(buffer[i].toInt() and 0xFF)
+ if (temp.length == 1) {
+ temp = "0$temp"
+ }
+ h += temp
+ }
+ return h
+ }
+
+ private fun hex2Str(hex: String): String {
+ val sb = StringBuilder()
+ val temp = StringBuilder()
+ run {
+ var i = 0
+ while (i < hex.length - 1) {
+ val output = hex.substring(i, i + 2)
+ val decimal = output.toInt(16)
+ sb.append(decimal.toChar())
+ temp.append(decimal)
+ i += 2
+ }
+ }
+ return sb.toString()
+ }
+
private fun takePicture() {
PictureSelector.create(this).openCamera(SelectMimeType.ofImage())
.forResult(object : OnResultCallbackListener {
@@ -429,4 +489,9 @@
.init()
initLayoutImmersionBar(rootView)
}
+
+ override fun onDestroy() {
+ gpioManager.setGpioLow("18")
+ super.onDestroy()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
index 3297c76..ae56b26 100644
--- a/app/src/main/java/com/casic/detector/view/LoginActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
@@ -4,6 +4,7 @@
import com.amap.api.navi.NaviSetting
import com.casic.detector.R
import com.casic.detector.extensions.initLayoutImmersionBar
+import com.casic.detector.utils.GpioManager
import com.casic.detector.utils.LoadingDialogHub
import com.casic.detector.utils.LocaleConstant
import com.casic.detector.vm.UserViewModel
@@ -18,8 +19,10 @@
class LoginActivity : KotlinBaseActivity() {
private lateinit var userViewModel: UserViewModel
+ private val gpioManager by lazy { GpioManager() }
override fun initData() {
+ gpioManager.setGpioLow("18")
//先把导航隐私政策声明,后面导航会用到
NaviSetting.updatePrivacyShow(this, true, true)
NaviSetting.updatePrivacyAgree(this, true)
diff --git a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
index 8bca233..3140bc3 100644
--- a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
@@ -1,14 +1,15 @@
package com.casic.detector.view
+import android.os.Bundle
import com.casic.detector.R
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.extensions.initLayoutImmersionBar
import com.gyf.immersionbar.ImmersionBar
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import kotlinx.android.synthetic.main.activity_search_label.*
-class SearchLabelActivity : KotlinBaseActivity() {
+class SearchLabelActivity : SerialPortActivity() {
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
}
@@ -16,6 +17,10 @@
leftBackView.setOnClickListener { finish() }
}
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+
+ }
+
override fun initLayoutView(): Int = R.layout.activity_search_label
override fun observeRequestState() {
diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk
new file mode 100644
index 0000000..f4ce1c3
--- /dev/null
+++ b/app/src/main/jni/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright 2009 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+TARGET_PLATFORM := android-3
+LOCAL_MODULE := serial_port
+LOCAL_SRC_FILES := SerialPort.c
+LOCAL_LDLIBS := -llog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/app/src/main/jni/Application.mk b/app/src/main/jni/Application.mk
new file mode 100644
index 0000000..a252a72
--- /dev/null
+++ b/app/src/main/jni/Application.mk
@@ -0,0 +1 @@
+APP_ABI := all
diff --git a/app/src/main/jni/SerialPort.c b/app/src/main/jni/SerialPort.c
new file mode 100644
index 0000000..84748a7
--- /dev/null
+++ b/app/src/main/jni/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
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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_android_1serialport_1api_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, "", "()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_android_1serialport_1api_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);
+}
+
diff --git a/app/src/main/jni/SerialPort.h b/app/src/main/jni/SerialPort.h
new file mode 100644
index 0000000..61f1fb2
--- /dev/null
+++ b/app/src/main/jni/SerialPort.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class android_serialport_api_SerialPort */
+
+#ifndef _Included_android_serialport_api_SerialPort
+#define _Included_android_serialport_api_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_android_1serialport_1api_SerialPort_open
+ (JNIEnv *, jclass, jstring, jint, jint);
+
+/*
+ * Class: android_serialport_api_SerialPort
+ * Method: close
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_close
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
new file mode 100644
index 0000000..c7229ad
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
@@ -0,0 +1,100 @@
+package com.casic.detector.base
+
+import android.os.Bundle
+import android_serialport_api.SerialPort
+import androidx.appcompat.app.AppCompatActivity
+import com.pengxh.kt.lite.extensions.show
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.security.InvalidParameterException
+
+
+abstract class SerialPortActivity : AppCompatActivity() {
+
+ private var serialPort: SerialPort? = null
+ var outputStream: OutputStream? = null
+ private var inputStream: InputStream? = null
+ private var readThread: ReadThread? = null
+
+ inner class ReadThread : Thread() {
+ override fun run() {
+ super.run()
+ while (!isInterrupted) {
+ var size: Int
+ try {
+ val buffer = ByteArray(64)
+ if (inputStream == null) return
+ size = inputStream!!.read(buffer)
+ if (size > 0) {
+ onDataReceived(buffer, size)
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(initLayoutView())
+ setupTopBarLayout()
+ initData(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ try {
+ serialPort = BaseApplication.get().getSerialPort()
+ outputStream = serialPort?.outputStream
+ inputStream = serialPort?.inputStream
+
+ readThread = ReadThread()
+ readThread?.start()
+ } catch (e: SecurityException) {
+ "您没有串口的读写权限!".show(this)
+ } catch (e: IOException) {
+ "因为不明原因,串口无法打开!".show(this)
+ } catch (e: InvalidParameterException) {
+ "请检查串口!".show(this)
+ }
+ }
+
+ /**
+ * 初始化xml布局
+ */
+ abstract fun initLayoutView(): Int
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initData(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ /**
+ * 串口读数
+ * */
+ abstract fun onDataReceived(buffer: ByteArray?, size: Int)
+
+ override fun onDestroy() {
+ readThread?.interrupt()
+ BaseApplication.get().closeSerialPort()
+ serialPort = null
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/utils/GpioManager.java b/app/src/main/java/com/casic/detector/utils/GpioManager.java
new file mode 100644
index 0000000..0f54f1a
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/GpioManager.java
@@ -0,0 +1,121 @@
+package com.casic.detector.utils;
+
+
+public class GpioManager {
+
+ private static final int MT6761 = 0;
+ private int selected;
+ private final MT6761Gpio mt6761;
+
+ public GpioManager(int selected) {
+ this.selected = selected;
+ mt6761 = new MT6761Gpio();
+ }
+
+ public GpioManager() {
+ mt6761 = new MT6761Gpio();
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ this.selected = selected;
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳叆
+ * *********************************************************************/
+ public void setGpioInput(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioInput();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭楂�
+ * *********************************************************************/
+ public void setGpioHigh(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioHigh();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭浣�
+ * *********************************************************************/
+ public void setGpioLow(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioLow();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO鏃犱笂涓嬫媺
+ * *********************************************************************/
+ public void setNotPen(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setNotPen();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓嬫媺
+ * *********************************************************************/
+ public void setPullDown(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullDown();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓婃媺
+ * *********************************************************************/
+ public void setPullUp(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullUp();
+ }
+ }
+
+ /************************************************************************
+ * 璇诲彇鍗曚釜GPIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireSingleGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioSingle();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireAllGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioAll();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬佹爣棰�
+ * *********************************************************************/
+ public String readGpioTitle() {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ status = mt6761.readGpioTitle();
+ }
+ return status;
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
new file mode 100644
index 0000000..d9d394f
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
@@ -0,0 +1,157 @@
+package com.casic.detector.utils;
+
+import java.io.BufferedReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class MT6761Gpio {
+
+ private final String filePath = "/sys/devices/platform/1000b000.pinctrl/mt_gpio";
+ private String pin;
+
+ public void setGpioHigh() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "1");
+ }
+
+ public void setGpioLow() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "0");
+ }
+
+ public void setGpioInput() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "0");
+ }
+
+ public void setNotPen() {
+ setGpioPen(pin, "0");
+ }
+
+ public void setPullUp() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "1");
+ }
+
+ public void setPullDown() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "0");
+ }
+
+ public void setCtrlPin(String gpio) {
+ pin = gpio;
+ }
+
+ public String readGpioTitle() {
+ return read(filePath, "PIN:");
+ }
+
+ public String readGpioSingle() {
+ int gpio = 0;
+ if (pin.isEmpty()) {
+ return "";
+ }
+ try {
+ gpio = Integer.parseInt(pin);
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+
+ String str = String.format("%3d", gpio).replace(" ", "0");
+ return read(filePath, pin + ":");
+ }
+
+ public String readGpioAll() {
+ return read_all(filePath);
+ }
+
+ private void setGpioMode(String pin, String value) {
+ nm_write("mode " + pin + " " + value);
+ }
+
+ private void setGpioDir(String pin, String value) {
+ nm_write("dir " + pin + " " + value);
+ }
+
+ private void setGpioOut(String pin, String value) {
+ nm_write("out " + pin + " " + value);
+ }
+
+ private void setGpioPen(String pin, String value) { //1:浣胯兘涓婁笅鎷� 0:绂佹涓婁笅鎷�
+ nm_write("pullen " + pin + " " + value);
+ }
+
+ private void setGpioPsel(String pin, String value) { //1:璁剧疆涓婃媺 0:璁剧疆涓嬫媺
+ nm_write("pullsel " + pin + " " + value);
+ }
+
+ private void nm_write(String value) {
+ if (value.isEmpty()) {
+ return;
+ }
+ FileWriter fw;
+ try {
+ fw = new FileWriter(filePath);
+ fw.write(value);
+ fw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public String read(String sys_path, String value) {
+ if (value.isEmpty()) {
+ return null;
+ }
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+
+ String line;
+ while (null != (line = br.readLine())) {
+ if (line.contains(value)) {
+ return line;
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public String read_all(String sys_path) {
+ StringBuilder value = new StringBuilder();
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+
+ while (null != (line = br.readLine())) {
+ value.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return value.toString();
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
index ee56adf..09c5ae1 100644
--- a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
@@ -4,28 +4,30 @@
import android.app.DatePickerDialog
import android.content.Context
import android.content.Intent
+import android.media.AudioManager
+import android.media.SoundPool
+import android.os.Bundle
+import android.os.Handler
import android.provider.Settings
+import android.util.Log
import android.view.View
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.detector.R
import com.casic.detector.adapter.EditableImageAdapter
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.bean.LabelBean
import com.casic.detector.callback.ILocationListener
import com.casic.detector.callback.OnImageCompressListener
import com.casic.detector.callback.OnItemSelectedListener
import com.casic.detector.extensions.*
-import com.casic.detector.utils.DataBaseManager
-import com.casic.detector.utils.LoadingDialogHub
-import com.casic.detector.utils.LocaleConstant
-import com.casic.detector.utils.LocationHub
+import com.casic.detector.utils.*
import com.casic.detector.vm.TaskViewModel
import com.gyf.immersionbar.ImmersionBar
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.SaveKeyValues
import com.pengxh.kt.lite.vm.LoadState
@@ -36,10 +38,11 @@
import kotlinx.android.synthetic.main.include_install_label_object.*
import kotlinx.android.synthetic.main.include_install_label_open_camera.*
import java.io.File
+import java.io.IOException
import java.util.*
@SuppressLint("SetTextI18n")
-class InstallLabelActivity : KotlinBaseActivity() {
+class InstallLabelActivity : SerialPortActivity() {
private val kTag = "InstallLabelActivity"
private val context: Context = this@InstallLabelActivity
@@ -54,8 +57,10 @@
private var identifierTypeSelectedItem = ""
private var colorSelectedItem = ""
private lateinit var taskViewModel: TaskViewModel
+ private lateinit var soundPool: SoundPool
+ private val gpioManager by lazy { GpioManager() }
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
imageAdapter = EditableImageAdapter(this, 3, 3f)
addImageRecyclerView.adapter = imageAdapter
@@ -73,6 +78,9 @@
ownerView.setText("ownerView".getDefaultValue())
identifierDeepView.setText("identifierDeepView".getDefaultValue())
personDeptView.setText("personDeptView".getDefaultValue())
+
+ soundPool = SoundPool(10, AudioManager.STREAM_SYSTEM, 5)
+ soundPool.load(this, R.raw.ring4, 1)
}
override fun initEvent() {
@@ -331,12 +339,64 @@
//TODO 搜索标识器
readLabelButton.setOnClickListener {
- LoadingDialogHub.show(this, "正在搜索标识器,请稍后...")
- identifierIdView.text = "123456789"
- LoadingDialogHub.dismiss()
+ reception = "0"
+ gpioManager.setGpioHigh("18")
+
+ // 1000ms后发送读标识器或搜索信号
+ Handler().postDelayed({ // 发送读标识器或搜索信号
+ try {
+ outputStream?.write(0x02)
+ outputStream?.flush()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }, 1000)
}
}
+ private var reception = ""
+
+
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+ Log.d(kTag, "onDataReceived => " + buffer.contentToString())
+ if (buffer != null) {
+ reception = String.format(
+ "%010d", hex2Str(
+ byte2hex(buffer).substring(6, 22)
+ ).toLong(16)
+ )
+ Log.d(kTag, "onDataReceived => $reception")
+ }
+ }
+
+ private fun byte2hex(buffer: ByteArray): String {
+ var h = ""
+ for (i in buffer.indices) {
+ var temp = Integer.toHexString(buffer[i].toInt() and 0xFF)
+ if (temp.length == 1) {
+ temp = "0$temp"
+ }
+ h += temp
+ }
+ return h
+ }
+
+ private fun hex2Str(hex: String): String {
+ val sb = StringBuilder()
+ val temp = StringBuilder()
+ run {
+ var i = 0
+ while (i < hex.length - 1) {
+ val output = hex.substring(i, i + 2)
+ val decimal = output.toInt(16)
+ sb.append(decimal.toChar())
+ temp.append(decimal)
+ i += 2
+ }
+ }
+ return sb.toString()
+ }
+
private fun takePicture() {
PictureSelector.create(this).openCamera(SelectMimeType.ofImage())
.forResult(object : OnResultCallbackListener {
@@ -429,4 +489,9 @@
.init()
initLayoutImmersionBar(rootView)
}
+
+ override fun onDestroy() {
+ gpioManager.setGpioLow("18")
+ super.onDestroy()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
index 3297c76..ae56b26 100644
--- a/app/src/main/java/com/casic/detector/view/LoginActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
@@ -4,6 +4,7 @@
import com.amap.api.navi.NaviSetting
import com.casic.detector.R
import com.casic.detector.extensions.initLayoutImmersionBar
+import com.casic.detector.utils.GpioManager
import com.casic.detector.utils.LoadingDialogHub
import com.casic.detector.utils.LocaleConstant
import com.casic.detector.vm.UserViewModel
@@ -18,8 +19,10 @@
class LoginActivity : KotlinBaseActivity() {
private lateinit var userViewModel: UserViewModel
+ private val gpioManager by lazy { GpioManager() }
override fun initData() {
+ gpioManager.setGpioLow("18")
//先把导航隐私政策声明,后面导航会用到
NaviSetting.updatePrivacyShow(this, true, true)
NaviSetting.updatePrivacyAgree(this, true)
diff --git a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
index 8bca233..3140bc3 100644
--- a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
@@ -1,14 +1,15 @@
package com.casic.detector.view
+import android.os.Bundle
import com.casic.detector.R
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.extensions.initLayoutImmersionBar
import com.gyf.immersionbar.ImmersionBar
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import kotlinx.android.synthetic.main.activity_search_label.*
-class SearchLabelActivity : KotlinBaseActivity() {
+class SearchLabelActivity : SerialPortActivity() {
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
}
@@ -16,6 +17,10 @@
leftBackView.setOnClickListener { finish() }
}
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+
+ }
+
override fun initLayoutView(): Int = R.layout.activity_search_label
override fun observeRequestState() {
diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk
new file mode 100644
index 0000000..f4ce1c3
--- /dev/null
+++ b/app/src/main/jni/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright 2009 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+TARGET_PLATFORM := android-3
+LOCAL_MODULE := serial_port
+LOCAL_SRC_FILES := SerialPort.c
+LOCAL_LDLIBS := -llog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/app/src/main/jni/Application.mk b/app/src/main/jni/Application.mk
new file mode 100644
index 0000000..a252a72
--- /dev/null
+++ b/app/src/main/jni/Application.mk
@@ -0,0 +1 @@
+APP_ABI := all
diff --git a/app/src/main/jni/SerialPort.c b/app/src/main/jni/SerialPort.c
new file mode 100644
index 0000000..84748a7
--- /dev/null
+++ b/app/src/main/jni/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
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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_android_1serialport_1api_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, "", "()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_android_1serialport_1api_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);
+}
+
diff --git a/app/src/main/jni/SerialPort.h b/app/src/main/jni/SerialPort.h
new file mode 100644
index 0000000..61f1fb2
--- /dev/null
+++ b/app/src/main/jni/SerialPort.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class android_serialport_api_SerialPort */
+
+#ifndef _Included_android_serialport_api_SerialPort
+#define _Included_android_serialport_api_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_android_1serialport_1api_SerialPort_open
+ (JNIEnv *, jclass, jstring, jint, jint);
+
+/*
+ * Class: android_serialport_api_SerialPort
+ * Method: close
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_close
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/app/src/main/jni/gen_SerialPort_h.sh b/app/src/main/jni/gen_SerialPort_h.sh
new file mode 100755
index 0000000..5414670
--- /dev/null
+++ b/app/src/main/jni/gen_SerialPort_h.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+javah -o SerialPort.h -jni -classpath ../java android_serialport_api.SerialPort
+
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
new file mode 100644
index 0000000..c7229ad
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
@@ -0,0 +1,100 @@
+package com.casic.detector.base
+
+import android.os.Bundle
+import android_serialport_api.SerialPort
+import androidx.appcompat.app.AppCompatActivity
+import com.pengxh.kt.lite.extensions.show
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.security.InvalidParameterException
+
+
+abstract class SerialPortActivity : AppCompatActivity() {
+
+ private var serialPort: SerialPort? = null
+ var outputStream: OutputStream? = null
+ private var inputStream: InputStream? = null
+ private var readThread: ReadThread? = null
+
+ inner class ReadThread : Thread() {
+ override fun run() {
+ super.run()
+ while (!isInterrupted) {
+ var size: Int
+ try {
+ val buffer = ByteArray(64)
+ if (inputStream == null) return
+ size = inputStream!!.read(buffer)
+ if (size > 0) {
+ onDataReceived(buffer, size)
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(initLayoutView())
+ setupTopBarLayout()
+ initData(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ try {
+ serialPort = BaseApplication.get().getSerialPort()
+ outputStream = serialPort?.outputStream
+ inputStream = serialPort?.inputStream
+
+ readThread = ReadThread()
+ readThread?.start()
+ } catch (e: SecurityException) {
+ "您没有串口的读写权限!".show(this)
+ } catch (e: IOException) {
+ "因为不明原因,串口无法打开!".show(this)
+ } catch (e: InvalidParameterException) {
+ "请检查串口!".show(this)
+ }
+ }
+
+ /**
+ * 初始化xml布局
+ */
+ abstract fun initLayoutView(): Int
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initData(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ /**
+ * 串口读数
+ * */
+ abstract fun onDataReceived(buffer: ByteArray?, size: Int)
+
+ override fun onDestroy() {
+ readThread?.interrupt()
+ BaseApplication.get().closeSerialPort()
+ serialPort = null
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/utils/GpioManager.java b/app/src/main/java/com/casic/detector/utils/GpioManager.java
new file mode 100644
index 0000000..0f54f1a
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/GpioManager.java
@@ -0,0 +1,121 @@
+package com.casic.detector.utils;
+
+
+public class GpioManager {
+
+ private static final int MT6761 = 0;
+ private int selected;
+ private final MT6761Gpio mt6761;
+
+ public GpioManager(int selected) {
+ this.selected = selected;
+ mt6761 = new MT6761Gpio();
+ }
+
+ public GpioManager() {
+ mt6761 = new MT6761Gpio();
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ this.selected = selected;
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳叆
+ * *********************************************************************/
+ public void setGpioInput(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioInput();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭楂�
+ * *********************************************************************/
+ public void setGpioHigh(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioHigh();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭浣�
+ * *********************************************************************/
+ public void setGpioLow(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioLow();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO鏃犱笂涓嬫媺
+ * *********************************************************************/
+ public void setNotPen(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setNotPen();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓嬫媺
+ * *********************************************************************/
+ public void setPullDown(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullDown();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓婃媺
+ * *********************************************************************/
+ public void setPullUp(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullUp();
+ }
+ }
+
+ /************************************************************************
+ * 璇诲彇鍗曚釜GPIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireSingleGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioSingle();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireAllGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioAll();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬佹爣棰�
+ * *********************************************************************/
+ public String readGpioTitle() {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ status = mt6761.readGpioTitle();
+ }
+ return status;
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
new file mode 100644
index 0000000..d9d394f
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
@@ -0,0 +1,157 @@
+package com.casic.detector.utils;
+
+import java.io.BufferedReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class MT6761Gpio {
+
+ private final String filePath = "/sys/devices/platform/1000b000.pinctrl/mt_gpio";
+ private String pin;
+
+ public void setGpioHigh() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "1");
+ }
+
+ public void setGpioLow() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "0");
+ }
+
+ public void setGpioInput() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "0");
+ }
+
+ public void setNotPen() {
+ setGpioPen(pin, "0");
+ }
+
+ public void setPullUp() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "1");
+ }
+
+ public void setPullDown() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "0");
+ }
+
+ public void setCtrlPin(String gpio) {
+ pin = gpio;
+ }
+
+ public String readGpioTitle() {
+ return read(filePath, "PIN:");
+ }
+
+ public String readGpioSingle() {
+ int gpio = 0;
+ if (pin.isEmpty()) {
+ return "";
+ }
+ try {
+ gpio = Integer.parseInt(pin);
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+
+ String str = String.format("%3d", gpio).replace(" ", "0");
+ return read(filePath, pin + ":");
+ }
+
+ public String readGpioAll() {
+ return read_all(filePath);
+ }
+
+ private void setGpioMode(String pin, String value) {
+ nm_write("mode " + pin + " " + value);
+ }
+
+ private void setGpioDir(String pin, String value) {
+ nm_write("dir " + pin + " " + value);
+ }
+
+ private void setGpioOut(String pin, String value) {
+ nm_write("out " + pin + " " + value);
+ }
+
+ private void setGpioPen(String pin, String value) { //1:浣胯兘涓婁笅鎷� 0:绂佹涓婁笅鎷�
+ nm_write("pullen " + pin + " " + value);
+ }
+
+ private void setGpioPsel(String pin, String value) { //1:璁剧疆涓婃媺 0:璁剧疆涓嬫媺
+ nm_write("pullsel " + pin + " " + value);
+ }
+
+ private void nm_write(String value) {
+ if (value.isEmpty()) {
+ return;
+ }
+ FileWriter fw;
+ try {
+ fw = new FileWriter(filePath);
+ fw.write(value);
+ fw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public String read(String sys_path, String value) {
+ if (value.isEmpty()) {
+ return null;
+ }
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+
+ String line;
+ while (null != (line = br.readLine())) {
+ if (line.contains(value)) {
+ return line;
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public String read_all(String sys_path) {
+ StringBuilder value = new StringBuilder();
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+
+ while (null != (line = br.readLine())) {
+ value.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return value.toString();
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
index ee56adf..09c5ae1 100644
--- a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
@@ -4,28 +4,30 @@
import android.app.DatePickerDialog
import android.content.Context
import android.content.Intent
+import android.media.AudioManager
+import android.media.SoundPool
+import android.os.Bundle
+import android.os.Handler
import android.provider.Settings
+import android.util.Log
import android.view.View
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.detector.R
import com.casic.detector.adapter.EditableImageAdapter
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.bean.LabelBean
import com.casic.detector.callback.ILocationListener
import com.casic.detector.callback.OnImageCompressListener
import com.casic.detector.callback.OnItemSelectedListener
import com.casic.detector.extensions.*
-import com.casic.detector.utils.DataBaseManager
-import com.casic.detector.utils.LoadingDialogHub
-import com.casic.detector.utils.LocaleConstant
-import com.casic.detector.utils.LocationHub
+import com.casic.detector.utils.*
import com.casic.detector.vm.TaskViewModel
import com.gyf.immersionbar.ImmersionBar
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.SaveKeyValues
import com.pengxh.kt.lite.vm.LoadState
@@ -36,10 +38,11 @@
import kotlinx.android.synthetic.main.include_install_label_object.*
import kotlinx.android.synthetic.main.include_install_label_open_camera.*
import java.io.File
+import java.io.IOException
import java.util.*
@SuppressLint("SetTextI18n")
-class InstallLabelActivity : KotlinBaseActivity() {
+class InstallLabelActivity : SerialPortActivity() {
private val kTag = "InstallLabelActivity"
private val context: Context = this@InstallLabelActivity
@@ -54,8 +57,10 @@
private var identifierTypeSelectedItem = ""
private var colorSelectedItem = ""
private lateinit var taskViewModel: TaskViewModel
+ private lateinit var soundPool: SoundPool
+ private val gpioManager by lazy { GpioManager() }
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
imageAdapter = EditableImageAdapter(this, 3, 3f)
addImageRecyclerView.adapter = imageAdapter
@@ -73,6 +78,9 @@
ownerView.setText("ownerView".getDefaultValue())
identifierDeepView.setText("identifierDeepView".getDefaultValue())
personDeptView.setText("personDeptView".getDefaultValue())
+
+ soundPool = SoundPool(10, AudioManager.STREAM_SYSTEM, 5)
+ soundPool.load(this, R.raw.ring4, 1)
}
override fun initEvent() {
@@ -331,12 +339,64 @@
//TODO 搜索标识器
readLabelButton.setOnClickListener {
- LoadingDialogHub.show(this, "正在搜索标识器,请稍后...")
- identifierIdView.text = "123456789"
- LoadingDialogHub.dismiss()
+ reception = "0"
+ gpioManager.setGpioHigh("18")
+
+ // 1000ms后发送读标识器或搜索信号
+ Handler().postDelayed({ // 发送读标识器或搜索信号
+ try {
+ outputStream?.write(0x02)
+ outputStream?.flush()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }, 1000)
}
}
+ private var reception = ""
+
+
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+ Log.d(kTag, "onDataReceived => " + buffer.contentToString())
+ if (buffer != null) {
+ reception = String.format(
+ "%010d", hex2Str(
+ byte2hex(buffer).substring(6, 22)
+ ).toLong(16)
+ )
+ Log.d(kTag, "onDataReceived => $reception")
+ }
+ }
+
+ private fun byte2hex(buffer: ByteArray): String {
+ var h = ""
+ for (i in buffer.indices) {
+ var temp = Integer.toHexString(buffer[i].toInt() and 0xFF)
+ if (temp.length == 1) {
+ temp = "0$temp"
+ }
+ h += temp
+ }
+ return h
+ }
+
+ private fun hex2Str(hex: String): String {
+ val sb = StringBuilder()
+ val temp = StringBuilder()
+ run {
+ var i = 0
+ while (i < hex.length - 1) {
+ val output = hex.substring(i, i + 2)
+ val decimal = output.toInt(16)
+ sb.append(decimal.toChar())
+ temp.append(decimal)
+ i += 2
+ }
+ }
+ return sb.toString()
+ }
+
private fun takePicture() {
PictureSelector.create(this).openCamera(SelectMimeType.ofImage())
.forResult(object : OnResultCallbackListener {
@@ -429,4 +489,9 @@
.init()
initLayoutImmersionBar(rootView)
}
+
+ override fun onDestroy() {
+ gpioManager.setGpioLow("18")
+ super.onDestroy()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/view/LoginActivity.kt b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
index 3297c76..ae56b26 100644
--- a/app/src/main/java/com/casic/detector/view/LoginActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/LoginActivity.kt
@@ -4,6 +4,7 @@
import com.amap.api.navi.NaviSetting
import com.casic.detector.R
import com.casic.detector.extensions.initLayoutImmersionBar
+import com.casic.detector.utils.GpioManager
import com.casic.detector.utils.LoadingDialogHub
import com.casic.detector.utils.LocaleConstant
import com.casic.detector.vm.UserViewModel
@@ -18,8 +19,10 @@
class LoginActivity : KotlinBaseActivity() {
private lateinit var userViewModel: UserViewModel
+ private val gpioManager by lazy { GpioManager() }
override fun initData() {
+ gpioManager.setGpioLow("18")
//先把导航隐私政策声明,后面导航会用到
NaviSetting.updatePrivacyShow(this, true, true)
NaviSetting.updatePrivacyAgree(this, true)
diff --git a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
index 8bca233..3140bc3 100644
--- a/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/SearchLabelActivity.kt
@@ -1,14 +1,15 @@
package com.casic.detector.view
+import android.os.Bundle
import com.casic.detector.R
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.extensions.initLayoutImmersionBar
import com.gyf.immersionbar.ImmersionBar
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import kotlinx.android.synthetic.main.activity_search_label.*
-class SearchLabelActivity : KotlinBaseActivity() {
+class SearchLabelActivity : SerialPortActivity() {
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
}
@@ -16,6 +17,10 @@
leftBackView.setOnClickListener { finish() }
}
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+
+ }
+
override fun initLayoutView(): Int = R.layout.activity_search_label
override fun observeRequestState() {
diff --git a/app/src/main/jni/Android.mk b/app/src/main/jni/Android.mk
new file mode 100644
index 0000000..f4ce1c3
--- /dev/null
+++ b/app/src/main/jni/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright 2009 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+TARGET_PLATFORM := android-3
+LOCAL_MODULE := serial_port
+LOCAL_SRC_FILES := SerialPort.c
+LOCAL_LDLIBS := -llog
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/app/src/main/jni/Application.mk b/app/src/main/jni/Application.mk
new file mode 100644
index 0000000..a252a72
--- /dev/null
+++ b/app/src/main/jni/Application.mk
@@ -0,0 +1 @@
+APP_ABI := all
diff --git a/app/src/main/jni/SerialPort.c b/app/src/main/jni/SerialPort.c
new file mode 100644
index 0000000..84748a7
--- /dev/null
+++ b/app/src/main/jni/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
+#include
+#include
+#include
+#include
+#include
+#include
+
+#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_android_1serialport_1api_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, "", "()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_android_1serialport_1api_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);
+}
+
diff --git a/app/src/main/jni/SerialPort.h b/app/src/main/jni/SerialPort.h
new file mode 100644
index 0000000..61f1fb2
--- /dev/null
+++ b/app/src/main/jni/SerialPort.h
@@ -0,0 +1,29 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class android_serialport_api_SerialPort */
+
+#ifndef _Included_android_serialport_api_SerialPort
+#define _Included_android_serialport_api_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_android_1serialport_1api_SerialPort_open
+ (JNIEnv *, jclass, jstring, jint, jint);
+
+/*
+ * Class: android_serialport_api_SerialPort
+ * Method: close
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_android_1serialport_1api_SerialPort_close
+ (JNIEnv *, jobject);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/app/src/main/jni/gen_SerialPort_h.sh b/app/src/main/jni/gen_SerialPort_h.sh
new file mode 100755
index 0000000..5414670
--- /dev/null
+++ b/app/src/main/jni/gen_SerialPort_h.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+javah -o SerialPort.h -jni -classpath ../java android_serialport_api.SerialPort
+
diff --git a/app/src/main/jniLibs/arm64-v8a/libserial_port.so b/app/src/main/jniLibs/arm64-v8a/libserial_port.so
new file mode 100755
index 0000000..fe664b1
--- /dev/null
+++ b/app/src/main/jniLibs/arm64-v8a/libserial_port.so
Binary files differ
diff --git a/app/build.gradle b/app/build.gradle
index ef50c2a..b4ce9a7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -14,6 +14,12 @@
targetSdkVersion 32
versionCode 1
versionName "1.0.0.0"
+
+ ndk {
+ moduleName "serial_port"
+ //"log"表示加入Android Logcat日志,需要导入 #include "android/log.h"
+ ldLibs "log"
+ }
}
buildTypes {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c54bf2a..348eb88 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -22,6 +22,12 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/android_serialport_api/SerialPort.java b/app/src/main/java/android_serialport_api/SerialPort.java
new file mode 100644
index 0000000..4b975d9
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPort.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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;
+
+public class SerialPort {
+
+ private static final String TAG = "SerialPort";
+
+ /*
+ * Do not remove or rename the field mFd: it is used by native method close();
+ */
+ private FileDescriptor mFd;
+ private final FileInputStream mFileInputStream;
+ private final FileOutputStream mFileOutputStream;
+
+ public SerialPort(File device, int baudrate, int flags) throws SecurityException, IOException {
+
+ /* Check access permission */
+ if (!device.canRead() || !device.canWrite()) {
+ try {
+ /* Missing read/write permission, trying to chmod the file */
+ Process su;
+ su = Runtime.getRuntime().exec("/system/bin/su");
+ String cmd = "chmod 666 " + device.getAbsolutePath() + "\n"
+ + "exit\n";
+ su.getOutputStream().write(cmd.getBytes());
+ if ((su.waitFor() != 0) || !device.canRead() || !device.canWrite()) {
+ throw new SecurityException();
+ }
+ } 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
+ private native static FileDescriptor open(String path, int baudrate, int flags);
+
+ public native void close();
+
+ static {
+ System.loadLibrary("serial_port");
+ }
+}
diff --git a/app/src/main/java/android_serialport_api/SerialPortFinder.java b/app/src/main/java/android_serialport_api/SerialPortFinder.java
new file mode 100644
index 0000000..23e6b89
--- /dev/null
+++ b/app/src/main/java/android_serialport_api/SerialPortFinder.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2009 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.
+ */
+
+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.Iterator;
+import java.util.Vector;
+
+public class SerialPortFinder {
+
+ public class Driver {
+ public Driver(String name, String root) {
+ mDriverName = name;
+ mDeviceRoot = root;
+ }
+
+ private String mDriverName;
+ private String mDeviceRoot;
+ Vector mDevices = null;
+
+ public Vector getDevices() {
+ if (mDevices == null) {
+ mDevices = new Vector();
+ File dev = new File("/dev");
+ 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]);
+ mDevices.add(files[i]);
+ }
+ }
+ }
+ return mDevices;
+ }
+
+ public String getName() {
+ return mDriverName;
+ }
+ }
+
+ private static final String TAG = "SerialPort";
+
+ private Vector mDrivers = null;
+
+ Vector getDrivers() throws IOException {
+ if (mDrivers == null) {
+ mDrivers = new Vector();
+ LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));
+ String l;
+ while ((l = r.readLine()) != null) {
+ // Issue 3:
+ // Since driver name may contain spaces, we do not extract driver name with split()
+ String drivername = l.substring(0, 0x15).trim();
+ String[] w = l.split(" +");
+ if ((w.length >= 5) && (w[w.length - 1].equals("serial"))) {
+ Log.d(TAG, "Found new driver " + drivername + " on " + w[w.length - 4]);
+ mDrivers.add(new Driver(drivername, w[w.length - 4]));
+ }
+ }
+ r.close();
+ }
+ return mDrivers;
+ }
+
+ public String[] getAllDevices() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getName();
+ String value = String.format("%s (%s)", device, driver.getName());
+ devices.add(value);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+
+ public String[] getAllDevicesPath() {
+ Vector devices = new Vector();
+ // Parse each driver
+ Iterator itdriv;
+ try {
+ itdriv = getDrivers().iterator();
+ while (itdriv.hasNext()) {
+ Driver driver = itdriv.next();
+ Iterator itdev = driver.getDevices().iterator();
+ while (itdev.hasNext()) {
+ String device = itdev.next().getAbsolutePath();
+ devices.add(device);
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return devices.toArray(new String[devices.size()]);
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/base/BaseApplication.kt b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
index f5f784a..c36fcea 100644
--- a/app/src/main/java/com/casic/detector/base/BaseApplication.kt
+++ b/app/src/main/java/com/casic/detector/base/BaseApplication.kt
@@ -1,14 +1,32 @@
package com.casic.detector.base
import android.app.Application
+import android_serialport_api.SerialPort
import com.casic.detector.greendao.DaoMaster
import com.casic.detector.greendao.DaoSession
import com.pengxh.kt.lite.utils.SaveKeyValues
+import java.io.File
+import java.io.IOException
+import java.security.InvalidParameterException
import kotlin.properties.Delegates
+
class BaseApplication : Application() {
private val kTag = "BaseApplication"
+ private var serialPort: SerialPort? = null
+
+ @Throws(SecurityException::class, IOException::class, InvalidParameterException::class)
+ fun getSerialPort(): SerialPort? {
+ if (serialPort == null) {
+ /**
+ * Open the serial port
+ * */
+ serialPort =
+ SerialPort(File("/dev/ttysWK1"), 9600, 0)
+ }
+ return serialPort
+ }
companion object {
private var application: BaseApplication by Delegates.notNull()
@@ -30,4 +48,11 @@
fun getDaoSession(): DaoSession {
return daoSession
}
+
+ fun closeSerialPort() {
+ if (serialPort != null) {
+ serialPort?.close()
+ serialPort = null
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
new file mode 100644
index 0000000..c7229ad
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/base/SerialPortActivity.kt
@@ -0,0 +1,100 @@
+package com.casic.detector.base
+
+import android.os.Bundle
+import android_serialport_api.SerialPort
+import androidx.appcompat.app.AppCompatActivity
+import com.pengxh.kt.lite.extensions.show
+import java.io.IOException
+import java.io.InputStream
+import java.io.OutputStream
+import java.security.InvalidParameterException
+
+
+abstract class SerialPortActivity : AppCompatActivity() {
+
+ private var serialPort: SerialPort? = null
+ var outputStream: OutputStream? = null
+ private var inputStream: InputStream? = null
+ private var readThread: ReadThread? = null
+
+ inner class ReadThread : Thread() {
+ override fun run() {
+ super.run()
+ while (!isInterrupted) {
+ var size: Int
+ try {
+ val buffer = ByteArray(64)
+ if (inputStream == null) return
+ size = inputStream!!.read(buffer)
+ if (size > 0) {
+ onDataReceived(buffer, size)
+ }
+ } catch (e: IOException) {
+ e.printStackTrace()
+ return
+ }
+ }
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(initLayoutView())
+ setupTopBarLayout()
+ initData(savedInstanceState)
+ observeRequestState()
+ initEvent()
+
+ try {
+ serialPort = BaseApplication.get().getSerialPort()
+ outputStream = serialPort?.outputStream
+ inputStream = serialPort?.inputStream
+
+ readThread = ReadThread()
+ readThread?.start()
+ } catch (e: SecurityException) {
+ "您没有串口的读写权限!".show(this)
+ } catch (e: IOException) {
+ "因为不明原因,串口无法打开!".show(this)
+ } catch (e: InvalidParameterException) {
+ "请检查串口!".show(this)
+ }
+ }
+
+ /**
+ * 初始化xml布局
+ */
+ abstract fun initLayoutView(): Int
+
+ /**
+ * 特定页面定制沉浸式状态栏
+ */
+ abstract fun setupTopBarLayout()
+
+ /**
+ * 初始化默认数据
+ */
+ abstract fun initData(savedInstanceState: Bundle?)
+
+ /**
+ * 数据请求状态监听
+ */
+ abstract fun observeRequestState()
+
+ /**
+ * 初始化业务逻辑
+ */
+ abstract fun initEvent()
+
+ /**
+ * 串口读数
+ * */
+ abstract fun onDataReceived(buffer: ByteArray?, size: Int)
+
+ override fun onDestroy() {
+ readThread?.interrupt()
+ BaseApplication.get().closeSerialPort()
+ serialPort = null
+ super.onDestroy()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/casic/detector/utils/GpioManager.java b/app/src/main/java/com/casic/detector/utils/GpioManager.java
new file mode 100644
index 0000000..0f54f1a
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/GpioManager.java
@@ -0,0 +1,121 @@
+package com.casic.detector.utils;
+
+
+public class GpioManager {
+
+ private static final int MT6761 = 0;
+ private int selected;
+ private final MT6761Gpio mt6761;
+
+ public GpioManager(int selected) {
+ this.selected = selected;
+ mt6761 = new MT6761Gpio();
+ }
+
+ public GpioManager() {
+ mt6761 = new MT6761Gpio();
+ }
+
+ public int getSelected() {
+ return selected;
+ }
+
+ public void setSelected(int selected) {
+ this.selected = selected;
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳叆
+ * *********************************************************************/
+ public void setGpioInput(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioInput();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭楂�
+ * *********************************************************************/
+ public void setGpioHigh(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioHigh();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO杈撳嚭浣�
+ * *********************************************************************/
+ public void setGpioLow(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setGpioLow();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO鏃犱笂涓嬫媺
+ * *********************************************************************/
+ public void setNotPen(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setNotPen();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓嬫媺
+ * *********************************************************************/
+ public void setPullDown(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullDown();
+ }
+ }
+
+ /************************************************************************
+ * 璁剧疆GPIO涓婃媺
+ * *********************************************************************/
+ public void setPullUp(String gpio) {
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ mt6761.setPullUp();
+ }
+ }
+
+ /************************************************************************
+ * 璇诲彇鍗曚釜GPIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireSingleGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioSingle();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬�
+ * *********************************************************************/
+ public String inquireAllGpio(String gpio) {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ mt6761.setCtrlPin(gpio);
+ status = mt6761.readGpioAll();
+ }
+ return status;
+ }
+
+ /************************************************************************
+ * 璇诲彇鎵�鏈塆PIO鐨勭姸鎬佹爣棰�
+ * *********************************************************************/
+ public String readGpioTitle() {
+ String status = "";
+ if (this.getSelected() == MT6761) {
+ status = mt6761.readGpioTitle();
+ }
+ return status;
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
new file mode 100644
index 0000000..d9d394f
--- /dev/null
+++ b/app/src/main/java/com/casic/detector/utils/MT6761Gpio.java
@@ -0,0 +1,157 @@
+package com.casic.detector.utils;
+
+import java.io.BufferedReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+public class MT6761Gpio {
+
+ private final String filePath = "/sys/devices/platform/1000b000.pinctrl/mt_gpio";
+ private String pin;
+
+ public void setGpioHigh() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "1");
+ }
+
+ public void setGpioLow() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "1");
+ setGpioOut(pin, "0");
+ }
+
+ public void setGpioInput() {
+ if (pin.isEmpty()) {
+ return;
+ }
+ setGpioMode(pin, "0");
+ setGpioDir(pin, "0");
+ }
+
+ public void setNotPen() {
+ setGpioPen(pin, "0");
+ }
+
+ public void setPullUp() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "1");
+ }
+
+ public void setPullDown() {
+ setGpioPen(pin, "1");
+ setGpioPsel(pin, "0");
+ }
+
+ public void setCtrlPin(String gpio) {
+ pin = gpio;
+ }
+
+ public String readGpioTitle() {
+ return read(filePath, "PIN:");
+ }
+
+ public String readGpioSingle() {
+ int gpio = 0;
+ if (pin.isEmpty()) {
+ return "";
+ }
+ try {
+ gpio = Integer.parseInt(pin);
+ } catch (NumberFormatException e) {
+ e.printStackTrace();
+ }
+
+ String str = String.format("%3d", gpio).replace(" ", "0");
+ return read(filePath, pin + ":");
+ }
+
+ public String readGpioAll() {
+ return read_all(filePath);
+ }
+
+ private void setGpioMode(String pin, String value) {
+ nm_write("mode " + pin + " " + value);
+ }
+
+ private void setGpioDir(String pin, String value) {
+ nm_write("dir " + pin + " " + value);
+ }
+
+ private void setGpioOut(String pin, String value) {
+ nm_write("out " + pin + " " + value);
+ }
+
+ private void setGpioPen(String pin, String value) { //1:浣胯兘涓婁笅鎷� 0:绂佹涓婁笅鎷�
+ nm_write("pullen " + pin + " " + value);
+ }
+
+ private void setGpioPsel(String pin, String value) { //1:璁剧疆涓婃媺 0:璁剧疆涓嬫媺
+ nm_write("pullsel " + pin + " " + value);
+ }
+
+ private void nm_write(String value) {
+ if (value.isEmpty()) {
+ return;
+ }
+ FileWriter fw;
+ try {
+ fw = new FileWriter(filePath);
+ fw.write(value);
+ fw.close();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ public String read(String sys_path, String value) {
+ if (value.isEmpty()) {
+ return null;
+ }
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+
+ String line;
+ while (null != (line = br.readLine())) {
+ if (line.contains(value)) {
+ return line;
+ }
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return "";
+ }
+
+ public String read_all(String sys_path) {
+ StringBuilder value = new StringBuilder();
+ try {
+ Runtime runtime = Runtime.getRuntime();
+ Process process = runtime.exec("cat " + sys_path + "\n"); // 姝ゅ杩涜璇绘搷浣�
+ InputStream is = process.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String line;
+
+ while (null != (line = br.readLine())) {
+ value.append(line).append("\n");
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return value.toString();
+ }
+}
diff --git a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
index ee56adf..09c5ae1 100644
--- a/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
+++ b/app/src/main/java/com/casic/detector/view/InstallLabelActivity.kt
@@ -4,28 +4,30 @@
import android.app.DatePickerDialog
import android.content.Context
import android.content.Intent
+import android.media.AudioManager
+import android.media.SoundPool
+import android.os.Bundle
+import android.os.Handler
import android.provider.Settings
+import android.util.Log
import android.view.View
import androidx.lifecycle.ViewModelProvider
import com.amap.api.location.AMapLocation
import com.casic.detector.R
import com.casic.detector.adapter.EditableImageAdapter
+import com.casic.detector.base.SerialPortActivity
import com.casic.detector.bean.LabelBean
import com.casic.detector.callback.ILocationListener
import com.casic.detector.callback.OnImageCompressListener
import com.casic.detector.callback.OnItemSelectedListener
import com.casic.detector.extensions.*
-import com.casic.detector.utils.DataBaseManager
-import com.casic.detector.utils.LoadingDialogHub
-import com.casic.detector.utils.LocaleConstant
-import com.casic.detector.utils.LocationHub
+import com.casic.detector.utils.*
import com.casic.detector.vm.TaskViewModel
import com.gyf.immersionbar.ImmersionBar
import com.luck.picture.lib.basic.PictureSelector
import com.luck.picture.lib.config.SelectMimeType
import com.luck.picture.lib.entity.LocalMedia
import com.luck.picture.lib.interfaces.OnResultCallbackListener
-import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.*
import com.pengxh.kt.lite.utils.SaveKeyValues
import com.pengxh.kt.lite.vm.LoadState
@@ -36,10 +38,11 @@
import kotlinx.android.synthetic.main.include_install_label_object.*
import kotlinx.android.synthetic.main.include_install_label_open_camera.*
import java.io.File
+import java.io.IOException
import java.util.*
@SuppressLint("SetTextI18n")
-class InstallLabelActivity : KotlinBaseActivity() {
+class InstallLabelActivity : SerialPortActivity() {
private val kTag = "InstallLabelActivity"
private val context: Context = this@InstallLabelActivity
@@ -54,8 +57,10 @@
private var identifierTypeSelectedItem = ""
private var colorSelectedItem = ""
private lateinit var taskViewModel: TaskViewModel
+ private lateinit var soundPool: SoundPool
+ private val gpioManager by lazy { GpioManager() }
- override fun initData() {
+ override fun initData(savedInstanceState: Bundle?) {
imageAdapter = EditableImageAdapter(this, 3, 3f)
addImageRecyclerView.adapter = imageAdapter
@@ -73,6 +78,9 @@
ownerView.setText("ownerView".getDefaultValue())
identifierDeepView.setText("identifierDeepView".getDefaultValue())
personDeptView.setText("personDeptView".getDefaultValue())
+
+ soundPool = SoundPool(10, AudioManager.STREAM_SYSTEM, 5)
+ soundPool.load(this, R.raw.ring4, 1)
}
override fun initEvent() {
@@ -331,12 +339,64 @@
//TODO 搜索标识器
readLabelButton.setOnClickListener {
- LoadingDialogHub.show(this, "正在搜索标识器,请稍后...")
- identifierIdView.text = "123456789"
- LoadingDialogHub.dismiss()
+ reception = "0"
+ gpioManager.setGpioHigh("18")
+
+ // 1000ms后发送读标识器或搜索信号
+ Handler().postDelayed({ // 发送读标识器或搜索信号
+ try {
+ outputStream?.write(0x02)
+ outputStream?.flush()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ }
+ }, 1000)
}
}
+ private var reception = ""
+
+
+ override fun onDataReceived(buffer: ByteArray?, size: Int) {
+ Log.d(kTag, "onDataReceived => " + buffer.contentToString())
+ if (buffer != null) {
+ reception = String.format(
+ "%010d", hex2Str(
+ byte2hex(buffer).substring(6, 22)
+ ).toLong(16)
+ )
+ Log.d(kTag, "onDataReceived => $reception")
+ }
+ }
+
+ private fun byte2hex(buffer: ByteArray): String {
+ var h = ""
+ for (i in buffer.indices) {
+ var temp = Integer.toHexString(buffer[i].toInt() and 0xFF)
+ if (temp.length == 1) {
+ temp = "0$temp"
+ }
+ h += temp
+ }
+ return h
+ }
+
+ private fun hex2Str(hex: String): String {
+ val sb = StringBuilder()
+ val temp = StringBuilder()
+ run {
+ var i = 0
+ while (i < hex.length - 1) {
+ val output = hex.substring(i, i + 2)
+ val decimal = output.toInt(16)
+ sb.append(decimal.toChar())
+ temp.append(decimal)
+ i += 2
+ }
+ }
+ return sb.toString()
+ }
+
private fun takePicture() {
PictureSelector.create(this).openCamera(SelectMimeType.ofImage())
.forResult(object : OnResultCallbackListener