Advertisement
vergepuppeter

Bluetooth

Jan 21st, 2020
555
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 22.14 KB | None | 0 0
  1. package com.seesharp.app.bodysensor
  2.  
  3. import android.Manifest
  4. import android.animation.ArgbEvaluator
  5. import android.animation.ObjectAnimator
  6. import android.animation.ValueAnimator
  7. import android.app.Activity
  8. import android.app.ProgressDialog
  9. import android.bluetooth.*
  10. import android.bluetooth.BluetoothProfile.STATE_CONNECTED
  11. import android.os.Bundle
  12. import com.google.android.material.snackbar.Snackbar
  13. import androidx.appcompat.app.AppCompatActivity
  14. import android.view.Menu
  15. import android.view.MenuItem
  16.  
  17. import com.mazenrashed.printooth.Printooth;
  18. import com.mazenrashed.printooth.data.printable.Printable;
  19. import com.mazenrashed.printooth.data.printable.TextPrintable;
  20. import com.mazenrashed.printooth.data.printer.DefaultPrinter;
  21. import com.mazenrashed.printooth.ui.ScanningActivity;
  22. import com.mazenrashed.printooth.utilities.Printing;
  23. import com.mazenrashed.printooth.utilities.PrintingCallback;
  24.  
  25. import kotlinx.android.synthetic.main.activity_main.*
  26. import android.bluetooth.le.BluetoothLeScanner
  27. import android.bluetooth.le.ScanCallback
  28. import android.bluetooth.le.ScanResult
  29. import android.content.Context
  30. import android.content.Intent
  31. import android.content.pm.PackageManager
  32. import android.graphics.Color
  33. import android.net.Uri
  34. import android.os.Build
  35. import android.os.VibrationEffect
  36. import android.os.Vibrator
  37. import android.provider.Settings
  38. import android.util.Log
  39. import android.view.View
  40. import android.widget.Toast
  41. import androidx.core.app.ActivityCompat
  42. import androidx.core.content.ContextCompat
  43. import kotlinx.android.synthetic.main.content_main.*
  44. import org.jetbrains.anko.indeterminateProgressDialog
  45. import kotlin.math.abs
  46.  
  47.  
  48. class MainActivity : AppCompatActivity() {
  49.  
  50.     companion object{
  51.         val POSTURE_SENSING_SERVICE = "0000FFE0-0000-1000-8000-00805F9B34FB"
  52.         val POSTURE_SENSING_READING_1 = "0000ffe1-0000-1000-8000-00805f9b34fb"
  53.         val POSTURE_SENSING_READING_2 = "0000ffe2-0000-1000-8000-00805f9b34fb"
  54.     }
  55.  
  56.     private var bluetoothAdapter: BluetoothAdapter? = null
  57.     private var gatt: BluetoothGatt? = null
  58.     private var device: BluetoothDevice? = null
  59.     private var bluetoothScanner: BluetoothLeScanner? = null
  60.     private val REQUEST_ENABLE_BT: Int = 1
  61.     private val PERMISSION_REQ_BLUETOOTH: Int = 2
  62.     private var hasScannedStarted: Boolean = false
  63.     private var hasFound: Boolean = false
  64.     private var dialog: ProgressDialog? = null
  65.     private var packetCount = 1
  66.     private val stringBuilder = StringBuilder()
  67.     private var dataInArray = ByteArray(3)
  68.     private var vibrator: Vibrator? = null
  69.     private val VIBRATOR_PATTERN : LongArray = longArrayOf(1000, 1000, 1000)
  70.     private var isVibrating : Boolean = false
  71.     private var hasChangeBackrgound : Boolean = false
  72.     private var initialLineValue = 0f
  73.     private var initialLineValue2 = 0f
  74.  
  75.     override fun onCreate(savedInstanceState: Bundle?) {
  76.         super.onCreate(savedInstanceState)
  77.         setContentView(R.layout.activity_main)
  78.         setSupportActionBar(toolbar)
  79.  
  80.         vibrator = getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
  81.         bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
  82.         dialog = indeterminateProgressDialog(message = "Searching for SKY-BLE…")
  83.     }
  84.  
  85.  
  86.     override fun onPostCreate(savedInstanceState: Bundle?) {
  87.         super.onPostCreate(savedInstanceState)
  88.  
  89.         if(!vibrator!!.hasVibrator())
  90.             vibrator = null
  91.  
  92.         if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
  93.             != PackageManager.PERMISSION_GRANTED) {
  94.             // Permission is not granted
  95.  
  96.             if (ActivityCompat.shouldShowRequestPermissionRationale(this,
  97.                     Manifest.permission.ACCESS_COARSE_LOCATION)) {
  98.                 // Show an explanation to the user *asynchronously* -- don't block
  99.                 // this thread waiting for the user's response! After the user
  100.                 // sees the explanation, try again to request the permission.
  101.             } else {
  102.                 // No explanation needed, we can request the permission.
  103.                 ActivityCompat.requestPermissions(
  104.                     this,
  105.                     arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION),
  106.                     PERMISSION_REQ_BLUETOOTH
  107.                 )
  108.             }
  109.         }
  110.         else{
  111.             dialog!!.show()
  112.             bluetoothScanner = bluetoothAdapter!!.bluetoothLeScanner
  113.             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  114.                 bluetoothScanner!!.startScan(mLeScanCallback)
  115.             } else {
  116.                 bluetoothScanner!!.startScan(mLeScanCallback)
  117.             }
  118.  
  119.             hasScannedStarted = true
  120.         }
  121.  
  122. //        if (bluetoothAdapter == null || bluetoothAdapter!!.isEnabled) {
  123. //            val builder = AlertDialog.Builder(this@MainActivity)
  124. //            builder.setTitle("Bluetooth")
  125. //            builder.setMessage("Bluetooth is off. Turn it on?")
  126. //            builder.setPositiveButton("YES"){dialog, which ->
  127. //                val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
  128. //                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
  129. //            }
  130. //
  131. //            builder.setNegativeButton("No"){dialog,which ->
  132. //                Snackbar.make(findViewById(R.id.root), // Parent view
  133. //                    "Bluetooth is off", // Message to show
  134. //                    Snackbar.LENGTH_INDEFINITE //
  135. //                ).setAction("Enable") { // Action button click listener
  136. //                    val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
  137. //                    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
  138. //                }.show()
  139. //            }
  140. //            val dialog: AlertDialog = builder.create()
  141. //            dialog.show()
  142. //        }
  143. //        else{
  144. //
  145. //        }
  146.     }
  147.  
  148. //    override fun onCreateOptionsMenu(menu: Menu): Boolean {
  149. //        // Inflate the menu; this adds items to the action bar if it is present.
  150. //        menuInflater.inflate(R.menu.menu_main, menu)
  151. //        return true
  152. //    }
  153. //
  154. //    override fun onOptionsItemSelected(item: MenuItem): Boolean {
  155. //        // Handle action bar item clicks here. The action bar will
  156. //        // automatically handle clicks on the Home/Up button, so long
  157. //        // as you specify a parent activity in AndroidManifest.xml.
  158. //        return when (item.itemId) {
  159. //            R.id.action_settings -> true
  160. //            else -> super.onOptionsItemSelected(item)
  161. //        }
  162. //    }
  163.  
  164.     private val mLeScanCallback = object : ScanCallback() {
  165.         override fun onScanResult(callbackType: Int, result: ScanResult) {
  166.             super.onScanResult(callbackType, result)
  167.             Log.e("Bluetooth", result.device.name+"|"+result.device.type+"|"+result.device.address)
  168.             if(result.device.address == "50:8C:B1:52:16:3B"){
  169.                 if(device == null){ // Prevent duplicate
  170.                     device = result.device
  171.                     hasFound = true
  172.                     stopScan()
  173.  
  174.                     dialog!!.dismiss()
  175.                     gatt = device!!.connectGatt(this@MainActivity, false, bluetoothGattCallback)
  176. //                    gatt!!.requestMtu(50)
  177.                     Toast.makeText(this@MainActivity, "Connected to "+device!!.name, Toast.LENGTH_LONG).show()
  178.                     meter.visibility = View.VISIBLE
  179.                 }
  180.             }
  181.  
  182.         }
  183.  
  184.         override fun onBatchScanResults(results: List<ScanResult>) {
  185.             super.onBatchScanResults(results)
  186.         }
  187.  
  188.         override fun onScanFailed(errorCode: Int) {
  189.             super.onScanFailed(errorCode)
  190.         }
  191.     }
  192.  
  193.     private val bluetoothGattCallback = object : BluetoothGattCallback() {
  194.         override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) {
  195.             super.onServicesDiscovered(gatt, status)
  196.             for(service in gatt!!.services){
  197.                 Log.e("Service", service.uuid.toString())
  198.                 if(service.uuid.toString().equals(POSTURE_SENSING_SERVICE, ignoreCase = true)){
  199.                     Log.e("Service Found", "true")
  200.                     for(characteristic in service.characteristics){
  201.                         Log.e("Characteristic", characteristic!!.uuid.toString())
  202.                         if(characteristic.uuid.toString().equals(POSTURE_SENSING_READING_1, ignoreCase = true)){
  203.                             val char = gatt.getService(service.uuid).getCharacteristic(characteristic.uuid)
  204.                             gatt.setCharacteristicNotification(char, true)
  205.                             break
  206.                         }
  207.                     }
  208.                     break
  209.                 }
  210.             }
  211.         }
  212.  
  213.         override fun onMtuChanged(gatt: BluetoothGatt?, mtu: Int, status: Int) {
  214.             super.onMtuChanged(gatt, mtu, status)
  215.             Log.e("MTU", "has changed")
  216.         }
  217.  
  218.         override fun onDescriptorWrite(gatt: BluetoothGatt?, descriptor: BluetoothGattDescriptor?, status: Int) {
  219.             super.onDescriptorWrite(gatt, descriptor, status)
  220.  
  221. //            val characteristic = descriptor!!.characteristic
  222. //            characteristic.setValue(100)
  223.         }
  224.  
  225.         override fun onConnectionStateChange(gatt: BluetoothGatt?, status: Int, newState: Int) {
  226.             super.onConnectionStateChange(gatt, status, newState)
  227.  
  228.             when(newState){
  229.                 STATE_CONNECTED -> {
  230.                     if(null != gatt){
  231.                         gatt.discoverServices()
  232.                     }
  233.                 }
  234.             }
  235.         }
  236.  
  237.  
  238.  
  239.         override fun onCharacteristicRead(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?, status: Int) {
  240.             super.onCharacteristicRead(gatt, characteristic, status)
  241.             Log.e("BLEValue1", characteristic!!.value.toString(Charsets.UTF_8))
  242.         }
  243.  
  244.         override fun onCharacteristicChanged(gatt: BluetoothGatt?, characteristic: BluetoothGattCharacteristic?) {
  245.             super.onCharacteristicChanged(gatt, characteristic)
  246.             val data = characteristic!!.value.toString(Charsets.UTF_8)
  247.  
  248.             if(packetCount == 3){
  249.                 //Process and reset data
  250. //Pitch = -3.51,Roll = -0.77,Temp(C) = 23.
  251.                 val hashmap = HashMap<String, String>()
  252.                 val separatedString = stringBuilder.toString().split(",")
  253.                 for(s in separatedString){
  254.                     val separatedValues = s.split("=")
  255.                     if(separatedValues.size == 2){
  256.                         hashmap[separatedValues[0].trim()] = separatedValues[1].trim()
  257.                     }
  258.                 }
  259.  
  260.                 Log.e("Data", hashmap.toString())
  261.  
  262.                 if(hashmap.containsKey("Pitch")){
  263.                     val value = hashmap["Pitch"]!!.toDouble()
  264.                     val roundedValue = value.toFloat()
  265.  
  266.                     if(value > 0){
  267.                         rotateLine1(false, roundedValue)
  268.                         //Positive value, set meter to more than 50
  269.                         val degree = (value/90) * 100
  270.                         val m = ((50 + (degree/2)) / 100)
  271.                         Log.e("Value mP", m.toString())
  272.                         if(value > 20){
  273.                             if(null != vibrator) {
  274.                                 if(!isVibrating){
  275.                                     isVibrating = true
  276.                                     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
  277.                                         vibrator!!.vibrate(VibrationEffect.createWaveform(VIBRATOR_PATTERN, 0))
  278.                                     } else {
  279.                                         vibrator!!.vibrate(VIBRATOR_PATTERN, 0)
  280.                                     }
  281.                                 }
  282.                             }
  283.  
  284.                             changeBackgroundOnVibrate()
  285.                         }
  286.                         else{
  287.                             if(isVibrating){
  288.                                 isVibrating = false
  289.                                 vibrator!!.cancel()
  290.                             }
  291.                             resetBackground()
  292.                         }
  293.  
  294.                         runOnUiThread {
  295.                             if(m in 0.45..0.52)
  296.                                 meter.animate(0.5f, 0.0)
  297.                             else
  298.                                 meter.animate(m.toFloat(), value)
  299.                         }
  300.                     }
  301.                     else{
  302.                         rotateLine1(true, roundedValue)
  303.                         //Positive value, set meter to more than 50
  304.                         val negateValue = abs(value)
  305.                         val degree = (negateValue/90) * 100
  306.                         val m = 1.0 - ((50 + (degree/2)) / 100)
  307.                         Log.e("Value mP", m.toString())
  308.                         runOnUiThread {
  309.                             if(m in 0.45..0.52)
  310.                                 meter.animate(0.5f, 0.0)
  311.                             else
  312.                                 meter.animate(m.toFloat(), value)
  313.                         }
  314.                     }
  315.                 }
  316.  
  317.                 if(hashmap.containsKey("Roll")){
  318.                     val value = hashmap["Roll"]!!.toDouble()
  319.                     val roundedValue = value.toFloat()
  320.  
  321.                     if(value > 0){
  322.                         rotateLine2(false, roundedValue)
  323.                         //Positive value, set meter to more than 50
  324.                         val degree = (value/90) * 100
  325.                         val m = 1.0 - ((50 + (degree/2)) / 100)
  326.                         Log.e("Value m", m.toString())
  327.                         runOnUiThread {
  328.                             if(m in 0.45..0.52)
  329.                                 meter2.animate(0.5f, 0.0)
  330.                             else
  331.                                 meter2.animate(m.toFloat(), value)
  332.                         }
  333.                     }
  334.                     else{
  335.                         rotateLine2(true, roundedValue)
  336.                         //Positive value, set meter to more than 50
  337.                         val negateValue = abs(value)
  338.                         val degree = (negateValue/90) * 100
  339.                         val m = (50 + (degree/2)) / 100
  340.                         Log.e("Value m", m.toString())
  341.                         runOnUiThread {
  342.                             if(m in 0.45..0.52)
  343.                                 meter2.animate(0.5f, 0.0)
  344.                             else
  345.                                 meter2.animate(m.toFloat(), value)
  346.                         }
  347.                     }
  348.                 }
  349.  
  350.                 if(hashmap.containsKey("Temp(C)")){
  351.                     val value = hashmap["Temp(C)"]!!.toDouble()
  352.                     runOnUiThread {
  353.                         temp.text = value.toInt().toString() + "°C"
  354.                     }
  355.                 }
  356.  
  357.                 stringBuilder.setLength(0)
  358.                 packetCount = 1
  359.             }
  360.             else{
  361.                 stringBuilder.append(data)
  362.                 packetCount++
  363.             }
  364.         }
  365.     }
  366.  
  367.     override fun onResume() {
  368.         super.onResume()
  369.  
  370.         if(null == device){
  371.             if(!hasScannedStarted){
  372.                 requestPermission()
  373.             }
  374.         }
  375.     }
  376.  
  377.     override fun onDestroy() {
  378.         super.onDestroy()
  379.  
  380.         if(null == device){
  381.             if(hasScannedStarted){
  382.                 stopScan()
  383.             }
  384.         }
  385.         else{
  386.             if(null != gatt){
  387.                 gatt!!.close()
  388.                 gatt = null
  389.             }
  390.         }
  391.     }
  392.  
  393.     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
  394.         super.onActivityResult(requestCode, resultCode, data)
  395.  
  396.         if (requestCode == REQUEST_ENABLE_BT && resultCode == Activity.RESULT_OK) {
  397.             requestPermission()
  398.         }
  399.     }
  400.  
  401.     override fun onRequestPermissionsResult(requestCode: Int,
  402.                                             permissions: Array<String>, grantResults: IntArray) {
  403.         when (requestCode) {
  404.             PERMISSION_REQ_BLUETOOTH -> {
  405.                 // If request is cancelled, the result arrays are empty.
  406.                 if ((grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
  407.                     // permission was granted, yay! Do the
  408.                     // contacts-related task you need to do.
  409.                     if (bluetoothAdapter == null || bluetoothAdapter!!.isEnabled) {
  410.                         bluetoothScanner = bluetoothAdapter!!.bluetoothLeScanner
  411.                         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  412.                             bluetoothScanner!!.startScan(mLeScanCallback)
  413.                         } else {
  414.                             bluetoothScanner!!.startScan(mLeScanCallback)
  415.                         }
  416.  
  417.                         hasScannedStarted = true
  418.                     }
  419.                 } else {
  420.                     // permission denied, boo! Disable the
  421.                     // functionality that depends on this permission.
  422.                     Snackbar.make(findViewById(R.id.root), // Parent view
  423.                         "Bluetooth is off pr permission was denied", // Message to show
  424.                         Snackbar.LENGTH_INDEFINITE //
  425.                     ).setAction("Enable") { // Action button click listener
  426.                         val enableBtIntent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
  427.                         val uri = Uri.fromParts("package", packageName, null)
  428.                         enableBtIntent.data = uri
  429.                         startActivity(enableBtIntent)
  430.                     }.show()
  431.                 }
  432.                 return
  433.             }
  434.  
  435.             // Add other 'when' lines to check for other
  436.             // permissions this app might request.
  437.             else -> {
  438.                 // Ignore all other requests.
  439.             }
  440.         }
  441.     }
  442.  
  443.     private fun requestPermission(){
  444.         if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
  445.             != PackageManager.PERMISSION_GRANTED) {
  446.             // Permission is not granted
  447.             if (ActivityCompat.shouldShowRequestPermissionRationale(this,
  448.                     Manifest.permission.ACCESS_COARSE_LOCATION)) {
  449.                 // Show an explanation to the user *asynchronously* -- don't block
  450.                 // this thread waiting for the user's response! After the user
  451.                 // sees the explanation, try again to request the permission.
  452.             } else {
  453.                 // No explanation needed, we can request the permission.
  454.                 ActivityCompat.requestPermissions(this,
  455.                     arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION),
  456.                     PERMISSION_REQ_BLUETOOTH)
  457.  
  458.                 // MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
  459.                 // app-defined int constant. The callback method gets the
  460.                 // result of the request.
  461.             }
  462.         }
  463.         else{
  464.             if (bluetoothAdapter == null || bluetoothAdapter!!.isEnabled) {
  465.                 bluetoothScanner = bluetoothAdapter!!.bluetoothLeScanner
  466.                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
  467.                     bluetoothScanner!!.startScan(mLeScanCallback)
  468.                 } else {
  469.                     bluetoothScanner!!.startScan(mLeScanCallback)
  470.                 }
  471.  
  472.                 hasScannedStarted = true
  473.             }
  474.         }
  475.     }
  476.  
  477.     private fun stopScan(){
  478.         hasScannedStarted = false
  479.         bluetoothScanner!!.stopScan(mLeScanCallback)
  480.     }
  481.  
  482.     private fun changeBackgroundOnVibrate(){
  483.         if(!hasChangeBackrgound){
  484.             hasChangeBackrgound = true
  485.             runOnUiThread {
  486.                 ObjectAnimator.ofObject(rootView, "backgroundColor", ArgbEvaluator(), Color.argb(255, 0, 87, 75), Color.argb(255, 216, 27, 96))
  487.                     .setDuration(300)
  488.                     .start()
  489.  
  490.                 ObjectAnimator.ofObject(toolbar, "backgroundColor", ArgbEvaluator(), Color.argb(255, 0, 87, 75), Color.argb(255, 216, 27, 96))
  491.                     .setDuration(300)
  492.                     .start()
  493.             }
  494.         }
  495.  
  496.     }
  497.  
  498.     private fun resetBackground(){
  499.         if(hasChangeBackrgound){
  500.             hasChangeBackrgound = false
  501.             runOnUiThread {
  502.                 ObjectAnimator.ofObject(rootView, "backgroundColor", ArgbEvaluator(), Color.argb(255, 216, 27, 96), Color.argb(255, 0, 87, 75))
  503.                     .setDuration(300)
  504.                     .start()
  505.  
  506.                 ObjectAnimator.ofObject(toolbar, "backgroundColor", ArgbEvaluator(), Color.argb(255, 216, 27, 96), Color.argb(255, 0, 87, 75))
  507.                     .setDuration(300)
  508.                     .start()
  509.             }
  510.         }
  511.     }
  512.  
  513.     private fun rotateLine1(isNegative:Boolean, value: Float){
  514.         runOnUiThread {
  515.             if(isNegative){
  516.                 val newVal = abs(value)
  517.                 ObjectAnimator.ofFloat(postureLine, View.ROTATION, newVal, initialLineValue)
  518.                     .setDuration(100)
  519.                     .start()
  520.  
  521.                 initialLineValue = newVal
  522.             }
  523.             else{
  524.                 val newVal = abs(value) * -1
  525.                 ObjectAnimator.ofFloat(postureLine, View.ROTATION, newVal, initialLineValue)
  526.                     .setDuration(100)
  527.                     .start()
  528.  
  529.                 initialLineValue = newVal
  530.             }
  531.         }
  532.     }
  533.  
  534.     private fun rotateLine2(isNegative: Boolean, value: Float){
  535.         runOnUiThread {
  536.             if(isNegative){
  537.                 ObjectAnimator.ofFloat(postureLine2, View.ROTATION, value, initialLineValue2)
  538.                     .setDuration(100)
  539.                     .start()
  540.  
  541.                 initialLineValue2 = value
  542.             }
  543.             else{
  544.                 ObjectAnimator.ofFloat(postureLine2, View.ROTATION, value, initialLineValue2)
  545.                     .setDuration(100)
  546.                     .start()
  547.  
  548.                 initialLineValue2 = value
  549.             }
  550.         }
  551.     }
  552. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement