commit c217ba26b1390023dcb00f556e64c97c4f731a3e Author: Patrick Moessler Date: Wed Oct 16 23:21:46 2019 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..603b140 --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..356cf2c --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,127 @@ + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..169fd0d --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..dfd2c79 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/app/.gitignore b/app/.gitignore new file mode 100644 index 0000000..796b96d --- /dev/null +++ b/app/.gitignore @@ -0,0 +1 @@ +/build diff --git a/app/build.gradle b/app/build.gradle new file mode 100644 index 0000000..df0a102 --- /dev/null +++ b/app/build.gradle @@ -0,0 +1,60 @@ +apply plugin: 'com.android.application' +apply plugin: 'com.google.protobuf' + +apply plugin: 'kotlin-android' + +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.2" + defaultConfig { + applicationId "de.asaril.bletail" + minSdkVersion 28 + targetSdkVersion 29 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } +} +repositories { + mavenCentral() +} +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.core:core-ktx:1.0.2' + implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'com.google.protobuf:protobuf-lite:3.0.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' + implementation 'com.google.android.material:material:1.0.0' +} +protobuf { + protoc { + artifact = 'com.google.protobuf:protoc:3.0.0' + } + plugins { + javalite { + artifact = 'com.google.protobuf:protoc-gen-javalite:3.0.0' + } + } + generateProtoTasks { + all().each { task -> + task.builtins { + remove java + } + task.plugins { + javalite {} + } + } + } +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/app/src/androidTest/java/de/asaril/bletail/ExampleInstrumentedTest.kt b/app/src/androidTest/java/de/asaril/bletail/ExampleInstrumentedTest.kt new file mode 100644 index 0000000..3f4a434 --- /dev/null +++ b/app/src/androidTest/java/de/asaril/bletail/ExampleInstrumentedTest.kt @@ -0,0 +1,24 @@ +package de.asaril.bletail + +import androidx.test.platform.app.InstrumentationRegistry +import androidx.test.ext.junit.runners.AndroidJUnit4 + +import org.junit.Test +import org.junit.runner.RunWith + +import org.junit.Assert.* + +/** + * Instrumented test, which will execute on an Android device. + * + * See [testing documentation](http://d.android.com/tools/testing). + */ +@RunWith(AndroidJUnit4::class) +class ExampleInstrumentedTest { + @Test + fun useAppContext() { + // Context of the app under test. + val appContext = InstrumentationRegistry.getInstrumentation().targetContext + assertEquals("de.asaril.bletail", appContext.packageName) + } +} diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..c10ffd8 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/java/de/asaril/bletail/MainActivity.kt b/app/src/main/java/de/asaril/bletail/MainActivity.kt new file mode 100644 index 0000000..b239a80 --- /dev/null +++ b/app/src/main/java/de/asaril/bletail/MainActivity.kt @@ -0,0 +1,231 @@ +package de.asaril.bletail + +import android.bluetooth.* +import android.bluetooth.le.ScanCallback +import android.bluetooth.le.ScanResult +import android.content.Context +import android.content.Intent +import android.graphics.Color +import android.os.Bundle +import android.util.Log +import android.view.Menu +import android.view.MenuItem +import android.widget.LinearLayout +import androidx.appcompat.app.AppCompatActivity +import kotlinx.android.synthetic.main.activity_main.* +import java.util.* + + +const val END: Byte = 0xC0.toByte() +const val ESC: Byte = 0xDB.toByte() +const val ESC_END: Byte = 0xDC.toByte() +const val ESC_ESC: Byte = 0xDD.toByte() + +class MainActivity : AppCompatActivity() { + + private val LED_COUNT: Int = 40 + + private val requestEnableBt: Int = 1 + //private var bleTailDevice:BluetoothDevice? = null + private val uartUUID = UUID.fromString("6E400001-B5A3-F393-E0A9-E50E24DCCA9E") + private val rxUUID = UUID.fromString("6E400002-B5A3-F393-E0A9-E50E24DCCA9E") + private val txUUID = UUID.fromString("6E400003-B5A3-F393-E0A9-E50E24DCCA9E") + private val cccdUUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb") + + var bleTailGatt: BluetoothGatt? = null + var rxChar: BluetoothGattCharacteristic? = null + var txChar: BluetoothGattCharacteristic? = null + var segments: MutableList? = null + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + setSupportActionBar(toolbar) + + val bluetoothManager: BluetoothManager = + getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager + val bluetoothAdapter: BluetoothAdapter = bluetoothManager.adapter + + if (!bluetoothAdapter.isEnabled) { + val enableIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE) + 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) + + result.device.connectGatt( + applicationContext, + true, + object : BluetoothGattCallback() { + override fun onConnectionStateChange( + gatt: BluetoothGatt?, + status: Int, + newState: Int + ) { + super.onConnectionStateChange(gatt, status, newState) + + if (newState == BluetoothGatt.STATE_CONNECTED) { + gatt!!.discoverServices() + bleTailGatt = gatt + } + } + + override fun onServicesDiscovered(gatt: BluetoothGatt?, status: Int) { + super.onServicesDiscovered(gatt, status) + + rxChar = gatt!!.getService(uartUUID).getCharacteristic(rxUUID) + + if (rxChar == null) { + Log.e("bleTail", "Rx characteristic not found!") + } + + txChar = gatt.getService(uartUUID).getCharacteristic(txUUID) + + if (txChar == null) { + Log.e("bleTail", "Tx characteristic not found!") + } else { + gatt.setCharacteristicNotification(txChar, true) + + val descriptor = txChar!!.getDescriptor(cccdUUID) + descriptor.value = + BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE + gatt.writeDescriptor(descriptor) + + onConnected() + } + } + + override fun onCharacteristicRead( + gatt: BluetoothGatt, + characteristic: BluetoothGattCharacteristic, + status: Int + ) { + if (status == BluetoothGatt.GATT_SUCCESS) { + handleUpdate(characteristic) + } + } + + override fun onCharacteristicChanged( + gatt: BluetoothGatt, + characteristic: BluetoothGattCharacteristic + ) { + handleUpdate(characteristic) + } + + fun handleUpdate(characteristic: BluetoothGattCharacteristic) { + if (characteristic.uuid == txUUID) { + Log.d("bleTail", "Received TX: %d${characteristic.value}") + } + } + }) + } + } + }) + } + + private fun onConnected() { + segments = MutableList(5, init = { + SegmentCardView(this, it, 0, LED_COUNT - 1, fx.Fx.Mode.THEATER_CHASE_RAINBOW, Color(), Color(), Color(), 0x0800, false) + }) + + for (s in segments!!) { + s.sendCallback = this::sendToBleUart + } + } + + override fun onDestroy() { + segments = null + bleTailGatt?.disconnect() + super.onDestroy() + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + // Inflate the menu; this adds items to the action bar if it is present. + menuInflater.inflate(R.menu.main_menu, menu) + return true + } + + private fun updateSegmentCards(count: Int) { + val r: fx.Fx.Root.Builder = fx.Fx.Root.newBuilder() + val m = fx.Fx.setNumSegments_msg.newBuilder() + m.numSegments = count + r.setNumSegments = m.build() + sendToBleUart(r.build().toByteArray()) + + val segLength: Int = LED_COUNT / count + val segmentListLayout = findViewById(R.id.segmentList) + + for (i in 0 until count) { + segments!![i].start = segLength * i + segments!![i].end = if (i == count - 1) { + LED_COUNT - 1 + } else { + (segLength * (i + 1) - 1) + } + segments!![i].sendSetSegment() + } + + while (segmentListLayout.childCount > count) { + val ind = segmentListLayout.childCount - 1 + segmentListLayout.removeViewAt(ind) + } + while (segmentListLayout.childCount < count) { + val ind = segmentListLayout.childCount + segmentListLayout.addView(segments!![ind], ind) + } + } + + private fun encodeSlip(payload: ByteArray): ByteArray { + var output = ByteArray(0) + for (b in payload) { + when (b) { + END -> { + output += ESC + output += ESC_END + } + ESC -> { + output += ESC + output += ESC_ESC + } + else -> output += b + } + } + output += END + return output + } + + fun powerOffClick(item: MenuItem) { + val r: fx.Fx.Root.Builder = fx.Fx.Root.newBuilder() + r.halt = fx.Fx.halt_msg.newBuilder().build() + val msgRaw = r.build().toByteArray() + sendToBleUart(msgRaw) + } + + fun segCountClick(item: MenuItem) { + updateSegmentCards( + when (item.itemId) { + R.id.segCount1 -> 1 + R.id.segCount2 -> 2 + R.id.segCount3 -> 3 + R.id.segCount5 -> 5 + else -> 1 + } + ) + } + + fun sendToBleUart(msgRaw: ByteArray) { + val arr: ByteArray = encodeSlip(msgRaw) + fun ByteArray.toHexString() = joinToString("") { "%02x".format(it) } + Log.i("BLEtail", "tx:" + arr.toHexString()) + this.rxChar!!.value = arr + Log.i("bleTail", this.bleTailGatt!!.writeCharacteristic(this.rxChar!!).toString()) + } + + +} diff --git a/app/src/main/java/de/asaril/bletail/SegmentCardView.kt b/app/src/main/java/de/asaril/bletail/SegmentCardView.kt new file mode 100644 index 0000000..d67b648 --- /dev/null +++ b/app/src/main/java/de/asaril/bletail/SegmentCardView.kt @@ -0,0 +1,196 @@ +package de.asaril.bletail + +import android.content.Context +import android.graphics.Color +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.* +import androidx.cardview.widget.CardView +import fx.Fx + +/** + * TODO: document your custom view class. + */ +class SegmentCardView : CardView { + + private var viewText: TextView? = null + private var viewMode: Spinner? = null + private var viewCol0: ImageButton? = null + private var viewCol1: ImageButton? = null + private var viewCol2: ImageButton? = null + private var viewGuideline: androidx.constraintlayout.widget.Guideline? = null + private var viewSpeed: SeekBar? = null + private var viewReverse: ToggleButton? = null + + + var index: Int = 0 + var start: Int = 0 + var end: Int = 0 + var mode: Fx.Mode = Fx.Mode.STATIC + var color1: Color = Color.valueOf(Color.RED) + var color2: Color = Color.valueOf(Color.BLACK) + var color3: Color = Color.valueOf(Color.BLACK) + var speed: Int = 0 + var reverse: Boolean = false + + var sendCallback: ((ByteArray) -> Unit)? = null + + private fun Color.toWrgb() = toArgb().and(0x00FFFFFF) + + private var ctx:Context? = null + + fun sendSetSegment() { + val r = Fx.Root.newBuilder() + val m = Fx.setSegment_msg.newBuilder() + m.segment = this.index + m.start = this.start + m.end = this.end + m.mode = this.mode + val mc = Fx.MultiColor.newBuilder() + mc.col1 = this.color1.toWrgb() + mc.col2 = this.color2.toWrgb() + mc.col3 = this.color3.toWrgb() + val c = Fx.ColorType.newBuilder() + c.multiColor = mc.build() + m.color = c.build() + m.speed = this.speed + val o = Fx.Options.newBuilder() + o.reverse = this.reverse + o.fadeRate = Fx.FadeRate.FADE_RATE_MEDIUM + o.gammaCorrect = false + o.size = Fx.Size.SIZE_SMALL + m.options = o.build() + r.setSegment = m.build() + sendCallback!!(r.build().toByteArray()) + } + + fun sendSetMode() { + val r = Fx.Root.newBuilder() + val m = Fx.setMode_msg.newBuilder() + m.segment = this.index + m.mode = this.mode + r.setMode = m.build() + sendCallback!!(r.build().toByteArray()) + } + + fun sendSetSpeed() { + val r = Fx.Root.newBuilder() + val m = Fx.setSpeed_msg.newBuilder() + m.segment = this.index + m.speed = this.speed + r.setSpeed = m.build() + sendCallback!!(r.build().toByteArray()) + } + + fun sendSetColor() { + val r = Fx.Root.newBuilder() + val m = Fx.setColor_msg.newBuilder() + m.segment = this.index + val mc = Fx.MultiColor.newBuilder() + mc.col1 = this.color1.toWrgb() + mc.col2 = this.color2.toWrgb() + mc.col3 = this.color3.toWrgb() + val c = Fx.ColorType.newBuilder() + c.multiColor = mc.build() + m.color = c.build() + r.setColor = m.build() + sendCallback!!(r.build().toByteArray()) + } + + constructor( + context: Context, + index: Int, + start: Int, + end: Int, + mode: Fx.Mode, + color1: Color, + color2: Color, + color3: Color, + speed: Int, + reverse: Boolean + ) : super(context) { + this.start = start + this.index = index + this.start = start + this.end = end + this.mode = mode + this.color1 = color1 + this.color2 = color2 + this.color3 = color3 + this.speed = speed + this.reverse = reverse + init(context, null, 0) + } + + constructor(context: Context) : super(context) { + init(context, null, 0) + } + + constructor(context: Context, attrs: AttributeSet) : super(context, attrs) { + init(context, attrs, 0) + } + + constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) { + init(context, attrs, defStyle) + } + + private fun init(context: Context, attrs: AttributeSet?, defStyle: Int) { + ctx=context + + // Load attributes + val a = context.obtainStyledAttributes( + attrs, R.styleable.SegmentCardView, defStyle, 0 + ) + + + val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater + inflater.inflate(R.layout.segment_card_view, this) + + a.recycle() + } + + override fun onFinishInflate() { + super.onFinishInflate() + + viewText = this.findViewById(R.id.segText) + viewMode = this.findViewById(R.id.segMode) + viewCol0 = this.findViewById(R.id.segCol0) + viewCol1 = this.findViewById(R.id.segCol1) + viewCol2 = this.findViewById(R.id.segCol2) + viewGuideline = this.findViewById(R.id.segGuide) + viewSpeed = this.findViewById(R.id.segSpeed) + viewReverse = this.findViewById(R.id.segReverse) + + viewText!!.text = String.format(resources.getString(R.string.segment), index) + + viewMode!!.adapter = ArrayAdapter(ctx!!, android.R.layout.simple_spinner_item, Fx.Mode.values()) + viewMode!!.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onNothingSelected(parent: AdapterView<*>?) { + return + } + + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + mode = parent!!.getItemAtPosition(position) as Fx.Mode + sendSetMode() + } + } + + viewSpeed!!.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener { + override fun onProgressChanged(var1: SeekBar, var2: Int, var3: Boolean) { + speed = var2 + sendSetSpeed() + } + + override fun onStartTrackingTouch(var1: SeekBar) { + return + } + + override fun onStopTrackingTouch(var1: SeekBar) { + return + } + }) + + } + +} diff --git a/app/src/main/proto/fx.proto b/app/src/main/proto/fx.proto new file mode 100644 index 0000000..a51d5ef --- /dev/null +++ b/app/src/main/proto/fx.proto @@ -0,0 +1,315 @@ +syntax = "proto2"; +package fx; + +// ENUMS + +enum Mode { + STATIC = 0; + BLINK = 1; + BREATH = 2; + COLOR_WIPE = 3; + COLOR_WIPE_INV = 4; + COLOR_WIPE_REV = 5; + COLOR_WIPE_REV_INV = 6; + COLOR_WIPE_RANDOM = 7; + RANDOM_COLOR = 8; + SINGLE_DYNAMIC = 9; + MULTI_DYNAMIC = 10; + RAINBOW = 11; + RAINBOW_CYCLE = 12; + SCAN = 13; + DUAL_SCAN = 14; + FADE = 15; + THEATER_CHASE = 16; + THEATER_CHASE_RAINBOW = 17; + RUNNING_LIGHTS = 18; + TWINKLE = 19; + TWINKLE_RANDOM = 20; + TWINKLE_FADE = 21; + TWINKLE_FADE_RANDOM = 22; + SPARKLE = 23; + FLASH_SPARKLE = 24; + HYPER_SPARKLE = 25; + STROBE = 26; + STROBE_RAINBOW = 27; + MULTI_STROBE = 28; + BLINK_RAINBOW = 29; + CHASE_WHITE = 30; + CHASE_COLOR = 31; + CHASE_RANDOM = 32; + CHASE_RAINBOW = 33; + CHASE_FLASH = 34; + CHASE_FLASH_RANDOM = 35; + CHASE_RAINBOW_WHITE = 36; + CHASE_BLACKOUT = 37; + CHASE_BLACKOUT_RAINBOW = 38; + COLOR_SWEEP_RANDOM = 39; + RUNNING_COLOR = 40; + RUNNING_RED_BLUE = 41; + RUNNING_RANDOM = 42; + LARSON_SCANNER = 43; + COMET = 44; + FIREWORKS = 45; + FIREWORKS_RANDOM = 46; + MERRY_CHRISTMAS = 47; + FIRE_FLICKER = 48; + FIRE_FLICKER_SOFT = 49; + FIRE_FLICKER_INTENSE = 50; + CIRCUS_COMBUSTUS = 51; + HALLOWEEN = 52; + BICOLOR_CHASE = 53; + TRICOLOR_CHASE = 54; + ICU = 55; + CUSTOM_0 = 56; + CUSTOM_1 = 57; + CUSTOM_2 = 58; + CUSTOM_3 = 59; +} + +enum FadeRate { + FADE_RATE_XFAST = 1; + FADE_RATE_FAST = 2; + FADE_RATE_MEDIUM = 3; + FADE_RATE_SLOW = 4; + FADE_RATE_XSLOW = 5; + FADE_RATE_XXSLOW = 6; + FADE_RATE_GLACIAL = 7; +} + +enum Size { + SIZE_SMALL = 0; + SIZE_MEDIUM = 1; + SIZE_LARGE = 2; + SIZE_XLARGE = 3; +} + +// TYPES + +message RGB { + required uint32 r = 1; + required uint32 g = 2; + required uint32 b = 3; +} + +message RGBW { + required uint32 r = 1; + required uint32 g = 2; + required uint32 b = 3; + required uint32 w = 4; +} + +message MultiColor { + required fixed32 col1 = 1; + required fixed32 col2 = 2; + required fixed32 col3 = 3; +} + +message ColorType { + oneof colorTypes { + RGB rgb = 1; + RGBW rgbw = 2; + fixed32 color = 3; + MultiColor multiColor = 4; + } +} + +message Options { + required bool reverse = 1; + required FadeRate fadeRate = 2; + required bool gammaCorrect = 3; + required Size size = 4; +} + +// MESSAGES + +message init_msg { + //(void), +} +message service_msg { + //(void), +} +message start_msg { + //(void), +} +message stop_msg { + //(void), +} +message pause_msg { + //(void), +} +message resume_msg { + //(void), +} +message strip_off_msg { + //(void), +} +message fade_out_msg { + optional uint32 fadeTime = 1; +} +message setMode_msg { + optional uint32 segment = 1; + required Mode mode = 2; +} +message setOptions_msg { + required uint32 segment = 1; + required Options options = 2; +} +message setSpeed_msg { + optional uint32 segment = 1; + required uint32 speed = 2; +} +message increaseSpeed_msg { + required uint32 step = 1; +} +message decreaseSpeed_msg { + required uint32 step = 1; +} +message setColor_msg { + optional uint32 segment = 1; + required ColorType color = 2; +} +message setBrightness_msg { + required uint32 brightness = 1; +} +message increaseBrightness_msg { + required uint32 step = 1; +} +message decreaseBrightness_msg { + required uint32 step = 1; +} +message setLength_msg { + required uint32 numPixels = 1; +} +message increaseLength_msg { + required uint32 step = 1; +} +message decreaseLength_msg { + required uint32 step = 1; +} +message trigger_msg { + //(void), +} +message setNumSegments_msg { + required uint32 numSegments = 1; +} +message setSegment_msg { + required uint32 segment = 1; + required uint32 start = 2; + required uint32 end = 3; + required Mode mode = 4; + required ColorType color = 5; + required uint32 speed = 6; + required Options options = 7; +} +message resetSegments_msg { + //(), +} +message resetSegmentRuntimes_msg { + //(), +} +message resetSegmentRuntime_msg { + required uint32 segment = 1; +} +message setPixelColor_msg { + required uint32 offset = 1; + required ColorType color = 2; +} +message copyPixels_msg { + required uint32 destination = 1; + required uint32 source = 2; + required uint32 count = 3; +} +message display_msg { + required uint32 offset = 1; + repeated fixed32 color = 2; +} +message show_msg { + //(void); +} + +message halt_msg { + //(void); +} + + +// MAIN MESSAGE + +message Root { + oneof msg { + init_msg init = 1; + start_msg start = 2; + stop_msg stop = 3; + pause_msg pause = 4; + resume_msg resume = 5; + strip_off_msg strip_off = 6; + fade_out_msg fade_out = 7; + setMode_msg setMode = 8; + setOptions_msg setOptions = 9; + setSpeed_msg setSpeed = 10; + increaseSpeed_msg increaseSpeed = 11; + decreaseSpeed_msg decreaseSpeed = 12; + setColor_msg setColor = 13; + setBrightness_msg setBrightness = 14; + increaseBrightness_msg increaseBrightness = 15; + decreaseBrightness_msg decreaseBrightness = 16; + setLength_msg setLength = 17; + increaseLength_msg increaseLength = 18; + decreaseLength_msg decreaseLength = 19; + trigger_msg trigger = 20; + setNumSegments_msg setNumSegments = 21; + setSegment_msg setSegment = 22; + resetSegments_msg resetSegments = 23; + resetSegmentRuntimes_msg resetSegmentRuntimes = 24; + resetSegmentRuntime_msg resetSegmentRuntime = 25; + setPixelColor_msg setPixelColor = 26; + copyPixels_msg copyPixels = 27; + display_msg display = 28; + show_msg show = 29; + halt_msg halt = 30; + } +} + +//ORG +// init(void), +// service(void), +// start(void), +// stop(void), +// pause(void), +// resume(void), +// strip_off(void), +// fade_out(void), +// fade_out(uint32_t), +// setMode(uint8_t m), +// setMode(uint8_t seg, uint8_t m), +// setOptions(uint8_t seg, uint8_t o), +// setCustomMode(uint16_t (*p)()), +// setCustomShow(void (*p)()), +// setSpeed(uint16_t s), +// setSpeed(uint8_t seg, uint16_t s), +// increaseSpeed(uint8_t s), +// decreaseSpeed(uint8_t s), +// setColor(uint8_t r, uint8_t g, uint8_t b), +// setColor(uint8_t r, uint8_t g, uint8_t b, uint8_t w), +// setColor(uint32_t c), +// setColor(uint8_t seg, uint32_t c), +// setColors(uint8_t seg, uint32_t* c), +// setBrightness(uint8_t b), +// increaseBrightness(uint8_t s), +// decreaseBrightness(uint8_t s), +// setLength(uint16_t b), +// increaseLength(uint16_t s), +// decreaseLength(uint16_t s), +// trigger(void), +// setNumSegments(uint8_t n), +// setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, bool reverse), +// setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, uint32_t color, uint16_t speed, uint8_t options), +// setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint16_t speed, bool reverse), +// setSegment(uint8_t n, uint16_t start, uint16_t stop, uint8_t mode, const uint32_t colors[], uint16_t speed, uint8_t options), +// resetSegments(), +// resetSegmentRuntimes(), +// resetSegmentRuntime(uint8_t), +// setPixelColor(uint16_t n, uint32_t c), +// setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b), +// setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b, uint8_t w), +// copyPixels(uint16_t d, uint16_t s, uint16_t c), +// show(void); \ No newline at end of file diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..1f6bb29 --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..0d025f9 --- /dev/null +++ b/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..eef9850 --- /dev/null +++ b/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,536 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/sample_segment_card_view.xml b/app/src/main/res/layout/sample_segment_card_view.xml new file mode 100644 index 0000000..a0c98c6 --- /dev/null +++ b/app/src/main/res/layout/sample_segment_card_view.xml @@ -0,0 +1,16 @@ + + + + + + + diff --git a/app/src/main/res/layout/segment_card_view.xml b/app/src/main/res/layout/segment_card_view.xml new file mode 100644 index 0000000..8ddfd7c --- /dev/null +++ b/app/src/main/res/layout/segment_card_view.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/main_menu.xml b/app/src/main/res/menu/main_menu.xml new file mode 100644 index 0000000..6761091 --- /dev/null +++ b/app/src/main/res/menu/main_menu.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..898f3ed Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..dffca36 Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..64ba76f Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..dae5e08 Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..e5ed465 Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..14ed0af Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..b0907ca Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..d8ae031 Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..2c18de9 Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..beed3cd Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/app/src/main/res/values/attrs_segment_card_view.xml b/app/src/main/res/values/attrs_segment_card_view.xml new file mode 100644 index 0000000..c991ce2 --- /dev/null +++ b/app/src/main/res/values/attrs_segment_card_view.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..69b2233 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,6 @@ + + + #008577 + #00574B + #D81B60 + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..da62b5f --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,5 @@ + + 180dp + 16dp + 16dp + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..25e62e4 --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,14 @@ + + BLEtail + Halt + Settings + 3 + 5 + 2 + 1 + Number of segments + Segment %1$d + Segment Color 2 + Segment Color 1 + Segment Color 0 + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..5fb5eb1 --- /dev/null +++ b/app/src/main/res/values/styles.xml @@ -0,0 +1,20 @@ + + + + + + + +