cubing 0.57.3 → 0.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/cubing/bluetooth/index.js +697 -53
- package/dist/lib/cubing/bluetooth/index.js.map +4 -4
- package/dist/lib/cubing/chunks/{chunk-CJSXUBHM.js → chunk-2H2XY6KQ.js} +101 -24
- package/dist/lib/cubing/chunks/chunk-2H2XY6KQ.js.map +7 -0
- package/dist/lib/cubing/chunks/{chunk-4SW5YMBF.js → chunk-3U3UEVVD.js} +2 -2
- package/dist/lib/cubing/chunks/{chunk-XWAGJB3J.js → chunk-F7UESNJD.js} +15 -10
- package/dist/lib/cubing/chunks/{chunk-XWAGJB3J.js.map → chunk-F7UESNJD.js.map} +2 -2
- package/dist/lib/cubing/chunks/{chunk-VZOWBQJT.js → chunk-H75BKRPQ.js} +2 -2
- package/dist/lib/cubing/chunks/{inside-CE7DDCWK.js → inside-AYMLD6IQ.js} +7 -7
- package/dist/lib/cubing/chunks/{search-dynamic-sgs-side-events-QYEVKG6G.js → search-dynamic-sgs-side-events-T4N6YHT7.js} +2 -2
- package/dist/lib/cubing/chunks/{search-dynamic-sgs-unofficial-CD7VNHVB.js → search-dynamic-sgs-unofficial-EQIJODP7.js} +2 -2
- package/dist/lib/cubing/chunks/{search-dynamic-solve-4x4x4-6CAJNKYW.js → search-dynamic-solve-4x4x4-NT5XKSLV.js} +4 -4
- package/dist/lib/cubing/chunks/search-worker-entry.js +1 -1
- package/dist/lib/cubing/chunks/{twisty-dynamic-3d-PGO6KXRX.js → twisty-dynamic-3d-FRZJG7S6.js} +3 -3
- package/dist/lib/cubing/puzzles/index.d.ts +2 -0
- package/dist/lib/cubing/puzzles/index.js +1 -1
- package/dist/lib/cubing/scramble/index.js +3 -3
- package/dist/lib/cubing/search/index.js +3 -3
- package/dist/lib/cubing/twisty/index.js +2 -2
- package/package.json +4 -3
- package/dist/lib/cubing/chunks/chunk-CJSXUBHM.js.map +0 -7
- /package/dist/lib/cubing/chunks/{chunk-4SW5YMBF.js.map → chunk-3U3UEVVD.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{chunk-VZOWBQJT.js.map → chunk-H75BKRPQ.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{inside-CE7DDCWK.js.map → inside-AYMLD6IQ.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{search-dynamic-sgs-side-events-QYEVKG6G.js.map → search-dynamic-sgs-side-events-T4N6YHT7.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{search-dynamic-sgs-unofficial-CD7VNHVB.js.map → search-dynamic-sgs-unofficial-EQIJODP7.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{search-dynamic-solve-4x4x4-6CAJNKYW.js.map → search-dynamic-solve-4x4x4-NT5XKSLV.js.map} +0 -0
- /package/dist/lib/cubing/chunks/{twisty-dynamic-3d-PGO6KXRX.js.map → twisty-dynamic-3d-FRZJG7S6.js.map} +0 -0
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
cube3x3x3,
|
|
7
7
|
puzzles
|
|
8
|
-
} from "../chunks/chunk-
|
|
8
|
+
} from "../chunks/chunk-2H2XY6KQ.js";
|
|
9
9
|
import {
|
|
10
10
|
experimental3x3x3KPuzzle
|
|
11
11
|
} from "../chunks/chunk-666TWRT6.js";
|
|
@@ -268,6 +268,12 @@ async function unsafeEncryptBlockWithIV(key, plaintextBlock, iv) {
|
|
|
268
268
|
);
|
|
269
269
|
return cryptoResult.slice(0, blockSize);
|
|
270
270
|
}
|
|
271
|
+
async function unsafeEncryptBlock(key, plaintextBlock) {
|
|
272
|
+
return (await unsafeEncryptBlockWithIV(key, plaintextBlock, zeros)).slice(
|
|
273
|
+
0,
|
|
274
|
+
blockSize
|
|
275
|
+
);
|
|
276
|
+
}
|
|
271
277
|
async function unsafeDecryptBlock(key, ciphertextBlock) {
|
|
272
278
|
const paddingBlock = await unsafeEncryptBlockWithIV(
|
|
273
279
|
key,
|
|
@@ -288,6 +294,52 @@ async function unsafeDecryptBlock(key, ciphertextBlock) {
|
|
|
288
294
|
return cryptoResult.slice(0, blockSize);
|
|
289
295
|
}
|
|
290
296
|
|
|
297
|
+
// src/cubing/bluetooth/smart-puzzle/common.ts
|
|
298
|
+
var reidEdgeOrder = "UF UR UB UL DF DR DB DL FR FL BR BL".split(" ");
|
|
299
|
+
var reidCornerOrder = "UFR URB UBL ULF DRF DFL DLB DBR".split(" ");
|
|
300
|
+
function rotateLeft(s, i) {
|
|
301
|
+
return s.slice(i) + s.slice(0, i);
|
|
302
|
+
}
|
|
303
|
+
var pieceMap = {};
|
|
304
|
+
reidEdgeOrder.forEach((edge, idx) => {
|
|
305
|
+
for (let i = 0; i < 2; i++) {
|
|
306
|
+
pieceMap[rotateLeft(edge, i)] = { piece: idx, orientation: i };
|
|
307
|
+
}
|
|
308
|
+
});
|
|
309
|
+
reidCornerOrder.forEach((corner, idx) => {
|
|
310
|
+
for (let i = 0; i < 3; i++) {
|
|
311
|
+
pieceMap[rotateLeft(corner, i)] = { piece: idx, orientation: i };
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
function getPatternData(stickers, faceOrder3, edgeMappings, cornerMappings) {
|
|
315
|
+
const patternData = {
|
|
316
|
+
CORNERS: {
|
|
317
|
+
pieces: [],
|
|
318
|
+
orientation: []
|
|
319
|
+
},
|
|
320
|
+
EDGES: {
|
|
321
|
+
pieces: [],
|
|
322
|
+
orientation: []
|
|
323
|
+
},
|
|
324
|
+
CENTERS: {
|
|
325
|
+
pieces: [0, 1, 2, 3, 4, 5],
|
|
326
|
+
orientation: [0, 0, 0, 0, 0, 0],
|
|
327
|
+
orientationMod: [1, 1, 1, 1, 1, 1]
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
for (const cornerMapping of cornerMappings) {
|
|
331
|
+
const pieceInfo = pieceMap[cornerMapping.map((i) => faceOrder3[stickers[i]]).join("")];
|
|
332
|
+
patternData["CORNERS"].pieces.push(pieceInfo.piece);
|
|
333
|
+
patternData["CORNERS"].orientation.push(pieceInfo.orientation);
|
|
334
|
+
}
|
|
335
|
+
for (const edgeMapping of edgeMappings) {
|
|
336
|
+
const pieceInfo = pieceMap[edgeMapping.map((i) => faceOrder3[stickers[i]]).join("")];
|
|
337
|
+
patternData["EDGES"].pieces.push(pieceInfo.piece);
|
|
338
|
+
patternData["EDGES"].orientation.push(pieceInfo.orientation);
|
|
339
|
+
}
|
|
340
|
+
return patternData;
|
|
341
|
+
}
|
|
342
|
+
|
|
291
343
|
// src/cubing/bluetooth/smart-puzzle/gan.ts
|
|
292
344
|
var DEFAULT_INTERVAL_MS = 150;
|
|
293
345
|
var MAX_LATEST_MOVES = 6;
|
|
@@ -454,22 +506,6 @@ function buf2hex(buffer) {
|
|
|
454
506
|
(x) => `00${x.toString(16)}`.slice(-2)
|
|
455
507
|
).join(" ");
|
|
456
508
|
}
|
|
457
|
-
var reidEdgeOrder = "UF UR UB UL DF DR DB DL FR FL BR BL".split(" ");
|
|
458
|
-
var reidCornerOrder = "UFR URB UBL ULF DRF DFL DLB DBR".split(" ");
|
|
459
|
-
function rotateLeft(s, i) {
|
|
460
|
-
return s.slice(i) + s.slice(0, i);
|
|
461
|
-
}
|
|
462
|
-
var pieceMap = {};
|
|
463
|
-
reidEdgeOrder.forEach((edge, idx) => {
|
|
464
|
-
for (let i = 0; i < 2; i++) {
|
|
465
|
-
pieceMap[rotateLeft(edge, i)] = { piece: idx, orientation: i };
|
|
466
|
-
}
|
|
467
|
-
});
|
|
468
|
-
reidCornerOrder.forEach((corner, idx) => {
|
|
469
|
-
for (let i = 0; i < 3; i++) {
|
|
470
|
-
pieceMap[rotateLeft(corner, i)] = { piece: idx, orientation: i };
|
|
471
|
-
}
|
|
472
|
-
});
|
|
473
509
|
var gan356iCornerMappings = [
|
|
474
510
|
[0, 21, 15],
|
|
475
511
|
[5, 13, 47],
|
|
@@ -625,33 +661,15 @@ var GanCube = class _GanCube extends BluetoothPuzzle {
|
|
|
625
661
|
v >>= 3;
|
|
626
662
|
}
|
|
627
663
|
}
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
CENTERS: {
|
|
638
|
-
pieces: [0, 1, 2, 3, 4, 5],
|
|
639
|
-
orientation: [0, 0, 0, 0, 0, 0],
|
|
640
|
-
orientationMod: [1, 1, 1, 1, 1, 1]
|
|
641
|
-
// TODO
|
|
642
|
-
}
|
|
643
|
-
};
|
|
644
|
-
for (const cornerMapping of gan356iCornerMappings) {
|
|
645
|
-
const pieceInfo = pieceMap[cornerMapping.map((i) => faceOrder[stickers[i]]).join("")];
|
|
646
|
-
patternData["CORNERS"].pieces.push(pieceInfo.piece);
|
|
647
|
-
patternData["CORNERS"].orientation.push(pieceInfo.orientation);
|
|
648
|
-
}
|
|
649
|
-
for (const edgeMapping of gan356iEdgeMappings) {
|
|
650
|
-
const pieceInfo = pieceMap[edgeMapping.map((i) => faceOrder[stickers[i]]).join("")];
|
|
651
|
-
patternData["EDGES"].pieces.push(pieceInfo.piece);
|
|
652
|
-
patternData["EDGES"].orientation.push(pieceInfo.orientation);
|
|
653
|
-
}
|
|
654
|
-
return new KPattern(this.kpuzzle, patternData);
|
|
664
|
+
return new KPattern(
|
|
665
|
+
this.kpuzzle,
|
|
666
|
+
getPatternData(
|
|
667
|
+
stickers,
|
|
668
|
+
faceOrder,
|
|
669
|
+
gan356iEdgeMappings,
|
|
670
|
+
gan356iCornerMappings
|
|
671
|
+
)
|
|
672
|
+
);
|
|
655
673
|
}
|
|
656
674
|
async faceletStatus1Characteristic() {
|
|
657
675
|
this.cachedFaceletStatus1Characteristic = this.cachedFaceletStatus1Characteristic || this.service.getCharacteristic(UUIDs.faceletStatus1Characteristic);
|
|
@@ -1198,11 +1216,637 @@ var heykubeConfig = {
|
|
|
1198
1216
|
optionalServices: [UUIDs4.heykubeService]
|
|
1199
1217
|
};
|
|
1200
1218
|
|
|
1219
|
+
// src/cubing/bluetooth/smart-puzzle/qiyi.ts
|
|
1220
|
+
var UUIDs5 = {
|
|
1221
|
+
qiyiMainService: 65520,
|
|
1222
|
+
qiyiMainCharacteristic: 65526
|
|
1223
|
+
};
|
|
1224
|
+
var qiyiMoveToBlockMove = {
|
|
1225
|
+
1: new Move("L", -1),
|
|
1226
|
+
2: new Move("L"),
|
|
1227
|
+
3: new Move("R", -1),
|
|
1228
|
+
4: new Move("R"),
|
|
1229
|
+
5: new Move("D", -1),
|
|
1230
|
+
6: new Move("D"),
|
|
1231
|
+
7: new Move("U", -1),
|
|
1232
|
+
8: new Move("U"),
|
|
1233
|
+
9: new Move("F", -1),
|
|
1234
|
+
10: new Move("F"),
|
|
1235
|
+
11: new Move("B", -1),
|
|
1236
|
+
12: new Move("B")
|
|
1237
|
+
};
|
|
1238
|
+
var faceOrder2 = "LRDUFB";
|
|
1239
|
+
var qiyiCornerMappings = [
|
|
1240
|
+
[8, 20, 9],
|
|
1241
|
+
// UFR,
|
|
1242
|
+
[2, 11, 45],
|
|
1243
|
+
// URB,
|
|
1244
|
+
[0, 47, 36],
|
|
1245
|
+
// UBL,
|
|
1246
|
+
[6, 38, 18],
|
|
1247
|
+
// ULF,
|
|
1248
|
+
[29, 15, 26],
|
|
1249
|
+
// DRF,
|
|
1250
|
+
[27, 24, 44],
|
|
1251
|
+
// DFL,
|
|
1252
|
+
[33, 42, 53],
|
|
1253
|
+
// DLB,
|
|
1254
|
+
[35, 51, 17]
|
|
1255
|
+
// DBR,
|
|
1256
|
+
];
|
|
1257
|
+
var qiyiEdgeMappings = [
|
|
1258
|
+
[7, 19],
|
|
1259
|
+
// UF,
|
|
1260
|
+
[5, 10],
|
|
1261
|
+
// UR,
|
|
1262
|
+
[1, 46],
|
|
1263
|
+
// UB,
|
|
1264
|
+
[3, 37],
|
|
1265
|
+
// UL,
|
|
1266
|
+
[28, 25],
|
|
1267
|
+
// DF,
|
|
1268
|
+
[32, 16],
|
|
1269
|
+
// DR,
|
|
1270
|
+
[34, 52],
|
|
1271
|
+
// DB,
|
|
1272
|
+
[30, 43],
|
|
1273
|
+
// DL,
|
|
1274
|
+
[23, 12],
|
|
1275
|
+
// FR,
|
|
1276
|
+
[21, 41],
|
|
1277
|
+
// FL,
|
|
1278
|
+
[48, 14],
|
|
1279
|
+
// BR,
|
|
1280
|
+
[50, 39]
|
|
1281
|
+
// BL,
|
|
1282
|
+
];
|
|
1283
|
+
function generateChecksum(data) {
|
|
1284
|
+
const TABLE = new Uint16Array([
|
|
1285
|
+
0,
|
|
1286
|
+
49345,
|
|
1287
|
+
49537,
|
|
1288
|
+
320,
|
|
1289
|
+
49921,
|
|
1290
|
+
960,
|
|
1291
|
+
640,
|
|
1292
|
+
49729,
|
|
1293
|
+
50689,
|
|
1294
|
+
1728,
|
|
1295
|
+
1920,
|
|
1296
|
+
51009,
|
|
1297
|
+
1280,
|
|
1298
|
+
50625,
|
|
1299
|
+
50305,
|
|
1300
|
+
1088,
|
|
1301
|
+
52225,
|
|
1302
|
+
3264,
|
|
1303
|
+
3456,
|
|
1304
|
+
52545,
|
|
1305
|
+
3840,
|
|
1306
|
+
53185,
|
|
1307
|
+
52865,
|
|
1308
|
+
3648,
|
|
1309
|
+
2560,
|
|
1310
|
+
51905,
|
|
1311
|
+
52097,
|
|
1312
|
+
2880,
|
|
1313
|
+
51457,
|
|
1314
|
+
2496,
|
|
1315
|
+
2176,
|
|
1316
|
+
51265,
|
|
1317
|
+
55297,
|
|
1318
|
+
6336,
|
|
1319
|
+
6528,
|
|
1320
|
+
55617,
|
|
1321
|
+
6912,
|
|
1322
|
+
56257,
|
|
1323
|
+
55937,
|
|
1324
|
+
6720,
|
|
1325
|
+
7680,
|
|
1326
|
+
57025,
|
|
1327
|
+
57217,
|
|
1328
|
+
8e3,
|
|
1329
|
+
56577,
|
|
1330
|
+
7616,
|
|
1331
|
+
7296,
|
|
1332
|
+
56385,
|
|
1333
|
+
5120,
|
|
1334
|
+
54465,
|
|
1335
|
+
54657,
|
|
1336
|
+
5440,
|
|
1337
|
+
55041,
|
|
1338
|
+
6080,
|
|
1339
|
+
5760,
|
|
1340
|
+
54849,
|
|
1341
|
+
53761,
|
|
1342
|
+
4800,
|
|
1343
|
+
4992,
|
|
1344
|
+
54081,
|
|
1345
|
+
4352,
|
|
1346
|
+
53697,
|
|
1347
|
+
53377,
|
|
1348
|
+
4160,
|
|
1349
|
+
61441,
|
|
1350
|
+
12480,
|
|
1351
|
+
12672,
|
|
1352
|
+
61761,
|
|
1353
|
+
13056,
|
|
1354
|
+
62401,
|
|
1355
|
+
62081,
|
|
1356
|
+
12864,
|
|
1357
|
+
13824,
|
|
1358
|
+
63169,
|
|
1359
|
+
63361,
|
|
1360
|
+
14144,
|
|
1361
|
+
62721,
|
|
1362
|
+
13760,
|
|
1363
|
+
13440,
|
|
1364
|
+
62529,
|
|
1365
|
+
15360,
|
|
1366
|
+
64705,
|
|
1367
|
+
64897,
|
|
1368
|
+
15680,
|
|
1369
|
+
65281,
|
|
1370
|
+
16320,
|
|
1371
|
+
16e3,
|
|
1372
|
+
65089,
|
|
1373
|
+
64001,
|
|
1374
|
+
15040,
|
|
1375
|
+
15232,
|
|
1376
|
+
64321,
|
|
1377
|
+
14592,
|
|
1378
|
+
63937,
|
|
1379
|
+
63617,
|
|
1380
|
+
14400,
|
|
1381
|
+
10240,
|
|
1382
|
+
59585,
|
|
1383
|
+
59777,
|
|
1384
|
+
10560,
|
|
1385
|
+
60161,
|
|
1386
|
+
11200,
|
|
1387
|
+
10880,
|
|
1388
|
+
59969,
|
|
1389
|
+
60929,
|
|
1390
|
+
11968,
|
|
1391
|
+
12160,
|
|
1392
|
+
61249,
|
|
1393
|
+
11520,
|
|
1394
|
+
60865,
|
|
1395
|
+
60545,
|
|
1396
|
+
11328,
|
|
1397
|
+
58369,
|
|
1398
|
+
9408,
|
|
1399
|
+
9600,
|
|
1400
|
+
58689,
|
|
1401
|
+
9984,
|
|
1402
|
+
59329,
|
|
1403
|
+
59009,
|
|
1404
|
+
9792,
|
|
1405
|
+
8704,
|
|
1406
|
+
58049,
|
|
1407
|
+
58241,
|
|
1408
|
+
9024,
|
|
1409
|
+
57601,
|
|
1410
|
+
8640,
|
|
1411
|
+
8320,
|
|
1412
|
+
57409,
|
|
1413
|
+
40961,
|
|
1414
|
+
24768,
|
|
1415
|
+
24960,
|
|
1416
|
+
41281,
|
|
1417
|
+
25344,
|
|
1418
|
+
41921,
|
|
1419
|
+
41601,
|
|
1420
|
+
25152,
|
|
1421
|
+
26112,
|
|
1422
|
+
42689,
|
|
1423
|
+
42881,
|
|
1424
|
+
26432,
|
|
1425
|
+
42241,
|
|
1426
|
+
26048,
|
|
1427
|
+
25728,
|
|
1428
|
+
42049,
|
|
1429
|
+
27648,
|
|
1430
|
+
44225,
|
|
1431
|
+
44417,
|
|
1432
|
+
27968,
|
|
1433
|
+
44801,
|
|
1434
|
+
28608,
|
|
1435
|
+
28288,
|
|
1436
|
+
44609,
|
|
1437
|
+
43521,
|
|
1438
|
+
27328,
|
|
1439
|
+
27520,
|
|
1440
|
+
43841,
|
|
1441
|
+
26880,
|
|
1442
|
+
43457,
|
|
1443
|
+
43137,
|
|
1444
|
+
26688,
|
|
1445
|
+
30720,
|
|
1446
|
+
47297,
|
|
1447
|
+
47489,
|
|
1448
|
+
31040,
|
|
1449
|
+
47873,
|
|
1450
|
+
31680,
|
|
1451
|
+
31360,
|
|
1452
|
+
47681,
|
|
1453
|
+
48641,
|
|
1454
|
+
32448,
|
|
1455
|
+
32640,
|
|
1456
|
+
48961,
|
|
1457
|
+
32e3,
|
|
1458
|
+
48577,
|
|
1459
|
+
48257,
|
|
1460
|
+
31808,
|
|
1461
|
+
46081,
|
|
1462
|
+
29888,
|
|
1463
|
+
30080,
|
|
1464
|
+
46401,
|
|
1465
|
+
30464,
|
|
1466
|
+
47041,
|
|
1467
|
+
46721,
|
|
1468
|
+
30272,
|
|
1469
|
+
29184,
|
|
1470
|
+
45761,
|
|
1471
|
+
45953,
|
|
1472
|
+
29504,
|
|
1473
|
+
45313,
|
|
1474
|
+
29120,
|
|
1475
|
+
28800,
|
|
1476
|
+
45121,
|
|
1477
|
+
20480,
|
|
1478
|
+
37057,
|
|
1479
|
+
37249,
|
|
1480
|
+
20800,
|
|
1481
|
+
37633,
|
|
1482
|
+
21440,
|
|
1483
|
+
21120,
|
|
1484
|
+
37441,
|
|
1485
|
+
38401,
|
|
1486
|
+
22208,
|
|
1487
|
+
22400,
|
|
1488
|
+
38721,
|
|
1489
|
+
21760,
|
|
1490
|
+
38337,
|
|
1491
|
+
38017,
|
|
1492
|
+
21568,
|
|
1493
|
+
39937,
|
|
1494
|
+
23744,
|
|
1495
|
+
23936,
|
|
1496
|
+
40257,
|
|
1497
|
+
24320,
|
|
1498
|
+
40897,
|
|
1499
|
+
40577,
|
|
1500
|
+
24128,
|
|
1501
|
+
23040,
|
|
1502
|
+
39617,
|
|
1503
|
+
39809,
|
|
1504
|
+
23360,
|
|
1505
|
+
39169,
|
|
1506
|
+
22976,
|
|
1507
|
+
22656,
|
|
1508
|
+
38977,
|
|
1509
|
+
34817,
|
|
1510
|
+
18624,
|
|
1511
|
+
18816,
|
|
1512
|
+
35137,
|
|
1513
|
+
19200,
|
|
1514
|
+
35777,
|
|
1515
|
+
35457,
|
|
1516
|
+
19008,
|
|
1517
|
+
19968,
|
|
1518
|
+
36545,
|
|
1519
|
+
36737,
|
|
1520
|
+
20288,
|
|
1521
|
+
36097,
|
|
1522
|
+
19904,
|
|
1523
|
+
19584,
|
|
1524
|
+
35905,
|
|
1525
|
+
17408,
|
|
1526
|
+
33985,
|
|
1527
|
+
34177,
|
|
1528
|
+
17728,
|
|
1529
|
+
34561,
|
|
1530
|
+
18368,
|
|
1531
|
+
18048,
|
|
1532
|
+
34369,
|
|
1533
|
+
33281,
|
|
1534
|
+
17088,
|
|
1535
|
+
17280,
|
|
1536
|
+
33601,
|
|
1537
|
+
16640,
|
|
1538
|
+
33217,
|
|
1539
|
+
32897,
|
|
1540
|
+
16448
|
|
1541
|
+
]);
|
|
1542
|
+
let crc = 65535;
|
|
1543
|
+
for (const dataPoint of data) {
|
|
1544
|
+
const xor = (dataPoint ^ crc) & 255;
|
|
1545
|
+
crc >>= 8;
|
|
1546
|
+
crc ^= TABLE[xor];
|
|
1547
|
+
}
|
|
1548
|
+
return crc;
|
|
1549
|
+
}
|
|
1550
|
+
async function prepareMessage(message, aesKey) {
|
|
1551
|
+
const messageCopyForChecksum = structuredClone(message);
|
|
1552
|
+
const checksum = generateChecksum(messageCopyForChecksum);
|
|
1553
|
+
messageCopyForChecksum.push(checksum & 255);
|
|
1554
|
+
messageCopyForChecksum.push(checksum >> 8);
|
|
1555
|
+
const paddedLength = Math.ceil(messageCopyForChecksum.length / 16) * 16;
|
|
1556
|
+
const paddedArray = new Uint8Array([
|
|
1557
|
+
...messageCopyForChecksum,
|
|
1558
|
+
...Array(paddedLength - messageCopyForChecksum.length).fill(0)
|
|
1559
|
+
]);
|
|
1560
|
+
const encryptedMessage = new Uint8Array(paddedLength);
|
|
1561
|
+
for (let i = 0; i < paddedArray.length / 16; i++) {
|
|
1562
|
+
const encryptedBlock = new Uint8Array(
|
|
1563
|
+
await unsafeEncryptBlock(aesKey, paddedArray.slice(i * 16, (i + 1) * 16))
|
|
1564
|
+
);
|
|
1565
|
+
encryptedMessage.set(encryptedBlock, i * 16);
|
|
1566
|
+
}
|
|
1567
|
+
return encryptedMessage;
|
|
1568
|
+
}
|
|
1569
|
+
async function decryptMessage(encryptedMessage, aesKey) {
|
|
1570
|
+
const decryptedMessage = new Uint8Array(encryptedMessage.length);
|
|
1571
|
+
for (let i = 0; i < encryptedMessage.length / 16; i++) {
|
|
1572
|
+
const decryptedBlock = new Uint8Array(
|
|
1573
|
+
await unsafeDecryptBlock(
|
|
1574
|
+
aesKey,
|
|
1575
|
+
encryptedMessage.slice(i * 16, (i + 1) * 16)
|
|
1576
|
+
)
|
|
1577
|
+
);
|
|
1578
|
+
decryptedMessage.set(decryptedBlock, i * 16);
|
|
1579
|
+
}
|
|
1580
|
+
return decryptedMessage;
|
|
1581
|
+
}
|
|
1582
|
+
function getMacAddress(device) {
|
|
1583
|
+
if (device.name === void 0) {
|
|
1584
|
+
return;
|
|
1585
|
+
}
|
|
1586
|
+
return [
|
|
1587
|
+
204,
|
|
1588
|
+
163,
|
|
1589
|
+
0,
|
|
1590
|
+
0,
|
|
1591
|
+
parseInt(device.name.slice(10, 12), 16),
|
|
1592
|
+
parseInt(device.name.slice(12, 14), 16)
|
|
1593
|
+
];
|
|
1594
|
+
}
|
|
1595
|
+
var MAX_TIMESTAMP_COUNT = 12;
|
|
1596
|
+
var TIMESTAMP_SCALE = 1.6;
|
|
1597
|
+
var CUBE_HELLO = 2;
|
|
1598
|
+
var STATE_CHANGE = 3;
|
|
1599
|
+
var QiyiCube = class _QiyiCube extends BluetoothPuzzle {
|
|
1600
|
+
constructor(kpuzzle, aesKey, server) {
|
|
1601
|
+
super();
|
|
1602
|
+
this.kpuzzle = kpuzzle;
|
|
1603
|
+
this.aesKey = aesKey;
|
|
1604
|
+
this.server = server;
|
|
1605
|
+
this.sendAppHello();
|
|
1606
|
+
this.startNotifications();
|
|
1607
|
+
this.allTimeStamps = /* @__PURE__ */ new Set();
|
|
1608
|
+
this.allTimeStampsQueue = [];
|
|
1609
|
+
}
|
|
1610
|
+
latestTimestamp;
|
|
1611
|
+
allTimeStamps;
|
|
1612
|
+
// Without this set, moves are constantly duplicated
|
|
1613
|
+
allTimeStampsQueue;
|
|
1614
|
+
stickers = [
|
|
1615
|
+
3,
|
|
1616
|
+
3,
|
|
1617
|
+
3,
|
|
1618
|
+
3,
|
|
1619
|
+
3,
|
|
1620
|
+
3,
|
|
1621
|
+
3,
|
|
1622
|
+
3,
|
|
1623
|
+
3,
|
|
1624
|
+
1,
|
|
1625
|
+
1,
|
|
1626
|
+
1,
|
|
1627
|
+
1,
|
|
1628
|
+
1,
|
|
1629
|
+
1,
|
|
1630
|
+
1,
|
|
1631
|
+
1,
|
|
1632
|
+
1,
|
|
1633
|
+
4,
|
|
1634
|
+
4,
|
|
1635
|
+
4,
|
|
1636
|
+
4,
|
|
1637
|
+
4,
|
|
1638
|
+
4,
|
|
1639
|
+
4,
|
|
1640
|
+
4,
|
|
1641
|
+
4,
|
|
1642
|
+
2,
|
|
1643
|
+
2,
|
|
1644
|
+
2,
|
|
1645
|
+
2,
|
|
1646
|
+
2,
|
|
1647
|
+
2,
|
|
1648
|
+
2,
|
|
1649
|
+
2,
|
|
1650
|
+
2,
|
|
1651
|
+
0,
|
|
1652
|
+
0,
|
|
1653
|
+
0,
|
|
1654
|
+
0,
|
|
1655
|
+
0,
|
|
1656
|
+
0,
|
|
1657
|
+
0,
|
|
1658
|
+
0,
|
|
1659
|
+
0,
|
|
1660
|
+
5,
|
|
1661
|
+
5,
|
|
1662
|
+
5,
|
|
1663
|
+
5,
|
|
1664
|
+
5,
|
|
1665
|
+
5,
|
|
1666
|
+
5,
|
|
1667
|
+
5,
|
|
1668
|
+
5
|
|
1669
|
+
];
|
|
1670
|
+
batteryLevel = 100;
|
|
1671
|
+
static async connect(server) {
|
|
1672
|
+
const aesKey = await importKey(
|
|
1673
|
+
new Uint8Array([
|
|
1674
|
+
87,
|
|
1675
|
+
177,
|
|
1676
|
+
249,
|
|
1677
|
+
171,
|
|
1678
|
+
205,
|
|
1679
|
+
90,
|
|
1680
|
+
232,
|
|
1681
|
+
167,
|
|
1682
|
+
156,
|
|
1683
|
+
185,
|
|
1684
|
+
140,
|
|
1685
|
+
231,
|
|
1686
|
+
87,
|
|
1687
|
+
140,
|
|
1688
|
+
81,
|
|
1689
|
+
8
|
|
1690
|
+
])
|
|
1691
|
+
);
|
|
1692
|
+
return new _QiyiCube(await puzzles["3x3x3"].kpuzzle(), aesKey, server);
|
|
1693
|
+
}
|
|
1694
|
+
async sendAppHello() {
|
|
1695
|
+
const mainService = await this.server.getPrimaryService(
|
|
1696
|
+
UUIDs5.qiyiMainService
|
|
1697
|
+
);
|
|
1698
|
+
const mainCharacteristic = await mainService.getCharacteristic(
|
|
1699
|
+
UUIDs5.qiyiMainCharacteristic
|
|
1700
|
+
);
|
|
1701
|
+
for (let macGuessCounter = 0; macGuessCounter < 8; macGuessCounter++) {
|
|
1702
|
+
const mac = getMacAddress(this.server.device);
|
|
1703
|
+
mac[3] = macGuessCounter;
|
|
1704
|
+
const reversedMac = mac.reverse();
|
|
1705
|
+
const appHello = [
|
|
1706
|
+
254,
|
|
1707
|
+
21,
|
|
1708
|
+
0,
|
|
1709
|
+
0,
|
|
1710
|
+
0,
|
|
1711
|
+
0,
|
|
1712
|
+
0,
|
|
1713
|
+
0,
|
|
1714
|
+
0,
|
|
1715
|
+
0,
|
|
1716
|
+
0,
|
|
1717
|
+
0,
|
|
1718
|
+
0,
|
|
1719
|
+
...reversedMac
|
|
1720
|
+
];
|
|
1721
|
+
const appHelloMessage = await prepareMessage(appHello, this.aesKey);
|
|
1722
|
+
await mainCharacteristic.writeValue(appHelloMessage);
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
async startNotifications() {
|
|
1726
|
+
const mainService = await this.server.getPrimaryService(
|
|
1727
|
+
UUIDs5.qiyiMainService
|
|
1728
|
+
);
|
|
1729
|
+
const mainCharacteristic = await mainService.getCharacteristic(
|
|
1730
|
+
UUIDs5.qiyiMainCharacteristic
|
|
1731
|
+
);
|
|
1732
|
+
mainCharacteristic.addEventListener(
|
|
1733
|
+
"characteristicvaluechanged",
|
|
1734
|
+
this.cubeMessageHandler.bind(this)
|
|
1735
|
+
);
|
|
1736
|
+
await mainCharacteristic.startNotifications();
|
|
1737
|
+
}
|
|
1738
|
+
async cubeMessageHandler(event) {
|
|
1739
|
+
const characteristic = event.target;
|
|
1740
|
+
const decryptedMessage = await decryptMessage(
|
|
1741
|
+
new Uint8Array(characteristic.value.buffer),
|
|
1742
|
+
this.aesKey
|
|
1743
|
+
);
|
|
1744
|
+
const opCode = decryptedMessage[2];
|
|
1745
|
+
let needsAck = false;
|
|
1746
|
+
switch (opCode) {
|
|
1747
|
+
case CUBE_HELLO: {
|
|
1748
|
+
const initialState = decryptedMessage.slice(7, 34);
|
|
1749
|
+
this.updateState(initialState);
|
|
1750
|
+
this.batteryLevel = decryptedMessage[35];
|
|
1751
|
+
needsAck = true;
|
|
1752
|
+
break;
|
|
1753
|
+
}
|
|
1754
|
+
case STATE_CHANGE: {
|
|
1755
|
+
const state = decryptedMessage.slice(7, 34);
|
|
1756
|
+
this.updateState(state);
|
|
1757
|
+
const latestMove = qiyiMoveToBlockMove[decryptedMessage[34]];
|
|
1758
|
+
const latestTimestamp = new DataView(
|
|
1759
|
+
decryptedMessage.slice(3, 7).buffer
|
|
1760
|
+
).getInt32(0);
|
|
1761
|
+
const moves = [[latestMove, latestTimestamp]];
|
|
1762
|
+
const previousMoves = new DataView(
|
|
1763
|
+
decryptedMessage.slice(36, 91).buffer
|
|
1764
|
+
);
|
|
1765
|
+
for (let i = previousMoves.byteLength - 1; i > 0 && previousMoves.getUint8(i) !== 255; i -= 5) {
|
|
1766
|
+
const move = qiyiMoveToBlockMove[previousMoves.getUint8(i)];
|
|
1767
|
+
const timestamp = previousMoves.getUint32(i - 4);
|
|
1768
|
+
if (this.latestTimestamp === void 0 || timestamp <= this.latestTimestamp) {
|
|
1769
|
+
continue;
|
|
1770
|
+
}
|
|
1771
|
+
moves.push([move, timestamp]);
|
|
1772
|
+
}
|
|
1773
|
+
moves.sort((a, b) => a[1] - b[1]);
|
|
1774
|
+
for (const move of moves) {
|
|
1775
|
+
const latestAlgLeaf = move[0];
|
|
1776
|
+
const timeStamp = Math.round(move[1] / TIMESTAMP_SCALE);
|
|
1777
|
+
if (!this.allTimeStamps.has(timeStamp)) {
|
|
1778
|
+
this.dispatchAlgLeaf({
|
|
1779
|
+
latestAlgLeaf,
|
|
1780
|
+
timeStamp
|
|
1781
|
+
});
|
|
1782
|
+
this.allTimeStamps.add(timeStamp);
|
|
1783
|
+
this.allTimeStampsQueue.push(timeStamp);
|
|
1784
|
+
if (this.allTimeStampsQueue.length > MAX_TIMESTAMP_COUNT) {
|
|
1785
|
+
this.allTimeStamps.delete(this.allTimeStampsQueue.shift());
|
|
1786
|
+
}
|
|
1787
|
+
}
|
|
1788
|
+
}
|
|
1789
|
+
this.latestTimestamp = latestTimestamp;
|
|
1790
|
+
needsAck = decryptedMessage[91] === 1;
|
|
1791
|
+
break;
|
|
1792
|
+
}
|
|
1793
|
+
default:
|
|
1794
|
+
console.error(`Opcode not implemented: ${opCode}`);
|
|
1795
|
+
break;
|
|
1796
|
+
}
|
|
1797
|
+
if (needsAck) {
|
|
1798
|
+
await characteristic.writeValue(
|
|
1799
|
+
await prepareMessage(
|
|
1800
|
+
[254, 9, ...decryptedMessage.slice(2, 7)],
|
|
1801
|
+
this.aesKey
|
|
1802
|
+
)
|
|
1803
|
+
);
|
|
1804
|
+
}
|
|
1805
|
+
}
|
|
1806
|
+
updateState(state) {
|
|
1807
|
+
this.stickers = Array.from(state).flatMap((twoPieces) => [
|
|
1808
|
+
twoPieces & 15,
|
|
1809
|
+
twoPieces >> 4
|
|
1810
|
+
]);
|
|
1811
|
+
}
|
|
1812
|
+
name() {
|
|
1813
|
+
return this.server.device.name;
|
|
1814
|
+
}
|
|
1815
|
+
disconnect() {
|
|
1816
|
+
this.server.disconnect();
|
|
1817
|
+
}
|
|
1818
|
+
async getPattern() {
|
|
1819
|
+
return new KPattern(
|
|
1820
|
+
this.kpuzzle,
|
|
1821
|
+
getPatternData(
|
|
1822
|
+
this.stickers,
|
|
1823
|
+
faceOrder2,
|
|
1824
|
+
qiyiEdgeMappings,
|
|
1825
|
+
qiyiCornerMappings
|
|
1826
|
+
)
|
|
1827
|
+
);
|
|
1828
|
+
}
|
|
1829
|
+
getBattery() {
|
|
1830
|
+
return this.batteryLevel;
|
|
1831
|
+
}
|
|
1832
|
+
};
|
|
1833
|
+
var qiyiConfig = {
|
|
1834
|
+
connect: QiyiCube.connect.bind(QiyiCube),
|
|
1835
|
+
prefixes: ["QY-QYSC"],
|
|
1836
|
+
filters: [
|
|
1837
|
+
{
|
|
1838
|
+
namePrefix: "QY-QYSC"
|
|
1839
|
+
}
|
|
1840
|
+
],
|
|
1841
|
+
optionalServices: [UUIDs5.qiyiMainService]
|
|
1842
|
+
};
|
|
1843
|
+
|
|
1201
1844
|
// src/cubing/bluetooth/smart-puzzle/connect.ts
|
|
1202
1845
|
var smartPuzzleConfigs = [
|
|
1203
1846
|
ganConfig,
|
|
1204
1847
|
goCubeConfig,
|
|
1205
1848
|
heykubeConfig,
|
|
1849
|
+
qiyiConfig,
|
|
1206
1850
|
giiKERConfig
|
|
1207
1851
|
// GiiKER must be last, due to Xiaomi naming. TODO: enforce this using tests.
|
|
1208
1852
|
];
|
|
@@ -1224,7 +1868,7 @@ var U_D_SWAP = new Alg("F B R2 L2 B' F'");
|
|
|
1224
1868
|
var U_D_UNSWAP = U_D_SWAP.invert();
|
|
1225
1869
|
var F_B_SWAP = new Alg("U D R2 L2 D' U'");
|
|
1226
1870
|
var F_B_UNSWAP = F_B_SWAP.invert();
|
|
1227
|
-
var
|
|
1871
|
+
var UUIDs6 = {
|
|
1228
1872
|
ganRobotService: "0000fff0-0000-1000-8000-00805f9b34fb",
|
|
1229
1873
|
statusCharacteristic: "0000fff2-0000-1000-8000-00805f9b34fb",
|
|
1230
1874
|
moveCharacteristic: "0000fff3-0000-1000-8000-00805f9b34fb"
|
|
@@ -1310,13 +1954,13 @@ var GanRobot = class _GanRobot extends EventTarget {
|
|
|
1310
1954
|
// We have to perform async operations before we call the constructor.
|
|
1311
1955
|
static async connect(server, device) {
|
|
1312
1956
|
const ganTimerService = await server.getPrimaryService(
|
|
1313
|
-
|
|
1957
|
+
UUIDs6.ganRobotService
|
|
1314
1958
|
);
|
|
1315
1959
|
const statusCharacteristic = await ganTimerService.getCharacteristic(
|
|
1316
|
-
|
|
1960
|
+
UUIDs6.statusCharacteristic
|
|
1317
1961
|
);
|
|
1318
1962
|
const moveCharacteristic = await ganTimerService.getCharacteristic(
|
|
1319
|
-
|
|
1963
|
+
UUIDs6.moveCharacteristic
|
|
1320
1964
|
);
|
|
1321
1965
|
const timer = new _GanRobot(
|
|
1322
1966
|
ganTimerService,
|
|
@@ -1470,7 +2114,7 @@ var ganTimerConfig = {
|
|
|
1470
2114
|
connect: GanRobot.connect.bind(GanRobot),
|
|
1471
2115
|
prefixes: ["GAN"],
|
|
1472
2116
|
filters: [{ namePrefix: "GAN" }],
|
|
1473
|
-
optionalServices: [
|
|
2117
|
+
optionalServices: [UUIDs6.ganRobotService]
|
|
1474
2118
|
};
|
|
1475
2119
|
|
|
1476
2120
|
// src/cubing/bluetooth/smart-robot/index.ts
|
|
@@ -1480,7 +2124,7 @@ async function connectSmartRobot(options) {
|
|
|
1480
2124
|
}
|
|
1481
2125
|
|
|
1482
2126
|
// src/cubing/bluetooth/smart-timer/GanTimer.ts
|
|
1483
|
-
var
|
|
2127
|
+
var UUIDs7 = {
|
|
1484
2128
|
ganTimerService: "0000fff0-0000-1000-8000-00805f9b34fb",
|
|
1485
2129
|
timeCharacteristic: "0000fff2-0000-1000-8000-00805f9b34fb"
|
|
1486
2130
|
};
|
|
@@ -1501,11 +2145,11 @@ var GanTimer = class _GanTimer extends EventTarget {
|
|
|
1501
2145
|
// We have to perform async operations before we call the constructor.
|
|
1502
2146
|
static async connect(server, device) {
|
|
1503
2147
|
const ganTimerService = await server.getPrimaryService(
|
|
1504
|
-
|
|
2148
|
+
UUIDs7.ganTimerService
|
|
1505
2149
|
);
|
|
1506
2150
|
console.log("Service:", ganTimerService);
|
|
1507
2151
|
const timeCharacteristic = await ganTimerService.getCharacteristic(
|
|
1508
|
-
|
|
2152
|
+
UUIDs7.timeCharacteristic
|
|
1509
2153
|
);
|
|
1510
2154
|
console.log("Characteristic:", timeCharacteristic);
|
|
1511
2155
|
const timer = new _GanTimer(
|
|
@@ -1576,7 +2220,7 @@ var ganTimerConfig2 = {
|
|
|
1576
2220
|
connect: GanTimer.connect.bind(GanTimer),
|
|
1577
2221
|
prefixes: ["GAN"],
|
|
1578
2222
|
filters: [{ namePrefix: "GAN" }],
|
|
1579
|
-
optionalServices: [
|
|
2223
|
+
optionalServices: [UUIDs7.ganTimerService]
|
|
1580
2224
|
};
|
|
1581
2225
|
|
|
1582
2226
|
// src/cubing/bluetooth/smart-timer/index.ts
|