mirror of
https://github.com/cagnulein/qdomyos-zwift.git
synced 2026-02-18 00:17:41 +01:00
Compare commits
2026 Commits
android_ap
...
2.16.58
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96c5b7e595 | ||
|
|
51413841cc | ||
|
|
fae69702fb | ||
|
|
f0fdf428d2 | ||
|
|
2c62c1268c | ||
|
|
e2513cd25a | ||
|
|
c1ee0abaef | ||
|
|
78df32ea8d | ||
|
|
87fe37721e | ||
|
|
f1d026d533 | ||
|
|
f15fd05771 | ||
|
|
c57be3c247 | ||
|
|
88a9dab57e | ||
|
|
9481601bc6 | ||
|
|
99967a9169 | ||
|
|
8f48421ddd | ||
|
|
7f364e274b | ||
|
|
a215d5f129 | ||
|
|
55b07e1415 | ||
|
|
3e7617da5a | ||
|
|
c65c784d96 | ||
|
|
afe5e52fdb | ||
|
|
4f8d7d8e48 | ||
|
|
7be0aa4f9b | ||
|
|
cab132e88e | ||
|
|
9d7b3fa7e6 | ||
|
|
139630fcb8 | ||
|
|
b983e5a1f1 | ||
|
|
3644b70c8f | ||
|
|
61a6be9bc4 | ||
|
|
908cd7fff8 | ||
|
|
9e8d232f60 | ||
|
|
6ef309d05e | ||
|
|
5d4d969dc2 | ||
|
|
970fb4eeab | ||
|
|
2f0854b072 | ||
|
|
76bd70fae1 | ||
|
|
45fe36fc67 | ||
|
|
c1c4ee5dca | ||
|
|
037ee1f94b | ||
|
|
fe42408beb | ||
|
|
f442f90474 | ||
|
|
54abd22d09 | ||
|
|
9077cfdabc | ||
|
|
2f93050df4 | ||
|
|
08efde867d | ||
|
|
ad3e80128e | ||
|
|
d2ed216de6 | ||
|
|
3d4e07780f | ||
|
|
f89914e493 | ||
|
|
938c7baa35 | ||
|
|
d5453a1c93 | ||
|
|
0161c6edb7 | ||
|
|
33288e2af5 | ||
|
|
76a7ef25ee | ||
|
|
60c23871c5 | ||
|
|
84429039f1 | ||
|
|
9e33f7e969 | ||
|
|
6e52c836fa | ||
|
|
a75a4a639d | ||
|
|
cf86933a38 | ||
|
|
003b09e023 | ||
|
|
49f681d024 | ||
|
|
1bab10a0c5 | ||
|
|
304439f0d9 | ||
|
|
1775bcd14c | ||
|
|
e8df0938ea | ||
|
|
ce051344e9 | ||
|
|
55f59a6974 | ||
|
|
8dc3bce5f7 | ||
|
|
3f0a3fda20 | ||
|
|
9095236a30 | ||
|
|
ec9ad531f7 | ||
|
|
079b5d9fea | ||
|
|
7270d02537 | ||
|
|
e00b3e3be3 | ||
|
|
39e8e96935 | ||
|
|
fac7f30554 | ||
|
|
67449c6974 | ||
|
|
2c105055db | ||
|
|
e4b430953a | ||
|
|
c9c9d08b47 | ||
|
|
127ddba542 | ||
|
|
f1261e08a8 | ||
|
|
6102fe6331 | ||
|
|
42b7d359bf | ||
|
|
879242f27b | ||
|
|
f31bfbd796 | ||
|
|
db28e44da9 | ||
|
|
ac1daa3354 | ||
|
|
41efa25200 | ||
|
|
95c3c0d13f | ||
|
|
64ffb70988 | ||
|
|
6554fd7630 | ||
|
|
24f6c3b82f | ||
|
|
85a0ca0004 | ||
|
|
d37978431c | ||
|
|
cd99cc6b43 | ||
|
|
cfea9e9c10 | ||
|
|
1c5ac682b3 | ||
|
|
a5777a533b | ||
|
|
63717e4116 | ||
|
|
bb946ee172 | ||
|
|
2b8f82ea68 | ||
|
|
7bdd6e529a | ||
|
|
8d0565f411 | ||
|
|
cd32a90912 | ||
|
|
61cc94f7a9 | ||
|
|
f62a3278e7 | ||
|
|
8106a216c3 | ||
|
|
e48da60aa7 | ||
|
|
9803458018 | ||
|
|
e37d3ca66e | ||
|
|
0596d05e74 | ||
|
|
961de710b3 | ||
|
|
6cd52efe77 | ||
|
|
8e8942386e | ||
|
|
725b0e8976 | ||
|
|
ff32af5b94 | ||
|
|
641b93ecac | ||
|
|
386d6b9fb0 | ||
|
|
1811fe23e6 | ||
|
|
8fc91f8957 | ||
|
|
f3c82a5d85 | ||
|
|
a82515f85a | ||
|
|
ffd44bcf69 | ||
|
|
69245499fd | ||
|
|
7bb585652d | ||
|
|
717337ecc5 | ||
|
|
de755345df | ||
|
|
f29ee9b8b0 | ||
|
|
f7fd7385f3 | ||
|
|
c774e53c5f | ||
|
|
1a3aca47d3 | ||
|
|
43178057fd | ||
|
|
dbb6b32b03 | ||
|
|
a561219f29 | ||
|
|
ca0398c7d5 | ||
|
|
0af749c9f2 | ||
|
|
d2d661c7fd | ||
|
|
241e34c79e | ||
|
|
c6225db6a4 | ||
|
|
4f855f3d60 | ||
|
|
a55ccb4a97 | ||
|
|
06eccc33f4 | ||
|
|
f080bff4cd | ||
|
|
ecc06675dc | ||
|
|
d5758cf0ed | ||
|
|
d3ebdf252e | ||
|
|
81840bd831 | ||
|
|
1210ec5232 | ||
|
|
cc4a3a6623 | ||
|
|
bc3ec3b39f | ||
|
|
2c7c82bbde | ||
|
|
f18e12e1a7 | ||
|
|
0952d2b8ba | ||
|
|
69e2ed26e2 | ||
|
|
dea1450452 | ||
|
|
7accf7f184 | ||
|
|
d099e58de0 | ||
|
|
0d735c4192 | ||
|
|
03e60d96e7 | ||
|
|
5bfa0bba16 | ||
|
|
ed983a0657 | ||
|
|
8b6a4b3565 | ||
|
|
6d4572a745 | ||
|
|
711afe4b08 | ||
|
|
da43761133 | ||
|
|
977acde7d1 | ||
|
|
1405f3c2c3 | ||
|
|
fb36f7d68d | ||
|
|
381fbf5767 | ||
|
|
e4003ebd81 | ||
|
|
377bd2b667 | ||
|
|
c47df1fe49 | ||
|
|
15cc111dda | ||
|
|
0af6aee343 | ||
|
|
69006d4d18 | ||
|
|
1cd4c801f7 | ||
|
|
3c4f850127 | ||
|
|
9a5b3d279d | ||
|
|
70e82d3aaf | ||
|
|
f48392082f | ||
|
|
df8f409403 | ||
|
|
cb4f20c25e | ||
|
|
cf9321d144 | ||
|
|
89c1439049 | ||
|
|
cf0ea0f84f | ||
|
|
6f211c441c | ||
|
|
0a804c9d6d | ||
|
|
062623580a | ||
|
|
5560c920ec | ||
|
|
ec1c504083 | ||
|
|
27ce527fd6 | ||
|
|
fdc1dc7b9a | ||
|
|
1c76b898e4 | ||
|
|
b2014df95b | ||
|
|
a250ada61e | ||
|
|
dd6c8ca20c | ||
|
|
d8e489f64d | ||
|
|
741fd4367d | ||
|
|
fd2e7ef994 | ||
|
|
a142968feb | ||
|
|
4fd06f91b0 | ||
|
|
e27133fb3a | ||
|
|
9df1c4fdba | ||
|
|
39391c3200 | ||
|
|
70367b8365 | ||
|
|
8e30bde019 | ||
|
|
cb717ff213 | ||
|
|
d723bf054d | ||
|
|
491e900ec3 | ||
|
|
64247cff21 | ||
|
|
38cf417927 | ||
|
|
fcb05aba9f | ||
|
|
9142d8c54d | ||
|
|
8e7a8d14ab | ||
|
|
ca44612565 | ||
|
|
2a40356d4a | ||
|
|
315b750647 | ||
|
|
80ba54294d | ||
|
|
a0218d8d70 | ||
|
|
8d150111aa | ||
|
|
964e49ddb5 | ||
|
|
5f4dd1a1b4 | ||
|
|
b027179dd8 | ||
|
|
5d859024a1 | ||
|
|
99c02259dc | ||
|
|
7048471601 | ||
|
|
9cb1e7a190 | ||
|
|
e1c1ac441a | ||
|
|
0e621aafd5 | ||
|
|
079d406c73 | ||
|
|
9f9ab5c8ca | ||
|
|
a9be8055f2 | ||
|
|
65f49c5c52 | ||
|
|
a429c82f4c | ||
|
|
3288caacb2 | ||
|
|
f4850ff67d | ||
|
|
f644edff24 | ||
|
|
6db6221238 | ||
|
|
db823bd5f4 | ||
|
|
04e2d213da | ||
|
|
64eae75549 | ||
|
|
8118040619 | ||
|
|
c92f546141 | ||
|
|
ddf9bfbef3 | ||
|
|
8d451a4e87 | ||
|
|
c8c4597eb7 | ||
|
|
90a364a8c0 | ||
|
|
22d5bbacbc | ||
|
|
231e01fba8 | ||
|
|
8095fd2314 | ||
|
|
8c796531f6 | ||
|
|
ad28a9e2a5 | ||
|
|
2bcf5f229a | ||
|
|
c53b6e3dab | ||
|
|
471e331641 | ||
|
|
a95d630731 | ||
|
|
eea38d4ecf | ||
|
|
3f7238243f | ||
|
|
a92bfc211b | ||
|
|
a27047156d | ||
|
|
1391930a00 | ||
|
|
6c59f3ee30 | ||
|
|
eeb3a9ce6f | ||
|
|
d1352ae3dd | ||
|
|
053725a577 | ||
|
|
726a2341c0 | ||
|
|
6d7fa3b67e | ||
|
|
4883202703 | ||
|
|
6953f96e59 | ||
|
|
9910234b44 | ||
|
|
3746d89069 | ||
|
|
f2a52e932f | ||
|
|
17fb96dab8 | ||
|
|
e9467724bc | ||
|
|
56b5e759a6 | ||
|
|
f59eb258f1 | ||
|
|
0565a5cf60 | ||
|
|
102e1d6b78 | ||
|
|
7170e28f75 | ||
|
|
3f0441304c | ||
|
|
e76cb14d59 | ||
|
|
339a4279e1 | ||
|
|
02d9b74001 | ||
|
|
a587936f91 | ||
|
|
a84ad5da45 | ||
|
|
959b6db9d0 | ||
|
|
4b289c57f8 | ||
|
|
43f1bda372 | ||
|
|
8ee1046c1d | ||
|
|
60084c7981 | ||
|
|
f23614d793 | ||
|
|
e60c8c2d16 | ||
|
|
e3134a6bd9 | ||
|
|
c42d38d8cc | ||
|
|
f487634923 | ||
|
|
b5bda493cc | ||
|
|
8925d6acf7 | ||
|
|
df88e7e9d6 | ||
|
|
408ee351bb | ||
|
|
2834f6c5d8 | ||
|
|
629aa73f24 | ||
|
|
a5016a66da | ||
|
|
bd54646fe9 | ||
|
|
f6df2a7bf3 | ||
|
|
c32430c12f | ||
|
|
bee144a359 | ||
|
|
dd8fdcd796 | ||
|
|
e45c5e9c13 | ||
|
|
0523fde5bc | ||
|
|
db43605f7a | ||
|
|
ed6553c190 | ||
|
|
b84526ccea | ||
|
|
acd9637c8e | ||
|
|
1235bf7bac | ||
|
|
44a2229e5c | ||
|
|
7d6f1d31a8 | ||
|
|
af608d38c8 | ||
|
|
5b6c231fd1 | ||
|
|
80b09419bd | ||
|
|
aefc83140a | ||
|
|
4c5045315c | ||
|
|
c803d7253e | ||
|
|
b17990e378 | ||
|
|
f184b2b545 | ||
|
|
5aaed653e9 | ||
|
|
69fb207aa2 | ||
|
|
01d5a6d3ba | ||
|
|
ba742c5049 | ||
|
|
4e35e889f8 | ||
|
|
29926b7457 | ||
|
|
ccd2b1399d | ||
|
|
32a2831066 | ||
|
|
aa5f48c33b | ||
|
|
3f15f37f70 | ||
|
|
f79939be2c | ||
|
|
a1983e39f6 | ||
|
|
e50091bd26 | ||
|
|
3e9132e0d5 | ||
|
|
ad678787bb | ||
|
|
4526324dc0 | ||
|
|
e13f8510ba | ||
|
|
1e9b6a4372 | ||
|
|
2ab490e520 | ||
|
|
4a288cb144 | ||
|
|
4aee609476 | ||
|
|
104e11e5b8 | ||
|
|
df06a63678 | ||
|
|
414df68353 | ||
|
|
5ccc8cf77e | ||
|
|
bf2d9e95cb | ||
|
|
4f0ffaae32 | ||
|
|
12e27084be | ||
|
|
c02935f4b1 | ||
|
|
5969c0f37f | ||
|
|
11a1ffdf32 | ||
|
|
be8408e4c7 | ||
|
|
018ea9f080 | ||
|
|
c3b1ae9dcd | ||
|
|
a32645bb15 | ||
|
|
bd9f5ea765 | ||
|
|
8d025a91b2 | ||
|
|
006663b2f1 | ||
|
|
28761764a4 | ||
|
|
b5c47f5aa6 | ||
|
|
2f0806df7b | ||
|
|
6e5ffdccb0 | ||
|
|
5864e81e57 | ||
|
|
fc9fb178a2 | ||
|
|
56fe2c8fcc | ||
|
|
145a919f22 | ||
|
|
b47d62c2ca | ||
|
|
092e318b55 | ||
|
|
35f5065cb2 | ||
|
|
6ac55ee7e3 | ||
|
|
6461d68954 | ||
|
|
3168a84fd6 | ||
|
|
587bd6469d | ||
|
|
a2f6f45aa6 | ||
|
|
bfc301a8b9 | ||
|
|
0774a9e5c5 | ||
|
|
5b9a1d5135 | ||
|
|
c96b591360 | ||
|
|
67a2151b68 | ||
|
|
b565cef516 | ||
|
|
020d732725 | ||
|
|
1677b03113 | ||
|
|
a831add2d5 | ||
|
|
038e597177 | ||
|
|
17ab93720f | ||
|
|
34f28b4b79 | ||
|
|
fa0e981174 | ||
|
|
67de90b88e | ||
|
|
cdd3f53244 | ||
|
|
438c1a5021 | ||
|
|
ba074414b0 | ||
|
|
bc1b2d4d19 | ||
|
|
202d018521 | ||
|
|
b5bb557210 | ||
|
|
3937c9593e | ||
|
|
531ce52643 | ||
|
|
9eb282ec23 | ||
|
|
3753c33581 | ||
|
|
6859b8663f | ||
|
|
e1a5c2a7ea | ||
|
|
23d702ddd4 | ||
|
|
ac0440edaf | ||
|
|
0ed7413254 | ||
|
|
9a2d51a7fd | ||
|
|
bdc64ac13f | ||
|
|
a4a6924f7a | ||
|
|
02ac7fc4c8 | ||
|
|
1bd47aa02c | ||
|
|
974d57d595 | ||
|
|
4a8b37919c | ||
|
|
3780cf7727 | ||
|
|
3ca52a76e9 | ||
|
|
625c73556a | ||
|
|
b022207787 | ||
|
|
4275bb18a0 | ||
|
|
432413526f | ||
|
|
976fb849c7 | ||
|
|
6f861e54c2 | ||
|
|
1d85e90b15 | ||
|
|
6340c7cf82 | ||
|
|
dd2160344e | ||
|
|
abf33019ee | ||
|
|
5f3e1bfd7f | ||
|
|
28c6e035d9 | ||
|
|
84c351e55c | ||
|
|
b2ab7e1328 | ||
|
|
d48ce08102 | ||
|
|
7bfb76a415 | ||
|
|
432e82cc84 | ||
|
|
2c0f32c4c5 | ||
|
|
b6fa09702c | ||
|
|
fac68e0fce | ||
|
|
896d91a3ba | ||
|
|
cf3151465a | ||
|
|
23d450e52b | ||
|
|
eda7e72d04 | ||
|
|
fb4eec9e10 | ||
|
|
4090cd71eb | ||
|
|
616f3e1976 | ||
|
|
fd6acc3626 | ||
|
|
52b0d0c5a1 | ||
|
|
2f61a1addc | ||
|
|
280fa8c0f4 | ||
|
|
83af28ea25 | ||
|
|
7a3bf4a78e | ||
|
|
54cb9c3ef7 | ||
|
|
a96f497633 | ||
|
|
dc07457631 | ||
|
|
30008c7f9b | ||
|
|
3c557067d7 | ||
|
|
0fae320cf5 | ||
|
|
fca9e879f2 | ||
|
|
a0493cac89 | ||
|
|
6096b09f9c | ||
|
|
d1734b96af | ||
|
|
a98772f2fd | ||
|
|
9bebef29cc | ||
|
|
869bc0d720 | ||
|
|
4bc20961b4 | ||
|
|
f9fe046f54 | ||
|
|
92bffc42fa | ||
|
|
d2256f563a | ||
|
|
0cff162fcc | ||
|
|
2c73351f94 | ||
|
|
a5129f6a3a | ||
|
|
ff9c7f746a | ||
|
|
cfd8fa3eeb | ||
|
|
952052ecca | ||
|
|
bf4597f863 | ||
|
|
d973d0dd0c | ||
|
|
e46cd2421d | ||
|
|
2e729f50ec | ||
|
|
e7ae05aa16 | ||
|
|
0dc369cfe6 | ||
|
|
f2bc2a79be | ||
|
|
dbf428d239 | ||
|
|
f6d94ca133 | ||
|
|
53049c073f | ||
|
|
981f9258ca | ||
|
|
b1706eb395 | ||
|
|
44c2e45c1c | ||
|
|
00307eb228 | ||
|
|
2d851913f2 | ||
|
|
e8177e4410 | ||
|
|
b53ff75a5f | ||
|
|
1f444d0dd0 | ||
|
|
3dc61fff85 | ||
|
|
031a24764d | ||
|
|
c4b371eddf | ||
|
|
4a8c42c755 | ||
|
|
8d61e9cfff | ||
|
|
ac6468e507 | ||
|
|
1abe748ad2 | ||
|
|
390d835fba | ||
|
|
51415561a0 | ||
|
|
d7ea35cfef | ||
|
|
8aece1ac6d | ||
|
|
4e6a52030f | ||
|
|
c346aaa055 | ||
|
|
f8341e0d6b | ||
|
|
4d3dd3a86c | ||
|
|
393e7be824 | ||
|
|
2758688f2c | ||
|
|
9628f6be45 | ||
|
|
ed122948cc | ||
|
|
747858b544 | ||
|
|
eeb24b94e0 | ||
|
|
d178317f77 | ||
|
|
2ac2b278b6 | ||
|
|
9a8561b229 | ||
|
|
2c63fd3cc3 | ||
|
|
7f1eb1486a | ||
|
|
6b0a15d19b | ||
|
|
928f9bc613 | ||
|
|
1e3121375f | ||
|
|
12d5794fcd | ||
|
|
6d475919af | ||
|
|
08fa2d8fd9 | ||
|
|
1882862e03 | ||
|
|
bd0dd1c504 | ||
|
|
3874d15a44 | ||
|
|
397379ad9b | ||
|
|
ee1201cc3e | ||
|
|
f968d6628b | ||
|
|
129506f7e5 | ||
|
|
5d4665bfbb | ||
|
|
463c349fc3 | ||
|
|
ab3071aafc | ||
|
|
978ac7ee0f | ||
|
|
8a791c4dde | ||
|
|
77eb4e5b1a | ||
|
|
e3730cf22a | ||
|
|
717d90b98c | ||
|
|
98de190dd5 | ||
|
|
05b4b6ef4d | ||
|
|
c1129bbc0f | ||
|
|
0d48bab025 | ||
|
|
85e9d0f6d1 | ||
|
|
fd2d17879b | ||
|
|
c91248fd52 | ||
|
|
3dfe880b1b | ||
|
|
9065ef0c19 | ||
|
|
4ba070e089 | ||
|
|
fed4c0ca0f | ||
|
|
ab63a29cad | ||
|
|
d8ed66e0ea | ||
|
|
1274112aed | ||
|
|
be13c4176f | ||
|
|
f2cef085d2 | ||
|
|
478a27ed68 | ||
|
|
001c651c58 | ||
|
|
4e6b29d494 | ||
|
|
82ef4e4350 | ||
|
|
bcff966976 | ||
|
|
0931ef6055 | ||
|
|
f204c1bac0 | ||
|
|
93779d04c5 | ||
|
|
7f6e6e2ce0 | ||
|
|
76dc3b38b8 | ||
|
|
48345dc2d2 | ||
|
|
2cb4187951 | ||
|
|
76deb91b0b | ||
|
|
2c71206327 | ||
|
|
e3be4ffa0e | ||
|
|
868d5cc3a8 | ||
|
|
94eb866740 | ||
|
|
f192cf6c75 | ||
|
|
c7efde82b6 | ||
|
|
f32dcb4e1e | ||
|
|
6157bfdcc8 | ||
|
|
9ff91faf00 | ||
|
|
3b88bc2f1f | ||
|
|
4f7cfbbfc1 | ||
|
|
56c112ed4c | ||
|
|
f6b8984575 | ||
|
|
52579e3efc | ||
|
|
fef5d8f4a7 | ||
|
|
6c93d85932 | ||
|
|
b7763154a3 | ||
|
|
fe393bd70d | ||
|
|
3330cc516e | ||
|
|
49e288ec01 | ||
|
|
f1e14d1652 | ||
|
|
2b541c220b | ||
|
|
372d57368c | ||
|
|
21f977ad44 | ||
|
|
a152a0edb9 | ||
|
|
effb3cdfe5 | ||
|
|
e0144445a3 | ||
|
|
8042989552 | ||
|
|
d5ba21da2e | ||
|
|
9d970fbca7 | ||
|
|
600d679e21 | ||
|
|
e860224908 | ||
|
|
081d778405 | ||
|
|
5f18b4daf1 | ||
|
|
7b0065d49a | ||
|
|
65c45d5f3a | ||
|
|
12d3f469de | ||
|
|
707fe68301 | ||
|
|
69511f8c38 | ||
|
|
37ea50fca9 | ||
|
|
c91a24cf23 | ||
|
|
ea48d30f73 | ||
|
|
117c3749ea | ||
|
|
6376e45a13 | ||
|
|
e1068bc1e5 | ||
|
|
c501466372 | ||
|
|
d8dea4f69d | ||
|
|
d44fcd72f7 | ||
|
|
2a19918889 | ||
|
|
420e263a9c | ||
|
|
8a71567a46 | ||
|
|
5a5d9fb4b4 | ||
|
|
f5484768b8 | ||
|
|
5beb890d85 | ||
|
|
edf8a33b87 | ||
|
|
03ddac15da | ||
|
|
e41c60fbeb | ||
|
|
2a435b6b65 | ||
|
|
da31761c35 | ||
|
|
6908bb5d43 | ||
|
|
cf35fccca7 | ||
|
|
d4a8322160 | ||
|
|
dc5f835445 | ||
|
|
85c7a70053 | ||
|
|
b615bd008e | ||
|
|
2ea7337a0f | ||
|
|
34f34312ce | ||
|
|
d4818cc96e | ||
|
|
d801bc7984 | ||
|
|
0efe227318 | ||
|
|
40549f16e8 | ||
|
|
7295ebbf62 | ||
|
|
95db80a249 | ||
|
|
534de944d1 | ||
|
|
d4c9f2b1dd | ||
|
|
ffb2a6e072 | ||
|
|
2dc7ad7fd9 | ||
|
|
35d2eb23aa | ||
|
|
4ab4e17f03 | ||
|
|
acd80b1105 | ||
|
|
01ab6841fc | ||
|
|
e547924350 | ||
|
|
30b0bd51ca | ||
|
|
a3a2bca715 | ||
|
|
bf14b9a8e0 | ||
|
|
a53e7a6e44 | ||
|
|
5eefb07e9e | ||
|
|
55b0689d1d | ||
|
|
beb0a8a80c | ||
|
|
65f57d111a | ||
|
|
7de08d223f | ||
|
|
2b69f2dcd0 | ||
|
|
27da18fed9 | ||
|
|
22fd82cdff | ||
|
|
d9202218dd | ||
|
|
baf9e24640 | ||
|
|
9c0ab9b9f6 | ||
|
|
49e0506815 | ||
|
|
80c528f370 | ||
|
|
54fa926596 | ||
|
|
9f80a7b679 | ||
|
|
7639d19f5e | ||
|
|
9870626695 | ||
|
|
5be30f8f6c | ||
|
|
751f9c4f84 | ||
|
|
dd61b8e2ca | ||
|
|
7dfc994888 | ||
|
|
c662b84bc2 | ||
|
|
7b0ec35303 | ||
|
|
5d235eaab7 | ||
|
|
4e55e2b085 | ||
|
|
e221e4bf7e | ||
|
|
67f0be7c06 | ||
|
|
415025e43d | ||
|
|
ba1854659a | ||
|
|
f622a3e3f7 | ||
|
|
aad888cdab | ||
|
|
b3d45319ae | ||
|
|
0ecff51b14 | ||
|
|
face819d09 | ||
|
|
f8b9c65dab | ||
|
|
0b0081a506 | ||
|
|
94c63f5b77 | ||
|
|
87725cdd1d | ||
|
|
0ddeb747bf | ||
|
|
63a7476d14 | ||
|
|
28701625ac | ||
|
|
e0bc9071c5 | ||
|
|
5bd16f8200 | ||
|
|
d2b844ffb9 | ||
|
|
4018d2947c | ||
|
|
f030c319ac | ||
|
|
ccd4a9896e | ||
|
|
246bf944b2 | ||
|
|
0b7ded9020 | ||
|
|
8bf64c64be | ||
|
|
dbd0227722 | ||
|
|
7e04ab4f92 | ||
|
|
9b7e1d873c | ||
|
|
60ee86476c | ||
|
|
430378b441 | ||
|
|
b9537ff042 | ||
|
|
c0bba3943b | ||
|
|
f729260cbd | ||
|
|
bff00001ab | ||
|
|
91e5a1f14e | ||
|
|
b928be6a33 | ||
|
|
2e0dde6aa4 | ||
|
|
7b8c8ea2b8 | ||
|
|
afd6e5ce26 | ||
|
|
2b8b005762 | ||
|
|
1e639cacd1 | ||
|
|
16611c7e49 | ||
|
|
757febf35a | ||
|
|
2c46293612 | ||
|
|
9a1f9ee980 | ||
|
|
96c80d5bb6 | ||
|
|
98fbd64b89 | ||
|
|
23131f8fb8 | ||
|
|
ec966d6036 | ||
|
|
11f0d6786b | ||
|
|
0f2619233c | ||
|
|
a2ba4cefb5 | ||
|
|
a83e5951aa | ||
|
|
9fe09e7b4b | ||
|
|
0ea2269a67 | ||
|
|
fdba749812 | ||
|
|
ac257b13ed | ||
|
|
0890bf8096 | ||
|
|
ea75a04ad5 | ||
|
|
c3a4238618 | ||
|
|
8017bf64cd | ||
|
|
04633c6296 | ||
|
|
513b59c106 | ||
|
|
04c3cc329c | ||
|
|
e99d7279f4 | ||
|
|
716f917e2a | ||
|
|
0147498c69 | ||
|
|
22b3cef9d2 | ||
|
|
81e4e95272 | ||
|
|
12cc5d0221 | ||
|
|
5b1f85a8cb | ||
|
|
9a9d5fa95e | ||
|
|
8f335894e7 | ||
|
|
3292af09ec | ||
|
|
747acae290 | ||
|
|
04c13f2842 | ||
|
|
b77ed2af6a | ||
|
|
5f186204d6 | ||
|
|
6e9a1ef58a | ||
|
|
180a246902 | ||
|
|
09ab5b142c | ||
|
|
50249a5236 | ||
|
|
4da2ac2fe1 | ||
|
|
ba9253209c | ||
|
|
e8031f5a19 | ||
|
|
b649e5e0f5 | ||
|
|
da9c570029 | ||
|
|
f79eae87a9 | ||
|
|
44beb23212 | ||
|
|
ed35ece439 | ||
|
|
37b513904c | ||
|
|
639397d594 | ||
|
|
de51899ca3 | ||
|
|
ff40d68223 | ||
|
|
1385ea8b88 | ||
|
|
13c88474c6 | ||
|
|
e55577d835 | ||
|
|
6409eab90c | ||
|
|
a314dfe325 | ||
|
|
9b41e2494d | ||
|
|
8672240d72 | ||
|
|
8e83967036 | ||
|
|
8d8b1c141a | ||
|
|
64d40b5d79 | ||
|
|
91811b6b0e | ||
|
|
3e4c898d9f | ||
|
|
67398fce4b | ||
|
|
42c2c52eef | ||
|
|
94cfede7ac | ||
|
|
e8e6068aa2 | ||
|
|
056a903cf2 | ||
|
|
911e66041f | ||
|
|
dbc3c2abf2 | ||
|
|
6f37799e56 | ||
|
|
00bfd0707c | ||
|
|
6bc003db9b | ||
|
|
7b1044a634 | ||
|
|
3686b77405 | ||
|
|
ba3bb3b724 | ||
|
|
495168c204 | ||
|
|
8a9230942b | ||
|
|
100eaccc99 | ||
|
|
24c0df5075 | ||
|
|
9116a46b27 | ||
|
|
64059f2db5 | ||
|
|
2e386ef2a1 | ||
|
|
1ecee4cd3e | ||
|
|
fd523000c0 | ||
|
|
47c272d3d0 | ||
|
|
4eec504016 | ||
|
|
da08e3335e | ||
|
|
0100da67cf | ||
|
|
12e03510f6 | ||
|
|
c8a17ad70e | ||
|
|
9748558f1b | ||
|
|
c807291389 | ||
|
|
29c4e323b0 | ||
|
|
4b1408401f | ||
|
|
39e2ef50cb | ||
|
|
880ac67fbc | ||
|
|
b21695bc14 | ||
|
|
eab058f401 | ||
|
|
58f62303be | ||
|
|
22f935c827 | ||
|
|
dce2ba7067 | ||
|
|
51665c76b4 | ||
|
|
a76cf602d6 | ||
|
|
a3f6bb8d0c | ||
|
|
3f83e4a999 | ||
|
|
14546d4ed3 | ||
|
|
1afff6a79d | ||
|
|
e95bf77c9d | ||
|
|
76ebceccbc | ||
|
|
f54b900c18 | ||
|
|
42e7749856 | ||
|
|
13fb8ae05a | ||
|
|
ee27386d11 | ||
|
|
5073ed766f | ||
|
|
c571a98775 | ||
|
|
1e66fb10b9 | ||
|
|
c9bcfb201e | ||
|
|
d701d01f13 | ||
|
|
f3ae244587 | ||
|
|
755e98d49a | ||
|
|
006c365fee | ||
|
|
2d9110c251 | ||
|
|
30e945f609 | ||
|
|
d3289fa5d1 | ||
|
|
1dd8846c2e | ||
|
|
9a3dc093a2 | ||
|
|
5674c75f4f | ||
|
|
f97e11b1d2 | ||
|
|
68a5bf7f44 | ||
|
|
d644aa4523 | ||
|
|
d04a1a9f01 | ||
|
|
e907170ba2 | ||
|
|
8a55ac1088 | ||
|
|
f83c7565cc | ||
|
|
7de500503e | ||
|
|
61b15254e1 | ||
|
|
2503835a59 | ||
|
|
00ceee2ee0 | ||
|
|
c93cf781fb | ||
|
|
a17da417c2 | ||
|
|
306ce699d4 | ||
|
|
fbbd40a0f8 | ||
|
|
5398b09643 | ||
|
|
94046b18fe | ||
|
|
4e9a03d931 | ||
|
|
2392251992 | ||
|
|
973ff3a586 | ||
|
|
87e5a1905d | ||
|
|
f39ca765d8 | ||
|
|
b33ce3233d | ||
|
|
4209f6f653 | ||
|
|
7d36b4082b | ||
|
|
a3015858f9 | ||
|
|
12515752f6 | ||
|
|
9334c6b472 | ||
|
|
884bea8352 | ||
|
|
8b4c579539 | ||
|
|
c9f3a3a092 | ||
|
|
547bc8a5c9 | ||
|
|
9c600dbc00 | ||
|
|
f29d9fd1e6 | ||
|
|
8d1e98e81f | ||
|
|
94ac9d1bdd | ||
|
|
9e74918b65 | ||
|
|
3be43c14e1 | ||
|
|
e1b951e664 | ||
|
|
53126b16d3 | ||
|
|
0fb8e12d31 | ||
|
|
679300c930 | ||
|
|
4008d588d7 | ||
|
|
fda528babc | ||
|
|
0e9bac6168 | ||
|
|
f8c1330862 | ||
|
|
8e81df67d0 | ||
|
|
1a3c13eac9 | ||
|
|
15b16c7e5c | ||
|
|
b5ceb0a0f1 | ||
|
|
00939c56dd | ||
|
|
5f1ebc439e | ||
|
|
81db615692 | ||
|
|
65d12f00f4 | ||
|
|
adcb87b3c4 | ||
|
|
90900b786a | ||
|
|
b495e833bd | ||
|
|
fb01341dd1 | ||
|
|
867143e43e | ||
|
|
b85d7d72f5 | ||
|
|
32cb3b9e37 | ||
|
|
3ff8938b41 | ||
|
|
5156cb38f0 | ||
|
|
dd4a5dbc54 | ||
|
|
cf37b8705e | ||
|
|
bc8302c761 | ||
|
|
76ecf5c66e | ||
|
|
3693c2d1b2 | ||
|
|
3905bd8ba7 | ||
|
|
92cac7485e | ||
|
|
458c44758e | ||
|
|
be12859343 | ||
|
|
d201919b55 | ||
|
|
138a42c2e6 | ||
|
|
bbe69f3f60 | ||
|
|
b95b3a5018 | ||
|
|
fb0cbb74a5 | ||
|
|
deed6019ab | ||
|
|
7636f768f1 | ||
|
|
cdf8a95e30 | ||
|
|
13389afe77 | ||
|
|
8acfb6b764 | ||
|
|
4244ce79a0 | ||
|
|
907e96330f | ||
|
|
35136be5b9 | ||
|
|
6cd33f2ff9 | ||
|
|
7e52925242 | ||
|
|
98971bf036 | ||
|
|
51e97321ac | ||
|
|
d959c0bea2 | ||
|
|
875f283984 | ||
|
|
b4f378a8e9 | ||
|
|
22e50a7600 | ||
|
|
30f3b47a8c | ||
|
|
103f1675e6 | ||
|
|
db7bc008e4 | ||
|
|
e634348d75 | ||
|
|
8956957e4d | ||
|
|
f79b0074a8 | ||
|
|
34abdab013 | ||
|
|
b741378a0e | ||
|
|
5404a68689 | ||
|
|
73bc5691e8 | ||
|
|
de42318370 | ||
|
|
61acaf033a | ||
|
|
cd2592b14e | ||
|
|
b0ef38885b | ||
|
|
34a3e1067d | ||
|
|
b084afea11 | ||
|
|
46eb6b3776 | ||
|
|
23d646848e | ||
|
|
e78d4565bc | ||
|
|
9540bff975 | ||
|
|
4d5db2e3b3 | ||
|
|
20027b914e | ||
|
|
5764efd487 | ||
|
|
c427c72726 | ||
|
|
41be14bb8a | ||
|
|
2fcd6eb310 | ||
|
|
656d404582 | ||
|
|
548bdeb5e4 | ||
|
|
eaa5fca1fe | ||
|
|
c9778f918d | ||
|
|
de17acdfcf | ||
|
|
3f16b7d146 | ||
|
|
881e6db650 | ||
|
|
d27bccaea5 | ||
|
|
afde8ad8d5 | ||
|
|
d8d0613f6d | ||
|
|
e255267116 | ||
|
|
e7e79b1816 | ||
|
|
df09bd2a9c | ||
|
|
7ae17516f1 | ||
|
|
4f53e28cc4 | ||
|
|
08c9869c84 | ||
|
|
86bd39b370 | ||
|
|
1e68328c0f | ||
|
|
81d8950bb6 | ||
|
|
df109a620e | ||
|
|
fdc3e4166a | ||
|
|
144472c57f | ||
|
|
d23b36f267 | ||
|
|
47ed429773 | ||
|
|
f8a09dc301 | ||
|
|
c1b6b0e175 | ||
|
|
d2e007fb43 | ||
|
|
589dd85678 | ||
|
|
4f4c6cebf1 | ||
|
|
1688a571af | ||
|
|
018f96d243 | ||
|
|
428d7fee83 | ||
|
|
ffb09bf78d | ||
|
|
3a94929584 | ||
|
|
fea04b29a4 | ||
|
|
f7145710af | ||
|
|
e3ef341e60 | ||
|
|
b097e0898e | ||
|
|
8237c3c862 | ||
|
|
6d6bad02db | ||
|
|
9dd25f0d69 | ||
|
|
c84e16aed9 | ||
|
|
f10e68f47b | ||
|
|
07111d5a9e | ||
|
|
77a4d4224a | ||
|
|
bda145a29e | ||
|
|
54799c3519 | ||
|
|
1580471db8 | ||
|
|
0b918f1b44 | ||
|
|
a13719b0a0 | ||
|
|
90469409b7 | ||
|
|
e3474fa844 | ||
|
|
2da438778a | ||
|
|
2cf61c2ccf | ||
|
|
6b8b1c2f68 | ||
|
|
85b0bd5f74 | ||
|
|
bf53671dc7 | ||
|
|
86f4bdddd7 | ||
|
|
1096b08fdd | ||
|
|
5d1b115645 | ||
|
|
094c5a838d | ||
|
|
2488cc8758 | ||
|
|
8084b9f06b | ||
|
|
8b48707dfb | ||
|
|
0ad679e2f8 | ||
|
|
33a1202f5f | ||
|
|
776aee4902 | ||
|
|
c44f576876 | ||
|
|
a723dce8fc | ||
|
|
7329389ffc | ||
|
|
71647a8406 | ||
|
|
669a99e6cd | ||
|
|
49b0883e26 | ||
|
|
ec13911855 | ||
|
|
5b7422cff0 | ||
|
|
ee7b1ca1d5 | ||
|
|
b588037651 | ||
|
|
5a19c314ba | ||
|
|
4e06af6200 | ||
|
|
b6ffdb7145 | ||
|
|
02c7c2ff2a | ||
|
|
6369194167 | ||
|
|
fd8984f2ca | ||
|
|
328b2cadc1 | ||
|
|
8a9b5a3cc9 | ||
|
|
46792b3c4f | ||
|
|
5662f90e31 | ||
|
|
81c94738b0 | ||
|
|
b3874957ca | ||
|
|
7f16b04824 | ||
|
|
a3af5be2ce | ||
|
|
033ab6bd16 | ||
|
|
38df1caf10 | ||
|
|
ef909a35df | ||
|
|
65777dea2d | ||
|
|
f2554ad454 | ||
|
|
56c04335ae | ||
|
|
c5cf31b228 | ||
|
|
1b04588b4e | ||
|
|
c99c008b64 | ||
|
|
af2db915b4 | ||
|
|
1c2a220ae4 | ||
|
|
77cb8439c0 | ||
|
|
5f14e7aa22 | ||
|
|
e0ab1edbb6 | ||
|
|
ff09896cf4 | ||
|
|
a9a118d03a | ||
|
|
f3d6f13be9 | ||
|
|
f23ec88dfb | ||
|
|
9027eb961f | ||
|
|
6b637e1d92 | ||
|
|
e96eceb271 | ||
|
|
a77074a874 | ||
|
|
1927ad9577 | ||
|
|
f79fd80838 | ||
|
|
cfe05c76f4 | ||
|
|
4c8da03f19 | ||
|
|
7abf133a61 | ||
|
|
383ecc6381 | ||
|
|
dfd68c4445 | ||
|
|
cd689cb6fc | ||
|
|
43094f41e2 | ||
|
|
ad6d683b09 | ||
|
|
db5d177925 | ||
|
|
bfe6838acc | ||
|
|
4a061acbfb | ||
|
|
5326089804 | ||
|
|
42c6e35219 | ||
|
|
a9f86f78b4 | ||
|
|
3ce7828c8f | ||
|
|
cb821f65b8 | ||
|
|
cbc09609a0 | ||
|
|
0f8ad887dd | ||
|
|
5d7f688321 | ||
|
|
b904af9335 | ||
|
|
030689217c | ||
|
|
8f02feb172 | ||
|
|
27ee8d99d8 | ||
|
|
4fcb13b11b | ||
|
|
13d488025f | ||
|
|
c379985c68 | ||
|
|
50e4ff371f | ||
|
|
01749bad6e | ||
|
|
7ba1986929 | ||
|
|
0a52f15406 | ||
|
|
abd2e76f4f | ||
|
|
035d150c6d | ||
|
|
a29619feca | ||
|
|
964be4b5d1 | ||
|
|
d01be6384d | ||
|
|
0845406940 | ||
|
|
fd30c61124 | ||
|
|
a49b9b07ef | ||
|
|
af91761a23 | ||
|
|
32af96b05b | ||
|
|
658006a12a | ||
|
|
4451680cea | ||
|
|
beaab12894 | ||
|
|
cc74ef6fe4 | ||
|
|
958487b0e5 | ||
|
|
68d191d581 | ||
|
|
aca68b2a10 | ||
|
|
c3f013a69a | ||
|
|
c2dc509c97 | ||
|
|
520726f989 | ||
|
|
04c7837e35 | ||
|
|
e1b097837b | ||
|
|
b443b03d49 | ||
|
|
c8cf9367db | ||
|
|
1a7c0be896 | ||
|
|
bb219fdf9a | ||
|
|
d446186082 | ||
|
|
1bc00b4f9d | ||
|
|
28db6a7f70 | ||
|
|
a1ad083422 | ||
|
|
0132a3f38d | ||
|
|
1a6a06ead4 | ||
|
|
f34f373687 | ||
|
|
95327f6c1a | ||
|
|
93e60262d6 | ||
|
|
992ae1c88c | ||
|
|
5754e800d2 | ||
|
|
ee9491d5f6 | ||
|
|
789c911966 | ||
|
|
d95c6f86c7 | ||
|
|
4d7da98c7a | ||
|
|
193518c1c1 | ||
|
|
32aafc3d00 | ||
|
|
1ffd44ae91 | ||
|
|
d3c8441717 | ||
|
|
ca8638abe0 | ||
|
|
514ac12484 | ||
|
|
db5c4cc73e | ||
|
|
58f2934bb8 | ||
|
|
6c677a3a2b | ||
|
|
2b4d04acc0 | ||
|
|
3841918383 | ||
|
|
d843d09829 | ||
|
|
c1bceca06f | ||
|
|
ec7782b86f | ||
|
|
ae6505bdb4 | ||
|
|
3690120207 | ||
|
|
dfe8c59a91 | ||
|
|
e25abb0317 | ||
|
|
4dd02ad1b6 | ||
|
|
ef715f002b | ||
|
|
f02c2d4293 | ||
|
|
9a4baffe81 | ||
|
|
dd7e1b3861 | ||
|
|
7cffb2c51e | ||
|
|
d6e5accc84 | ||
|
|
900a7f2d94 | ||
|
|
dd6e0068ee | ||
|
|
fd9c3f414b | ||
|
|
dd692b5b04 | ||
|
|
1f83bc94f2 | ||
|
|
c7386511ea | ||
|
|
446c6ee027 | ||
|
|
e85a6bc090 | ||
|
|
2a84b6075e | ||
|
|
1ff6295aae | ||
|
|
70913cd7af | ||
|
|
3576eff46e | ||
|
|
49984654ea | ||
|
|
c7f17cd749 | ||
|
|
20af8dcfed | ||
|
|
1f113b0164 | ||
|
|
11d0a33374 | ||
|
|
e371d13f0f | ||
|
|
f5d201aed1 | ||
|
|
d561dfa318 | ||
|
|
ef095dc9f1 | ||
|
|
0db053b60a | ||
|
|
2eeba4f9a6 | ||
|
|
f4ccbfb33f | ||
|
|
32b9c2810f | ||
|
|
7abc3834aa | ||
|
|
51cf710b08 | ||
|
|
34ae065c2c | ||
|
|
cbf0b178d6 | ||
|
|
229b6a8e30 | ||
|
|
02cc189d72 | ||
|
|
af9d1d97a8 | ||
|
|
20b3263a5b | ||
|
|
f712b7bb92 | ||
|
|
38b69c20e1 | ||
|
|
5f99c1dd22 | ||
|
|
a715849756 | ||
|
|
16b62d8752 | ||
|
|
b68c166b01 | ||
|
|
c6aaaa6944 | ||
|
|
625e8c91eb | ||
|
|
4d81a51442 | ||
|
|
bbe3b4e369 | ||
|
|
e94e030a00 | ||
|
|
c9f8076a5e | ||
|
|
dbc1e43c2b | ||
|
|
b4ea2cd1c5 | ||
|
|
e2d0c9284a | ||
|
|
66bedca4a4 | ||
|
|
5a10627594 | ||
|
|
7465f71c74 | ||
|
|
8c58f03d82 | ||
|
|
e199ea3fc6 | ||
|
|
bbd37dc36c | ||
|
|
48646ec3bb | ||
|
|
dca0b1b917 | ||
|
|
db78365ffd | ||
|
|
1325b1cd29 | ||
|
|
43780a076f | ||
|
|
a374ebcf6e | ||
|
|
7ab1eac7fe | ||
|
|
d378ab23ea | ||
|
|
4c3566a156 | ||
|
|
51fb564640 | ||
|
|
ef40f29597 | ||
|
|
34db47f611 | ||
|
|
100d0b3f58 | ||
|
|
2a4b58634b | ||
|
|
95cb85fd88 | ||
|
|
ff1abb2b9f | ||
|
|
aa22225e5e | ||
|
|
b6b5d8ecba | ||
|
|
e9be1d8fb2 | ||
|
|
5bfa0b3312 | ||
|
|
7fd491e005 | ||
|
|
0717799d15 | ||
|
|
2c34d9001b | ||
|
|
61498cb6ef | ||
|
|
95ec82b641 | ||
|
|
c6a34c59d3 | ||
|
|
c9d243ab18 | ||
|
|
172440872a | ||
|
|
7ccbc07808 | ||
|
|
e02fb8e1c5 | ||
|
|
17b54a1963 | ||
|
|
5e7b208c92 | ||
|
|
78a652a512 | ||
|
|
9a49ef1e7f | ||
|
|
39f92a429a | ||
|
|
a70c79f144 | ||
|
|
278e209670 | ||
|
|
9fefde58ac | ||
|
|
7f26e63cd6 | ||
|
|
54beb7cc4e | ||
|
|
35d7e54871 | ||
|
|
5eb9de8c9b | ||
|
|
0f703cd836 | ||
|
|
9157e39ebd | ||
|
|
e9c76bde99 | ||
|
|
1398cb26fb | ||
|
|
35a986fdd0 | ||
|
|
3f8aa376a6 | ||
|
|
21a3ae6816 | ||
|
|
3da7ac198a | ||
|
|
36aed6c326 | ||
|
|
2a02eec288 | ||
|
|
0ca1a8caad | ||
|
|
13ea251697 | ||
|
|
9c0757986f | ||
|
|
81028fc111 | ||
|
|
1999bbaee0 | ||
|
|
12ad01ddde | ||
|
|
8b79b85f8c | ||
|
|
3e900c1a55 | ||
|
|
5f22107085 | ||
|
|
6354d20bc4 | ||
|
|
d1aeb30abb | ||
|
|
e2592896c6 | ||
|
|
d4305fa93a | ||
|
|
cc0051f7c3 | ||
|
|
56962545d8 | ||
|
|
7b128d2a8a | ||
|
|
a228f55a9a | ||
|
|
9ec12d5733 | ||
|
|
f460a9770a | ||
|
|
49bbbddbe2 | ||
|
|
f1b7daf34b | ||
|
|
e78434fbb3 | ||
|
|
397dcc7db8 | ||
|
|
c2b0ebb882 | ||
|
|
68a8169e0b | ||
|
|
5611be511f | ||
|
|
427b63b113 | ||
|
|
716a256cf4 | ||
|
|
8d123cec1a | ||
|
|
582c260dd9 | ||
|
|
7994c884ea | ||
|
|
58dbee1e15 | ||
|
|
5c2483b264 | ||
|
|
15d94329c2 | ||
|
|
77de4703d3 | ||
|
|
2318531980 | ||
|
|
993727d251 | ||
|
|
128ad2a84b | ||
|
|
9e8a8a18f2 | ||
|
|
19e05219f5 | ||
|
|
58376bff43 | ||
|
|
d4518fe018 | ||
|
|
d6258a5774 | ||
|
|
063ab524e6 | ||
|
|
fbf8fed94d | ||
|
|
bbf0ef11d4 | ||
|
|
1439f5d15a | ||
|
|
79aad21d26 | ||
|
|
062cac38f6 | ||
|
|
36046c00ad | ||
|
|
8e84d2bf95 | ||
|
|
66aaeb5c8b | ||
|
|
52c25f5fc7 | ||
|
|
ec457a18c2 | ||
|
|
eb00d52512 | ||
|
|
55ad2dbe3e | ||
|
|
2ea9ad2992 | ||
|
|
211024f67f | ||
|
|
3b7fa4f8a8 | ||
|
|
e3c0fc933a | ||
|
|
e4d2d7899b | ||
|
|
70e87ac6a3 | ||
|
|
9d6b53586a | ||
|
|
b35c41a319 | ||
|
|
010d0b0dcc | ||
|
|
a31c926a1a | ||
|
|
94c03ba9b4 | ||
|
|
bce965c6d6 | ||
|
|
74e5e04f0c | ||
|
|
159611da89 | ||
|
|
8cb9d24261 | ||
|
|
74cc93b91e | ||
|
|
85d622a1e3 | ||
|
|
9967550a41 | ||
|
|
bf41d8f1d7 | ||
|
|
f4999e3233 | ||
|
|
2b01877a7c | ||
|
|
d985b9a477 | ||
|
|
960aa7a17b | ||
|
|
42e7c3481e | ||
|
|
7404128eba | ||
|
|
f81f5354f6 | ||
|
|
b3e588cff5 | ||
|
|
a39597765c | ||
|
|
28f4bb04da | ||
|
|
80ab7a3877 | ||
|
|
5fcd1233c1 | ||
|
|
b894906f48 | ||
|
|
f998d7123f | ||
|
|
35c4ecc781 | ||
|
|
c98e0db8b0 | ||
|
|
0eead667a3 | ||
|
|
759dcf37c7 | ||
|
|
4f79679601 | ||
|
|
a834e6ea14 | ||
|
|
325963327e | ||
|
|
ef96f05127 | ||
|
|
d836883fc3 | ||
|
|
4abb1be184 | ||
|
|
8af0ca3350 | ||
|
|
c16e113290 | ||
|
|
6e92bcece2 | ||
|
|
f71a393c2b | ||
|
|
015bf842b0 | ||
|
|
cde122089e | ||
|
|
709ead19a3 | ||
|
|
8b4fe10f87 | ||
|
|
74d69f5d8f | ||
|
|
d7a8caa24c | ||
|
|
803291ba43 | ||
|
|
38f53fd1bf | ||
|
|
3d310bfd14 | ||
|
|
5cdad64d9c | ||
|
|
d3c2d15fc3 | ||
|
|
794cda41cc | ||
|
|
330359c446 | ||
|
|
c75906f766 | ||
|
|
a2d9994608 | ||
|
|
0a01f62f79 | ||
|
|
8888639bef | ||
|
|
5a114a7f8f | ||
|
|
53717078b9 | ||
|
|
d2c94da6bf | ||
|
|
320a40c65c | ||
|
|
9efb573f83 | ||
|
|
072024cee1 | ||
|
|
bf692fbcc0 | ||
|
|
2909a61a94 | ||
|
|
c06dc9c332 | ||
|
|
85ee8fae3c | ||
|
|
0f3f5d7db3 | ||
|
|
5d34e2e6eb | ||
|
|
679fec7e69 | ||
|
|
1cd68457a9 | ||
|
|
065494ae43 | ||
|
|
c59ee00d3e | ||
|
|
d504812655 | ||
|
|
06110e808d | ||
|
|
c27e7353b7 | ||
|
|
38ca4cbf33 | ||
|
|
f86604d7b2 | ||
|
|
7309df034e | ||
|
|
16180689ac | ||
|
|
880a8708f0 | ||
|
|
fbc68c5487 | ||
|
|
1540fd4fe3 | ||
|
|
9855b9e76f | ||
|
|
3ba1eaf92a | ||
|
|
474d519d85 | ||
|
|
3e8bbf57d2 | ||
|
|
80f6a5a9ee | ||
|
|
c1c1a07cd9 | ||
|
|
369eb4d101 | ||
|
|
115bdc1cb2 | ||
|
|
3b6b5a6721 | ||
|
|
24b680ca12 | ||
|
|
7c53a16e38 | ||
|
|
0eabe10ea1 | ||
|
|
c92b702b2e | ||
|
|
9068e82ae3 | ||
|
|
77ebbe7c6d | ||
|
|
8ec760855e | ||
|
|
5d1b399fa6 | ||
|
|
b6ebeadae2 | ||
|
|
c43dfaeb1f | ||
|
|
0f6caeff8a | ||
|
|
7191141177 | ||
|
|
256981dff7 | ||
|
|
ac8e295322 | ||
|
|
d772ae85bf | ||
|
|
83180f37ce | ||
|
|
af695b0aab | ||
|
|
68bf628cf3 | ||
|
|
c631511fc9 | ||
|
|
7a0ac82f0d | ||
|
|
f90e980a62 | ||
|
|
03b871143a | ||
|
|
c374cbeace | ||
|
|
df55d648c9 | ||
|
|
d18a2ebe38 | ||
|
|
bca55a68a1 | ||
|
|
a34d880ef3 | ||
|
|
1b07564429 | ||
|
|
53fd346348 | ||
|
|
11e037dd84 | ||
|
|
0869ad36c5 | ||
|
|
334e0cfd25 | ||
|
|
d2af89f693 | ||
|
|
2f832c65ed | ||
|
|
cb087ea4be | ||
|
|
72df934997 | ||
|
|
349b525295 | ||
|
|
3e58c2d681 | ||
|
|
e7748f943c | ||
|
|
03a755ee36 | ||
|
|
9ad1821194 | ||
|
|
04b16b5849 | ||
|
|
12c16b9634 | ||
|
|
4034109195 | ||
|
|
5355b43cdf | ||
|
|
ecbb40a375 | ||
|
|
6235d00c55 | ||
|
|
bff9f1a0a2 | ||
|
|
ecc6306b7d | ||
|
|
e9856d8b42 | ||
|
|
099bbf7d9c | ||
|
|
ba462a4d10 | ||
|
|
f953335bd2 | ||
|
|
3e60e0bd91 | ||
|
|
3e98e548be | ||
|
|
8021055345 | ||
|
|
3fdf890474 | ||
|
|
53e4e58c3f | ||
|
|
ad37d26815 | ||
|
|
a59321e7b8 | ||
|
|
e203fdaa67 | ||
|
|
81b95ac080 | ||
|
|
3ce3719630 | ||
|
|
5eaac9e509 | ||
|
|
65adba7285 | ||
|
|
03aadfa864 | ||
|
|
b3a83c13b3 | ||
|
|
a92e43ba4d | ||
|
|
bbf2fd54f3 | ||
|
|
2b110e7d9c | ||
|
|
ac3f2dd7f9 | ||
|
|
afda87f2b3 | ||
|
|
2689b01159 | ||
|
|
28c69284cf | ||
|
|
606aa28231 | ||
|
|
26e25914db | ||
|
|
6d83d67ec3 | ||
|
|
aad68cb1b9 | ||
|
|
959b2e1663 | ||
|
|
48b247fed6 | ||
|
|
a575776ea7 | ||
|
|
a394c7d075 | ||
|
|
1efad04a7c | ||
|
|
d6418d199f | ||
|
|
6915494594 | ||
|
|
44b278173d | ||
|
|
621de55f67 | ||
|
|
11f347276c | ||
|
|
d165382960 | ||
|
|
819ecaf133 | ||
|
|
b744ceb731 | ||
|
|
d706314802 | ||
|
|
c9e5c2f065 | ||
|
|
eadaf62064 | ||
|
|
ca9ada6d83 | ||
|
|
aa9948b4ba | ||
|
|
07a301f53c | ||
|
|
984a6395d0 | ||
|
|
50361e2b4f | ||
|
|
fb6478324b | ||
|
|
048edf2022 | ||
|
|
0985816c20 | ||
|
|
95e7ca1f6b | ||
|
|
f30e141d3f | ||
|
|
0bd4232d24 | ||
|
|
f56b12ae85 | ||
|
|
d98fccdf5a | ||
|
|
13b62ab0d0 | ||
|
|
a20f73dc1b | ||
|
|
dd84d2ce04 | ||
|
|
b304505a1b | ||
|
|
c6c2717bb5 | ||
|
|
61e539c822 | ||
|
|
5cfb8141af | ||
|
|
bb03d1c36a | ||
|
|
59c4249741 | ||
|
|
a44f52995d | ||
|
|
ac2848cb55 | ||
|
|
e8169806f9 | ||
|
|
8295ad654b | ||
|
|
6abcf8e536 | ||
|
|
8161aae3da | ||
|
|
36c1933192 | ||
|
|
0508d26796 | ||
|
|
67d2292680 | ||
|
|
873c4e8b72 | ||
|
|
1a3a10f636 | ||
|
|
a876959e79 | ||
|
|
138af1514a | ||
|
|
c9ec71ae02 | ||
|
|
e10e7e5cc7 | ||
|
|
e7ea68e766 | ||
|
|
2ccdbb1336 | ||
|
|
c3c43991f2 | ||
|
|
ef135f1ffe | ||
|
|
3294c9284b | ||
|
|
9f287ca8c7 | ||
|
|
cbacce66ca | ||
|
|
dac3a5323e | ||
|
|
d486d7e2a0 | ||
|
|
1c0e212125 | ||
|
|
146e1c5da4 | ||
|
|
d21e0da604 | ||
|
|
11864ed49d | ||
|
|
86c0db5612 | ||
|
|
b61b2132f9 | ||
|
|
66c963ec7c | ||
|
|
2505e49675 | ||
|
|
8e4d0dd49e | ||
|
|
919902f8bb | ||
|
|
020c1440d6 | ||
|
|
349f03b330 | ||
|
|
fd1224e7c9 | ||
|
|
672455c0d3 | ||
|
|
676f2f1f9a | ||
|
|
b94fa37aaf | ||
|
|
0af537701c | ||
|
|
d819781150 | ||
|
|
d9443cff54 | ||
|
|
92283b65ba | ||
|
|
497cbc67f1 | ||
|
|
3085d284f6 | ||
|
|
d39b51c389 | ||
|
|
590e42dc73 | ||
|
|
242ca22bc5 | ||
|
|
34f37bc70a | ||
|
|
43ae256c18 | ||
|
|
466be88bb9 | ||
|
|
ff7b7bbfe7 | ||
|
|
1d1c22b234 | ||
|
|
1b1850f82c | ||
|
|
e9942ca63d | ||
|
|
b87cf9162c | ||
|
|
8c11fe9ae1 | ||
|
|
4a1726df27 | ||
|
|
9f51255994 | ||
|
|
d2b3262edd | ||
|
|
3f7b085173 | ||
|
|
ed4cb797d4 | ||
|
|
d3bc3cdfaf | ||
|
|
db3f8c217b | ||
|
|
5cf4719de2 | ||
|
|
0ddfb3d910 | ||
|
|
47621150d3 | ||
|
|
d5ff290a8b | ||
|
|
4629a9ed04 | ||
|
|
92a2fb5854 | ||
|
|
3dedb4cb5e | ||
|
|
23ef0eab21 | ||
|
|
c72535e423 | ||
|
|
07a050d6c5 | ||
|
|
58c1ac9d5b | ||
|
|
0d2e53e6af | ||
|
|
581f2a4af1 | ||
|
|
009b569f25 | ||
|
|
d47364d344 | ||
|
|
61b011b3ce | ||
|
|
09d48c0bbf | ||
|
|
e184347f0e | ||
|
|
dc3f83093e | ||
|
|
0bf0466a11 | ||
|
|
2347b5633d | ||
|
|
7de641ce5c | ||
|
|
2e8189037c | ||
|
|
a54071f05d | ||
|
|
77e92f4e96 | ||
|
|
39e63a435f | ||
|
|
2218bb4489 | ||
|
|
dc85b4a35e | ||
|
|
75604aed8c | ||
|
|
029995d420 | ||
|
|
aec612614c | ||
|
|
2a4ca076cf | ||
|
|
e215918987 | ||
|
|
23e2a11b6b | ||
|
|
5f8a09d82e | ||
|
|
6e2107e82e | ||
|
|
af3ab73359 | ||
|
|
7d3828d3b9 | ||
|
|
a43b73fb9e | ||
|
|
bd102dee72 | ||
|
|
2634993a3a | ||
|
|
30f93ac439 | ||
|
|
337b06cce4 | ||
|
|
cc41d02607 | ||
|
|
4b7829e1f3 | ||
|
|
ac8fd15d0a | ||
|
|
b1a4b58ba2 | ||
|
|
3bd17743d2 | ||
|
|
e88e89c96b | ||
|
|
ae3a393038 | ||
|
|
12f2f2601c | ||
|
|
e42825b0ec | ||
|
|
eb7895bb48 | ||
|
|
1366c21891 | ||
|
|
341b0607fc | ||
|
|
e8a59937f6 | ||
|
|
20c69a374c | ||
|
|
3eb3dbecc8 | ||
|
|
f8a6e428ee | ||
|
|
196bfe351d | ||
|
|
5169cf78a4 | ||
|
|
11425ea861 | ||
|
|
d4a5604af6 | ||
|
|
b53ff4a516 | ||
|
|
1adf0b2e08 | ||
|
|
883c4c56d6 | ||
|
|
13a2c95671 | ||
|
|
48df8b3057 | ||
|
|
e771b4a62d | ||
|
|
c7bed0a259 | ||
|
|
bb7dc3f4e9 | ||
|
|
e9c383ce8b | ||
|
|
395973b0ae | ||
|
|
8cdbc8463a | ||
|
|
9f1d6a163f | ||
|
|
44b304bcf7 | ||
|
|
b0bea930e0 | ||
|
|
6ce71c69f6 | ||
|
|
1bf665ae98 | ||
|
|
a3e6cbd416 | ||
|
|
c2ef787a74 | ||
|
|
c00f2a81ca | ||
|
|
b4164cd10f | ||
|
|
f95a0510c7 | ||
|
|
b6c5099e07 | ||
|
|
bc26307c63 | ||
|
|
ee0b7993de | ||
|
|
93a6a352a1 | ||
|
|
1e98454070 | ||
|
|
a90d3f227f | ||
|
|
0ad5ca8651 | ||
|
|
8daf02afb6 | ||
|
|
422bf4144f | ||
|
|
57455ee7d6 | ||
|
|
032636b3b6 | ||
|
|
536067d731 | ||
|
|
9aaa1a0d18 | ||
|
|
17db301d5d | ||
|
|
0e4945f15b | ||
|
|
94ba539de4 | ||
|
|
9c9d540585 | ||
|
|
9f6e54dfc4 | ||
|
|
3b1d24381e | ||
|
|
563e7708f0 | ||
|
|
5127420097 | ||
|
|
9202958a39 | ||
|
|
c2ca7a06fe | ||
|
|
0a852644bc | ||
|
|
fd32d29c87 | ||
|
|
c4c1091147 | ||
|
|
fd15b1ac4f | ||
|
|
7b53ee0dc9 | ||
|
|
59fc9864ec | ||
|
|
c59e8a0079 | ||
|
|
96ff845abe | ||
|
|
62f504bdc7 | ||
|
|
8113bccb77 | ||
|
|
ab14cbfa49 | ||
|
|
ee252a313d | ||
|
|
293ff2eda1 | ||
|
|
f084b88312 | ||
|
|
bc9c36624a | ||
|
|
b49af71c2e | ||
|
|
118684ebff | ||
|
|
9e8c8322e3 | ||
|
|
cce52fcdfa | ||
|
|
e29b7f1356 | ||
|
|
036f0c4fc9 | ||
|
|
2ff9cdeba6 | ||
|
|
1b7e61e77a | ||
|
|
5affe4b687 | ||
|
|
5f6d3cc7f3 | ||
|
|
c651c682c3 | ||
|
|
6163b967f7 | ||
|
|
0c1c25823c | ||
|
|
30046c8177 | ||
|
|
c893180e4d | ||
|
|
5d49fa8174 | ||
|
|
e0f8c30a94 | ||
|
|
a4b7eb7ebb | ||
|
|
ee3067baa0 | ||
|
|
73a1d8dbb6 | ||
|
|
63f778c32d | ||
|
|
9d50363a9c | ||
|
|
7dc112b6f5 | ||
|
|
3b1a478822 | ||
|
|
e114745d5f | ||
|
|
a18818d5fe | ||
|
|
c5fdf4a9bf | ||
|
|
f45610343b | ||
|
|
f45dd3bfed | ||
|
|
5d0f0138a5 | ||
|
|
827285ede0 | ||
|
|
df759a14a1 | ||
|
|
2b38d4fbe3 | ||
|
|
2dccd4016a | ||
|
|
06ccf9136b | ||
|
|
66e3420abc | ||
|
|
650fc81c6d | ||
|
|
dff786dd2a | ||
|
|
78bc2b2d97 | ||
|
|
bd79b30eda | ||
|
|
2a6a4e3db8 | ||
|
|
8af33b0845 | ||
|
|
cdb09471b1 | ||
|
|
f5c7b1d891 | ||
|
|
7908420622 | ||
|
|
e0ba6e6f08 | ||
|
|
c9cb0e5728 | ||
|
|
43c263bd22 | ||
|
|
1f38aee4d0 | ||
|
|
424d98cb80 | ||
|
|
8869913c4e | ||
|
|
69d9b23b6e | ||
|
|
c9b215ff44 | ||
|
|
ee8c66d3e8 | ||
|
|
c2589f7f26 | ||
|
|
8dd3ff6340 | ||
|
|
82e075798c | ||
|
|
732e84d2e3 | ||
|
|
c2d0176b67 | ||
|
|
01ef11496d | ||
|
|
0c768a4943 | ||
|
|
9e63e31954 | ||
|
|
c7efa0e5ad | ||
|
|
0b9de9509c | ||
|
|
92dbbcaf5a | ||
|
|
d8951ab83e | ||
|
|
a4bd3cfd6e | ||
|
|
83637aa626 | ||
|
|
f65ecd3df7 | ||
|
|
7e11c740ac | ||
|
|
7b4102964e | ||
|
|
c706b2db71 | ||
|
|
70f5b627d1 | ||
|
|
547bd51673 | ||
|
|
b42f684bbf | ||
|
|
8434cebdc7 | ||
|
|
9f7886af58 | ||
|
|
82f3cf227d | ||
|
|
8708bb76cc | ||
|
|
3a23d6798a | ||
|
|
9d3457b53c | ||
|
|
e0f5c90d93 | ||
|
|
46d2d0c346 | ||
|
|
dc2876f80a | ||
|
|
73767d68fe | ||
|
|
ee840abd5e | ||
|
|
31d401a1df | ||
|
|
05a0184f03 | ||
|
|
1707f7c8ff | ||
|
|
c0b4ea071e | ||
|
|
7a2528d007 | ||
|
|
1a37a4c3b2 | ||
|
|
ed1568c583 | ||
|
|
69d95ee27d | ||
|
|
1cfb556e6c | ||
|
|
20a0b9e968 | ||
|
|
57dd826033 | ||
|
|
fe7e259db3 | ||
|
|
88ba5a5239 | ||
|
|
bbd586895a | ||
|
|
ae1d25208e | ||
|
|
2b19896498 | ||
|
|
ea6c5c1190 | ||
|
|
50bb52c15c | ||
|
|
be4454563b | ||
|
|
0ac29a4470 | ||
|
|
136c807f16 | ||
|
|
c74e3545d4 | ||
|
|
a05345264c | ||
|
|
92c10f3042 | ||
|
|
76935090a4 | ||
|
|
2b0accb933 | ||
|
|
26e2146051 | ||
|
|
f552f27224 | ||
|
|
05deaa76fc | ||
|
|
8d79fb3f35 | ||
|
|
ec748b695e | ||
|
|
8618384bb6 | ||
|
|
11e1117611 | ||
|
|
ba08f656fe | ||
|
|
af875a7295 | ||
|
|
56e38e650a | ||
|
|
3b75f4fa94 | ||
|
|
7e18946909 | ||
|
|
6edde653b6 | ||
|
|
caedc73901 | ||
|
|
19e552f4cd | ||
|
|
6dc46aa689 | ||
|
|
2cce91beea | ||
|
|
4824b65590 | ||
|
|
f327d13252 | ||
|
|
e1a4bbb19a | ||
|
|
e11d4610a9 | ||
|
|
68d1eb678f | ||
|
|
95d1f1fd8e | ||
|
|
ceaa5f0fa2 | ||
|
|
efede4bee0 | ||
|
|
18787431a6 | ||
|
|
e30e3c85e3 | ||
|
|
e5724b43db | ||
|
|
2428b4c230 | ||
|
|
cf111ab23c | ||
|
|
3c37f1d77b | ||
|
|
e0a79b51d3 | ||
|
|
5de8e7f1d8 | ||
|
|
45ddd78624 | ||
|
|
b47d605999 | ||
|
|
b2ea235729 | ||
|
|
875764ac5c | ||
|
|
832fd25edb | ||
|
|
c526d4e675 | ||
|
|
bb8e0f0417 | ||
|
|
9cbf72d594 | ||
|
|
df65f0d951 | ||
|
|
2325635b28 | ||
|
|
1d9c24ba91 | ||
|
|
39ba7402d7 | ||
|
|
4e29df685a | ||
|
|
d1f5afce4c | ||
|
|
641783d90a | ||
|
|
7f6cdf82cf | ||
|
|
6e414f8e02 | ||
|
|
5f41e9a08d | ||
|
|
115cbc0fa1 | ||
|
|
a702d7e4c3 | ||
|
|
cbe3f7de78 | ||
|
|
0803236439 | ||
|
|
5c8c8881e0 | ||
|
|
1bbca34ca5 | ||
|
|
37e98fa0a6 | ||
|
|
9498aa5501 | ||
|
|
e659322a0b | ||
|
|
b74a5b3f8b | ||
|
|
6e2541d1b7 | ||
|
|
647717cd73 | ||
|
|
56a09fad21 | ||
|
|
b156396d1c | ||
|
|
ae1f099703 | ||
|
|
07d62ed9ad | ||
|
|
a8cf95380c | ||
|
|
48f2d479a3 | ||
|
|
67515b94c9 | ||
|
|
f1b05c5975 | ||
|
|
2e1d3b03c7 | ||
|
|
79e3be71ca | ||
|
|
82717a6775 | ||
|
|
1f0582e0d0 | ||
|
|
f4b9be340f | ||
|
|
43d6e6c233 | ||
|
|
2e608cae22 | ||
|
|
0d8dd957ad | ||
|
|
810391f03b | ||
|
|
386484d03b | ||
|
|
2c2436a430 | ||
|
|
06c178cbff | ||
|
|
ce22fef00d | ||
|
|
4c49918a97 | ||
|
|
88344438a7 | ||
|
|
09d8881b43 | ||
|
|
83fe4e19ec | ||
|
|
5733889e8a | ||
|
|
5895f5cc7c | ||
|
|
94830044f6 | ||
|
|
3200cf2b28 | ||
|
|
38cb8f4ccd | ||
|
|
73a20b9980 | ||
|
|
57b06c2143 | ||
|
|
583ab09dc4 | ||
|
|
67a5f8612f | ||
|
|
14c91a308b | ||
|
|
8995cf866c | ||
|
|
3808619f3e | ||
|
|
3206a28199 | ||
|
|
216e6874b2 | ||
|
|
28aaf7fbff | ||
|
|
55d4467886 | ||
|
|
f1887b7ea1 | ||
|
|
a8bc82c2d0 | ||
|
|
3b2dcaef43 | ||
|
|
cd217d4f38 | ||
|
|
c5e113bd20 | ||
|
|
d63eafe0b3 | ||
|
|
ea69aa2251 | ||
|
|
e697842df7 | ||
|
|
909bc2dbc5 | ||
|
|
d152c5d9c6 | ||
|
|
dad642e82d | ||
|
|
c3d757a872 | ||
|
|
a1cd69d68f | ||
|
|
cd6edddea0 | ||
|
|
22a8352963 | ||
|
|
997b04ee54 | ||
|
|
835b1c3956 | ||
|
|
097e23d20b | ||
|
|
51e55a81e7 | ||
|
|
95eeae56cc | ||
|
|
90278bd6b2 | ||
|
|
32c0019f89 | ||
|
|
f8df2c580b | ||
|
|
38dce24e26 | ||
|
|
5bfa16ace1 | ||
|
|
7b0819dce2 | ||
|
|
c349e3d6e4 | ||
|
|
e6a3ce0d3c | ||
|
|
85f8d4454f | ||
|
|
3ea6780fe7 | ||
|
|
8c2598f2c6 | ||
|
|
6c987ef4bf | ||
|
|
970915996a | ||
|
|
7159812dbc | ||
|
|
515ec1605b | ||
|
|
00802d1374 | ||
|
|
428f07dc6f | ||
|
|
dcfb1f9588 | ||
|
|
5736cc6a97 | ||
|
|
146ebd156c | ||
|
|
0ad2c37dcb | ||
|
|
253244abda | ||
|
|
0ac3d3e944 | ||
|
|
c6b1398aa9 | ||
|
|
4ba6862c61 | ||
|
|
9066c4e02a | ||
|
|
9349996989 | ||
|
|
da5157970a | ||
|
|
28efbcdd9b | ||
|
|
10200c1e29 | ||
|
|
e37e0853d1 | ||
|
|
4b464ba041 | ||
|
|
ff7863a25c | ||
|
|
72af1701a2 | ||
|
|
487ff2e8e9 | ||
|
|
6cda7cd02c | ||
|
|
77b34e2f41 | ||
|
|
0e27c87480 | ||
|
|
fb1bac5e5e | ||
|
|
27ea164da1 | ||
|
|
2ec9abc4ad | ||
|
|
bb1d903e07 | ||
|
|
9ccb1ef5d5 | ||
|
|
065ee078a2 | ||
|
|
8b876ac17f |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -7,6 +7,6 @@ ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
issuehunt: cagnulein
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: ['https://www.buymeacoffee.com/cagnulein'] # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
||||
|
||||
1038
.github/workflows/main.yml
vendored
1038
.github/workflows/main.yml
vendored
File diff suppressed because it is too large
Load Diff
7
.gitignore
vendored
7
.gitignore
vendored
@@ -25,7 +25,6 @@ src/secret.h
|
||||
|
||||
build-qdomyos-zwift-Android_Qt_5_15_2_Clang_Multi_Abi-Debug/*
|
||||
**/node_modules/*
|
||||
*.pro.user
|
||||
|
||||
template-examples/youtube-viewer/node_modules/*
|
||||
template-examples/youtube-viewer/*.json
|
||||
@@ -40,8 +39,14 @@ template-examples/train-program-saver/.eslintrc.js
|
||||
template-examples/train-program-saver/.jshintrc
|
||||
template-examples/train-program-saver/debug.js
|
||||
|
||||
google_test/*
|
||||
|
||||
# Qt-es
|
||||
*.pro.user
|
||||
*build-*
|
||||
!build-qdomyos-zwift-Qt_*_for_iOS-Debug # Needed for Apple Watch
|
||||
src/inner_templates/googlemaps/cesium-key.js
|
||||
*.autosave
|
||||
.vscode/settings.json
|
||||
/tst/Devices/.vs
|
||||
src/inner_templates/googlemaps/cesium-key.js
|
||||
|
||||
11
.gitmodules
vendored
11
.gitmodules
vendored
@@ -9,3 +9,14 @@
|
||||
path = src/qmdnsengine
|
||||
url = https://github.com/cagnulein/qmdnsengine.git
|
||||
branch = zwift
|
||||
[submodule "tst/googletest"]
|
||||
path = tst/googletest
|
||||
url = https://github.com/google/googletest.git
|
||||
branch = tags/release-1.12.1
|
||||
[submodule "src/qthttpserver"]
|
||||
path = src/qthttpserver
|
||||
url = https://github.com/qt-labs/qthttpserver
|
||||
[submodule "zwiftplay"]
|
||||
path = zwiftplay
|
||||
url = https://github.com/cagnulein/zwiftplay.git
|
||||
branch = lib
|
||||
|
||||
128
CODE_OF_CONDUCT.md
Normal file
128
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
roberto.viola83@gmail.com.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
||||
437
QZ_ESP32/QZ_ESP32.ino
Normal file
437
QZ_ESP32/QZ_ESP32.ino
Normal file
@@ -0,0 +1,437 @@
|
||||
/** NimBLE_Server Demo:
|
||||
*
|
||||
This is working to broadcast Power and Cadence under the Cycling Power Service Profile
|
||||
Data tested against Edge and Phone
|
||||
*
|
||||
*/
|
||||
#include <Arduino.h>
|
||||
#include <NimBLEDevice.h>
|
||||
|
||||
short powerInstantaneous = 0;
|
||||
short cadenceInstantaneous = 0;
|
||||
short speedInstantaneous = 0;
|
||||
float powerScale = 1.28; // incoming power is multiplied by this value for correction
|
||||
short resistance = 0; //Not currently doing anything with this value after receiving it
|
||||
bool notify = false;
|
||||
|
||||
// Define stuff for the Client that will receive data from Fitness Machine
|
||||
// The remote service we wish to connect to.
|
||||
static BLEUUID serviceUUID("1826"); // Fitness Machine
|
||||
// The characteristic of the remote service we are interested in.
|
||||
static BLEUUID charUUID("2ad2"); // Indoor Bike (Fitness Machine)
|
||||
|
||||
|
||||
static BLEUUID HRserviceUUID("180D"); // HR Service
|
||||
static BLEUUID HRcharUUID("2a37"); // HR Measuremente
|
||||
|
||||
static boolean doConnect = false;
|
||||
static boolean connected = false;
|
||||
static boolean doScan = false;
|
||||
static BLERemoteCharacteristic *pRemoteCharacteristic;
|
||||
static BLEAdvertisedDevice *myDevice;
|
||||
/*
|
||||
* Server Stuff
|
||||
*/
|
||||
static NimBLEServer *pServer;
|
||||
/** None of these are required as they will be handled by the library with defaults. **
|
||||
** Remove as you see fit for your needs */
|
||||
class ServerCallbacks : public NimBLEServerCallbacks
|
||||
{
|
||||
void onConnect(NimBLEServer *pServer)
|
||||
{
|
||||
Serial.println("Client connected");
|
||||
Serial.println("Multi-connect support: start advertising");
|
||||
NimBLEDevice::startAdvertising();
|
||||
};
|
||||
/** Alternative onConnect() method to extract details of the connection.
|
||||
* See: src/ble_gap.h for the details of the ble_gap_conn_desc struct.
|
||||
*/
|
||||
void onConnect(NimBLEServer *pServer, ble_gap_conn_desc *desc)
|
||||
{
|
||||
Serial.print("Client address: ");
|
||||
Serial.println(NimBLEAddress(desc->peer_ota_addr).toString().c_str());
|
||||
/** We can use the connection handle here to ask for different connection parameters.
|
||||
* Args: connection handle, min connection interval, max connection interval
|
||||
* latency, supervision timeout.
|
||||
* Units; Min/Max Intervals: 1.25 millisecond increments.
|
||||
* Latency: number of intervals allowed to skip.
|
||||
* Timeout: 10 millisecond increments, try for 5x interval time for best results.
|
||||
*/
|
||||
pServer->updateConnParams(desc->conn_handle, 24, 48, 0, 60);
|
||||
};
|
||||
void onDisconnect(NimBLEServer *pServer)
|
||||
{
|
||||
Serial.println("Client disconnected - start advertising");
|
||||
NimBLEDevice::startAdvertising();
|
||||
};
|
||||
void onMTUChange(uint16_t MTU, ble_gap_conn_desc *desc)
|
||||
{
|
||||
Serial.printf("MTU updated: %u for connection ID: %u\n", MTU, desc->conn_handle);
|
||||
};
|
||||
};
|
||||
|
||||
/** Handler class for characteristic actions */
|
||||
class CharacteristicCallbacks : public NimBLECharacteristicCallbacks
|
||||
{
|
||||
void onRead(NimBLECharacteristic *pCharacteristic)
|
||||
{
|
||||
Serial.print(pCharacteristic->getUUID().toString().c_str());
|
||||
Serial.print(": onRead(), value: ");
|
||||
Serial.println(pCharacteristic->getValue().c_str());
|
||||
};
|
||||
|
||||
void onWrite(NimBLECharacteristic *pCharacteristic)
|
||||
{
|
||||
Serial.print(pCharacteristic->getUUID().toString().c_str());
|
||||
Serial.print(": onWrite(), value: ");
|
||||
Serial.println(pCharacteristic->getValue().c_str());
|
||||
};
|
||||
/** Called before notification or indication is sent,
|
||||
* the value can be changed here before sending if desired.
|
||||
*/
|
||||
void onNotify(NimBLECharacteristic *pCharacteristic)
|
||||
{
|
||||
Serial.println("Sending notification to clients");
|
||||
};
|
||||
|
||||
/** The status returned in status is defined in NimBLECharacteristic.h.
|
||||
* The value returned in code is the NimBLE host return code.
|
||||
*/
|
||||
void onStatus(NimBLECharacteristic *pCharacteristic, Status status, int code)
|
||||
{
|
||||
String str = ("Notification/Indication status code: ");
|
||||
str += status;
|
||||
str += ", return code: ";
|
||||
str += code;
|
||||
str += ", ";
|
||||
str += NimBLEUtils::returnCodeToString(code);
|
||||
Serial.println(str);
|
||||
};
|
||||
|
||||
void onSubscribe(NimBLECharacteristic *pCharacteristic, ble_gap_conn_desc *desc, uint16_t subValue)
|
||||
{
|
||||
String str = "Client ID: ";
|
||||
str += desc->conn_handle;
|
||||
str += " Address: ";
|
||||
str += std::string(NimBLEAddress(desc->peer_ota_addr)).c_str();
|
||||
if (subValue == 0)
|
||||
{
|
||||
str += " Unsubscribed to ";
|
||||
}
|
||||
else if (subValue == 1)
|
||||
{
|
||||
str += " Subscribed to notifications for ";
|
||||
}
|
||||
else if (subValue == 2)
|
||||
{
|
||||
str += " Subscribed to indications for ";
|
||||
}
|
||||
else if (subValue == 3)
|
||||
{
|
||||
str += " Subscribed to notifications and indications for ";
|
||||
}
|
||||
str += std::string(pCharacteristic->getUUID()).c_str();
|
||||
|
||||
Serial.println(str);
|
||||
};
|
||||
};
|
||||
|
||||
/** Handler class for descriptor actions */
|
||||
class DescriptorCallbacks : public NimBLEDescriptorCallbacks
|
||||
{
|
||||
void onWrite(NimBLEDescriptor *pDescriptor)
|
||||
{
|
||||
std::string dscVal((char *)pDescriptor->getValue(), pDescriptor->getLength());
|
||||
Serial.print("Descriptor witten value:");
|
||||
Serial.println(dscVal.c_str());
|
||||
};
|
||||
|
||||
void onRead(NimBLEDescriptor *pDescriptor)
|
||||
{
|
||||
Serial.print(pDescriptor->getUUID().toString().c_str());
|
||||
Serial.println(" Descriptor read");
|
||||
};
|
||||
};
|
||||
/*
|
||||
* Client Stuff
|
||||
*/
|
||||
// This callback is for when data is received from Server
|
||||
static void notifyCallback(
|
||||
BLERemoteCharacteristic *pBLERemoteCharacteristic,
|
||||
uint8_t *pData,
|
||||
size_t length,
|
||||
bool isNotify)
|
||||
{
|
||||
powerInstantaneous = pData[8] | pData[9] << 8; // 2 bytes of power
|
||||
cadenceInstantaneous = 60; //(pData[4] | pData[5] << 8) / 2; // 2 bytes of power in 0.5 resolution RPM, convert to RPM
|
||||
resistance = pData[6]; // 1 byte of resistance
|
||||
Serial.printf("Power = %d | Cadence = %d | Resistance = %d\n", powerInstantaneous, cadenceInstantaneous, resistance);
|
||||
}
|
||||
|
||||
/** None of these are required as they will be handled by the library with defaults. **
|
||||
** Remove as you see fit for your needs */
|
||||
class MyClientCallback : public BLEClientCallbacks
|
||||
{
|
||||
void onConnect(BLEClient *pclient)
|
||||
{
|
||||
}
|
||||
|
||||
void onDisconnect(BLEClient *pclient)
|
||||
{
|
||||
connected = false;
|
||||
Serial.println("onDisconnect");
|
||||
}
|
||||
};
|
||||
|
||||
bool connectToServer()
|
||||
{
|
||||
Serial.print("Forming a connection to ");
|
||||
Serial.println(myDevice->getAddress().toString().c_str());
|
||||
|
||||
BLEClient *pClient = BLEDevice::createClient();
|
||||
Serial.println(" - Created client");
|
||||
|
||||
pClient->setClientCallbacks(new MyClientCallback());
|
||||
|
||||
// Connect to the remove BLE Server.
|
||||
pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
|
||||
Serial.println(" - Connected to server");
|
||||
|
||||
// Obtain a reference to the service we are after in the remote BLE server.
|
||||
BLERemoteService *pRemoteService = pClient->getService(serviceUUID);
|
||||
if (pRemoteService == nullptr)
|
||||
{
|
||||
Serial.print("Failed to find our service UUID: ");
|
||||
Serial.println(serviceUUID.toString().c_str());
|
||||
pClient->disconnect();
|
||||
return false;
|
||||
}
|
||||
Serial.println(" - Found our service");
|
||||
|
||||
// Obtain a reference to the characteristic in the service of the remote BLE server.
|
||||
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
|
||||
if (pRemoteCharacteristic == nullptr)
|
||||
{
|
||||
Serial.print("Failed to find our characteristic UUID: ");
|
||||
Serial.println(charUUID.toString().c_str());
|
||||
pClient->disconnect();
|
||||
return false;
|
||||
}
|
||||
Serial.println(" - Found our characteristic");
|
||||
|
||||
// Read the value of the characteristic.
|
||||
if (pRemoteCharacteristic->canRead())
|
||||
{
|
||||
std::string value = pRemoteCharacteristic->readValue();
|
||||
Serial.print("The characteristic value was: ");
|
||||
Serial.println(value.c_str());
|
||||
}
|
||||
|
||||
if (pRemoteCharacteristic->canNotify())
|
||||
pRemoteCharacteristic->registerForNotify(notifyCallback);
|
||||
|
||||
connected = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan for BLE servers and find the first one that advertises the service we are looking for.
|
||||
*/
|
||||
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
|
||||
{
|
||||
/**
|
||||
* Called for each advertising BLE server.
|
||||
*/
|
||||
|
||||
/*** Only a reference to the advertised device is passed now
|
||||
void onResult(BLEAdvertisedDevice advertisedDevice) { **/
|
||||
void onResult(BLEAdvertisedDevice *advertisedDevice)
|
||||
{
|
||||
Serial.print("BLE Advertised Device found: ");
|
||||
Serial.println(advertisedDevice->toString().c_str());
|
||||
|
||||
// We have found a device, let us now see if it contains the service we are looking for.
|
||||
/********************************************************************************
|
||||
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
|
||||
********************************************************************************/
|
||||
if (advertisedDevice->haveServiceUUID() && advertisedDevice->isAdvertisingService(serviceUUID))
|
||||
{
|
||||
|
||||
BLEDevice::getScan()->stop();
|
||||
/*******************************************************************
|
||||
myDevice = new BLEAdvertisedDevice(advertisedDevice);
|
||||
*******************************************************************/
|
||||
myDevice = advertisedDevice; /** Just save the reference now, no need to copy the object */
|
||||
doConnect = true;
|
||||
doScan = true;
|
||||
|
||||
} // Found our server
|
||||
} // onResult
|
||||
}; // MyAdvertisedDeviceCallbacks
|
||||
|
||||
//delays for X ms, should not block execution
|
||||
void softDelay(unsigned long delayTime)
|
||||
{
|
||||
unsigned long startTime = millis();
|
||||
while ((millis() - startTime) < delayTime)
|
||||
{
|
||||
//wait
|
||||
}
|
||||
}
|
||||
|
||||
/** Define callback instances globally to use for multiple Characteristics \ Descriptors */
|
||||
// This section is for the Server that will broadcast the data as Cycling Power
|
||||
static DescriptorCallbacks dscCallbacks;
|
||||
static CharacteristicCallbacks chrCallbacks;
|
||||
NimBLECharacteristic *CyclingPowerFeature = NULL;
|
||||
NimBLECharacteristic *CyclingPowerMeasurement = NULL;
|
||||
NimBLECharacteristic *CyclingPowerSensorLocation = NULL;
|
||||
NimBLECharacteristic *HRMeasurement = NULL;
|
||||
unsigned char bleBuffer[8];
|
||||
unsigned char slBuffer[1];
|
||||
unsigned char fBuffer[4];
|
||||
unsigned short revolutions = 0;
|
||||
unsigned short timestamp = 0;
|
||||
unsigned short flags = 0x20;
|
||||
byte sensorlocation = 0x0D;
|
||||
long lastNotify = 0;
|
||||
long lastRevolution = 0;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println("Starting NimBLE Server");
|
||||
|
||||
/** sets device name */
|
||||
NimBLEDevice::init("QZESP");
|
||||
/** Optional: set the transmit power, default is 3db */
|
||||
NimBLEDevice::setPower(ESP_PWR_LVL_P9); /** +9db */
|
||||
|
||||
pServer = NimBLEDevice::createServer();
|
||||
pServer->setCallbacks(new ServerCallbacks());
|
||||
|
||||
fBuffer[0] = 0x00;
|
||||
fBuffer[1] = 0x00;
|
||||
fBuffer[2] = 0x00;
|
||||
fBuffer[3] = 0x08;
|
||||
|
||||
slBuffer[0] = sensorlocation & 0xff;
|
||||
|
||||
NimBLEService *pDeadService = pServer->createService("1818");
|
||||
CyclingPowerFeature = pDeadService->createCharacteristic(
|
||||
"2A65",
|
||||
NIMBLE_PROPERTY::READ);
|
||||
CyclingPowerSensorLocation = pDeadService->createCharacteristic(
|
||||
"2A5D",
|
||||
NIMBLE_PROPERTY::READ);
|
||||
CyclingPowerMeasurement = pDeadService->createCharacteristic(
|
||||
"2A63",
|
||||
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
|
||||
|
||||
CyclingPowerFeature->setValue(fBuffer, 4);
|
||||
CyclingPowerSensorLocation->setValue(slBuffer, 1);
|
||||
CyclingPowerMeasurement->setValue(slBuffer, 1);
|
||||
|
||||
/** Start the services when finished creating all Characteristics and Descriptors */
|
||||
pDeadService->start();
|
||||
|
||||
#if 0
|
||||
// HR service
|
||||
NimBLEService *pHRService = pServer->createService("180D");
|
||||
HRMeasurement = pHRService->createCharacteristic(
|
||||
"2A37",
|
||||
NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::NOTIFY);
|
||||
|
||||
HRMeasurement->setValue(fBuffer, 2);
|
||||
|
||||
/** Start the services when finished creating all Characteristics and Descriptors */
|
||||
pHRService->start();
|
||||
#endif
|
||||
|
||||
NimBLEAdvertising *pAdvertising = NimBLEDevice::getAdvertising();
|
||||
/** Add the services to the advertisement data **/
|
||||
// pAdvertising->addServiceUUID(pHRService->getUUID());
|
||||
pAdvertising->addServiceUUID(pDeadService->getUUID());
|
||||
pAdvertising->setScanResponse(true);
|
||||
pAdvertising->start();
|
||||
|
||||
Serial.println("Advertising Started");
|
||||
|
||||
Serial.println("Starting Arduino BLE Client application...");
|
||||
BLEDevice::init("");
|
||||
|
||||
// Retrieve a Scanner and set the callback we want to use to be informed when we
|
||||
// have detected a new device. Specify that we want active scanning and start the
|
||||
// scan to run for 5 seconds.
|
||||
BLEScan *pBLEScan = BLEDevice::getScan();
|
||||
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
|
||||
pBLEScan->setInterval(1349);
|
||||
pBLEScan->setWindow(449);
|
||||
pBLEScan->setActiveScan(true);
|
||||
pBLEScan->start(5, false);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// If the flag "doConnect" is true then we have scanned for and found the desired
|
||||
// BLE Server with which we wish to connect. Now we connect to it. Once we are
|
||||
// connected we set the connected flag to be true.
|
||||
if (doConnect == true)
|
||||
{
|
||||
if (connectToServer())
|
||||
{
|
||||
Serial.println("We are now connected to the BLE Server.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("We have failed to connect to the server; there is nothing more we will do.");
|
||||
}
|
||||
doConnect = false;
|
||||
}
|
||||
// If we are connected to a peer BLE Server, update the characteristic each time we are reached
|
||||
// with the current time since boot.
|
||||
if (connected)
|
||||
{
|
||||
//Stuff to do when connected to Client
|
||||
}
|
||||
else if (doScan)
|
||||
{
|
||||
BLEDevice::getScan()->start(0); // this is just sample to start scan after disconnect, most likely there is better way to do it in arduino
|
||||
}
|
||||
|
||||
// convert RPM to timestamp
|
||||
if (cadenceInstantaneous != 0 && (millis()) >= (lastRevolution + (60000 / cadenceInstantaneous)))
|
||||
{
|
||||
revolutions++; // One crank revolution should have passed, add one revolution
|
||||
timestamp = (unsigned short)(((millis() * 1024) / 1000) % 65536); // create timestamp and format
|
||||
lastRevolution = millis();
|
||||
}
|
||||
|
||||
if (millis() - lastNotify >= 1000) // do this every second
|
||||
{
|
||||
//if (pServer->getConnectedCount() > 0)
|
||||
{
|
||||
bleBuffer[0] = flags & 0xff;
|
||||
bleBuffer[1] = (flags >> 8) & 0xff;
|
||||
bleBuffer[2] = powerInstantaneous & 0xff;
|
||||
bleBuffer[3] = (powerInstantaneous >> 8) & 0xff;
|
||||
bleBuffer[4] = revolutions & 0xff;
|
||||
bleBuffer[5] = (revolutions >> 8) & 0xff;
|
||||
bleBuffer[6] = timestamp & 0xff;
|
||||
bleBuffer[7] = (timestamp >> 8) & 0xff;
|
||||
CyclingPowerMeasurement->setValue(bleBuffer, 8);
|
||||
CyclingPowerMeasurement->notify();
|
||||
|
||||
/*bleBuffer[0] = 0;
|
||||
bleBuffer[1] = powerInstantaneous;
|
||||
|
||||
HRMeasurement->setValue(bleBuffer, 2);
|
||||
HRMeasurement->notify();*/
|
||||
lastNotify = millis();
|
||||
}
|
||||
}
|
||||
/*if (pServer->getConnectedCount() == 0)
|
||||
{
|
||||
powerInstantaneous = 0;
|
||||
}*/
|
||||
}
|
||||
53
QZ_ESP32/ftms_rower.ino/ftms_rower.ino.ino
Normal file
53
QZ_ESP32/ftms_rower.ino/ftms_rower.ino.ino
Normal file
@@ -0,0 +1,53 @@
|
||||
#include <NimBLEDevice.h>
|
||||
|
||||
#define INDOOR_BIKE_DATA_UUID "00002AD2-0000-1000-8000-00805f9b34fb"
|
||||
#define CUSTOM_SERVICE_UUID "ce060000-43e5-11e4-916c-0800200c9a66"
|
||||
|
||||
NimBLEServer* pServer = nullptr;
|
||||
NimBLECharacteristic* pIndoorBikeDataChar = nullptr;
|
||||
|
||||
class ServerCallbacks: public NimBLEServerCallbacks {
|
||||
void onConnect(NimBLEServer* pServer) {
|
||||
Serial.println("Client connected");
|
||||
};
|
||||
|
||||
void onDisconnect(NimBLEServer* pServer) {
|
||||
Serial.println("Client disconnected");
|
||||
}
|
||||
};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.println("Starting NimBLE Server");
|
||||
|
||||
NimBLEDevice::init("PM5 431431183 Row");
|
||||
|
||||
pServer = NimBLEDevice::createServer();
|
||||
pServer->setCallbacks(new ServerCallbacks());
|
||||
|
||||
NimBLEService* pFtmService = pServer->createService("1826");
|
||||
//NimBLEService* pCustomService = pServer->createService(CUSTOM_SERVICE_UUID);
|
||||
|
||||
pIndoorBikeDataChar = pFtmService->createCharacteristic(
|
||||
INDOOR_BIKE_DATA_UUID,
|
||||
NIMBLE_PROPERTY::READ |
|
||||
NIMBLE_PROPERTY::NOTIFY
|
||||
);
|
||||
|
||||
pFtmService->start();
|
||||
//pCustomService->start();
|
||||
|
||||
NimBLEAdvertising* pAdvertising = NimBLEDevice::getAdvertising();
|
||||
pAdvertising->addServiceUUID(pFtmService->getUUID());
|
||||
//pAdvertising->addServiceUUID(CUSTOM_SERVICE_UUID);
|
||||
const std::string data = { 0x01, 0x10, 0x00 }; // Imposta i valori desiderati
|
||||
pAdvertising->setServiceData(pFtmService->getUUID(), data);
|
||||
pAdvertising->start();
|
||||
|
||||
Serial.println("Advertising started");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Metti qui il tuo codice principale, da eseguire ripetutamente
|
||||
// Ad esempio, potresti aggiornare il valore della caratteristica Indoor Bike Data
|
||||
}
|
||||
113
README.md
113
README.md
@@ -7,35 +7,100 @@ Zwift bridge for Treadmills and Bike!
|
||||
[<img src="docs/img/app_store.png">](https://apps.apple.com/app/id1543684531?fbclid=IwAR10H6y3mEgwkTlGJON3e8voYOh2wt3kLFOpFzoIXaYZ_N0y0pDvKxHMUaM)
|
||||
<a href="https://www.buymeacoffee.com/cagnulein" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: 41px !important;width: 174px !important;box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" ></a>
|
||||
|
||||

|
||||
|
||||
[](https://www.youtube.com/watch?v=GgG3dMhmo2Y)
|
||||
|
||||

|
||||

|
||||
|
||||
UI on Linux
|
||||
|
||||

|
||||
|
||||
UI on MacOS
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<img src="icons/AppScreen/iOS%20Phones%20-%206.5_/screenshot1.jpeg" style="height: 400px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" >
|
||||
</td>
|
||||
<td>
|
||||
<img src="icons/AppScreen/iOS%20Phones%20-%206.5_/screenshot2.jpeg" style="height: 400px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" >
|
||||
</td>
|
||||
<td>
|
||||
<img src="icons/AppScreen/iOS%20Phones%20-%206.5_/screenshot3.jpeg" style="height: 400px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" >
|
||||
</td>
|
||||
<td>
|
||||
<img src="icons/AppScreen/iOS%20Phones%20-%206.5_/screenshot4.jpeg" style="height: 400px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" >
|
||||
</td>
|
||||
<td>
|
||||
<img src="icons/AppScreen/iOS%20Phones%20-%206.5_/screenshot5.jpeg" style="height: 400px !important; box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;-webkit-box-shadow: 0px 3px 2px 0px rgba(190, 190, 190, 0.5) !important;" >
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
### Features
|
||||
|
||||
1. Domyos compatible
|
||||
2. Toorx TRX Route Key compatible
|
||||
3. Echelon Connect Sport compatible
|
||||
4. Zwift compatible
|
||||
5. Create, load and save train programs
|
||||
6. Measure distance, elevation gain and watts
|
||||
7. Gpx import (with difficulty slider)
|
||||
8. Realtime Charts
|
||||
# UI Features
|
||||
|
||||
|Feature|Bike|Treadmill|Elliptical|Rower|Notes|
|
||||
|:---|:---:|:---:|:---:|:---:|---:|
|
||||
|Tiles Customization|X|X|X|X|Order and visibility of each tile|
|
||||
|Profiles|X|X|X|X|Different user or different fitness device profiles|
|
||||
|UI Zoom Customization|X|X|X|X||
|
||||
|
||||
# Peloton Features
|
||||
|
||||
|Feature|Bike|Treadmill|Elliptical|Rower|Notes|
|
||||
|:---|:---:|:---:|:---:|:---:|---:|
|
||||
|Bike metrics on the peloton app|X||X|||
|
||||
|Power zone with auto resistance|X|||||
|
||||
|Peloton real-time resistance conversion|X||X||with the possibility to customize it|
|
||||
|Peloton real-time auto-resistance|X||X||with the possibility to customize it|
|
||||
|Peloton auto speed and auto inclination||X|X||with the possibility to customize it|
|
||||
|
||||
# Heart Rate Features
|
||||
|
||||
|Feature|Bike|Treadmill|Elliptical|Rower|Notes|
|
||||
|:---|:---:|:---:|:---:|:---:|---:|
|
||||
|Heart Rate support|X|X|X|X|Apple Watch, ANT+ devices and Bluetooth devices|
|
||||
|Heart Rate Zones Customizations|X|X|X|X||
|
||||
|Ability to calculate Wattage from HR and Cadence|X||||for the bikes that doesn't have a power sensor|
|
||||
|
||||
# 3rd Apps Compatibility
|
||||
|
||||
|Feature|Bike|Treadmill|Elliptical|Rower|Notes|
|
||||
|:---|:---:|:---:|:---:|:---:|---:|
|
||||
|Zwift Compatibility|X|X|X|X||
|
||||
|Zwift Auto resistance|X||X|||
|
||||
|Zwift Auto inclination and speed||X|X||https://www.youtube.com/watch?v=KTQ2n7yeDbo|
|
||||
|Wahoo RGT Compatibility|X|X|X|X||
|
||||
|VzFit Compatibility|X|X|X|X||
|
||||
|Rouvy Compatibility|X|X|X|X||
|
||||
|IFIT app Compatibility|X|||||
|
||||
|Echelon app Compatibility|X|||||
|
||||
|Wahoo Dircon Compatibility|X|X|X|X|in order to send data to Zwift or RGT with Wifi only!|
|
||||
|One device only support for Zwift and Wahoo RGT|X|X|X|X|using Wahoo Dircon https://www.youtube.com/watch?v=gYYUXNWFAok|
|
||||
|BitGym Compatibility|X|X|X|X||
|
||||
|
||||
# Training Program
|
||||
|Feature|Bike|Treadmill|Elliptical|Rower|Notes|
|
||||
|:---|:---:|:---:|:---:|:---:|---:|
|
||||
|Builtin video support (Kinomap like)|X|X|X|X|Files could be local or on the cloud!|
|
||||
|GPX auto following|X|X|X|X||
|
||||
|2D/3D maps for GPX|X|X|X|X||
|
||||
|ZWO (Zwift workout file) compatibility|X|X|X|X||
|
||||
|XML Workout file compatibility|X|X|X|X||
|
||||
|Auto follow workout based on your heart rate|X|X|X|X||
|
||||
|Random workout|X|X|X|X||
|
||||
|
||||
|
||||
# Statistics
|
||||
|
||||
|Feature|Bike|Treadmill|Elliptical|Rower|Notes|
|
||||
|:---|:---:|:---:|:---:|:---:|---:|
|
||||
|E-Mail report|X|X|X|X|at the end of the workout|
|
||||
|Strava integration|X|X|X|X|press stop at the end of the workout to auto upload it|
|
||||
|
||||
# Misc
|
||||
|
||||
|Feature|Bike|Treadmill|Elliptical|Rower|Notes|
|
||||
|:---|:---:|:---:|:---:|:---:|---:|
|
||||
|Resistance shifting with bluetooth remote|X||X|||
|
||||
|TTS support|X|X|X|X||
|
||||
|
||||

|
||||
|
||||
### Installation
|
||||
|
||||
You can install on multiple platforms.
|
||||
You can install it on multiple platforms.
|
||||
Read the [installation procedure](docs/10_Installation.md)
|
||||
|
||||
|
||||
@@ -45,7 +110,7 @@ You can run the app on [Macintosh or Linux devices](docs/10_Installation.md). IO
|
||||
|
||||
QDomyos-Zwift works on every [FTMS-compatible application](docs/20_supported_devices_and_applications.md), and virtually any [bluetooth enabled device](docs/20_supported_devices_and_applications.md).
|
||||
|
||||
### No gui version
|
||||
### No GUI version
|
||||
|
||||
run as
|
||||
|
||||
@@ -57,7 +122,7 @@ https://github.com/ProH4Ck/treadmill-bridge
|
||||
|
||||
https://www.livestrong.com/article/422012-what-is-10-degrees-in-incline-on-a-treadmill/
|
||||
|
||||
Icons used in this documentation comes from [flaticon.com](https://www.flaticon.com)
|
||||
Icons used in this documentation come from [flaticon.com](https://www.flaticon.com)
|
||||
|
||||
### Blog
|
||||
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
||||
#import "swiftDebug.h"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -53,12 +53,17 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_accessibility_support_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bluetooth.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bluetooth_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bodymovin_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bootstrap_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_charts.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_charts_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_clipboard_support_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_concurrent.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_concurrent_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_core.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_core_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_datavisualization.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_datavisualization_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_devicediscovery_support_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_edid_support_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_eventdispatcher_support_private.pri \
|
||||
@@ -71,6 +76,9 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_gui_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_help.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_help_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_httpserver.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_httpserver_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_httpserver.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_location.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_location_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_macextras.pri \
|
||||
@@ -95,6 +103,8 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_positioning_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_positioningquick.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_positioningquick_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_purchasing.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_purchasing_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qml.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qml_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qmldebug_private.pri \
|
||||
@@ -107,6 +117,16 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qmlworkerscript_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qtmultimediaquicktools_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3d.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3d_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dassetimport.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dassetimport_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3drender.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3drender_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3druntimerender.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3druntimerender_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dutils.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dutils_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quickcontrols2.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quickcontrols2_private.pri \
|
||||
@@ -120,12 +140,21 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_remoteobjects_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_repparser.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_repparser_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_script.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_script_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scripttools.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scripttools_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scxml.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scxml_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sensors.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sensors_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_serialbus.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_serialbus_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sql.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sql_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_sslserver.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_sslserver_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sslserver.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_svg.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_svg_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_testlib.pri \
|
||||
@@ -136,6 +165,8 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_uiplugin.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_uitools.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_uitools_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_virtualkeyboard.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_virtualkeyboard_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_webchannel.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_webchannel_private.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_websockets.pri \
|
||||
@@ -194,15 +225,26 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtiff.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtmedia_audioengine.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtmultimedia_m3u.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtpassthrucanbus.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtpeakcanbus.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtposition_cl.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtposition_positionpoll.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensorgestures_plugin.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensorgestures_shakeplugin.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensors_generic.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensors_ios.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qttinycanbus.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtuiotouchplugin.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualcanbus.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_hangul.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_openwnn.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_pinyin.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_tcime.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_thai.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboardplugin.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtwebview_darwin.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qwbmp.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qwebgl.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qwebp.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_scene2d.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/features/qt_functions.prf \
|
||||
@@ -219,6 +261,9 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/features/default_pre.prf \
|
||||
../../Qt/5.15.2/ios/mkspecs/features/mac/default_pre.prf \
|
||||
../../Qt/5.15.2/ios/mkspecs/features/uikit/default_pre.prf \
|
||||
../defaults.pri \
|
||||
../src/purchasing/purchasing.pri \
|
||||
../src/qdomyos-zwift.pri \
|
||||
../../Qt/5.15.2/ios/mkspecs/features/resolve_config.prf \
|
||||
../../Qt/5.15.2/ios/mkspecs/features/uikit/resolve_config.prf \
|
||||
../../Qt/5.15.2/ios/mkspecs/features/default_post.prf \
|
||||
@@ -226,6 +271,9 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/features/uikit/default_post.prf \
|
||||
../../Qt/5.15.2/ios/mkspecs/macx-ios-clang/features/default_post.prf \
|
||||
../../Qt/5.15.2/ios/mkspecs/features/mac/objective_c.prf \
|
||||
../../Qt/5.15.2/ios/mkspecs/features/qmltypes.prf \
|
||||
../../Qt/5.15.2/ios/mkspecs/features/metatypes.prf \
|
||||
../../Qt/5.15.2/ios/mkspecs/features/ltcg.prf \
|
||||
../../Qt/5.15.2/ios/mkspecs/features/qml_debug.prf \
|
||||
../../Qt/5.15.2/ios/mkspecs/features/mac/mac.prf \
|
||||
../../Qt/5.15.2/ios/mkspecs/features/uikit/bitcode.prf \
|
||||
@@ -264,6 +312,18 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/lib/libqtharfbuzz_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5Core_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libqtpcre2_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/mediaservice/libqavfmediaplayer_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_esri_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_itemsoverlay_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_mapbox_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_mapboxgl_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_nokia_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_osm_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/webview/libqtwebview_darwin_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/mediaservice/libqavfcamera_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/mediaservice/libqtmedia_audioengine_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/audio/libqtaudio_coreaudio_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/playlistformats/libqtmultimedia_m3u_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/imageformats/libqgif_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/imageformats/libqicns_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/imageformats/libqico_debug.prl \
|
||||
@@ -288,32 +348,51 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/plugins/qmltooling/libqmldbg_server_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/qmltooling/libqmldbg_tcp_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/bearer/libqgenericbearer_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/texttospeech/libqtexttospeech_speechios_debug.prl \
|
||||
../../Qt/5.15.2/ios/plugins/sqldrivers/libqsqlite_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5HttpServer_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5SslServer_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5Charts_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5Widgets_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5Location_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5PositioningQuick_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5QuickControls2_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5Quick_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5Multimedia_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5WebView_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5Bluetooth_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5Xml_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5Positioning_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5QmlModels_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5Qml_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5NetworkAuth_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5WebSockets_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5Network_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5TextToSpeech_debug.prl \
|
||||
../../Qt/5.15.2/ios/lib/libQt5Concurrent_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick.2/libqtquick2plugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Layouts/libqquicklayoutsplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/libqtquickcontrols2plugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Material/libqtquickcontrols2materialstyleplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/libqtgraphicaleffectsplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Window.2/libwindowplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/Qt/labs/settings/libqmlsettingsplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQml/libqmlplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Templates.2/libqtquicktemplates2plugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/private/libqtgraphicaleffectsprivate_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQml/Models.2/libmodelsplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQml/WorkerScript.2/libworkerscriptplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Dialogs/libdialogplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Window.2/libwindowplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Material/libqtquickcontrols2materialstyleplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtWebView/libdeclarative_webview_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtCharts/libqtchartsqml2_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/Qt/labs/folderlistmodel/libqmlfolderlistmodelplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/Qt/labs/settings/libqmlsettingsplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Dialogs/libdialogplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtPositioning/libdeclarative_positioning_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtLocation/libdeclarative_location_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Dialogs/Private/libdialogsprivateplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls/libqtquickcontrolsplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/PrivateWidgets/libwidgetsplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Layouts/libqquicklayoutsplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/libqtgraphicaleffectsplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/Qt/labs/platform/libqtlabsplatformplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtMultimedia/libdeclarative_multimedia_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/private/libqtgraphicaleffectsprivate_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Fusion/libqtquickcontrols2fusionstyleplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Universal/libqtquickcontrols2universalstyleplugin_debug.prl \
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Imagine/libqtquickcontrols2imaginestyleplugin_debug.prl
|
||||
@@ -361,12 +440,17 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_accessibility_support_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bluetooth.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bluetooth_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bodymovin_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_bootstrap_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_charts.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_charts_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_clipboard_support_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_concurrent.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_concurrent_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_core.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_core_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_datavisualization.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_datavisualization_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_devicediscovery_support_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_edid_support_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_eventdispatcher_support_private.pri:
|
||||
@@ -379,6 +463,9 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_gui_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_help.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_help_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_httpserver.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_httpserver_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_httpserver.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_location.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_location_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_macextras.pri:
|
||||
@@ -403,6 +490,8 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_positioning_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_positioningquick.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_positioningquick_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_purchasing.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_purchasing_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qml.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qml_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qmldebug_private.pri:
|
||||
@@ -415,6 +504,16 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qmlworkerscript_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_qtmultimediaquicktools_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3d.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3d_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dassetimport.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dassetimport_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3drender.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3drender_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3druntimerender.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3druntimerender_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dutils.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick3dutils_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quick_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quickcontrols2.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_quickcontrols2_private.pri:
|
||||
@@ -428,12 +527,21 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_remoteobjects_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_repparser.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_repparser_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_script.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_script_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scripttools.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scripttools_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scxml.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_scxml_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sensors.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sensors_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_serialbus.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_serialbus_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sql.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sql_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_sslserver.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules-inst/qt_lib_sslserver_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_sslserver.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_svg.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_svg_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_testlib.pri:
|
||||
@@ -444,6 +552,8 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_uiplugin.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_uitools.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_uitools_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_virtualkeyboard.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_virtualkeyboard_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_webchannel.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_webchannel_private.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_lib_websockets.pri:
|
||||
@@ -502,15 +612,26 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtiff.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtmedia_audioengine.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtmultimedia_m3u.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtpassthrucanbus.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtpeakcanbus.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtposition_cl.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtposition_positionpoll.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensorgestures_plugin.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensorgestures_shakeplugin.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensors_generic.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtsensors_ios.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qttinycanbus.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtuiotouchplugin.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualcanbus.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_hangul.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_openwnn.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_pinyin.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_tcime.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboard_thai.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtvirtualkeyboardplugin.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qtwebview_darwin.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qwbmp.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qwebgl.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_qwebp.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/modules/qt_plugin_scene2d.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/features/qt_functions.prf:
|
||||
@@ -527,6 +648,9 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/features/default_pre.prf:
|
||||
../../Qt/5.15.2/ios/mkspecs/features/mac/default_pre.prf:
|
||||
../../Qt/5.15.2/ios/mkspecs/features/uikit/default_pre.prf:
|
||||
../defaults.pri:
|
||||
../src/purchasing/purchasing.pri:
|
||||
../src/qdomyos-zwift.pri:
|
||||
../../Qt/5.15.2/ios/mkspecs/features/resolve_config.prf:
|
||||
../../Qt/5.15.2/ios/mkspecs/features/uikit/resolve_config.prf:
|
||||
../../Qt/5.15.2/ios/mkspecs/features/default_post.prf:
|
||||
@@ -534,6 +658,9 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/mkspecs/features/uikit/default_post.prf:
|
||||
../../Qt/5.15.2/ios/mkspecs/macx-ios-clang/features/default_post.prf:
|
||||
../../Qt/5.15.2/ios/mkspecs/features/mac/objective_c.prf:
|
||||
../../Qt/5.15.2/ios/mkspecs/features/qmltypes.prf:
|
||||
../../Qt/5.15.2/ios/mkspecs/features/metatypes.prf:
|
||||
../../Qt/5.15.2/ios/mkspecs/features/ltcg.prf:
|
||||
../../Qt/5.15.2/ios/mkspecs/features/qml_debug.prf:
|
||||
../../Qt/5.15.2/ios/mkspecs/features/mac/mac.prf:
|
||||
../../Qt/5.15.2/ios/mkspecs/features/uikit/bitcode.prf:
|
||||
@@ -572,6 +699,18 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/lib/libqtharfbuzz_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5Core_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libqtpcre2_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/mediaservice/libqavfmediaplayer_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_esri_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_itemsoverlay_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_mapbox_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_mapboxgl_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_nokia_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/geoservices/libqtgeoservices_osm_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/webview/libqtwebview_darwin_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/mediaservice/libqavfcamera_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/mediaservice/libqtmedia_audioengine_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/audio/libqtaudio_coreaudio_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/playlistformats/libqtmultimedia_m3u_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/imageformats/libqgif_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/imageformats/libqicns_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/imageformats/libqico_debug.prl:
|
||||
@@ -596,32 +735,51 @@ qdomyoszwift.xcodeproj/project.pbxproj: ../src/qdomyos-zwift.pro ../../Qt/5.15.2
|
||||
../../Qt/5.15.2/ios/plugins/qmltooling/libqmldbg_server_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/qmltooling/libqmldbg_tcp_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/bearer/libqgenericbearer_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/texttospeech/libqtexttospeech_speechios_debug.prl:
|
||||
../../Qt/5.15.2/ios/plugins/sqldrivers/libqsqlite_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5HttpServer_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5SslServer_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5Charts_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5Widgets_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5Location_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5PositioningQuick_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5QuickControls2_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5Quick_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5Multimedia_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5WebView_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5Bluetooth_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5Xml_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5Positioning_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5QmlModels_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5Qml_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5NetworkAuth_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5WebSockets_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5Network_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5TextToSpeech_debug.prl:
|
||||
../../Qt/5.15.2/ios/lib/libQt5Concurrent_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick.2/libqtquick2plugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Layouts/libqquicklayoutsplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/libqtquickcontrols2plugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Material/libqtquickcontrols2materialstyleplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/libqtgraphicaleffectsplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Window.2/libwindowplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/Qt/labs/settings/libqmlsettingsplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQml/libqmlplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Templates.2/libqtquicktemplates2plugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/private/libqtgraphicaleffectsprivate_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQml/Models.2/libmodelsplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQml/WorkerScript.2/libworkerscriptplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Dialogs/libdialogplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Window.2/libwindowplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Material/libqtquickcontrols2materialstyleplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtWebView/libdeclarative_webview_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtCharts/libqtchartsqml2_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/Qt/labs/folderlistmodel/libqmlfolderlistmodelplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/Qt/labs/settings/libqmlsettingsplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Dialogs/libdialogplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtPositioning/libdeclarative_positioning_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtLocation/libdeclarative_location_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Dialogs/Private/libdialogsprivateplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls/libqtquickcontrolsplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/PrivateWidgets/libwidgetsplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Layouts/libqquicklayoutsplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/libqtgraphicaleffectsplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/Qt/labs/platform/libqtlabsplatformplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtMultimedia/libdeclarative_multimedia_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtGraphicalEffects/private/libqtgraphicaleffectsprivate_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Fusion/libqtquickcontrols2fusionstyleplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Universal/libqtquickcontrols2universalstyleplugin_debug.prl:
|
||||
../../Qt/5.15.2/ios/qml/QtQuick/Controls.2/Imagine/libqtquickcontrols2imaginestyleplugin_debug.prl:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -87,8 +87,6 @@
|
||||
</RemoteRunnable>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "876E4E102594747F00BD5714"
|
||||
BuildableName = "watchkit.app"
|
||||
BlueprintName = "watchkit"
|
||||
ReferencedContainer = "container:qdomyoszwift.xcodeproj">
|
||||
|
||||
@@ -17,16 +17,33 @@ class MainController: WKInterfaceController {
|
||||
@IBOutlet weak var distanceLabel: WKInterfaceLabel!
|
||||
@IBOutlet weak var heartRateLabel: WKInterfaceLabel!
|
||||
@IBOutlet weak var startButton: WKInterfaceButton!
|
||||
@IBOutlet weak var cmbSports: WKInterfacePicker!
|
||||
static var start: Bool! = false
|
||||
let pedometer = CMPedometer()
|
||||
var sport: Int = 0
|
||||
|
||||
override func awake(withContext context: Any?) {
|
||||
super.awake(withContext: context)
|
||||
let sports: [WKPickerItem] = [WKPickerItem(),WKPickerItem(),WKPickerItem(),WKPickerItem(),WKPickerItem()]
|
||||
sports[0].title = "Bike"
|
||||
sports[1].title = "Run"
|
||||
sports[2].title = "Walk"
|
||||
sports[3].title = "Elliptical"
|
||||
sports[4].title = "Rowing"
|
||||
cmbSports.setItems(sports)
|
||||
sport = UserDefaults.standard.value(forKey: "sport") as? Int ?? 0
|
||||
cmbSports.setSelectedItemIndex(sport)
|
||||
|
||||
// Configure interface objects here.
|
||||
print("AWAKE")
|
||||
}
|
||||
|
||||
@IBAction func changeSport(_ value: Int) {
|
||||
self.sport = value
|
||||
UserDefaults.standard.set(value, forKey: "sport")
|
||||
UserDefaults.standard.synchronize()
|
||||
}
|
||||
|
||||
override func willActivate() {
|
||||
// This method is called when watch view controller is about to be visible to user
|
||||
super.willActivate()
|
||||
@@ -57,6 +74,7 @@ extension MainController {
|
||||
MainController.start = true
|
||||
startButton.setTitle("Stop")
|
||||
WorkoutTracking.authorizeHealthKit()
|
||||
WorkoutTracking.shared.setSport(sport)
|
||||
WorkoutTracking.shared.startWorkOut()
|
||||
WorkoutTracking.shared.delegate = self
|
||||
|
||||
@@ -86,8 +104,15 @@ extension MainController: WorkoutTrackingDelegate {
|
||||
"\(heartRate)" as AnyObject])
|
||||
WorkoutTracking.distance = WatchKitConnection.distance
|
||||
WorkoutTracking.kcal = WatchKitConnection.kcal
|
||||
|
||||
self.distanceLabel.setText("Distance \(Double(WorkoutTracking.distance))")
|
||||
WorkoutTracking.speed = WatchKitConnection.speed
|
||||
WorkoutTracking.power = WatchKitConnection.power
|
||||
WorkoutTracking.cadence = WatchKitConnection.cadence
|
||||
|
||||
if Locale.current.measurementSystem != "Metric" {
|
||||
self.distanceLabel.setText("Distance \(String(format:"%.2f", WorkoutTracking.distance))")
|
||||
} else {
|
||||
self.distanceLabel.setText("Distance \(String(format:"%.2f", WorkoutTracking.distance * 1.60934))")
|
||||
}
|
||||
self.caloriesLabel.setText("KCal \(Int(WorkoutTracking.kcal))")
|
||||
//WorkoutTracking.cadenceSteps = pedometer.
|
||||
}
|
||||
@@ -105,3 +130,11 @@ extension MainController: WatchKitConnectionDelegate {
|
||||
userNameLabel.setText(userName)
|
||||
}
|
||||
}
|
||||
|
||||
extension Locale
|
||||
{
|
||||
var measurementSystem : String?
|
||||
{
|
||||
return (self as NSLocale).object(forKey: NSLocale.Key.measurementSystem) as? String
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPITypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>NSPrivacyAccessedAPIType</key>
|
||||
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
|
||||
<key>NSPrivacyAccessedAPITypeReasons</key>
|
||||
<array>
|
||||
<string>CA92.1</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -24,6 +24,9 @@ class WatchKitConnection: NSObject {
|
||||
public static var distance = 0.0
|
||||
public static var kcal = 0.0
|
||||
public static var stepCadence = 0
|
||||
public static var speed = 0.0
|
||||
public static var cadence = 0.0
|
||||
public static var power = 0.0
|
||||
weak var delegate: WatchKitConnectionDelegate?
|
||||
|
||||
private override init() {
|
||||
@@ -66,6 +69,13 @@ extension WatchKitConnection: WatchKitConnectionProtocol {
|
||||
WatchKitConnection.distance = dDistance
|
||||
let dKcal = Double(result["kcal"] as! Double)
|
||||
WatchKitConnection.kcal = dKcal
|
||||
|
||||
let dSpeed = Double(result["speed"] as! Double)
|
||||
WatchKitConnection.speed = dSpeed
|
||||
let dPower = Double(result["power"] as! Double)
|
||||
WatchKitConnection.power = dPower
|
||||
let dCadence = Double(result["cadence"] as! Double)
|
||||
WatchKitConnection.cadence = dCadence
|
||||
}, errorHandler: { (error) in
|
||||
print(error)
|
||||
})
|
||||
|
||||
@@ -31,6 +31,11 @@ class WorkoutTracking: NSObject {
|
||||
public static var cadenceTimeStamp = NSDate().timeIntervalSince1970
|
||||
public static var cadenceLastSteps = Double()
|
||||
public static var cadenceSteps = 0
|
||||
public static var speed = Double()
|
||||
public static var power = Double()
|
||||
public static var cadence = Double()
|
||||
public static var lastDateMetric = Date()
|
||||
var sport: Int = 0
|
||||
let healthStore = HKHealthStore()
|
||||
let configuration = HKWorkoutConfiguration()
|
||||
var workoutSession: HKWorkoutSession!
|
||||
@@ -101,8 +106,23 @@ extension WorkoutTracking {
|
||||
}
|
||||
}
|
||||
|
||||
func setSport(_ sport: Int) {
|
||||
self.sport = sport
|
||||
}
|
||||
|
||||
private func configWorkout() {
|
||||
configuration.activityType = .cycling
|
||||
var activityType = HKWorkoutActivityType.cycling
|
||||
if self.sport == 1 {
|
||||
activityType = HKWorkoutActivityType.running
|
||||
} else if self.sport == 2 {
|
||||
activityType = HKWorkoutActivityType.walking
|
||||
} else if self.sport == 3 {
|
||||
activityType = HKWorkoutActivityType.elliptical
|
||||
} else if self.sport == 4 {
|
||||
activityType = HKWorkoutActivityType.rowing
|
||||
}
|
||||
|
||||
configuration.activityType = activityType
|
||||
configuration.locationType = .indoor
|
||||
|
||||
do {
|
||||
@@ -130,13 +150,37 @@ extension WorkoutTracking: WorkoutTrackingProtocol {
|
||||
HKSampleType.workoutType()
|
||||
])
|
||||
|
||||
let infoToShare = Set([
|
||||
HKSampleType.quantityType(forIdentifier: .stepCount)!,
|
||||
HKSampleType.quantityType(forIdentifier: .heartRate)!,
|
||||
HKSampleType.quantityType(forIdentifier: .distanceCycling)!,
|
||||
HKSampleType.quantityType(forIdentifier: .activeEnergyBurned)!,
|
||||
HKSampleType.workoutType()
|
||||
])
|
||||
var infoToShare: Set<HKSampleType> = []
|
||||
|
||||
if #available(watchOSApplicationExtension 10.0, *) {
|
||||
infoToShare = Set([
|
||||
HKSampleType.quantityType(forIdentifier: .stepCount)!,
|
||||
HKSampleType.quantityType(forIdentifier: .heartRate)!,
|
||||
HKSampleType.quantityType(forIdentifier: .distanceCycling)!,
|
||||
HKSampleType.quantityType(forIdentifier: .distanceWalkingRunning)!,
|
||||
HKSampleType.quantityType(forIdentifier: .activeEnergyBurned)!,
|
||||
HKSampleType.quantityType(forIdentifier: .cyclingPower)!,
|
||||
HKSampleType.quantityType(forIdentifier: .cyclingSpeed)!,
|
||||
HKSampleType.quantityType(forIdentifier: .cyclingCadence)!,
|
||||
HKSampleType.quantityType(forIdentifier: .runningPower)!,
|
||||
HKSampleType.quantityType(forIdentifier: .runningSpeed)!,
|
||||
HKSampleType.quantityType(forIdentifier: .runningStrideLength)!,
|
||||
HKSampleType.quantityType(forIdentifier: .runningVerticalOscillation)!,
|
||||
HKSampleType.quantityType(forIdentifier: .walkingSpeed)!,
|
||||
HKSampleType.quantityType(forIdentifier: .walkingStepLength)!,
|
||||
HKSampleType.workoutType()
|
||||
])
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
infoToShare = Set([
|
||||
HKSampleType.quantityType(forIdentifier: .stepCount)!,
|
||||
HKSampleType.quantityType(forIdentifier: .heartRate)!,
|
||||
HKSampleType.quantityType(forIdentifier: .distanceCycling)!,
|
||||
HKSampleType.quantityType(forIdentifier: .distanceWalkingRunning)!,
|
||||
HKSampleType.quantityType(forIdentifier: .activeEnergyBurned)!,
|
||||
HKSampleType.workoutType()
|
||||
])
|
||||
}
|
||||
|
||||
HKHealthStore().requestAuthorization(toShare: infoToShare, read: infoToRead) { (success, error) in
|
||||
if success {
|
||||
@@ -151,6 +195,7 @@ extension WorkoutTracking: WorkoutTrackingProtocol {
|
||||
}
|
||||
|
||||
func startWorkOut() {
|
||||
WorkoutTracking.lastDateMetric = Date()
|
||||
print("Start workout")
|
||||
configWorkout()
|
||||
workoutSession.startActivity(with: Date())
|
||||
@@ -159,6 +204,10 @@ extension WorkoutTracking: WorkoutTrackingProtocol {
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
|
||||
if self.sport > 0 {
|
||||
self.workoutBuilder.dataSource?.enableCollection(for: HKQuantityType.quantityType(forIdentifier: .distanceWalkingRunning)!, predicate: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,29 +232,72 @@ extension WorkoutTracking: WorkoutTrackingProtocol {
|
||||
end: Date())
|
||||
|
||||
workoutBuilder.add([sample]) {(success, error) in}
|
||||
|
||||
guard let quantityTypeDistance = HKQuantityType.quantityType(
|
||||
forIdentifier: .distanceCycling) else {
|
||||
return
|
||||
}
|
||||
|
||||
let unitDistance = HKUnit.mile()
|
||||
let miles = WorkoutTracking.distance
|
||||
let quantityMiles = HKQuantity(unit: unitDistance,
|
||||
doubleValue: miles)
|
||||
|
||||
let sampleDistance = HKCumulativeQuantitySeriesSample(type: quantityTypeDistance,
|
||||
quantity: quantityMiles,
|
||||
start: workoutSession.startDate!,
|
||||
end: Date())
|
||||
|
||||
workoutBuilder.add([sample]) {(success, error) in}
|
||||
workoutBuilder.add([sampleDistance]) {(success, error) in}
|
||||
|
||||
workoutBuilder.endCollection(withEnd: Date()) { (success, error) in
|
||||
if(sport == 0) {
|
||||
|
||||
guard let quantityTypeDistance = HKQuantityType.quantityType(
|
||||
forIdentifier: .distanceCycling) else {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
let sampleDistance = HKCumulativeQuantitySeriesSample(type: quantityTypeDistance,
|
||||
quantity: quantityMiles,
|
||||
start: workoutSession.startDate!,
|
||||
end: Date())
|
||||
|
||||
workoutBuilder.add([sampleDistance]) {(success, error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
self.workoutBuilder.endCollection(withEnd: Date()) { (success, error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
self.workoutBuilder.finishWorkout{ (workout, error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
workout?.setValue(quantityMiles, forKey: "totalDistance")
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
guard let quantityTypeDistance = HKQuantityType.quantityType(
|
||||
forIdentifier: .distanceWalkingRunning) else {
|
||||
return
|
||||
}
|
||||
|
||||
let sampleDistance = HKCumulativeQuantitySeriesSample(type: quantityTypeDistance,
|
||||
quantity: quantityMiles,
|
||||
start: workoutSession.startDate!,
|
||||
end: Date())
|
||||
|
||||
workoutBuilder.add([sampleDistance]) {(success, error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
self.workoutBuilder.endCollection(withEnd: Date()) { (success, error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
self.workoutBuilder.finishWorkout{ (workout, error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
workout?.setValue(quantityMiles, forKey: "totalDistance")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
workoutBuilder.finishWorkout{ (success, error) in }
|
||||
|
||||
|
||||
}
|
||||
|
||||
func fetchStepCounts() {
|
||||
@@ -248,6 +340,135 @@ extension WorkoutTracking: HKLiveWorkoutBuilderDelegate {
|
||||
handleSendStatisticsData(statistics)
|
||||
}
|
||||
}
|
||||
|
||||
if(sport == 0) {
|
||||
if #available(watchOSApplicationExtension 10.0, *) {
|
||||
let wattPerInterval = HKQuantity(unit: HKUnit.watt(),
|
||||
doubleValue: WorkoutTracking.power)
|
||||
|
||||
if(WorkoutTracking.lastDateMetric.distance(to: Date()) < 1) {
|
||||
return
|
||||
}
|
||||
|
||||
guard let powerType = HKQuantityType.quantityType(
|
||||
forIdentifier: .cyclingPower) else {
|
||||
return
|
||||
}
|
||||
let wattPerIntervalSample = HKQuantitySample(type: powerType,
|
||||
quantity: wattPerInterval,
|
||||
start: WorkoutTracking.lastDateMetric,
|
||||
end: Date())
|
||||
workoutBuilder.add([wattPerIntervalSample]) {(success, error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
let cadencePerInterval = HKQuantity(unit: HKUnit.count().unitDivided(by: HKUnit.second()),
|
||||
doubleValue: WorkoutTracking.cadence / 60.0)
|
||||
|
||||
guard let cadenceType = HKQuantityType.quantityType(
|
||||
forIdentifier: .cyclingCadence) else {
|
||||
return
|
||||
}
|
||||
let cadencePerIntervalSample = HKQuantitySample(type: cadenceType,
|
||||
quantity: cadencePerInterval,
|
||||
start: WorkoutTracking.lastDateMetric,
|
||||
end: Date())
|
||||
workoutBuilder.add([cadencePerIntervalSample]) {(success, error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
let speedPerInterval = HKQuantity(unit: HKUnit.meter().unitDivided(by: HKUnit.second()),
|
||||
doubleValue: WorkoutTracking.speed * 0.277778)
|
||||
|
||||
guard let speedType = HKQuantityType.quantityType(
|
||||
forIdentifier: .cyclingSpeed) else {
|
||||
return
|
||||
}
|
||||
let speedPerIntervalSample = HKQuantitySample(type: speedType,
|
||||
quantity: speedPerInterval,
|
||||
start: WorkoutTracking.lastDateMetric,
|
||||
end: Date())
|
||||
workoutBuilder.add([speedPerIntervalSample]) {(success, error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
}
|
||||
} else if(sport == 1) {
|
||||
if #available(watchOSApplicationExtension 10.0, *) {
|
||||
let wattPerInterval = HKQuantity(unit: HKUnit.watt(),
|
||||
doubleValue: WorkoutTracking.power)
|
||||
|
||||
if(WorkoutTracking.lastDateMetric.distance(to: Date()) < 1) {
|
||||
return
|
||||
}
|
||||
|
||||
guard let powerType = HKQuantityType.quantityType(
|
||||
forIdentifier: .runningPower) else {
|
||||
return
|
||||
}
|
||||
let wattPerIntervalSample = HKQuantitySample(type: powerType,
|
||||
quantity: wattPerInterval,
|
||||
start: WorkoutTracking.lastDateMetric,
|
||||
end: Date())
|
||||
workoutBuilder.add([wattPerIntervalSample]) {(success, error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
let speedPerInterval = HKQuantity(unit: HKUnit.meter().unitDivided(by: HKUnit.second()),
|
||||
doubleValue: WorkoutTracking.speed * 0.277778)
|
||||
|
||||
guard let speedType = HKQuantityType.quantityType(
|
||||
forIdentifier: .runningSpeed) else {
|
||||
return
|
||||
}
|
||||
let speedPerIntervalSample = HKQuantitySample(type: speedType,
|
||||
quantity: speedPerInterval,
|
||||
start: WorkoutTracking.lastDateMetric,
|
||||
end: Date())
|
||||
workoutBuilder.add([speedPerIntervalSample]) {(success, error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
}
|
||||
} else if(sport == 2) {
|
||||
if #available(watchOSApplicationExtension 10.0, *) {
|
||||
let speedPerInterval = HKQuantity(unit: HKUnit.meter().unitDivided(by: HKUnit.second()),
|
||||
doubleValue: WorkoutTracking.speed * 0.277778)
|
||||
|
||||
guard let speedType = HKQuantityType.quantityType(
|
||||
forIdentifier: .walkingSpeed) else {
|
||||
return
|
||||
}
|
||||
let speedPerIntervalSample = HKQuantitySample(type: speedType,
|
||||
quantity: speedPerInterval,
|
||||
start: WorkoutTracking.lastDateMetric,
|
||||
end: Date())
|
||||
workoutBuilder.add([speedPerIntervalSample]) {(success, error) in
|
||||
if let error = error {
|
||||
print(error)
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Fallback on earlier versions
|
||||
}
|
||||
}
|
||||
|
||||
WorkoutTracking.lastDateMetric = Date()
|
||||
}
|
||||
|
||||
func workoutBuilderDidCollectEvent(_ workoutBuilder: HKLiveWorkoutBuilder) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="19529" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Tpn-rd-UUX">
|
||||
<document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="20037" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="Tpn-rd-UUX">
|
||||
<device id="watch38"/>
|
||||
<dependencies>
|
||||
<deployment identifier="watchOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="19514"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBWatchKitPlugin" version="20006"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--Main-->
|
||||
@@ -22,9 +22,15 @@
|
||||
<label width="136" alignment="left" text="Step Counts" id="HpA-e9-6YV"/>
|
||||
<label width="136" alignment="left" text="Calories" id="Szi-Jp-J3S"/>
|
||||
<label width="136" alignment="left" text="Distance" id="eRf-NJ-6If"/>
|
||||
<picker height="100" alignment="left" id="OTR-HF-vYb">
|
||||
<connections>
|
||||
<action selector="changeSport:" destination="Tpn-rd-UUX" id="3vY-lq-IhZ"/>
|
||||
</connections>
|
||||
</picker>
|
||||
</items>
|
||||
<connections>
|
||||
<outlet property="caloriesLabel" destination="Szi-Jp-J3S" id="trd-YS-bJy"/>
|
||||
<outlet property="cmbSports" destination="OTR-HF-vYb" id="Ws5-w9-ZT8"/>
|
||||
<outlet property="distanceLabel" destination="eRf-NJ-6If" id="ZE2-OB-jqN"/>
|
||||
<outlet property="heartRateLabel" destination="Nda-m1-XRw" id="1la-8R-3jG"/>
|
||||
<outlet property="startButton" destination="vZg-X8-uY5" id="pJc-09-kfV"/>
|
||||
|
||||
15
defaults.pri
Normal file
15
defaults.pri
Normal file
@@ -0,0 +1,15 @@
|
||||
QT += gui bluetooth widgets xml positioning quick networkauth websockets texttospeech location multimedia
|
||||
QTPLUGIN += qavfmediaplayer
|
||||
QT+= charts
|
||||
|
||||
unix:android: QT += androidextras gui-private
|
||||
|
||||
android: include(android_openssl/openssl.pri)
|
||||
|
||||
INCLUDEPATH += $$PWD/src/qmdnsengine/src/include
|
||||
|
||||
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/src/android
|
||||
|
||||
ANDROID_ABIS = armeabi-v7a arm64-v8a x86 x86_64
|
||||
|
||||
#QMAKE_CXXFLAGS += -Werror=suggest-override
|
||||
@@ -4,17 +4,20 @@ QDomyos-Zwift can be installed from source on MacOs, Linux, Android and IOS.
|
||||
|
||||
Once you've installed QDomyos-Zwift, you can access the [operation guide](30_usage.md) for more information.
|
||||
|
||||
These instructions build the app itself, not the test project.
|
||||
|
||||
## On a Linux System (from source)
|
||||
|
||||
```buildoutcfg
|
||||
$ sudo apt update && sudo apt upgrade # this is very important on raspberry pi: you need the bluetooth firmware updated!
|
||||
$ sudo apt install git qtquickcontrols2-5-dev libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 qtconnectivity5-dev qtpositioning5-dev libqt5charts5-dev libqt5charts5 qt5-assistant libqt5networkauth5-dev libqt5websockets5-dev qml-module* libqt5texttospeech5-dev libqt5texttospeech5 libqt5location5-plugins qtlocation5-dev qtmultimedia5-dev libqt5multimediawidgets5 libqt5multimedia5-plugins libqt5multimedia5
|
||||
$ sudo apt install git qtquickcontrols2-5-dev libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 qtconnectivity5-dev qtpositioning5-dev libqt5charts5-dev libqt5charts5 qt5-assistant libqt5networkauth5-dev libqt5websockets5-dev qml-module* libqt5texttospeech5-dev libqt5texttospeech5 libqt5location5-plugins qtlocation5-dev qtmultimedia5-dev libqt5multimediawidgets5 libqt5multimedia5-plugins libqt5multimedia5 g++ make
|
||||
$ git clone https://github.com/cagnulein/qdomyos-zwift.git
|
||||
$ cd qdomyos-zwift
|
||||
$ git submodule update --init src/smtpclient/
|
||||
$ git submodule update --init src/qmdnsengine/
|
||||
$ git submodule update --init tst/googletest/
|
||||
$ cd src
|
||||
$ qmake
|
||||
$ qmake qdomyos-zwift.pro
|
||||
$ make -j4
|
||||
$ sudo ./qdomyos-zwift
|
||||
```
|
||||
@@ -25,13 +28,13 @@ $ sudo ./qdomyos-zwift
|
||||
You will need to (at a minimum) to install the xcode Command Line Tools (CLI) thanks to @richardwait
|
||||
https://developer.apple.com/download/more/?=xcode
|
||||
|
||||
Download and install http://download.qt.io/official_releases/qt/5.12/5.12.9/qt-opensource-mac-x64-5.12.9.dmg and simply run the qdomyos-zwift relase for MacOs
|
||||
Download and install https://download.qt.io/archive/qt/5.12/5.12.12/qt-opensource-mac-x64-5.12.12.dmg and simply run the qdomyos-zwift release for MacOs
|
||||
|
||||
## On Raspberry Pi Zero W
|
||||
|
||||

|
||||
|
||||
This guide will walk you through steps to setup an autonomous, headless raspberry brigde.
|
||||
This guide will walk you through steps to setup an autonomous, headless raspberry bridge.
|
||||
|
||||
|
||||
### Initial System Preparation
|
||||
@@ -74,7 +77,7 @@ Apply the changes `sudo systemctl restart dhcpcd.service` and ensure you have in
|
||||
|
||||
#### Enable SSH access
|
||||
|
||||
You might want to access your raspberry remotely while it is attached to your fitness equipement.
|
||||
You might want to access your raspberry remotely while it is attached to your fitness equipment.
|
||||
|
||||
`sudo raspi-config` > `Interface Options` > `SSH`
|
||||
|
||||
@@ -102,15 +105,17 @@ This operation takes a moment to complete.
|
||||
|
||||
#### Install qdomyos-zwift from sources
|
||||
|
||||
`sudo apt install git libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 qtconnectivity5-dev qtpositioning5-dev libqt5charts5-dev libqt5charts5 qt5-assistant libqt5networkauth5-dev libqt5websockets5-dev qtmultimedia5-dev libqt5multimediawidgets5 libqt5multimedia5-plugins libqt5multimedia5 qtlocation5-dev qtquickcontrols2-5-dev libqt5texttospeech5-dev libqt5texttospeech5`
|
||||
|
||||
`git clone https://github.com/cagnulein/qdomyos-zwift.git`
|
||||
`cd qdomyos-zwift`
|
||||
`git submodule update --init src/smtpclient/`
|
||||
`git submodule update --init src/qmdnsengine/`
|
||||
`cd src`
|
||||
`qmake`
|
||||
`make`
|
||||
```bash
|
||||
sudo apt install git libqt5bluetooth5 libqt5widgets5 libqt5positioning5 libqt5xml5 qtconnectivity5-dev qtpositioning5-dev libqt5charts5-dev libqt5charts5 qt5-assistant libqt5networkauth5-dev libqt5websockets5-dev qtmultimedia5-dev libqt5multimediawidgets5 libqt5multimedia5-plugins libqt5multimedia5 qtlocation5-dev qtquickcontrols2-5-dev libqt5texttospeech5-dev libqt5texttospeech5 g++ make
|
||||
git clone https://github.com/cagnulein/qdomyos-zwift.git
|
||||
cd qdomyos-zwift
|
||||
git submodule update --init src/smtpclient/
|
||||
git submodule update --init src/qmdnsengine/
|
||||
git submodule update --init tst/googletest/
|
||||
cd src
|
||||
qmake qdomyos-zwift.pro
|
||||
make
|
||||
```
|
||||
|
||||
Please note :
|
||||
- Don't build the application with `-j4` option (this will fail)
|
||||
@@ -170,7 +175,7 @@ Then reboot to check operations (`sudo reboot`)
|
||||
|
||||
### (optional) Enable overlay FS
|
||||
|
||||
Once that everything is working as expected, and if you dedicate your raspeberry pi to this usage, you might want to enable the read-only overlay FS.
|
||||
Once that everything is working as expected, and if you dedicate your Raspberry pi to this usage, you might want to enable the read-only overlay FS.
|
||||
|
||||
By enabling the overlay read-only system, your SD card will be read-only only and every file written will be to RAM.
|
||||
Then at each reboot the RAM is erased and you'll revert to the initial status of the overlay file-system.
|
||||
|
||||
@@ -36,7 +36,7 @@ An android device is required for this operation.
|
||||
8. Disable the option Enable Bluetooth HCI snoop log
|
||||
9. in Developer Options: Bug report->Full report
|
||||
10. wait a random amount of time (10-20 seconds)
|
||||
11. A notification will appear at the top of the device. Click on it, share, email it to yourself
|
||||
11. A notification will appear at the top of the device. Click on it, share, email it to yourself. If it doesn't appear you need to use ADB to pull the file from the phone itself
|
||||
12. You'll get a zip file with the entire report. In the FS/Data/Log/bt directory of the zipfile is the file you want.
|
||||
13. attach the log file in a new issue with a short description of the steps you did in the app when you used it
|
||||
|
||||
|
||||
@@ -26,5 +26,5 @@ You can have ae true 4k video stream while you ride ("extreme quality" setting)
|
||||
The application do not read the FTMS value. It is required to start the application with `-heart-service` or `bike_heartrate_service: true` in settings.
|
||||
|
||||
### Resistance management
|
||||
You can adjust resistence using arrows [up and down](img/21_zwift-resistance-buttons.jpg) rom the riding screen.
|
||||
You can adjust resistance using arrows [up and down](img/21_zwift-resistance-buttons.jpg) rom the riding screen.
|
||||
|
||||
|
||||
@@ -18,14 +18,15 @@ Please refer to this article for more information under [QML Operations](https:/
|
||||
|
||||
## Configuration in NativeQT mode
|
||||
|
||||
This is the list of settings available in the application. These settings needs to be appended to the binary command line.
|
||||
This is the list of settings available in the application. These settings need to be appended to the binary command line.
|
||||
*Example :* `sudo ./qdomyos-zwift -no-gui` for disabling any graphical interface.
|
||||
|
||||
| **Option** | **Type** | **Default** | **Function** |
|
||||
|:------------------------------|:---------|:------------|:-----------------------------------------------------------------------------|
|
||||
| -no-gui | Boolean | False | Disable GUI |
|
||||
| -qml | Boolean | False | Enables the QML interface |
|
||||
| -miles | Boolean | False | Swithes to Imperial Units System |
|
||||
| -qml | Boolean | True | Enables the QML interface |
|
||||
| -noqml | Boolean | False | Enables the NativeQT interface |
|
||||
| -miles | Boolean | False | Switches to Imperial Units System |
|
||||
| -no-console | Boolean | False | Not in use |
|
||||
| -test-resistance | Boolean | False | |
|
||||
| -no-log | Boolean | False | Disable Logging |
|
||||
@@ -34,18 +35,18 @@ This is the list of settings available in the application. These settings needs
|
||||
| -heart-service | Boolean | True | Simulate HR service (required for applications not reading FTMS) |
|
||||
| -only-virtualbike | Boolean | False | |
|
||||
| -only-virtualtreadmill | Boolean | False | |
|
||||
| -no-reconnection | Boolean | False | QZ will not try to reconnect your fitness equipement if enabled |
|
||||
| -bluetooth-relaxed | Boolean | False | In case of deconnections from QZ to your fitness equipement |
|
||||
| -no-reconnection | Boolean | False | QZ will not try to reconnect your fitness equipment if enabled |
|
||||
| -bluetooth-relaxed | Boolean | False | In case of deconnections from QZ to your fitness equipment |
|
||||
| -bike-cadence-sensor | Boolean | False | |
|
||||
| -bike-power-sensor | Boolean | False | |
|
||||
| -battery-service | Boolean | False | |
|
||||
| -service-changed | Boolean | False | |
|
||||
| -bike-wheel-revs | Boolean | False | |
|
||||
| -run-cadence-sensor | Boolean | False | |
|
||||
| -nordictrack-10-treadmill | Boolean | False | Enable NordicTrack compatibility mode |
|
||||
| -nordictrack-10-treadmill | Boolean | False | Enable NordicTrack compatibility mode |
|
||||
| -train | String | | Force training program |
|
||||
| -name | String | | Force bluetooth device name (if QZ struggles finding your fitness equipment) |
|
||||
| -poll-device-time | Int | 200 (ms) | Frequency to refresh informations from QZ to Fitness equipment |
|
||||
| -name | String | | Force bluetooth device name (if QZ struggles to find your fitness equipment) |
|
||||
| -poll-device-time | Int | 200 (ms) | Frequency to refresh information from QZ to Fitness equipment |
|
||||
| -bike-resistance-gain | Int | | Adjust resistance from the fitness application |
|
||||
| -bike-resistance-offset | Int | | Set another resistance point than default |
|
||||
|
||||
|
||||
505
docs/50_writing_tests.md
Normal file
505
docs/50_writing_tests.md
Normal file
@@ -0,0 +1,505 @@
|
||||
# QDomyos-Zwift Guide to Writing Unit Tests
|
||||
|
||||
## About
|
||||
|
||||
The testing project tst/qdomyos-zwift-tests.pro contains test code that uses the Google Test library.
|
||||
|
||||
## Adding a new device
|
||||
|
||||
New devices are added to the main QZ application by creating or modifying a subclass of the bluetoothdevice class.
|
||||
|
||||
At minimum, each device has a corresponding BluetoothDeviceTestData subclass in the test project, which is coded to provide information to the test framework to generate tests for device detection and potentially other things.
|
||||
|
||||
In the test project
|
||||
* create a new folder for the device under tst/Devices. This is for anything you define for testing this device.
|
||||
* add a new class with header file and optionally .cpp file to the project in that folder. Name the class DeviceNameTestData, substituting an appropriate name in place of "DeviceName".
|
||||
* edit the header file to inherit the class from the BluetoothDeviceTestData abstract subclass appropriate to the device type, i.e. BikeTestData, RowerTestData, EllipticalTestData, TreadmillTestData.
|
||||
* have this new subclass' constructor pass a unique test name to its superclass.
|
||||
|
||||
The tests are not organised around real devices that are handled, but the bluetoothdevice subclass that handles them - the "driver" of sorts.
|
||||
|
||||
You need to provide the following:
|
||||
- patterns for valid names (e.g. equals a value, starts with a value, case sensitivity, specific length)
|
||||
- invalid names to ensure the device is not identified when the name is invalid
|
||||
- configuration settings that are required for the device to be detected
|
||||
- invalid configurations to test that the device is not detected, e.g. when it's disabled in the settings, but the name is correct
|
||||
- exclusion devices: if a device with the same name but of a higher priority type is detected, this device should not be detected
|
||||
- valid and invalid QBluetoothDeviceInfo configurations, e.g. to check the device is only detected when the manufacturer data is set correctly, or certain services are available or not.
|
||||
|
||||
## Tools in the Test Framework
|
||||
|
||||
### TestSettings
|
||||
|
||||
The detection of many devices depends on settings that are accessed programmatically using the QSettings class and the constants in the QZSettings namespace. The TestSettings class stores a QSettings object with what is intended to be a unique application and organisation name, to keep the configuration it represents seperate from others in the system. It also makes the stored QSettings object the default by setting the QCoreApplication's organisation and application names to those of the QSettings object. The original values are restored by calling the deactivate() function or on object destruction.
|
||||
|
||||
i.e. a test will
|
||||
* apply a configuration from a TestSettings object
|
||||
* perform device detection
|
||||
* use the TestSettings object to restore the previous settings either directly or by letting its destructor be called.
|
||||
|
||||
### DeviceDiscoveryInfo
|
||||
|
||||
This class contains a set of fields that store strongly typed QSettings values.
|
||||
It also provides methods to read and write the values it knows about from and to a QSettings object.
|
||||
|
||||
It is used in conjunction with a TestSettings object to write a configuration during a test.
|
||||
|
||||
|
||||
## Writing a device detection test
|
||||
|
||||
Because of the way the TestData classes currently work, it may be necessary to define multiple test data classes to cover the various cases.
|
||||
For example, if any of a list of names is enough to identify a device, or another group of names but with a certain service in the bluetooth device info, that will require multiple classes.
|
||||
|
||||
### Recognition by Name
|
||||
|
||||
Consider the detection code for the Domyos Bike:
|
||||
|
||||
```
|
||||
} else if (b.name().startsWith(QStringLiteral("Domyos-Bike")) &&
|
||||
!b.name().startsWith(QStringLiteral("DomyosBridge")) && !domyosBike && filter) {
|
||||
|
||||
```
|
||||
|
||||
Reading this, to identify this device:
|
||||
- bluetooth name should start with "Domyos-Bike" using a case sensitive comparison
|
||||
- bluetooth name should NOT start with "DomyosBridge", also using a case sensitive comparison
|
||||
- there should not have been a device using the corresponding device class detected already (i.e. domyos)
|
||||
- filter has not been activated (this isn't tested)
|
||||
|
||||
In this case, we are not testing the last two, but can test the first two.
|
||||
|
||||
|
||||
```
|
||||
#pragma once
|
||||
|
||||
#include "Devices/Bike/biketestdata.h"
|
||||
#include "devices/domyosbike/domyosbike.h"
|
||||
|
||||
class DomyosBikeTestData : public BikeTestData {
|
||||
|
||||
public:
|
||||
DomyosBikeTestData() : BikeTestData("Domyos Bike") {
|
||||
|
||||
this->addDeviceName("Domyos-Bike", comparison::StartsWith);
|
||||
this->addInvalidDeviceName("DomyosBridge", comparison::StartsWith);
|
||||
}
|
||||
|
||||
// not used yet
|
||||
deviceType get_expectedDeviceType() const override { return deviceType::DomyosBike; }
|
||||
|
||||
bool get_isExpectedDevice(bluetoothdevice * detectedDevice) const override {
|
||||
return dynamic_cast<domyosbike*>(detectedDevice)!=nullptr;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
The constructor adds a valid device name, and an invalid one. Various overloads of these methods and other members of the comparison enumeration provide other capabilities for specifying test data. If you add a valid device name that says the name should start with a value, additional names will be added automatically to the valid list with additional characters to test that it is in fact a "starts with" relationship. Also, valid and invalid names will be generated base on whether the comparison is case sensitive or not.
|
||||
|
||||
The get_expectedDeviceType() function is not actually used and is part of an unfinished refactoring of the device detection code, whereby the bluetoothdevice object doesn't actually get created intially. You could add a new value to the deviceType enum and return that, but it's not used yet. There's always deviceType::None.
|
||||
|
||||
The get_isExpectedDevice(bluetoothdevice *) function must be overridden to indicate if the specified object is of the type expected for this test data.
|
||||
|
||||
### Configuration Settings
|
||||
|
||||
Consider the CompuTrainerTestData. This device is not detected by name, but only by whether or not it is enabled in the settings.
|
||||
To specify this in the test data, we override one of the configureSettings methods, the one for the simple case where there is a single valid and a single invalid configuration.
|
||||
|
||||
Settings from QSettings that contribute to tests should be put into the DeviceDiscoveryInfo class.
|
||||
|
||||
For example, for the Computrainer Bike, the "computrainer_serial_port" value from the QSettings determines if the bike should be detected or not.
|
||||
|
||||
```
|
||||
class DeviceDiscoveryInfo {
|
||||
public :
|
||||
...
|
||||
QString computrainer_serial_port = nullptr;
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
The getValues and setValues methods should be updated to include the addition(s):
|
||||
|
||||
```
|
||||
|
||||
void DeviceDiscoveryInfo::setValues(QSettings &settings, bool clear) const {
|
||||
if(clear) settings.clear();
|
||||
...
|
||||
settings.setValue(QZSettings::computrainer_serialport, this->computrainer_serial_port);
|
||||
...
|
||||
}
|
||||
|
||||
void DeviceDiscoveryInfo::getValues(QSettings &settings){
|
||||
...
|
||||
this->computrainer_serial_port = settings.value(QZSettings::computrainer_serialport, QZSettings::default_computrainer_serialport).toString();
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
In the following example, the DeviceDiscoveryInfo class has been updated to contain the device's configuration setting (computrainer_serial_port).
|
||||
- if an enabling configuration is requested (enable==true) a string that is known to be accepted is supplied
|
||||
- if a disabling configuration is requested (enable==false) an empty string is supplied.
|
||||
|
||||
This example uses the simpler of 2 configureSettings methods returns true/false to indicate if the configuration should be used for the test.
|
||||
|
||||
```
|
||||
#pragma once
|
||||
|
||||
#include "Devices/Bike/biketestdata.h"
|
||||
#include "devices/computrainerbike/computrainerbike.h"
|
||||
|
||||
class CompuTrainerTestData : public BikeTestData {
|
||||
protected:
|
||||
bool configureSettings(DeviceDiscoveryInfo& info, bool enable) const override {
|
||||
info.computrainer_serial_port = enable ? "X":QString();
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
CompuTrainerTestData() : BikeTestData("CompuTrainer Bike") {
|
||||
// any name
|
||||
this->addDeviceName("", comparison::StartsWithIgnoreCase);
|
||||
}
|
||||
|
||||
deviceType get_expectedDeviceType() const override { return deviceType::CompuTrainerBike; }
|
||||
|
||||
bool get_isExpectedDevice(bluetoothdevice * detectedDevice) const override {
|
||||
return dynamic_cast<computrainerbike*>(detectedDevice)!=nullptr;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
Similarly, the Pafers Bike has a simple configuration setting:
|
||||
|
||||
```
|
||||
#include "Devices/Bike/biketestdata.h"
|
||||
#include "devices/pafersbike/pafersbike.h"
|
||||
|
||||
|
||||
class PafersBikeTestData : public BikeTestData {
|
||||
protected:
|
||||
bool configureSettings(DeviceDiscoveryInfo& info, bool enable) const override {
|
||||
// the treadmill is given priority
|
||||
info.pafers_treadmill = !enable;
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
PafersBikeTestData() : BikeTestData("Pafers Bike") {
|
||||
this->addDeviceName("PAFERS_", comparison::StartsWithIgnoreCase);
|
||||
}
|
||||
|
||||
deviceType get_expectedDeviceType() const override { return deviceType::PafersBike; }
|
||||
|
||||
bool get_isExpectedDevice(bluetoothdevice * detectedDevice) const override {
|
||||
return dynamic_cast<pafersbike*>(detectedDevice)!=nullptr;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
A more complicated example is the Pafers Treadmill. It involves a name match, but also some configuration settings obtained earlier...
|
||||
|
||||
```
|
||||
bool pafers_treadmill = settings.value(QZSettings::pafers_treadmill, QZSettings::default_pafers_treadmill).toBool();
|
||||
...
|
||||
|
||||
bool pafers_treadmill_bh_iboxster_plus =
|
||||
settings
|
||||
.value(QZSettings::pafers_treadmill_bh_iboxster_plus, QZSettings::default_pafers_treadmill_bh_iboxster_plus)
|
||||
.toBool();
|
||||
...
|
||||
|
||||
} else if (b.name().toUpper().startsWith(QStringLiteral("PAFERS_")) && !pafersTreadmill &&
|
||||
(pafers_treadmill || pafers_treadmill_bh_iboxster_plus) && filter) {
|
||||
```
|
||||
|
||||
Here the device could be activated due to a name match and various combinations of settings.
|
||||
For this, the configureSettings function that takes a vector of DeviceDiscoveryInfo objects which is populated with configurations that lead to the specified result (enable = detected, !enable=not detected). Instead of returning a boolean to indicate if a configuration has been supplied, it populates a vector of DeviceDiscoveryInfo objects.
|
||||
|
||||
```
|
||||
#pragma once
|
||||
|
||||
#include "Devices/Treadmill/treadmilltestdata.h"
|
||||
#include "devices/paferstreadmill/paferstreadmill.h"
|
||||
|
||||
class PafersTreadmillTestData : public TreadmillTestData {
|
||||
protected:
|
||||
void configureSettings(const DeviceDiscoveryInfo& info, bool enable, std::vector<DeviceDiscoveryInfo>& configurations) const override {
|
||||
DeviceDiscoveryInfo config(info);
|
||||
|
||||
if (enable) {
|
||||
for(int x = 1; x<=3; x++) {
|
||||
config.pafers_treadmill = x & 1;
|
||||
config.pafers_treadmill_bh_iboxster_plus = x & 2;
|
||||
configurations.push_back(config);
|
||||
}
|
||||
} else {
|
||||
config.pafers_treadmill = false;
|
||||
config.pafers_treadmill_bh_iboxster_plus = false;
|
||||
configurations.push_back(config);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
PafersTreadmillTestData() : TreadmillTestData("Pafers Treadmill") {
|
||||
this->addDeviceName("PAFERS_", comparison::StartsWithIgnoreCase);
|
||||
}
|
||||
|
||||
deviceType get_expectedDeviceType() const override { return deviceType::PafersTreadmill; }
|
||||
|
||||
bool get_isExpectedDevice(bluetoothdevice * detectedDevice) const override {
|
||||
return dynamic_cast<paferstreadmill*>(detectedDevice)!=nullptr;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Considering Extra QBluetoothDeviceInfo Content
|
||||
|
||||
Detection of some devices requires some specific bluetooth device information.
|
||||
|
||||
Supplying enabling and disabling QBluetoothDeviceInfo objects is done using a similar pattern to the multiple configurations scenario.
|
||||
For example, the M3iBike requires specific manufacturer information.
|
||||
|
||||
|
||||
```
|
||||
void M3IBikeTestData::configureBluetoothDeviceInfos(const QBluetoothDeviceInfo& info, bool enable, std::vector<QBluetoothDeviceInfo>& bluetoothDeviceInfos) const {
|
||||
// The M3I bike detector looks into the manufacturer data.
|
||||
|
||||
QBluetoothDeviceInfo result = info;
|
||||
|
||||
if(!enable) {
|
||||
result.setManufacturerData(1, QByteArray("Invalid manufacturer data."));
|
||||
bluetoothDeviceInfos.push_back(result);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int key=0;
|
||||
result.setManufacturerData(key++, hex2bytes("02010639009F00000000000000000014008001"));
|
||||
|
||||
bluetoothDeviceInfos.push_back(result);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The test framework populates the incoming QBluetoothDeviceInfo object with a name and a UUID. This is expected to have nothing else defined.
|
||||
Another example is one of the test data classes for detecting a device that uses the statesbike class:
|
||||
|
||||
Detection code from bluetooth.cpp:
|
||||
|
||||
```
|
||||
((b.name().toUpper().startsWith("KICKR CORE")) && !deviceHasService(b, QBluetoothUuid((quint16)0x1826)) && deviceHasService(b, QBluetoothUuid((quint16)0x1818)))
|
||||
```
|
||||
|
||||
This condition is actually extracted from a more complicated example where the current test data classes can't cover all the detection criteria in one implementation. This is why this class inherits from StagesBikeTestData rather than BikeTestData directly.
|
||||
|
||||
```
|
||||
class StagesBike3TestData : public StagesBikeTestData {
|
||||
protected:
|
||||
void configureBluetoothDeviceInfos(const QBluetoothDeviceInfo& info, bool enable, std::vector<QBluetoothDeviceInfo>& bluetoothDeviceInfos) const override {
|
||||
// The condition, if the name is acceptable, is:
|
||||
// !deviceHasService(b, QBluetoothUuid((quint16)0x1826)) && deviceHasService(b, QBluetoothUuid((quint16)0x1818)))
|
||||
|
||||
if(enable) {
|
||||
QBluetoothDeviceInfo result = info;
|
||||
result.setServiceUuids(QVector<QBluetoothUuid>({QBluetoothUuid((quint16)0x1818)}));
|
||||
bluetoothDeviceInfos.push_back(result);
|
||||
} else {
|
||||
QBluetoothDeviceInfo hasInvalid = info;
|
||||
hasInvalid.setServiceUuids(QVector<QBluetoothUuid>({QBluetoothUuid((quint16)0x1826)}));
|
||||
QBluetoothDeviceInfo hasBoth = hasInvalid;
|
||||
hasBoth.setServiceUuids(QVector<QBluetoothUuid>({QBluetoothUuid((quint16)0x1818),QBluetoothUuid((quint16)0x1826)}));
|
||||
|
||||
bluetoothDeviceInfos.push_back(info); // has neither
|
||||
bluetoothDeviceInfos.push_back(hasInvalid);
|
||||
bluetoothDeviceInfos.push_back(hasBoth);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
StagesBike3TestData() : StagesBikeTestData("Stages Bike (KICKR CORE)") {
|
||||
|
||||
this->addDeviceName("KICKR CORE", comparison::StartsWithIgnoreCase);
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
In this case, it populates the vector with the single enabling configuration if that's what's been requested, otherwise 3 disabling ones.
|
||||
|
||||
### Exclusions
|
||||
|
||||
Sometimes there might be ambiguity when multiple devices are available, and the detection code may specify that if the other conditions match, but certain specific kinds of devices (the exclusion devices) have already been detected, the newly matched device should be ignored.
|
||||
|
||||
The TestData class can be made to cover this by overriding the configureExclusions() method to add instances of the TestData classes for the exclusion devices to the object's internal list of exclusions.
|
||||
|
||||
Detection code:
|
||||
|
||||
```
|
||||
} else if (b.name().startsWith(QStringLiteral("ECH")) && !echelonRower && !echelonStride &&
|
||||
!echelonConnectSport && filter) {
|
||||
```
|
||||
The configureExclusions code is overridden to specify the exclusion test data objects. Note that the test for a previously detected device of the same type is not included.
|
||||
|
||||
```
|
||||
#pragma once
|
||||
|
||||
#include "Devices/Bike/biketestdata.h"
|
||||
#include "Devices/EchelonRower/echelonrowertestdata.h"
|
||||
#include "Devices/EchelonStrideTreadmill/echelonstridetreadmilltestdata.h"
|
||||
#include "devices/echelonconnectsport/echelonconnectsport.h"
|
||||
|
||||
class EchelonConnectSportBikeTestData : public BikeTestData {
|
||||
|
||||
public:
|
||||
EchelonConnectSportBikeTestData() : BikeTestData("Echelon Connect Sport Bike") {
|
||||
this->addDeviceName("ECH", comparison::StartsWith);
|
||||
}
|
||||
|
||||
void configureExclusions() override {
|
||||
this->exclude(new EchelonRowerTestData());
|
||||
this->exclude(new EchelonStrideTreadmillTestData());
|
||||
}
|
||||
|
||||
deviceType get_expectedDeviceType() const override { return deviceType::EchelonConnectSport; }
|
||||
|
||||
bool get_isExpectedDevice(bluetoothdevice * detectedDevice) const override {
|
||||
return dynamic_cast<echelonconnectsport*>(detectedDevice)!=nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
```
|
||||
|
||||
### When a single TestData Class Can't Cover all the Conditions
|
||||
|
||||
Detection code:
|
||||
|
||||
```
|
||||
QString powerSensorName =
|
||||
settings.value(QZSettings::power_sensor_name, QZSettings::default_power_sensor_name).toString();
|
||||
...
|
||||
} else if ((b.name().toUpper().startsWith(QStringLiteral("STAGES ")) ||
|
||||
(b.name().toUpper().startsWith("TACX SATORI")) ||
|
||||
((b.name().toUpper().startsWith("KICKR CORE")) && !deviceHasService(b, QBluetoothUuid((quint16)0x1826)) && deviceHasService(b, QBluetoothUuid((quint16)0x1818))) ||
|
||||
(b.name().toUpper()==QStringLiteral("QD")) ||
|
||||
(b.name().toUpper().startsWith(QStringLiteral("ASSIOMA")) &&
|
||||
powerSensorName.startsWith(QStringLiteral("Disabled")))) &&
|
||||
!stagesBike && !ftmsBike && filter) {
|
||||
```
|
||||
|
||||
This presents 3 scenarios for the current test framework.
|
||||
1. Match names only (starts with:"STAGES ", starts with: "TACX SATORI", equals: "QD")
|
||||
2. Match the name "KICKR CORE", presence and absence of specific service ids
|
||||
3. Match the name "ASSIOMA" and the power sensor name setting starts with "Disabled"
|
||||
|
||||
The framework is not currently capable of specifying all these scenarios in a single class.
|
||||
The generated test data is approximately the combinations of these lists: names * settings * bluetoothdeviceInfo * exclusions.
|
||||
If a combination should not exist, a separate class should be used.
|
||||
|
||||
In the example of the StagesBikeTestData classes, the exclusions, which apply to all situations, are implemented in the superclass StagesBikeTestData,
|
||||
|
||||
|
||||
```
|
||||
#pragma once
|
||||
|
||||
#include "Devices/Bike/biketestdata.h"
|
||||
#include "devices/stagesbike/stagesbike.h"
|
||||
#include "Devices/FTMSBike/ftmsbiketestdata.h"
|
||||
|
||||
class StagesBikeTestData : public BikeTestData {
|
||||
protected:
|
||||
StagesBikeTestData(std::string testName): BikeTestData(testName) {
|
||||
}
|
||||
|
||||
void configureExclusions() override {
|
||||
this->exclude(new FTMSBike1TestData());
|
||||
this->exclude(new FTMSBike2TestData());
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
deviceType get_expectedDeviceType() const override { return deviceType::StagesBike; }
|
||||
|
||||
bool get_isExpectedDevice(bluetoothdevice * detectedDevice) const override {
|
||||
return dynamic_cast<stagesbike*>(detectedDevice)!=nullptr;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
The name-match only in one subclass:
|
||||
|
||||
```
|
||||
class StagesBike1TestData : public StagesBikeTestData {
|
||||
|
||||
public:
|
||||
StagesBike1TestData() : StagesBikeTestData("Stages Bike") {
|
||||
this->addDeviceName("STAGES ", comparison::StartsWithIgnoreCase);
|
||||
this->addDeviceName("TACX SATORI", comparison::StartsWithIgnoreCase);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
The name and setting match in another subclass:
|
||||
|
||||
```
|
||||
|
||||
class StagesBike2TestData : public StagesBikeTestData {
|
||||
protected:
|
||||
bool configureSettings(DeviceDiscoveryInfo& info, bool enable) const override {
|
||||
info.powerSensorName = enable ? "Disabled":"Roberto";
|
||||
return true;
|
||||
}
|
||||
public:
|
||||
StagesBike2TestData() : StagesBikeTestData("Stages Bike (Assioma / Power Sensor disabled") {
|
||||
|
||||
this->addDeviceName("ASSIOMA", comparison::StartsWithIgnoreCase);
|
||||
}
|
||||
};
|
||||
|
||||
```
|
||||
The name and bluetooth device info configurations in another:
|
||||
|
||||
```
|
||||
|
||||
class StagesBike3TestData : public StagesBikeTestData {
|
||||
protected:
|
||||
void configureBluetoothDeviceInfos(const QBluetoothDeviceInfo& info, bool enable, std::vector<QBluetoothDeviceInfo>& bluetoothDeviceInfos) const override {
|
||||
// The condition, if the name is acceptable, is:
|
||||
// !deviceHasService(b, QBluetoothUuid((quint16)0x1826)) && deviceHasService(b, QBluetoothUuid((quint16)0x1818)))
|
||||
|
||||
if(enable) {
|
||||
QBluetoothDeviceInfo result = info;
|
||||
result.setServiceUuids(QVector<QBluetoothUuid>({QBluetoothUuid((quint16)0x1818)}));
|
||||
bluetoothDeviceInfos.push_back(result);
|
||||
} else {
|
||||
QBluetoothDeviceInfo hasInvalid = info;
|
||||
hasInvalid.setServiceUuids(QVector<QBluetoothUuid>({QBluetoothUuid((quint16)0x1826)}));
|
||||
QBluetoothDeviceInfo hasBoth = hasInvalid;
|
||||
hasBoth.setServiceUuids(QVector<QBluetoothUuid>({QBluetoothUuid((quint16)0x1818),QBluetoothUuid((quint16)0x1826)}));
|
||||
|
||||
bluetoothDeviceInfos.push_back(info); // has neither
|
||||
bluetoothDeviceInfos.push_back(hasInvalid);
|
||||
bluetoothDeviceInfos.push_back(hasBoth);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
StagesBike3TestData() : StagesBikeTestData("Stages Bike (KICKR CORE)") {
|
||||
|
||||
this->addDeviceName("KICKR CORE", comparison::StartsWithIgnoreCase);
|
||||
}
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
## Telling Google Test Where to Look
|
||||
|
||||
To register your test data class(es) with Google Test:
|
||||
|
||||
- open tst/Devices/devices.h
|
||||
- add a #include for your new header file(s)
|
||||
- add your new classes to the BluetoothDeviceTestDataTypes list.
|
||||
|
||||
This will add tests for your new device class to test runs of the tests in the BluetoothDeviceTestSuite class, which are about detecting, and not detecting devices in circumstances generated from the TestData classes.
|
||||
|
||||
|
||||
272
docs/specs/org.bluetooth.characteristic.cross_trainer_data.xml
Normal file
272
docs/specs/org.bluetooth.characteristic.cross_trainer_data.xml
Normal file
@@ -0,0 +1,272 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Copyright 2017 Bluetooth SIG, Inc. All rights reserved.-->
|
||||
<Characteristic xsi:noNamespaceSchemaLocation="http://schemas.bluetooth.org/Documents/characteristic.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
name="Cross Trainer Data"
|
||||
type="org.bluetooth.characteristic.cross_trainer_data" uuid="2ACE"
|
||||
last-modified="2017-02-14" approved="Yes">
|
||||
<InformativeText>
|
||||
<Summary>The Cross Trainer Data characteristic is used to send
|
||||
training-related data to the Client from a cross trainer
|
||||
(Server).</Summary>
|
||||
</InformativeText>
|
||||
<Value>
|
||||
<Field name="Flags">
|
||||
<Requirement>Mandatory</Requirement>
|
||||
<Format>24bit</Format>
|
||||
<BitField>
|
||||
<Bit index="0" size="1" name="More Data">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" requires="C1" />
|
||||
<Enumeration key="1" value="True" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="1" size="1" name="Average Speed present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C2" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="2" size="1" name="Total Distance Present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C3" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="3" size="1" name="Step Count present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C4" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="4" size="1" name="Stride Count present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C5" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="5" size="1" name="Elevation Gain present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C6" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="6" size="1"
|
||||
name="Inclination and Ramp Angle Setting present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C7" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="7" size="1" name="Resistance Level Present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C8" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="8" size="1" name="Instantaneous Power present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C9" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="9" size="1" name="Average Power present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C10" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="10" size="1" name="Expended Energy present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C11" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="11" size="1" name="Heart Rate present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C12" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="12" size="1"
|
||||
name="Metabolic Equivalent present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C13" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="13" size="1" name="Elapsed Time present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C14" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="14" size="1" name="Remaining Time present">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="False" />
|
||||
<Enumeration key="1" value="True" requires="C15" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<Bit index="15" size="1" name="Movement Direction">
|
||||
<Enumerations>
|
||||
<Enumeration key="0" value="Forward" />
|
||||
<Enumeration key="1" value="Backward" />
|
||||
</Enumerations>
|
||||
</Bit>
|
||||
<ReservedForFutureUse index="16" size="8" />
|
||||
</BitField>
|
||||
</Field>
|
||||
<Field name="Instantaneous Speed">
|
||||
<InformativeText>Kilometer per hour with a resolution of
|
||||
0.01</InformativeText>
|
||||
<Requirement>C1</Requirement>
|
||||
<Format>uint16</Format>
|
||||
<Unit>org.bluetooth.unit.velocity.kilometre_per_hour</Unit>
|
||||
<DecimalExponent>-2</DecimalExponent>
|
||||
</Field>
|
||||
<Field name="Average Speed">
|
||||
<InformativeText>Kilometer per hour with a resolution of
|
||||
0.01</InformativeText>
|
||||
<Requirement>C2</Requirement>
|
||||
<Format>uint16</Format>
|
||||
<Unit>org.bluetooth.unit.velocity.kilometre_per_hour</Unit>
|
||||
<DecimalExponent>-2</DecimalExponent>
|
||||
</Field>
|
||||
<Field name="Total Distance">
|
||||
<InformativeText>Meters with a resolution of
|
||||
1</InformativeText>
|
||||
<Requirement>C3</Requirement>
|
||||
<Format>uint24</Format>
|
||||
<Unit>org.bluetooth.unit.length.metre</Unit>
|
||||
</Field>
|
||||
<Field name="Step Per Minute">
|
||||
<InformativeText>Step/minute with a resolution of
|
||||
1</InformativeText>
|
||||
<Requirement>C4</Requirement>
|
||||
<Format>uint16</Format>
|
||||
<Unit>org.bluetooth.unit.step_per_minute</Unit>
|
||||
</Field>
|
||||
<Field name="Average Step Rate">
|
||||
<InformativeText>Step/minute with a resolution of
|
||||
1</InformativeText>
|
||||
<Requirement>C4</Requirement>
|
||||
<Format>uint16</Format>
|
||||
<Unit>org.bluetooth.unit.step_per_minute</Unit>
|
||||
</Field>
|
||||
<Field name="Stride Count">
|
||||
<InformativeText>Unitless with a resolution of
|
||||
0.1</InformativeText>
|
||||
<Requirement>C5</Requirement>
|
||||
<Format>uint16</Format>
|
||||
<DecimalExponent>-1</DecimalExponent>
|
||||
<Unit>org.bluetooth.unit.unitless</Unit>
|
||||
</Field>
|
||||
<Field name="Positive Elevation Gain">
|
||||
<InformativeText>Meters with a resolution of
|
||||
1</InformativeText>
|
||||
<Requirement>C6</Requirement>
|
||||
<Format>uint16</Format>
|
||||
<Unit>org.bluetooth.unit.length.metre</Unit>
|
||||
</Field>
|
||||
<Field name="Negative Elevation Gain">
|
||||
<InformativeText>Meters with a resolution of
|
||||
1</InformativeText>
|
||||
<Requirement>C6</Requirement>
|
||||
<Format>uint16</Format>
|
||||
<Unit>org.bluetooth.unit.length.metre</Unit>
|
||||
</Field>
|
||||
<Field name="Inclination">
|
||||
<InformativeText>Percent with a resolution of
|
||||
0.1</InformativeText>
|
||||
<Requirement>C7</Requirement>
|
||||
<Format>sint16</Format>
|
||||
<Unit>org.bluetooth.unit.percentage</Unit>
|
||||
<DecimalExponent>-1</DecimalExponent>
|
||||
</Field>
|
||||
<Field name="Ramp Angle Setting">
|
||||
<InformativeText>Degree with a resolution of
|
||||
0.1</InformativeText>
|
||||
<Requirement>C7</Requirement>
|
||||
<Format>sint16</Format>
|
||||
<Unit>org.bluetooth.unit.plane_angle.degree</Unit>
|
||||
<DecimalExponent>-1</DecimalExponent>
|
||||
</Field>
|
||||
<Field name="Resistance Level">
|
||||
<InformativeText>Unitless with a resolution of
|
||||
0.1</InformativeText>
|
||||
<Requirement>C8</Requirement>
|
||||
<Format>sint16</Format>
|
||||
<DecimalExponent>-1</DecimalExponent>
|
||||
<Unit>org.bluetooth.unit.unitless</Unit>
|
||||
</Field>
|
||||
<Field name="Instantaneous Power">
|
||||
<InformativeText>Watts with a resolution of
|
||||
1</InformativeText>
|
||||
<Requirement>C9</Requirement>
|
||||
<Format>sint16</Format>
|
||||
<Unit>org.bluetooth.unit.power.watt</Unit>
|
||||
</Field>
|
||||
<Field name="Average Power">
|
||||
<InformativeText>Watts with a resolution of
|
||||
1</InformativeText>
|
||||
<Requirement>C10</Requirement>
|
||||
<Format>sint16</Format>
|
||||
<Unit>org.bluetooth.unit.power.watt</Unit>
|
||||
</Field>
|
||||
<Field name="Total Energy">
|
||||
<InformativeText>Kilo Calorie with a resolution of
|
||||
1</InformativeText>
|
||||
<Requirement>C11</Requirement>
|
||||
<Format>uint16</Format>
|
||||
<Unit>org.bluetooth.unit.energy.kilogram_calorie</Unit>
|
||||
</Field>
|
||||
<Field name="Energy Per Hour">
|
||||
<InformativeText>Kilo Calorie with a resolution of
|
||||
1</InformativeText>
|
||||
<Requirement>C11</Requirement>
|
||||
<Format>uint16</Format>
|
||||
<Unit>org.bluetooth.unit.energy.kilogram_calorie</Unit>
|
||||
</Field>
|
||||
<Field name="Energy Per Minute">
|
||||
<InformativeText>Kilo Calorie with a resolution of
|
||||
1</InformativeText>
|
||||
<Requirement>C11</Requirement>
|
||||
<Format>uint8</Format>
|
||||
<Unit>org.bluetooth.unit.energy.kilogram_calorie</Unit>
|
||||
</Field>
|
||||
<Field name="Heart Rate">
|
||||
<InformativeText>Beats per minute with a resolution of
|
||||
1</InformativeText>
|
||||
<Requirement>C12</Requirement>
|
||||
<Format>uint8</Format>
|
||||
<Unit>org.bluetooth.unit.period.beats_per_minute</Unit>
|
||||
</Field>
|
||||
<Field name="Metabolic Equivalent">
|
||||
<InformativeText>Metabolic Equivalent with a resolution of
|
||||
0.1</InformativeText>
|
||||
<Requirement>C13</Requirement>
|
||||
<Format>uint8</Format>
|
||||
<DecimalExponent>-1</DecimalExponent>
|
||||
<Unit>org.bluetooth.unit.metabolic_equivalent</Unit>
|
||||
</Field>
|
||||
<Field name="Elapsed Time">
|
||||
<InformativeText>Second with a resolution of
|
||||
1</InformativeText>
|
||||
<Requirement>C14</Requirement>
|
||||
<Format>uint16</Format>
|
||||
<Unit>org.bluetooth.unit.time.second</Unit>
|
||||
</Field>
|
||||
<Field name="Remaining Time">
|
||||
<InformativeText>Second with a resolution of
|
||||
1</InformativeText>
|
||||
<Requirement>C15</Requirement>
|
||||
<Format>uint16</Format>
|
||||
<Unit>org.bluetooth.unit.time.second</Unit>
|
||||
</Field>
|
||||
</Value>
|
||||
<Note>The fields in the above table, reading from top to bottom,
|
||||
are shown in the order of LSO to MSO, where LSO = Least
|
||||
Significant Octet and MSO = Most Significant Octet. The Least
|
||||
Significant Octet represents the eight bits numbered 0 to
|
||||
7.</Note>
|
||||
</Characteristic>
|
||||
28
helpers/wireshark-json-filter.py
Normal file
28
helpers/wireshark-json-filter.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import json
|
||||
|
||||
def generate_code(hex_string, start_index):
|
||||
hex_pairs = [hex_string[i:i+2] for i in range(0, len(hex_string), 2)]
|
||||
output = ""
|
||||
array_name = f"initData{start_index}"
|
||||
array_elements = ', '.join([f"0x{hex_pair}" for hex_pair in hex_pairs])
|
||||
output += f"uint8_t {array_name}[] = {{{array_elements}}};\n"
|
||||
output += f'writeCharacteristic({array_name}, sizeof({array_name}), QStringLiteral("init"), false, false);\n'
|
||||
output += "QThread::msleep(sleepms);\n\n"
|
||||
return output
|
||||
|
||||
json_file_path = "C:\\Work\\qdomyos-zwift\\helpers\\tmp.json"
|
||||
|
||||
with open(json_file_path, 'r') as file:
|
||||
# Carica i dati JSON
|
||||
json_data = json.load(file)
|
||||
|
||||
|
||||
line = 0
|
||||
|
||||
for item in json_data:
|
||||
try:
|
||||
if(item['_source']['layers']['btatt']['btatt.value_raw'][0] != ''):
|
||||
line = line + 1
|
||||
print(generate_code(item['_source']['layers']['btatt']['btatt.value_raw'][0], line))
|
||||
except:
|
||||
pass
|
||||
2575
qHttpServerBin/5.15.2/headers/http_parser.c
Normal file
2575
qHttpServerBin/5.15.2/headers/http_parser.c
Normal file
File diff suppressed because it is too large
Load Diff
449
qHttpServerBin/5.15.2/headers/http_parser.h
Normal file
449
qHttpServerBin/5.15.2/headers/http_parser.h
Normal file
@@ -0,0 +1,449 @@
|
||||
/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to
|
||||
* deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
* sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef http_parser_h
|
||||
#define http_parser_h
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Also update SONAME in the Makefile whenever you change these. */
|
||||
#define HTTP_PARSER_VERSION_MAJOR 2
|
||||
#define HTTP_PARSER_VERSION_MINOR 9
|
||||
#define HTTP_PARSER_VERSION_PATCH 4
|
||||
|
||||
#include <stddef.h>
|
||||
#if defined(_WIN32) && !defined(__MINGW32__) && \
|
||||
(!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
|
||||
#include <BaseTsd.h>
|
||||
typedef __int8 int8_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#elif (defined(__sun) || defined(__sun__)) && defined(__SunOS_5_9)
|
||||
#include <sys/inttypes.h>
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
|
||||
* faster
|
||||
*/
|
||||
#ifndef HTTP_PARSER_STRICT
|
||||
# define HTTP_PARSER_STRICT 1
|
||||
#endif
|
||||
|
||||
/* Maximium header size allowed. If the macro is not defined
|
||||
* before including this header then the default is used. To
|
||||
* change the maximum header size, define the macro in the build
|
||||
* environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove
|
||||
* the effective limit on the size of the header, define the macro
|
||||
* to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff)
|
||||
*/
|
||||
#ifndef HTTP_MAX_HEADER_SIZE
|
||||
# define HTTP_MAX_HEADER_SIZE (80*1024)
|
||||
#endif
|
||||
|
||||
typedef struct http_parser http_parser;
|
||||
typedef struct http_parser_settings http_parser_settings;
|
||||
|
||||
|
||||
/* Callbacks should return non-zero to indicate an error. The parser will
|
||||
* then halt execution.
|
||||
*
|
||||
* The one exception is on_headers_complete. In a HTTP_RESPONSE parser
|
||||
* returning '1' from on_headers_complete will tell the parser that it
|
||||
* should not expect a body. This is used when receiving a response to a
|
||||
* HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
|
||||
* chunked' headers that indicate the presence of a body.
|
||||
*
|
||||
* Returning `2` from on_headers_complete will tell parser that it should not
|
||||
* expect neither a body nor any futher responses on this connection. This is
|
||||
* useful for handling responses to a CONNECT request which may not contain
|
||||
* `Upgrade` or `Connection: upgrade` headers.
|
||||
*
|
||||
* http_data_cb does not return data chunks. It will be called arbitrarily
|
||||
* many times for each string. E.G. you might get 10 callbacks for "on_url"
|
||||
* each providing just a few characters more data.
|
||||
*/
|
||||
typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
|
||||
typedef int (*http_cb) (http_parser*);
|
||||
|
||||
|
||||
/* Status Codes */
|
||||
#define HTTP_STATUS_MAP(XX) \
|
||||
XX(100, CONTINUE, Continue) \
|
||||
XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \
|
||||
XX(102, PROCESSING, Processing) \
|
||||
XX(200, OK, OK) \
|
||||
XX(201, CREATED, Created) \
|
||||
XX(202, ACCEPTED, Accepted) \
|
||||
XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \
|
||||
XX(204, NO_CONTENT, No Content) \
|
||||
XX(205, RESET_CONTENT, Reset Content) \
|
||||
XX(206, PARTIAL_CONTENT, Partial Content) \
|
||||
XX(207, MULTI_STATUS, Multi-Status) \
|
||||
XX(208, ALREADY_REPORTED, Already Reported) \
|
||||
XX(226, IM_USED, IM Used) \
|
||||
XX(300, MULTIPLE_CHOICES, Multiple Choices) \
|
||||
XX(301, MOVED_PERMANENTLY, Moved Permanently) \
|
||||
XX(302, FOUND, Found) \
|
||||
XX(303, SEE_OTHER, See Other) \
|
||||
XX(304, NOT_MODIFIED, Not Modified) \
|
||||
XX(305, USE_PROXY, Use Proxy) \
|
||||
XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \
|
||||
XX(308, PERMANENT_REDIRECT, Permanent Redirect) \
|
||||
XX(400, BAD_REQUEST, Bad Request) \
|
||||
XX(401, UNAUTHORIZED, Unauthorized) \
|
||||
XX(402, PAYMENT_REQUIRED, Payment Required) \
|
||||
XX(403, FORBIDDEN, Forbidden) \
|
||||
XX(404, NOT_FOUND, Not Found) \
|
||||
XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \
|
||||
XX(406, NOT_ACCEPTABLE, Not Acceptable) \
|
||||
XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \
|
||||
XX(408, REQUEST_TIMEOUT, Request Timeout) \
|
||||
XX(409, CONFLICT, Conflict) \
|
||||
XX(410, GONE, Gone) \
|
||||
XX(411, LENGTH_REQUIRED, Length Required) \
|
||||
XX(412, PRECONDITION_FAILED, Precondition Failed) \
|
||||
XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \
|
||||
XX(414, URI_TOO_LONG, URI Too Long) \
|
||||
XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \
|
||||
XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \
|
||||
XX(417, EXPECTATION_FAILED, Expectation Failed) \
|
||||
XX(421, MISDIRECTED_REQUEST, Misdirected Request) \
|
||||
XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \
|
||||
XX(423, LOCKED, Locked) \
|
||||
XX(424, FAILED_DEPENDENCY, Failed Dependency) \
|
||||
XX(426, UPGRADE_REQUIRED, Upgrade Required) \
|
||||
XX(428, PRECONDITION_REQUIRED, Precondition Required) \
|
||||
XX(429, TOO_MANY_REQUESTS, Too Many Requests) \
|
||||
XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \
|
||||
XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \
|
||||
XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \
|
||||
XX(501, NOT_IMPLEMENTED, Not Implemented) \
|
||||
XX(502, BAD_GATEWAY, Bad Gateway) \
|
||||
XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \
|
||||
XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \
|
||||
XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \
|
||||
XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \
|
||||
XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \
|
||||
XX(508, LOOP_DETECTED, Loop Detected) \
|
||||
XX(510, NOT_EXTENDED, Not Extended) \
|
||||
XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \
|
||||
|
||||
enum http_status
|
||||
{
|
||||
#define XX(num, name, string) HTTP_STATUS_##name = num,
|
||||
HTTP_STATUS_MAP(XX)
|
||||
#undef XX
|
||||
};
|
||||
|
||||
|
||||
/* Request Methods */
|
||||
#define HTTP_METHOD_MAP(XX) \
|
||||
XX(0, DELETE, DELETE) \
|
||||
XX(1, GET, GET) \
|
||||
XX(2, HEAD, HEAD) \
|
||||
XX(3, POST, POST) \
|
||||
XX(4, PUT, PUT) \
|
||||
/* pathological */ \
|
||||
XX(5, CONNECT, CONNECT) \
|
||||
XX(6, OPTIONS, OPTIONS) \
|
||||
XX(7, TRACE, TRACE) \
|
||||
/* WebDAV */ \
|
||||
XX(8, COPY, COPY) \
|
||||
XX(9, LOCK, LOCK) \
|
||||
XX(10, MKCOL, MKCOL) \
|
||||
XX(11, MOVE, MOVE) \
|
||||
XX(12, PROPFIND, PROPFIND) \
|
||||
XX(13, PROPPATCH, PROPPATCH) \
|
||||
XX(14, SEARCH, SEARCH) \
|
||||
XX(15, UNLOCK, UNLOCK) \
|
||||
XX(16, BIND, BIND) \
|
||||
XX(17, REBIND, REBIND) \
|
||||
XX(18, UNBIND, UNBIND) \
|
||||
XX(19, ACL, ACL) \
|
||||
/* subversion */ \
|
||||
XX(20, REPORT, REPORT) \
|
||||
XX(21, MKACTIVITY, MKACTIVITY) \
|
||||
XX(22, CHECKOUT, CHECKOUT) \
|
||||
XX(23, MERGE, MERGE) \
|
||||
/* upnp */ \
|
||||
XX(24, MSEARCH, M-SEARCH) \
|
||||
XX(25, NOTIFY, NOTIFY) \
|
||||
XX(26, SUBSCRIBE, SUBSCRIBE) \
|
||||
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
|
||||
/* RFC-5789 */ \
|
||||
XX(28, PATCH, PATCH) \
|
||||
XX(29, PURGE, PURGE) \
|
||||
/* CalDAV */ \
|
||||
XX(30, MKCALENDAR, MKCALENDAR) \
|
||||
/* RFC-2068, section 19.6.1.2 */ \
|
||||
XX(31, LINK, LINK) \
|
||||
XX(32, UNLINK, UNLINK) \
|
||||
/* icecast */ \
|
||||
XX(33, SOURCE, SOURCE) \
|
||||
|
||||
enum http_method
|
||||
{
|
||||
#define XX(num, name, string) HTTP_##name = num,
|
||||
HTTP_METHOD_MAP(XX)
|
||||
#undef XX
|
||||
};
|
||||
|
||||
|
||||
enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
|
||||
|
||||
|
||||
/* Flag values for http_parser.flags field */
|
||||
enum flags
|
||||
{ F_CHUNKED = 1 << 0
|
||||
, F_CONNECTION_KEEP_ALIVE = 1 << 1
|
||||
, F_CONNECTION_CLOSE = 1 << 2
|
||||
, F_CONNECTION_UPGRADE = 1 << 3
|
||||
, F_TRAILING = 1 << 4
|
||||
, F_UPGRADE = 1 << 5
|
||||
, F_SKIPBODY = 1 << 6
|
||||
, F_CONTENTLENGTH = 1 << 7
|
||||
};
|
||||
|
||||
|
||||
/* Map for errno-related constants
|
||||
*
|
||||
* The provided argument should be a macro that takes 2 arguments.
|
||||
*/
|
||||
#define HTTP_ERRNO_MAP(XX) \
|
||||
/* No error */ \
|
||||
XX(OK, "success") \
|
||||
\
|
||||
/* Callback-related errors */ \
|
||||
XX(CB_message_begin, "the on_message_begin callback failed") \
|
||||
XX(CB_url, "the on_url callback failed") \
|
||||
XX(CB_header_field, "the on_header_field callback failed") \
|
||||
XX(CB_header_value, "the on_header_value callback failed") \
|
||||
XX(CB_headers_complete, "the on_headers_complete callback failed") \
|
||||
XX(CB_body, "the on_body callback failed") \
|
||||
XX(CB_message_complete, "the on_message_complete callback failed") \
|
||||
XX(CB_status, "the on_status callback failed") \
|
||||
XX(CB_chunk_header, "the on_chunk_header callback failed") \
|
||||
XX(CB_chunk_complete, "the on_chunk_complete callback failed") \
|
||||
\
|
||||
/* Parsing-related errors */ \
|
||||
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
|
||||
XX(HEADER_OVERFLOW, \
|
||||
"too many header bytes seen; overflow detected") \
|
||||
XX(CLOSED_CONNECTION, \
|
||||
"data received after completed connection: close message") \
|
||||
XX(INVALID_VERSION, "invalid HTTP version") \
|
||||
XX(INVALID_STATUS, "invalid HTTP status code") \
|
||||
XX(INVALID_METHOD, "invalid HTTP method") \
|
||||
XX(INVALID_URL, "invalid URL") \
|
||||
XX(INVALID_HOST, "invalid host") \
|
||||
XX(INVALID_PORT, "invalid port") \
|
||||
XX(INVALID_PATH, "invalid path") \
|
||||
XX(INVALID_QUERY_STRING, "invalid query string") \
|
||||
XX(INVALID_FRAGMENT, "invalid fragment") \
|
||||
XX(LF_EXPECTED, "LF character expected") \
|
||||
XX(INVALID_HEADER_TOKEN, "invalid character in header") \
|
||||
XX(INVALID_CONTENT_LENGTH, \
|
||||
"invalid character in content-length header") \
|
||||
XX(UNEXPECTED_CONTENT_LENGTH, \
|
||||
"unexpected content-length header") \
|
||||
XX(INVALID_CHUNK_SIZE, \
|
||||
"invalid character in chunk size header") \
|
||||
XX(INVALID_CONSTANT, "invalid constant string") \
|
||||
XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
|
||||
XX(STRICT, "strict mode assertion failed") \
|
||||
XX(PAUSED, "parser is paused") \
|
||||
XX(UNKNOWN, "an unknown error occurred") \
|
||||
XX(INVALID_TRANSFER_ENCODING, \
|
||||
"request has invalid transfer-encoding") \
|
||||
|
||||
|
||||
/* Define HPE_* values for each errno value above */
|
||||
#define HTTP_ERRNO_GEN(n, s) HPE_##n,
|
||||
enum http_errno {
|
||||
HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
|
||||
};
|
||||
#undef HTTP_ERRNO_GEN
|
||||
|
||||
|
||||
/* Get an http_errno value from an http_parser */
|
||||
#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
|
||||
|
||||
|
||||
struct http_parser {
|
||||
/** PRIVATE **/
|
||||
unsigned int type : 2; /* enum http_parser_type */
|
||||
unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */
|
||||
unsigned int state : 7; /* enum state from http_parser.c */
|
||||
unsigned int header_state : 7; /* enum header_state from http_parser.c */
|
||||
unsigned int index : 5; /* index into current matcher */
|
||||
unsigned int uses_transfer_encoding : 1; /* Transfer-Encoding header is present */
|
||||
unsigned int allow_chunked_length : 1; /* Allow headers with both
|
||||
* `Content-Length` and
|
||||
* `Transfer-Encoding: chunked` set */
|
||||
unsigned int lenient_http_headers : 1;
|
||||
|
||||
uint32_t nread; /* # bytes read in various scenarios */
|
||||
uint64_t content_length; /* # bytes in body. `(uint64_t) -1` (all bits one)
|
||||
* if no Content-Length header.
|
||||
*/
|
||||
|
||||
/** READ-ONLY **/
|
||||
unsigned short http_major;
|
||||
unsigned short http_minor;
|
||||
unsigned int status_code : 16; /* responses only */
|
||||
unsigned int method : 8; /* requests only */
|
||||
unsigned int http_errno : 7;
|
||||
|
||||
/* 1 = Upgrade header was present and the parser has exited because of that.
|
||||
* 0 = No upgrade header present.
|
||||
* Should be checked when http_parser_execute() returns in addition to
|
||||
* error checking.
|
||||
*/
|
||||
unsigned int upgrade : 1;
|
||||
|
||||
/** PUBLIC **/
|
||||
void *data; /* A pointer to get hook to the "connection" or "socket" object */
|
||||
};
|
||||
|
||||
|
||||
struct http_parser_settings {
|
||||
http_cb on_message_begin;
|
||||
http_data_cb on_url;
|
||||
http_data_cb on_status;
|
||||
http_data_cb on_header_field;
|
||||
http_data_cb on_header_value;
|
||||
http_cb on_headers_complete;
|
||||
http_data_cb on_body;
|
||||
http_cb on_message_complete;
|
||||
/* When on_chunk_header is called, the current chunk length is stored
|
||||
* in parser->content_length.
|
||||
*/
|
||||
http_cb on_chunk_header;
|
||||
http_cb on_chunk_complete;
|
||||
};
|
||||
|
||||
|
||||
enum http_parser_url_fields
|
||||
{ UF_SCHEMA = 0
|
||||
, UF_HOST = 1
|
||||
, UF_PORT = 2
|
||||
, UF_PATH = 3
|
||||
, UF_QUERY = 4
|
||||
, UF_FRAGMENT = 5
|
||||
, UF_USERINFO = 6
|
||||
, UF_MAX = 7
|
||||
};
|
||||
|
||||
|
||||
/* Result structure for http_parser_parse_url().
|
||||
*
|
||||
* Callers should index into field_data[] with UF_* values iff field_set
|
||||
* has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
|
||||
* because we probably have padding left over), we convert any port to
|
||||
* a uint16_t.
|
||||
*/
|
||||
struct http_parser_url {
|
||||
uint16_t field_set; /* Bitmask of (1 << UF_*) values */
|
||||
uint16_t port; /* Converted UF_PORT string */
|
||||
|
||||
struct {
|
||||
uint16_t off; /* Offset into buffer in which field starts */
|
||||
uint16_t len; /* Length of run in buffer */
|
||||
} field_data[UF_MAX];
|
||||
};
|
||||
|
||||
|
||||
/* Returns the library version. Bits 16-23 contain the major version number,
|
||||
* bits 8-15 the minor version number and bits 0-7 the patch level.
|
||||
* Usage example:
|
||||
*
|
||||
* unsigned long version = http_parser_version();
|
||||
* unsigned major = (version >> 16) & 255;
|
||||
* unsigned minor = (version >> 8) & 255;
|
||||
* unsigned patch = version & 255;
|
||||
* printf("http_parser v%u.%u.%u\n", major, minor, patch);
|
||||
*/
|
||||
unsigned long http_parser_version(void);
|
||||
|
||||
void http_parser_init(http_parser *parser, enum http_parser_type type);
|
||||
|
||||
|
||||
/* Initialize http_parser_settings members to 0
|
||||
*/
|
||||
void http_parser_settings_init(http_parser_settings *settings);
|
||||
|
||||
|
||||
/* Executes the parser. Returns number of parsed bytes. Sets
|
||||
* `parser->http_errno` on error. */
|
||||
size_t http_parser_execute(http_parser *parser,
|
||||
const http_parser_settings *settings,
|
||||
const char *data,
|
||||
size_t len);
|
||||
|
||||
|
||||
/* If http_should_keep_alive() in the on_headers_complete or
|
||||
* on_message_complete callback returns 0, then this should be
|
||||
* the last message on the connection.
|
||||
* If you are the server, respond with the "Connection: close" header.
|
||||
* If you are the client, close the connection.
|
||||
*/
|
||||
int http_should_keep_alive(const http_parser *parser);
|
||||
|
||||
/* Returns a string version of the HTTP method. */
|
||||
const char *http_method_str(enum http_method m);
|
||||
|
||||
/* Returns a string version of the HTTP status code. */
|
||||
const char *http_status_str(enum http_status s);
|
||||
|
||||
/* Return a string name of the given error */
|
||||
const char *http_errno_name(enum http_errno err);
|
||||
|
||||
/* Return a string description of the given error */
|
||||
const char *http_errno_description(enum http_errno err);
|
||||
|
||||
/* Initialize all http_parser_url members to 0 */
|
||||
void http_parser_url_init(struct http_parser_url *u);
|
||||
|
||||
/* Parse a URL; return nonzero on failure */
|
||||
int http_parser_parse_url(const char *buf, size_t buflen,
|
||||
int is_connect,
|
||||
struct http_parser_url *u);
|
||||
|
||||
/* Pause or un-pause the parser; a nonzero value pauses */
|
||||
void http_parser_pause(http_parser *parser, int paused);
|
||||
|
||||
/* Checks if this is the final chunk of the body. */
|
||||
int http_body_is_final(const http_parser *parser);
|
||||
|
||||
/* Change the maximum header size provided at compile time. */
|
||||
void http_parser_set_max_header_size(uint32_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
24
qdomyos-zwift.pro
Normal file
24
qdomyos-zwift.pro
Normal file
@@ -0,0 +1,24 @@
|
||||
TEMPLATE = subdirs
|
||||
CONFIG+=ordered
|
||||
|
||||
!ios: !android: {
|
||||
SUBDIRS = \
|
||||
src/qdomyos-zwift-lib.pro \
|
||||
src/qdomyos-zwift.pro \
|
||||
tst/qdomyos-zwift-tests.pro
|
||||
|
||||
tst.depends = src/qdomyos-zwift-lib.pro
|
||||
}
|
||||
|
||||
android: {
|
||||
SUBDIRS = \
|
||||
src/qdomyos-zwift.pro
|
||||
}
|
||||
|
||||
ios: {
|
||||
SUBDIRS = \
|
||||
src/qdomyos-zwift-lib.pro \
|
||||
src/qdomyos-zwift.pro
|
||||
}
|
||||
|
||||
|
||||
BIN
qt-patches/android/5.15.0/jar/QtAndroidBluetooth.jar
Normal file
BIN
qt-patches/android/5.15.0/jar/QtAndroidBluetooth.jar
Normal file
Binary file not shown.
@@ -1018,7 +1018,7 @@ public class QtBluetoothLE {
|
||||
|
||||
/*
|
||||
* Already executed in GattCallback so executed by the HandlerThread. No need to
|
||||
* post it to the Hander.
|
||||
* post it to the Handler.
|
||||
*/
|
||||
private void scheduleMtuExchange() {
|
||||
ReadWriteJob newJob = new ReadWriteJob();
|
||||
|
||||
@@ -385,11 +385,11 @@ QT_USE_NAMESPACE
|
||||
}
|
||||
|
||||
[uuids addObject:nsUuid];
|
||||
// With the latest CoreBluetooth, we can synchronously retrive peripherals:
|
||||
// With the latest CoreBluetooth, we can synchronously retrieve peripherals:
|
||||
QT_BT_MAC_AUTORELEASEPOOL;
|
||||
NSArray *const peripherals = [manager retrievePeripheralsWithIdentifiers:uuids];
|
||||
if (!peripherals || peripherals.count != 1) {
|
||||
qCWarning(QT_BT_OSX) << "failed to retrive a peripheral";
|
||||
qCWarning(QT_BT_OSX) << "failed to retrieve a peripheral";
|
||||
if (notifier)
|
||||
emit notifier->CBManagerError(QLowEnergyController::UnknownRemoteDeviceError);
|
||||
return;
|
||||
@@ -648,7 +648,7 @@ QT_USE_NAMESPACE
|
||||
servicesToDiscoverDetails.removeAll(serviceUuid);
|
||||
|
||||
const NSUInteger nHandles = qt_countGATTEntries(service);
|
||||
Q_ASSERT_X(nHandles, Q_FUNC_INFO, "unexpected number of GATT entires");
|
||||
Q_ASSERT_X(nHandles, Q_FUNC_INFO, "unexpected number of GATT entries");
|
||||
|
||||
const QLowEnergyHandle maxHandle = std::numeric_limits<QLowEnergyHandle>::max();
|
||||
if (nHandles >= maxHandle || lastValidHandle > maxHandle - nHandles) {
|
||||
@@ -1058,7 +1058,7 @@ QT_USE_NAMESPACE
|
||||
|
||||
// TODO: test that we NEVER have the same characteristic twice in array!
|
||||
// At the moment I just protect against this by iterating in a reverse
|
||||
// order (at least avoiding a potential inifite loop with '-indexOfObject:').
|
||||
// order (at least avoiding a potential infinite loop with '-indexOfObject:').
|
||||
NSArray *const cs = service.characteristics;
|
||||
if (cs.count == 1)
|
||||
return nil;
|
||||
@@ -1091,7 +1091,7 @@ QT_USE_NAMESPACE
|
||||
|
||||
// TODO: test that we NEVER have the same characteristic twice in array!
|
||||
// At the moment I just protect against this by iterating in a reverse
|
||||
// order (at least avoiding a potential inifite loop with '-indexOfObject:').
|
||||
// order (at least avoiding a potential infinite loop with '-indexOfObject:').
|
||||
NSArray *const cs = service.characteristics;
|
||||
if (cs.count == 1)
|
||||
return nil;
|
||||
@@ -1597,8 +1597,8 @@ QT_USE_NAMESPACE
|
||||
} else {
|
||||
// This is (probably) the result of update notification.
|
||||
// It's very possible we can have an invalid handle here (0) -
|
||||
// if something esle is wrong (we subscribed for a notification),
|
||||
// disconnected (but other application is connected) and still receiveing
|
||||
// if something else is wrong (we subscribed for a notification),
|
||||
// disconnected (but other application is connected) and still receiving
|
||||
// updated values ...
|
||||
// TODO: this must be properly tested.
|
||||
if (!chHandle) {
|
||||
|
||||
BIN
qt-patches/windows/5.15.2/binary/mingw64/Qt5Bluetooth.dll
Normal file
BIN
qt-patches/windows/5.15.2/binary/mingw64/Qt5Bluetooth.dll
Normal file
Binary file not shown.
BIN
qt-patches/windows/5.15.2/binary/msvc2019/Qt5Bluetooth.dll
Normal file
BIN
qt-patches/windows/5.15.2/binary/msvc2019/Qt5Bluetooth.dll
Normal file
Binary file not shown.
BIN
qt-patches/windows/5.15.2/binary/msvc2019/Qt5Bluetooth.exp
Normal file
BIN
qt-patches/windows/5.15.2/binary/msvc2019/Qt5Bluetooth.exp
Normal file
Binary file not shown.
BIN
qt-patches/windows/5.15.2/binary/msvc2019/Qt5Bluetooth.lib
Normal file
BIN
qt-patches/windows/5.15.2/binary/msvc2019/Qt5Bluetooth.lib
Normal file
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
QMAKE_PRL_BUILD_DIR = C:/qt-everywhere-src-5.15.2/qtconnectivity/src/bluetooth
|
||||
QMAKE_PRO_INPUT = bluetooth.pro
|
||||
QMAKE_PRL_TARGET = Qt5Bluetooth.lib
|
||||
QMAKE_PRL_CONFIG = lex yacc depend_includepath testcase_targets import_plugins import_qpa_plugin windows prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on release link_prl flat debug_and_release precompile_header autogen_precompile_source embed_manifest_dll embed_manifest_exe shared shared release no_plugin_manifest win32 msvc copy_dir_files sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd rdseed shani x86SimdAlways prefix_build force_independent utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions release ReleaseBuild Release build_pass c++11 generated_privates relative_qt_rpath target_qt c++11 strict_c++ c++14 c++1z qt_install_headers need_fwd_pri qt_install_module debug_and_release build_all create_cmake skip_target_version_ext release ReleaseBuild Release build_pass have_target dll exclusive_builds debug_info no_autoqmake thread moc resources
|
||||
QMAKE_PRL_VERSION = 5.15.2
|
||||
BIN
qt-patches/windows/5.15.2/binary/msvc2019/Qt5Bluetoothd.dll
Normal file
BIN
qt-patches/windows/5.15.2/binary/msvc2019/Qt5Bluetoothd.dll
Normal file
Binary file not shown.
BIN
qt-patches/windows/5.15.2/binary/msvc2019/Qt5Bluetoothd.exp
Normal file
BIN
qt-patches/windows/5.15.2/binary/msvc2019/Qt5Bluetoothd.exp
Normal file
Binary file not shown.
BIN
qt-patches/windows/5.15.2/binary/msvc2019/Qt5Bluetoothd.lib
Normal file
BIN
qt-patches/windows/5.15.2/binary/msvc2019/Qt5Bluetoothd.lib
Normal file
Binary file not shown.
@@ -0,0 +1,5 @@
|
||||
QMAKE_PRL_BUILD_DIR = C:/qt-everywhere-src-5.15.2/qtconnectivity/src/bluetooth
|
||||
QMAKE_PRO_INPUT = bluetooth.pro
|
||||
QMAKE_PRL_TARGET = Qt5Bluetoothd.lib
|
||||
QMAKE_PRL_CONFIG = lex yacc debug depend_includepath testcase_targets import_plugins import_qpa_plugin windows prepare_docs qt_docs_targets qt_build_extra file_copies qmake_use qt warn_on link_prl flat debug_and_release precompile_header autogen_precompile_source embed_manifest_dll embed_manifest_exe shared shared no_plugin_manifest win32 msvc copy_dir_files sse2 aesni sse3 ssse3 sse4_1 sse4_2 avx avx2 avx512f avx512bw avx512cd avx512dq avx512er avx512ifma avx512pf avx512vbmi avx512vl compile_examples f16c force_debug_info largefile precompile_header rdrnd rdseed shani x86SimdAlways prefix_build force_independent utf8_source create_prl link_prl no_private_qt_headers_warning QTDIR_build qt_example_installs exceptions_off testcase_exceptions debug DebugBuild Debug build_pass c++11 generated_privates relative_qt_rpath target_qt c++11 strict_c++ c++14 c++1z qt_install_headers need_fwd_pri qt_install_module debug_and_release build_all create_cmake skip_target_version_ext debug DebugBuild Debug build_pass have_target dll no_plist exclusive_builds debug_info no_autoqmake thread moc resources
|
||||
QMAKE_PRL_VERSION = 5.15.2
|
||||
BIN
qt-patches/windows/5.15.2/binary/msvc2019/ucrtbased.dll
Normal file
BIN
qt-patches/windows/5.15.2/binary/msvc2019/ucrtbased.dll
Normal file
Binary file not shown.
1357
qt-patches/windows/5.15.2/qlowenergycontroller_win.cpp
Normal file
1357
qt-patches/windows/5.15.2/qlowenergycontroller_win.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1162
qt-patches/windows/5.15.2/qlowenergycontroller_winrt.cpp
Normal file
1162
qt-patches/windows/5.15.2/qlowenergycontroller_winrt.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1740
qt-patches/windows/5.15.2/qlowenergycontroller_winrt_new.cpp
Normal file
1740
qt-patches/windows/5.15.2/qlowenergycontroller_winrt_new.cpp
Normal file
File diff suppressed because it is too large
Load Diff
25
src/ChartFooter.qml
Normal file
25
src/ChartFooter.qml
Normal file
@@ -0,0 +1,25 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Controls.Material 2.0
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
Loader {
|
||||
id: chartFooterLoader
|
||||
sourceComponent: ChartFooterInnerJS
|
||||
anchors.fill: parent
|
||||
active: false
|
||||
}
|
||||
|
||||
Loader {
|
||||
anchors.fill: parent
|
||||
source: CHARTJS ? "ChartFooterInnerJS.qml":"ChartFooterInnerNoJS.qml"
|
||||
onLoaded: {
|
||||
if(CHARTJS) {
|
||||
chartFooterLoader.active = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
31
src/ChartFooterInnerJS.qml
Normal file
31
src/ChartFooterInnerJS.qml
Normal file
@@ -0,0 +1,31 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Controls.Material 2.0
|
||||
import Qt.labs.settings 1.0
|
||||
import QtWebView 1.1
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
Settings {
|
||||
id: settings
|
||||
}
|
||||
WebView {
|
||||
id: webView
|
||||
anchors.fill: parent
|
||||
url: "http://localhost:" + settings.value("template_inner_QZWS_port") + "/chartjs/chartlive.htm"
|
||||
visible: rootItem.chartFooterVisible
|
||||
onLoadingChanged: {
|
||||
if (loadRequest.errorString) {
|
||||
console.error(loadRequest.errorString);
|
||||
console.error("port " + settings.value("template_inner_QZWS_port"));
|
||||
}
|
||||
}
|
||||
onVisibleChanged: {
|
||||
console.log("onVisibleChanged" + visible)
|
||||
if(visible === true) {
|
||||
reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/ChartFooterInnerNoJS.qml
Normal file
12
src/ChartFooterInnerNoJS.qml
Normal file
@@ -0,0 +1,12 @@
|
||||
import QtQuick 2.7
|
||||
import QtQuick.Layouts 1.3
|
||||
import QtQuick.Controls 2.15
|
||||
import QtQuick.Controls.Material 2.0
|
||||
import Qt.labs.settings 1.0
|
||||
|
||||
ColumnLayout {
|
||||
anchors.fill: parent
|
||||
Settings {
|
||||
id: settings
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,12 @@ ColumnLayout {
|
||||
}
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: chartJscheckStartFromWeb
|
||||
interval: 200; running: true; repeat: true
|
||||
onTriggered: {if(rootItem.startRequested) {rootItem.startRequested = false; rootItem.stopRequested = false; stackView.pop(); }}
|
||||
}
|
||||
|
||||
Button {
|
||||
id: closeButton
|
||||
height: 50
|
||||
|
||||
44
src/ConnectIQ/iOS/ConnectIQ.xcframework/Info.plist
Normal file
44
src/ConnectIQ/iOS/ConnectIQ.xcframework/Info.plist
Normal file
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AvailableLibraries</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>BinaryPath</key>
|
||||
<string>ConnectIQ.framework/ConnectIQ</string>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>ios-arm64</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>ConnectIQ.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>ios</string>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>BinaryPath</key>
|
||||
<string>ConnectIQ.framework/ConnectIQ</string>
|
||||
<key>LibraryIdentifier</key>
|
||||
<string>ios-arm64_x86_64-simulator</string>
|
||||
<key>LibraryPath</key>
|
||||
<string>ConnectIQ.framework</string>
|
||||
<key>SupportedArchitectures</key>
|
||||
<array>
|
||||
<string>arm64</string>
|
||||
<string>x86_64</string>
|
||||
</array>
|
||||
<key>SupportedPlatform</key>
|
||||
<string>ios</string>
|
||||
<key>SupportedPlatformVariant</key>
|
||||
<string>simulator</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>XFWK</string>
|
||||
<key>XCFrameworkFormatVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
Binary file not shown.
@@ -0,0 +1,237 @@
|
||||
//
|
||||
// ConnectIQ.h
|
||||
// ConnectIQ
|
||||
//
|
||||
// Copyright (c) 2014 Garmin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <ConnectIQ/IQConstants.h>
|
||||
#import <ConnectIQ/IQDevice.h>
|
||||
#import <ConnectIQ/IQApp.h>
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - PUBLIC TYPES
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief SendMessage progress callback block
|
||||
///
|
||||
/// @param sentBytes The number of bytes that have been successfully transferred
|
||||
/// to the device so far for this connection.
|
||||
/// @param totalBytes The total number of bytes to transfer for this connection.
|
||||
typedef void (^IQSendMessageProgress)(uint32_t sentBytes, uint32_t totalBytes);
|
||||
|
||||
/// @brief SendMessage completion callback block
|
||||
///
|
||||
/// @param result The result of the SendMessage operation.
|
||||
typedef void (^IQSendMessageCompletion)(IQSendMessageResult result);
|
||||
|
||||
/// @brief Conforming to the IQUIOverrideDelegate protocol indicates that an
|
||||
/// object handles one or more events triggered by the ConnectIQ SDK that
|
||||
/// require user input.
|
||||
@protocol IQUIOverrideDelegate <NSObject>
|
||||
@optional
|
||||
/// @brief Called by the ConnectIQ SDK when an action has been requested that
|
||||
/// requires Garmin Connect Mobile to be installed.
|
||||
///
|
||||
/// The receiver should choose whether or not to launch the Apple App
|
||||
/// Store page for GCM, ideally by presenting the user with a choice.
|
||||
///
|
||||
/// If the receiver of this message decides to install GCM, it must call
|
||||
/// showAppStoreForConnectMobile.
|
||||
- (void)needsToInstallConnectMobile;
|
||||
@end
|
||||
|
||||
/// @brief Conforming to the IQDeviceEventDelegate protocol indicates that an
|
||||
/// object handles ConnectIQ device status events.
|
||||
@protocol IQDeviceEventDelegate <NSObject>
|
||||
@optional
|
||||
/// @brief Called by the ConnectIQ SDK when an IQDevice's connection status has
|
||||
/// changed.
|
||||
///
|
||||
/// @param device The IQDevice whose status changed.
|
||||
/// @param status The new status of the device.
|
||||
- (void)deviceStatusChanged:(IQDevice *)device status:(IQDeviceStatus)status;
|
||||
@end
|
||||
|
||||
/// @brief Conforming to the IQAppMessageDelegate protocol indicates that an
|
||||
/// object handles messages from ConnectIQ apps on compatible devices.
|
||||
@protocol IQAppMessageDelegate <NSObject>
|
||||
@optional
|
||||
/// @brief Called by the ConnectIQ SDK when a message is received from a device.
|
||||
///
|
||||
/// @param message The message that was received.
|
||||
/// @param app The device app that sent the message.
|
||||
- (void)receivedMessage:(id)message fromApp:(IQApp *)app;
|
||||
@end
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - CLASS DEFINITION
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief The root of the ConnectIQ SDK API.
|
||||
@interface ConnectIQ : NSObject
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - SINGLETON ACCESS
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief Exposes the single static instance of the ConnectIQ class.
|
||||
///
|
||||
/// @return The single status instance of the ConnectIQ class.
|
||||
+ (ConnectIQ *)sharedInstance;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - INITIALIZATION
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief Initializes the ConnectIQ SDK with startup parameters necessary for
|
||||
/// its operation.
|
||||
///
|
||||
/// @param urlScheme The URL scheme for this companion app. When Garmin Connect
|
||||
/// Mobile is launched, it will return to the companion app by
|
||||
/// launching a URL with this scheme.
|
||||
/// @param delegate The delegate that the SDK will use for notifying the
|
||||
/// companion app about events that require user input. If this
|
||||
/// is nil, the SDK's default UI will be used.
|
||||
- (void)initializeWithUrlScheme:(NSString *)urlScheme uiOverrideDelegate:(id<IQUIOverrideDelegate>)delegate;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - EXTERNAL LAUNCHING
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief Launches the Apple App Store page for the Garmin Connect Mobile app.
|
||||
/// The companion app should only call this in response to a
|
||||
/// needsToInstallConnectMobile event that gets triggered on the
|
||||
/// IQUIOverrideDelegate.
|
||||
- (void)showAppStoreForConnectMobile;
|
||||
|
||||
/// @brief Launches Garmin Connect Mobile for the purpose of retrieving a list of
|
||||
/// ConnectIQ-compatible devices.
|
||||
///
|
||||
/// Once the user has chosen which ConnectIQ devices to share with the
|
||||
/// companion app, GCM will return those devices to the companion app by
|
||||
/// opening a URL with the scheme registered in
|
||||
/// initializeWithUrlScheme:uiOverrideDelegate:.
|
||||
///
|
||||
/// The companion app should handle this URL by passing it in to the
|
||||
/// parseDeviceSelectionResponseFromURL: method to get the list of devices
|
||||
/// that the user permitted the companion app to communicate with.
|
||||
- (void)showConnectIQDeviceSelection;
|
||||
|
||||
/// @brief Parses a URL opened from Garmin Connect Mobile into a list of devices.
|
||||
///
|
||||
/// @param url The URL to parse.
|
||||
///
|
||||
/// @return An array of IQDevice objects representing the ConnectIQ-compatible
|
||||
/// devices that the user allowed GCM to share with the companion app.
|
||||
///
|
||||
/// @seealso showConnectIQDeviceSelection
|
||||
- (NSArray *)parseDeviceSelectionResponseFromURL:(NSURL *)url;
|
||||
|
||||
/// @brief Launches Garmin Connect Mobile and shows the ConnectIQ app store page
|
||||
/// for the given app.
|
||||
///
|
||||
/// The companion app should call this if the user would like to manage
|
||||
/// the app on the device, such as to install, upgrade, uninstall, or
|
||||
/// modify settings.
|
||||
///
|
||||
/// @param app The app to show the ConnectIQ app store page for.
|
||||
- (void)showConnectIQStoreForApp:(IQApp *)app;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - DEVICE MANAGEMENT
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief Registers an object as a listener for ConnectIQ device status events.
|
||||
///
|
||||
/// A device may have multiple device event listeners if this method is
|
||||
/// called more than once.
|
||||
///
|
||||
/// @param device A device to listen for status events from.
|
||||
/// @param delegate The listener which will receive status events for this device.
|
||||
- (void)registerForDeviceEvents:(IQDevice *)device delegate:(id<IQDeviceEventDelegate>)delegate;
|
||||
|
||||
/// @brief Unregisters a listener for a specific device.
|
||||
///
|
||||
/// @param device The device to unregister the listener for.
|
||||
/// @param delegate The listener to remove from the device.
|
||||
- (void)unregisterForDeviceEvents:(IQDevice *)device delegate:(id<IQDeviceEventDelegate>)delegate;
|
||||
|
||||
/// @brief Unregisters the specified listener from all devices for which it had
|
||||
/// previously been registered.
|
||||
///
|
||||
/// @param delegate The listener to unregister.
|
||||
- (void)unregisterForAllDeviceEvents:(id<IQDeviceEventDelegate>)delegate;
|
||||
|
||||
/// @brief Gets the current connection status of a device.
|
||||
///
|
||||
/// The device must have been registered for event notifications by
|
||||
/// calling registerForDeviceEvents:delegate: or this method will return
|
||||
/// IQDeviceStatus_InvalidDevice.
|
||||
///
|
||||
/// @param device The device to get the status for.
|
||||
///
|
||||
/// @return The device's current connection status.
|
||||
- (IQDeviceStatus)getDeviceStatus:(IQDevice *)device;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - APP MANAGEMENT
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief Begins getting the status of an app on a device. This method returns
|
||||
/// immediately.
|
||||
///
|
||||
/// @param app The IQApp to get the status for.
|
||||
/// @param completion The completion block that will be triggered when the device
|
||||
/// status operation is complete.
|
||||
- (void)getAppStatus:(IQApp *)app completion:(void(^)(IQAppStatus *appStatus))completion;
|
||||
|
||||
/// @brief Registers an object as a listener for ConnectIQ messages from an app
|
||||
/// on a device.
|
||||
///
|
||||
/// An app may have multiple message listeners if this method is called
|
||||
/// more than once.
|
||||
///
|
||||
/// @param app The app to listen for messages from.
|
||||
/// @param delegate The listener which will receive messages for this app.
|
||||
- (void)registerForAppMessages:(IQApp *)app delegate:(id<IQAppMessageDelegate>)delegate;
|
||||
|
||||
/// @brief Unregisters a listener for a specific app.
|
||||
///
|
||||
/// @param app The app to unregister a listener for.
|
||||
/// @param delegate The listener to remove from the app.
|
||||
- (void)unregisterForAppMessages:(IQApp *)app delegate:(id<IQAppMessageDelegate>)delegate;
|
||||
|
||||
/// @brief Unregisters all previously registered apps for a specific listener.
|
||||
///
|
||||
/// @param delegate The listener to unregister.
|
||||
- (void)unregisterForAllAppMessages:(id<IQAppMessageDelegate>)delegate;
|
||||
|
||||
/// @brief Begins sending a message to an app. This method returns immediately.
|
||||
///
|
||||
/// @param message The message to send to the app. This message must be one of
|
||||
/// the following types: NSString, NSNumber, NSNull, NSArray,
|
||||
/// or NSDictionary. Arrays and dictionaries may be nested.
|
||||
/// @param app The app to send the message to.
|
||||
/// @param progress A progress block that will be triggered periodically
|
||||
/// throughout the transfer. This is guaranteed to be triggered
|
||||
/// at least once.
|
||||
/// @param completion A completion block that will be triggered when the send
|
||||
/// message operation is complete.
|
||||
- (void)sendMessage:(id)message toApp:(IQApp *)app progress:(IQSendMessageProgress)progress completion:(IQSendMessageCompletion)completion;
|
||||
|
||||
/// @brief Sends an open app request message request to the device. This method returns immediately.
|
||||
///
|
||||
/// @param app The app to open.
|
||||
/// @param completion A completion block that will be triggered when the send
|
||||
/// message operation is complete.
|
||||
- (void)openAppRequest:(IQApp *)app completion:(IQSendMessageCompletion)completion;
|
||||
|
||||
// TODO *** Holding off on documenting this until this method actually works.
|
||||
- (void)sendImage:(NSData *)bitmap toApp:(IQApp *)app progress:(IQSendMessageProgress)progress completion:(IQSendMessageCompletion)completion;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// IQApp.h
|
||||
// ConnectIQ
|
||||
//
|
||||
// Copyright (c) 2014 Garmin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <ConnectIQ/IQDevice.h>
|
||||
#import <ConnectIQ/IQAppStatus.h>
|
||||
|
||||
/// @brief Represents an instance of a ConnectIQ app that is installed on a
|
||||
/// Garmin device.
|
||||
@interface IQApp : NSObject <NSSecureCoding>
|
||||
|
||||
/// @brief The unique identifier for this app.
|
||||
@property (nonatomic, readonly) NSUUID *uuid;
|
||||
|
||||
/// @brief The unique identifier for this app in the store.
|
||||
@property (nonatomic, readonly) NSUUID *storeUuid;
|
||||
|
||||
/// @brief The device that this app is installed on.
|
||||
@property (nonatomic, readonly) IQDevice *device;
|
||||
|
||||
/// @brief Creates a new app instance.
|
||||
///
|
||||
/// @param uuid The UUID of the app to create.
|
||||
/// @param storeUuid The store UUID of the app to create.
|
||||
/// @param device The device the app to create is installed on.
|
||||
///
|
||||
/// @return A new IQApp instance with the appropriate values set.
|
||||
+ (IQApp *)appWithUUID:(NSUUID *)uuid storeUuid:(NSUUID *)storeUuid device:(IQDevice *)device;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// IQAppStatus.h
|
||||
// ConnectIQ
|
||||
//
|
||||
// Copyright (c) 2014 Garmin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/// @brief Represents the current status of an app on a Garmin device.
|
||||
@interface IQAppStatus : NSObject
|
||||
|
||||
/// @brief YES if the app is installed on the device, NO if it isn't.
|
||||
@property (nonatomic, readonly) BOOL isInstalled;
|
||||
|
||||
/// @brief The version of the app that is currently installed on the device. If
|
||||
/// the app is not installed, this value is unused.
|
||||
@property (nonatomic, readonly) uint16_t version;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// IQConstants.h
|
||||
// ConnectIQ
|
||||
//
|
||||
// Copyright (c) 2014 Garmin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/// @brief The current version of the ConnectIQ SDK.
|
||||
extern int const IQSDKVersion;
|
||||
|
||||
/// @brief The bundle identifier for the Garmin Connect Mobile app.
|
||||
extern NSString * const IQGCMBundle;
|
||||
|
||||
/// @brief The bundle identifier for the Garmin Connect Mobile Beta app.
|
||||
extern NSString * const IQGCMInternalBetaBundle;
|
||||
|
||||
/// @brief The result of a SendMessage operation
|
||||
typedef NS_ENUM(NSInteger, IQSendMessageResult){
|
||||
///! @brief The message was sent successfully.
|
||||
IQSendMessageResult_Success,
|
||||
|
||||
/// @brief The message failed to send due to an unknown error.
|
||||
IQSendMessageResult_Failure_Unknown,
|
||||
|
||||
/// @brief The message failed to send. There was an error within the SDK or
|
||||
/// on the device.
|
||||
IQSendMessageResult_Failure_InternalError,
|
||||
|
||||
/// @brief The message failed to send. The device is not available right now.
|
||||
IQSendMessageResult_Failure_DeviceNotAvailable,
|
||||
|
||||
/// @brief The message failed to send. The app is not installed on the
|
||||
/// device.
|
||||
IQSendMessageResult_Failure_AppNotFound,
|
||||
|
||||
/// @brief The message failed to send. The device is busy and cannot receive
|
||||
/// the message right now.
|
||||
IQSendMessageResult_Failure_DeviceIsBusy,
|
||||
|
||||
/// @brief The message failed to send. The message contained an unsupported
|
||||
/// type.
|
||||
IQSendMessageResult_Failure_UnsupportedType,
|
||||
|
||||
/// @brief The message failed to send. The device does not have enough memory
|
||||
/// to receive the message.
|
||||
IQSendMessageResult_Failure_InsufficientMemory,
|
||||
|
||||
/// @brief The message failed to send. The connection timed out while sending
|
||||
/// the message.
|
||||
IQSendMessageResult_Failure_Timeout,
|
||||
|
||||
/// @brief The message failed to send and was retried, but could not complete
|
||||
/// after a number of tries.
|
||||
IQSendMessageResult_Failure_MaxRetries,
|
||||
|
||||
/// @brief The message was received by the device but it chose not to display
|
||||
/// a message prompt, ignoring the message.
|
||||
IQSendMessageResult_Failure_PromptNotDisplayed,
|
||||
|
||||
/// @brief The message was received by the device but the app to open
|
||||
/// was already running on the device.
|
||||
IQSendMessageResult_Failure_AppAlreadyRunning,
|
||||
};
|
||||
NSString *NSStringFromSendMessageResult(IQSendMessageResult value);
|
||||
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// IQDevice.h
|
||||
// ConnectIQ
|
||||
//
|
||||
// Copyright (c) 2014 Garmin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreBluetooth/CoreBluetooth.h>
|
||||
|
||||
/// @brief The current status of an IQDevice.
|
||||
typedef NS_ENUM(NSInteger, IQDeviceStatus){
|
||||
/// @brief No device with this UUID has been registered for status events
|
||||
/// the SDK.
|
||||
IQDeviceStatus_InvalidDevice,
|
||||
|
||||
/// @brief Bluetooth is either powered off or resetting.
|
||||
IQDeviceStatus_BluetoothNotReady,
|
||||
|
||||
/// @brief This device could not be found by iOS. Perhaps the user removed
|
||||
/// the device?
|
||||
IQDeviceStatus_NotFound,
|
||||
|
||||
/// @brief The device is recognized by iOS, but it is not currently
|
||||
/// connected.
|
||||
IQDeviceStatus_NotConnected,
|
||||
|
||||
/// @brief The device is connected and ready to communicate.
|
||||
IQDeviceStatus_Connected,
|
||||
};
|
||||
|
||||
/// @brief Represents a ConnectIQ-compatible Garmin device.
|
||||
@interface IQDevice : NSObject <NSSecureCoding>
|
||||
|
||||
/// @brief The unique identifier for this device.
|
||||
@property (nonatomic, readonly) NSUUID *uuid;
|
||||
|
||||
/// @brief The model name of the device provided by Garmin Connect Mobile.
|
||||
@property (nonatomic, readonly) NSString *modelName;
|
||||
|
||||
/// @brief The friendly name of the device, set by the user and provided by
|
||||
/// Garmin Connect Mobile.
|
||||
@property (nonatomic, readonly) NSString *friendlyName;
|
||||
|
||||
/// @brief Creates a new device instance.
|
||||
///
|
||||
/// @param uuid The UUID of the device to create.
|
||||
/// @param modelName The model name of the device to create.
|
||||
/// @param friendlyName The friendly name of the device to create.
|
||||
///
|
||||
/// @return A new IQDevice instance with the appropriate values set.
|
||||
+ (IQDevice *)deviceWithId:(NSUUID *)uuid modelName:(NSString *)modelName friendlyName:(NSString *)friendlyName;
|
||||
|
||||
/// @brief Creates a new device instance by copying another device's values.
|
||||
///
|
||||
/// @param device The device to copy values from.
|
||||
///
|
||||
/// @return A new IQDevice instance with all values copied.
|
||||
- (instancetype)initWithDevice:(IQDevice *)device;
|
||||
|
||||
@end
|
||||
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
framework module ConnectIQ {
|
||||
umbrella header "ConnectIQ.h"
|
||||
export *
|
||||
|
||||
module * { export * }
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,237 @@
|
||||
//
|
||||
// ConnectIQ.h
|
||||
// ConnectIQ
|
||||
//
|
||||
// Copyright (c) 2014 Garmin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <ConnectIQ/IQConstants.h>
|
||||
#import <ConnectIQ/IQDevice.h>
|
||||
#import <ConnectIQ/IQApp.h>
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - PUBLIC TYPES
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief SendMessage progress callback block
|
||||
///
|
||||
/// @param sentBytes The number of bytes that have been successfully transferred
|
||||
/// to the device so far for this connection.
|
||||
/// @param totalBytes The total number of bytes to transfer for this connection.
|
||||
typedef void (^IQSendMessageProgress)(uint32_t sentBytes, uint32_t totalBytes);
|
||||
|
||||
/// @brief SendMessage completion callback block
|
||||
///
|
||||
/// @param result The result of the SendMessage operation.
|
||||
typedef void (^IQSendMessageCompletion)(IQSendMessageResult result);
|
||||
|
||||
/// @brief Conforming to the IQUIOverrideDelegate protocol indicates that an
|
||||
/// object handles one or more events triggered by the ConnectIQ SDK that
|
||||
/// require user input.
|
||||
@protocol IQUIOverrideDelegate <NSObject>
|
||||
@optional
|
||||
/// @brief Called by the ConnectIQ SDK when an action has been requested that
|
||||
/// requires Garmin Connect Mobile to be installed.
|
||||
///
|
||||
/// The receiver should choose whether or not to launch the Apple App
|
||||
/// Store page for GCM, ideally by presenting the user with a choice.
|
||||
///
|
||||
/// If the receiver of this message decides to install GCM, it must call
|
||||
/// showAppStoreForConnectMobile.
|
||||
- (void)needsToInstallConnectMobile;
|
||||
@end
|
||||
|
||||
/// @brief Conforming to the IQDeviceEventDelegate protocol indicates that an
|
||||
/// object handles ConnectIQ device status events.
|
||||
@protocol IQDeviceEventDelegate <NSObject>
|
||||
@optional
|
||||
/// @brief Called by the ConnectIQ SDK when an IQDevice's connection status has
|
||||
/// changed.
|
||||
///
|
||||
/// @param device The IQDevice whose status changed.
|
||||
/// @param status The new status of the device.
|
||||
- (void)deviceStatusChanged:(IQDevice *)device status:(IQDeviceStatus)status;
|
||||
@end
|
||||
|
||||
/// @brief Conforming to the IQAppMessageDelegate protocol indicates that an
|
||||
/// object handles messages from ConnectIQ apps on compatible devices.
|
||||
@protocol IQAppMessageDelegate <NSObject>
|
||||
@optional
|
||||
/// @brief Called by the ConnectIQ SDK when a message is received from a device.
|
||||
///
|
||||
/// @param message The message that was received.
|
||||
/// @param app The device app that sent the message.
|
||||
- (void)receivedMessage:(id)message fromApp:(IQApp *)app;
|
||||
@end
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - CLASS DEFINITION
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief The root of the ConnectIQ SDK API.
|
||||
@interface ConnectIQ : NSObject
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - SINGLETON ACCESS
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief Exposes the single static instance of the ConnectIQ class.
|
||||
///
|
||||
/// @return The single status instance of the ConnectIQ class.
|
||||
+ (ConnectIQ *)sharedInstance;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - INITIALIZATION
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief Initializes the ConnectIQ SDK with startup parameters necessary for
|
||||
/// its operation.
|
||||
///
|
||||
/// @param urlScheme The URL scheme for this companion app. When Garmin Connect
|
||||
/// Mobile is launched, it will return to the companion app by
|
||||
/// launching a URL with this scheme.
|
||||
/// @param delegate The delegate that the SDK will use for notifying the
|
||||
/// companion app about events that require user input. If this
|
||||
/// is nil, the SDK's default UI will be used.
|
||||
- (void)initializeWithUrlScheme:(NSString *)urlScheme uiOverrideDelegate:(id<IQUIOverrideDelegate>)delegate;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - EXTERNAL LAUNCHING
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief Launches the Apple App Store page for the Garmin Connect Mobile app.
|
||||
/// The companion app should only call this in response to a
|
||||
/// needsToInstallConnectMobile event that gets triggered on the
|
||||
/// IQUIOverrideDelegate.
|
||||
- (void)showAppStoreForConnectMobile;
|
||||
|
||||
/// @brief Launches Garmin Connect Mobile for the purpose of retrieving a list of
|
||||
/// ConnectIQ-compatible devices.
|
||||
///
|
||||
/// Once the user has chosen which ConnectIQ devices to share with the
|
||||
/// companion app, GCM will return those devices to the companion app by
|
||||
/// opening a URL with the scheme registered in
|
||||
/// initializeWithUrlScheme:uiOverrideDelegate:.
|
||||
///
|
||||
/// The companion app should handle this URL by passing it in to the
|
||||
/// parseDeviceSelectionResponseFromURL: method to get the list of devices
|
||||
/// that the user permitted the companion app to communicate with.
|
||||
- (void)showConnectIQDeviceSelection;
|
||||
|
||||
/// @brief Parses a URL opened from Garmin Connect Mobile into a list of devices.
|
||||
///
|
||||
/// @param url The URL to parse.
|
||||
///
|
||||
/// @return An array of IQDevice objects representing the ConnectIQ-compatible
|
||||
/// devices that the user allowed GCM to share with the companion app.
|
||||
///
|
||||
/// @seealso showConnectIQDeviceSelection
|
||||
- (NSArray *)parseDeviceSelectionResponseFromURL:(NSURL *)url;
|
||||
|
||||
/// @brief Launches Garmin Connect Mobile and shows the ConnectIQ app store page
|
||||
/// for the given app.
|
||||
///
|
||||
/// The companion app should call this if the user would like to manage
|
||||
/// the app on the device, such as to install, upgrade, uninstall, or
|
||||
/// modify settings.
|
||||
///
|
||||
/// @param app The app to show the ConnectIQ app store page for.
|
||||
- (void)showConnectIQStoreForApp:(IQApp *)app;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - DEVICE MANAGEMENT
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief Registers an object as a listener for ConnectIQ device status events.
|
||||
///
|
||||
/// A device may have multiple device event listeners if this method is
|
||||
/// called more than once.
|
||||
///
|
||||
/// @param device A device to listen for status events from.
|
||||
/// @param delegate The listener which will receive status events for this device.
|
||||
- (void)registerForDeviceEvents:(IQDevice *)device delegate:(id<IQDeviceEventDelegate>)delegate;
|
||||
|
||||
/// @brief Unregisters a listener for a specific device.
|
||||
///
|
||||
/// @param device The device to unregister the listener for.
|
||||
/// @param delegate The listener to remove from the device.
|
||||
- (void)unregisterForDeviceEvents:(IQDevice *)device delegate:(id<IQDeviceEventDelegate>)delegate;
|
||||
|
||||
/// @brief Unregisters the specified listener from all devices for which it had
|
||||
/// previously been registered.
|
||||
///
|
||||
/// @param delegate The listener to unregister.
|
||||
- (void)unregisterForAllDeviceEvents:(id<IQDeviceEventDelegate>)delegate;
|
||||
|
||||
/// @brief Gets the current connection status of a device.
|
||||
///
|
||||
/// The device must have been registered for event notifications by
|
||||
/// calling registerForDeviceEvents:delegate: or this method will return
|
||||
/// IQDeviceStatus_InvalidDevice.
|
||||
///
|
||||
/// @param device The device to get the status for.
|
||||
///
|
||||
/// @return The device's current connection status.
|
||||
- (IQDeviceStatus)getDeviceStatus:(IQDevice *)device;
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
#pragma mark - APP MANAGEMENT
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
/// @brief Begins getting the status of an app on a device. This method returns
|
||||
/// immediately.
|
||||
///
|
||||
/// @param app The IQApp to get the status for.
|
||||
/// @param completion The completion block that will be triggered when the device
|
||||
/// status operation is complete.
|
||||
- (void)getAppStatus:(IQApp *)app completion:(void(^)(IQAppStatus *appStatus))completion;
|
||||
|
||||
/// @brief Registers an object as a listener for ConnectIQ messages from an app
|
||||
/// on a device.
|
||||
///
|
||||
/// An app may have multiple message listeners if this method is called
|
||||
/// more than once.
|
||||
///
|
||||
/// @param app The app to listen for messages from.
|
||||
/// @param delegate The listener which will receive messages for this app.
|
||||
- (void)registerForAppMessages:(IQApp *)app delegate:(id<IQAppMessageDelegate>)delegate;
|
||||
|
||||
/// @brief Unregisters a listener for a specific app.
|
||||
///
|
||||
/// @param app The app to unregister a listener for.
|
||||
/// @param delegate The listener to remove from the app.
|
||||
- (void)unregisterForAppMessages:(IQApp *)app delegate:(id<IQAppMessageDelegate>)delegate;
|
||||
|
||||
/// @brief Unregisters all previously registered apps for a specific listener.
|
||||
///
|
||||
/// @param delegate The listener to unregister.
|
||||
- (void)unregisterForAllAppMessages:(id<IQAppMessageDelegate>)delegate;
|
||||
|
||||
/// @brief Begins sending a message to an app. This method returns immediately.
|
||||
///
|
||||
/// @param message The message to send to the app. This message must be one of
|
||||
/// the following types: NSString, NSNumber, NSNull, NSArray,
|
||||
/// or NSDictionary. Arrays and dictionaries may be nested.
|
||||
/// @param app The app to send the message to.
|
||||
/// @param progress A progress block that will be triggered periodically
|
||||
/// throughout the transfer. This is guaranteed to be triggered
|
||||
/// at least once.
|
||||
/// @param completion A completion block that will be triggered when the send
|
||||
/// message operation is complete.
|
||||
- (void)sendMessage:(id)message toApp:(IQApp *)app progress:(IQSendMessageProgress)progress completion:(IQSendMessageCompletion)completion;
|
||||
|
||||
/// @brief Sends an open app request message request to the device. This method returns immediately.
|
||||
///
|
||||
/// @param app The app to open.
|
||||
/// @param completion A completion block that will be triggered when the send
|
||||
/// message operation is complete.
|
||||
- (void)openAppRequest:(IQApp *)app completion:(IQSendMessageCompletion)completion;
|
||||
|
||||
// TODO *** Holding off on documenting this until this method actually works.
|
||||
- (void)sendImage:(NSData *)bitmap toApp:(IQApp *)app progress:(IQSendMessageProgress)progress completion:(IQSendMessageCompletion)completion;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,34 @@
|
||||
//
|
||||
// IQApp.h
|
||||
// ConnectIQ
|
||||
//
|
||||
// Copyright (c) 2014 Garmin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <ConnectIQ/IQDevice.h>
|
||||
#import <ConnectIQ/IQAppStatus.h>
|
||||
|
||||
/// @brief Represents an instance of a ConnectIQ app that is installed on a
|
||||
/// Garmin device.
|
||||
@interface IQApp : NSObject <NSSecureCoding>
|
||||
|
||||
/// @brief The unique identifier for this app.
|
||||
@property (nonatomic, readonly) NSUUID *uuid;
|
||||
|
||||
/// @brief The unique identifier for this app in the store.
|
||||
@property (nonatomic, readonly) NSUUID *storeUuid;
|
||||
|
||||
/// @brief The device that this app is installed on.
|
||||
@property (nonatomic, readonly) IQDevice *device;
|
||||
|
||||
/// @brief Creates a new app instance.
|
||||
///
|
||||
/// @param uuid The UUID of the app to create.
|
||||
/// @param storeUuid The store UUID of the app to create.
|
||||
/// @param device The device the app to create is installed on.
|
||||
///
|
||||
/// @return A new IQApp instance with the appropriate values set.
|
||||
+ (IQApp *)appWithUUID:(NSUUID *)uuid storeUuid:(NSUUID *)storeUuid device:(IQDevice *)device;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// IQAppStatus.h
|
||||
// ConnectIQ
|
||||
//
|
||||
// Copyright (c) 2014 Garmin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/// @brief Represents the current status of an app on a Garmin device.
|
||||
@interface IQAppStatus : NSObject
|
||||
|
||||
/// @brief YES if the app is installed on the device, NO if it isn't.
|
||||
@property (nonatomic, readonly) BOOL isInstalled;
|
||||
|
||||
/// @brief The version of the app that is currently installed on the device. If
|
||||
/// the app is not installed, this value is unused.
|
||||
@property (nonatomic, readonly) uint16_t version;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,66 @@
|
||||
//
|
||||
// IQConstants.h
|
||||
// ConnectIQ
|
||||
//
|
||||
// Copyright (c) 2014 Garmin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/// @brief The current version of the ConnectIQ SDK.
|
||||
extern int const IQSDKVersion;
|
||||
|
||||
/// @brief The bundle identifier for the Garmin Connect Mobile app.
|
||||
extern NSString * const IQGCMBundle;
|
||||
|
||||
/// @brief The bundle identifier for the Garmin Connect Mobile Beta app.
|
||||
extern NSString * const IQGCMInternalBetaBundle;
|
||||
|
||||
/// @brief The result of a SendMessage operation
|
||||
typedef NS_ENUM(NSInteger, IQSendMessageResult){
|
||||
///! @brief The message was sent successfully.
|
||||
IQSendMessageResult_Success,
|
||||
|
||||
/// @brief The message failed to send due to an unknown error.
|
||||
IQSendMessageResult_Failure_Unknown,
|
||||
|
||||
/// @brief The message failed to send. There was an error within the SDK or
|
||||
/// on the device.
|
||||
IQSendMessageResult_Failure_InternalError,
|
||||
|
||||
/// @brief The message failed to send. The device is not available right now.
|
||||
IQSendMessageResult_Failure_DeviceNotAvailable,
|
||||
|
||||
/// @brief The message failed to send. The app is not installed on the
|
||||
/// device.
|
||||
IQSendMessageResult_Failure_AppNotFound,
|
||||
|
||||
/// @brief The message failed to send. The device is busy and cannot receive
|
||||
/// the message right now.
|
||||
IQSendMessageResult_Failure_DeviceIsBusy,
|
||||
|
||||
/// @brief The message failed to send. The message contained an unsupported
|
||||
/// type.
|
||||
IQSendMessageResult_Failure_UnsupportedType,
|
||||
|
||||
/// @brief The message failed to send. The device does not have enough memory
|
||||
/// to receive the message.
|
||||
IQSendMessageResult_Failure_InsufficientMemory,
|
||||
|
||||
/// @brief The message failed to send. The connection timed out while sending
|
||||
/// the message.
|
||||
IQSendMessageResult_Failure_Timeout,
|
||||
|
||||
/// @brief The message failed to send and was retried, but could not complete
|
||||
/// after a number of tries.
|
||||
IQSendMessageResult_Failure_MaxRetries,
|
||||
|
||||
/// @brief The message was received by the device but it chose not to display
|
||||
/// a message prompt, ignoring the message.
|
||||
IQSendMessageResult_Failure_PromptNotDisplayed,
|
||||
|
||||
/// @brief The message was received by the device but the app to open
|
||||
/// was already running on the device.
|
||||
IQSendMessageResult_Failure_AppAlreadyRunning,
|
||||
};
|
||||
NSString *NSStringFromSendMessageResult(IQSendMessageResult value);
|
||||
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// IQDevice.h
|
||||
// ConnectIQ
|
||||
//
|
||||
// Copyright (c) 2014 Garmin. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <CoreBluetooth/CoreBluetooth.h>
|
||||
|
||||
/// @brief The current status of an IQDevice.
|
||||
typedef NS_ENUM(NSInteger, IQDeviceStatus){
|
||||
/// @brief No device with this UUID has been registered for status events
|
||||
/// the SDK.
|
||||
IQDeviceStatus_InvalidDevice,
|
||||
|
||||
/// @brief Bluetooth is either powered off or resetting.
|
||||
IQDeviceStatus_BluetoothNotReady,
|
||||
|
||||
/// @brief This device could not be found by iOS. Perhaps the user removed
|
||||
/// the device?
|
||||
IQDeviceStatus_NotFound,
|
||||
|
||||
/// @brief The device is recognized by iOS, but it is not currently
|
||||
/// connected.
|
||||
IQDeviceStatus_NotConnected,
|
||||
|
||||
/// @brief The device is connected and ready to communicate.
|
||||
IQDeviceStatus_Connected,
|
||||
};
|
||||
|
||||
/// @brief Represents a ConnectIQ-compatible Garmin device.
|
||||
@interface IQDevice : NSObject <NSSecureCoding>
|
||||
|
||||
/// @brief The unique identifier for this device.
|
||||
@property (nonatomic, readonly) NSUUID *uuid;
|
||||
|
||||
/// @brief The model name of the device provided by Garmin Connect Mobile.
|
||||
@property (nonatomic, readonly) NSString *modelName;
|
||||
|
||||
/// @brief The friendly name of the device, set by the user and provided by
|
||||
/// Garmin Connect Mobile.
|
||||
@property (nonatomic, readonly) NSString *friendlyName;
|
||||
|
||||
/// @brief Creates a new device instance.
|
||||
///
|
||||
/// @param uuid The UUID of the device to create.
|
||||
/// @param modelName The model name of the device to create.
|
||||
/// @param friendlyName The friendly name of the device to create.
|
||||
///
|
||||
/// @return A new IQDevice instance with the appropriate values set.
|
||||
+ (IQDevice *)deviceWithId:(NSUUID *)uuid modelName:(NSString *)modelName friendlyName:(NSString *)friendlyName;
|
||||
|
||||
/// @brief Creates a new device instance by copying another device's values.
|
||||
///
|
||||
/// @param device The device to copy values from.
|
||||
///
|
||||
/// @return A new IQDevice instance with all values copied.
|
||||
- (instancetype)initWithDevice:(IQDevice *)device;
|
||||
|
||||
@end
|
||||
Binary file not shown.
@@ -0,0 +1,6 @@
|
||||
framework module ConnectIQ {
|
||||
umbrella header "ConnectIQ.h"
|
||||
export *
|
||||
|
||||
module * { export * }
|
||||
}
|
||||
@@ -0,0 +1,690 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>files</key>
|
||||
<dict>
|
||||
<key>Headers/ConnectIQ.h</key>
|
||||
<data>
|
||||
yih4e2KjbC/GqavxdCZ3xQ4mHmA=
|
||||
</data>
|
||||
<key>Headers/IQApp.h</key>
|
||||
<data>
|
||||
NDlj8k5C84UPFmD+qEMz2WcZloY=
|
||||
</data>
|
||||
<key>Headers/IQAppStatus.h</key>
|
||||
<data>
|
||||
WnybOSMMVqCKGns0rEz9C3EfQOg=
|
||||
</data>
|
||||
<key>Headers/IQConstants.h</key>
|
||||
<data>
|
||||
z5FAXaGG7RDVUTai1Vvqs33zc98=
|
||||
</data>
|
||||
<key>Headers/IQDevice.h</key>
|
||||
<data>
|
||||
bl545C/cu0mw2KlRmzojKmHPom0=
|
||||
</data>
|
||||
<key>Info.plist</key>
|
||||
<data>
|
||||
YUOCJU/YBLc4CRWV1z8JHDjCx8M=
|
||||
</data>
|
||||
<key>Modules/module.modulemap</key>
|
||||
<data>
|
||||
eEyhq/G44PBlD3KiydN8B1vbfCU=
|
||||
</data>
|
||||
<key>ar.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
1CDTE/Qaf1Z/HuhSt9CUnwitv4M=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>cs.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
/jkyQ77G2Xd9wy6QptBphGNbtCY=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>da.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
FYi0wjOu/Hw//Qe96yqxSb9yClc=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>de.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
MitzVbGhXhTLjPvw9vuWcQQa50Q=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>el.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
n82gLcjjjHszaroTFeJUvSrrc0o=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>en.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
hcxxLyrTI+aElXlPc5dwr7jdqwc=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>es.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
ff8DVQtNhO8pF7HFnXjh8foHXbo=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>fi.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
R9cr8yqJmu91Xz31tGyprGR3t/s=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>fr.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
PwFmqFeRTcjdHmkXYrPzNVYoe5o=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>he.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
/jPUgFtYbbyELG5DZ3Sjoi/If9w=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>hr.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
H2GtdTeORRPCnogvpWY69Dg9uME=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>hu.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
QIimMhNyYmqp4ZW01hfj554WAMg=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>id.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
2/54a0gkcVuk1I3m4ulDAXOLL5o=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>it.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
hNIKYIcP/87e6g7AUP+zKRtJ52M=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>ja.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
0iU2PbJ/3xgXMZ20ffsqaWpxKWc=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>ko.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
ERH8oHR9H9jMHjP0EAgaTtVhnX4=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>ms.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
DkbQA2+v/qSgQWma/fg3647Bkqs=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>nb.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
T3zFOvuvrJt5Vnmfqt2Mf/du8as=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>nl.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
t9PD5JEbfoSLaQ7f8M2cLghOReI=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>pl.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
wfTnhBccAm6JfwH/JkZKNRKTUAU=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>pt-PT.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
7yXkcZEpJ4UiRHAzhK+vw/Q857Y=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>pt.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
tZPncsQs8weCDJa03AKLpijXSUw=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>ru.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
Ct+byJ3rWeigvg0q6rB/kQaR+yE=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>sk.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
1yTM1nAsAYpSH7NrYU6/nFlqk5E=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>sv.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
i84z6vuHLrFpO0qZ2V0zYjixIws=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>th.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
oW5npy+pDJM1wUOgTkw9FY1Ave4=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>tr.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
76rD7PLrQMiT5YTlI8IjEFgsiU4=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>zh-Hans.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
DNlMxUKypOvKArzi7ioJUiFfFXg=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>zh-Hant.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash</key>
|
||||
<data>
|
||||
U6I+uL07KIv2b77w0c0glaJlhMg=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>files2</key>
|
||||
<dict>
|
||||
<key>Headers/ConnectIQ.h</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
kAenemss8n98vVLi54JqBUtGwaL1/i+HSejFBZgawHA=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/IQApp.h</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
bSRRooQ0FKFr3BgrFolAnkU402889YFHrH+6EEca3cg=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/IQAppStatus.h</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
tg9qNXtTmFUvNoJtq7O/aEXBNngcGENVRhvxLJ8C/xo=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/IQConstants.h</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
qVLQDlPhVsyAAQ/LCGOCdEOUaabcgwTHijMQiuWbAXM=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Headers/IQDevice.h</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
4N4+64IHeb9iBwyziNxo0SMuCM75ez9Em4UfmtgtTHA=
|
||||
</data>
|
||||
</dict>
|
||||
<key>Modules/module.modulemap</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
6a9Ehz1N4Sm/6qBlTfQpHUqRlpzQr2JMF26AfW4xUtY=
|
||||
</data>
|
||||
</dict>
|
||||
<key>ar.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
CWyQue2TCS0heGoGbN4ffetM2QZSk7lqgc2Wer2fgTg=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>cs.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
1mSn+EYeYcTV1dArgHz7PkmZrV6mHWfnuG5aDa6Y87E=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>da.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
yLkvGzd+smkOjicvW/+Oe6wGGyirHS+/YfjuSzyVoMM=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>de.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
DFHv7MWBJmyAkOj993NmSFKbS2t8/vtSev603sBUtjI=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>el.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
i4FAK4mi+SgS6oZv8zM74kRZToakn49E8GD7FcJBLoQ=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>en.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
vmBi9DFJzFcG0OwaWKSDjgklNi407U8u2pz3EnEENN4=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>es.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
z6RjynaWjrRKHmv4sLirc4eXwKOtQdylzj5+TiHpaTc=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>fi.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
6BI0iPRVWaP63/XFdjLBz6z7DsvvuOoaEAS+mYzrx8E=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>fr.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
geXjZzXre2CRiALecPFBGz4JSJA7MbkDnB4qrEMKNwk=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>he.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
47mcrSx16SFjWPIiN7guCAG0va8NiJ6I5s45tSVEHlY=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>hr.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
4bQvygPax6VBpoFlyS5by1N6otnDMliHu+bWsDaWSQc=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>hu.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
0m2fIyz26vh3RlUqqSXvoNTLovxIixrUyJoL/IDSoVk=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>id.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
hQf9SrG7d8aVWsXIbCIxkKEJjbnW1FLvS+MbOI1VtHQ=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>it.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
XAbEWX6cicDxGzxGgSx3DhF4rjUHX4LV+dO0X3rUEqc=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>ja.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
YOqOvZq0WEN4DCoSwc0lcTSRc4C812DqzjIsaid1SHg=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>ko.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
WJyaRCWn1KqmcDeajRnC41MdNrlpbI+1JbPkXhbKrKY=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>ms.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
gztYxa4Hn58HkKmcUIZI1jCz44IETZeMsqrpZSKxJvc=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>nb.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
Oy6UOwSN+/xPIrthAEvzV8PEn27kfsHpMMLU5w1rww0=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>nl.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
XbijhSaZgmsW59Vo9ZEbhDuUQH18fHizWKzsLosiM0o=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>pl.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
MQYgqA+Hl03JJ261Q19K5Lt64kSTBP+pfpD+jOVE3AU=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>pt-PT.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
seINq3QazVameLGOW+pIAtGWLa6NDl5XWRtqnObxywo=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>pt.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
GnzdqEuQwORzVCih99bwr79UHIyzXm+zuN5b9m1NrKY=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>ru.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
yCN9s/JXYqsMNZ1icaH4hUwyMQ1NtxOmV6sIAtRd9pc=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>sk.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
OFHDtkGLLSfTuSx8GOTycKDCKOKmX0Wh2QG1CHhRz3I=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>sv.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
a3Gk+3USOT5uundOXrNCgnbcD0rDo2lkCO7b7+zg2Is=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>th.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
qxGqAqRMwm0/dMd0W7DUsvbWb9x65GT+3d1zOQEql1w=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>tr.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
Y6TnKQmqO/TAx+0KYqRRG6UOz7I/gM1YmbUwgSfZSQU=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>zh-Hans.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
BI3m4MTMHuPI4sQKPGeQnxIlBJJrXwgVuR7Ho1Q5o6Y=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>zh-Hant.lproj/IQLocalizable.strings</key>
|
||||
<dict>
|
||||
<key>hash2</key>
|
||||
<data>
|
||||
14dQnjX3pEz2Um4J/fOdQDRe/LSuXxqkg1hEkO8E5ys=
|
||||
</data>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>rules</key>
|
||||
<dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^version.plist$</key>
|
||||
<true/>
|
||||
</dict>
|
||||
<key>rules2</key>
|
||||
<dict>
|
||||
<key>.*\.dSYM($|/)</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>11</real>
|
||||
</dict>
|
||||
<key>^(.*/)?\.DS_Store$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>2000</real>
|
||||
</dict>
|
||||
<key>^.*</key>
|
||||
<true/>
|
||||
<key>^.*\.lproj/</key>
|
||||
<dict>
|
||||
<key>optional</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1000</real>
|
||||
</dict>
|
||||
<key>^.*\.lproj/locversion.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>1100</real>
|
||||
</dict>
|
||||
<key>^Base\.lproj/</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>1010</real>
|
||||
</dict>
|
||||
<key>^Info\.plist$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^PkgInfo$</key>
|
||||
<dict>
|
||||
<key>omit</key>
|
||||
<true/>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^embedded\.provisionprofile$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
<key>^version\.plist$</key>
|
||||
<dict>
|
||||
<key>weight</key>
|
||||
<real>20</real>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user