Android 4.4.2上与BLE 蓝牙锁设备的通讯

arduino蓝牙模块1 国庆假期玩什么?蓝牙模块了解下!1.蓝牙的来历2.蓝牙3.蓝牙模块的分类经典蓝牙模块低功耗蓝牙模块4.HC-05蓝牙模块5.通信实验 国庆假期到了,小编先祝大家节日玩的开心!然后小编又又又要出来发表文章了图片图片图片 今天,我们来聊一聊Arduino中常用的无线传输模块----蓝牙。 1.蓝牙的来历 介绍蓝牙之前,我们先了解一下蓝牙的来历,蓝牙这个名称来自于第十世纪的一位丹麦国王 Harald Blatand(Bluetooth) , 因为国王喜欢吃蓝莓,牙龈每天都是蓝色的所以叫蓝牙(据说是这个样子的图片 阅读详情

Android 4.4.2上与BLE 蓝牙锁设备的通讯

Android从4.3(Api level 18)开始支持BLE的开发,本文记录了Android 4.4.2设备与BLE设备通讯的流程。

权限需求:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

步骤:
1.获取蓝牙服务
BluetoothManager btManager= (BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE);
2.获取蓝牙设备管理器(适配器)
BluetoothAdapter mBluetoothAdapter = btManager.getAdapter();
3.判断设备是否支持BLE蓝牙通讯,支持则判断蓝牙是否已开启,未开启蓝牙的设置开启。
if (mBluetoothAdapter != null && (!mBluetoothAdapter.isEnabled())){
mBluetoothAdapter.enable();//打开蓝牙
}
4.扫描当前附近的蓝牙BLE设备(这个操作比较耗电,要适时地停止)
5.停止设备扫描
6.与指定BLE设备建立Gatt连接
7.在连接成功后,设置扫描BLE设备支持的service和characteristic,并设置。这里需要注意,需要开启通知的,需要设置相应描述符。
8.读写操作
9.断开Gatt连接
10.关闭Gatt连接

在开发过程中,遇到的主要问题是onCharacteristicWrite失败回调,这个可能跟低功耗蓝牙外设有关,需要断开并关闭Gatt连接重新建立

 下面是主要参考代码

复制代码

package com.rollup.bluetoothlock;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;

import com.android.peephole.MyApplication;
import com.rollup.bluetoothlock.MyLog;
import com.rollup.bluetoothlock.Utils;
import com.rollup.bluetoothlock.Value;



import android.R.integer;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothAdapter.LeScanCallback;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Handler;
import android.os.Message;
import android.widget.EditText;
import android.widget.Toast;

public class BleManager {
    private static final String TAG = "BleManager";
    public static final int ERROR_NO_ERROR = 0;//成功
    public static final int ERROR_BTDEVICE_EXC_FAIL = 1;// 蓝牙锁端执行错误
    public static final int ERROR_PSD_ERROR = 2; // 钥匙错误
    public static final int ERROR_CONNECT_FAIL = 3;
    public static final int ERROR_DEFAULT = 4;
    public static final int ERROR_NOT_FOUND_DEVICE = 5;// 未扫描到指定编码的锁
    public static final int ERROR_HAVE_CONNECTED = 6;//上次连接未执行完毕
    public static final int ERROR_NO_DEVICE = 7;//设备没有初始化
    public static final int ERROR_CREATE_FAIL = 8;

    private static final int STOP_LESCAN = 1;
    private final int OVER_TIMER = 60 * 1000;// 扫描超时时间

    private Context mContext = null;
    private BluetoothAdapter mBluetoothAdapter = null;
    private BluetoothManager mBluetoothManager = null;
    public BluetoothDevice mBluetoothDevice = null;
    private BluetoothGatt mBluetoothGatt;
    private static boolean isScanning = false;
    private BluetoothGattCharacteristic writeCharacteristic = null;
    private static boolean isConnectToDevice = false;
    private String btName = null;
    private String psd = null;
    private boolean hasExcuteOpenDoor = false;// 开门命令已执行
    private byte[] devceKey;

    private static boolean haveRetry = false;
    private static BleManager instance = null;
    private MyHandler mHandler = null;

    public static long lastOpendoorTime = 0;

    private OnBleScanOpenDoorCallback openDoorCallback = null;

    public interface OnBleScanOpenDoorCallback {
        public void openDoorSuc();
        public void openDoorFail(int error);
    }

    private BleManager(Context context, String btName, String psd) {
        this.mContext = context;
        initBluetooth();
        if (mBluetoothManager == null) {
            MyLog.e(TAG, "Unable to initialize BluetoothManager.");
            return;
        }
        this.btName = btName;
        this.psd = psd;
        devceKey = new byte[16];
    }

    public static BleManager getInstance(String btName, String psd) {
        if (instance == null) {
            instance = new BleManager(MyApplication.getMyApplication(), btName,
                    psd);
        } else {
            instance.setBTinfo(btName, psd);
        }
        return instance;
    }

    private void setBTinfo(String name, String psd) {
        this.btName = name;
        this.psd = psd;
    }

    private void initBluetooth() {
        mHandler = new MyHandler(this);
        mBluetoothManager = (BluetoothManager) mContext
                .getSystemService(Context.BLUETOOTH_SERVICE);
        if (mBluetoothManager != null) {
            mBluetoothAdapter = mBluetoothManager.getAdapter();
            if (mBluetoothAdapter != null) {
                if (!mBluetoothAdapter.isEnabled()) {
                    mBluetoothAdapter.enable(); // 打开蓝牙
                }
            }
        }
    }
    
    /**
     * 是否空闲可用
     * @return
     */
    public static boolean isFree(){
        return (!isConnectToDevice)&&(!isScanning);
    }

    public void startLeScan(boolean autoConnect) {
        if (mBluetoothAdapter == null) {
            return;
        }
        if (btName == null || btName.length() == 0) {
            return;
        }

        if (isScanning) {
            return;
        }
        isScanning = true;

        if (autoConnect) {
            mBluetoothAdapter.startLeScan(mLeScanCallback2);
        } else {
            mBluetoothAdapter.startLeScan(mLeScanCallback); // 此mLeScanCallback为回调函数
        }

        mHandler.sendEmptyMessageDelayed(STOP_LESCAN, OVER_TIMER); // 这个搜索30秒,如果搜索不到则停止搜索
    }

    private void stopLeScan() {
        if (mHandler != null && mHandler.hasMessages(STOP_LESCAN)) {
            mHandler.removeMessages(STOP_LESCAN);
        }
        if (mBluetoothAdapter == null) {
            return;
        }

        if (!isScanning) {
            return;
        }
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
        mBluetoothAdapter.stopLeScan(mLeScanCallback2);
        isScanning = false;
    }

    private LeScanCallback mLeScanCallback = new LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int arg1, byte[] arg2) {
            MyLog.i(TAG, "onLeScan() DeviceName------>" + device.getName()); // 在这里可通过device这个对象来获取到搜索到的ble设备名称和一些相关信息
            if (device.getAddress() != null) {
                if (device.getName().toLowerCase().replace("_", "")
                        .contentEquals(btName.toLowerCase().replace(" ", ""))) {
                    mBluetoothDevice = device;
                    stopLeScan();
                }
            }
        }
    };

    private LeScanCallback mLeScanCallback2 = new LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int arg1, byte[] arg2) {
            MyLog.i(TAG, "onLeScan() DeviceName------>" + device.getName()); // 在这里可通过device这个对象来获取到搜索到的ble设备名称和一些相关信息
            if (device.getAddress() != null) {
                if (device.getName().toLowerCase().replace("_", "")
                        .contentEquals(btName.toLowerCase().replace(" ", ""))) {
                    mBluetoothDevice = device;
                    stopLeScan();
                    connect();
                }
            }
        }
    };

    private static class MyHandler extends Handler {
        WeakReference<BleManager> wf = null;

        public MyHandler(BleManager manager) {
            // TODO Auto-generated constructor stub
            wf = new WeakReference<BleManager>(manager);
        }

        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            switch (msg.what) {
            case STOP_LESCAN:
                MyLog.i(TAG,  "MyHandler handleMessage STOP_LESCAN");
                if (wf.get()!=null){
                    wf.get().stopLeScan();
                }
                MyLog.i(TAG, "release(), Scan time is up");
                break;
            }
        }
    }

    public int connect() {
        if (mBluetoothDevice == null) {
            MyLog.i(TAG, "BluetoothDevice is null.");
            return ERROR_NO_DEVICE;
        }
        
        if(isConnectToDevice){
            MyLog.i(TAG, "Have connected to device");
            return ERROR_HAVE_CONNECTED;
        }
        isConnectToDevice = true;
        hasExcuteOpenDoor = false;

        // 两个设备通过BLE通信,首先需要建立GATT连接。这里我们讲的是Android设备作为client端,连接GATT Server

        mBluetoothGatt = mBluetoothDevice.connectGatt(mContext, false,
                mGattCallback); // mGattCallback为回调接口

        if (mBluetoothGatt != null) {

            if (mBluetoothGatt.connect()) {
                MyLog.d(TAG, "Connect succeed.");
                return ERROR_NO_ERROR;
            } else {
                MyLog.d(TAG, "Connect fail.");
                return ERROR_CONNECT_FAIL;
            }
        } else {
            MyLog.d(TAG, "BluetoothGatt null.");
            return ERROR_CREATE_FAIL;
        }
    }

    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status,
                int newState) {
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                isConnectToDevice = true;
                gatt.discoverServices(); // 执行到这里其实蓝牙已经连接成功了
                MyLog.i(TAG, "Connected to GATT server.");
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                if (!hasExcuteOpenDoor) {
                    disconnect();
                    retryUnlock();
                    if (!haveRetry) {
                        //已失败重试过
                        if (openDoorCallback != null) {
                            openDoorCallback.openDoorFail(ERROR_CONNECT_FAIL);
                        }
                    } 
                } else {
                    MyLog.i(TAG, "BluetoothProfile.STATE_DISCONNECTED  hasExcuteOpenDoor=TRUE");
                    haveRetry = false;
                    disconnect();
                }
                MyLog.i(TAG, "BluetoothProfile.STATE_DISCONNECTED --release()");
            }
        }

        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                MyLog.i(TAG, "onServicesDiscovered");
                List<BluetoothGattService> services = gatt.getServices();
                for (int i = 0; i < services.size(); i++) {
                    MyLog.i(TAG, "[Service " + i + "] uuid:"
                            + services.get(i).getUuid());
                    if (services.get(i).getUuid().equals(Value.uuid)) {
                        List<BluetoothGattCharacteristic> characteristics = services
                                .get(i).getCharacteristics();
                        for (int j = 0; j < characteristics.size(); j++) {
                            MyLog.i(TAG, "[Characteristic]"
                                    + characteristics.get(j).getUuid());
                            if (characteristics.get(j).getUuid()
                                    .equals(Value.CHARACTERISTIC_READ)) {
                                boolean res = mBluetoothGatt
                                        .setCharacteristicNotification(
                                                characteristics.get(j), true);
                                // 打开通知描述
                                for (BluetoothGattDescriptor descriptor : characteristics
                                        .get(j).getDescriptors()) {
                                    descriptor
                                            .setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                                    gatt.writeDescriptor(descriptor);
                                    MyLog.i(TAG,
                                            "Characteristic set notification is Success!");
                                }
                                MyLog.i(TAG,
                                        "onServicesDiscovered setCharacteristicNotification result="
                                                + res);
                                break;
                            }
                        }
                        characteristics = null;
                    }
                }

                for (int i = 0; i < services.size(); i++) {
                    MyLog.i(TAG, "[Service " + i + "] uuid:"
                            + services.get(i).getUuid());
                    if (services.get(i).getUuid().equals(Value.uuid)) {
                        List<BluetoothGattCharacteristic> characteristics = services
                                .get(i).getCharacteristics();
                        for (int j = 0; j < characteristics.size(); j++) {
                            MyLog.i(TAG, "[Characteristic]"
                                    + characteristics.get(j).getUuid());
                            if (characteristics.get(j).getUuid()
                                    .equals(Value.CHARACTERISTIC_WRITE)) {
                                writeCharacteristic = characteristics.get(j);
                                final int charaProp = characteristics.get(j)
                                        .getProperties();
                                // 如果该char可写
                                if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                                    byte[] value = new byte[] { 0x01, 0x00,
                                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                            0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                            0x00, 0x00, 0x00 };
                                    characteristics.get(j).setValue(value);
                                    writeCharacteristic
                                            .setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
                                    mBluetoothGatt
                                            .writeCharacteristic(characteristics
                                                    .get(j));
                                    value = null;
                                }
                                break;
                            }
                        }
                        characteristics = null;
                    }
                }
                services = null;
            } else {
                MyLog.i(TAG, "onServicesDiscovered status------>" + status);
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic, int status) {
            MyLog.i(TAG,
                    "onCharacteristicRead------>"
                            + Utils.bytesToHexString(characteristic.getValue()));

        }

        

        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic) {
            MyLog.i(TAG,
                    "onCharacteristicChanged------>"
                            + Utils.bytesToHexString(characteristic.getValue()));
            MyLog.i(TAG, "UUID------>" + characteristic.getUuid().toString());

            if (Value.CHARACTERISTIC_READ.equals(characteristic.getUuid())) {
                byte[] value = characteristic.getValue();
                if ((value[0] & 0xFF) == 0x81) {
                    for (int i = 0; i < 16; i++) {
                        devceKey[i] = value[i + 1];
                    }
                    // MyLog.i(TAG, "加密秘钥为:"+Utils.bytesToHexString(devceKey));
                    if (writeCharacteristic != null) {
                        byte[] cmd = new byte[] { 0x01, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                0x00, 0x00, 0x00 };
                        if (psd.length() == 8) {
                            int j = 0;
                            for (int i = 0; i < 4; i++) {
                                cmd[5 + i] = (byte) (((((Integer.valueOf(psd
                                        .charAt(j)) - 48) << 4) & (0xF0)) + ((Integer
                                        .valueOf(psd.charAt(j + 1)) - 48) & 0x0F)) & 0xFF);
                                MyLog.i(TAG, "cmd" + (9 + i) + "=" + cmd[9 + i]);
                                j = j + 2;
                            }
                        }
                        byte[] cmd_encrypt = Utils.enCode(devceKey, cmd);
                        if (cmd_encrypt != null) {
                            byte[] request = new byte[17];
                            request[0] = 0x03;
                            for (int i = 1; i < (cmd_encrypt.length < request.length ? cmd_encrypt.length
                                    : request.length); i++) {
                                request[i] = cmd_encrypt[i - 1];
                            }
                            writeCharacteristic.setValue(request);
                            writeCharacteristic
                                    .setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
                            // MyLog.i(TAG,
                            // "发送开锁命令:"+Utils.bytesToHexString(request));
                            mBluetoothGatt
                                    .writeCharacteristic(writeCharacteristic);
                            request = null;
                        }
                        cmd_encrypt  = null;
                        cmd = null;
                    }

                } else if ((value[0] & 0xFF) == 0x83) {
                    byte[] res = new byte[16];
                    for (int i = 0; i < 16; i++) {
                        res[i] = value[i + 1];
                    }
                    // MyLog.i(TAG, "解密秘钥为:"+Utils.bytesToHexString(devceKey));
                    // MyLog.i(TAG, "待解密数据为:"+Utils.bytesToHexString(res));
                    byte[] decode_res = Utils.deCode(devceKey, res);
                    hasExcuteOpenDoor = true;
                    if (decode_res != null) {
                        MyLog.i(TAG,
                                "获取到蓝牙开锁返回数据:"
                                        + Utils.bytesToHexString(decode_res));
                        if ((decode_res[0] & 0xFF) == 0x01) {
                            if ((decode_res[1] & 0xFF) == 0x00) {
                                MyLog.i(TAG, "开锁成功");

                                if (openDoorCallback != null) {
                                    openDoorCallback.openDoorSuc();
                                }
                                lastOpendoorTime = System.currentTimeMillis();
                            } else if ((decode_res[1] & 0xFF) == 0x01) {
                                MyLog.i(TAG, "开锁失败:命令执行失败");
                                if (openDoorCallback != null) {
                                    openDoorCallback
                                            .openDoorFail(ERROR_BTDEVICE_EXC_FAIL);
                                }
                            } else if ((decode_res[1] & 0xFF) == 0x02) {
                                MyLog.i(TAG, "开锁失败:密钥解密失败,无效用户密钥");
                                if (openDoorCallback != null) {
                                    openDoorCallback
                                            .openDoorFail(ERROR_PSD_ERROR);
                                }
                            } else {
                                MyLog.e(TAG, "开锁返回异常");
                                if (openDoorCallback != null) {
                                    openDoorCallback
                                            .openDoorFail(ERROR_DEFAULT);
                                }
                            }

                            new Timer().schedule(new TimerTask() {

                                @Override
                                public void run() {
                                    // TODO Auto-generated method stub
                                    sendEndCmd();
                                }
                            }, 500);

                        } else {
                            MyLog.e(TAG, "开锁返回动作标志位异常,此时锁还会再次返回其他数据");
                            if (openDoorCallback != null) {
                                openDoorCallback.openDoorFail(ERROR_DEFAULT);
                            }
                        }

                    } else {
                        MyLog.e(TAG, "蓝牙开锁数据获取失败");
                        if (openDoorCallback != null) {
                            openDoorCallback.openDoorFail(ERROR_DEFAULT);
                        }
//                        disconnect(true);
                    }
                    decode_res = null;
                    res = null;
                } else {
                    MyLog.e(TAG, " value[0] =  " + value[0]
                            + " ===release()    11111111");
//                    disconnect(true);
                }
                value = null;
            }
        }

        // 接受Characteristic被写的通知,收到蓝牙模块的数据后会触发onCharacteristicWrite
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt,
                BluetoothGattCharacteristic characteristic, int status) {
            MyLog.i(TAG,
                    "onCharacteristicWrite status = " + status
                            + ",onCharacteristicWrite------>"
                            + Utils.bytesToHexString(characteristic.getValue()));
            if (status != 0) {
//                disconnect(true);
            }
        }
    };
    
    private void sendEndCmd() {
        if (writeCharacteristic != null) {
            byte[] cmd = new byte[] { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00 };
            byte[] cmd_encrypt = Utils.enCode(devceKey, cmd);
            if (cmd_encrypt != null) {
                byte[] request = new byte[17];
                request[0] = 0x08;
                for (int i = 1; i < (cmd_encrypt.length < request.length ? cmd_encrypt.length
                        : request.length); i++) {
                    request[i] = cmd_encrypt[i - 1];
                }
                writeCharacteristic.setValue(request);
                writeCharacteristic
                        .setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
                mBluetoothGatt.writeCharacteristic(writeCharacteristic);
                request = null;
            }
            cmd = null;
            cmd_encrypt = null;
        }
        // release();
    }

    private void retryUnlock() {
        if (!haveRetry) {
            haveRetry = true;
            connect();
        } else {
            haveRetry = false;
            MyLog.i(TAG, "retryUnlock  haveRetry");
        }
    }

    public void setOpenDoorCallback(OnBleScanOpenDoorCallback callback) {
        openDoorCallback = callback;
    }
    
    public synchronized void disconnect() {
        MyLog.i(TAG, "disconnect");
        if (mBluetoothGatt != null) {
            mBluetoothGatt.disconnect();
            mBluetoothGatt.close();
            mBluetoothGatt = null;
        }
        isConnectToDevice = false;
    }
}

复制代码

复制代码

package com.example.common;

import java.security.SecureRandom;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class Utils {

     /** Convert byte[] to hex string.这里我们可以将byte转换成int,然后利用Integer.toHexString(int)来转换成16进制字符串。  
     * @param src byte[] data  
     * @return hex string  
     */     
    public static String bytesToHexString(byte[] src){  
        StringBuilder stringBuilder = new StringBuilder("");  
        if (src == null || src.length <= 0) {  
            return null;  
        }  
        for (int i = 0; i < src.length; i++) {  
            int v = src[i] & 0xFF;  
            String hv = Integer.toHexString(v);  
            if (hv.length() < 2) {  
                stringBuilder.append(0);  
            }  
            stringBuilder.append(hv);  
        }  
        return stringBuilder.toString();  
    }  
    /** 
     * Convert hex string to byte[] 
     * @param hexString the hex string 
     * @return byte[] 
     */  
    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;  
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));  
        }  
        return d;  
    }  
    
    /** 
     * Convert char to byte 
     * @param c char 
     * @return byte 
     */  
     private static byte charToByte(char c) {  
        return (byte) "0123456789ABCDEF".indexOf(c);  
    }  

    //将指定byte数组以16进制的形式打印到控制台  
    public static void printHexString( byte[] b) {    
       for (int i = 0; i < b.length; i++) {   
         String hex = Integer.toHexString(b[i] & 0xFF);   
         if (hex.length() == 1) {   
           hex = '0' + hex;   
         }   
         System.out.print(hex.toUpperCase() );   
       }   
      
    }  
    
    /**
     * 真正的加密过程
     * 1.通过密钥得到一个密钥专用的对象SecretKeySpec
     * 2.Cipher 加密算法,加密模式和填充方式三部分或指定加密算 (可以只用写算法然后用默认的其他方式)Cipher.getInstance("AES");
     * @param key
     * @param src
     * @return
     * @throws Exception
     */
    public static byte[] enCode(byte[] key, byte[] src) {
        try {
            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/ZeroBytePadding"); 
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
            byte[] encrypted = cipher.doFinal(src);
            return encrypted;
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            return null;
        }
        
    }
    
     /**
     * 解密
     * @param view
     */
    public static byte[] deCode(byte[] key, byte[] src){ 
        try {
            //获取AESkey
            SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/ZeroBytePadding"); //AES/ECB/ZeroBytePadding
            cipher.init(Cipher.DECRYPT_MODE, skeySpec);
            byte[] decrypted = cipher.doFinal(src);
            byte[] result;
            if (decrypted.length<16){
                result = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
                for (int i=0; i<decrypted.length; i++){
                    result[i]=decrypted[i];
                }
            }else{
                result = decrypted;
            }
            return result;
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
            return null;
        }
    }
}

复制代码

复制代码

package com.example.common;

import java.util.UUID;

public class Value {
    public static final String BLE_LOCK_SP_NAME = "BleLockConfig";
    public static final String KEY_BLE_LOCK_ID = "kEY_BLE_LOCK_ID";
    public static final String KEY_BLE_LOCK_KEY = "KEY_BLE_LOCK_KEY";
    
    public final static UUID uuid = UUID.fromString("0000ff12-0000-1000-8000-00805f9b34fb");
    public final static UUID CHARACTERISTIC_WRITE = UUID.fromString("0000ff01-0000-1000-8000-00805f9b34fb");//主机BLE发送给BLE模块数据使用
    public final static UUID CHARACTERISTIC_READ = UUID.fromString("0000ff04-0000-1000-8000-00805f9b34fb");//BLE模块发送给主机BLE数据使用,NOTIFY功能发送,前提是双方连接上后,需要主机BLE主动打开BLE模块的UUID=0XFF04(NOTIFY)功能。
}

复制代码

复制代码

package com.example.bluetoothdemo;

import com.example.common.BleManager;
import com.example.common.Utils;
import com.example.common.BleManager.OnBleScanOpenDoorCallback;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener, OnBleScanOpenDoorCallback{
    
    private final String TAG = "MainActivity";
    private final String KEY_BLE_LOCK_ID = "kEY_BLE_LOCK_ID";
    private final String KEY_BLE_LOCK_KEY = "KEY_BLE_LOCK_KEY";
    
    private BleManager mBleManager = null;
    
    private RelativeLayout relativeLayout = null;
    private EditText idEditText = null;
    private EditText psdEditText = null;
    private Button scanButton = null;
    private Button connectButton = null;
    private ProgressDialog progressDialog = null;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        
        relativeLayout = (RelativeLayout) findViewById(R.id.relativelayout);
        scanButton = (Button) findViewById(R.id.button_scan);    
        connectButton = (Button) findViewById(R.id.button_connect);
        idEditText = (EditText) findViewById(R.id.edittext_lock_id);
        psdEditText = (EditText) findViewById(R.id.edittext_psd);
        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage(getString(R.string.waiting));
        
        SharedPreferences sp = getPreferences(MODE_PRIVATE);
        String bleName = sp.getString(KEY_BLE_LOCK_ID, "ZY121711240013");
        String blePsd = sp.getString(KEY_BLE_LOCK_KEY, "12345678");
        idEditText.setText(bleName);
        psdEditText.setText(blePsd);
        
        relativeLayout.setOnClickListener(this);
        scanButton.setOnClickListener(this);        
        connectButton.setOnClickListener(this);
        
        mBleManager = BleManager.getInstance(bleName, blePsd);  //这个this是一个上下文,只要在上面的BleManager工具类定义一个有参数就好
        mBleManager.setOpenDoorCallback(this);
    }
    
    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
    }
    
    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        SharedPreferences sp = getPreferences(MODE_PRIVATE);
        Editor editable = sp.edit();
        editable.putString(KEY_BLE_LOCK_ID, idEditText.getText().toString().trim());
        editable.putString(KEY_BLE_LOCK_KEY, psdEditText.getText().toString().trim());
        editable.commit();
    }

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        switch (v.getId()) {
        case R.id.button_scan:
            break;
        case R.id.relativelayout:
            InputMethodManager m = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            m .hideSoftInputFromWindow(relativeLayout.getWindowToken(), 0);//比如EditView
            break;
        case R.id.button_connect:
            progressDialog.show();
            int res = mBleManager.connect();
            
            if (res == BleManager.ERROR_NO_ERROR){
            }else if (res == BleManager.ERROR_HAVE_CONNECTED){
                //已经连接不能再次连
                progressDialog.dismiss();
            }else{
                mBleManager.startLeScan(true);
            }

            break;
        
        default:            
            break;
        }
    }

    @Override
    protected void onDestroy() {
        // TODO Auto-generated method stub
        
        if (mBleManager != null){
            mBleManager.setOpenDoorCallback(null);
            mBleManager.disconnect();
            mBleManager = null;
        }
        super.onDestroy();
    }


    @Override
    public void openDoorSuc() {
        // TODO Auto-generated method stub
        runOnUiThread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                if (progressDialog.isShowing()){
                    progressDialog.dismiss();
                }
                Toast.makeText(MainActivity.this, getString(R.string.open_door_suc), Toast.LENGTH_LONG).show();
            }
        });
        
    }

    @Override
    public void openDoorFail(final int error) {
        // TODO Auto-generated method stub
        runOnUiThread(new Runnable() {
            
            @Override
            public void run() {
                // TODO Auto-generated method stub
                if (progressDialog.isShowing()){
                    progressDialog.dismiss();
                }
                int resId  = R.string.error_default;
                if (error==BleManager.ERROR_BTDEVICE_EXC_FAIL){
                    resId = R.string.error_btdevice_exc_fail;
                }else if (error == BleManager.ERROR_CONNECT_FAIL){
                    resId = R.string.error_not_connect;
                }else if (error == BleManager.ERROR_PSD_ERROR){
                    resId = R.string.error_psd_error;
                }else if (error == BleManager.ERROR_NOT_FOUND_DEVICE){
                    resId = R.string.error_device_not_found;
                }
                Toast.makeText(MainActivity.this, resId, Toast.LENGTH_LONG).show();
            }
        });
        
    }
}

复制代码

 

Android之BLE(低功耗)蓝牙开发,kotlin开发安卓 } return bleUtil; } public void startBle() { if (!isStandByBle) { Toast.makeText(context, “该设备不支持蓝牙功能”, Toast.LENGTH_SHORT).show(); return; } bleDevices = new ArrayList<>(); BleScanRuleConfig scanRuleConfig = new BleScanRuleConfig.Builder() // 阅读详情

相关推荐

Android蓝牙自动匹配与连接实现指南

蓝牙技术是一种全球通用的短距离无线通信标准,主要用于替代电缆和其他有线连接方式。它的存在简化了各种电子设备之间的互连,使得音频设备、打印机、键盘、鼠标等都可以通过无线技术实现通信。本章节介绍了如何通过系统服务获取实例,以及如何检查设备蓝牙功能的可用性和监听蓝牙状态变化。通过注册广播接收器并实现相应的处理逻辑,我们可以及时响应设备蓝牙状态的变化,并执行相关的业务逻辑。下一章节中,我们将深入探讨蓝牙设备自动配对的实现方法以及相关代码示例。

weixin_31869917的博客 1289

蓝牙语音通话的实现——音频基础概念

前段时间调试蓝牙语音通话功能,下面做个总结。 环境:iMX6q平台+RTL8723bu模块,PCM接口,Android4.4.2系统 一. 音频基础 (1).PCM概念 就音频领域而言,PCM脉冲编码调制是Pulse...

BHJ1119的专栏 9001

android9.0ble补丁蓝牙语音遥控器支持补丁.rar

ble audio补丁原理是利用hidraw节点捕捉协议栈发送的语音数据,目前Android Blueroid将ble语音数据和按键信息通过hid发送出去,通过建立hidraw节点,可以从中捕捉到语音数据。目前通过ble hal实现从hidraw中读取遥控器语音数据,在Android框架层上就通过配置文件将ble hal导入到音频框架中,并通过绑定Android原生已有的耳麦设备来完成audio音频策略选择,通过apk检测ble连接状态,通知audio服务耳麦设备的状态就可以使得录音通路切换至ble hal,实现从ble获取录音数据功能。 打补丁前最好使用干净的环境,不要有别家方案ble补丁,否则可能会有不兼容问题。 补丁如若不能使用首先检查节点是否存在和其权限,正常节点权限如下: ls -l /dev/hidraw* crw-rw---- 1 system audio 241, 0 2018-12-18 13:42 /dev/hidraw0 audio用户组有读写权限。 2、如果selinux模式为Enforcing,可以通过logcat搜索avc关键字。有如下类似提示则为异常,提示进程没有权限,检查sepolicy是否设置正常: avc: denied { read } for name="/" dev="tmpfs" ino=6145 scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0 tclass=dir permissive=0 //Android 5.0和6.0版本,audio hal被mediaserver进程加载 avc: denied { read } for name="/" dev="tmpfs" ino=8125 scontext=u:r:audioserver:s0 tcontext=u:object_r:device:s0 tclass=dir permissive=0 //Android 7.0版本,audio hal被audioserver进程加载 avc: denied { read } for name="hidraw" dev="sysfs" ino=16332 scontext=u:r:hal_audio_default:s0 tcontext=u:object_r:sysfs:s0 tclass=dir permissive=0 //Android 8.0和9.0版本,audio hal被android.hardware.audio@2.0-service进程加载 3、检查audio的配置,打上patch后,首先确认小机上文件是否有修改到,目前文件可能位于/vendor/etc或/system/etc目录下,其中/vendor/etc下的配置文件是优先解析的。确保文件无误后,通过dumpsys media.audio_policy查看ble hal是否正常加载。 以下是相关说明: AudioPolicyManager: 0xf20c5200 Command Thread: 0xf20af140 Tones Thread: 0xf20af020 ... - Available input devices: Device 1: - id: 3 - type: AUDIO_DEVICE_IN_BUILTIN_MIC - Profiles: Profile 0: - format: AUDIO_FORMAT_PCM_16_BIT - sampling rates:8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000 - channel masks:0x000c, 0x0010 Device 2: - id: 20 - type: AUDIO_DEVICE_IN_WIRED_HEADSET //对应的数值是0x80000010 - name: RemoteDM1204 - Profiles: Available input devices指示当前可用设备,目前ble hal是和AUDIO_DEVICE_IN_WIRED_HEADSET设备绑定,如果需要录音走ble hal,AUDIO_DEVICE_IN_WIRED_HEADSET设备必须出现在可用设备中,如果没有,就可能是补丁中hidaudio.apk的问题。 HW Modules dump: ... - H

android 蓝牙基本的操作

以下是android5.1的相关操作,蓝牙操作的基础是BluetoothAdapter,在整个系统中,该类仅有一个实例。 private BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 判断蓝牙是否可用: Boolean BTis = mBluetoothAdapter.isE

Jack的博客 1240

保姆级教程:在Ubuntu 22.04上用Conda搞定nuPlan数据集环境(Python 3.9 + PyTorch)

本文提供了一份详细的Ubuntu 22.04环境下使用Conda配置nuPlan自动驾驶数据集的保姆级教程,涵盖Python 3.9安装、Conda环境管理、PyTorch配置及数据集可视化验证等关键步骤,帮助开发者高效搭建开发环境。

weixin_29061997的博客 255

IAP板卡远程升级(串口网口都可)+Ymodem+AES对bin文件加密+pc软件+板卡相互烧录

还是决定记录一下,毕竟这个东西我也搞了挺久的,遇到一些棘手的,或者是因为我很粗心遇到的问题也和大家分享一下,。 板卡核心是 STM32F103RCT6,256kflash 前言 开始看这个远程升级的时候,我是一头雾水的,原子哥的教程里面也有说到过iap,有了一个大概的了解,我想不明白的是,通过串口下载的方式把hex文件下载到flash,和把bin文件下载到flash难道不是拉一根线,下载一个文件嘛,(初入职场的我并没有考虑到安全这个问题)如果直接将hex文件给到客户那边,风险是非常大...

那可真是太开心了的博客 5371

Android蓝牙开发初识篇

流程 获取蓝牙操作对象-BluetoothAdapter 开启蓝牙 通过intent,需要用户同意 mBluetoothAdapter.enable() 不用用户同意 查看自己配对信息 bondedDevices 开启可检测性-intent 搜索设备-广播监听、startDiscovery() 统一UUID 成为客户端(写出信息)- BluetoothSocket 成为服务端(读出信息)- ...

猫雨流心的博客 545

第一篇:常见CAN错误帧及其排查方向

在本文中主要阐述各类错误帧的形成原因以及在使用同星硬件设备出现错误帧时,应当 如何进行排查并消除错误帧。在 CAN 总线通信中,通常遇见的错误帧主要为以下五种,其 分别是:bit error、ACK error、stuff error、CRC error 以及 form error。

u013089100的博客 1745

Android Bluetooth蓝牙enable过程

Android BlueDroid蓝牙enable过程 Android Bluetooth框架 enable的追踪从settings app开始,一直到最底层的driver,基本按照上图的框架,把函数的调用过程代入图中有助于理解整个蓝牙的架构。 源码追踪 以下为Bluetooth的enable从settings app开始往下追踪的过程,当然仅为调用过程。 1.BluetoothEnabler.java(packages\apps\settings\src\com\android\settings\blu

生命不息,奋斗不止! 4274

快速理解OSI七层模型(举例理解,数据传输过程,深入理解OSI七层模型)

我们需要了解互联网的本质是一系列的网络协议,这个协议就叫做OSI协议(开放系统互联(Open System Interconnection)),它是由ISO(国际标准化组织)定义的。 需要注意,随着时代的发展,OSI已经被TCP/IP 4层模型淘汰,在当今世界上并没有大规模的使用。 那么对于OSI,人们按照功能不同,分工不同,人为的将OSI的分为七层。实际上这七层是并不存在的,也就是说没有这些概念,而我们今天提到的七层概念,只是人为的划分而已。目的只是为了让大家更好地理解这些都是用来做什么的。

CN_TangZheng的博客 3万+

YOLOv8深度集成SDFM:显著增强特征细节与多尺度融合,实现小目标检测革命性提升

本文介绍了如何将SDFM(Superficial Detail Fusion Module)模块集成到YOLOv8目标检测模型中,以提升特征融合效能。SDFM通过精细的特征预校准、通道注意力机制和动态加权融合策略,有效解决了多尺度特征融合中的细节保留问题。实验表明,集成SDFM后YOLOv8的mAP50-95提升12.7%,召回率提升9.0%,精确率提升5.9%,显著增强了模型性能。教程详细阐述了SDFM的工作原理、代码实现步骤及优化思路,为研究者和开发者提供了实用的技术指南。

FJN110的博客 117

android专题-蓝牙扫描、连接、读写

android专题-蓝牙扫描、连接、读写 项目源码:https://codechina.csdn.net/android1/projectbasic 上篇:无 目录 下篇:

ios、Android、j2ee项目实用技能分享 3257

云效 CI/CD + 阿里云 OSS 自动部署前端项目实战指南(2026)

前端项目部署到 OSS + CDN 是阿里云生态中最常见的静态站点托管方案。手动上传 OSS,容易遗漏文件或部署错版本权限配置不当,要么过宽(全桶读写)要么报 403CDN 缓存没刷新,用户看到的还是旧版本多环境(dev/test/pro)流水线重复配置本文基于实际生产环境经验,完整覆盖从 RAM 权限 → OSS 配置 → CDN 加速 → 云效流水线的全链路,含两种授权方案对比和踩坑记录。一套可直接复用的 RAM 最小权限策略两种云效授权方案的完整配置步骤。

探索云原生与智能化驱动下的安全运维新范式。关注DevSecOps、可观测性、AIOps等前沿领域,与您共赴技术前沿。 429

汇承HC-04蓝牙的使用

理论上,一个蓝牙主端设备,可同时与7个蓝牙从端设备进行通讯。一个具备蓝牙通讯功能的设备, 可以在两个角色间切换,平时工作在从模式,等待其它主设备来连接,需要时,转换为主模式,向其它设备发起呼叫。一个蓝牙设备以主模式发起呼叫时,需要知道对方的蓝牙地址,配对密码等信息,配对完成后,可直接发起呼叫。蓝牙SPP:传统经典蓝牙(以HC-05为代表),2004年SPP协议(Serial Port Profile)泛指支持蓝牙协议在4.0以下的模块,一般用于数据量比较大的传输,如:语音、音乐等较高数据量传输。

weixin_51370842的博客 3704

深入剖析 Hive 中 CASE WHEN 与 IF 函数的性能差异:解锁高效数据处理的关键

CASE WHEN 函数堪称 Hive 中条件判断的多面手,它具备两种强大的语法形式,以应对各种复杂的业务逻辑。简单 CASE 表达式这种形式适用于对某一列的值进行直接的条件匹配。其语法如下:END例如,我们有一个记录学生成绩的表CASE scoreELSE 'D'搜索 CASE 表达式当业务逻辑需要更灵活的条件判断时,搜索 CASE 表达式便派上用场。它的语法为:CASEENDCASEELSE 'D'

2401_83088008的博客 1125

PostgreSQL核心原理:数据库崩溃恢复的唯一真相详解

PostgreSQL崩溃恢复机制通过WAL日志确保数据一致性和持久性。核心流程包括:触发恢复(非正常关闭时)、读取控制文件获取检查点LSN、顺序扫描WAL日志进行Redo阶段重做已提交事务、利用MVCC标记未提交事务为ABORTED实现逻辑撤销,最后执行检查点完成恢复。该机制依赖WAL原子性、检查点锚点和无Undo的可见性模型三大支柱,保证即使系统崩溃也能恢复到逻辑一致状态。关键设计包括延迟写入、LSN顺序控制和FPW防部分写,最终通过确定性重放实现ACID特性。

数据知道的博客 2663

BLE产品开发必看:如何根据各国射频规范调整2.4GHz信道配置

本文为BLE产品开发者提供了应对全球不同国家射频规范的实战指南。文章深入解析了2.4GHz信道配置的全球差异,特别是法国、西班牙等国的特殊限制,并详细介绍了动态功率控制(DPC)策略与欧盟RED认证的关键流程。旨在帮助产品经理和工程师将射频合规性融入开发全周期,确保产品顺利出海。

ik678901的博客 527

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

android 4.4 ble 代码,GitHub - AnlieMelody/BleLib: BleLib是Android低功耗蓝牙4.0及以上开发的辅助库,一行代码解决Ble初始化、扫描、连接、特...

#BleLibBleLib是Android低功耗蓝牙4.0及以上开发的辅助库,一行代码解决Ble初始化、扫描、连接、特性读写、设置通知等操作。BleLib中的关键类:BleService是单个Ble连接操作的服务类GattAttributes类中包含了蓝牙联盟规定的服务和特征的UUID值MultipleBleService类是可多个蓝牙设备同时连接的服务类##Usage###引入BleLib库已上...

weixin_42109732的博客 330

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Android4.2蓝牙Enable完全分析

这应该只会是唯一的一篇从头到尾的调用关系都分析一遍的文章,目的是为了帮助初学者从上往下一层一层分析代码,对大量的代码不再害怕。如果是对阅读Android代码很熟悉的人可以略过这一篇。 蓝牙Enable Android的蓝牙Enable是由BluetoothAdapter提供的。只需要调用BluetoothAdapter.enable()即可启动蓝牙。下面我就分析这一个过程。由于Andr

鱼塘鱼汤的专栏 1万+

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

Android4.4 BLE HOGP 设备回连

Android4.4 环境下 BLE HOGP设备的自动回连 本博文简单介绍了蓝牙BLE HOGP 设备的回连过程,包括回连前的处理和HOGP disconnect后的动作。

utadalight的专栏 6770

Android中蓝牙的基本使用----BluetoothAdapter类简介

原文:http://blog.csdn.net/qinjuning     天气逐渐热了,自己也越来越懒了,虽然看着了很多东西,解决了很多问题,有些收获却不想写着。主要有一下两方面原因:           第一、以前写的一些关于Android知识的Blog,都是在学习过程中发现网络上没有相关知识,因此下了很大决心,才一步                一步码字儿给贴出来。承蒙各位网友的厚爱,本博...

The more effort ,the more lucky 6369

android4.4 BLE开发

最近做android BLE开发,由于有人把大致框架搭建好了(其实也就是

zzj000的专栏 5633

android -- 蓝牙 bluetooth (一) 入门

前段时间在 网上看了一些关于android蓝牙的文章,发现大部分是基于老版本(4.1以前含4.1)的源码,虽然无碍了解蓝牙的基本原理和工作流程,但对着4.2.2的代码看起来总是有些遗憾。所以针对4.2.2版本代码整理下相关知识,当然蓝牙工作的主干流程是没有变的,上电、加载驱动这些动作少不了的,只是这些功能的实现代码位置变了不少。希望本文可以让大家对android4.2的蓝牙部分代码有一个初步的了解

balmy的专栏 7万+

Android Application类的学习

Application是什么Application和Activity、Service一样是系统框架的组件,当程序启动时会自动创建一个Application对象,用来保存一些系统信息。Android系统会为每个程序启动时会创建一个Application对象且只创建一个,因此Application类可以说是单例模式(singleton)的一个类。

freshxu的博客 641

【android 蓝牙开发——BLE(低功耗)蓝牙 2021-10-09更新】

本篇博客,接着上一篇博客,讲一下低功耗蓝牙的开发。相关博客:google 官方文件 比较具有参考价值google 官方 Daemon android-BluetoothLeGatt Android BLE蓝牙4.0开发详解

da_caoyuan的博客 1476
上一篇: pytorch-Train-Val-Test划分(下)
下一篇: linux创建用户
robitmind
博客等级 码龄14年 35粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值