import { Injectable } from '@angular/core' ; import { Platform } from '@ionic/angular' ; import { Zeroconf } from '@ionic-native/zeroconf/ngx' ; import { BLE } from '@ionic-native/ble/ngx' ; import { transcoding , str2ab , Uint8Array2hex , isJson , isNumber , mac2name , isNewerVersion , deviceName2id } from '../functions/func' ; import { DataService } from './data.service' ; import { HttpClient } from '@angular/common/http' ; import { API } from 'src/app/configs/api.config' ; import { BlinkerBroker } from '../model/broker.model' ; import { PermissionService } from './permission.service' ; import { Subscription , Subject } from 'rxjs' ; import { DebugService } from 'src/app/debug/debug.service' ; import { BlinkerDevice } from '../model/device.model' ; import { NativeService } from './native.service' ; import { NoticeService } from './notice.service' ; import { ToastService } from './toast.service' ; declare var mqtt ; @ Injectable ( { providedIn : 'root' } ) export class DeviceService { get uuid ( ) { return this . dataService . auth . uuid ; } get token ( ) { return this . dataService . auth . token ; } get brokerDataDict ( ) { return this . dataService . brokers . dict ; } get brokerDataList ( ) { if ( typeof this . dataService . brokers != 'undefined' ) return this . dataService . brokers . list ; return [ ] ; } get deviceDataDict ( ) { return this . dataService . device . dict ; } get deviceDataList ( ) { return this . dataService . device . list ; } oneDeviceName : string ; _device ; get device ( ) { if ( typeof this . deviceDataDict [ this . oneDeviceName ] == 'undefined' ) return 'undefined' ; else return this . deviceDataDict [ this . oneDeviceName ] ; } lanDeviceList = { } ; bleDeviceList = { } ; mqttCloseCnt = 0 ; wsClient ; timer = [ ] ; userUrl : string ; newDeviceSubject = new Subject ; constructor ( private http , private zeroconf , private plt , private ble , private dataService , private permissionService , private debugService , private nativeService , private noticeService , private toastService ) { } init ( ) { this . dataService . initCompleted . subscribe ( loaded => { if ( loaded ) { console . log ( '启动加载' ) ; this . connectMqttBrokers ( ) ; this . searchLocalDevice ( ) ; } } ) ; this . dataService . authDataExpire . subscribe ( state => { if ( state ) { this . disconnectMqttBrokers ( ) ; } } ) ; } connectMqttBrokers ( ) { for ( let verder of this . brokerDataList ) { if ( typeof this . brokerDataDict [ verder ] . client == 'undefined' ) { console . log ( "第一次创建" ) ; this . connectMqttBroker ( this . brokerDataDict [ verder ] ) ; } else { console . log ( "第二次连接" ) ; this . reconnectMqttBroker ( this . brokerDataDict [ verder ] ) ; } } } closeCounter = 0 ; closeTimer ; reconnectTimer ; connectMqttBroker ( broker ) { try { console . log ( 'connectMqttBroker:' + broker . vender ) ; let mqttClient = mqtt . connect ( broker . host , broker . options ) ; broker . client = mqttClient ; mqttClient . on ( 'connect' , ( ) => { console . log ( 'mqtt connect:' + broker . vender ) ; broker . connected . next ( true ) ; } ) ; mqttClient . on ( 'message' , ( topic , message , packet ) => { console . log ( 'mqtt receive:\n' + message ) ; let data = JSON . parse ( message ) ; if ( data . fromDevice != data . toDevice ) this . processMessage ( data ) ; } ) ; mqttClient . on ( 'reconnect' , ( ) => { console . log ( 'mqtt reconnect:' + broker . vender ) ; } ) ; mqttClient . on ( 'error' , err => { console . error ( 'mqtt error:' + err ) ; } ) ; mqttClient . on ( 'close' , ( ) => { console . log ( 'mqtt close' ) ; this . closeCounter ++ ; clearTimeout ( this . closeTimer ) ; this . closeTimer = setTimeout ( ( ) => { this . closeCounter = 0 ; } , 3000 ) ; if ( this . closeCounter > 5 ) { broker . connected . next ( false ) ; this . dataService . authCheck . next ( true ) ; } } ) ; mqttClient . on ( 'offline' , ( ) => { console . log ( 'mqtt offline' ) ; } ) ; mqttClient . subscribe ( broker . topic . receive , { qos : 0 } ) ; } catch ( error ) { console . log ( error ) ; } } reconnectMqttBroker ( broker ) { broker . client . reconnect ( ) ; } async disconnectMqttBrokers ( ) { if ( typeof this . brokerDataList != 'undefined' ) for ( const verder of this . brokerDataList ) await this . disconnectMqttBroker ( this . brokerDataDict [ verder ] ) ; } disconnectMqttBroker ( broker ) { return new Promise < boolean > ( ( resolve , reject ) => { broker . client . end ( false , { } , ( ) => { broker . connected . next ( false ) ; resolve ( false ) ; } ) ; } ) ; } pubMessage ( device , message ) { if ( this . islocalDevice ( device ) ) { if ( this . lanDeviceList [ device . deviceName ] . state == 'disconnected' ) { this . connectLocalDevice ( device ) ; } else { if ( typeof message == 'object' ) message = JSON . stringify ( message ) ; this . lanDeviceList [ device . deviceName ] . client . send ( message ) ; this . send2debug ( device , 'send' , message ) ; return ; } } let broker = this . brokerDataDict [ device . config . broker ] ; if ( typeof broker == 'undefined' ) return ; let mqttJson = JSON . parse ( JSON . stringify ( broker . dataTemplate ) ) ; mqttJson . toDevice = device . deviceName ; mqttJson . deviceType = ( ( device . deviceType == 'DiyArduino' || device . deviceType == 'DiyLinux' ) ? device . deviceType : 'ProDevice' ) ; try { mqttJson . data = JSON . parse ( message ) ; } catch ( error ) { mqttJson . data = message ; } if ( JSON . stringify ( mqttJson . data ) != '{"get":"state"}' ) console . log ( `mqtt send:\n${ JSON . stringify ( mqttJson ) }` ) ; broker . client . publish ( broker . topic . send , JSON . stringify ( mqttJson ) , { qos : 0 } ) ; this . send2debug ( device , 'send' , message ) ; } islocalDevice ( device ) { if ( typeof this . lanDeviceList [ device . deviceName ] != 'undefined' ) { return true ; } if ( typeof this . bleDeviceList [ deviceName2id ( device . deviceName ) ] != 'undefined' ) { return true ; } return false ; } connectLocalDevice ( device ) { return new Promise < boolean > ( ( resolve , reject ) => { try { this . lanDeviceList [ device . deviceName ] . client = new WebSocket ( "ws://" + this . lanDeviceList [ device . deviceName ] . ip + ":81" ) ; } catch ( error ) { console . log ( error ) ; resolve ( false ) ; } this . lanDeviceList [ device . deviceName ] . client . onmessage = ( event ) => { let data = event . data ; if ( data . indexOf ( `{"state":"connected"}` ) > - 1 ) { this . lanDeviceList [ device . deviceName ] . state = 'connected' ; data = `{"state":"online"}` ; } let message = { } ; message [ "fromDevice" ] = device . deviceName ; try { message [ "data" ] = JSON . parse ( data ) ; } catch ( e ) { message [ "data" ] = data ; } this . processMessage ( message ) ; } ; this . lanDeviceList [ device . deviceName ] . client . onopen = ( event ) => { } ; this . lanDeviceList [ device . deviceName ] . client . onerror = ( event ) => { this . removeLocalDevice ( device ) ; resolve ( false ) ; } ; this . lanDeviceList [ device . deviceName ] . client . onclose = ( event ) => { this . removeLocalDevice ( device ) ; resolve ( false ) ; } ; } ) ; } removeLocalDevice ( device ) { delete this . lanDeviceList [ device . deviceName ] ; this . queryDevice ( device ) ; } processMessage ( message ) { if ( JSON . stringify ( message . data ) == '{"message":"Registration successful"}' ) { this . newDeviceSubject . next ( deviceName2id ( message . fromDevice ) ) ; return ; } this . message2Device ( this . deviceDataDict [ deviceName2id ( message . fromDevice ) ] , message . data ) ; } message2Device ( device , data ) { if ( device . data . state == 'disconnected' || device . data . state == 'offline' ) { if ( device . config . mode == 'mqtt' ) { device [ 'data' ] [ 'state' ] = 'online' ; } else { device [ 'data' ] [ 'state' ] = 'connected' ; } } if ( typeof ( data ) == 'string' || typeof ( data ) == "number" ) { this . send2debug ( device , 'unknown' , data . toString ( ) ) ; return ; } for ( let key in data ) { if ( key == "config" || key == "deviceName" || key == "deviceType" ) break ; if ( key == "notice" ) { this . toastService . show ( { device : device , message : data [ key ] } ) ; } device . data [ key ] = data [ key ] ; device . subject . next ( { key : 'loaded' } ) ; if ( key == "vibrate" ) this . nativeService . vibrate ( data [ key ] ) ; } this . send2debug ( device , 'receive' , JSON . stringify ( data ) ) ; } searchLocalDevice ( ) { if ( ! this . plt . is ( 'cordova' ) ) return ; this . scanMdnsDevice ( ) ; this . scanBleDevice ( ) ; } protocol = '_blinker._tcp.' ; async scanMdnsDevice ( ) { for ( let deviceName in this . lanDeviceList ) { let deviceWsClient = this . lanDeviceList [ deviceName ] . client ; try { if ( typeof deviceWsClient . close == 'function' ) deviceWsClient . close ( ) ; } catch ( error ) { console . log ( error ) ; } } this . lanDeviceList = { } ; if ( this . plt . is ( 'android' ) ) { this . zeroconf . watchAddressFamily = 'ipv4' ; await this . zeroconf . reInit ( ) ; } this . zeroconf . watch ( this . protocol , 'local.' ) . subscribe ( result => { if ( typeof result . service . txtRecord . mac == 'string' ) if ( ( ! ( result . service . name in this . lanDeviceList ) ) && ( result . service . ipv4Addresses . length > 0 ) ) { let device = { client : new Object , state : 'disconnected' , ip : result . service . ipv4Addresses [ 0 ] , } ; this . lanDeviceList [ result . service . name ] = device ; this . lanDeviceList [ result . service . txtRecord . mac ] = device ; } } ) ; setTimeout ( ( ) => { console . log ( "mdns devices:" ) ; console . log ( this . lanDeviceList ) ; this . zeroconf . close ( ) ; } , 30000 ) ; } closeScanMdnsDevice ( ) { this . zeroconf . close ( ) ; } async scanBleDevice ( ) { if ( ! this . plt . is ( 'cordova' ) ) return ; if ( ! this . permissionService . CheckBleAvailability ( { showNotice : false } ) ) return ; this . bleDeviceList = { } ; this . ble . scan ( [ ] , 5 ) . subscribe ( result => { if ( this . plt . is ( 'android' ) ) { let UUID = Uint8Array2hex ( result . advertising ) . toUpperCase ( ) ; if ( ( UUID . indexOf ( "02E0FF" ) != - 1 ) || ( UUID . indexOf ( "02F0FF" ) != - 1 ) || ( UUID . indexOf ( "03E0FF" ) != - 1 ) || ( UUID . indexOf ( "03F0FF" ) != - 1 ) ) this . bleDeviceList [ mac2name ( result ) ] = "ble" ; } else if ( typeof ( result . advertising . kCBAdvDataServiceUUIDs ) != 'undefined' ) { let UUIDs = result . advertising . kCBAdvDataServiceUUIDs ; for ( let i = 0 ; i < UUIDs . length ; i ++ ) { if ( ( UUIDs [ i ] . indexOf ( "FFE0" ) != - 1 ) || ( ( UUIDs [ i ] . indexOf ( "FFF0" ) != - 1 ) ) ) { console . log ( UUIDs [ i ] ) ; if ( typeof ( result . advertising . kCBAdvDataManufacturerData ) != 'undefined' ) { let data = new Uint8Array ( result . advertising . kCBAdvDataManufacturerData ) ; if ( data . length <= 12 ) { this . bleDeviceList [ mac2name ( result ) ] = "ble" ; } } } } } } ) ; setTimeout ( ( ) => { console . log ( "ble devices:" ) ; console . log ( this . bleDeviceList ) ; this . ble . stopScan ( ) . then ( ( ) => { console . log ( 'ble scan stopped' ) ; } ) ; } , 3900 ) ; } queryDevice ( device ) { if ( device . config . mode == "mqtt" && this . brokerDataList . indexOf ( device . config . broker ) > - 1 ) { let connected = this . brokerDataDict [ device . config . broker ] . connected . subscribe ( state => { if ( state ) { device . data [ 'oldState' ] = device . data . state ; device . data . state = 'waiting' ; this . pubMessage ( device , `{"get":"state"}` ) ; setTimeout ( ( ) => { if ( device . data [ 'oldState' ] == 'online' ) if ( device . data . state != "online" ) this . pubMessage ( device , `{"get":"state"}` ) ; } , 3000 ) ; setTimeout ( ( ) => { if ( device . data . state != "online" ) device . data . state = "offline" ; } , 6000 ) ; setTimeout ( ( ) => { connected . unsubscribe ( ) ; } , 100 ) ; } } ) ; } else if ( device . data . state == "connected" ) this . sendData ( device , `{"get":"state"}` ) ; } queryDevices ( ) { try { for ( let deviceName in this . deviceDataDict ) { this . queryDevice ( this . deviceDataDict [ deviceName ] ) ; } } catch ( error ) { console . warn ( error ) ; } } connectDeviceTimer ; connectDevice ( device , mode = "show" ) { return new Promise < boolean > ( async ( resolve , reject ) => { if ( ! this . plt . is ( 'cordova' ) ) return resolve ( false ) ; this . connectDeviceTimer = setTimeout ( ( ) => { if ( mode == "show" ) this . noticeService . showToast ( 'timeoutConnect' ) ; this . disconnectDevice ( device ) ; return resolve ( false ) ; } , 6000 ) ; if ( device . data . state != "disconnected" ) device . data . state = "disconnected" ; if ( device . config . mode == "ble" ) { if ( ! this . permissionService . CheckBleAvailability ( ) ) return resolve ( false ) ; if ( mode == "show" ) await this . noticeService . showLoading ( 'connect' ) ; let result = await this . connectBleDevice ( device ) ; return resolve ( result ) ; } } ) ; } disconnectDevice ( device ) { if ( ! this . plt . is ( 'cordova' ) ) return ; window . clearTimeout ( this . connectDeviceTimer ) ; this . noticeService . hideLoading ( ) ; if ( device . config . mode == "ble" ) { this . disconnectBleDevice ( device ) ; } } sendTimerList = { } ; fullMqttDateList = { } ; sendData ( device , data ) { if ( device . config . mode == "mqtt" ) { if ( isJson ( data ) ) { if ( typeof this . fullMqttDateList [ device . deviceName ] == 'undefined' ) this . fullMqttDateList [ device . deviceName ] = '' ; let ob = this . fullMqttDateList [ device . deviceName ] == '' ? { } : JSON . parse ( this . fullMqttDateList [ device . deviceName ] ) ; let ob2 = JSON . parse ( data ) ; this . fullMqttDateList [ device . deviceName ] = JSON . stringify ( Object . assign ( ob , ob2 ) ) ; if ( typeof this . sendTimerList [ device . deviceName ] != 'undefined' ) window . clearTimeout ( this . sendTimerList [ device . deviceName ] ) ; let deviceInLocal = false ; if ( this . islocalDevice ( device ) ) { if ( this . lanDeviceList [ device . deviceName ] . state == 'connected' ) deviceInLocal = true ; } this . sendTimerList [ device . deviceName ] = setTimeout ( ( ) => { this . pubMessage ( device , this . fullMqttDateList [ device . deviceName ] ) ; this . fullMqttDateList [ device . deviceName ] = '' ; delete this . sendTimerList [ device . deviceName ] ; } , deviceInLocal ? 100 : 300 ) ; } else { this . pubMessage ( device , data ) ; } } if ( ! this . plt . is ( 'cordova' ) ) return ; if ( typeof data == 'string' ) { if ( data [ data . length - 1 ] != '\n' ) data = data + '\n' ; } if ( device . data . state != 'disconnected' ) { if ( device . config . mode == "ble" ) { this . send2ble ( device , data ) ; } } } lastbuf = new Uint8Array ( 10240 ) ; lastbufcnt = 0 ; bleUUID = null ; connectBleDevice ( device ) { return new Promise < boolean > ( ( resolve , reject ) => { if ( this . bleUUID != null ) this . ble . disconnect ( this . bleUUID ) ; console . log ( "scanBle" ) ; this . ble . startScan ( [ ] ) . subscribe ( result => { console . log ( result ) ; if ( this . plt . is ( 'android' ) || ( typeof ( result . advertising . kCBAdvDataManufacturerData ) != 'undefined' ) ) { if ( deviceName2id ( device . deviceName ) == mac2name ( result ) ) { this . ble . stopScan ( ) ; console . log ( 'connect ble device:' + result . id ) ; window . clearTimeout ( this . connectDeviceTimer ) ; this . ble . connect ( result . id ) . subscribe ( async ( data ) => { this . bleUUID = result . id ; console . log ( data ) ; await this . noticeService . hideLoading ( ) ; if ( device . data . state != "connected" ) device . data . state = "connected" ; this . lastbuf . fill ( 0 ) ; this . lastbufcnt = 0 ; this . ble . startNotification ( result . id , 'FFE0' , 'FFE1' ) . subscribe ( buffer => { let buftmp = new Uint8Array ( buffer [ 0 ] ) ; this . lastbuf . set ( buftmp , this . lastbufcnt ) ; this . lastbufcnt += buftmp . length ; while ( this . lastbuf . indexOf ( 10 ) > - 1 ) { let index = this . lastbuf . indexOf ( 10 ) ; let fullMessage = transcoding ( this . lastbuf ) ; console . log ( fullMessage ) ; let message = { } ; message [ "fromDevice" ] = device . deviceName ; if ( fullMessage . indexOf ( '{' ) > - 1 ) { try { message [ "data" ] = JSON . parse ( fullMessage ) ; } catch ( e ) { message [ "data" ] = fullMessage ; } } else message [ "data" ] = fullMessage ; this . processMessage ( message ) ; let slicetmp = this . lastbuf . slice ( index + 1 , this . lastbufcnt ) ; this . lastbuf . fill ( 0 ) ; this . lastbuf . set ( slicetmp ) ; this . lastbufcnt -= index + 1 ; } } ) ; return resolve ( true ) ; } , error => { this . bleUUID = null ; if ( device . data . state != "disconnected" ) device . data . state = "disconnected" ; console . log ( error ) ; return resolve ( false ) ; } ) ; } } } , error => { console . log ( error ) ; if ( error == 'Location Services are disabled' ) { this . noticeService . showAlert ( 'bleNeedLocation' ) ; } } ) ; } ) ; } async disconnectBleDevice ( device ) { this . ble . stopScan ( ) ; this . ble . stopStateNotifications ( ) ; this . ble . disconnect ( this . bleUUID ) ; if ( device . data . state != "disconnected" ) device . data . state = "disconnected" ; this . bleUUID = null ; this . lastbuf . fill ( 0 ) ; } lastSendTime = 0 ; send2ble ( device , message ) { console . log ( 'send2ble' ) ; if ( this . plt . is ( 'android' ) ) { console . log ( message ) ; let t = this . lastSendTime - new Date ( ) . getTime ( ) ; this . lastSendTime = new Date ( ) . getTime ( ) ; if ( t < 0 ) t = 0 ; let i = 0 ; for ( i = 0 ; i < message . length ; i += 20 ) { let tmp = message . slice ( i , i + 20 ) ; let delay = i + t ; setTimeout ( ( ) => { this . ble . writeWithoutResponse ( this . bleUUID , 'ffe0' , 'ffe1' , str2ab ( tmp ) ) ; } , delay ) ; } this . lastSendTime = this . lastSendTime + i + t ; } else { this . ble . writeWithoutResponse ( this . bleUUID , 'ffe0' , 'ffe1' , str2ab ( message ) ) ; } this . send2debug ( device , 'send' , message ) ; } async connectNetDevice ( device ) { return new Promise < boolean > ( ( resolve , reject ) => { if ( this . plt . is ( 'android' ) ) { this . zeroconf . watchAddressFamily = 'ipv4' ; } this . zeroconf . watch ( '_' + device . deviceType + '._tcp.' , 'local.' ) . subscribe ( result => { if ( result . action == "resolved" ) { if ( result . service . name == deviceName2id ( device . deviceName ) && result . service . ipv4Addresses . length > 0 ) { window . clearTimeout ( this . connectDeviceTimer ) ; this . zeroconf . close ( ) ; this . noticeService . hideLoading ( ) ; this . disconnectNetDevice ( device ) ; this . wsClient = new WebSocket ( "ws://" + result . service . ipv4Addresses [ 0 ] + ":81" ) ; this . wsClient . onmessage = ( event ) => { let message = { } ; message [ "fromDevice" ] = device . deviceName ; try { message [ "data" ] = JSON . parse ( event . data ) ; } catch ( e ) { message [ "data" ] = event . data ; } this . processMessage ( message ) ; } ; this . wsClient . onopen = ( event ) => { console . log ( "ws open" ) ; console . log ( event ) ; if ( device . data . state != "connected" ) device . data . state = "connected" ; return resolve ( true ) ; } ; this . wsClient . onerror = ( event ) => { console . log ( "ws error" ) ; console . log ( event ) ; } ; this . wsClient . onclose = ( event ) => { console . log ( "ws close" ) ; console . log ( event ) ; if ( device . data . state != "disconnected" ) device . data . state = "disconnected" ; } ; } } } ) ; } ) ; } disconnectNetDevice ( device ) { if ( typeof ( this . wsClient ) != "undefined" ) this . wsClient . close ( ) ; this . zeroconf . close ( ) ; } send2net ( device , message ) { this . wsClient . send ( message ) ; this . send2debug ( device , 'send' , message ) ; } async isWifiAvailable ( ) { if ( await this . permissionService . CheckWifiAvailability ( ) ) { return true ; } else { this . noticeService . showAlert ( 'openWifi' ) ; return false ; } } send2debug ( device , type , data ) { if ( this . debugService . enable ) this . debugService . update ( { deviceName : device . deviceName , type : type , data : data } ) ; } saveDeviceConfig ( device , deviceConfig ) { return this . http . post ( API . DEVICE . SAVE_CONFIG , { "uuid" : this . uuid , 'token' : this . token , "deviceName" : device . deviceName , "deviceConfig" : JSON . stringify ( deviceConfig ) } ) . toPromise ( ) . then ( response => { console . log ( response ) ; let data = JSON . parse ( JSON . stringify ( response ) ) ; if ( data . message == 1000 ) { return true ; } else { return false ; } } ) . catch ( this . handleError ) ; } loadDeviceConfig ( device ) { return this . http . get ( API . DEVICE . LOAD_CONFIG , { params : { uuid : this . uuid , token : this . token , deviceName : device . deviceName } } ) . toPromise ( ) . then ( response => { console . log ( response ) ; let data = JSON . parse ( JSON . stringify ( response ) ) ; if ( data . message == 1000 ) { return data . detail ; } } ) . catch ( this . handleError ) ; } loadDeviceLayouter ( device ) { this . loadDeviceConfig ( device ) . then ( config => { device . config . layouter = config . layouter ; } ) ; } checkDeviceVersion ( device ) { return new Promise < boolean > ( ( resolve , reject ) => { if ( typeof device . data . version == "undefined" ) { this . pubMessage ( device , `{"get":"version"}` ) ; setTimeout ( ( ) => { if ( typeof device . data . version != 'undefined' ) { this . checkDeviceNewVersion ( device ) ; return device . data . version ; } else { return '0.0.0' ; } } , 2500 ) ; } else { setTimeout ( ( ) => { this . checkDeviceNewVersion ( device ) ; return device . data . version ; } ) ; } } ) ; } checkDeviceNewVersion ( device ) { if ( typeof device . data . version == 'undefined' ) { console . log ( 'no found version info' ) ; return new Promise ( ( resolve , reject ) => { resolve ( false ) ; } ) ; } if ( device . data . version != '0.0.0' && typeof device . data . newVersion == 'undefined' ) return this . http . get ( API . DEVICE . NEW_VERSION , { params : { deviceName : device . deviceName , uuid : this . uuid , token : this . token } } ) . toPromise ( ) . then ( response => { console . log ( response ) ; let data = JSON . parse ( JSON . stringify ( response ) ) ; if ( data . message == 1000 ) { device . data [ 'newVersion' ] = data . detail . version ; if ( device . data . newVersion == null ) return false ; device . data [ 'newVersionDescription' ] = data . detail . description ; if ( isNewerVersion ( device . data . version , device . data . newVersion ) ) { device . data [ 'hasNewVersion' ] = true ; return true ; } return false ; } else return false ; } ) . catch ( this . handleError ) ; } checkDeviceUpdate ( device ) { return this . http . get ( API . DEVICE . OTA_STATE , { params : { deviceName : device . deviceName , uuid : this . uuid , token : this . token } } ) . toPromise ( ) . then ( response => { console . log ( response ) ; let data = JSON . parse ( JSON . stringify ( response ) ) ; if ( data . message == 1000 ) if ( typeof data . detail . upgradeData . step != 'undefined' ) return data . detail . upgradeData . step ; } ) . catch ( this . handleError ) ; } handleError ( error ) { console . error ( 'An error occurred' , error ) ; return false ; } }