Newer
Older
LaserMethane / LaserMethane / ViewController / Map / MapViewController.swift
//
//  MapViewController.swift
//  LaserMethane
//
//  Created by 203 on 2021/8/6.
//

import Alamofire
import AudioToolbox
import CoreBluetooth
import DefaultsKit
import SnapKit
import SwiftyJSON
import Toast_Swift
import UIKit

class MapViewController: UIViewController, MAMapViewDelegate {
    private let timeFormatter = DateFormatter()
    private let manager = CLLocationManager()
    private let locationManager = AMapLocationManager()
    private let defaults = Defaults.shared
    private var mapView: MAMapView!

    private var topTagView: UIView!
    @IBOutlet var deviceStatusLabel: UILabel!
    @IBOutlet var inspectNameLabel: UILabel!
    @IBOutlet var inspectTimeLabel: UILabel!
    @IBOutlet var stopButton: UIButton!
    @IBOutlet var refreshButton: UIButton!
    @IBOutlet var bluetoothButton: UIButton!
    @IBOutlet var expandButton: UIButton!
    @IBOutlet var minusButton: UIButton!
    @IBOutlet var addEventButton: UIButton!
    @IBOutlet var currentView: UIView!
    @IBOutlet var settingView: UIView!
    @IBOutlet var maxView: UIView!

    @IBOutlet var currentValueLabel: UILabel!
    @IBOutlet var settingValueLabel: UILabel!
    @IBOutlet var maxValueLabel: UILabel!

    private var valueDelegate: TransferValueDelegate!
    private var userModel: UserDataCacheModel!
    private var baseURL: String!
    private var centralManager = CBCentralManager()
    // 扫描到的设备的集合
    private var scanDevices = [CBPeripheral]()
    private var writeCharacteristic: CBCharacteristic!
    private var deviceName: String!
    private var cbPeripheral: CBPeripheral!
    private var isConnected = false
    // 弹窗里面的输入框
    private var inputTextField: UITextField!
    private var inspectionId: String!
    // 新建巡检数据模型
    private var model: NewInspectionModel!
    private var routeArray = [NewRouteModel]()
    private var alarmCount: Int = 0
    private var isGeneratingTask = false

    override func viewDidLoad() {
        super.viewDidLoad()
        // 设置导航栏背景和标题
        title = "巡检"
        navigationController?.navigationBar.isTranslucent = false
        navigationController?.navigationBar.barTintColor = .systemBlue
        let dict: [NSAttributedString.Key: Any] = [NSAttributedString.Key.foregroundColor: UIColor.white]
        navigationController?.navigationBar.titleTextAttributes = dict
        navigationController?.navigationBar.tintColor = .white
        // 初始化基本数据
        baseURL = defaults.get(for: serverConfigKey)!
        userModel = defaults.get(for: userDataCacheModelKey)
        timeFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        // 蓝牙相关
        centralManager.delegate = self
        // 延时加载地图
        DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) { [self] in
            setUpMap()
            // 在地图图层上面View
            topTagView = UIView(frame: CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: 55))
            topTagView.backgroundColor = UIColor(hex: "#D6EEFE")
            addTopTagSubview()
            addLeftSubview()
            addBottomSubview()
            view.addSubview(topTagView)
            // 新建巡检弹窗
            creatNewInspection()
        }
    }

    func creatNewInspection() {
        let isInspectDone = defaults.get(for: statusKey) ?? true
        if isInspectDone {
            let msgAlertCtr = UIAlertController(title: nil, message: "请输入巡检标签", preferredStyle: .alert)
            msgAlertCtr.addTextField { [self] textField in
                textField.placeholder = "如:xxx区间巡检"
                inputTextField = textField
                inputTextField.delegate = self
            }
            let actionOK = UIAlertAction(title: "开始巡检", style: .default) { [self] (_: UIAlertAction) -> Void in
                if inputTextField.text == "" {
                    AlertHub.shared.showWaringAlert(controller: self, message: "巡检标签不能为空")
                    return
                }
                // 获取当前时间戳
                let timeInterval: TimeInterval = Date().timeIntervalSince1970
                let timeStamp = Int(timeInterval)
                // 新建巡检,inspectionId必为空
                inspectionId = timeStamp.id()
                print("巡检id: \(inspectionId!)")
                // 设置标题和时间
                inspectNameLabel.text = inputTextField.text!
                inspectTimeLabel.text = timeFormatter.string(
                        from: Date(timeIntervalSince1970: timeInterval)
                )

                let dateFormatter = DateFormatter()
                dateFormatter.dateFormat = "yyyy-MM-dd"

                // 构造巡检初始参数
                model = NewInspectionModel(
                        id: inspectionId,
                        name: inspectNameLabel.text!,
                        startTime: inspectTimeLabel.text!,
                        endTime: "",
                        date: dateFormatter.string(from: Date(timeIntervalSince1970: timeInterval)),
                        startLng: 0.0,
                        startLat: 0.0,
                        endLng: 0.0,
                        endLat: 0.0,
                        routes: "",
                        user: userModel.name!
                )
                // 开始巡检
                startInspection()
            }
            let actionCancel = UIAlertAction(title: "放弃", style: .cancel) { [self] (_: UIAlertAction) -> Void in
                navigationController?.popViewController(animated: true)
            }
            // 设置取消按钮颜色为红色
            actionCancel.setValue(UIColor.red, forKey: "titleTextColor")
            msgAlertCtr.addAction(actionOK)
            msgAlertCtr.addAction(actionCancel)
            present(msgAlertCtr, animated: true, completion: nil)
        } else {
            let cacheModel = defaults.get(for: inspectionCacheModelKey)
            if cacheModel == nil {
                let alertController = UIAlertController(title: "提示", message: "没有巡检记录,请新建巡检任务", preferredStyle: .alert)
                let okAction = UIAlertAction(title: "去新建", style: .default, handler: { [self] _ in
                    defaults.set(true, for: statusKey)
                    navigationController?.popViewController(animated: true)
                })
                alertController.addAction(okAction)
                present(alertController, animated: true, completion: nil)
            } else {
                model = NewInspectionModel(
                        id: cacheModel!.id,
                        name: cacheModel!.name,
                        startTime: cacheModel!.startTime,
                        endTime: "",
                        date: cacheModel!.date,
                        startLng: cacheModel!.startLng,
                        startLat: cacheModel!.startLat,
                        endLng: 0.0,
                        endLat: 0.0,
                        routes: cacheModel!.routes,
                        user: cacheModel!.user
                )
                startInspection()
                view.makeToast("欢迎回来,继续未完成巡检", duration: 2, position: .center)
            }
        }
    }

    func startInspection() {
        // 显示定位蓝点
        mapView.showsUserLocation = true
        mapView.userTrackingMode = .follow
        // 设置定位最小更新距离
        locationManager.distanceFilter = 5
        // 开启定位
        locationManager.delegate = self
        // 开启持续定位
        manager.requestWhenInUseAuthorization()
        manager.requestAlwaysAuthorization()
        locationManager.startUpdatingLocation()
        //
        defaults.set(false, for: statusKey)
    }

    func setUpMap() {
        mapView = MAMapView(frame: view.bounds)
        // 开启缩放手势
        mapView.isZoomEnabled = true
        // 地图的缩放级别的范围是[3-19]
        mapView.setZoomLevel(15, animated: true)
        // 禁用旋转手势
        mapView.isRotateEnabled = false
        // 禁用倾斜手势
        mapView.isRotateCameraEnabled = false
        mapView.isRotateEnabled = false
        // 不显示罗盘
        mapView.showsCompass = false
        mapView.delegate = self
        view.addSubview(mapView)
        // 放大
        expandButton.layer.cornerRadius = 5
        view.addSubview(expandButton)
        expandButton.snp.makeConstraints { (make) -> Void in
            make.size.equalTo(CGSize(width: BUTTON_WIDTH, height: BUTTON_HEIGHT))
            make.right.equalTo(-5)
            make.top.equalTo((SCREEN_HEIGHT - BUTTON_HEIGHT) / 3)
        }
        // 缩小
        minusButton.layer.cornerRadius = 5
        view.addSubview(minusButton)
        minusButton.snp.makeConstraints { (make) -> Void in
            make.size.equalTo(CGSize(width: BUTTON_WIDTH, height: BUTTON_HEIGHT))
            make.right.equalTo(-5)
            make.top.equalTo((SCREEN_HEIGHT - BUTTON_HEIGHT) / 3 + BUTTON_HEIGHT + 2)
        }
    }

    func addTopTagSubview() {
        topTagView.addSubview(deviceStatusLabel)
        deviceStatusLabel.snp.makeConstraints { (make) -> Void in
            make.size.equalTo(CGSize(width: topTagView.frame.width, height: 20))
            make.top.equalTo(5)
            make.centerX.equalToSuperview()
        }

        topTagView.addSubview(inspectNameLabel)
        inspectNameLabel.snp.makeConstraints { (make) -> Void in
            make.size.equalTo(CGSize(width: topTagView.frame.width / 2, height: 20))
            make.top.equalTo(30)
            make.left.equalTo(5)
        }

        inspectTimeLabel.textAlignment = .right
        topTagView.addSubview(inspectTimeLabel)
        inspectTimeLabel.snp.makeConstraints { (make) -> Void in
            make.size.equalTo(CGSize(width: topTagView.frame.width / 2, height: 20))
            make.top.equalTo(30)
            make.right.equalTo(-5)
        }
    }

    func addLeftSubview() {
        stopButton.layer.cornerRadius = 18
        view.addSubview(stopButton)
        stopButton.snp.makeConstraints { (make) -> Void in
            // 设置视图大小
            make.size.equalTo(CGSize(width: BUTTON_WIDTH, height: BUTTON_HEIGHT))
            make.left.equalTo(10)
            make.top.equalTo(topTagView.frame.height + 10)
        }

        bluetoothButton.layer.cornerRadius = 18
        view.addSubview(bluetoothButton)
        bluetoothButton.snp.makeConstraints { (make) -> Void in
            // 设置视图大小
            make.size.equalTo(CGSize(width: BUTTON_WIDTH, height: BUTTON_HEIGHT))
            make.left.equalTo(10)
            make.top.equalTo(topTagView.frame.height + 20 + BUTTON_HEIGHT)
        }

        refreshButton.layer.cornerRadius = 18
        view.addSubview(refreshButton)
        refreshButton.snp.makeConstraints { (make) -> Void in
            // 设置视图大小
            make.size.equalTo(CGSize(width: BUTTON_WIDTH, height: BUTTON_HEIGHT))
            make.left.equalTo(10)
            make.top.equalTo(topTagView.frame.height + 30 + BUTTON_HEIGHT * 2)
        }
    }

    func addBottomSubview() {
        LayerShadowHub.shared.setShadow(
                view: currentView,
                sColor: .mainBackground,
                offset: CGSize(width: 0, height: 0),
                alpha: 1.0,
                radius: CGFloat(5.0)
        )
        view.addSubview(currentView)
        currentView.snp.makeConstraints { (make) -> Void in
            make.size.equalTo(CGSize(width: DEVICE_DATA_VIEW_WIDTH, height: DEVICE_DATA_VIEW_HEIGHT))
            make.bottom.equalTo(-(SCREEN_HEIGHT * 0.1 + 20))
            make.left.equalTo(10)
        }

        LayerShadowHub.shared.setShadow(
                view: settingView,
                sColor: .mainBackground,
                offset: CGSize(width: 0, height: 0),
                alpha: 1.0,
                radius: CGFloat(5.0)
        )
        view.addSubview(settingView)
        settingView.snp.makeConstraints { (make) -> Void in
            make.size.equalTo(CGSize(width: DEVICE_DATA_VIEW_WIDTH, height: DEVICE_DATA_VIEW_HEIGHT))
            make.bottom.equalTo(-(SCREEN_HEIGHT * 0.1 + 20))
            make.centerX.equalToSuperview()
        }

        LayerShadowHub.shared.setShadow(
                view: maxView,
                sColor: .mainBackground,
                offset: CGSize(width: 0, height: 0),
                alpha: 1.0,
                radius: CGFloat(5.0)
        )
        view.addSubview(maxView)
        maxView.snp.makeConstraints { (make) -> Void in
            make.size.equalTo(CGSize(width: DEVICE_DATA_VIEW_WIDTH, height: DEVICE_DATA_VIEW_HEIGHT))
            make.bottom.equalTo(-(SCREEN_HEIGHT * 0.1 + 20))
            make.right.equalTo(-10)
        }

        // 添加按钮
        let buttonWidth = SCREEN_WIDTH * 0.8
        addEventButton.layer.cornerRadius = 8
        view.addSubview(addEventButton)
        addEventButton.snp.makeConstraints { (make) -> Void in
            make.top.equalTo(SCREEN_HEIGHT * 0.8)
            make.size.equalTo(CGSize(width: buttonWidth, height: BUTTON_HEIGHT))
            make.centerX.equalToSuperview()
        }
    }

    // 停止巡检
    @IBAction func stopInspectAction(_ sender: Any) {
        let msgAlertCtr = UIAlertController(title: "温馨提示", message: "确定结束巡检吗?", preferredStyle: .alert)
        let actionOK = UIAlertAction(title: "确定", style: .default) { [self] (_: UIAlertAction) -> Void in
            // 取最新位置作为结束位置经纬度
            let endLng = defaults.get(for: lngKey)!
            let endLat = defaults.get(for: latKey)!
            // 提交巡检
            let addInspectionURL = baseURL! + Constant.addInspection.rawValue
            let timeInterval: TimeInterval = Date().timeIntervalSince1970
            let endTime = timeFormatter.string(from: Date(timeIntervalSince1970: timeInterval))
            let param: [String: Any] = [
                "id": model.id,
                "name": model.name,
                "startTime": model.startTime,
                "endTime": endTime,
                "date": model.date,
                "startLng": model.startLng,
                "startLat": model.startLat,
                "endLng": endLng, "endLat": endLat,
                "routes": model.routes,
                "user": model.user,
            ]
            // 提交参数: ["startLat": 39.915913628472225, "id": "162925125712000", "date": "2021-08-18", "startTime": "2021-08-18 09:47:37", "endLng": 116.26874240451389, "startLng": 116.26874240451389, "routes": "[{\"lat\":39.915913628472225,\"lng\":116.26874240451389}]", "user": "王晓颖", "name": "测试iOS", "endTime": "2021-08-18 09:47:56", "endLat": 39.915913628472225]
            print("提交参数: \(param)")
            LoadingHub.shared.showLoading(text: "保存中,请稍后...")
            Alamofire.request(
                    addInspectionURL,
                    method: .post,
                    parameters: param,
                    headers: ["token": defaults.get(for: tokenKey)!]
            ).responseJSON(completionHandler: { response in
                switch response.result {
                case let .success(value):
                    let actionModel = ActionResultModel(respJson: JSON(value))
                    if actionModel.code == 200 {
                        let alertController = UIAlertController(title: "提示", message: "巡检记录保存成功", preferredStyle: .alert)
                        let okAction = UIAlertAction(title: "知道了", style: .default, handler: { _ in
                            defaults.set(true, for: statusKey)
                            // 提交成功后清除此次缓存的巡检
                            defaults.clear(inspectionCacheModelKey)
                            navigationController?.popViewController(animated: true)
                        })
                        alertController.addAction(okAction)
                        present(alertController, animated: true, completion: nil)
                    } else {
                        defaults.set(false, for: statusKey)
                        AlertHub.shared.showWaringAlert(controller: self, message: "服务器异常")
                    }
                case .failure:
                    defaults.set(false, for: statusKey)
                    AlertHub.shared.showWaringAlert(controller: self, message: "网络异常,提交失败")
                }
                LoadingHub.shared.hideLoading()
            })
        }
        let actionCancel = UIAlertAction(title: "取消", style: .cancel, handler: nil)
        // 设置取消按钮颜色为红色
        actionCancel.setValue(UIColor.red, forKey: "titleTextColor")
        msgAlertCtr.addAction(actionOK)
        msgAlertCtr.addAction(actionCancel)
        present(msgAlertCtr, animated: true, completion: nil)
    }

    // 搜索蓝牙
    @IBAction func searchBluetoothAction(_ sender: Any) {
        if isBluetoothAvailable() {
            if isConnected {
                centralManager.cancelPeripheralConnection(cbPeripheral)
                isConnected = false
            } else {
                LoadingHub.shared.showLoading(text: "设备搜索中...")
                centralManager.scanForPeripherals(withServices: nil, options: nil)
                DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: { [self] in
                    // 列表显示扫描到的设备
                    showTableView()
                })
            }
        } else {
            AlertHub.shared.showWaringAlert(controller: self, message: "蓝牙不可用,请检查")
        }
    }

    func showTableView() {
        centralManager.stopScan()
        LoadingHub.shared.hideLoading()

        if scanDevices.count == 0 {
            AlertHub.shared.showWaringAlert(controller: self, message: "无可用设备,请确认设备是否已开启")
        } else {
            let actionSheetController = UIAlertController()
            for device in scanDevices {
                actionSheetController.addAction(UIAlertAction(title: device.name, style: .default, handler: { [self] alertAction in
                    // 连接点击的设备
                    LoadingHub.shared.showLoading(text: "设备连接中...")
                    scanDevices.forEach { it in
                        if alertAction.title == it.name {
                            centralManager.connect(it, options: nil)
                        }
                    }
                }))
            }
            actionSheetController.addAction(UIAlertAction(title: "取消", style: .cancel))
            present(actionSheetController, animated: true, completion: nil)
        }
    }

    // 重新发送指令
    @IBAction func refreshCmdAction(_ sender: Any) {
        if isBluetoothAvailable() {
            writeToPeripheral(OPEN_TRANSFER_COMMAND)
        } else {
            AlertHub.shared.showWaringAlert(controller: self, message: "请先连接设备")
        }
    }

    @IBAction func addEventAction(_ sender: Any) {
        let lng = defaults.get(for: lngKey)!
        let lat = defaults.get(for: latKey)!
        print("新建事件位置信息: [\(lng), \(lat)]")

        let newEventViewController = NewEventViewController(nibName: "NewEventViewController", bundle: nil)
        // 委托代理
        valueDelegate = newEventViewController
        let selectController = UIAlertController(title: "选择事件类型", message: nil, preferredStyle: .alert)

        let inspectButton = UIAlertAction(title: "报警事件", style: .default, handler: { [self] _ in
            // 实现代理的方法,传值
            valueDelegate.transfer(
                    controller: self,
                    dic: ["isWarning": true,
                          "inspectionId": model.id,
                          "inspectionName": model.name,
                          "longitude": lng,
                          "latitude": lat,
                    ]
            )
            navigationController?.pushViewController(newEventViewController, animated: true)
        })
        let eventLogButton = UIAlertAction(title: "自定义事件", style: .default, handler: { [self] _ in
            // 实现代理的方法,传值
            valueDelegate.transfer(
                    controller: self,
                    dic: ["isWarning": false,
                          "inspectionId": model.id,
                          "inspectionName": model.name,
                          "longitude": lng,
                          "latitude": lat,
                    ]
            )
            navigationController?.pushViewController(newEventViewController, animated: true)
        })
        selectController.addAction(inspectButton)
        selectController.addAction(eventLogButton)
        present(selectController, animated: true, completion: nil)
    }

    @IBAction func expandMap(_ sender: Any) {
        var zoomLevel = mapView.zoomLevel
        zoomLevel += 1
        mapView.setZoomLevel(zoomLevel, animated: true)
    }

    @IBAction func minusMap(_ sender: Any) {
        var zoomLevel = mapView.zoomLevel
        zoomLevel -= 1
        mapView.setZoomLevel(zoomLevel, animated: true)
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)
        locationManager.stopUpdatingLocation()
//        if cbPeripheral == nil {
//            return
//        }
//        centralManager.cancelPeripheralConnection(cbPeripheral)
//        isConnected = false
    }
}

extension MapViewController: AMapLocationManagerDelegate {
    // 持续定位位置信息
    func amapLocationManager(_ manager: AMapLocationManager!, didUpdate location: CLLocation!) {
        print("位置信息: [\(location.coordinate.latitude),\(location.coordinate.longitude)]")
        // 保存最新的一次位置
        defaults.set(location.coordinate.longitude, for: lngKey)
        defaults.set(location.coordinate.latitude, for: latKey)
        // 设置起始经纬度
        if model.startLng == 0.0 || model.startLat == 0.0 {
            model.startLng = location.coordinate.longitude
            model.startLat = location.coordinate.latitude
        }
        // 包装routes
        let route = NewRouteModel()
        route.lng = location.coordinate.longitude
        route.lat = location.coordinate.latitude
        routeArray.append(route)

        let routesJson = routeArray.toJSONString()!
        // iOS位置JSON: [{"lng":116.26879475911458,"lat":39.915928276909725}]
        // Android位置: [{"lat":39.917433,"lng":116.269525},{"lat":39.917433,"lng":116.269525}]
        print("位置JSON: \(routesJson)")
        model.routes = routesJson
        // 根据定位位置的变化不停的覆盖保存巡检记录
        let cacheModel = InspectionCacheModel(
                id: model.id,
                name: model.name,
                startTime: model.startTime,
                endTime: model.endTime,
                date: model.date,
                startLng: model.startLng,
                startLat: model.startLat,
                endLng: model.endLng,
                endLat: model.endLat,
                routes: model.routes,
                user: model.user
        )
        defaults.set(cacheModel, for: inspectionCacheModelKey)
    }
}

extension MapViewController: CBCentralManagerDelegate {
    func isBluetoothAvailable() -> Bool {
        if #available(iOS 10.0, *) {
            return centralManager.state == CBManagerState.poweredOn
        } else {
            return centralManager.state == .poweredOn
        }
    }

    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case .poweredOn:
            print("可用")
        case .resetting:
            print("重置中")
        case .unsupported:
            print("不支持")
        case .unauthorized:
            print("未验证")
        case .poweredOff:
            print("未启动")
        case .unknown:
            print("未知的")
        @unknown default:
            print("未知的")
        }
    }

    // 发现设备
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {
        deviceName = peripheral.name
        if deviceName != nil {
//            if deviceName.isNumber() {
//                // 如果不包含 就加入
//                if !scanDevices.contains(peripheral) {
//                    scanDevices.append(peripheral)
//                }
//            }
            // 如果不包含 就加入
            if !scanDevices.contains(peripheral) {
                scanDevices.append(peripheral)
            }
        }
    }

    // 设备已连接
    func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        LoadingHub.shared.hideLoading()
        print("设备已连接,开始搜索设备特性服务")
        cbPeripheral = peripheral
        cbPeripheral.delegate = self
        cbPeripheral.discoverServices(nil)
        isConnected = true
    }

    // 设备连接失败
    func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) {
        LoadingHub.shared.hideLoading()
        AlertHub.shared.showWaringAlert(controller: self, message: "设备连接失败,请检查")
    }

    // 设备断开连接
    func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        print("设备断开连接")
        deviceStatusLabel.text = "设备编号:未连接"
        currentValueLabel.text = "--"
        settingValueLabel.text = "--"
        maxValueLabel.text = "--"
    }
}

extension MapViewController: CBPeripheralDelegate {
    // 发送指令到设备
    func writeToPeripheral(_ bytes: [UInt8]) {
        if writeCharacteristic != nil {
            cbPeripheral.writeValue(
                    Data(bytes: bytes, count: bytes.count),
                    for: writeCharacteristic, type: .withResponse
            )
        }
    }

    func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        for service in peripheral.services! {
            print("发现服务: \(service.uuid.uuidString)")
            // 发现服务: 0003CDD0-0000-1000-8000-00805F9B0131
            if Constant.SERVICE_UUID.rawValue == service.uuid.uuidString {
                peripheral.discoverCharacteristics(nil, for: service)
            }
        }
    }

    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        for character in service.characteristics! {
            print("发现特征值: \(character.uuid.uuidString)")

            if Constant.READ_CHARACTERISTIC_UUID.rawValue == character.uuid.uuidString {
                // 发现特征值: 0003CDD1-0000-1000-8000-00805F9B0131
                cbPeripheral.readValue(for: character)
            }

            if Constant.WRITE_CHARACTERISTIC_UUID.rawValue == character.uuid.uuidString {
                // 发现特征值: 0003CDD2-0000-1000-8000-00805F9B0131
                writeCharacteristic = character
            }
            cbPeripheral.setNotifyValue(true, for: character)
        }
        // 查询设备编号
        writeToPeripheral(ASK_DEV_CODE_COMMAND)
    }

    func peripheral(_ peripheral: CBPeripheral, didWriteValueFor characteristic: CBCharacteristic, error: Error?) {
        if error != nil {
            print("发送数据失败! error信息: \(String(describing: error))")
        }
    }

    // 特征的订阅状体发生变化
    func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
        guard error == nil else {
            return
        }
    }

    // 所有的,不管是 read , notify 的特征的值都是在这里读取
    func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) {
        if error != nil {
            return
        }
        if Constant.READ_CHARACTERISTIC_UUID.rawValue == characteristic.uuid.uuidString {
            let data = characteristic.value!
//            print("蓝牙探测数据: \(data)")
//            print("探测数据长度: \(data.count)")
            if data.count == 28 {
                // 51, 51, 50, 48, 50, 49, 48, 49, 48, 48, 48, 51, 13, 10, 170, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0, 0, 13, 10
                // 只解析前14位,后14位是测量值
                var deviceCodeData = Data()
                for i in 0...13 {
                    deviceCodeData.append(data[i])
                }
                deviceStatusLabel.text = "设备编号: \(NSString(data: deviceCodeData, encoding: String.Encoding.utf8.rawValue)! as String)"
                // 获取到编号之后再开启数据发送命令
                writeToPeripheral(OPEN_TRANSFER_COMMAND)
            } else if data.count == 14 {
                /**
                 * 170,0,0,0,100,1,0,100,0,0,0,100,13,10
                 *
                 * 170是数据标头AA
                 * 13,10是数据结束位
                 * */
                // 浓度:4字节   0-99999

                let p1 = UInt(data[1]) * 256 * 3
                let p2 = UInt(data[2]) * 256 * 2
                let p3 = UInt(data[3]) * 256 * 1
                let potencyValue = p1 + p2 + p3 + UInt(data[4])
                currentValueLabel.text = potencyValue.description
                // 报警值:2字节    0-65535
                let alarmValue = UInt(data[6]) * 256 + UInt(data[7])
                settingValueLabel.text = alarmValue.description
                // 5s内最大值:    4字节   0-99999
                let m1 = UInt(data[8]) * 256 * 3
                let m2 = UInt(data[9]) * 256 * 2
                let m3 = UInt(data[10]) * 256 * 1
                let maxPotencyValue = m1 + m2 + m3 + UInt(data[11])
                maxValueLabel.text = maxPotencyValue.description
                // 判断是否需要报警
                let isOpenWarning = defaults.get(for: openWarningKey) ?? false
                if isOpenWarning {
                    if maxPotencyValue >= alarmValue {
                        // 当前值大于设置值,需要报警
//                        OtherUtils.playSound(mapActivity, R.raw.alarm)
                        AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
                        let isAutoRecord = defaults.get(for: autoRecordKey) ?? false
                        if isAutoRecord {
                            // 如果连续超过10个报警,自动生成报警事件
                            alarmCount += 1
                            if alarmCount >= 10 {
                                generateAlarmTask(maxValue: maxValueLabel.text!)
                            }
                        }
                    } else {
                        // 当测量值小于设置值,报警还未结束,需要停止响铃
                        print("测量值小于设置值,停止响铃")
                    }
                }
            } else {
                print("错误数据")
            }
        }
    }

    // 生成报警事件
    func generateAlarmTask(maxValue: String) {
        if isGeneratingTask {
            print("正在生成报警事件")
            return
        }
        isGeneratingTask = true
        // 取最新位置作为报警位置经纬度
        let longitude = defaults.get(for: lngKey)!
        let latitude = defaults.get(for: latKey)!
        // 提交事件
        let addEventURL = baseURL! + Constant.addEvent.rawValue
        let param: [String: Any] = [
            "id": "t".id(),
            "inspectionId": model.id,
            "name": model.name,
            "createTime": model.startTime,
            "type": "报警事件",
            "lng": longitude,
            "lat": latitude,
            "data": Double(maxValue)!,
            "images": "",
            "description": "自动报警记录",
            "user": model.user,
        ]
        print("提交参数: \(param)")
        Alamofire.request(
                addEventURL,
                method: .post,
                parameters: param,
                headers: ["token": defaults.get(for: tokenKey)!]
        ).responseJSON(completionHandler: { [self] response in
            switch response.result {
            case let .success(value):
                let actionModel = ActionResultModel(respJson: JSON(value))
                if actionModel.code == 200 {
                    view.makeToast("保存成功", duration: 2, position: .center)
                    isGeneratingTask = false
                    alarmCount = 0
                } else {
                    view.makeToast("保存失败,服务器异常", duration: 2, position: .center)
                }
            case .failure:
                view.makeToast("保存失败,网络异常", duration: 2, position: .center)
            }
        })
    }
}

extension MapViewController: UITextFieldDelegate {
}