From 03be52c74bfe5f4332feec6b6913c9bcc73baa81 Mon Sep 17 00:00:00 2001 From: Leo CACHEUX Date: Sat, 1 Nov 2025 18:23:56 +0100 Subject: [PATCH 1/3] Use Bytonio to refactor NvpLib without using reflect or JVM features --- gradle/libs.versions.toml | 7 +- nvplib/core/build.gradle.kts | 9 +- .../kotlin/net/cacheux/nvplib/DataReader.kt | 11 +- .../net/cacheux/nvplib/NvpController.kt | 18 ++- .../net/cacheux/nvplib/PayloadFunctions.kt | 20 +-- .../kotlin/net/cacheux/nvplib/PhdManager.kt | 24 ++-- .../net/cacheux/nvplib/TransceiveResult.kt | 4 +- .../net/cacheux/nvplib/annotations/Types.kt | 13 -- .../net/cacheux/nvplib/data/ARequest.kt | 63 +++++---- .../net/cacheux/nvplib/data/AResponse.kt | 15 +- .../kotlin/net/cacheux/nvplib/data/Apdu.kt | 52 ++++--- .../net/cacheux/nvplib/data/ApoepElement.kt | 47 +++---- .../cacheux/nvplib/data/ArgumentsSimple.kt | 17 ++- .../net/cacheux/nvplib/data/Attribute.kt | 44 +++--- .../net/cacheux/nvplib/data/Configuration.kt | 21 ++- .../cacheux/nvplib/data/ConfirmedAction.kt | 21 ++- .../net/cacheux/nvplib/data/DataApdu.kt | 130 ++++++++++++------ .../nvplib/data/DummyBinarySerializable.kt | 12 ++ .../net/cacheux/nvplib/data/Encodable.kt | 70 ---------- .../net/cacheux/nvplib/data/EventReport.kt | 41 +++--- .../net/cacheux/nvplib/data/EventRequest.kt | 18 ++- .../cacheux/nvplib/data/FullSpecification.kt | 18 +-- .../net/cacheux/nvplib/data/InsulinDose.kt | 44 ++++-- .../net/cacheux/nvplib/data/PhdPacket.kt | 57 ++++---- .../net/cacheux/nvplib/data/SegmentEntry.kt | 30 ++-- .../net/cacheux/nvplib/data/SegmentInfo.kt | 17 ++- .../cacheux/nvplib/data/SegmentInfoList.kt | 18 ++- .../net/cacheux/nvplib/data/SegmentInfoMap.kt | 21 ++- .../net/cacheux/nvplib/data/Specification.kt | 14 +- .../net/cacheux/nvplib/data/T4Update.kt | 22 ++- .../nvplib/data/TriggerSegmentDataXfer.kt | 25 ++-- .../net/cacheux/nvplib/utils/ByteUtils.kt | 87 ++---------- .../net/cacheux/nvplib/data/DataApduTest.kt | 24 ++-- .../net/cacheux/nvplib/data/EncodableTest.kt | 45 ------ .../net/cacheux/nvplib/utils/ByteUtilsTest.kt | 39 +----- 35 files changed, 506 insertions(+), 612 deletions(-) delete mode 100644 nvplib/core/src/main/kotlin/net/cacheux/nvplib/annotations/Types.kt create mode 100644 nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/DummyBinarySerializable.kt delete mode 100644 nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Encodable.kt delete mode 100644 nvplib/core/src/test/kotlin/net/cacheux/nvplib/data/EncodableTest.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1b3eb6f..b630e72 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -java = "17" +java = "21" android-minSdk = "24" android-compileSdk = "36" agp = "8.13.2" @@ -10,6 +10,7 @@ coroutines = "1.10.2" room = "2.8.2" sqlite = "2.6.1" androidx-datastore = "1.1.7" +bytonio = "0.0.1" [plugins] ksp = { id = "com.google.devtools.ksp", version = "2.1.21-2.0.1" } @@ -48,6 +49,10 @@ hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt" hilt-android-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" } hilt-android-testing = { module = "com.google.dagger:hilt-android-testing", version.ref = "hilt" } +# Bytonio +bytonio-core = { module = "net.cacheux.bytonio:bytonio-core", version.ref = "bytonio" } +bytonio-processor = { module = "net.cacheux.bytonio:bytonio-processor", version.ref = "bytonio" } + # Testing junit = { group = "junit", name = "junit", version = "4.13.2" } androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version = "1.3.0" } diff --git a/nvplib/core/build.gradle.kts b/nvplib/core/build.gradle.kts index d754192..8be9c3c 100644 --- a/nvplib/core/build.gradle.kts +++ b/nvplib/core/build.gradle.kts @@ -3,6 +3,7 @@ plugins { id("maven-publish") alias(libs.plugins.kotlin.jvm) alias(libs.plugins.dokka) + alias(libs.plugins.ksp) signing } @@ -14,8 +15,14 @@ java { withSourcesJar() } +ksp { + arg("bytonio.packageName", "net.cacheux.nvplib.generated") + arg("bytonio.dataSizeFormat", "short") +} + dependencies { - implementation(kotlin("reflect")) + api(libs.bytonio.core) + ksp(libs.bytonio.processor) testImplementation(libs.junit) testImplementation(project(":nvplib:testing")) diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/DataReader.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/DataReader.kt index d6bf4d0..48613c7 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/DataReader.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/DataReader.kt @@ -1,6 +1,6 @@ package net.cacheux.nvplib -import java.nio.ByteBuffer +import net.cacheux.bytonio.utils.reader import kotlin.experimental.and /** @@ -27,13 +27,12 @@ fun DataReader.readResult(command: ByteArray): TransceiveResult { onDataSent(command) val data = readData(command) onDataReceived(data) - val buffer = ByteBuffer.wrap(data) + val buffer = data.reader() val dataSize = buffer.remaining() - 2 - val result = ByteArray(dataSize) - buffer.get(result, 0, dataSize) + val result = buffer.readByteArray(dataSize) return TransceiveResult( - content = ByteBuffer.wrap(result), - success = (buffer.getShort() and 0xffff.toShort()) == NvpController.COMMAND_COMPLETED + content = result.reader(), + success = (buffer.readShort().toShort() and 0xffff.toShort()) == NvpController.COMMAND_COMPLETED ) } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/NvpController.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/NvpController.kt index aac9aea..5fc8636 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/NvpController.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/NvpController.kt @@ -3,6 +3,7 @@ package net.cacheux.nvplib import net.cacheux.nvplib.data.ARequest import net.cacheux.nvplib.data.AResponse import net.cacheux.nvplib.data.Apdu +import net.cacheux.nvplib.data.ApduDeserializer import net.cacheux.nvplib.data.ApoepElement.Companion.APOEP import net.cacheux.nvplib.data.DataApdu import net.cacheux.nvplib.data.EventReport @@ -16,8 +17,6 @@ import net.cacheux.nvplib.data.SegmentInfoList import net.cacheux.nvplib.data.T4Update import net.cacheux.nvplib.data.dataApdu import net.cacheux.nvplib.data.eventReport -import net.cacheux.nvplib.utils.wrap -import java.nio.ByteBuffer /** * Implement the full pen reading protocol. @@ -59,16 +58,16 @@ class NvpController( stopCondition: StopCondition = noStopCondition ): PenResult { val lengthResult = dataReader.readResult(createReadPayload(0, 2)) - val length = lengthResult.content.getShort().toInt() + val length = lengthResult.content.readShort().toInt() val fullRead = dataReader.readResult(createReadPayload(2, length)) val ack = T4Update(byteArrayOf(0xd0.toByte(), 0x00, 0x00)) dataReader.readResult(ack.toByteArray()) - val phdPacket = PhdPacket.fromByteBuffer(fullRead.content) + val phdPacket = PhdPacket.fromByteArrayReader(fullRead.content) - val apdu = Apdu.fromByteBuffer(ByteBuffer.wrap(phdPacket.content)) + val apdu = ApduDeserializer.fromByteArray(phdPacket.content) val aRequest = apdu.payload as ARequest @@ -80,7 +79,7 @@ class NvpController( ) val result = phdManager.sendApduRequest(sendApdu) - val resultApdu = Apdu.fromByteBuffer(result.wrap()) + val resultApdu = ApduDeserializer.fromByteArray(result) val dataApdu = (resultApdu.payload as DataApdu) val configuration = (dataApdu.payload as EventReport).configuration @@ -95,7 +94,7 @@ class NvpController( val doseList = mutableListOf() val storageArray = phdManager.sendApduRequest(confirmedAction(dataApdu.invokeId)) - val storage = Apdu.fromByteBuffer(storageArray.wrap()) + val storage = ApduDeserializer.fromByteArray(storageArray) (storage.payload as DataApdu).let { dataApdu -> (dataApdu.payload as SegmentInfoList).let { segmentInfoList -> @@ -131,8 +130,7 @@ class NvpController( invokeId = invokeId, segment = segment.instnum )) - Apdu.fromByteBuffer(xferArray.wrap()) // xfer - + ApduDeserializer.fromByteArray(xferArray) // xfer var result = phdManager.sendEmptyRequest() var currentInstance: Int @@ -145,7 +143,7 @@ class NvpController( result = phdManager.sendEmptyRequest() } - val logApdu = Apdu.fromByteBuffer(result.wrap()) + val logApdu = ApduDeserializer.fromByteArray(result) logApdu.eventReport()?.let { eventReport -> doseList.addAll(eventReport.insulinDoses) diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/PayloadFunctions.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/PayloadFunctions.kt index 05e3c1d..d6efb42 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/PayloadFunctions.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/PayloadFunctions.kt @@ -1,5 +1,6 @@ package net.cacheux.nvplib +import net.cacheux.bytonio.utils.writer import net.cacheux.nvplib.data.Apdu import net.cacheux.nvplib.data.Apdu.Companion.PRST import net.cacheux.nvplib.data.ArgumentsSimple @@ -16,7 +17,6 @@ import net.cacheux.nvplib.data.EventReport.Companion.MDC_NOTI_SEGMENT_DATA import net.cacheux.nvplib.data.EventRequest import net.cacheux.nvplib.utils.putUnsignedByte import net.cacheux.nvplib.utils.putUnsignedShort -import java.nio.ByteBuffer fun applicationSelect() = createTranceivePayload(NvpController.BY_NAME, 0, NvpController.NDEF_TAG_APPLICATION_SELECT, true) @@ -28,26 +28,26 @@ fun ndefSelect() = createTranceivePayload(0, NvpController.FIRST_ONLY, NvpController.NDEF_SELECT) fun createReadPayload(offset: Int, length: Int): ByteArray { - return ByteBuffer.allocate(5).apply { + return ByteArray(5).writer().apply { putUnsignedByte(NvpController.CLA) putUnsignedByte(NvpController.INS_RB) putUnsignedShort(offset) putUnsignedByte(length) - }.array() + }.byteArray } private fun createTranceivePayload(p1: Int, p2: Int, data: ByteArray, le: Boolean = false): ByteArray { - return ByteBuffer.allocate(data.size + if (le) 6 else 5).apply { + return ByteArray(data.size + if (le) 6 else 5).writer().apply { putUnsignedByte(NvpController.CLA) putUnsignedByte(NvpController.INS_SL) putUnsignedByte(p1) putUnsignedByte(p2) putUnsignedByte(data.size) - put(data) + writeByteArray(data) if (le) { putUnsignedByte(0x00) } - }.array() + }.byteArray } /** @@ -64,10 +64,10 @@ fun retrieveInformation(invokeId: Int, config: Configuration) = handle = 0, currentTime = 0, type = MDC_NOTI_CONFIG, - data = ByteBuffer.allocate(4).apply { + data = ByteArray(4).writer().apply { putUnsignedShort(config.id) putUnsignedShort(0) - }.array() + }.byteArray ) ) ) @@ -125,7 +125,7 @@ fun confirmedXfer(invokeId: Int, data: ByteArray) = ) fun eventRequestData(instance: Int, index: Int, count: Int, confirmed: Boolean): ByteArray = - ByteBuffer.allocate(12).apply { + ByteArray(12).writer().apply { putUnsignedShort(instance) putUnsignedShort(0) putUnsignedShort(index) @@ -133,4 +133,4 @@ fun eventRequestData(instance: Int, index: Int, count: Int, confirmed: Boolean): putUnsignedShort(count) putUnsignedByte(0x00) // block putUnsignedByte(if (confirmed) 0x80 else 0) - }.array() \ No newline at end of file + }.byteArray \ No newline at end of file diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/PhdManager.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/PhdManager.kt index 909dcd2..04c843d 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/PhdManager.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/PhdManager.kt @@ -1,14 +1,15 @@ package net.cacheux.nvplib +import net.cacheux.bytonio.BinarySerializable +import net.cacheux.bytonio.utils.reader +import net.cacheux.bytonio.utils.writer import net.cacheux.nvplib.data.Apdu +import net.cacheux.nvplib.data.ApduDeserializer import net.cacheux.nvplib.data.DataApdu -import net.cacheux.nvplib.data.Encodable import net.cacheux.nvplib.data.PhdPacket import net.cacheux.nvplib.data.T4Update import net.cacheux.nvplib.utils.decomposeNumber import net.cacheux.nvplib.utils.getUnsignedShort -import net.cacheux.nvplib.utils.wrap -import java.nio.ByteBuffer class PhdManager( private val dataReader: DataReader @@ -39,16 +40,15 @@ class PhdManager( val reads = decomposeNumber(len, MAX_READ_SIZE) - val fullResult = ByteBuffer.allocate(len) + val fullResult = ByteArray(len) + val fullResultWriter = fullResult.writer() reads.forEachIndexed { index, i -> val readResult = request(createReadPayload(2 + index * MAX_READ_SIZE, i)) - fullResult.put(readResult.content) + fullResultWriter.writeByteArray(readResult.content.byteArray) } - fullResult.rewind() - - val resultPhd = PhdPacket.fromByteBuffer(fullResult) + val resultPhd = PhdPacket.fromByteArrayReader(fullResult.reader()) sequence = resultPhd.seq + 1 @@ -60,17 +60,17 @@ class PhdManager( fun sendApduRequest(apdu: Apdu) = sendRequest(apdu.toByteArray()) - fun decodeDataApduRequest(inputApdu: Apdu): T { + fun decodeDataApduRequest(inputApdu: Apdu): T { val byteArray = sendApduRequest(inputApdu) - val outputApdu = Apdu.fromByteBuffer(byteArray.wrap()) + val outputApdu = ApduDeserializer.fromByteArray(byteArray) (outputApdu.payload as DataApdu).let { dataApdu -> return dataApdu.payload as T } } - fun decodeRequest(input: ByteArray): T { + fun decodeRequest(input: ByteArray): T { val output = sendRequest(input) - val apdu = Apdu.fromByteBuffer(output.wrap()) + val apdu = ApduDeserializer.fromByteArray(output) (apdu.payload as DataApdu).let { dataApdu -> return dataApdu.payload as T } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/TransceiveResult.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/TransceiveResult.kt index 79d0009..cf7461e 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/TransceiveResult.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/TransceiveResult.kt @@ -1,8 +1,8 @@ package net.cacheux.nvplib -import java.nio.ByteBuffer +import net.cacheux.bytonio.utils.ByteArrayReader data class TransceiveResult( - val content: ByteBuffer, + val content: ByteArrayReader, val success: Boolean ) diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/annotations/Types.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/annotations/Types.kt deleted file mode 100644 index 365d371..0000000 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/annotations/Types.kt +++ /dev/null @@ -1,13 +0,0 @@ -package net.cacheux.nvplib.annotations - -@Target(AnnotationTarget.PROPERTY) -@Retention(AnnotationRetention.RUNTIME) -annotation class IsShort - -@Target(AnnotationTarget.PROPERTY) -@Retention(AnnotationRetention.RUNTIME) -annotation class IsByte - -@Target(AnnotationTarget.PROPERTY) -@Retention(AnnotationRetention.RUNTIME) -annotation class IsInt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ARequest.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ARequest.kt index 816694a..aaa82fd 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ARequest.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ARequest.kt @@ -1,37 +1,48 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsInt -import net.cacheux.nvplib.annotations.IsShort +import net.cacheux.bytonio.BinaryDeserializer +import net.cacheux.bytonio.BinarySerializable +import net.cacheux.bytonio.annotations.DataObject +import net.cacheux.bytonio.annotations.Deserializer +import net.cacheux.bytonio.annotations.EncodeAsShort +import net.cacheux.bytonio.utils.ByteArrayReader +import net.cacheux.bytonio.utils.reader import net.cacheux.nvplib.data.ApoepElement.Companion.APOEP -import net.cacheux.nvplib.utils.getByteArray -import net.cacheux.nvplib.utils.getUnsignedInt -import net.cacheux.nvplib.utils.getUnsignedShort -import java.nio.ByteBuffer +import net.cacheux.nvplib.generated.ARequestSerializer +import net.cacheux.nvplib.generated.ApoepElementDeserializer +@DataObject +@Deserializer(ARequestDeserializer::class) data class ARequest( - @IsInt val protocol: Int, - @IsInt val version: Int, - @IsShort val elements: Int, + val protocol: Int, + val version: Int, + @EncodeAsShort val elements: Int, val apoep: ApoepElement -): Encodable() { - companion object { - fun fromByteBuffer(data: ByteBuffer): ARequest { - val version = data.getUnsignedInt() - val elements = data.getUnsignedShort() - data.getUnsignedShort() // len +): BinarySerializable { + override fun getBinarySize() = ARequestSerializer.getBinarySize(this) + override fun toByteArray() = ARequestSerializer.toByteArray(this) +} - var apoep: ApoepElement? = null - repeat(elements) { - val protocol = data.getUnsignedShort() - val bytes = data.getByteArray() - if (protocol == APOEP) { - apoep = ApoepElement.fromByteBuffer(ByteBuffer.wrap(bytes)) - } - } +object ARequestDeserializer: BinaryDeserializer { + override fun fromByteArray(byteArray: ByteArray) = + fromByteArrayReader(byteArray.reader()) + + override fun fromByteArrayReader(reader: ByteArrayReader): ARequest { + val version = reader.readInt() + val elements = reader.readShort() + reader.readShort() // len - apoep?.let { - return ARequest(protocol = APOEP, version, elements, it) - } ?: throw IllegalStateException("APOEP packet not found") + var apoep: ApoepElement? = null + repeat(elements) { + val protocol = reader.readShort() + val bytes = reader.readByteArray(reader.readShort()) + if (protocol == APOEP) { + apoep = ApoepElementDeserializer.fromByteArray(bytes) + } } + + apoep?.let { + return ARequest(protocol = APOEP, version, elements, it) + } ?: throw IllegalStateException("APOEP packet not found") } } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/AResponse.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/AResponse.kt index 2998bdb..d90134a 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/AResponse.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/AResponse.kt @@ -1,13 +1,18 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsShort +import net.cacheux.bytonio.BinarySerializable +import net.cacheux.bytonio.annotations.DataObject +import net.cacheux.bytonio.annotations.EncodeAsShort import net.cacheux.nvplib.data.ApoepElement.Companion.SYS_TYPE_MANAGER +import net.cacheux.nvplib.generated.AResponseSerializer +@DataObject data class AResponse( - @IsShort var result: Int, - @IsShort var protocol: Int, + @EncodeAsShort var result: Int, + @EncodeAsShort var protocol: Int, var apoep: ApoepElement -): Encodable() { +): BinarySerializable { + override fun getBinarySize() = AResponseSerializer.getBinarySize(this) override fun toByteArray(): ByteArray { apoep.recMode = 0 apoep.configId = 0 @@ -15,6 +20,6 @@ data class AResponse( apoep.listCount = 0 apoep.listLen = 0 - return super.toByteArray() + return AResponseSerializer.toByteArray(this) } } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Apdu.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Apdu.kt index 00cb9df..2e6215f 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Apdu.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Apdu.kt @@ -1,13 +1,26 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsShort -import net.cacheux.nvplib.utils.getUnsignedShort -import java.nio.ByteBuffer +import net.cacheux.bytonio.BinaryDeserializer +import net.cacheux.bytonio.BinarySerializable +import net.cacheux.bytonio.annotations.DataObject +import net.cacheux.bytonio.annotations.Deserializer +import net.cacheux.bytonio.annotations.EncodeAsShort +import net.cacheux.bytonio.utils.ByteArrayReader +import net.cacheux.bytonio.utils.reader +import net.cacheux.nvplib.data.Apdu.Companion.AARE +import net.cacheux.nvplib.data.Apdu.Companion.AARQ +import net.cacheux.nvplib.data.Apdu.Companion.ABRT +import net.cacheux.nvplib.data.Apdu.Companion.PRST +import net.cacheux.nvplib.data.Apdu.Companion.RLRE +import net.cacheux.nvplib.data.Apdu.Companion.RLRQ +import net.cacheux.nvplib.generated.ApduSerializer +@DataObject +@Deserializer(ApduDeserializer::class) data class Apdu( - @IsShort val at: Int, - val payload: Encodable -): Encodable() { + @EncodeAsShort val at: Int, + val payload: BinarySerializable +): BinarySerializable { companion object { const val AARQ = 0xE200 const val AARE = 0xE300 @@ -15,20 +28,27 @@ data class Apdu( const val RLRE = 0xE500 const val ABRT = 0xE600 const val PRST = 0xE700 + } + + override fun getBinarySize() = ApduSerializer.getBinarySize(this) + override fun toByteArray() = ApduSerializer.toByteArray(this) +} - fun fromByteBuffer(buffer: ByteBuffer): Apdu { - val at = buffer.getUnsignedShort() - buffer.getUnsignedShort() // payloadLen +object ApduDeserializer: BinaryDeserializer { + override fun fromByteArray(byteArray: ByteArray) = fromByteArrayReader(byteArray.reader()) - val payload = when (at) { - AARQ, AARE -> ARequest.fromByteBuffer(buffer) - PRST -> DataApdu.fromByteBuffer(buffer) - RLRQ, RLRE, ABRT -> Encodable() - else -> throw IllegalStateException("Unknown at value $at") - } + override fun fromByteArrayReader(reader: ByteArrayReader): Apdu { + val at = reader.readShort() + reader.readShort() - return Apdu(at, payload) + val payload = when (at) { + AARQ, AARE -> ARequestDeserializer.fromByteArrayReader(reader) + PRST -> DataApduDeserializer.fromByteArrayReader(reader) + RLRQ, RLRE, ABRT -> DummyBinarySerializable() + else -> throw IllegalStateException("Unknown at value $at") } + + return Apdu(at, payload) } } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ApoepElement.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ApoepElement.kt index 8a832a4..990658d 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ApoepElement.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ApoepElement.kt @@ -1,40 +1,29 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsInt -import net.cacheux.nvplib.annotations.IsShort -import net.cacheux.nvplib.utils.getByteArray -import net.cacheux.nvplib.utils.getUnsignedInt -import net.cacheux.nvplib.utils.getUnsignedShort -import java.nio.ByteBuffer +import net.cacheux.bytonio.BinarySerializable +import net.cacheux.bytonio.annotations.DataObject +import net.cacheux.bytonio.annotations.EncodeAsShort +import net.cacheux.nvplib.generated.ApoepElementSerializer +@DataObject data class ApoepElement( - @IsInt var version: Int, - @IsShort var encoding: Int, - @IsInt var nomenclature: Int, - @IsInt var functional: Int, - @IsInt var systemType: Int, + var version: Int, + @EncodeAsShort var encoding: Int, + var nomenclature: Int, + var functional: Int, + var systemType: Int, var systemId: ByteArray, - @IsShort var configId: Int, - @IsInt var recMode: Int, - @IsShort var listCount: Int, - @IsShort var listLen: Int, -): Encodable() { + @EncodeAsShort var configId: Int, + var recMode: Int, + @EncodeAsShort var listCount: Int, + @EncodeAsShort var listLen: Int, +): BinarySerializable { companion object { const val APOEP = 20601 const val SYS_TYPE_MANAGER = 0x80000000 const val SYS_TYPE_AGENT = 0x00800000 - - fun fromByteBuffer(buffer: ByteBuffer) = ApoepElement( - version = buffer.getUnsignedInt(), - encoding = buffer.getUnsignedShort(), - nomenclature = buffer.getUnsignedInt(), - functional = buffer.getUnsignedInt(), - systemType = buffer.getUnsignedInt(), - systemId = buffer.getByteArray(), - configId = buffer.getUnsignedShort(), - recMode = buffer.getUnsignedInt(), - listCount = buffer.getUnsignedShort(), - listLen = buffer.getUnsignedShort(), - ) } + + override fun getBinarySize() = ApoepElementSerializer.getBinarySize(this) + override fun toByteArray() = ApoepElementSerializer.toByteArray(this) } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ArgumentsSimple.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ArgumentsSimple.kt index 2facbfd..d11f0ed 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ArgumentsSimple.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ArgumentsSimple.kt @@ -1,9 +1,16 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsShort +import net.cacheux.bytonio.BinarySerializable +import net.cacheux.bytonio.annotations.DataObject +import net.cacheux.bytonio.annotations.EncodeAsShort +import net.cacheux.nvplib.generated.ArgumentsSimpleSerializer +@DataObject data class ArgumentsSimple( - @IsShort val handle: Int, - @IsShort val size: Int = 0, - @IsShort val size2: Int = 0, -): Encodable() + @EncodeAsShort val handle: Int, + @EncodeAsShort val size: Int = 0, + @EncodeAsShort val size2: Int = 0, +): BinarySerializable { + override fun getBinarySize() = ArgumentsSimpleSerializer.getBinarySize(this) + override fun toByteArray() = ArgumentsSimpleSerializer.toByteArray(this) +} diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Attribute.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Attribute.kt index e42739c..b559307 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Attribute.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Attribute.kt @@ -1,16 +1,20 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsShort -import net.cacheux.nvplib.utils.getByteArray -import net.cacheux.nvplib.utils.getUnsignedInt -import net.cacheux.nvplib.utils.getUnsignedShort -import net.cacheux.nvplib.utils.wrap -import java.nio.ByteBuffer +import net.cacheux.bytonio.BinaryDeserializer +import net.cacheux.bytonio.annotations.DataObject +import net.cacheux.bytonio.annotations.Deserializer +import net.cacheux.bytonio.annotations.IgnoreEncoding +import net.cacheux.bytonio.utils.ByteArrayReader +import net.cacheux.bytonio.utils.readInt +import net.cacheux.bytonio.utils.readShort +import net.cacheux.bytonio.utils.reader +@DataObject +@Deserializer(AttributeDeserializer::class) data class Attribute( - @IsShort val type: Int, + val type: Int, val data: ByteArray, - val value: Int + @IgnoreEncoding val value: Int = -1 ) { companion object { const val ATTR_SYS_ID = 2436 @@ -40,16 +44,22 @@ data class Attribute( const val ATTR_CLEAR_TIMEOUT = 2659 const val ATTR_TRANSFER_TIMEOUT = 2660 const val ATTR_ENUM_OBS_VAL_BASIC_BIT_STR = 2662 + } +} + +object AttributeDeserializer: BinaryDeserializer { + override fun fromByteArray(byteArray: ByteArray) = + fromByteArrayReader(byteArray.reader()) - fun fromByteBuffer(buffer: ByteBuffer) : Attribute { - val type = buffer.getUnsignedShort() - val data = buffer.getByteArray() - val value = when (data.size) { - 2 -> data.wrap().getUnsignedShort() - 4 -> data.wrap().getUnsignedInt() - else -> -1 - } - return Attribute(type, data, value) + override fun fromByteArrayReader(reader: ByteArrayReader): Attribute { + val type = reader.readShort() + val len = reader.readShort() + val data = reader.readByteArray(len) + val value = when (data.size) { + 2 -> data.readShort() + 4 -> data.readInt() + else -> -1 } + return Attribute(type, data, value) } } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Configuration.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Configuration.kt index b15b129..11c8309 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Configuration.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Configuration.kt @@ -1,7 +1,6 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.utils.getUnsignedShort -import java.nio.ByteBuffer +import net.cacheux.bytonio.utils.ByteArrayReader data class Configuration( val id: Int, @@ -13,10 +12,10 @@ data class Configuration( val attributes: List = listOf() ) { companion object { - fun fromByteBuffer(buffer: ByteBuffer): Configuration { - val id = buffer.getUnsignedShort() - val count = buffer.getUnsignedShort() - buffer.getUnsignedShort() // len + fun fromByteArrayReader(reader: ByteArrayReader): Configuration { + val id = reader.readShort() + val count = reader.readShort() + reader.readShort() // len var nbSegment = -1 var totalEntries = -1 @@ -26,13 +25,13 @@ data class Configuration( val attributes = mutableListOf() repeat(count) { - buffer.getUnsignedShort() // cls - buffer.getUnsignedShort() // handle - val attrCount = buffer.getUnsignedShort() - buffer.getUnsignedShort() //attrLen + reader.readShort() // cls + reader.readShort() // handle + val attrCount = reader.readShort() + reader.readShort() //attrLen repeat(attrCount) { - val attribute = Attribute.fromByteBuffer(buffer) + val attribute = AttributeDeserializer.fromByteArrayReader(reader) when (attribute.type) { Attribute.ATTR_NUM_SEG -> nbSegment = attribute.value diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ConfirmedAction.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ConfirmedAction.kt index 87b59b1..c609dc6 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ConfirmedAction.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ConfirmedAction.kt @@ -1,13 +1,17 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsShort -import java.nio.ByteBuffer +import net.cacheux.bytonio.BinarySerializable +import net.cacheux.bytonio.annotations.DataObject +import net.cacheux.bytonio.annotations.EncodeAsShort +import net.cacheux.bytonio.utils.writer +import net.cacheux.nvplib.generated.ConfirmedActionSerializer -data class ConfirmedAction private constructor( - @IsShort val handle: Int, - @IsShort val type: Int, +@DataObject +data class ConfirmedAction( + @EncodeAsShort val handle: Int, + @EncodeAsShort val type: Int, val bytes: ByteArray -): Encodable() { +): BinarySerializable { companion object { const val STORE_HANDLE = 0x100 const val ALL_SEGMENTS = 0x0001 @@ -19,7 +23,10 @@ data class ConfirmedAction private constructor( fun segment(handle: Int, type: Int, segment: Int) = ConfirmedAction( handle = handle, type = type, - bytes = ByteBuffer.allocate(2).putShort(segment.toShort()).array() + bytes = ByteArray(2).writer().apply { writeShort(segment.toShort()) }.byteArray ) } + + override fun getBinarySize() = ConfirmedActionSerializer.getBinarySize(this) + override fun toByteArray() = ConfirmedActionSerializer.toByteArray(this) } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/DataApdu.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/DataApdu.kt index efe4f9a..bc6f63d 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/DataApdu.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/DataApdu.kt @@ -1,14 +1,31 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsShort -import net.cacheux.nvplib.utils.getUnsignedShort +import net.cacheux.bytonio.BinaryDeserializer +import net.cacheux.bytonio.BinarySerializable +import net.cacheux.bytonio.BinarySerializer +import net.cacheux.bytonio.annotations.DataObject +import net.cacheux.bytonio.annotations.Deserializer +import net.cacheux.bytonio.annotations.EncodeAsShort +import net.cacheux.bytonio.annotations.Serializer +import net.cacheux.bytonio.utils.ByteArrayReader +import net.cacheux.bytonio.utils.reader +import net.cacheux.nvplib.data.DataApdu.Companion.CONFIRMED_ACTION_CHOSEN +import net.cacheux.nvplib.data.DataApdu.Companion.CONFIRMED_EVENT_REPORT_CHOSEN +import net.cacheux.nvplib.data.DataApdu.Companion.GET_CHOSEN +import net.cacheux.nvplib.data.DataApdu.Companion.MDC_ACT_SEG_GET_INFO +import net.cacheux.nvplib.data.DataApdu.Companion.MDC_ACT_SEG_TRIG_XFER +import net.cacheux.nvplib.data.DataApdu.Companion.SGET_CHOSEN +import net.cacheux.nvplib.generated.TriggerSegmentDataXferDeserializer import java.nio.ByteBuffer +@DataObject +@Serializer(DataApduSerializer::class) +@Deserializer(DataApduDeserializer::class) data class DataApdu( - @IsShort val invokeId: Int, - @IsShort val dchoice: Int, - val payload: Encodable? = null -): Encodable() { + @EncodeAsShort val invokeId: Int, + @EncodeAsShort val dchoice: Int, + val payload: BinarySerializable? = null +): BinarySerializable { companion object { const val EVENT_REPORT_CHOSEN = 0x0100 const val CONFIRMED_EVENT_REPORT_CHOSEN = 0x0101 @@ -19,57 +36,82 @@ data class DataApdu( const val CONFIRMED_ACTION_CHOSEN = 0x0207 const val MDC_ACT_SEG_GET_INFO = 0x0C0D const val MDC_ACT_SEG_TRIG_XFER = 0x0C1C - - fun fromByteBuffer(buffer: ByteBuffer): DataApdu { - buffer.getUnsignedShort() // olen - val invokeId = buffer.getUnsignedShort() - val dchoice = buffer.getUnsignedShort() - buffer.getUnsignedShort() // dlen - - val payload = when (dchoice) { - CONFIRMED_ACTION_CHOSEN -> { - buffer.getUnsignedShort() // handle - val actionType = buffer.getUnsignedShort() - buffer.getUnsignedShort() // actionLen - when (actionType) { - MDC_ACT_SEG_GET_INFO -> SegmentInfoList.fromByteBuffer(buffer) - MDC_ACT_SEG_TRIG_XFER -> TriggerSegmentDataXfer.fromByteBuffer(buffer) - else -> null - } - } - - CONFIRMED_EVENT_REPORT_CHOSEN -> EventReport.fromByteBuffer(buffer) - - SGET_CHOSEN, GET_CHOSEN -> { - buffer.getUnsignedShort() // handle - val count = buffer.getUnsignedShort() - buffer.getUnsignedShort() // len - FullSpecification.fromAttributes((1 .. count).map { Attribute.fromByteBuffer(buffer) }) - } - - else -> null - } - - return DataApdu(invokeId, dchoice, payload) - } } - override fun encodedSize(): Int { - return 6 + (payload?.let { it.encodedSize() + 2 } ?: 0) + override fun getBinarySize(): Int { + return 6 + (payload?.let { it.getBinarySize() + 2 } ?: 0) } override fun toByteArray(): ByteArray { val payloadSize = (payload?.let { - it.encodedSize() + 2 + it.getBinarySize() + 2 } ?: 0) - return ByteBuffer.allocate(encodedSize()).apply { + return ByteBuffer.allocate(getBinarySize()).apply { putShort((payloadSize + 4).toShort()) putShort(invokeId.toShort()) putShort(dchoice.toShort()) payload?.let { - putShort(payload.encodedSize().toShort()) + putShort(payload.getBinarySize().toShort()) put(payload.toByteArray()) } }.array() } } + +object DataApduSerializer: BinarySerializer { + override fun getBinarySize(data: DataApdu): Int { + return 6 + (data.payload?.let { it.getBinarySize() + 2 } ?: 0) + } + + override fun toByteArray(data: DataApdu): ByteArray { + val payloadSize = (data.payload?.let { + it.getBinarySize() + 2 + } ?: 0) + return ByteBuffer.allocate(data.getBinarySize()).apply { + putShort((payloadSize + 4).toShort()) + putShort(data.invokeId.toShort()) + putShort(data.dchoice.toShort()) + data.payload?.let { + putShort(data.payload.getBinarySize().toShort()) + put(data.payload.toByteArray()) + } + }.array() + } +} + +object DataApduDeserializer: BinaryDeserializer { + override fun fromByteArray(byteArray: ByteArray) = fromByteArrayReader(byteArray.reader()) + + override fun fromByteArrayReader(reader: ByteArrayReader): DataApdu { + reader.readShort() // olen + val invokeId = reader.readShort() + val dchoice = reader.readShort() + reader.readShort() // dlen + + val payload = when (dchoice) { + CONFIRMED_ACTION_CHOSEN -> { + reader.readShort() // handle + val actionType = reader.readShort() + reader.readShort() // actionLen + when (actionType) { + MDC_ACT_SEG_GET_INFO -> SegmentInfoList.fromByteArrayReader(reader) + MDC_ACT_SEG_TRIG_XFER -> TriggerSegmentDataXferDeserializer.fromByteArrayReader(reader) + else -> null + } + } + + CONFIRMED_EVENT_REPORT_CHOSEN -> EventReport.fromByteArrayReader(reader) + + SGET_CHOSEN, GET_CHOSEN -> { + reader.readShort() // handle + val count = reader.readShort() + reader.readShort() // len + FullSpecification.fromAttributes((1 .. count).map { AttributeDeserializer.fromByteArrayReader(reader) }) + } + + else -> null + } + + return DataApdu(invokeId, dchoice, payload) + } +} diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/DummyBinarySerializable.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/DummyBinarySerializable.kt new file mode 100644 index 0000000..211ae56 --- /dev/null +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/DummyBinarySerializable.kt @@ -0,0 +1,12 @@ +package net.cacheux.nvplib.data + +import net.cacheux.bytonio.BinarySerializable +import net.cacheux.bytonio.utils.byteArrayOf + +/** + * Base class for data classes that won't need serialization but still need BinarySerializable interface. + */ +open class DummyBinarySerializable: BinarySerializable { + override fun getBinarySize() = 0 + override fun toByteArray() = byteArrayOf() +} \ No newline at end of file diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Encodable.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Encodable.kt deleted file mode 100644 index 6d49d55..0000000 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Encodable.kt +++ /dev/null @@ -1,70 +0,0 @@ -package net.cacheux.nvplib.data - -import net.cacheux.nvplib.annotations.IsByte -import net.cacheux.nvplib.annotations.IsShort -import java.nio.ByteBuffer -import kotlin.reflect.KProperty -import kotlin.reflect.full.createType -import kotlin.reflect.full.hasAnnotation -import kotlin.reflect.full.isSubtypeOf - -open class Encodable { - - open fun encodedSize(): Int { - return this::class.members.mapNotNull { - if (it is KProperty<*>) { - if (it.returnType.isSubtypeOf(Encodable::class.createType())) { - (it.getter.call(this) as Encodable).encodedSize() + 2 - } else if (it.returnType.isSubtypeOf(Encodable::class.createType(nullable = true))) { - (it.getter.call(this) as Encodable?)?.let { it.encodedSize() + 2 } ?: 0 - } else if (it.returnType.classifier == ByteArray::class) { - (it.getter.call(this) as ByteArray).size + 2 - } else if (it.returnType.classifier == Int::class) { - when { - it.hasAnnotation() -> 2 - it.hasAnnotation() -> 1 - else -> 4 - } - } else 0 - } else null - }.sum() - } - - open fun toByteArray(): ByteArray { - val clazz = this::class - - val size = encodedSize() - val buffer = ByteBuffer.allocate(size) - - // Use parameters from constructor to keep order - clazz.constructors.first().parameters.forEach { param -> - val prop = clazz.members.find { it.name == param.name } - - if (prop is KProperty<*>) { - if (prop.returnType.isSubtypeOf(Encodable::class.createType())) { - val array = (prop.getter.call(this) as Encodable).toByteArray() - buffer.putShort(array.size.toShort()) - buffer.put(array) - } else if (prop.returnType.isSubtypeOf(Encodable::class.createType(nullable = true))) { - (prop.getter.call(this) as Encodable?)?.let { - val array = it.toByteArray() - buffer.putShort(array.size.toShort()) - buffer.put(array) - } - } else if (prop.returnType.classifier == ByteArray::class) { - val array = prop.getter.call(this) as ByteArray - buffer.putShort(array.size.toShort()) - buffer.put(array) - } else if (prop.returnType.classifier == Int::class) { - when { - prop.hasAnnotation() -> buffer.putShort((prop.getter.call(this) as Int).toShort()) - prop.hasAnnotation() -> buffer.put((prop.getter.call(this) as Int).toByte()) - else -> buffer.putInt(prop.getter.call(this) as Int) - } - } - } - } - - return buffer.array() - } -} \ No newline at end of file diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/EventReport.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/EventReport.kt index 250ae64..4d2b824 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/EventReport.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/EventReport.kt @@ -1,44 +1,41 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsInt -import net.cacheux.nvplib.annotations.IsShort -import net.cacheux.nvplib.utils.getUnsignedInt -import net.cacheux.nvplib.utils.getUnsignedShort -import java.nio.ByteBuffer +import net.cacheux.bytonio.annotations.IgnoreEncoding +import net.cacheux.bytonio.utils.ByteArrayReader data class EventReport( - @IsShort val handle: Int, - @IsInt val relativeTime: Int, - @IsShort val eventType: Int, + val handle: Int, + val relativeTime: Int, + val eventType: Int, val configuration: Configuration? = null, val instance: Int = -1, val index: Int = -1, - val insulinDoses: List = listOf() -): Encodable() { + @IgnoreEncoding val insulinDoses: List = listOf() +): DummyBinarySerializable() { companion object { const val MDC_NOTI_CONFIG: Int = 3356 const val MDC_NOTI_SEGMENT_DATA: Int = 3361 - fun fromByteBuffer(buffer: ByteBuffer): EventReport { - val handle = buffer.getUnsignedShort() - val relativeTime = buffer.getUnsignedInt() - val eventType = buffer.getUnsignedShort() - buffer.getUnsignedShort() // len + fun fromByteArrayReader(reader: ByteArrayReader): EventReport { + val handle = reader.readShort() + val relativeTime = reader.readInt() + val eventType = reader.readShort() + reader.readShort() // len val doses = mutableListOf() return when (eventType) { MDC_NOTI_SEGMENT_DATA -> { - val instance = buffer.getUnsignedShort() - val index = buffer.getUnsignedInt() - val count = buffer.getUnsignedInt() - buffer.getUnsignedShort() // status - buffer.getUnsignedShort() // bcount + val instance = reader.readShort() + val index = reader.readInt() + val count = reader.readInt() + reader.readShort() // status + reader.readShort() // bcount val currentTime = System.currentTimeMillis() repeat(count) { - InsulinDose.fromByteBuffer(buffer).let { + InsulinDoseDeserializer.fromByteArrayReader(reader).let { if (it.flags == InsulinDose.VALID_FLAG) doses.add(it.withUtcTime(relativeTime, currentTime)) } @@ -46,7 +43,7 @@ data class EventReport( EventReport(handle, relativeTime, eventType, null, instance, index, doses) } MDC_NOTI_CONFIG -> { - EventReport(handle, relativeTime, eventType, Configuration.fromByteBuffer(buffer)) + EventReport(handle, relativeTime, eventType, Configuration.fromByteArrayReader(reader)) } else -> EventReport(handle, relativeTime, eventType) } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/EventRequest.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/EventRequest.kt index 0bc433b..bcfd8e9 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/EventRequest.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/EventRequest.kt @@ -1,11 +1,17 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsInt -import net.cacheux.nvplib.annotations.IsShort +import net.cacheux.bytonio.BinarySerializable +import net.cacheux.bytonio.annotations.DataObject +import net.cacheux.bytonio.annotations.EncodeAsShort +import net.cacheux.nvplib.generated.EventRequestSerializer +@DataObject data class EventRequest( - @IsShort val handle: Int, - @IsInt val currentTime: Int, - @IsShort val type: Int, + @EncodeAsShort val handle: Int, + val currentTime: Int, + @EncodeAsShort val type: Int, val data: ByteArray -): Encodable() +): BinarySerializable { + override fun getBinarySize() = EventRequestSerializer.getBinarySize(this) + override fun toByteArray() = EventRequestSerializer.toByteArray(this) +} diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/FullSpecification.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/FullSpecification.kt index 8446fb9..917d2b9 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/FullSpecification.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/FullSpecification.kt @@ -1,17 +1,17 @@ package net.cacheux.nvplib.data +import net.cacheux.bytonio.annotations.IgnoreEncoding +import net.cacheux.bytonio.utils.reader import net.cacheux.nvplib.data.Attribute.Companion.ATTR_ID_MODEL import net.cacheux.nvplib.data.Attribute.Companion.ATTR_ID_PROD_SPECN import net.cacheux.nvplib.data.Attribute.Companion.ATTR_TIME_REL import net.cacheux.nvplib.utils.getIndexedString -import net.cacheux.nvplib.utils.getUnsignedInt -import net.cacheux.nvplib.utils.wrap data class FullSpecification( val specification: Specification, val relativeTime: Long = 0L, - val model: List = listOf() -): Encodable() { + @IgnoreEncoding val model: List = listOf() +): DummyBinarySerializable() { companion object { fun fromAttributes(attributes: List): FullSpecification { var specification = Specification() @@ -20,15 +20,15 @@ data class FullSpecification( attributes.forEach { when (it.type) { ATTR_ID_PROD_SPECN -> { - specification = Specification.fromByteBuffer(it.data.wrap()) + specification = Specification.fromByteArrayReader(it.data.reader()) } ATTR_TIME_REL -> { - relativeTime = it.data.wrap().getUnsignedInt().toLong() + relativeTime = it.data.reader().readInt().toLong() } ATTR_ID_MODEL -> { - val buffer = it.data.wrap() - while (buffer.hasRemaining()) { - model.add(buffer.getIndexedString()) + val reader = it.data.reader() + while (reader.hasRemaining()) { + model.add(reader.getIndexedString()) } } } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/InsulinDose.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/InsulinDose.kt index b3d0138..e5dc6ed 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/InsulinDose.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/InsulinDose.kt @@ -1,24 +1,23 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsInt -import net.cacheux.nvplib.utils.getUnsignedInt -import java.nio.ByteBuffer +import net.cacheux.bytonio.BinaryDeserializer +import net.cacheux.bytonio.BinarySerializable +import net.cacheux.bytonio.annotations.DataObject +import net.cacheux.bytonio.annotations.Deserializer +import net.cacheux.bytonio.annotations.EncodeAsInt +import net.cacheux.bytonio.utils.ByteArrayReader +import net.cacheux.bytonio.utils.reader +import net.cacheux.nvplib.generated.InsulinDoseSerializer +@DataObject +@Deserializer(InsulinDoseDeserializer::class) data class InsulinDose( - @IsInt val time: Long, - @IsInt val units: Int, - @IsInt val flags: Int -): Encodable() { + @EncodeAsInt val time: Long, + @EncodeAsInt val units: Int, + @EncodeAsInt val flags: Int +): BinarySerializable { companion object { const val VALID_FLAG = 0x08000000 - - fun fromByteBuffer(buffer: ByteBuffer): InsulinDose { - val relativeTime = buffer.getUnsignedInt() - val units = (buffer.getUnsignedInt() and 0xFFFF) - val flags = buffer.getUnsignedInt() - - return InsulinDose(relativeTime.toLong(), units, flags) - } } /** @@ -31,4 +30,19 @@ data class InsulinDose( time = (currentTime - ( (relativeTime - time) * 1000 )), units = units, flags = flags ) + + override fun getBinarySize() = InsulinDoseSerializer.getBinarySize(this) + override fun toByteArray() = InsulinDoseSerializer.toByteArray(this) +} + +object InsulinDoseDeserializer: BinaryDeserializer { + override fun fromByteArray(byteArray: ByteArray) = fromByteArrayReader(byteArray.reader()) + + override fun fromByteArrayReader(reader: ByteArrayReader): InsulinDose { + val relativeTime = reader.readInt() + val units = (reader.readInt() and 0xFFFF) + val flags = reader.readInt() + + return InsulinDose(relativeTime.toLong(), units, flags) + } } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/PhdPacket.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/PhdPacket.kt index 2644a86..901dd8f 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/PhdPacket.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/PhdPacket.kt @@ -1,8 +1,9 @@ package net.cacheux.nvplib.data +import net.cacheux.bytonio.utils.ByteArrayReader +import net.cacheux.bytonio.utils.writer import net.cacheux.nvplib.utils.getUnsignedByte import net.cacheux.nvplib.utils.putUnsignedByte -import java.nio.ByteBuffer data class PhdPacket( val opcode: Byte = -1, @@ -23,26 +24,26 @@ data class PhdPacket( private const val WELL_KNOWN = 1 - fun fromByteBuffer(buffer: ByteBuffer): PhdPacket { - val opcode = buffer.getUnsignedByte() - val typeLen = buffer.getUnsignedByte() - val payloadLen = buffer.getUnsignedByte() - 1 + fun fromByteArrayReader(reader: ByteArrayReader): PhdPacket { + val opcode = reader.getUnsignedByte() + val typeLen = reader.getUnsignedByte() + val payloadLen = reader.getUnsignedByte() - 1 val hasId = opcode and (1 shl 3) != 0 val headerLen = if (hasId) { - buffer.getUnsignedByte() + reader.getUnsignedByte() } else 0 - val protoId = ByteArray(3) - buffer.get(protoId) + val protoId = reader.readByteArray(3) val header = if (hasId) { - ByteArray(headerLen).apply { buffer.get(this) } + reader.readByteArray(headerLen.toInt()) } else null - val chk = buffer.getUnsignedByte() - val realLen = if (buffer.remaining() < payloadLen) buffer.remaining() else payloadLen - val inner = ByteArray(realLen).apply { - buffer.get(this) - } + val chk = reader.getUnsignedByte() + val realLen = if (reader.remaining() < payloadLen.toInt()) reader.remaining() else payloadLen.toInt() + val inner = reader.readByteArray(realLen) - return PhdPacket(opcode.toByte(), typeLen, realLen, headerLen, header, seq = (chk and 0x0f), chk = chk, inner) + return PhdPacket(opcode.toByte(), typeLen, + realLen, headerLen, + header, seq = (chk and 0x0f), chk = chk, inner + ) } } @@ -50,18 +51,18 @@ data class PhdPacket( val ilen = content.size val idLen = header?.size ?: 0 val hasId = idLen > 0 - val b = ByteBuffer.allocate(ilen + 7) - b.putUnsignedByte(MB or ME or SR or (if(hasId) IL else 0) or WELL_KNOWN) - b.putUnsignedByte(3) - b.putUnsignedByte(ilen + 1) - if (hasId) { - b.put(header) - } - b.put("PHD".toByteArray()) - b.putUnsignedByte(seq and 0x0F or 0x80 or chk) - if (ilen > 0) { - b.put(content) - } - return b.array() + return ByteArray(ilen + 7).writer().apply { + putUnsignedByte(MB or ME or SR or (if(hasId) IL else 0) or WELL_KNOWN) + putUnsignedByte(3) + putUnsignedByte(ilen + 1) + if (hasId && header != null) { + writeByteArray(header) + } + writeByteArray("PHD".toByteArray()) + putUnsignedByte(seq and 0x0F or 0x80 or chk) + if (ilen > 0) { + writeByteArray(content) + } + }.byteArray } } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentEntry.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentEntry.kt index 460efb9..8d210ce 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentEntry.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentEntry.kt @@ -1,26 +1,14 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsShort -import net.cacheux.nvplib.utils.getByteArray -import net.cacheux.nvplib.utils.getUnsignedShort -import java.nio.ByteBuffer +import net.cacheux.bytonio.annotations.DataObject +import net.cacheux.bytonio.annotations.EncodeAsShort +@DataObject data class SegmentEntry( - @IsShort val classId: Int, - @IsShort val metricType: Int, - @IsShort val otype: Int, - @IsShort val handle: Int, - @IsShort val amCount: Int, + @EncodeAsShort val classId: Int, + @EncodeAsShort val metricType: Int, + @EncodeAsShort val otype: Int, + @EncodeAsShort val handle: Int, + @EncodeAsShort val amCount: Int, val data: ByteArray -) { - companion object { - fun fromByteBuffer(buffer: ByteBuffer): SegmentEntry = SegmentEntry( - classId = buffer.getUnsignedShort(), - metricType = buffer.getUnsignedShort(), - otype = buffer.getUnsignedShort(), - handle = buffer.getUnsignedShort(), - amCount = buffer.getUnsignedShort(), - data = buffer.getByteArray() - ) - } -} +) diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfo.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfo.kt index d8ade91..269767e 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfo.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfo.kt @@ -1,10 +1,9 @@ package net.cacheux.nvplib.data +import net.cacheux.bytonio.utils.ByteArrayReader +import net.cacheux.bytonio.utils.reader import net.cacheux.nvplib.data.Attribute.Companion.ATTR_PM_SEG_MAP import net.cacheux.nvplib.data.Attribute.Companion.ATTR_SEG_USAGE_CNT -import net.cacheux.nvplib.utils.getUnsignedShort -import net.cacheux.nvplib.utils.wrap -import java.nio.ByteBuffer data class SegmentInfo( val instnum: Int, @@ -13,17 +12,17 @@ data class SegmentInfo( val segmentInfoMap: SegmentInfoMap? = null, ) { companion object { - fun fromByteBuffer(buffer: ByteBuffer): SegmentInfo { - val instnum = buffer.getUnsignedShort() - val count = buffer.getUnsignedShort() - buffer.getUnsignedShort() // length + fun fromByteArrayReader(reader: ByteArrayReader): SegmentInfo { + val instnum = reader.readShort() + val count = reader.readShort() + reader.readShort() // length var usage = -1 var segmentInfoMap: SegmentInfoMap? = null val items = mutableListOf() repeat(count) { - val attribute = Attribute.fromByteBuffer(buffer) + val attribute = AttributeDeserializer.fromByteArrayReader(reader) when (attribute.type) { - ATTR_PM_SEG_MAP -> segmentInfoMap = SegmentInfoMap.fromByteBuffer(attribute.data.wrap()) + ATTR_PM_SEG_MAP -> segmentInfoMap = SegmentInfoMap.fromByteArrayReader(attribute.data.reader()) ATTR_SEG_USAGE_CNT -> usage = attribute.value } items.add(attribute) diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfoList.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfoList.kt index 7cf49e1..19a331e 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfoList.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfoList.kt @@ -1,19 +1,23 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.utils.getUnsignedShort -import java.nio.ByteBuffer +import net.cacheux.bytonio.BinarySerializable +import net.cacheux.bytonio.utils.ByteArrayReader +import net.cacheux.bytonio.utils.byteArrayOf data class SegmentInfoList( val items: List = listOf() -): Encodable() { +): BinarySerializable { + override fun getBinarySize() = 0 + override fun toByteArray() = byteArrayOf() + companion object { - fun fromByteBuffer(buffer: ByteBuffer): SegmentInfoList { - val count = buffer.getUnsignedShort() - buffer.getUnsignedShort() // length + fun fromByteArrayReader(reader: ByteArrayReader): SegmentInfoList { + val count = reader.readShort() + reader.readShort() // length return SegmentInfoList( (1..count).map { - SegmentInfo.fromByteBuffer(buffer) + SegmentInfo.fromByteArrayReader(reader) } ) } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfoMap.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfoMap.kt index cb9f153..3be732d 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfoMap.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfoMap.kt @@ -1,23 +1,22 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsShort -import net.cacheux.nvplib.utils.getUnsignedShort -import java.nio.ByteBuffer +import net.cacheux.bytonio.utils.ByteArrayReader +import net.cacheux.nvplib.generated.SegmentEntryDeserializer data class SegmentInfoMap( - @IsShort val bits: Int, - @IsShort val count: Int, - @IsShort val length: Int, + val bits: Int, + val count: Int, + val length: Int, val items: List ) { companion object { - fun fromByteBuffer(buffer: ByteBuffer): SegmentInfoMap { - val bits = buffer.getUnsignedShort() - val count = buffer.getUnsignedShort() - val length = buffer.getUnsignedShort() + fun fromByteArrayReader(reader: ByteArrayReader): SegmentInfoMap { + val bits = reader.readShort() + val count = reader.readShort() + val length = reader.readShort() val items = mutableListOf() repeat(count) { - items.add(SegmentEntry.fromByteBuffer(buffer)) + items.add(SegmentEntryDeserializer.fromByteArrayReader(reader)) } return SegmentInfoMap(bits, count, length, items) diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Specification.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Specification.kt index e5073c5..bc5881f 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Specification.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Specification.kt @@ -1,8 +1,8 @@ package net.cacheux.nvplib.data +import net.cacheux.bytonio.utils.ByteArrayReader import net.cacheux.nvplib.utils.getIndexedString import net.cacheux.nvplib.utils.getUnsignedShort -import java.nio.ByteBuffer data class Specification( val serial: String = "", @@ -16,18 +16,18 @@ data class Specification( private const val HW_VERSION = 3 private const val SW_VERSION = 4 - fun fromByteBuffer(buffer: ByteBuffer): Specification { + fun fromByteArrayReader(reader: ByteArrayReader): Specification { var serial = "" var partNumber = "" var softwareRevision = "" var hardwareRevision = "" - val count = buffer.getUnsignedShort() - buffer.getUnsignedShort() // size + val count = reader.getUnsignedShort() + reader.getUnsignedShort() // size repeat(count) { - val type = buffer.getUnsignedShort() - buffer.getUnsignedShort() // component - val value = buffer.getIndexedString() + val type = reader.getUnsignedShort() + reader.getUnsignedShort() // component + val value = reader.getIndexedString() when (type) { SERIAL_NUMBER -> serial = value diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/T4Update.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/T4Update.kt index 03d3a50..598b47a 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/T4Update.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/T4Update.kt @@ -1,8 +1,8 @@ package net.cacheux.nvplib.data +import net.cacheux.bytonio.utils.writer import net.cacheux.nvplib.utils.putUnsignedByte import net.cacheux.nvplib.utils.putUnsignedShort -import java.nio.ByteBuffer class T4Update( private val bytes: ByteArray @@ -12,15 +12,13 @@ class T4Update( private val UPDATE_COMMAND = 0xD6 } - fun toByteArray(): ByteArray { - val b = ByteBuffer.allocate(bytes.size + 7) - b.putUnsignedByte(CLA) - b.putUnsignedByte(UPDATE_COMMAND) - b.putUnsignedShort(0) - b.putUnsignedByte(bytes.size + 2) - b.putUnsignedShort(bytes.size) - b.put(bytes) - - return b.array() - } + fun toByteArray() = + ByteArray(bytes.size + 7).writer().apply { + putUnsignedByte(CLA) + putUnsignedByte(UPDATE_COMMAND) + putUnsignedShort(0) + putUnsignedByte(bytes.size + 2) + putUnsignedShort(bytes.size) + writeByteArray(bytes) + }.byteArray } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/TriggerSegmentDataXfer.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/TriggerSegmentDataXfer.kt index edac9fb..9afaa9d 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/TriggerSegmentDataXfer.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/TriggerSegmentDataXfer.kt @@ -1,21 +1,16 @@ package net.cacheux.nvplib.data -import net.cacheux.nvplib.annotations.IsShort -import net.cacheux.nvplib.utils.getUnsignedShort -import java.nio.ByteBuffer +import net.cacheux.bytonio.BinarySerializable +import net.cacheux.bytonio.annotations.DataObject +import net.cacheux.bytonio.annotations.EncodeAsShort +import net.cacheux.nvplib.generated.TriggerSegmentDataXferSerializer +@DataObject data class TriggerSegmentDataXfer( - @IsShort val segmentId: Int, - @IsShort val responseCode: Int, -): Encodable() { - companion object { - fun fromByteBuffer(buffer: ByteBuffer): TriggerSegmentDataXfer { - val segment = buffer.getUnsignedShort() - val response = buffer.getUnsignedShort() - - return TriggerSegmentDataXfer(segment, response) - } - } - + @EncodeAsShort val segmentId: Int, + @EncodeAsShort val responseCode: Int, +): BinarySerializable { fun isOkay() = segmentId != 0 && responseCode == 0 + override fun getBinarySize() = TriggerSegmentDataXferSerializer.getBinarySize(this) + override fun toByteArray() = TriggerSegmentDataXferSerializer.toByteArray(this) } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/utils/ByteUtils.kt b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/utils/ByteUtils.kt index cb884ef..4b7409d 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/utils/ByteUtils.kt +++ b/nvplib/core/src/main/kotlin/net/cacheux/nvplib/utils/ByteUtils.kt @@ -1,89 +1,26 @@ package net.cacheux.nvplib.utils -import net.cacheux.nvplib.data.Encodable -import java.nio.ByteBuffer -import kotlin.reflect.KProperty -import kotlin.reflect.full.createType -import kotlin.reflect.full.isSubtypeOf +import net.cacheux.bytonio.utils.ByteArrayReader +import net.cacheux.bytonio.utils.ByteArrayWriter -fun ByteBuffer.putUnsignedByte(s: Int) { - put((s and 0xff).toByte()) +fun ByteArrayWriter.putUnsignedByte(s: Int) { + writeByte((s and 0xff).toByte()) } -fun ByteBuffer.putUnsignedShort(s: Int) { - putShort((s and 0xffff).toShort()) +fun ByteArrayWriter.putUnsignedShort(s: Int) { + writeShort((s and 0xffff).toShort()) } -fun ByteBuffer.putUnsignedInt(s: Int) { - putInt(s and 0xffffffff.toInt()) +fun ByteArrayReader.getUnsignedShort(): Int { + return readShort() and 0x0000ffff } -fun ByteBuffer.getUnsignedInt(): Int { - return (this.getInt().toLong() and 0xffffffffL).toInt() +fun ByteArrayReader.getUnsignedByte(): Int { + return readByte().toInt() and 0x000000ff } -fun ByteBuffer.getUnsignedShort(): Int { - return getShort().toInt() and 0x0000ffff -} - -fun ByteBuffer.getUnsignedByte(): Int { - return get().toInt() and 0x000000ff -} - -fun ByteBuffer.getByteArray(): ByteArray { - val size = getUnsignedShort() - val buffer = ByteArray(size) - get(buffer, 0, size) - return buffer -} - -fun ByteBuffer.getIndexedString() = - String(getByteArray()).replace( +fun ByteArrayReader.getIndexedString() = + String(readByteArray(getUnsignedShort())).replace( "\u0000", "" ) - -fun ByteArray.toHex(): String = joinToString(separator = "") { eachByte -> "%02x".format(eachByte) } -fun ByteArray.wrap(): ByteBuffer = ByteBuffer.wrap(this) - -fun encodedSize(data: T): Int { - val clazz = data!!::class - - return clazz.members.mapNotNull { - if (it is KProperty<*>) { - if (it.returnType.isSubtypeOf(Encodable::class.createType())) { - encodedSize(data) - } else when (it.returnType.classifier) { - ByteArray::class -> (it.getter.call(data) as ByteArray).size - Int::class -> 4 - Short::class -> 2 - Byte::class -> 1 - else -> 0 - } - } else null - }.sum() -} - -fun encodeToByteArray(data: T): ByteArray { - val clazz = data!!::class - - if (!clazz.isData) { - throw IllegalArgumentException("Parameter must be a data class") - } - - val buffer = ByteBuffer.allocate(encodedSize(data)) - // Use parameters from constructor to keep order - clazz.constructors.first().parameters.forEach { param -> - val prop = clazz.members.find { it.name == param.name } - if (prop is KProperty<*>) { - when (prop.returnType.classifier) { - ByteArray::class -> buffer.put(prop.getter.call(data) as ByteArray) - Int::class -> buffer.putInt(prop.getter.call(data) as Int) - Short::class -> buffer.putShort(prop.getter.call(data) as Short) - Byte::class -> buffer.put(prop.getter.call(data) as Byte) - } - } - } - - return buffer.array() -} diff --git a/nvplib/core/src/test/kotlin/net/cacheux/nvplib/data/DataApduTest.kt b/nvplib/core/src/test/kotlin/net/cacheux/nvplib/data/DataApduTest.kt index 41f8055..fea0bf0 100644 --- a/nvplib/core/src/test/kotlin/net/cacheux/nvplib/data/DataApduTest.kt +++ b/nvplib/core/src/test/kotlin/net/cacheux/nvplib/data/DataApduTest.kt @@ -1,14 +1,14 @@ package net.cacheux.nvplib.data +import net.cacheux.bytonio.utils.reader +import net.cacheux.bytonio.utils.writer import net.cacheux.nvplib.utils.hexToByteArray import net.cacheux.nvplib.utils.putUnsignedShort -import net.cacheux.nvplib.utils.wrap import org.junit.Assert.assertArrayEquals import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Test -import java.nio.ByteBuffer class DataApduTest { companion object { @@ -81,8 +81,8 @@ class DataApduTest { @Test fun testDataApduEventReportParsing() { - val phd = PhdPacket.fromByteBuffer(ByteBuffer.wrap(APDU_EVENT_REPORT.hexToByteArray())) - val resultApdu = Apdu.fromByteBuffer(phd.content.wrap()) + val phd = PhdPacket.fromByteArrayReader(APDU_EVENT_REPORT.hexToByteArray().reader()) + val resultApdu = ApduDeserializer.fromByteArray(phd.content) assertEquals(0x0000e700, resultApdu.at) assertTrue(resultApdu.payload is DataApdu) @@ -102,8 +102,8 @@ class DataApduTest { @Test fun testSpecificationParsing() { - val phd = PhdPacket.fromByteBuffer(ByteBuffer.wrap(APDU_SPECIFICATION.hexToByteArray())) - val resultApdu = Apdu.fromByteBuffer(phd.content.wrap()) + val phd = PhdPacket.fromByteArrayReader(APDU_SPECIFICATION.hexToByteArray().reader()) + val resultApdu = ApduDeserializer.fromByteArray(phd.content) assertEquals(0x0000e700, resultApdu.at) assertTrue(resultApdu.payload is DataApdu) @@ -120,8 +120,8 @@ class DataApduTest { @Test fun testDataApduSegmentInfoParsing() { - val phd = PhdPacket.fromByteBuffer(ByteBuffer.wrap(APDU_SEGMENT_INFO.hexToByteArray())) - val resultApdu = Apdu.fromByteBuffer(phd.content.wrap()) + val phd = PhdPacket.fromByteArrayReader(APDU_SEGMENT_INFO.hexToByteArray().reader()) + val resultApdu = ApduDeserializer.fromByteArray(phd.content) assertEquals(0x0000e700, resultApdu.at) assertTrue(resultApdu.payload is DataApdu) (resultApdu.payload as DataApdu).let { data -> @@ -135,8 +135,8 @@ class DataApduTest { @Test fun testDataApduDoseListParsing() { - val phd = PhdPacket.fromByteBuffer(ByteBuffer.wrap(APDU_DOSE_LIST.hexToByteArray())) - val resultApdu = Apdu.fromByteBuffer(phd.content.wrap()) + val phd = PhdPacket.fromByteArrayReader(APDU_DOSE_LIST.hexToByteArray().reader()) + val resultApdu = ApduDeserializer.fromByteArray(phd.content) assertEquals(0x0000e700, resultApdu.at) assertTrue(resultApdu.payload is DataApdu) (resultApdu.payload as DataApdu).let { data -> @@ -159,10 +159,10 @@ class DataApduTest { handle = 0, currentTime = 0, type = EventReport.MDC_NOTI_CONFIG, - data = ByteBuffer.allocate(4).apply { + data = ByteArray(4).writer().apply { putUnsignedShort(16394) putUnsignedShort(0) - }.array() + }.byteArray ) val dataApdu = DataApdu( diff --git a/nvplib/core/src/test/kotlin/net/cacheux/nvplib/data/EncodableTest.kt b/nvplib/core/src/test/kotlin/net/cacheux/nvplib/data/EncodableTest.kt deleted file mode 100644 index 3d152bf..0000000 --- a/nvplib/core/src/test/kotlin/net/cacheux/nvplib/data/EncodableTest.kt +++ /dev/null @@ -1,45 +0,0 @@ -package net.cacheux.nvplib.data - -import net.cacheux.nvplib.annotations.IsByte -import net.cacheux.nvplib.annotations.IsInt -import net.cacheux.nvplib.annotations.IsShort -import org.junit.Assert.assertArrayEquals -import org.junit.Test - -data class EncodableItem( - @IsInt var id: Int, - @IsShort var value: Int, - @IsByte var byte: Int, - var array: ByteArray, - val subItem: SubItem -): Encodable() - -data class SubItem( - val content: ByteArray -): Encodable() - -class EncodableTest { - @Test - fun testEncodable() { - val testItem = EncodableItem( - 98765, - 677, - 0x24, - byteArrayOf(0xAA.toByte(), 0xBB.toByte(), 0xCC.toByte()), - SubItem(byteArrayOf(0x11, 0x22, 0x33)) - ) - - val result = testItem.toByteArray() - assertArrayEquals( - byteArrayOf( - 0x00, 0x01, 0x81.toByte(), 0xCD.toByte(), - 0x02, 0xA5.toByte(), - 0x24, - 0x00, 0x03, - 0xAA.toByte(), 0xBB.toByte(), 0xCC.toByte(), - 0x00, 0x05, 0x00, 0x03, - 0x11, 0x22, 0x33 - ), result - ) - } -} diff --git a/nvplib/core/src/test/kotlin/net/cacheux/nvplib/utils/ByteUtilsTest.kt b/nvplib/core/src/test/kotlin/net/cacheux/nvplib/utils/ByteUtilsTest.kt index f945bd2..05a4e8a 100644 --- a/nvplib/core/src/test/kotlin/net/cacheux/nvplib/utils/ByteUtilsTest.kt +++ b/nvplib/core/src/test/kotlin/net/cacheux/nvplib/utils/ByteUtilsTest.kt @@ -1,43 +1,16 @@ package net.cacheux.nvplib.utils -import org.junit.Assert.assertArrayEquals +import net.cacheux.bytonio.utils.reader import org.junit.Assert.assertEquals import org.junit.Test -import java.nio.ByteBuffer - -data class TestClass( - var id: Int, - var value: Short, - var byte: Byte, - var array: ByteArray, -) class ByteUtilsTest { @Test fun getUnsignedByte() { - val buffer = ByteBuffer.wrap(byteArrayOf(0x03, 0xC9.toByte(), 0x11)) - - assertEquals(3, buffer.getUnsignedByte()) - assertEquals(201, buffer.getUnsignedByte()) - assertEquals(17, buffer.getUnsignedByte()) - } - - @Test - fun testDataClassSerialization() { - val item = TestClass( - 98765, - 677, - 0x24, - byteArrayOf(0xAA.toByte(), 0xBB.toByte(), 0xCC.toByte()) - ) + val reader = byteArrayOf(0x03, 0xC9.toByte(), 0x11).reader() - val result = encodeToByteArray(item) - assertArrayEquals( - byteArrayOf( - 0x00, 0x01, 0x81.toByte(), 0xCD.toByte(), - 0x02, 0xA5.toByte(), - 0x24, - 0xAA.toByte(), 0xBB.toByte(), 0xCC.toByte() - ), result) + assertEquals(3, reader.getUnsignedByte()) + assertEquals(201, reader.getUnsignedByte()) + assertEquals(17, reader.getUnsignedByte()) } -} \ No newline at end of file +} From a2c13226f24d9032bd46a969189f9e2b5e213cec Mon Sep 17 00:00:00 2001 From: Leo CACHEUX Date: Mon, 15 Dec 2025 17:39:34 +0100 Subject: [PATCH 2/3] Publish using KMP --- .github/workflows/publish_nvplib.yml | 25 +++ build.gradle.kts | 6 + gradle.properties | 1 + gradle/libs.versions.toml | 28 ++-- nvplib/core/build.gradle.kts | 149 +++++++++--------- .../{main => commonMain}/AndroidManifest.xml | 0 .../kotlin/net/cacheux/nvplib/DataReader.kt | 0 .../net/cacheux/nvplib/NvpController.kt | 0 .../net/cacheux/nvplib/PayloadFunctions.kt | 0 .../kotlin/net/cacheux/nvplib/PhdManager.kt | 0 .../net/cacheux/nvplib/StopConditionUtils.kt | 0 .../net/cacheux/nvplib/TransceiveResult.kt | 0 .../net/cacheux/nvplib/data/ARequest.kt | 0 .../net/cacheux/nvplib/data/AResponse.kt | 0 .../kotlin/net/cacheux/nvplib/data/Apdu.kt | 0 .../net/cacheux/nvplib/data/ApoepElement.kt | 0 .../cacheux/nvplib/data/ArgumentsSimple.kt | 0 .../net/cacheux/nvplib/data/Attribute.kt | 0 .../net/cacheux/nvplib/data/Configuration.kt | 0 .../cacheux/nvplib/data/ConfirmedAction.kt | 0 .../net/cacheux/nvplib/data/DataApdu.kt | 35 ++-- .../nvplib/data/DummyBinarySerializable.kt | 0 .../net/cacheux/nvplib/data/EventReport.kt | 5 +- .../net/cacheux/nvplib/data/EventRequest.kt | 0 .../cacheux/nvplib/data/FullSpecification.kt | 0 .../net/cacheux/nvplib/data/InsulinDose.kt | 5 +- .../net/cacheux/nvplib/data/PenResult.kt | 0 .../net/cacheux/nvplib/data/PhdPacket.kt | 2 +- .../net/cacheux/nvplib/data/SegmentEntry.kt | 0 .../net/cacheux/nvplib/data/SegmentInfo.kt | 0 .../cacheux/nvplib/data/SegmentInfoList.kt | 0 .../net/cacheux/nvplib/data/SegmentInfoMap.kt | 0 .../net/cacheux/nvplib/data/Specification.kt | 0 .../net/cacheux/nvplib/data/T4Update.kt | 0 .../nvplib/data/TriggerSegmentDataXfer.kt | 0 .../net/cacheux/nvplib/utils/ByteUtils.kt | 2 +- .../net/cacheux/nvplib/utils/TimeUtils.kt | 0 .../kotlin/net/cacheux/nvplib/utils/Utils.kt | 0 .../net/cacheux/nvplib/NvpControllerTest.kt | 0 .../cacheux/nvplib/StopConditionUtilsTest.kt | 0 .../nvplib/data/ConfirmedActionTest.kt | 0 .../net/cacheux/nvplib/data/DataApduTest.kt | 0 .../net/cacheux/nvplib/utils/ByteUtilsTest.kt | 0 .../net/cacheux/nvplib/utils/TimeUtilsTest.kt | 0 .../net/cacheux/nvplib/utils/UtilsTest.kt | 0 nvplib/nfc/build.gradle.kts | 96 ++++------- nvplib/testing/build.gradle.kts | 2 +- settings.gradle.kts | 4 + utils/build.gradle.kts | 2 +- 49 files changed, 180 insertions(+), 182 deletions(-) create mode 100644 .github/workflows/publish_nvplib.yml rename nvplib/core/src/{main => commonMain}/AndroidManifest.xml (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/DataReader.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/NvpController.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/PayloadFunctions.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/PhdManager.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/StopConditionUtils.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/TransceiveResult.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/ARequest.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/AResponse.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/Apdu.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/ApoepElement.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/ArgumentsSimple.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/Attribute.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/Configuration.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/ConfirmedAction.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/DataApdu.kt (78%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/DummyBinarySerializable.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/EventReport.kt (91%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/EventRequest.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/FullSpecification.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/InsulinDose.kt (89%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/PenResult.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/PhdPacket.kt (97%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/SegmentEntry.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/SegmentInfo.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/SegmentInfoList.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/SegmentInfoMap.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/Specification.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/T4Update.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/data/TriggerSegmentDataXfer.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/utils/ByteUtils.kt (89%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/utils/TimeUtils.kt (100%) rename nvplib/core/src/{main => commonMain}/kotlin/net/cacheux/nvplib/utils/Utils.kt (100%) rename nvplib/core/src/{test => jvmTest}/kotlin/net/cacheux/nvplib/NvpControllerTest.kt (100%) rename nvplib/core/src/{test => jvmTest}/kotlin/net/cacheux/nvplib/StopConditionUtilsTest.kt (100%) rename nvplib/core/src/{test => jvmTest}/kotlin/net/cacheux/nvplib/data/ConfirmedActionTest.kt (100%) rename nvplib/core/src/{test => jvmTest}/kotlin/net/cacheux/nvplib/data/DataApduTest.kt (100%) rename nvplib/core/src/{test => jvmTest}/kotlin/net/cacheux/nvplib/utils/ByteUtilsTest.kt (100%) rename nvplib/core/src/{test => jvmTest}/kotlin/net/cacheux/nvplib/utils/TimeUtilsTest.kt (100%) rename nvplib/core/src/{test => jvmTest}/kotlin/net/cacheux/nvplib/utils/UtilsTest.kt (100%) diff --git a/.github/workflows/publish_nvplib.yml b/.github/workflows/publish_nvplib.yml new file mode 100644 index 0000000..35ec337 --- /dev/null +++ b/.github/workflows/publish_nvplib.yml @@ -0,0 +1,25 @@ +name: Publish NvpLib +on: + push: + tags: + - 'nvplib-*' +jobs: + publish: + name: Release build and publish + runs-on: macOS-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + distribution: 'zulu' + java-version: 21 + - name: Publish to MavenCentral + run: ./gradlew nvplib:core:publishToMavenCentral nvplib:nfc:publishToMavenCentral --no-configuration-cache + env: + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.MAVEN_CENTRAL_USERNAME }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.MAVEN_CENTRAL_PASSWORD }} + ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.SIGNING_KEY_ID }} + ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }} + ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.GPG_KEY_CONTENTS }} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 5ed1402..23642f5 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -43,3 +43,9 @@ sonar { property("sonar.organization", "lcacheux") } } + +val nvplibVersion: String? by extra { + providers.exec { + commandLine("git", "describe", "--tags", "--match", "nvplib-*") + }.standardOutput.asText.get().trim().removePrefix("nvplib-") +} diff --git a/gradle.properties b/gradle.properties index 817e04e..a87bfa9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,3 +21,4 @@ kotlin.code.style=official # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library android.nonTransitiveRClass=true +ksp.useKSP2=false \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b630e72..745bb4b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,19 +1,20 @@ [versions] java = "21" +nvplibJava = "8" android-minSdk = "24" android-compileSdk = "36" agp = "8.13.2" -compose-plugin="1.9.0" -hilt = "2.57.1" -kotlin = "2.1.21" +compose-plugin="1.9.3" +hilt = "2.57.2" +kotlin = "2.2.20" coroutines = "1.10.2" -room = "2.8.2" -sqlite = "2.6.1" -androidx-datastore = "1.1.7" -bytonio = "0.0.1" +room = "2.8.4" +sqlite = "2.6.2" +androidx-datastore = "1.2.0" +bytonio = "0.0.3" [plugins] -ksp = { id = "com.google.devtools.ksp", version = "2.1.21-2.0.1" } +ksp = { id = "com.google.devtools.ksp", version = "2.2.20-2.0.4" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } @@ -23,20 +24,21 @@ hilt-android = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } room = { id = "androidx.room", version.ref = "room" } jetbrains-compose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } -dokka = { id = "org.jetbrains.dokka", version = "2.0.0" } +dokka = { id = "org.jetbrains.dokka", version = "2.1.0" } sonarqube = { id = "org.sonarqube", version = "6.3.1.5724" } +mavenPublish = { id = "com.vanniktech.maven.publish", version = "0.35.0" } [libraries] -colorpicker-compose = { module = "com.github.skydoves:colorpicker-compose", version = "1.1.2" } +colorpicker-compose = { module = "com.github.skydoves:colorpicker-compose", version = "1.1.3" } filekit-compose = { module = "io.github.vinceglb:filekit-compose", version = "0.8.8" } kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" } kotlinx-coroutines-swing = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-swing", version.ref = "coroutines" } kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "coroutines" } -androidx-activity-compose = { module = "androidx.activity:activity-compose", version = "1.11.0" } +androidx-activity-compose = { module = "androidx.activity:activity-compose", version = "1.12.1" } androidx-datastore-preferences = { module = "androidx.datastore:datastore-preferences", version = "androidx-datastore" } androidx-datastore-core = { module = "androidx.datastore:datastore-core", version.ref = "androidx-datastore" } -androidx-lifecycle-viewmodel-compose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version = "2.9.3" } +androidx-lifecycle-viewmodel-compose = { module = "org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose", version = "2.9.6" } # Room androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" } @@ -60,4 +62,4 @@ androidx-test-runner = { group = "androidx.test", name = "runner", version="1.7. mockito-android = { group = "org.mockito", name = "mockito-android", version = "5.20.0" } mockito-kotlin = { group = "org.mockito.kotlin", name = "mockito-kotlin", version = "6.1.0" } turbine = { group = "app.cash.turbine", name = "turbine", version = "1.2.1" } -androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version = "1.9.3" } +androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version = "1.10.0" } diff --git a/nvplib/core/build.gradle.kts b/nvplib/core/build.gradle.kts index 8be9c3c..9a39898 100644 --- a/nvplib/core/build.gradle.kts +++ b/nvplib/core/build.gradle.kts @@ -1,18 +1,57 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask + plugins { - id("java-library") - id("maven-publish") - alias(libs.plugins.kotlin.jvm) + alias(libs.plugins.kotlin.multiplatform) alias(libs.plugins.dokka) alias(libs.plugins.ksp) - signing + alias(libs.plugins.mavenPublish) } +val nvplibVersion: String? by project +group = "net.cacheux.nvplib" +version = nvplibVersion ?: "unknown" + kotlin { - jvmToolchain(libs.versions.java.get().toInt()) -} + jvmToolchain(libs.versions.nvplibJava.get().toInt()) + + jvm() + + val xcfName = "bytonioKit" + + iosX64 { + binaries.framework { + baseName = xcfName + } + } -java { - withSourcesJar() + iosArm64 { + binaries.framework { + baseName = xcfName + } + } + + iosSimulatorArm64 { + binaries.framework { + baseName = xcfName + } + } + + sourceSets { + commonMain { + kotlin.srcDir("build/generated/ksp/metadata/commonMain/kotlin") + dependencies { + api(libs.bytonio.core) + } + } + + jvmTest { + dependencies { + implementation(libs.junit) + implementation(project(":nvplib:testing")) + implementation(project(":utils")) + } + } + } } ksp { @@ -21,79 +60,47 @@ ksp { } dependencies { - api(libs.bytonio.core) - ksp(libs.bytonio.processor) - - testImplementation(libs.junit) - testImplementation(project(":nvplib:testing")) - testImplementation(project(":utils")) + add("kspCommonMainMetadata", libs.bytonio.processor) } -tasks.register("dokkaHtmlJar") { - dependsOn(tasks.dokkaHtml) - from(tasks.dokkaHtml.flatMap { it.outputDirectory }) - archiveClassifier.set("html-docs") -} +mavenPublishing { + publishToMavenCentral() -tasks.register("dokkaJavadocJar") { - dependsOn(tasks.dokkaJavadoc) - from(tasks.dokkaJavadoc.flatMap { it.outputDirectory }) - archiveClassifier.set("javadoc") -} + signAllPublications() -publishing { - repositories { - maven { - url = uri(layout.buildDirectory.dir("release")) - } - } + coordinates(group.toString(), "nvplib-core", version.toString()) - publications { - create("mavenCore") { - groupId = "net.cacheux.nvplib" - artifactId = "nvplib-core" - version = "0.1.2" - afterEvaluate { - from(components["java"]) - artifact(tasks["dokkaHtmlJar"]) - artifact(tasks["dokkaJavadocJar"]) + pom { + name = "NVP Lib Core" + description = "Core library to read data from Novopen insulin pens" + url = "https://github.com/lcacheux/nov-open-reader" + licenses { + license { + name = "The Apache License, Version 2.0" + url = "https://www.apache.org/licenses/LICENSE-2.0.txt" } - - pom { - name = "NVP Lib Core" - description = "Core library to read data from Novopen insulin pens" - url = "https://github.com/lcacheux/nov-open-reader" - licenses { - license { - name = "The Apache License, Version 2.0" - url = "https://www.apache.org/licenses/LICENSE-2.0.txt" - } - } - developers { - developer { - id = "lcacheux" - name = "Leo Cacheux" - email = "leo@cacheux.net" - } - } - scm { - connection = "scm:git:https://github.com/lcacheux/nov-open-reader.git" - developerConnection = "scm:git:ssh://github.com/lcacheux/nov-open-reader.git" - url = "https://github.com/lcacheux/nov-open-reader" - } + } + developers { + developer { + id = "lcacheux" + name = "Leo Cacheux" + email = "leo@cacheux.net" } } + scm { + connection = "scm:git:https://github.com/lcacheux/nov-open-reader.git" + developerConnection = "scm:git:ssh://github.com/lcacheux/nov-open-reader.git" + url = "https://github.com/lcacheux/nov-open-reader" + } } } -val signingIfAvailable: (Publication) -> Unit by project -signingIfAvailable(publishing.publications.getByName("mavenCore")) - -tasks.create("bundleZip") { - dependsOn("publish") - from(layout.buildDirectory.dir("release").get()) { - exclude("**/*.asc.*") +afterEvaluate { + tasks.withType(KotlinCompilationTask::class).configureEach { + if (name != "kspCommonMainKotlinMetadata") { + dependsOn("kspCommonMainKotlinMetadata") + } } - archiveFileName = "nvplib-core.zip" - destinationDirectory = layout.buildDirectory.dir("bundle").get() + tasks.findByName("sourcesJar")?.dependsOn("kspCommonMainKotlinMetadata") } + diff --git a/nvplib/core/src/main/AndroidManifest.xml b/nvplib/core/src/commonMain/AndroidManifest.xml similarity index 100% rename from nvplib/core/src/main/AndroidManifest.xml rename to nvplib/core/src/commonMain/AndroidManifest.xml diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/DataReader.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/DataReader.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/DataReader.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/DataReader.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/NvpController.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/NvpController.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/NvpController.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/NvpController.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/PayloadFunctions.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/PayloadFunctions.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/PayloadFunctions.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/PayloadFunctions.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/PhdManager.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/PhdManager.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/PhdManager.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/PhdManager.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/StopConditionUtils.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/StopConditionUtils.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/StopConditionUtils.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/StopConditionUtils.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/TransceiveResult.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/TransceiveResult.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/TransceiveResult.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/TransceiveResult.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ARequest.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/ARequest.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ARequest.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/ARequest.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/AResponse.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/AResponse.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/AResponse.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/AResponse.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Apdu.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/Apdu.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Apdu.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/Apdu.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ApoepElement.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/ApoepElement.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ApoepElement.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/ApoepElement.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ArgumentsSimple.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/ArgumentsSimple.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ArgumentsSimple.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/ArgumentsSimple.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Attribute.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/Attribute.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Attribute.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/Attribute.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Configuration.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/Configuration.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Configuration.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/Configuration.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ConfirmedAction.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/ConfirmedAction.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/ConfirmedAction.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/ConfirmedAction.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/DataApdu.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/DataApdu.kt similarity index 78% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/DataApdu.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/DataApdu.kt index bc6f63d..f738d0e 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/DataApdu.kt +++ b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/DataApdu.kt @@ -8,6 +8,7 @@ import net.cacheux.bytonio.annotations.Deserializer import net.cacheux.bytonio.annotations.EncodeAsShort import net.cacheux.bytonio.annotations.Serializer import net.cacheux.bytonio.utils.ByteArrayReader +import net.cacheux.bytonio.utils.ByteArrayWriter import net.cacheux.bytonio.utils.reader import net.cacheux.nvplib.data.DataApdu.Companion.CONFIRMED_ACTION_CHOSEN import net.cacheux.nvplib.data.DataApdu.Companion.CONFIRMED_EVENT_REPORT_CHOSEN @@ -16,7 +17,6 @@ import net.cacheux.nvplib.data.DataApdu.Companion.MDC_ACT_SEG_GET_INFO import net.cacheux.nvplib.data.DataApdu.Companion.MDC_ACT_SEG_TRIG_XFER import net.cacheux.nvplib.data.DataApdu.Companion.SGET_CHOSEN import net.cacheux.nvplib.generated.TriggerSegmentDataXferDeserializer -import java.nio.ByteBuffer @DataObject @Serializer(DataApduSerializer::class) @@ -38,24 +38,9 @@ data class DataApdu( const val MDC_ACT_SEG_TRIG_XFER = 0x0C1C } - override fun getBinarySize(): Int { - return 6 + (payload?.let { it.getBinarySize() + 2 } ?: 0) - } + override fun getBinarySize() = DataApduSerializer.getBinarySize(this) - override fun toByteArray(): ByteArray { - val payloadSize = (payload?.let { - it.getBinarySize() + 2 - } ?: 0) - return ByteBuffer.allocate(getBinarySize()).apply { - putShort((payloadSize + 4).toShort()) - putShort(invokeId.toShort()) - putShort(dchoice.toShort()) - payload?.let { - putShort(payload.getBinarySize().toShort()) - put(payload.toByteArray()) - } - }.array() - } + override fun toByteArray() = DataApduSerializer.toByteArray(this) } object DataApduSerializer: BinarySerializer { @@ -67,15 +52,15 @@ object DataApduSerializer: BinarySerializer { val payloadSize = (data.payload?.let { it.getBinarySize() + 2 } ?: 0) - return ByteBuffer.allocate(data.getBinarySize()).apply { - putShort((payloadSize + 4).toShort()) - putShort(data.invokeId.toShort()) - putShort(data.dchoice.toShort()) + return ByteArrayWriter(ByteArray(size = data.getBinarySize())).apply { + writeShort((payloadSize + 4).toShort()) + writeShort(data.invokeId.toShort()) + writeShort(data.dchoice.toShort()) data.payload?.let { - putShort(data.payload.getBinarySize().toShort()) - put(data.payload.toByteArray()) + writeShort(data.payload.getBinarySize().toShort()) + writeByteArray(data.payload.toByteArray()) } - }.array() + }.byteArray } } diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/DummyBinarySerializable.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/DummyBinarySerializable.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/DummyBinarySerializable.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/DummyBinarySerializable.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/EventReport.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/EventReport.kt similarity index 91% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/EventReport.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/EventReport.kt index 4d2b824..fdcddee 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/EventReport.kt +++ b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/EventReport.kt @@ -2,7 +2,10 @@ package net.cacheux.nvplib.data import net.cacheux.bytonio.annotations.IgnoreEncoding import net.cacheux.bytonio.utils.ByteArrayReader +import kotlin.time.Clock +import kotlin.time.ExperimentalTime +@OptIn(ExperimentalTime::class) data class EventReport( val handle: Int, val relativeTime: Int, @@ -32,7 +35,7 @@ data class EventReport( reader.readShort() // status reader.readShort() // bcount - val currentTime = System.currentTimeMillis() + val currentTime = Clock.System.now().toEpochMilliseconds() repeat(count) { InsulinDoseDeserializer.fromByteArrayReader(reader).let { diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/EventRequest.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/EventRequest.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/EventRequest.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/EventRequest.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/FullSpecification.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/FullSpecification.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/FullSpecification.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/FullSpecification.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/InsulinDose.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/InsulinDose.kt similarity index 89% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/InsulinDose.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/InsulinDose.kt index e5dc6ed..e0c515f 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/InsulinDose.kt +++ b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/InsulinDose.kt @@ -8,7 +8,10 @@ import net.cacheux.bytonio.annotations.EncodeAsInt import net.cacheux.bytonio.utils.ByteArrayReader import net.cacheux.bytonio.utils.reader import net.cacheux.nvplib.generated.InsulinDoseSerializer +import kotlin.time.Clock +import kotlin.time.ExperimentalTime +@OptIn(ExperimentalTime::class) @DataObject @Deserializer(InsulinDoseDeserializer::class) data class InsulinDose( @@ -26,7 +29,7 @@ data class InsulinDose( * @param relativeTime Should be the value parsed with [EventReport] * @param currentTime Current time in millis. Should be System.currentTimeMillis() */ - fun withUtcTime(relativeTime: Int, currentTime: Long = System.currentTimeMillis()) = InsulinDose( + fun withUtcTime(relativeTime: Int, currentTime: Long = Clock.System.now().toEpochMilliseconds()) = InsulinDose( time = (currentTime - ( (relativeTime - time) * 1000 )), units = units, flags = flags ) diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/PenResult.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/PenResult.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/PenResult.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/PenResult.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/PhdPacket.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/PhdPacket.kt similarity index 97% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/PhdPacket.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/PhdPacket.kt index 901dd8f..c5f95ae 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/PhdPacket.kt +++ b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/PhdPacket.kt @@ -58,7 +58,7 @@ data class PhdPacket( if (hasId && header != null) { writeByteArray(header) } - writeByteArray("PHD".toByteArray()) + writeByteArray("PHD".encodeToByteArray()) putUnsignedByte(seq and 0x0F or 0x80 or chk) if (ilen > 0) { writeByteArray(content) diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentEntry.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/SegmentEntry.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentEntry.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/SegmentEntry.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfo.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/SegmentInfo.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfo.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/SegmentInfo.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfoList.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/SegmentInfoList.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfoList.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/SegmentInfoList.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfoMap.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/SegmentInfoMap.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/SegmentInfoMap.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/SegmentInfoMap.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Specification.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/Specification.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/Specification.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/Specification.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/T4Update.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/T4Update.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/T4Update.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/T4Update.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/TriggerSegmentDataXfer.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/TriggerSegmentDataXfer.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/data/TriggerSegmentDataXfer.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/data/TriggerSegmentDataXfer.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/utils/ByteUtils.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/utils/ByteUtils.kt similarity index 89% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/utils/ByteUtils.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/utils/ByteUtils.kt index 4b7409d..1e510f0 100644 --- a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/utils/ByteUtils.kt +++ b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/utils/ByteUtils.kt @@ -20,7 +20,7 @@ fun ByteArrayReader.getUnsignedByte(): Int { } fun ByteArrayReader.getIndexedString() = - String(readByteArray(getUnsignedShort())).replace( + readByteArray(getUnsignedShort()).decodeToString().replace( "\u0000", "" ) diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/utils/TimeUtils.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/utils/TimeUtils.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/utils/TimeUtils.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/utils/TimeUtils.kt diff --git a/nvplib/core/src/main/kotlin/net/cacheux/nvplib/utils/Utils.kt b/nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/utils/Utils.kt similarity index 100% rename from nvplib/core/src/main/kotlin/net/cacheux/nvplib/utils/Utils.kt rename to nvplib/core/src/commonMain/kotlin/net/cacheux/nvplib/utils/Utils.kt diff --git a/nvplib/core/src/test/kotlin/net/cacheux/nvplib/NvpControllerTest.kt b/nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/NvpControllerTest.kt similarity index 100% rename from nvplib/core/src/test/kotlin/net/cacheux/nvplib/NvpControllerTest.kt rename to nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/NvpControllerTest.kt diff --git a/nvplib/core/src/test/kotlin/net/cacheux/nvplib/StopConditionUtilsTest.kt b/nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/StopConditionUtilsTest.kt similarity index 100% rename from nvplib/core/src/test/kotlin/net/cacheux/nvplib/StopConditionUtilsTest.kt rename to nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/StopConditionUtilsTest.kt diff --git a/nvplib/core/src/test/kotlin/net/cacheux/nvplib/data/ConfirmedActionTest.kt b/nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/data/ConfirmedActionTest.kt similarity index 100% rename from nvplib/core/src/test/kotlin/net/cacheux/nvplib/data/ConfirmedActionTest.kt rename to nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/data/ConfirmedActionTest.kt diff --git a/nvplib/core/src/test/kotlin/net/cacheux/nvplib/data/DataApduTest.kt b/nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/data/DataApduTest.kt similarity index 100% rename from nvplib/core/src/test/kotlin/net/cacheux/nvplib/data/DataApduTest.kt rename to nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/data/DataApduTest.kt diff --git a/nvplib/core/src/test/kotlin/net/cacheux/nvplib/utils/ByteUtilsTest.kt b/nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/utils/ByteUtilsTest.kt similarity index 100% rename from nvplib/core/src/test/kotlin/net/cacheux/nvplib/utils/ByteUtilsTest.kt rename to nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/utils/ByteUtilsTest.kt diff --git a/nvplib/core/src/test/kotlin/net/cacheux/nvplib/utils/TimeUtilsTest.kt b/nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/utils/TimeUtilsTest.kt similarity index 100% rename from nvplib/core/src/test/kotlin/net/cacheux/nvplib/utils/TimeUtilsTest.kt rename to nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/utils/TimeUtilsTest.kt diff --git a/nvplib/core/src/test/kotlin/net/cacheux/nvplib/utils/UtilsTest.kt b/nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/utils/UtilsTest.kt similarity index 100% rename from nvplib/core/src/test/kotlin/net/cacheux/nvplib/utils/UtilsTest.kt rename to nvplib/core/src/jvmTest/kotlin/net/cacheux/nvplib/utils/UtilsTest.kt diff --git a/nvplib/nfc/build.gradle.kts b/nvplib/nfc/build.gradle.kts index 737c8e8..17bcf81 100644 --- a/nvplib/nfc/build.gradle.kts +++ b/nvplib/nfc/build.gradle.kts @@ -1,13 +1,16 @@ plugins { - id("maven-publish") alias(libs.plugins.android.library) alias(libs.plugins.kotlin.android) alias(libs.plugins.dokka) - signing + alias(libs.plugins.mavenPublish) } +val nvplibVersion: String? by project +group = "net.cacheux.nvplib" +version = nvplibVersion ?: "unknown" + kotlin { - jvmToolchain(libs.versions.java.get().toInt()) + jvmToolchain(libs.versions.nvplibJava.get().toInt()) } android { @@ -30,81 +33,40 @@ android { ) } } - - publishing { - singleVariant("release") {} - } } dependencies { implementation(project(":nvplib:core")) } -tasks.register("dokkaHtmlJar") { - dependsOn(tasks.dokkaHtml) - from(tasks.dokkaHtml.flatMap { it.outputDirectory }) - archiveClassifier.set("html-docs") -} +mavenPublishing { + publishToMavenCentral() -tasks.register("dokkaJavadocJar") { - dependsOn(tasks.dokkaJavadoc) - from(tasks.dokkaJavadoc.flatMap { it.outputDirectory }) - archiveClassifier.set("javadoc") -} + signAllPublications() -publishing { - repositories { - maven { - url = uri(layout.buildDirectory.dir("release")) - } - } + coordinates(group.toString(), "nvplib-nfc-android", version.toString()) - publications { - create("mavenNfc") { - groupId = "net.cacheux.nvplib" - artifactId = "nvplib-nfc" - version = "0.1.2" - afterEvaluate { - from(components["release"]) - artifact(tasks["dokkaHtmlJar"]) - artifact(tasks["dokkaJavadocJar"]) + pom { + name = "NVP Lib NFC" + description = "Android NFC implementation to read data from Novopen insulin pens" + url = "https://github.com/lcacheux/nov-open-reader" + licenses { + license { + name = "The Apache License, Version 2.0" + url = "https://www.apache.org/licenses/LICENSE-2.0.txt" } - - pom { - name = "NVP Lib NFC" - description = "Android NFC implementation to read data from Novopen insulin pens" - url = "https://github.com/lcacheux/nov-open-reader" - licenses { - license { - name = "The Apache License, Version 2.0" - url = "https://www.apache.org/licenses/LICENSE-2.0.txt" - } - } - developers { - developer { - id = "lcacheux" - name = "Leo Cacheux" - email = "leo@cacheux.net" - } - } - scm { - connection = "scm:git:https://github.com/lcacheux/nov-open-reader.git" - developerConnection = "scm:git:ssh://github.com/lcacheux/nov-open-reader.git" - url = "https://github.com/lcacheux/nov-open-reader" - } + } + developers { + developer { + id = "lcacheux" + name = "Leo Cacheux" + email = "leo@cacheux.net" } } + scm { + connection = "scm:git:https://github.com/lcacheux/nov-open-reader.git" + developerConnection = "scm:git:ssh://github.com/lcacheux/nov-open-reader.git" + url = "https://github.com/lcacheux/nov-open-reader" + } } } - -val signingIfAvailable: (Publication) -> Unit by project -signingIfAvailable(publishing.publications.getByName("mavenNfc")) - -tasks.create("bundleZip") { - dependsOn("publish") - from(layout.buildDirectory.dir("release").get()) { - exclude("**/*.asc.*") - } - archiveFileName = "nvplib-nfc.zip" - destinationDirectory = layout.buildDirectory.dir("bundle").get() -} diff --git a/nvplib/testing/build.gradle.kts b/nvplib/testing/build.gradle.kts index fb8a310..6f83f91 100644 --- a/nvplib/testing/build.gradle.kts +++ b/nvplib/testing/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } kotlin { - jvmToolchain(libs.versions.java.get().toInt()) + jvmToolchain(libs.versions.nvplibJava.get().toInt()) } dependencies { diff --git a/settings.gradle.kts b/settings.gradle.kts index 4262fe4..54c76e2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,6 +13,10 @@ dependencyResolutionManagement { } } +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" +} + rootProject.name = "nov-open-reader" include(":app") diff --git a/utils/build.gradle.kts b/utils/build.gradle.kts index af4aeac..d617372 100644 --- a/utils/build.gradle.kts +++ b/utils/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } kotlin { - jvmToolchain(libs.versions.java.get().toInt()) + jvmToolchain(libs.versions.nvplibJava.get().toInt()) } dependencies { From 6d991544d7cab7439a51141b844628ced224c5ca Mon Sep 17 00:00:00 2001 From: Leo CACHEUX Date: Sun, 21 Dec 2025 11:03:33 +0100 Subject: [PATCH 3/3] Update JDK to 21 for build setup --- .github/workflows/build.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f02281a..9ffa9c5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,11 +13,11 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Set up JDK 17 + - name: Set up JDK 21 uses: actions/setup-java@v4 with: - java-version: 17 - distribution: 'zulu' # Alternative distribution options are available + distribution: 'zulu' + java-version: 21 - name: Cache SonarQube packages uses: actions/cache@v4 with: