commit cc514ab4a2efbf2f936b1cbcb4706fbfe4c0fcea Author: wuxiang Date: Sun Oct 15 15:06:06 2023 +0800 init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..56bba1b --- /dev/null +++ b/.gitignore @@ -0,0 +1,51 @@ +# Specifies intentionally untracked files to ignore when using Git +# http://git-scm.com/docs/gitignore + +*~ +*.sw[mnpcod] +.tmp +*.tmp +*.tmp.* +UserInterfaceState.xcuserstate +$RECYCLE.BIN/ + +*.log +log.txt + + +/.sourcemaps +/.versions +/coverage + +# IDEs and editors +.idea/ +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-project +*.sublime-workspace + +# Visual Studio Code +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history/* + + +# Miscellaneous +/.angular +/.angular/cache +.sass-cache/ +/connect.lock +/coverage +/libpeerconnection.log +testem.log +/typings + +# System files +.DS_Store +Thumbs.db diff --git a/README.md b/README.md new file mode 100644 index 0000000..7482e5a --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ +# 优博讯 PDA 的 RFID 读卡插件 + +不完善,只实际了基本的巡卡、读卡(EPC码、TID)的功能 + +## 已知问题 + +1. 在开始读卡后,再调用其它方法,将导致后续读到的卡信息无法返回前端。 + +## 示例App +https://m.shuto.cn:8681/public/ubxrfid-demo \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..f77b30a --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "cordova-plugin-ubx-rfid", + "version": "1.0.0", + "description": "Cordova UBX RFID Plugin", + "cordova": { + "id": "cordova-plugin-ubx-rfid", + "platforms": [ + "android" + ] + }, + "keywords": [ + "ecosystem:cordova", + "cordova-android" + ], + "types": "./www/index.d.ts", + "author": "shuto", + "license": "MIT" +} diff --git a/plugin.xml b/plugin.xml new file mode 100644 index 0000000..f5ec94d --- /dev/null +++ b/plugin.xml @@ -0,0 +1,24 @@ + + + + Cordova UBX RFID Plugin + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/android/USDKLibrary-v2.3.0620.aar b/src/android/USDKLibrary-v2.3.0620.aar new file mode 100755 index 0000000..1303b9b Binary files /dev/null and b/src/android/USDKLibrary-v2.3.0620.aar differ diff --git a/src/android/UbxRfid.java b/src/android/UbxRfid.java new file mode 100644 index 0000000..2a8f075 --- /dev/null +++ b/src/android/UbxRfid.java @@ -0,0 +1,339 @@ +package cordova.plugin.rfid; + +import android.util.Log; + +import com.ubx.usdk.RFIDSDKManager; +import com.ubx.usdk.rfid.RfidManager; +import com.ubx.usdk.rfid.aidl.IRfidCallback; +import com.ubx.usdk.util.SoundTool; + +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; + + +/** + * 优博讯超高频(UHF)RFID 读 EPC 插件 + */ +public class UbxRfid extends CordovaPlugin { + + private final String TAG = "UbxUHF"; + private RfidManager rfidManager; + private ScanCallback callback; + public boolean RFID_INIT_STATUS = false; + public int readerType = 0; + private byte session = 0; // 值有 0、1、2、3 ,一般用 0或者1. + private SoundTool soundTool; + private CallbackContext callbackContext; + private boolean beep = true; // 是否响铃 + + @Override + protected void pluginInitialize() { + super.pluginInitialize(); + soundTool = SoundTool.getInstance(cordova.getContext()); + this.callbackContext = null; +// openScanDevice(); // 放在这里,应用加载时会很慢 + } + + private boolean openScanDevice() { + boolean connect = RFIDSDKManager.getInstance().connect(); + + if (connect) { + Log.d(TAG, "initRfid() success."); + RFID_INIT_STATUS = true; + rfidManager = RFIDSDKManager.getInstance().getRfidManager(); + readerType = rfidManager.getReaderType();//80为短距,其他为长距 + Log.d(TAG, "initRfid: firmware = " + rfidManager.getFirmwareVersion()); + Log.d(TAG, "initRfid: ReaderType = " + readerType); + return true; + } else { + Log.d(TAG, "initRfid fail."); + return false; + } + } + + class ScanCallback implements IRfidCallback { + @Override + public void onInventoryTag(String epc, final String tid, final String rssi) { + Log.e(TAG, "onInventoryTag:............... epc:" + epc + ", tid:" + tid + ", rssi:" + rssi); + if (callbackContext == null) { + Log.w(TAG, "callbackContext is NULL"); + return; + } + if (beep) { + soundTool.playBeep(1); + } + JSONObject content = new JSONObject(); + try { + content.put("epc", epc); + content.put("tid", tid); + content.put("rssi", rssi); + } catch (JSONException e) { + Log.w(TAG, e); + callbackContext.error(e.getMessage()); + } + PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, content); + pluginResult.setKeepCallback(true); + callbackContext.sendPluginResult(pluginResult); + } + + /** + * 盘存结束回调(Inventory Command Operate End) + */ + @Override + public void onInventoryTagEnd() { + Log.d(TAG, "onInventoryTagEnd()"); + } + } + + private void setCallback() { + if (this.rfidManager != null) { + if (this.callback == null) { + this.callback = new ScanCallback(); + this.rfidManager.registerCallback(callback); + } + } else { + Log.e(TAG, "rfidManager NOT exist"); + } + } + + @Override + public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException { + this.callbackContext = callbackContext; + if (action.equals("searchCard")) { + this.searchCard(); + return true; + } + if (action.equals("startSearchCard")) { + this.startSearchCard(); + return true; + } + if (action.equals("stopSearchCard")) { + this.stopSearchCard(); + return true; + } + if (action.equals("getPower")) { + this.getPower(); + return true; + } + if (action.equals("setPower")) { + this.setPower(args); + return true; + } + if (action.equals("getDeviceInfo")) { + this.getDeviceInfo(); + return true; + } + if (action.equals("getScanInterval")) { + this.getScanInterval(); + return true; + } + if (action.equals("setScanInterval")) { + this.setScanInterval(args); + return true; + } + if (action.equals("getBeep")) { + this.getBeep(); + return true; + } + if (action.equals("beepOn")) { + this.beepOn(); + return true; + } + if (action.equals("beepOff")) { + this.beepOff(); + return true; + } + if (action.equals("setBeep")) { + this.setBeep(args.getBoolean(0)); + return true; + } + Log.w(TAG, "Unrecognized action: " + action); + return false; + } + + /** + * 开始巡卡 + */ + private void startSearchCard() { + if (!this.tryConnect()) { + return; + } + PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT); + pluginResult.setKeepCallback(true); // Keep callback + callbackContext.sendPluginResult(pluginResult); + rfidManager.startInventory(session); + } + + private boolean tryConnect() { + if (!RFID_INIT_STATUS) { + if (!openScanDevice()) { + callbackContext.error("RFID 未初始化,可能未连接或不可使用"); + return false; + } + } + setCallback(); + return true; + } + + /** + * 停止巡卡 + */ + private void stopSearchCard() { + if (!this.tryConnect()) { + return; + } + rfidManager.stopInventory(); + callbackContext.success(); + } + + /** + * 巡一次卡 + */ + private void searchCard() { + if (!this.tryConnect()) { + return; + } + PluginResult pluginResult = new PluginResult(PluginResult.Status.NO_RESULT); + pluginResult.setKeepCallback(true); // Keep callback + callbackContext.sendPluginResult(pluginResult); + rfidManager.inventorySingle(); + } + + /** + * 获取天线功率 + */ + private void getPower() { + if (!this.tryConnect()) { + return; + } + PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, rfidManager.getOutputPower()); + pluginResult.setKeepCallback(true); // Keep callback + callbackContext.sendPluginResult(pluginResult); + } + + /** + * 设置天线功率 + * + * @param message 功率,长距功率范围:0-33,短距版功率范围:0-26 + * @throws JSONException + */ + private void setPower(JSONArray message) throws JSONException { + if (!this.tryConnect()) { + return; + } + int power = message.getInt(0); + int readerType = rfidManager.getReaderType(); + int maxPower = readerType == 80 ? 26 : 33; // 80 短矩,其它 长矩 + if (power > maxPower) { + power = maxPower; + } else if (power < 0) { + power = 0; + } + rfidManager.setOutputPower((byte) power); + PluginResult pluginResult = new PluginResult(PluginResult.Status.OK); + pluginResult.setKeepCallback(true); // Keep callback + callbackContext.sendPluginResult(pluginResult); + } + + /** + * 获取巡卡间隔 + */ + private void getScanInterval() { + if (!this.tryConnect()) { + return; + } + PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, rfidManager.getScanInterval()); + pluginResult.setKeepCallback(true); // Keep callback + callbackContext.sendPluginResult(pluginResult); + } + + /** + * 设置巡卡间隔 + * @param message 巡卡间隔,一般在 0-60 之间 + * @throws JSONException + */ + private void setScanInterval(JSONArray message) throws JSONException { + if (!this.tryConnect()) { + return; + } + int interval = message.getInt(0); + if (interval > 60) { + interval = 60; + } else if (interval < 0) { + interval = 0; + } + rfidManager.setScanInterval(interval); + PluginResult pluginResult = new PluginResult(PluginResult.Status.OK); + pluginResult.setKeepCallback(true); // Keep callback + callbackContext.sendPluginResult(pluginResult); + } + + /** + * 设置读卡响铃 + */ + private void beepOn() { + this.setBeep(true); + } + + /** + * 关闭读卡响铃 + */ + private void beepOff() { + this.setBeep(false); + } + + private void setBeep(boolean beep) { + this.beep = beep; + PluginResult pluginResult = new PluginResult(PluginResult.Status.OK); + pluginResult.setKeepCallback(true); // Keep callback + callbackContext.sendPluginResult(pluginResult); + } + + /** + * 获取是否响铃 + */ + private void getBeep() { + PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, this.beep); + pluginResult.setKeepCallback(true); // Keep callback + callbackContext.sendPluginResult(pluginResult); + } + + /** + * 获取设备信息 + */ + private void getDeviceInfo() { + if (!this.tryConnect()) { + return; + } + JSONObject content = new JSONObject(); + try { + content.put("type", rfidManager.getReaderType() == 80 ? "短矩" : "长矩"); + content.put("firmware", rfidManager.getFirmwareVersion()); + content.put("power", rfidManager.getOutputPower()); + content.put("scanInterval", rfidManager.getScanInterval()); + content.put("beep", this.beep); + } catch (JSONException e) { + Log.w(TAG, e); + callbackContext.error(e.getMessage()); + return; + } + PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, content); + pluginResult.setKeepCallback(true); // Keep callback + callbackContext.sendPluginResult(pluginResult); + } + + @Override + public void onDestroy() { + if (rfidManager != null) { + rfidManager.unregisterCallback(callback); + rfidManager.disConnect(); + rfidManager.release(); + callback = null; + } + } + +} diff --git a/src/android/build.gradle b/src/android/build.gradle new file mode 100644 index 0000000..a0d0c96 --- /dev/null +++ b/src/android/build.gradle @@ -0,0 +1,3 @@ +dependencies { + implementation files('libs/USDKLibrary-v2.3.0620.aar') +} diff --git a/www/ubx-rfid.js b/www/ubx-rfid.js new file mode 100644 index 0000000..8fdeca6 --- /dev/null +++ b/www/ubx-rfid.js @@ -0,0 +1,124 @@ +var cordova = require('cordova'); +var exec = require('cordova/exec'); + +var UbxRfid = function () {}; + +/** + * 读到卡信息(EPC/ID)时的回调 + * + * @param {Object} epc info + */ +UbxRfid.prototype._epcs = function (info) { + if (info) { + cordova.fireWindowEvent('ubxrfid', info); + } +}; + +/** + * Error callback for error + */ +// UbxRfid.prototype._error = function (e) { +// console.log('Error : ' + e); +// }; + +/** + * 巡一次卡 + * + * @returns 卡信息 + */ +UbxRfid.prototype.searchCard = async function () { + return new Promise((resolve, reject) => exec(resolve,reject, 'UbxRfid', 'searchCard', [])); +}; + +/** + * 开始巡卡 + */ +UbxRfid.prototype.startSearchCard = async function () { + return new Promise((resolve, reject) => { + exec(ubxRfid._epcs, reject, 'UbxRfid', 'startSearchCard', []); + resolve(); + }); +}; + +/** + * 停止巡卡 + */ +UbxRfid.prototype.stopSearchCard = async function () { + return new Promise((resolve, reject) => exec(resolve,reject, 'UbxRfid', 'stopSearchCard', [])); +}; + +/** + * 获取天线功率 + * + * @returns 天线功率 + */ +UbxRfid.prototype.getPower = async function () { + return new Promise((resolve, reject) => exec(resolve,reject, 'UbxRfid', 'getPower', [])); +}; + +/** + * 设置天线功率 + * + * @param {*} data 功率值;长距功率范围:0-33,短距版功率范围:0-26 + */ +UbxRfid.prototype.setPower = async function (data) { + return new Promise((resolve, reject) => exec(resolve,reject, 'UbxRfid', 'setPower', [data])); +}; + +/** + * 获取巡卡时的间隔 + * + * @returns 间隔值,应该在 0-60 之间 + */ +UbxRfid.prototype.getScanInterval = async function () { + return new Promise((resolve, reject) => exec(resolve,reject, 'UbxRfid', 'getScanInterval', [])); +}; + +/** + * 设置巡卡间隔 + * + * @param {*} data 间隔值,应该在 0-60 之间 + */ +UbxRfid.prototype.setScanInterval = async function (data) { + return new Promise((resolve, reject) => exec(resolve,reject, 'UbxRfid', 'setScanInterval', [data])); +}; + +/** + * 获取设备信息 + * + * @returns 设备信息 + */ +UbxRfid.prototype.getDeviceInfo = async function () { + return new Promise((resolve, reject) => exec(resolve,reject, 'UbxRfid', 'getDeviceInfo', [])); +}; + +/** + * 设置读卡响铃 + */ +UbxRfid.prototype.beepOn = async function () { + return new Promise((resolve, reject) => exec(resolve,reject, 'UbxRfid', 'beepOn', [])); +}; + +/** + * 关闭读卡响铃 + */ +UbxRfid.prototype.beepOff = async function () { + return new Promise((resolve, reject) => exec(resolve,reject, 'UbxRfid', 'beepOff', [])); +}; + +UbxRfid.prototype.setBeep = async function (data) { + return new Promise((resolve, reject) => exec(resolve,reject, 'UbxRfid', 'setBeep', [data])); +}; + +/** + * 获取是否响铃 + * + * @returns 是否响铃 + */ +UbxRfid.prototype.getBeep = async function () { + return new Promise((resolve, reject) => exec(resolve,reject, 'UbxRfid', 'getBeep', [])); +}; + +var ubxRfid = new UbxRfid(); + +module.exports = ubxRfid;