commit a5841aa9dd0fe971771508be9ddf6cccd85d6bed Author: langxiankui <33216671+langxiankui@users.noreply.github.com> Date: Tue Jul 20 14:26:11 2021 +0800 Add files via upload diff --git a/package.json b/package.json new file mode 100644 index 0000000..05960d8 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "cordova-plugin-uhf", + "version": "0.0.1", + "description": "", + "cordova": { + "id": "cordova-plugin-uhf", + "platforms": [ + "android" + ] + }, + "keywords": [ + "ecosystem:cordova", + "cordova-android" + ], + "author": "", + "license": "ISC" +} diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..853f021 --- /dev/null +++ b/plugin.xml @@ -0,0 +1,46 @@ + + + Cordova UHF Plugin + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/android/ModuleAPI_J.jar b/src/android/ModuleAPI_J.jar new file mode 100644 index 0000000..b231d74 Binary files /dev/null and b/src/android/ModuleAPI_J.jar differ diff --git a/src/android/cordova/plugin/uhf/UHF.java b/src/android/cordova/plugin/uhf/UHF.java new file mode 100644 index 0000000..c0aee53 --- /dev/null +++ b/src/android/cordova/plugin/uhf/UHF.java @@ -0,0 +1,283 @@ +package cordova.plugin.uhf; + +import android.os.Message; +import android.util.Log; +import cn.pda.serialport.Tools; +import com.handheld.uhfr.UHFRManager; +import com.uhf.api.cls.Reader; +import org.apache.cordova.CallbackContext; +import org.apache.cordova.CordovaPlugin; +import org.apache.cordova.PluginResult; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.*; + + +/** + * 超高频(UHF)读写卡插件。 + * 因不同的机型使用的so库不同,故无法适配所有机型。 + */ +public class UHF extends CordovaPlugin { + private UHFRManager manager; + private String selectedEpc = ""; + private byte[] password = Tools.HexString2Bytes("00000000"); + private boolean threadFlag; + + @Override + protected void pluginInitialize() { + super.pluginInitialize(); + manager = UHFRManager.getInstance(); + } + + @Override + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { + switch (action) { + case "readCard": + this.readCard(callbackContext); + return true; + case "searchCard": + this.searchCard(callbackContext); + return true; + case "stopSearchCard": + this.stopSearchCard(callbackContext); + return true; + case "writeCard": + this.writeCard(args, callbackContext); + return true; + case "setPower": + this.setPower(args, callbackContext); + return true; + case "startWork": + this.startWork(callbackContext); + return true; + case "endWork": + this.endWork(callbackContext); + return true; + case "selectCard": + this.selectCard(args, callbackContext); + break; + case "inventoryCard": + this.inventoryCard(callbackContext); + return true; + case "stopInventoryCard": + this.stopInventoryCard(callbackContext); + return true; + } + return false; + } + + + private void startWork(CallbackContext callbackContext) { + if (this.manager == null) { + manager = UHFRManager.getInstance(); + } + callbackContext.success(); + } + + private void endWork(CallbackContext callbackContext) { + if (this.manager != null) { + this.manager.close(); + this.manager = null; + } + callbackContext.success(); + } + + + private void stopInventoryCard(CallbackContext callbackContext) { + threadFlag = false; + manager.asyncStopReading(); + callbackContext.success("停止"); + } + + private void inventoryCard(CallbackContext callbackContext) { + threadFlag = true; + manager.asyncStartReading(); + Thread thread = new InventoryThread(callbackContext); + thread.start(); + } + + + /** + * 巡卡,每执行一次,就扫描一次范围内的卡片,将巡到的卡片信息以json数组的形式返回 + */ + private void searchCard(CallbackContext callbackContext) { + manager.asyncStartReading(); + try { + Thread.sleep(100); + JSONArray ja = onceSearchCard(); + manager.asyncStopReading(); + callbackContext.success(ja); + } catch (Exception e) { + callbackContext.error(e.getMessage()); + } + } + + private JSONArray onceSearchCard() throws JSONException { + List list1; + list1 = manager.tagInventoryRealTime(); + String data; + JSONArray ja = new JSONArray(); + JSONObject jo; + if (list1 != null && list1.size() > 0) { + for (Reader.TAGINFO tfs : list1) { + jo = new JSONObject(); + byte[] epcdata = tfs.EpcId; + data = Tools.Bytes2HexString(epcdata, epcdata.length); + int rssi = tfs.RSSI; + jo = new JSONObject(); + jo.put("mEpcBytes", data); + jo.put("mRssi", rssi); + ja.put(jo); + } + } + return ja; + } + + private class InventoryThread extends Thread { + + private CallbackContext cb; + + public InventoryThread(CallbackContext cb) { + super(); + this.cb = cb; + } + + public InventoryThread() { + super(); + } + + @Override + public void run() { + super.run(); + try { + while (threadFlag) { + JSONArray ja = onceSearchCard(); + PluginResult pr = new PluginResult(PluginResult.Status.OK, ja); + pr.setKeepCallback(true); + cb.sendPluginResult(pr); + Thread.sleep(100); + } + } catch (Exception e) { + cb.error(e.getMessage()); + } + } + } + + private void stopSearchCard(CallbackContext callbackContext) { + manager.asyncStopReading(); + callbackContext.success("巡卡停止"); + } + + /** + * 读卡,将USER区的hex字符串转换为ascii读取,因EPC区与TID区不能写入,故暂时只读取USER区,注释掉的部分为适应EPC区与TID区读取的代码 + * 将注释解开后应抛出JSONException + */ + private void readCard(CallbackContext callbackContext) { +// JSONObject obj = message.getJSONObject(0); +// int site = obj.getInt("site"); +// int addr = obj.getInt("addr"); +// if (site == 1) { +// addr = 2; +// length = 6; +// } else if (site == 3) { +// addr = 0; +// length = 32; +// } else if (site == 2) { +// addr = 0; +// length = 12; +// } +// manager.selectEPC(Tools.HexString2Bytes(this.selectedEpc)); + int length = 32; +// byte[] data = manager.readFrom6C(3, 0, length, password); + byte[] data = new byte[length * 2]; + if (this.selectedEpc.length() == 0) { + manager.getTagData(3, 0, length, data, password, (short) 1000); + } else { + data = manager.getTagDataByFilter(3, 0, length, password, (short) 1000, Tools.HexString2Bytes(this.selectedEpc), 1, 0, true); + } + if (data != null && data.length >= 1) { + String msg; +// if (site == 3) { // 读取User区的时候,将16进制字符串转换为ascii + msg = Util.bytes2Str(data); +// } else { // 因EPC区与TID区不能写入,故读取时不转码 +// msg = Tools.Bytes2HexString(data, data.length); +// } + callbackContext.success(msg); + } else { + callbackContext.error("读取失败"); + } + } + + /** + * 选卡,将选到的卡储存在this.selectedEpc中 + */ + private void selectCard(JSONArray message, CallbackContext callbackContext) throws JSONException { + JSONObject obj = message.getJSONObject(0); + String epc = obj.getString("epc"); +// manager.selectEPC(Tools.HexString2Bytes(epc)); + this.selectedEpc = epc; + callbackContext.success(); + } + + /** + * 写卡,将ascii转换为bytes并写入 + */ + private void writeCard(JSONArray message, CallbackContext callbackContext) { +// manager.selectEPC(Tools.HexString2Bytes(this.selectedEpc)); + String _data = null; + try { + JSONObject obj = message.getJSONObject(0); + _data = Util.str2HexStr(obj.getString("data")); + } catch (JSONException e) { + callbackContext.error("JSON解析失败"); + } + // 处理_data,将ascii转换为16进制字符串,超过32 * 4位的16进制字符串报错,小于32 * 4时在16进制字符串末位补0x00作为完结标记,再转换为bytes + if (_data != null && _data.length() > 32 * 4) { + callbackContext.error("数据过长"); + return; + } + if (_data.length() < 32 * 4) { + _data += "00"; + } + byte[] dataBytes = Util.hexStringToBytes(_data); + boolean writeFlag = false; + Reader.READER_ERR er = null; + if (dataBytes != null) { + if (this.selectedEpc.length() > 0) { + er = manager.writeTagDataByFilter((char) 3, 0, dataBytes, dataBytes.length / 2, password, (short) 1000, Tools.HexString2Bytes(this.selectedEpc), 1, 0, true); + } else { + er = manager.writeTagData((char) 3, 0, dataBytes, dataBytes.length / 2, password, (short) 1000); + } +// writeFlag = manager.writeTo6C(password, 3, 0, dataBytes.length / 2, dataBytes); + } + if (er == Reader.READER_ERR.MT_OK_ERR) { + callbackContext.success("写入成功"); + } else { + callbackContext.error("写入失败"); + } + } + + private void setPower(JSONArray message, CallbackContext callbackContext) throws JSONException { + int power = message.getInt(0); + if (power > 30) { + power = 30; + } else if (power < 5) { + power = 5; + } + Reader.READER_ERR err = manager.setPower(power, power); + if (err == Reader.READER_ERR.MT_OK_ERR) { + callbackContext.success("设置成功"); + } else { + callbackContext.error("设置失败"); + } + } + + @Override + public void onDestroy() { + if (this.manager != null) { + this.manager.close(); + } + } +} diff --git a/src/android/cordova/plugin/uhf/Util.java b/src/android/cordova/plugin/uhf/Util.java new file mode 100644 index 0000000..ee1de93 --- /dev/null +++ b/src/android/cordova/plugin/uhf/Util.java @@ -0,0 +1,77 @@ +package cordova.plugin.uhf; + +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +import android.content.Context; +import android.media.AudioManager; +import android.media.SoundPool; +import android.util.Log; + +/** + * 工具类,主要用于实现各类字符串之间的转换 + */ +public class Util { + + public static String str2HexStr(String origin) { + byte[] bytes = origin.getBytes(); + String hex = bytesToHexString(bytes, bytes.length); + return hex; + } + + public static String hexStr2Str(String hex) { + byte[] bb = hexStringToBytes(hex); + String rr = new String(bb); + return rr; + } + + public static String bytes2Str(byte[] src) { + String rr = bytesToHexString(src, src.length); + String str = new String(hexStr2Str(rr)); + return str; + } + + private static String bytesToHexString(byte[] src, int size) { + StringBuilder stringBuilder = new StringBuilder(""); + if (src == null || size <= 0) { + return null; + } + for (int i = 0; i < size; i++) { + int v = src[i] & 0xFF; + String hv = Integer.toHexString(v); + if (hv.length() < 2) { + stringBuilder.append(0); + } + stringBuilder.append(hv); + } + String str = stringBuilder.toString(); + if (str.length() < 128) { + str += "00"; + } + return str; + } + + public static byte[] hexStringToBytes(String hexString) { + if (hexString == null || hexString.equals("")) { + return null; + } + hexString = hexString.toUpperCase(); + int length = hexString.length() / 2; + char[] hexChars = hexString.toCharArray(); + byte[] d = new byte[length]; + for (int i = 0; i < length; i++) { + int pos = i * 2; + // 以0x00为分界线,不读取后面的数据 + if ((byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])) == 00) { + break; + } + d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); + } + return d; + } + + private static byte charToByte(char c) { + return (byte) "0123456789ABCDEF".indexOf(c); + } +} diff --git a/src/android/jxl.jar b/src/android/jxl.jar new file mode 100644 index 0000000..daf1158 Binary files /dev/null and b/src/android/jxl.jar differ diff --git a/src/android/libs/arm64-v8a/libModuleAPIJni.so b/src/android/libs/arm64-v8a/libModuleAPIJni.so new file mode 100644 index 0000000..4072ad2 Binary files /dev/null and b/src/android/libs/arm64-v8a/libModuleAPIJni.so differ diff --git a/src/android/libs/arm64-v8a/libSerialPort.so b/src/android/libs/arm64-v8a/libSerialPort.so new file mode 100644 index 0000000..18949be Binary files /dev/null and b/src/android/libs/arm64-v8a/libSerialPort.so differ diff --git a/src/android/libs/arm64-v8a/libdevapi.so b/src/android/libs/arm64-v8a/libdevapi.so new file mode 100644 index 0000000..4e65b7e Binary files /dev/null and b/src/android/libs/arm64-v8a/libdevapi.so differ diff --git a/src/android/libs/arm64-v8a/libirdaSerialPort.so b/src/android/libs/arm64-v8a/libirdaSerialPort.so new file mode 100644 index 0000000..8c43d80 Binary files /dev/null and b/src/android/libs/arm64-v8a/libirdaSerialPort.so differ diff --git a/src/android/libs/armeabi-v7a/libModuleAPIJni.so b/src/android/libs/armeabi-v7a/libModuleAPIJni.so new file mode 100644 index 0000000..7e07755 Binary files /dev/null and b/src/android/libs/armeabi-v7a/libModuleAPIJni.so differ diff --git a/src/android/libs/armeabi-v7a/libSerialPort.so b/src/android/libs/armeabi-v7a/libSerialPort.so new file mode 100644 index 0000000..d7eb1f9 Binary files /dev/null and b/src/android/libs/armeabi-v7a/libSerialPort.so differ diff --git a/src/android/libs/armeabi-v7a/libdevapi.so b/src/android/libs/armeabi-v7a/libdevapi.so new file mode 100644 index 0000000..4ce4fc6 Binary files /dev/null and b/src/android/libs/armeabi-v7a/libdevapi.so differ diff --git a/src/android/libs/armeabi-v7a/libirdaSerialPort.so b/src/android/libs/armeabi-v7a/libirdaSerialPort.so new file mode 100644 index 0000000..d1c5202 Binary files /dev/null and b/src/android/libs/armeabi-v7a/libirdaSerialPort.so differ diff --git a/src/android/libs/armeabi/libModuleAPIJni.so b/src/android/libs/armeabi/libModuleAPIJni.so new file mode 100644 index 0000000..e837b9d Binary files /dev/null and b/src/android/libs/armeabi/libModuleAPIJni.so differ diff --git a/src/android/libs/armeabi/libSerialPort.so b/src/android/libs/armeabi/libSerialPort.so new file mode 100644 index 0000000..dc3c956 Binary files /dev/null and b/src/android/libs/armeabi/libSerialPort.so differ diff --git a/src/android/libs/armeabi/libdevapi.so b/src/android/libs/armeabi/libdevapi.so new file mode 100644 index 0000000..4ce4fc6 Binary files /dev/null and b/src/android/libs/armeabi/libdevapi.so differ diff --git a/src/android/libs/armeabi/libirdaSerialPort.so b/src/android/libs/armeabi/libirdaSerialPort.so new file mode 100644 index 0000000..b8a8974 Binary files /dev/null and b/src/android/libs/armeabi/libirdaSerialPort.so differ diff --git a/src/android/uhfr_v1.9.jar b/src/android/uhfr_v1.9.jar new file mode 100644 index 0000000..79b553e Binary files /dev/null and b/src/android/uhfr_v1.9.jar differ diff --git a/www/cordova-plugin-UHF.js b/www/cordova-plugin-UHF.js new file mode 100644 index 0000000..704cb08 --- /dev/null +++ b/www/cordova-plugin-UHF.js @@ -0,0 +1,41 @@ +var exec = require('cordova/exec'); + +var coolMethod = function () {}; + +coolMethod.readCard = function (success, error) { + exec(success, error, 'UHF', 'readCard', []); +} + +coolMethod.inventoryCard = function (success, error) { + exec(success, error, 'UHF', 'inventoryCard', []); +} + +coolMethod.stopInventoryCard = function (success, error) { + exec(success, error, 'UHF', 'stopInventoryCard', []); +} + +coolMethod.searchCard = function (success, error) { + exec(success, error, 'UHF', 'searchCard', []); +} + +coolMethod.writeCard = function (arg, success, error) { + exec(success, error, 'UHF', 'writeCard', [arg]); +} + +coolMethod.setPower = function (arg, success, error) { + exec(success, error, 'UHF', 'setPower', [arg]); +} + +coolMethod.startWork = function (success, error) { + exec(success, error, 'UHF', 'startWork', []); +} + +coolMethod.endWork = function (success, error) { + exec(success, error, 'UHF', 'endWork', []); +} + +coolMethod.selectCard = function (arg, success, error) { + exec(success, error, 'UHF', 'selectCard', [arg]); +} + +module.exports = coolMethod;