@@ -30,7 +30,7 @@ import com.health.openscale.core.utils.ConverterUtils
3030 * - "OKOK V20" (manufacturer id 0x20CA): stable flag + XOR checksum
3131 * - "OKOK V11" (manufacturer id 0x11CA): XOR checksum, unit & resolution in body properties
3232 * - "OKOK VF0" (manufacturer id 0xF0FF): simple weight field
33- * - "OKOK Nameless " (any manufacturer id where low byte == 0xC0): MAC-embedded, unit & resolution in attrib
33+ * - "OKOK C0 " (any manufacturer id where low byte == 0xC0): MAC-embedded, unit & resolution in attrib
3434 *
3535 * Link mode: BROADCAST_ONLY (no GATT connection).
3636 */
@@ -59,31 +59,40 @@ class OkOkHandler : ScaleDeviceHandler() {
5959 private val IDX_VF0_WEIGHT_MSB = 3
6060 private val IDX_VF0_WEIGHT_LSB = 2
6161
62- // Nameless/ 0xC0 indices
62+ // 0xC0 indices
6363 private val IDX_WEIGHT_MSB = 0
6464 private val IDX_WEIGHT_LSB = 1
6565 private val IDX_ATTRIB = 6
6666 private val UNIT_KG = 0
67+ private val UNIT_JIN = 1
6768 private val UNIT_LB = 2
6869 private val UNIT_STLB = 3
6970
71+ private val NamelessAlias = " OKOK Nameless"
72+
7073 /* *
7174 * Decide support + build a *dynamic* displayName based on manufacturer data present
7275 * in the advertisement that matched this device.
7376 */
7477 override fun supportFor (device : ScannedDeviceInfo ): DeviceSupport ? {
7578 val m = device.manufacturerData ? : return null
7679
80+ if (device.name.isEmpty() && containsLowByteC0(m))
81+ device.name = NamelessAlias
7782 val name = device.name
7883
79- val supports = name.equals(" NoName OkOk" ) || name.equals(" ADV" ) || name.equals(" Chipsea-BLE" )
84+ val supports = name.equals(NamelessAlias )
85+ || name.equals(" ADV" )
86+ || name.equals(" Chipsea-BLE" )
87+ || name.startsWith(" Yoda0" , ignoreCase = true )
88+ || name.startsWith(" Yoda1" , ignoreCase = true )
8089 if (! supports) return null
8190
8291 val variantName = when {
8392 hasKey(m, MANUF_V20 ) -> " OKOK V20"
8493 hasKey(m, MANUF_V11 ) -> " OKOK V11"
8594 hasKey(m, MANUF_VF0 ) -> " OKOK VF0"
86- containsLowByteC0(m) -> " OKOK Nameless "
95+ containsLowByteC0(m) -> " OKOK C0 "
8796 else -> null
8897 } ? : return null
8998
@@ -128,8 +137,8 @@ class OkOkHandler : ScaleDeviceHandler() {
128137 return BroadcastAction .CONSUMED_STOP
129138 }
130139
131- // Fallback: nameless 0xC0 vendor
132- parseNameless (m)?.let { kg ->
140+ // Fallback: 0xC0 vendor
141+ parseC0 (m)?.let { kg ->
133142 publish(ScaleMeasurement ().apply { userId = user.id; weight = kg })
134143 return BroadcastAction .CONSUMED_STOP
135144 }
@@ -186,10 +195,10 @@ class OkOkHandler : ScaleDeviceHandler() {
186195
187196 // unit ((props >> 3) & 3)
188197 return when ((props shr 3 ) and 0x3 ) {
189- 0 -> weight / divider // kg
190- 1 -> weight / (divider * 2.0f ) // jin → kg (approx. )
191- 2 -> (weight / divider) / 2.204623f // lb → kg
192- 3 -> { // st&lb
198+ UNIT_KG -> weight / divider
199+ UNIT_JIN -> weight / (divider * 2.0f )
200+ UNIT_LB -> (weight / divider) / 2.204623f
201+ UNIT_STLB -> {
193202 val stones = (weight shr 8 )
194203 val pounds = (weight and 0xFF ) / divider
195204 stones * 6.350293f + pounds * 0.453592f
@@ -205,7 +214,7 @@ class OkOkHandler : ScaleDeviceHandler() {
205214 return raw / 10.0f
206215 }
207216
208- private fun parseNameless (m : SparseArray <ByteArray >): Float? {
217+ private fun parseC0 (m : SparseArray <ByteArray >): Float? {
209218 val key = firstKeyWithLowByteC0(m) ? : return null
210219 val data = m.get(key) ? : return null
211220 if (data.size < 13 ) return null
@@ -226,6 +235,10 @@ class OkOkHandler : ScaleDeviceHandler() {
226235 val raw = u16be(data[IDX_WEIGHT_MSB ], data[IDX_WEIGHT_LSB ])
227236 raw / divider
228237 }
238+ UNIT_JIN -> {
239+ val raw = u16be(data[IDX_WEIGHT_MSB ], data[IDX_WEIGHT_LSB ])
240+ raw / divider / 2
241+ }
229242 UNIT_LB -> {
230243 val raw = u16be(data[IDX_WEIGHT_MSB ], data[IDX_WEIGHT_LSB ])
231244 ConverterUtils .toKilogram(raw / divider, WeightUnit .LB )
0 commit comments