Add connect, pause, sync
This commit is contained in:
parent
173e6690c2
commit
eaa6d72a3e
8 changed files with 339 additions and 79 deletions
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
|
|
89
app/src/main/java/de/asaril/bletail/BleConnectionHandler.kt
Normal file
89
app/src/main/java/de/asaril/bletail/BleConnectionHandler.kt
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
package de.asaril.bletail
|
||||||
|
|
||||||
|
import android.bluetooth.BluetoothAdapter
|
||||||
|
import android.bluetooth.BluetoothDevice
|
||||||
|
import android.bluetooth.BluetoothManager
|
||||||
|
import android.bluetooth.le.ScanCallback
|
||||||
|
import android.bluetooth.le.ScanResult
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.util.Log
|
||||||
|
import no.nordicsemi.android.ble.callback.SuccessCallback
|
||||||
|
|
||||||
|
class BleConnectionHandler(main: MainActivity) {
|
||||||
|
|
||||||
|
private var ble: UartManager? = null
|
||||||
|
private val activity: MainActivity = main
|
||||||
|
|
||||||
|
var connected = false
|
||||||
|
private set
|
||||||
|
|
||||||
|
private fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) }
|
||||||
|
|
||||||
|
|
||||||
|
fun connect(callback: ((Boolean) -> Unit)?) {
|
||||||
|
|
||||||
|
ble = UartManager(activity)
|
||||||
|
ble!!.setGattCallbacks(DefaultUartManagerCallbacks())
|
||||||
|
|
||||||
|
val bluetoothManager: BluetoothManager =
|
||||||
|
activity.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
|
||||||
|
val bluetoothAdapter: BluetoothAdapter = bluetoothManager.adapter
|
||||||
|
|
||||||
|
if (!bluetoothAdapter.isEnabled) {
|
||||||
|
val enableIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
|
||||||
|
val requestEnableBt = 1
|
||||||
|
activity.startActivityForResult(enableIntent, requestEnableBt)
|
||||||
|
}
|
||||||
|
|
||||||
|
bluetoothAdapter.bluetoothLeScanner.startScan(object : ScanCallback() {
|
||||||
|
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
||||||
|
super.onScanResult(callbackType, result)
|
||||||
|
Log.i("BLEtail", "Remote device name: " + result.device.name)
|
||||||
|
|
||||||
|
if (result.device.name == "Bluefruit52") {
|
||||||
|
bluetoothAdapter.bluetoothLeScanner.stopScan(this)
|
||||||
|
ble!!.connect(result.device)
|
||||||
|
.retry(3, 100)
|
||||||
|
.useAutoConnect(true)
|
||||||
|
.done {
|
||||||
|
connected = true
|
||||||
|
if (callback != null) {
|
||||||
|
callback(connected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fail { _: BluetoothDevice, _: Int ->
|
||||||
|
connected = false
|
||||||
|
if (callback != null) {
|
||||||
|
callback(connected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.enqueue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun disconnect(callback: ((Boolean) -> Unit)?) {
|
||||||
|
ble!!.disconnect()
|
||||||
|
.done {
|
||||||
|
connected = false
|
||||||
|
if (callback != null) {
|
||||||
|
callback(connected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.enqueue()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sendToBleUart(msgRaw: ByteArray) {
|
||||||
|
if (connected) {
|
||||||
|
val arr: ByteArray = CobsUtils.encode(msgRaw)
|
||||||
|
Log.i("BLEtail", "tx:" + arr.toHexString())
|
||||||
|
ble?.send(arr)
|
||||||
|
} else {
|
||||||
|
Log.w("BLEtail", "tx failed (not connected):" + msgRaw.toHexString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,18 +1,9 @@
|
||||||
package de.asaril.bletail
|
package de.asaril.bletail
|
||||||
|
|
||||||
import CobsUtils
|
|
||||||
import android.bluetooth.BluetoothAdapter
|
|
||||||
import android.bluetooth.BluetoothManager
|
|
||||||
import android.bluetooth.le.ScanCallback
|
|
||||||
import android.bluetooth.le.ScanResult
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.util.Log
|
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.SeekBar
|
import android.widget.SeekBar
|
||||||
|
@ -23,56 +14,46 @@ import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
|
||||||
class MainActivity : AppCompatActivity() {
|
class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private val LED_COUNT: Int = 40
|
private val LED_COUNT: Int = 40
|
||||||
|
|
||||||
private var ble: UartManager? = null
|
private var ble: BleConnectionHandler? = null
|
||||||
|
private var wasConnected = false
|
||||||
|
|
||||||
private var segments: MutableList<SegmentCardView>? = null
|
private var segments: MutableList<SegmentCardView>? = null
|
||||||
|
private var paused = false
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
|
|
||||||
|
ble = BleConnectionHandler(this)
|
||||||
|
|
||||||
segments = MutableList<SegmentCardView>(5, init = {
|
segments = MutableList<SegmentCardView>(5, init = {
|
||||||
SegmentCardView(this, it, 0, LED_COUNT - 1, Fx.Mode.THEATER_CHASE_RAINBOW, Color(), Color(), Color(), 0x0800, false)
|
SegmentCardView(this, it, 0, LED_COUNT - 1, Fx.Mode.THEATER_CHASE_RAINBOW, Color(), Color(), Color(), 0x0800, false)
|
||||||
})
|
})
|
||||||
for (s in segments!!) {
|
for (s in segments!!) {
|
||||||
s.sendCallback = this::sendToBleUart
|
s.sendCallback = { bytes: ByteArray -> ble!!.sendToBleUart(bytes) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ble!!.connect { connected: Boolean ->
|
||||||
ble = UartManager(this)
|
if (connected) {
|
||||||
ble!!.setGattCallbacks(DefaultUartManagerCallbacks())
|
val storedState = File(getExternalFilesDir(null)!!, "_stored.json")
|
||||||
|
val loaded = storedState.exists() and loadFile(storedState)
|
||||||
val bluetoothManager: BluetoothManager =
|
if (!loaded) {
|
||||||
getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
|
val defaultFile = File(getExternalFilesDir(null)!!, "default.json")
|
||||||
val bluetoothAdapter: BluetoothAdapter = bluetoothManager.adapter
|
if (defaultFile.exists()) {
|
||||||
|
loadFile(defaultFile)
|
||||||
if (!bluetoothAdapter.isEnabled) {
|
}
|
||||||
val enableIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
|
|
||||||
val requestEnableBt = 1
|
|
||||||
startActivityForResult(enableIntent, requestEnableBt)
|
|
||||||
}
|
|
||||||
|
|
||||||
bluetoothAdapter.bluetoothLeScanner.startScan(object : ScanCallback() {
|
|
||||||
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
|
||||||
super.onScanResult(callbackType, result)
|
|
||||||
Log.i("BLEtail", "Remote device name: " + result.device.name)
|
|
||||||
|
|
||||||
if (result.device.name == "Bluefruit52") {
|
|
||||||
bluetoothAdapter.bluetoothLeScanner.stopScan(this)
|
|
||||||
ble!!.connect(result.device)
|
|
||||||
.retry(3, 100)
|
|
||||||
.useAutoConnect(true)
|
|
||||||
.enqueue()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
updateConnection(connected)
|
||||||
|
}
|
||||||
|
|
||||||
brightness!!.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
brightness!!.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
||||||
override fun onProgressChanged(var1: SeekBar, var2: Int, var3: Boolean) {
|
override fun onProgressChanged(var1: SeekBar, var2: Int, var3: Boolean) {
|
||||||
|
@ -90,15 +71,49 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
if (wasConnected) {
|
||||||
|
ble?.connect { c -> updateConnection(c) }
|
||||||
|
}
|
||||||
|
super.onResume()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
saveFile("_stored")
|
||||||
|
super.onPause()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStop() {
|
||||||
|
wasConnected = (ble?.connected) ?: false
|
||||||
|
ble?.disconnect { c -> updateConnection(c) }
|
||||||
|
super.onStop()
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
segments = null
|
segments = null
|
||||||
ble!!.disconnect()
|
ble!!.disconnect { c -> updateConnection(c) }
|
||||||
|
val storedState = File(getExternalFilesDir(null)!!, "_stored.json")
|
||||||
|
if (storedState.exists()) {
|
||||||
|
storedState.deleteOnExit()
|
||||||
|
}
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||||
// Inflate the menu; this adds items to the action bar if it is present.
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
menuInflater.inflate(R.menu.main_menu, menu)
|
menuInflater.inflate(R.menu.main_menu, menu)
|
||||||
|
|
||||||
|
val connected = (ble != null) and (ble!!.connected)
|
||||||
|
menu.findItem(R.id.action_connection).apply {
|
||||||
|
if (connected) {
|
||||||
|
icon = getDrawable(R.drawable.ic_bluetooth_connected_black_24dp)
|
||||||
|
title = getString(R.string.disconnect)
|
||||||
|
} else {
|
||||||
|
icon = getDrawable(R.drawable.ic_bluetooth_disabled_black_24dp)
|
||||||
|
title = getString(R.string.connect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,28 +122,30 @@ class MainActivity : AppCompatActivity() {
|
||||||
val m = Fx.setNumSegments_msg.newBuilder()
|
val m = Fx.setNumSegments_msg.newBuilder()
|
||||||
m.numSegments = count
|
m.numSegments = count
|
||||||
r.setNumSegments = m.build()
|
r.setNumSegments = m.build()
|
||||||
sendToBleUart(r.build().toByteArray())
|
if (ble != null) {
|
||||||
|
ble!!.sendToBleUart(r.build().toByteArray())
|
||||||
|
|
||||||
val segLength: Int = LED_COUNT / count
|
val segLength: Int = LED_COUNT / count
|
||||||
val segmentListLayout = findViewById<LinearLayout>(R.id.segmentList)
|
val segmentListLayout = findViewById<LinearLayout>(R.id.segmentList)
|
||||||
|
|
||||||
for (i in 0 until count) {
|
for (i in 0 until count) {
|
||||||
segments!![i].start = segLength * i
|
segments!![i].start = segLength * i
|
||||||
segments!![i].end = if (i == count - 1) {
|
segments!![i].end = if (i == count - 1) {
|
||||||
LED_COUNT - 1
|
LED_COUNT - 1
|
||||||
} else {
|
} else {
|
||||||
(segLength * (i + 1) - 1)
|
(segLength * (i + 1) - 1)
|
||||||
|
}
|
||||||
|
segments!![i].sendSetSegment()
|
||||||
}
|
}
|
||||||
segments!![i].sendSetSegment()
|
|
||||||
}
|
|
||||||
|
|
||||||
while (segmentListLayout.childCount > count) {
|
while (segmentListLayout.childCount > count) {
|
||||||
val ind = segmentListLayout.childCount - 1
|
val ind = segmentListLayout.childCount - 1
|
||||||
segmentListLayout.removeViewAt(ind)
|
segmentListLayout.removeViewAt(ind)
|
||||||
}
|
}
|
||||||
while (segmentListLayout.childCount < count) {
|
while (segmentListLayout.childCount < count) {
|
||||||
val ind = segmentListLayout.childCount
|
val ind = segmentListLayout.childCount
|
||||||
segmentListLayout.addView(segments!![ind], ind)
|
segmentListLayout.addView(segments!![ind], ind)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,8 +158,9 @@ class MainActivity : AppCompatActivity() {
|
||||||
val r: Fx.Root.Builder = Fx.Root.newBuilder()
|
val r: Fx.Root.Builder = Fx.Root.newBuilder()
|
||||||
r.halt = Fx.halt_msg.newBuilder().build()
|
r.halt = Fx.halt_msg.newBuilder().build()
|
||||||
val msgRaw = r.build().toByteArray()
|
val msgRaw = r.build().toByteArray()
|
||||||
sendToBleUart(msgRaw)
|
ble?.sendToBleUart(msgRaw)
|
||||||
ble!!.disconnect()
|
ble?.disconnect(null)
|
||||||
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
builder.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() }
|
builder.setNegativeButton("Cancel") { dialog, _ -> dialog.cancel() }
|
||||||
|
@ -154,7 +172,7 @@ class MainActivity : AppCompatActivity() {
|
||||||
val m = Fx.setBrightness_msg.newBuilder()
|
val m = Fx.setBrightness_msg.newBuilder()
|
||||||
m.brightness = value
|
m.brightness = value
|
||||||
r.setBrightness = m.build()
|
r.setBrightness = m.build()
|
||||||
sendToBleUart(r.build().toByteArray())
|
ble?.sendToBleUart(r.build().toByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun segCountClick(item: MenuItem) {
|
fun segCountClick(item: MenuItem) {
|
||||||
|
@ -169,13 +187,6 @@ class MainActivity : AppCompatActivity() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendToBleUart(msgRaw: ByteArray) {
|
|
||||||
val arr: ByteArray = CobsUtils.encode(msgRaw)
|
|
||||||
fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) }
|
|
||||||
Log.i("BLEtail", "tx:" + arr.toHexString())
|
|
||||||
ble?.send(arr)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun serialize(): JSONObject {
|
fun serialize(): JSONObject {
|
||||||
val j = JSONObject()
|
val j = JSONObject()
|
||||||
|
@ -189,21 +200,32 @@ class MainActivity : AppCompatActivity() {
|
||||||
return j
|
return j
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deserialize(j: JSONObject) {
|
fun deserialize(j: JSONObject): Boolean {
|
||||||
brightness.progress = j.getInt("brightness")
|
brightness.progress = j.getInt("brightness")
|
||||||
val jsegs = j.getJSONArray("segments")
|
val jsegs = j.getJSONArray("segments")
|
||||||
updateSegmentCards(jsegs.length())
|
val segNum = jsegs.length()
|
||||||
for (i in 0 until jsegs.length()) {
|
if (segNum < 1) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
updateSegmentCards(segNum)
|
||||||
|
for (i in 0 until segNum) {
|
||||||
val jseg = jsegs[i] as JSONObject
|
val jseg = jsegs[i] as JSONObject
|
||||||
val idx = jseg.getInt("index")
|
val idx = jseg.getInt("index")
|
||||||
assert(idx < segments!!.size)
|
assert(idx < segments!!.size)
|
||||||
segments!![idx].deserialize(jseg)
|
segments!![idx].deserialize(jseg)
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadFile(file: File) {
|
private fun loadFile(file: File): Boolean {
|
||||||
val j = JSONObject(file.readText())
|
val j = JSONObject(file.readText())
|
||||||
deserialize(j)
|
val loaded = deserialize(j)
|
||||||
|
if ((!loaded) and (file.name == "_stored.json")) {
|
||||||
|
// remove broken stored state
|
||||||
|
file.delete()
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return loaded
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveFile(filename: String) {
|
private fun saveFile(filename: String) {
|
||||||
|
@ -240,5 +262,99 @@ class MainActivity : AppCompatActivity() {
|
||||||
builder.show()
|
builder.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun pauseClick(item: MenuItem) {
|
||||||
|
if ((ble != null) && (ble!!.connected)) {
|
||||||
|
this.paused = !this.paused
|
||||||
|
sendPause(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendPause(item: MenuItem) {
|
||||||
|
val r = Fx.Root.newBuilder()
|
||||||
|
if (paused) {
|
||||||
|
val m = Fx.pause_msg.newBuilder()
|
||||||
|
r.pause = m.build()
|
||||||
|
item.icon = getDrawable(android.R.drawable.ic_media_play)
|
||||||
|
item.title = getString(R.string.resume)
|
||||||
|
} else {
|
||||||
|
val m = Fx.resume_msg.newBuilder()
|
||||||
|
r.resume = m.build()
|
||||||
|
item.icon = getDrawable(android.R.drawable.ic_media_pause)
|
||||||
|
item.title = getString(R.string.pause)
|
||||||
|
}
|
||||||
|
ble?.sendToBleUart(r.build().toByteArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateConnection(connected: Boolean) {
|
||||||
|
(findViewById<View?>(R.id.action_connection) as MenuItem?)?.apply {
|
||||||
|
if (connected) {
|
||||||
|
icon = getDrawable(R.drawable.ic_bluetooth_connected_black_24dp)
|
||||||
|
title = getString(R.string.disconnect)
|
||||||
|
} else {
|
||||||
|
icon = getDrawable(R.drawable.ic_bluetooth_disabled_black_24dp)
|
||||||
|
title = getString(R.string.connect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun connectionClick(item: MenuItem) {
|
||||||
|
val callback = { connected: Boolean ->
|
||||||
|
item.apply {
|
||||||
|
if (connected) {
|
||||||
|
icon = getDrawable(R.drawable.ic_bluetooth_connected_black_24dp)
|
||||||
|
title = getString(R.string.disconnect)
|
||||||
|
} else {
|
||||||
|
icon = getDrawable(R.drawable.ic_bluetooth_disabled_black_24dp)
|
||||||
|
title = getString(R.string.connect)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ble != null) {
|
||||||
|
if (ble!!.connected) {
|
||||||
|
ble!!.disconnect(callback)
|
||||||
|
} else {
|
||||||
|
ble!!.connect(callback)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun stopClick(item: MenuItem) {
|
||||||
|
if ((ble != null) && (ble!!.connected)) {
|
||||||
|
paused = true
|
||||||
|
sendPause(item)
|
||||||
|
|
||||||
|
val r = Fx.Root.newBuilder()
|
||||||
|
val m = Fx.strip_off_msg.newBuilder()
|
||||||
|
r.stripOff = m.build()
|
||||||
|
ble?.sendToBleUart(r.build().toByteArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
val storedState = File(getExternalFilesDir(null)!!, "_stored.json")
|
||||||
|
if (storedState.exists()) {
|
||||||
|
storedState.deleteOnExit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun syncClick(item: MenuItem) {
|
||||||
|
if ((ble != null) && (ble!!.connected) && (segments != null)) {
|
||||||
|
var r = Fx.Root.newBuilder()
|
||||||
|
val m = Fx.stop_msg.newBuilder()
|
||||||
|
r.stop = m.build()
|
||||||
|
ble?.sendToBleUart(r.build().toByteArray())
|
||||||
|
|
||||||
|
for (i in 0 until segments!!.size) {
|
||||||
|
segments!![i].speed = segments!![0].speed
|
||||||
|
segments!![i].updateView()
|
||||||
|
}
|
||||||
|
|
||||||
|
r = Fx.Root.newBuilder()
|
||||||
|
val m2 = Fx.start_msg.newBuilder()
|
||||||
|
r.start = m2.build()
|
||||||
|
ble?.sendToBleUart(r.build().toByteArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,17 +266,22 @@ class SegmentCardView : CardView {
|
||||||
assert(this.index == j.getInt("index"))
|
assert(this.index == j.getInt("index"))
|
||||||
this.start = j.getInt("start")
|
this.start = j.getInt("start")
|
||||||
this.end = j.getInt("end")
|
this.end = j.getInt("end")
|
||||||
this.mode = Fx.Mode.forNumber(j.getInt("mode"))
|
|
||||||
val jcolors = j.getJSONArray("colors")
|
val jcolors = j.getJSONArray("colors")
|
||||||
this.colors[0] = Color.valueOf(jcolors[0] as Int)
|
this.colors[0] = Color.valueOf(jcolors[0] as Int)
|
||||||
this.colors[1] = Color.valueOf(jcolors[1] as Int)
|
this.colors[1] = Color.valueOf(jcolors[1] as Int)
|
||||||
this.colors[2] = Color.valueOf(jcolors[2] as Int)
|
this.colors[2] = Color.valueOf(jcolors[2] as Int)
|
||||||
this.speed = j.getInt("speed")
|
this.speed = j.getInt("speed")
|
||||||
|
|
||||||
this.reverse = j.getBoolean("reverse")
|
this.reverse = j.getBoolean("reverse")
|
||||||
|
|
||||||
|
// set mode last as this will trigger setSegment
|
||||||
|
this.mode = Fx.Mode.forNumber(j.getInt("mode"))
|
||||||
updateView()
|
updateView()
|
||||||
|
sendSetSegment()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateView() {
|
fun updateView() {
|
||||||
viewCol0!!.setColorFilter(colors[0].toArgb())
|
viewCol0!!.setColorFilter(colors[0].toArgb())
|
||||||
viewCol1!!.setColorFilter(colors[1].toArgb())
|
viewCol1!!.setColorFilter(colors[1].toArgb())
|
||||||
viewCol2!!.setColorFilter(colors[2].toArgb())
|
viewCol2!!.setColorFilter(colors[2].toArgb())
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M7,12l-2,-2 -2,2 2,2 2,-2zM17.71,7.71L12,2h-1v7.59L6.41,5 5,6.41 10.59,12 5,17.59 6.41,19 11,14.41L11,22h1l5.71,-5.71 -4.3,-4.29 4.3,-4.29zM13,5.83l1.88,1.88L13,9.59L13,5.83zM14.88,16.29L13,18.17v-3.76l1.88,1.88zM19,10l-2,2 2,2 2,-2 -2,-2z"/>
|
||||||
|
</vector>
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24.0"
|
||||||
|
android:viewportHeight="24.0">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M13,5.83l1.88,1.88 -1.6,1.6 1.41,1.41 3.02,-3.02L12,2h-1v5.03l2,2v-3.2zM5.41,4L4,5.41 10.59,12 5,17.59 6.41,19 11,14.41V22h1l4.29,-4.29 2.3,2.29L20,18.59 5.41,4zM13,18.17v-3.76l1.88,1.88L13,18.17z"/>
|
||||||
|
</vector>
|
|
@ -9,14 +9,28 @@
|
||||||
android:iconTint="@android:color/secondary_text_dark"
|
android:iconTint="@android:color/secondary_text_dark"
|
||||||
android:title="@string/load"
|
android:title="@string/load"
|
||||||
android:onClick="loadBtnClick"
|
android:onClick="loadBtnClick"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="always" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/saveBtn"
|
android:id="@+id/saveBtn"
|
||||||
android:title="@string/save"
|
android:title="@string/save"
|
||||||
android:icon="@android:drawable/ic_menu_save"
|
android:icon="@android:drawable/ic_menu_save"
|
||||||
android:iconTint="@android:color/primary_text_dark"
|
android:iconTint="@android:color/primary_text_dark"
|
||||||
android:onClick="saveBtnClick"
|
android:onClick="saveBtnClick"
|
||||||
app:showAsAction="ifRoom"/>
|
app:showAsAction="always"/>
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_pause"
|
||||||
|
android:icon="@android:drawable/ic_media_pause"
|
||||||
|
android:onClick="pauseClick"
|
||||||
|
android:title="@string/pause"
|
||||||
|
app:showAsAction="always" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_connection"
|
||||||
|
android:icon="@drawable/ic_bluetooth_disabled_black_24dp"
|
||||||
|
android:onClick="connectionClick"
|
||||||
|
android:title="@string/connect"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/segCountMenu"
|
android:id="@+id/segCountMenu"
|
||||||
|
@ -48,8 +62,20 @@
|
||||||
</menu>
|
</menu>
|
||||||
</item>
|
</item>
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_halt"
|
android:id="@+id/action_sync"
|
||||||
|
android:icon="@android:drawable/ic_popup_sync"
|
||||||
|
android:onClick="syncClick"
|
||||||
|
android:title="@string/action_sync"
|
||||||
|
app:showAsAction="collapseActionView" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_stop"
|
||||||
android:icon="@android:drawable/ic_lock_power_off"
|
android:icon="@android:drawable/ic_lock_power_off"
|
||||||
|
android:onClick="stopClick"
|
||||||
|
android:title="@string/action_stop"
|
||||||
|
app:showAsAction="collapseActionView" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_halt"
|
||||||
|
android:icon="@android:drawable/ic_delete"
|
||||||
android:onClick="powerOffClick"
|
android:onClick="powerOffClick"
|
||||||
android:title="@string/action_halt"
|
android:title="@string/action_halt"
|
||||||
app:showAsAction="collapseActionView" />
|
app:showAsAction="collapseActionView" />
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">BLEtail</string>
|
<string name="app_name">BLEtail</string>
|
||||||
<string name="action_halt">Halt</string>
|
<string name="action_halt">Shutdown</string>
|
||||||
<string name="action_settings">Settings</string>
|
<string name="action_settings">Settings</string>
|
||||||
<string name="seg3">3</string>
|
<string name="seg3">3</string>
|
||||||
<string name="seg5">5</string>
|
<string name="seg5">5</string>
|
||||||
|
@ -15,4 +15,10 @@
|
||||||
<string name="brightness">Brightness</string>
|
<string name="brightness">Brightness</string>
|
||||||
<string name="load">Load</string>
|
<string name="load">Load</string>
|
||||||
<string name="save">Save</string>
|
<string name="save">Save</string>
|
||||||
|
<string name="connect">Connect</string>
|
||||||
|
<string name="disconnect">Disconnect</string>
|
||||||
|
<string name="pause">Pause</string>
|
||||||
|
<string name="resume">Resume</string>
|
||||||
|
<string name="action_stop">Stop (Off)</string>
|
||||||
|
<string name="action_sync">Sync</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue