mirror of
https://github.com/meshtastic/firmware.git
synced 2025-12-14 06:42:34 +00:00
Compare commits
984 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e32202e4f8 | ||
|
|
ca99b6b3b7 | ||
|
|
2eb2e9142f | ||
|
|
15e1a3870c | ||
|
|
5bdc7216b3 | ||
|
|
cc127f7dad | ||
|
|
be38a58a62 | ||
|
|
5930f8270d | ||
|
|
c9f2318e78 | ||
|
|
5cdc2f5142 | ||
|
|
53d773b81f | ||
|
|
85b2ba7ce9 | ||
|
|
474e0e7158 | ||
|
|
99a8c80c44 | ||
|
|
03a9d7da5e | ||
|
|
6975848f45 | ||
|
|
0cdc1fc959 | ||
|
|
e80c79edbe | ||
|
|
651d045afe | ||
|
|
86952c5456 | ||
|
|
46781357df | ||
|
|
bb9abf2dca | ||
|
|
5249608dce | ||
|
|
ee8f4de5ab | ||
|
|
17297db2b1 | ||
|
|
ad8bcba5ef | ||
|
|
138cebbf03 | ||
|
|
9f9573d2eb | ||
|
|
e10b82c118 | ||
|
|
d82aaaa806 | ||
|
|
c0d94ae4ab | ||
|
|
02ce12607c | ||
|
|
bdeba54c50 | ||
|
|
26c9585c9d | ||
|
|
696255c1f7 | ||
|
|
d857f8ba6d | ||
|
|
5852caa61c | ||
|
|
e82752c777 | ||
|
|
3eae2c6286 | ||
|
|
1e5d0b25ad | ||
|
|
c8423400ea | ||
|
|
af88a34f75 | ||
|
|
b9f1ce70cb | ||
|
|
c361c1fab7 | ||
|
|
091e953ed4 | ||
|
|
9ab02119f5 | ||
|
|
2d4849e0d0 | ||
|
|
16f897d27c | ||
|
|
4cbf0a0730 | ||
|
|
99c8df8e7d | ||
|
|
8e2e4f7e6a | ||
|
|
45d72bd51b | ||
|
|
781ed3eafd | ||
|
|
c66a0a37d8 | ||
|
|
92f2007207 | ||
|
|
1f7b537d2d | ||
|
|
cabeacfa94 | ||
|
|
df8b3ebbc7 | ||
|
|
b1c30f0650 | ||
|
|
194028f9fc | ||
|
|
f49c8f4c43 | ||
|
|
b3b4c2c1c3 | ||
|
|
a0076eb394 | ||
|
|
a6a4fec4b9 | ||
|
|
2d4657c8d4 | ||
|
|
32b8e4f20a | ||
|
|
3753fef298 | ||
|
|
a4bb1937c1 | ||
|
|
4bd22dd5db | ||
|
|
79a24c200e | ||
|
|
90060e84c0 | ||
|
|
8f5a1f19d3 | ||
|
|
3e0dc44210 | ||
|
|
91b99bd584 | ||
|
|
b6e21bcbcd | ||
|
|
ae7d3ee5ed | ||
|
|
f1179bd3ea | ||
|
|
9b24cc6dd6 | ||
|
|
20c5b98b2d | ||
|
|
d3cb9bdd4a | ||
|
|
a70cda6fe4 | ||
|
|
7737123d0f | ||
|
|
5138aff4b2 | ||
|
|
0b0d293a66 | ||
|
|
ddab4a0235 | ||
|
|
50615540ce | ||
|
|
f5e42b2533 | ||
|
|
9e9913101f | ||
|
|
b1289b632a | ||
|
|
c427c8abf9 | ||
|
|
9170dc7738 | ||
|
|
cc36e3a9a6 | ||
|
|
7d4c77abfd | ||
|
|
1ba91ec27f | ||
|
|
575c5b2193 | ||
|
|
3473a1e323 | ||
|
|
11a00e2977 | ||
|
|
817c99e09c | ||
|
|
9801a62d2d | ||
|
|
2bd40b7053 | ||
|
|
dccc15946b | ||
|
|
3ab9d2a50e | ||
|
|
776a978ea0 | ||
|
|
f60922af34 | ||
|
|
cb34fd5eb9 | ||
|
|
19d81347f2 | ||
|
|
d7d13d637c | ||
|
|
df75cefeeb | ||
|
|
66f9dbec45 | ||
|
|
4679dd7c4d | ||
|
|
a02979d564 | ||
|
|
f2698bbf91 | ||
|
|
d045139945 | ||
|
|
2c9c5991a0 | ||
|
|
1b365fa0aa | ||
|
|
71d1d4d8fa | ||
|
|
64df994a32 | ||
|
|
49a19e26d5 | ||
|
|
ef37f955c3 | ||
|
|
ac50b9544b | ||
|
|
ccc1600bc9 | ||
|
|
7c220f8a39 | ||
|
|
1839f8f7ca | ||
|
|
48c461c50c | ||
|
|
f346b4f0f2 | ||
|
|
5aab4f5c95 | ||
|
|
d407db5ee1 | ||
|
|
93afc71e2e | ||
|
|
67e657f10f | ||
|
|
619a48085a | ||
|
|
68937d52fe | ||
|
|
e33657eb75 | ||
|
|
21751da5a2 | ||
|
|
c2e8ac7173 | ||
|
|
825001f313 | ||
|
|
576526576a | ||
|
|
2fd5ce00ce | ||
|
|
4204c494ae | ||
|
|
84beae1001 | ||
|
|
951b4293c4 | ||
|
|
952c216bf7 | ||
|
|
ff4b03b8c1 | ||
|
|
c5903a790b | ||
|
|
bbc36f7b6f | ||
|
|
2f9ef463d8 | ||
|
|
bea00569fd | ||
|
|
d7368d5a51 | ||
|
|
47bbde3c60 | ||
|
|
04942a3570 | ||
|
|
62a8c968e8 | ||
|
|
b9a1cae72d | ||
|
|
6b442784f3 | ||
|
|
cfcb62bd18 | ||
|
|
f698883c02 | ||
|
|
4a5cef886e | ||
|
|
f6ec129288 | ||
|
|
17763034a0 | ||
|
|
4ad562b9f4 | ||
|
|
6b838002d4 | ||
|
|
5e0d53a1e3 | ||
|
|
b1dae3608e | ||
|
|
44aafd5b9c | ||
|
|
7597d5b3fd | ||
|
|
1a8891c33d | ||
|
|
f0eeaf01d4 | ||
|
|
d4e95e95a6 | ||
|
|
0767c8be03 | ||
|
|
18bbf3523e | ||
|
|
b081a6da56 | ||
|
|
a102e49fdb | ||
|
|
c078c08c3e | ||
|
|
91756d1fec | ||
|
|
5981831bc0 | ||
|
|
00eed206cb | ||
|
|
130d55aaaa | ||
|
|
13ef48094d | ||
|
|
529fd5a830 | ||
|
|
baa3d1dae4 | ||
|
|
4dd50df810 | ||
|
|
14c4022c18 | ||
|
|
a5d7bacdbf | ||
|
|
0b3c25f6d9 | ||
|
|
ad7a474a52 | ||
|
|
430186ec53 | ||
|
|
e9279919ae | ||
|
|
227c6fc27e | ||
|
|
a37844d7e5 | ||
|
|
ff20b29c3c | ||
|
|
64c29c4a35 | ||
|
|
d4df3f8a7e | ||
|
|
a16c3af30a | ||
|
|
3061860dab | ||
|
|
2450d98b59 | ||
|
|
a371592ad9 | ||
|
|
f7aaf48ae9 | ||
|
|
1fb604ebc8 | ||
|
|
df2733a3b5 | ||
|
|
8fd3cb1aac | ||
|
|
485c476f17 | ||
|
|
7dd4ce32d2 | ||
|
|
7f12af73d4 | ||
|
|
63113d57b3 | ||
|
|
32850ff39d | ||
|
|
2901f773a4 | ||
|
|
a7c54e4ad7 | ||
|
|
e1f0e11cb8 | ||
|
|
c73ee98739 | ||
|
|
c2a1141dfa | ||
|
|
5b4472ab56 | ||
|
|
3262f732d8 | ||
|
|
cff21ca130 | ||
|
|
81ce04d3da | ||
|
|
f4d2b10840 | ||
|
|
2370cb8aac | ||
|
|
59ec87f5b0 | ||
|
|
0d9481b6ea | ||
|
|
8f0105ccd9 | ||
|
|
05ca3c3d56 | ||
|
|
ba549d8fcd | ||
|
|
b9df2c00fa | ||
|
|
d9dcb33576 | ||
|
|
f698231be7 | ||
|
|
8414f4a6a3 | ||
|
|
8505020be5 | ||
|
|
f3b93d55fb | ||
|
|
9e0731a956 | ||
|
|
2b373048c6 | ||
|
|
22f23bb07d | ||
|
|
b32e3f1269 | ||
|
|
68ddb712f5 | ||
|
|
2fb5cd8c1c | ||
|
|
79aea8231f | ||
|
|
b0837c10c6 | ||
|
|
cd811951b1 | ||
|
|
df2976dad0 | ||
|
|
4ccbe6ff71 | ||
|
|
038ddb887f | ||
|
|
9134faaed1 | ||
|
|
649a120fe0 | ||
|
|
4db0c4a563 | ||
|
|
5f2f3c94b9 | ||
|
|
3b2f5fa5e3 | ||
|
|
97adb598b6 | ||
|
|
152ebf0dff | ||
|
|
5b1511c930 | ||
|
|
7ef2cc8623 | ||
|
|
b41a32c6b6 | ||
|
|
1ebd7b0c3e | ||
|
|
5457541244 | ||
|
|
ca77d48b20 | ||
|
|
965c2bda8d | ||
|
|
02e3438d5e | ||
|
|
02b1ece6ac | ||
|
|
9fdef366f7 | ||
|
|
284816229e | ||
|
|
10008d4eef | ||
|
|
58cfd1317c | ||
|
|
3d3f7869d4 | ||
|
|
ef325289eb | ||
|
|
40c63c0615 | ||
|
|
a9de8b9bb3 | ||
|
|
66a7f896c8 | ||
|
|
45a36f5571 | ||
|
|
876d32c9ee | ||
|
|
b9ce75b09c | ||
|
|
62493efc40 | ||
|
|
2848b76cc9 | ||
|
|
ef8bea478d | ||
|
|
a8e4bbbe65 | ||
|
|
9a414d9c77 | ||
|
|
48e6a60a07 | ||
|
|
ca48079545 | ||
|
|
76b4be3b87 | ||
|
|
d39cc3d57b | ||
|
|
b17a8d7a6a | ||
|
|
3d21794039 | ||
|
|
beac614e65 | ||
|
|
87f2673fc4 | ||
|
|
999b292717 | ||
|
|
c16acb904e | ||
|
|
5b777219be | ||
|
|
32ea11d2af | ||
|
|
8330c3270e | ||
|
|
0c8e0efed2 | ||
|
|
c44d8a0433 | ||
|
|
49b4ed2a89 | ||
|
|
db8faa9faf | ||
|
|
4b9ea4f808 | ||
|
|
c3beca3e23 | ||
|
|
95cb6b06e4 | ||
|
|
c46a884558 | ||
|
|
2044427e97 | ||
|
|
514ebdf013 | ||
|
|
10f64590a9 | ||
|
|
4a70ba1f7a | ||
|
|
dd6a402ea0 | ||
|
|
bed7d8a619 | ||
|
|
6d178ebc91 | ||
|
|
f75a256631 | ||
|
|
4f659b7563 | ||
|
|
1b6e8e36d3 | ||
|
|
7a4b8cde11 | ||
|
|
113859e791 | ||
|
|
a6b82ccfd9 | ||
|
|
e8b8ec69f1 | ||
|
|
023f1c24fb | ||
|
|
f00d07baa3 | ||
|
|
62c228b986 | ||
|
|
1a3cc40c7e | ||
|
|
bdcd5c3981 | ||
|
|
fc82e872d6 | ||
|
|
dffcea1f4d | ||
|
|
b47c54b5b6 | ||
|
|
c0c83ad389 | ||
|
|
23aecbdc38 | ||
|
|
eca7242a1f | ||
|
|
ef899425b8 | ||
|
|
269f90c510 | ||
|
|
7a5832ab8a | ||
|
|
044cc26340 | ||
|
|
4ccd03623f | ||
|
|
7854a22fbf | ||
|
|
943d5cb08d | ||
|
|
7480eb1826 | ||
|
|
c32c97c389 | ||
|
|
b4b1b24c84 | ||
|
|
ef146fc0b5 | ||
|
|
f6861a8fe2 | ||
|
|
736642455f | ||
|
|
3c1c11e439 | ||
|
|
b072eec4ac | ||
|
|
ff9b49ddaa | ||
|
|
b8863c8a07 | ||
|
|
4d7cd0a09d | ||
|
|
fed8e80ae4 | ||
|
|
b38bcffafb | ||
|
|
530432411e | ||
|
|
71cdbb1a73 | ||
|
|
200aa27cc0 | ||
|
|
f7752e4f9d | ||
|
|
7f0e8a8d6b | ||
|
|
f30c84012f | ||
|
|
1f6877606f | ||
|
|
1907873831 | ||
|
|
bacc6caf04 | ||
|
|
56d4250197 | ||
|
|
d66cede7fc | ||
|
|
f7ffd196e3 | ||
|
|
3a638090a2 | ||
|
|
4342ae74fb | ||
|
|
5150d15997 | ||
|
|
7d6dbcfa3f | ||
|
|
5a7962896d | ||
|
|
cfb9a600e4 | ||
|
|
7f3217d69e | ||
|
|
d94be0f534 | ||
|
|
17a3e6e975 | ||
|
|
423cbc2c6d | ||
|
|
124a82888d | ||
|
|
fec7a6bf17 | ||
|
|
bc50b39a3b | ||
|
|
158e3edbe7 | ||
|
|
116fe6d109 | ||
|
|
6a4ef7e1d1 | ||
|
|
a0fd83428f | ||
|
|
e5d4fbb164 | ||
|
|
26bafb4082 | ||
|
|
154dd3990c | ||
|
|
78fe41710b | ||
|
|
1f38404e60 | ||
|
|
848760e5bf | ||
|
|
5ebac0cd54 | ||
|
|
9b4079317b | ||
|
|
0f64332f93 | ||
|
|
fd62edbcab | ||
|
|
46abb9ae3f | ||
|
|
b5361ef89f | ||
|
|
bf808f57fe | ||
|
|
648589ed16 | ||
|
|
28ec0e310d | ||
|
|
956d9e96f2 | ||
|
|
266ba03bb7 | ||
|
|
04c54840f4 | ||
|
|
db33200468 | ||
|
|
d7fbcf89bf | ||
|
|
a8b1bc735a | ||
|
|
ba8c640d6e | ||
|
|
d88d2780f4 | ||
|
|
b0bbf95b03 | ||
|
|
7ca150bf07 | ||
|
|
9c7aa02db8 | ||
|
|
6f444ed4b5 | ||
|
|
28119bf1bf | ||
|
|
7fdb5b594d | ||
|
|
6013fceb10 | ||
|
|
2996c7c8e2 | ||
|
|
d1c3078698 | ||
|
|
3e5f81bf2a | ||
|
|
772d045166 | ||
|
|
1a064a4666 | ||
|
|
e81c89dcae | ||
|
|
1f36139e99 | ||
|
|
6f77244af3 | ||
|
|
05351ce3e4 | ||
|
|
a79aff4778 | ||
|
|
86d6f88787 | ||
|
|
5fbeaee0b0 | ||
|
|
fed4dfd410 | ||
|
|
0d3b8bdb22 | ||
|
|
3c4f56f3bf | ||
|
|
d3c00584a2 | ||
|
|
ce7fa65595 | ||
|
|
9c0a0ad220 | ||
|
|
22d0ef36b8 | ||
|
|
829c5f493c | ||
|
|
2d8eb8e205 | ||
|
|
52a3927585 | ||
|
|
b39f6c96bd | ||
|
|
a96c2e0eac | ||
|
|
10b24c0269 | ||
|
|
4140883684 | ||
|
|
3352fae64c | ||
|
|
55cb0c52ee | ||
|
|
626d82614c | ||
|
|
d890068acb | ||
|
|
468ad39a94 | ||
|
|
5cbe06c2b0 | ||
|
|
3412ecfe7b | ||
|
|
adb16a334c | ||
|
|
377f0bda5d | ||
|
|
51ab853658 | ||
|
|
464a42258f | ||
|
|
9e9c50e6d8 | ||
|
|
945f726b65 | ||
|
|
7c44daf8f4 | ||
|
|
c57a9a8613 | ||
|
|
3c0429deee | ||
|
|
5d8f541e70 | ||
|
|
bd126b866c | ||
|
|
036a1991b8 | ||
|
|
6e3b22c624 | ||
|
|
82fbedbf41 | ||
|
|
0929b86d62 | ||
|
|
65fc1cf4a6 | ||
|
|
6f753799fd | ||
|
|
4d72afebe6 | ||
|
|
b1643e6036 | ||
|
|
362d8cb831 | ||
|
|
b203c95dd1 | ||
|
|
8d4672964c | ||
|
|
6e5e5822aa | ||
|
|
5fb0bf2575 | ||
|
|
9af2045dc1 | ||
|
|
9624cc3798 | ||
|
|
3541228c1f | ||
|
|
cc95361fdc | ||
|
|
9b1d1ad0a5 | ||
|
|
7e467f1466 | ||
|
|
d3e28e3e2c | ||
|
|
1a1a0fbfbe | ||
|
|
91305c2c84 | ||
|
|
48dd6d388d | ||
|
|
64710a6a04 | ||
|
|
c83ff03d66 | ||
|
|
73b47a78aa | ||
|
|
493b25f23e | ||
|
|
004f1f625b | ||
|
|
fc20f658e6 | ||
|
|
8e988cc926 | ||
|
|
8c240b59f6 | ||
|
|
f847e30a3c | ||
|
|
7050ae4ba1 | ||
|
|
3e64d8439d | ||
|
|
435c955acd | ||
|
|
c656a95a84 | ||
|
|
27ad8472c1 | ||
|
|
3fcd4a61aa | ||
|
|
c6d93d1a28 | ||
|
|
b0c82dcb5b | ||
|
|
7d4058f49d | ||
|
|
31fc8fafec | ||
|
|
313cee9a3f | ||
|
|
066d9d48a4 | ||
|
|
16de4a0d2e | ||
|
|
621fcb598e | ||
|
|
b2a6a4000b | ||
|
|
f5c939fb10 | ||
|
|
e508306395 | ||
|
|
cc6b500029 | ||
|
|
887b1b5dcd | ||
|
|
62e333b235 | ||
|
|
d859700497 | ||
|
|
f129b458ad | ||
|
|
bf68ad7cf5 | ||
|
|
6d9bdbb628 | ||
|
|
6782c2d3d1 | ||
|
|
b6f71ca1db | ||
|
|
92df77f228 | ||
|
|
caeea41867 | ||
|
|
bc17dd1a0f | ||
|
|
2a3175470b | ||
|
|
8ca6bbfb78 | ||
|
|
9777762052 | ||
|
|
da01f0ab7f | ||
|
|
1cd81208c0 | ||
|
|
2394075d94 | ||
|
|
de7b9877f9 | ||
|
|
ee27c15c2c | ||
|
|
076f8bd77b | ||
|
|
288363b3a6 | ||
|
|
48256d6e9e | ||
|
|
c007302564 | ||
|
|
0a9f7147f3 | ||
|
|
46ba36511a | ||
|
|
170f0693c6 | ||
|
|
d900509fbc | ||
|
|
8018c27dcd | ||
|
|
8df5ac9d3f | ||
|
|
c3196f47ef | ||
|
|
81a49d4e3c | ||
|
|
4f32c36db8 | ||
|
|
5db0bb3368 | ||
|
|
f3d38d84c9 | ||
|
|
f8bb6bbcb4 | ||
|
|
e0d5b9dce1 | ||
|
|
94e4b30125 | ||
|
|
2a067e7f6b | ||
|
|
97ab07e05c | ||
|
|
b8d39845cf | ||
|
|
cbea36a151 | ||
|
|
49dea6d6bd | ||
|
|
7d4c6c7086 | ||
|
|
fefd3d78f3 | ||
|
|
f41a77c46d | ||
|
|
6a475d8288 | ||
|
|
c629b94333 | ||
|
|
5423f4e06c | ||
|
|
88f8bbe21e | ||
|
|
eda4862f0d | ||
|
|
7ca752cd32 | ||
|
|
c5ffebc498 | ||
|
|
baa12aa5b3 | ||
|
|
ccf3522ada | ||
|
|
d14cf5aa94 | ||
|
|
810429b54f | ||
|
|
915427c964 | ||
|
|
347484baaf | ||
|
|
bb6913a56a | ||
|
|
6cdaf8c600 | ||
|
|
c370eb4a88 | ||
|
|
8dc4492ba3 | ||
|
|
901cc536ef | ||
|
|
41c2732e4f | ||
|
|
2d12a363db | ||
|
|
28455f0056 | ||
|
|
5125126aec | ||
|
|
f1ca1ee3c0 | ||
|
|
dffb6c2f06 | ||
|
|
7f214ffbb0 | ||
|
|
e049eac38a | ||
|
|
338445d175 | ||
|
|
8eb492d356 | ||
|
|
a5341d766e | ||
|
|
c78142b235 | ||
|
|
9ebaa2b962 | ||
|
|
79498580b1 | ||
|
|
41901aed97 | ||
|
|
2729a513ab | ||
|
|
af046e7dbd | ||
|
|
0caf534b65 | ||
|
|
f650222e94 | ||
|
|
5c40378805 | ||
|
|
780b7e3628 | ||
|
|
83ae3c7714 | ||
|
|
25ebb9adb8 | ||
|
|
7f6a0e7ddc | ||
|
|
f62e6793c5 | ||
|
|
babd57ecde | ||
|
|
de196810a2 | ||
|
|
82fe55471d | ||
|
|
83726086a9 | ||
|
|
60d90c4533 | ||
|
|
9145945efa | ||
|
|
7b09fbe049 | ||
|
|
a90bab5455 | ||
|
|
3d9cc8a056 | ||
|
|
ff885ef215 | ||
|
|
eb4286b560 | ||
|
|
9c90de0f6f | ||
|
|
d7a1cef046 | ||
|
|
6a359e2124 | ||
|
|
ca75dcd64d | ||
|
|
aba05ba5ce | ||
|
|
99882a675b | ||
|
|
9c9347df23 | ||
|
|
b66856c53f | ||
|
|
285069703c | ||
|
|
d91ab5480f | ||
|
|
e3b74ece74 | ||
|
|
66557241f3 | ||
|
|
3c09c3e520 | ||
|
|
781077e799 | ||
|
|
22946b5e51 | ||
|
|
c0307cbcb0 | ||
|
|
6b568ab2fb | ||
|
|
67bad9a689 | ||
|
|
559a790286 | ||
|
|
08e5bd728b | ||
|
|
0cfeeba2e2 | ||
|
|
5007624ba5 | ||
|
|
bba4677915 | ||
|
|
ac969cdb26 | ||
|
|
1c3eff0ee5 | ||
|
|
cba9546a4d | ||
|
|
ceae60cf13 | ||
|
|
3de1607cea | ||
|
|
029b2f3139 | ||
|
|
ab6c97bfef | ||
|
|
a61b15e861 | ||
|
|
8c7aa07c70 | ||
|
|
6a402b13fa | ||
|
|
c30b570e16 | ||
|
|
9b25818a50 | ||
|
|
5311e44660 | ||
|
|
55dafcbecb | ||
|
|
178958c165 | ||
|
|
d7cf7e2eb4 | ||
|
|
fce8c16d52 | ||
|
|
b690868bb1 | ||
|
|
dec88a368b | ||
|
|
17394d8c1c | ||
|
|
a7da7cd32e | ||
|
|
f37dc9c776 | ||
|
|
d6658dbb2e | ||
|
|
05531b2684 | ||
|
|
8b1fb39ce1 | ||
|
|
da46d4ca0e | ||
|
|
047141eb34 | ||
|
|
cb1053850d | ||
|
|
7652331e8c | ||
|
|
12bf3795ea | ||
|
|
7f45184d90 | ||
|
|
829763af2c | ||
|
|
75806ee666 | ||
|
|
91ec29db03 | ||
|
|
d191b12801 | ||
|
|
e0d6456618 | ||
|
|
70eda2ee06 | ||
|
|
7c4eb3eddd | ||
|
|
661a75d796 | ||
|
|
b617010a46 | ||
|
|
5a70c45a3e | ||
|
|
cb2b36811a | ||
|
|
92edcb97ed | ||
|
|
7f1ec15cab | ||
|
|
1aa7451866 | ||
|
|
d5c46dc114 | ||
|
|
5bab16636d | ||
|
|
204f2c1a68 | ||
|
|
a5b7501a4e | ||
|
|
b0e2c81666 | ||
|
|
00ca351169 | ||
|
|
0415a3c369 | ||
|
|
4eb27b637d | ||
|
|
107b56a346 | ||
|
|
abdc4dfae8 | ||
|
|
014eea2f56 | ||
|
|
9b4ca95660 | ||
|
|
78ff9a8116 | ||
|
|
66b147fb31 | ||
|
|
c5df1bc885 | ||
|
|
00cf3a768e | ||
|
|
b6a3deb341 | ||
|
|
531f488fe8 | ||
|
|
d674aaaa29 | ||
|
|
7f6dc104f0 | ||
|
|
102085808f | ||
|
|
2645730329 | ||
|
|
6aa28f55dd | ||
|
|
1e86365167 | ||
|
|
62c20f8ab9 | ||
|
|
7706f65921 | ||
|
|
68490336b8 | ||
|
|
20ac8d71fd | ||
|
|
ec082b7c9a | ||
|
|
ece75d1d7f | ||
|
|
9e10ce487c | ||
|
|
d248c6be4b | ||
|
|
39b0a89821 | ||
|
|
d9f43d3e2f | ||
|
|
94f03bee01 | ||
|
|
08c77caaa9 | ||
|
|
cfedc97cd0 | ||
|
|
cfad226b2b | ||
|
|
859642d2e4 | ||
|
|
8316419a01 | ||
|
|
96f5069742 | ||
|
|
e433249bb1 | ||
|
|
2a6df797ca | ||
|
|
28aa48c8d2 | ||
|
|
582f77e4ec | ||
|
|
5700cf96d5 | ||
|
|
769a98f1f4 | ||
|
|
4ee35a0612 | ||
|
|
64f6741f82 | ||
|
|
6ad5abcab2 | ||
|
|
5480f10184 | ||
|
|
41dfbdd331 | ||
|
|
903268c52a | ||
|
|
b60c630922 | ||
|
|
95588b420c | ||
|
|
b141ec2e35 | ||
|
|
3d0c611896 | ||
|
|
6cb92143ec | ||
|
|
f919eb6a64 | ||
|
|
4147786b12 | ||
|
|
3400bcde85 | ||
|
|
e5fac4b78d | ||
|
|
4d20865c67 | ||
|
|
8b4cf91f1f | ||
|
|
6a6a10fb9b | ||
|
|
44749470a4 | ||
|
|
8fe714d8b1 | ||
|
|
22137ff1bd | ||
|
|
da3b6d1958 | ||
|
|
c7213fb710 | ||
|
|
637960edde | ||
|
|
be7e4fea6a | ||
|
|
d9209ffaea | ||
|
|
9fb94796c8 | ||
|
|
f060f7faad | ||
|
|
55673fcd66 | ||
|
|
2ff94cb11d | ||
|
|
e46bebc06f | ||
|
|
80e8b4adcc | ||
|
|
e9be03b76c | ||
|
|
98dfecdb79 | ||
|
|
8ba8278fb5 | ||
|
|
51267379ab | ||
|
|
e2cf2ba4f2 | ||
|
|
4550cce639 | ||
|
|
f2f17c81d4 | ||
|
|
7c0d13f00a | ||
|
|
f78f3232e2 | ||
|
|
a687aa8e75 | ||
|
|
ed6b89b3b1 | ||
|
|
9d3ca0d0f9 | ||
|
|
05a0405709 | ||
|
|
efd8b70089 | ||
|
|
e12c057c31 | ||
|
|
0b5b18653a | ||
|
|
dc54e7331f | ||
|
|
6fbf6b2986 | ||
|
|
feb9992d7d | ||
|
|
fb4ac82d45 | ||
|
|
acbe8c159b | ||
|
|
63474dd952 | ||
|
|
cc35ed7782 | ||
|
|
d9fd227862 | ||
|
|
1415f2bed7 | ||
|
|
5b07d454b1 | ||
|
|
0c04ba4776 | ||
|
|
b00a936f41 | ||
|
|
5b11c1ca86 | ||
|
|
7802d00031 | ||
|
|
40a15248e8 | ||
|
|
9ba9e82706 | ||
|
|
ea6c33f3d2 | ||
|
|
82e5e1858a | ||
|
|
80b14c0a6f | ||
|
|
6954d0d5f4 | ||
|
|
7e53731fe6 | ||
|
|
c7290e6ccc | ||
|
|
284317cb25 | ||
|
|
311d1a56b4 | ||
|
|
ed589727d6 | ||
|
|
62c9bad183 | ||
|
|
616da8228e | ||
|
|
3a62453b8b | ||
|
|
c3f7829255 | ||
|
|
37d9fb2dad | ||
|
|
4388e72dec | ||
|
|
9803141fe7 | ||
|
|
1f0e9cc1c3 | ||
|
|
92b30ebec6 | ||
|
|
ccadb6a43d | ||
|
|
6f7f540c79 | ||
|
|
d5b8038457 | ||
|
|
0a6059ba13 | ||
|
|
aba5b01fa0 | ||
|
|
09f4943869 | ||
|
|
29c8543f87 | ||
|
|
7bd4940ed8 | ||
|
|
d5116935b5 | ||
|
|
0d320fe29b | ||
|
|
4159461a62 | ||
|
|
f4bd39e3fa | ||
|
|
fbc36a2cfd | ||
|
|
e93ba73adb | ||
|
|
03301f093d | ||
|
|
55a5fa6fb5 | ||
|
|
4d04d10135 | ||
|
|
cda423acab | ||
|
|
0f92678c3b | ||
|
|
8d122f36e3 | ||
|
|
439cdfbb32 | ||
|
|
0a6ab31e10 | ||
|
|
0b6486256d | ||
|
|
da12b93f82 | ||
|
|
6dec6af5dc | ||
|
|
11444621ae | ||
|
|
98f1b3296c | ||
|
|
26c43e7091 | ||
|
|
9b9447858a | ||
|
|
3151cfb064 | ||
|
|
c327fee986 | ||
|
|
a4f53270e8 | ||
|
|
a7456a1126 | ||
|
|
8381512ce4 | ||
|
|
57d968cdcd | ||
|
|
20a669029b | ||
|
|
f2e6c6de58 | ||
|
|
8fa44c3590 | ||
|
|
f5b7c33d4e | ||
|
|
be8e663d39 | ||
|
|
0d4a9748e3 | ||
|
|
bd477f0fb2 | ||
|
|
5317895a5e | ||
|
|
542b8b26ce | ||
|
|
aaca854620 | ||
|
|
64da384fc1 | ||
|
|
a595fc4642 | ||
|
|
ac135be8cd | ||
|
|
ac2d3e2ae0 | ||
|
|
33946af39f | ||
|
|
5ea59a1c4d | ||
|
|
8bafd87b76 | ||
|
|
6b40e9a5e0 | ||
|
|
a2f6fd9298 | ||
|
|
bc604fc9ba | ||
|
|
9baaa13897 | ||
|
|
65e53be8b0 | ||
|
|
7f5283e95d | ||
|
|
ae4ab48ddc | ||
|
|
afccf1da02 | ||
|
|
fc07c7c01f | ||
|
|
aeb906414f | ||
|
|
a6c6b45576 | ||
|
|
13806cce93 | ||
|
|
e7eee0995a | ||
|
|
5687bd09c6 | ||
|
|
f3db895832 | ||
|
|
dd2ffe5d14 | ||
|
|
ec10e784e1 | ||
|
|
649faa1d93 | ||
|
|
669f96b367 | ||
|
|
996821d18e | ||
|
|
2e172b019e | ||
|
|
3df05cd5c1 | ||
|
|
8bb85cdc69 | ||
|
|
9f6e23754c | ||
|
|
5a7cfdffb3 | ||
|
|
caafddfdfa | ||
|
|
ee0e31be97 | ||
|
|
f1da6469a3 | ||
|
|
68e57dd3a7 | ||
|
|
2504311671 | ||
|
|
aa29315624 | ||
|
|
e3bcb87cf0 | ||
|
|
2530dc44c7 | ||
|
|
70a8fe30b7 | ||
|
|
30e538e5ed | ||
|
|
58dbc3c702 | ||
|
|
210c904604 | ||
|
|
27fdab7c8d | ||
|
|
ba3e1abb5e | ||
|
|
ce194e2162 | ||
|
|
595166db8e | ||
|
|
38d9e34a66 | ||
|
|
c1e0977db3 | ||
|
|
b4f32e7645 | ||
|
|
6bb0c95c95 | ||
|
|
4e958c9230 | ||
|
|
64cf1890f2 | ||
|
|
6a857b00db | ||
|
|
6d60a061bc | ||
|
|
6a09ddef18 | ||
|
|
d48e803b7b | ||
|
|
9061b3d8c3 | ||
|
|
2839539c6c | ||
|
|
f77a1798f3 | ||
|
|
664b558a36 | ||
|
|
c1865f127c | ||
|
|
3a69539192 | ||
|
|
cfcaf28ace | ||
|
|
d9e93f3944 | ||
|
|
60470211e5 | ||
|
|
c5851a4a0c | ||
|
|
0c0b2446b7 | ||
|
|
ce9352fd23 | ||
|
|
375ae5fe77 | ||
|
|
665d35196d | ||
|
|
9757f9ae53 | ||
|
|
e45d0c4dcf | ||
|
|
5c9f22bc18 | ||
|
|
d8287e9cdb | ||
|
|
c66e064f42 | ||
|
|
364fc84aaa | ||
|
|
fe4f86bc84 | ||
|
|
982b2e33ff | ||
|
|
8190098bb8 | ||
|
|
c99411311b | ||
|
|
da8a048dce | ||
|
|
b4de495154 | ||
|
|
aaa6af3f38 | ||
|
|
b11b322581 | ||
|
|
60b38215ce | ||
|
|
53e68515dd | ||
|
|
7676ae9184 | ||
|
|
b385feefa5 | ||
|
|
fc50b4abc0 | ||
|
|
0104a2eb3a | ||
|
|
23fdc9d1a9 | ||
|
|
ea4a678308 | ||
|
|
6566c4f15e | ||
|
|
6f39f1740f | ||
|
|
7b61bdbfd2 | ||
|
|
8e65db19b0 | ||
|
|
698fcdad36 | ||
|
|
c25d6e974f | ||
|
|
35aae48932 | ||
|
|
f8afa2703f | ||
|
|
cd903dceb9 | ||
|
|
5843c6f25e | ||
|
|
3005373760 | ||
|
|
7678540a93 | ||
|
|
463666aec5 | ||
|
|
5847f94ece | ||
|
|
09855b76ef | ||
|
|
f4d476d160 | ||
|
|
d88d4be63e | ||
|
|
154114e900 | ||
|
|
03f019dea2 | ||
|
|
a47524b762 | ||
|
|
fd2f5a5ba4 | ||
|
|
e66b2234f6 | ||
|
|
f35b15b09c | ||
|
|
99dac51b9d | ||
|
|
656faf4ce9 | ||
|
|
d9ab6986ad | ||
|
|
514d45c219 | ||
|
|
94b7fc76c1 | ||
|
|
e9923ac257 | ||
|
|
60ad1793e4 | ||
|
|
96a15bec3b | ||
|
|
91b4cadb1b | ||
|
|
fba676fc07 | ||
|
|
9ad14ad98b | ||
|
|
477c62082d | ||
|
|
82169d4115 | ||
|
|
362d5452d5 | ||
|
|
92e5a15399 | ||
|
|
114e0c4ada | ||
|
|
075ff26499 | ||
|
|
d65f2ede81 | ||
|
|
4a9248a451 | ||
|
|
1c6092c430 | ||
|
|
0e9ed1e82f | ||
|
|
02ce0558b9 | ||
|
|
63110f0134 | ||
|
|
d8db4449be | ||
|
|
fda98bbf58 | ||
|
|
aadba1f694 | ||
|
|
2c8d152885 | ||
|
|
0b1a78c028 | ||
|
|
37c598833c | ||
|
|
e382a181f7 | ||
|
|
f02a2c0853 | ||
|
|
71a4cfefd5 | ||
|
|
1c63a70673 | ||
|
|
8022f3b920 | ||
|
|
4db176867b | ||
|
|
b8e1b28958 | ||
|
|
a23f327461 |
38
.github/ISSUE_TEMPLATE/bug-report-or-feature-proposal.md
vendored
Normal file
38
.github/ISSUE_TEMPLATE/bug-report-or-feature-proposal.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
---
|
||||
name: Bug report or feature proposal
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please - if you just have a question (i.e. not a bug report or a feature proposal), post in our [forum](https://meshtastic.discourse.group/) instead.
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Device info:**
|
||||
- Device model: [e.g. TBEAM]
|
||||
- Software Version [e.g. 0.7.8]
|
||||
|
||||
**Smartphone information (if relevant):**
|
||||
- Device: [e.g. iPhone6]
|
||||
- OS: [e.g. iOS8.1]
|
||||
- App Version [e.g. 0.7.2]
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
13
.github/pull_request_template.md
vendored
Normal file
13
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
## Thank you for sending in a pull request, here's some tips to get started!
|
||||
|
||||
(Please delete all these tips and replace with your text)
|
||||
|
||||
- Before starting on some new big chunk of code, it it is optional but highly recommended to open an issue first
|
||||
to say "hey, I think this idea X should be implemented and I'm starting work on it. My general plan is Y, any feedback
|
||||
is appreciated." This will allow other devs to potentially save you time by not accidentially duplicating work etc...
|
||||
- Please do not check in files that don't have real changes
|
||||
- Please do not reformat lines that you didn't have to change the code on
|
||||
- We recommend using the [Visual Studio Code](https://platformio.org/install/ide?install=vscode) editor,
|
||||
because automatically follows our indentation rules and it's auto reformatting will not cause spurious changes to lines.
|
||||
- If your PR fixes a bug, mention "fixes #bugnum" somewhere in your pull request description.
|
||||
- If your other co-developers have comments on your PR please tweak as needed.
|
||||
7
.github/workflows/main.yml
vendored
7
.github/workflows/main.yml
vendored
@@ -9,6 +9,8 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: Checkout submodules
|
||||
uses: textbook/git-checkout-submodule-action@master
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@master
|
||||
with:
|
||||
@@ -17,5 +19,8 @@ jobs:
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
- name: Install extra python tools
|
||||
run: |
|
||||
pip install -U adafruit-nrfutil
|
||||
- name: Build
|
||||
run: platformio run
|
||||
run: platformio run -e tbeam -e heltec -e lora-relay-v1 -e linux
|
||||
|
||||
13
.gitignore
vendored
13
.gitignore
vendored
@@ -7,4 +7,15 @@ main/credentials.h
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
*.code-workspace
|
||||
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
.autotools
|
||||
.built
|
||||
.context
|
||||
.cproject
|
||||
.idea/*
|
||||
.vagrant
|
||||
nanopb*
|
||||
flash.uf2
|
||||
|
||||
14
.vscode/settings.json
vendored
14
.vscode/settings.json
vendored
@@ -47,18 +47,26 @@
|
||||
"memory_resource": "cpp",
|
||||
"optional": "cpp",
|
||||
"string_view": "cpp",
|
||||
"cassert": "cpp"
|
||||
"cassert": "cpp",
|
||||
"iterator": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"iostream": "cpp"
|
||||
},
|
||||
"cSpell.words": [
|
||||
"Blox",
|
||||
"EINK",
|
||||
"HFSR",
|
||||
"Meshtastic",
|
||||
"NEMAGPS",
|
||||
"NMEAGPS",
|
||||
"RDEF",
|
||||
"Ublox",
|
||||
"bkpt",
|
||||
"cfsr",
|
||||
"descs",
|
||||
"ocrypto",
|
||||
"protobufs"
|
||||
]
|
||||
"protobufs",
|
||||
"wifi"
|
||||
],
|
||||
"C_Cpp.dimInactiveRegions": true
|
||||
}
|
||||
17
.vscode/tasks.json
vendored
Normal file
17
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"type": "PlatformIO",
|
||||
"task": "Build",
|
||||
"problemMatcher": [
|
||||
"$platformio"
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": true
|
||||
},
|
||||
"label": "PlatformIO: Build"
|
||||
}
|
||||
]
|
||||
}
|
||||
35
README.md
35
README.md
@@ -22,24 +22,35 @@ This software is 100% open source and developed by a group of hobbyist experimen
|
||||
|
||||
We currently support three models of radios.
|
||||
|
||||
- TTGO T-Beam
|
||||
|
||||
- [T-Beam V1.0 w/ NEO-M8N](https://www.aliexpress.com/item/33047631119.html) (Recommended)
|
||||
- [T-Beam V1.0 w/ NEO-6M](https://www.aliexpress.com/item/33050391850.html)
|
||||
- TTGO T-Beam (usually the recommended choice)
|
||||
- [T-Beam V1.1 w/ NEO-6M - special Meshtastic version](https://www.aliexpress.com/item/4001178678568.html) (Includes built-in OLED display and they have **preinstalled** the meshtastic software)
|
||||
- [T-Beam V1.1 w/ NEO-M8N](https://www.aliexpress.com/item/33047631119.html) (slightly better GPS)
|
||||
- [T-Beam V1.1 w/ NEO-M8N /w SX1262](https://www.aliexpress.com/item/4001287221970.html) (slightly better GPS + LoRa)
|
||||
- board labels "TTGO T22_V1.1 20191212"
|
||||
- [T-Beam V0.7 w/ NEO-6M](https://www.aliexpress.com/item/4000574335430.html) (will work but **you must use the tbeam0.7 firmware ** - but the T-Beam V1.0 or later are better!)
|
||||
- board labels "TTGO T22_V07 20180711"
|
||||
- 3D printable cases
|
||||
- [T-Beam V0](https://www.thingiverse.com/thing:3773717)
|
||||
- [T-Beam V1](https://www.thingiverse.com/thing:3830711)
|
||||
- [T-Beam V1 (SMA-antenna)](https://www.thingiverse.com/thing:3830711)
|
||||
- [T-Beam V1 (IPEX-antenna)](https://www.thingiverse.com/thing:4587297)
|
||||
- Laser-cut cases
|
||||
- [T-Beam V1](https://www.thingiverse.com/thing:4552771)
|
||||
|
||||
- [TTGO LORA32](https://www.aliexpress.com/item/4000211331316.html) - No GPS
|
||||
- version 2.1
|
||||
- board labels "TTGO T3_V1.6 20180606"
|
||||
- 3D printable case
|
||||
- [TTGO LORA32 v1](https://www.thingiverse.com/thing:3385109)
|
||||
|
||||
- [Heltec LoRa 32](https://heltec.org/project/wifi-lora-32/) - No GPS
|
||||
- [3D Printable case](https://www.thingiverse.com/thing:3125854)
|
||||
|
||||
**Make sure to get the frequency for your country**
|
||||
|
||||
- US/JP/AU/NZ - 915MHz
|
||||
- US/JP/AU/NZ/CA - 915MHz
|
||||
- CN - 470MHz
|
||||
- EU - 868MHz, 433MHz
|
||||
- full list of LoRa frequencies per region is available [here](https://www.thethingsnetwork.org/docs/lorawan/frequencies-by-country.html)
|
||||
|
||||
Getting a version that includes a screen is optional, but highly recommended.
|
||||
|
||||
@@ -47,6 +58,8 @@ Getting a version that includes a screen is optional, but highly recommended.
|
||||
|
||||
Prebuilt binaries for the supported radios are available in our [releases](https://github.com/meshtastic/Meshtastic-esp32/releases). Your initial installation has to happen over USB from your Mac, Windows or Linux PC. Once our software is installed, all future software updates happen over bluetooth from your phone.
|
||||
|
||||
Be **very careful** to install the correct load for your board. In particular the popular 'T-BEAM' radio from TTGO is not called 'TTGO-Lora' (that is a different board). So don't install the 'TTGO-Lora' build on a TBEAM, it won't work correctly.
|
||||
|
||||
Please post comments on our [group chat](https://meshtastic.discourse.group/) if you have problems or successes.
|
||||
|
||||
### Installing from a GUI - Windows and Mac
|
||||
@@ -90,10 +103,10 @@ Hard resetting via RTS pin...
|
||||
```
|
||||
|
||||
5. cd into the directory where the release zip file was expanded.
|
||||
6. Install the correct firmware for your board with `device-install.sh firmware-_board_-_country_.bin`.
|
||||
- Example: `./device-install.sh firmware-HELTEC-US-0.0.3.bin`.
|
||||
7. To update run `device-update.sh firmware-_board_-_country_.bin`
|
||||
- Example: `./device-update.sh firmware-HELTEC-US-0.0.3.bin`.
|
||||
6. Install the correct firmware for your board with `device-install.sh -f firmware-_board_-_country_.bin`.
|
||||
- Example: `./device-install.sh -f firmware-HELTEC-US-0.0.3.bin`.
|
||||
7. To update run `device-update.sh -f firmware-_board_-_country_.bin`
|
||||
- Example: `./device-update.sh -f firmware-HELTEC-US-0.0.3.bin`.
|
||||
|
||||
Note: If you have previously installed meshtastic, you don't need to run this full script instead just run `esptool.py --baud 921600 write_flash 0x10000 firmware-_board_-_country_-_version_.bin`. This will be faster, also all of your current preferences will be preserved.
|
||||
|
||||
@@ -168,7 +181,7 @@ Hard resetting via RTS pin...
|
||||
|
||||
# Meshtastic Android app
|
||||
|
||||
The companion (optional) Meshtastic Android app is [here](https://github.com/meshtastic/Meshtastic-Android). You can also download it on Google Play.
|
||||
The companion (optional) Meshtastic Android app is [here](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dgithub-dev-readme). You can also download it on Google Play.
|
||||
|
||||
# Python API
|
||||
|
||||
|
||||
@@ -2,14 +2,17 @@
|
||||
|
||||
set -e
|
||||
|
||||
source bin/version.sh
|
||||
VERSION=`bin/buildinfo.py`
|
||||
|
||||
COUNTRIES="US EU433 EU865 CN JP"
|
||||
COUNTRIES="US EU433 EU865 CN JP ANZ KR"
|
||||
#COUNTRIES=US
|
||||
#COUNTRIES=CN
|
||||
|
||||
BOARDS="ttgo-lora32-v2 ttgo-lora32-v1 tbeam heltec"
|
||||
#BOARDS=tbeam
|
||||
BOARDS_ESP32="tlora-v2 tlora-v1 tlora-v2-1-1.6 tbeam heltec tbeam0.7"
|
||||
#BOARDS_ESP32=tbeam
|
||||
|
||||
# FIXME note nrf52840dk build is for some reason only generating a BIN file but not a HEX file nrf52840dk-geeksville is fine
|
||||
BOARDS_NRF52="lora-relay-v1"
|
||||
|
||||
OUTDIR=release/latest
|
||||
|
||||
@@ -18,25 +21,61 @@ ARCHIVEDIR=release/archive
|
||||
|
||||
rm -f $OUTDIR/firmware*
|
||||
|
||||
mkdir -p $OUTDIR/bins $OUTDIR/elfs
|
||||
rm -f $OUTDIR/bins/*
|
||||
mkdir -p $OUTDIR/bins
|
||||
rm -r $OUTDIR/bins/*
|
||||
mkdir -p $OUTDIR/bins/universal $OUTDIR/elfs/universal
|
||||
|
||||
# build the named environment and copy the bins to the release directory
|
||||
function do_build {
|
||||
ENV_NAME=$1
|
||||
echo "Building for $ENV_NAME with $PLATFORMIO_BUILD_FLAGS"
|
||||
SRCBIN=.pio/build/$ENV_NAME/firmware.bin
|
||||
SRCELF=.pio/build/$ENV_NAME/firmware.elf
|
||||
rm -f $SRCBIN
|
||||
function do_build() {
|
||||
BOARD=$1
|
||||
COUNTRY=$2
|
||||
isNrf=$3
|
||||
|
||||
echo "Building $COUNTRY for $BOARD with $PLATFORMIO_BUILD_FLAGS"
|
||||
rm -f .pio/build/$BOARD/firmware.*
|
||||
|
||||
# The shell vars the build tool expects to find
|
||||
export HW_VERSION="1.0-$COUNTRY"
|
||||
export APP_VERSION=$VERSION
|
||||
export COUNTRY
|
||||
|
||||
pio run --jobs 4 --environment $ENV_NAME # -v
|
||||
cp $SRCBIN $OUTDIR/bins/firmware-$ENV_NAME-$COUNTRY-$VERSION.bin
|
||||
cp $SRCELF $OUTDIR/elfs/firmware-$ENV_NAME-$COUNTRY-$VERSION.elf
|
||||
# Are we building a universal/regionless rom?
|
||||
if [ "x$COUNTRY" != "x" ]
|
||||
then
|
||||
export HW_VERSION="1.0-$COUNTRY"
|
||||
export COUNTRY
|
||||
basename=firmware-$BOARD-$COUNTRY-$VERSION
|
||||
else
|
||||
export HW_VERSION="1.0"
|
||||
unset COUNTRY
|
||||
basename=universal/firmware-$BOARD-$VERSION
|
||||
fi
|
||||
|
||||
pio run --jobs 4 --environment $BOARD # -v
|
||||
SRCELF=.pio/build/$BOARD/firmware.elf
|
||||
cp $SRCELF $OUTDIR/elfs/$basename.elf
|
||||
|
||||
if [ "$isNrf" = "false" ]
|
||||
then
|
||||
echo "Copying ESP32 bin file"
|
||||
SRCBIN=.pio/build/$BOARD/firmware.bin
|
||||
cp $SRCBIN $OUTDIR/bins/$basename.bin
|
||||
else
|
||||
echo "Generating NRF52 uf2 file"
|
||||
SRCHEX=.pio/build/$BOARD/firmware.hex
|
||||
bin/uf2conv.py $SRCHEX -c -o $OUTDIR/bins/$basename.uf2 -f 0xADA52840
|
||||
fi
|
||||
}
|
||||
|
||||
function do_boards() {
|
||||
declare boards=$1
|
||||
declare isNrf=$2
|
||||
for board in $boards; do
|
||||
for country in $COUNTRIES; do
|
||||
do_build $board $country "$isNrf"
|
||||
done
|
||||
|
||||
# Build universal
|
||||
do_build $board "" "$isNrf"
|
||||
done
|
||||
}
|
||||
|
||||
# Make sure our submodules are current
|
||||
@@ -45,14 +84,20 @@ git submodule update
|
||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||
platformio lib update
|
||||
|
||||
for COUNTRY in $COUNTRIES; do
|
||||
for BOARD in $BOARDS; do
|
||||
do_build $BOARD
|
||||
done
|
||||
done
|
||||
do_boards "$BOARDS_ESP32" "false"
|
||||
do_boards "$BOARDS_NRF52" "true"
|
||||
|
||||
echo "Building SPIFFS for ESP32 targets"
|
||||
pio run --environment tbeam -t buildfs
|
||||
cp .pio/build/tbeam/spiffs.bin $OUTDIR/bins/universal/spiffs-$VERSION.bin
|
||||
|
||||
# keep the bins in archive also
|
||||
cp $OUTDIR/bins/firmware* $OUTDIR/elfs/firmware* $ARCHIVEDIR
|
||||
cp $OUTDIR/bins/firmware* $OUTDIR/bins/universal/spiffs* $OUTDIR/elfs/firmware* $OUTDIR/bins/universal/firmware* $OUTDIR/elfs/universal/firmware* $ARCHIVEDIR
|
||||
|
||||
echo Updating android bins $OUTDIR/forandroid
|
||||
rm -rf $OUTDIR/forandroid
|
||||
mkdir -p $OUTDIR/forandroid
|
||||
cp -a $OUTDIR/bins/universal/*.bin $OUTDIR/forandroid/
|
||||
|
||||
cat >$OUTDIR/curfirmwareversion.xml <<XML
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
@@ -66,7 +111,8 @@ Generated by bin/buildall.sh -->
|
||||
</resources>
|
||||
XML
|
||||
|
||||
echo Generating $ARCHIVEDIR/firmware-$VERSION.zip
|
||||
rm -f $ARCHIVEDIR/firmware-$VERSION.zip
|
||||
zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $OUTDIR/bins/firmware-*-$VERSION.* images/system-info.bin bin/device-install.sh bin/device-update.sh
|
||||
zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $ARCHIVEDIR/spiffs-$VERSION.bin $OUTDIR/bins/firmware-*-$VERSION.* images/system-info.bin bin/device-install.sh bin/device-update.sh
|
||||
|
||||
echo BUILT ALL
|
||||
|
||||
11
bin/buildinfo.py
Executable file
11
bin/buildinfo.py
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env python3
|
||||
import configparser
|
||||
|
||||
config = configparser.RawConfigParser()
|
||||
config.read('version.properties')
|
||||
|
||||
version = dict(config.items('VERSION'))
|
||||
|
||||
verStr = "{}.{}.{}".format(version["major"], version["minor"], version["build"])
|
||||
|
||||
print(f"{verStr}")
|
||||
@@ -1,11 +1,48 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
FILENAME=$1
|
||||
# Usage info
|
||||
show_help() {
|
||||
cat << EOF
|
||||
Usage: ${0##*/} [-h] [-p ESPTOOL_PORT] [-f FILENAME]
|
||||
Flash image file to device, but first erasing and writing system information"
|
||||
|
||||
echo "Trying to flash $FILENAME, but first erasing and writing system information"
|
||||
esptool.py --baud 921600 erase_flash
|
||||
esptool.py --baud 921600 write_flash 0x1000 system-info.bin
|
||||
esptool.py --baud 921600 write_flash 0x10000 $FILENAME
|
||||
-h Display this help and exit
|
||||
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous).
|
||||
-f FILENAME The .bin file to flash. Custom to your device type and region.
|
||||
EOF
|
||||
}
|
||||
|
||||
|
||||
while getopts ":h:p:f:" opt; do
|
||||
case "${opt}" in
|
||||
h)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
p) export ESPTOOL_PORT=${OPTARG}
|
||||
;;
|
||||
f) FILENAME=${OPTARG}
|
||||
;;
|
||||
*)
|
||||
echo "Invalid flag."
|
||||
show_help >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift "$((OPTIND-1))"
|
||||
|
||||
if [ -f "${FILENAME}" ]; then
|
||||
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
||||
esptool.py --baud 921600 erase_flash
|
||||
esptool.py --baud 921600 write_flash 0x1000 system-info.bin
|
||||
esptool.py --baud 921600 write_flash 0x00390000 spiffs-*.bin
|
||||
esptool.py --baud 921600 write_flash 0x10000 ${FILENAME}
|
||||
else
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
show_help
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -1,8 +1,43 @@
|
||||
#!/bin/bash
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
# Usage info
|
||||
show_help() {
|
||||
cat << EOF
|
||||
Usage: ${0##*/} [-h] [-p ESPTOOL_PORT] -f FILENAME
|
||||
Flash image file to device, leave existing system intact."
|
||||
|
||||
FILENAME=$1
|
||||
-h Display this help and exit
|
||||
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous).
|
||||
-f FILENAME The .bin file to flash. Custom to your device type and region.
|
||||
EOF
|
||||
}
|
||||
|
||||
echo "Trying to update $FILENAME"
|
||||
esptool.py --baud 921600 write_flash 0x10000 $FILENAME
|
||||
|
||||
while getopts ":h:p:f:" opt; do
|
||||
case "${opt}" in
|
||||
h)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
p) export ESPTOOL_PORT=${OPTARG}
|
||||
;;
|
||||
f) FILENAME=${OPTARG}
|
||||
;;
|
||||
*)
|
||||
echo "Invalid flag."
|
||||
show_help >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift "$((OPTIND-1))"
|
||||
|
||||
if [ -f "${FILENAME}" ]; then
|
||||
echo "Trying to flash update ${FILENAME}."
|
||||
esptool.py --baud 921600 write_flash 0x10000 ${FILENAME}
|
||||
else
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
show_help
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
3
bin/dump-ram-users.sh
Executable file
3
bin/dump-ram-users.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
arm-none-eabi-readelf -s -e .pio/build/nrf52dk/firmware.elf | head -80
|
||||
|
||||
nm -CSr --size-sort .pio/build/nrf52dk/firmware.elf | grep '^200'
|
||||
35
bin/install-bootloader.sh
Executable file
35
bin/install-bootloader.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
# You probably don't want to use this script, it programs a custom bootloader build onto a nrf52 board
|
||||
|
||||
set -e
|
||||
|
||||
# dependencies
|
||||
# apt install srecord
|
||||
|
||||
BOOTDIR=/home/kevinh/development/meshtastic/Adafruit_nRF52_Bootloader
|
||||
BOARD=othernet_ppr1
|
||||
BOOTVER=0.3.2
|
||||
BOOTNUM=128
|
||||
BOOTSHA=gc01b9ea
|
||||
SDCODE=s113
|
||||
SDVER=7.2.0
|
||||
PROJ=ppr1
|
||||
|
||||
# FIXME for nRF52840 use 0xff000, for nRF52833 use 0x7f000
|
||||
BOOTSET=0x7f000
|
||||
|
||||
nrfjprog --eraseall -f nrf52
|
||||
|
||||
# this generates an intel hex file that can be programmed into a NRF52 to tell the adafruit bootloader that the current app image is valid
|
||||
# Bootloader settings are at BOOTLOADER_SETTINGS (rw) : ORIGIN = 0xFF000, LENGTH = 0x1000
|
||||
# first 4 bytes should be 0x01 to indicate valid app image
|
||||
# second 4 bytes should be 0x00 to indicate no CRC required for image
|
||||
echo "01 00 00 00 00 00 00 00" | xxd -r -p - >/tmp/bootconf.bin
|
||||
srec_cat /tmp/bootconf.bin -binary -offset $BOOTSET -output /tmp/bootconf.hex -intel
|
||||
|
||||
echo Generating merged hex file from .pio/build/$PROJ/firmware.hex
|
||||
mergehex -o ${BOARD}_full.hex -m $BOOTDIR/_build/build-$BOARD/${BOARD}_bootloader-$BOOTVER-$BOOTNUM-$BOOTSHA-dirty_${SDCODE}_$SDVER.hex .pio/build/$PROJ/firmware.hex /tmp/bootconf.hex
|
||||
|
||||
echo Telling bootloader app region is valid and telling CPU to run
|
||||
nrfjprog --program ${BOARD}_full.hex -f nrf52 --reset
|
||||
|
||||
# nrfjprog --readuicr /tmp/uicr.hex; objdump -s /tmp/uicr.hex | less
|
||||
22
bin/install-eink.sh
Executable file
22
bin/install-eink.sh
Executable file
@@ -0,0 +1,22 @@
|
||||
# You probably don't want to use this script, it programs a custom bootloader build onto a nrf52 board
|
||||
|
||||
set -e
|
||||
|
||||
BOOTDIR=/home/kevinh/development/meshtastic/Adafruit_nRF52_Bootloader
|
||||
|
||||
nrfjprog --eraseall -f nrf52
|
||||
|
||||
# this generates an intel hex file that can be programmed into a NRF52 to tell the adafruit bootloader that the current app image is valid
|
||||
# Bootloader settings are at BOOTLOADER_SETTINGS (rw) : ORIGIN = 0xFF000, LENGTH = 0x1000
|
||||
# first 4 bytes should be 0x01 to indicate valid app image
|
||||
# second 4 bytes should be 0x00 to indicate no CRC required for image
|
||||
echo "01 00 00 00 00 00 00 00" | xxd -r -p - >/tmp/bootconf.bin
|
||||
srec_cat /tmp/bootconf.bin -binary -offset 0xff000 -output /tmp/bootconf.hex -intel
|
||||
|
||||
echo Generating merged hex file
|
||||
mergehex -m $BOOTDIR/_build/build-ttgo_eink/ttgo_eink_bootloader-0.3.2-125-gf38f8f4-dirty_s140_6.1.1.hex .pio/build/eink/firmware.hex /tmp/bootconf.hex -o ttgo_eink_full.hex
|
||||
|
||||
echo Telling bootloader app region is valid and telling CPU to run
|
||||
nrfjprog --program ttgo_eink_full.hex -f nrf52 --reset
|
||||
|
||||
# nrfjprog --readuicr /tmp/uicr.hex; objdump -s /tmp/uicr.hex | less
|
||||
3
bin/nrf52832-gdbserver.sh
Executable file
3
bin/nrf52832-gdbserver.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52832_XXAA
|
||||
3
bin/nrf52833-gdbserver.sh
Executable file
3
bin/nrf52833-gdbserver.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
JLinkGDBServerCLExe -if SWD -select USB -port 2331 -device NRF52833_XXAA
|
||||
16
bin/platformio-custom.py
Normal file
16
bin/platformio-custom.py
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
Import("projenv")
|
||||
|
||||
import configparser
|
||||
prefsLoc = projenv["PROJECT_DIR"] + "/version.properties"
|
||||
config = configparser.RawConfigParser()
|
||||
config.read(prefsLoc)
|
||||
version = dict(config.items('VERSION'))
|
||||
verStr = "{}.{}.{}".format(version["major"], version["minor"], version["build"])
|
||||
|
||||
print(f"Using meshtastic platform-custom.py, firmare version {verStr}")
|
||||
|
||||
# General options that are passed to the C and C++ compilers
|
||||
projenv.Append(CCFLAGS=[
|
||||
f"-DAPP_VERSION={verStr}"
|
||||
])
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
set -e
|
||||
|
||||
source bin/version.sh
|
||||
VERSION=`bin/buildinfo.py`
|
||||
|
||||
esptool.py --baud 921600 write_flash 0x10000 release/latest/bins/firmware-tbeam-US-$VERSION.bin
|
||||
|
||||
6
bin/program-release-universal.sh
Executable file
6
bin/program-release-universal.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
|
||||
set -e
|
||||
|
||||
source bin/version.sh
|
||||
|
||||
esptool.py --baud 921600 write_flash 0x10000 release/latest/bins/universal/firmware-tbeam-$VERSION.bin
|
||||
6
bin/qspi-flash-test.sh
Executable file
6
bin/qspi-flash-test.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
# You probably don't need this - it is a basic test of the serial flash on the TTGO eink board
|
||||
|
||||
nrfjprog -qspiini nrf52/ttgo_eink_qpsi.ini --qspieraseall
|
||||
nrfjprog --qspiini nrf52/ttgo_eink_qpsi.ini --memwr 0x12000000 --val 0xdeadbeef --verify
|
||||
nrfjprog --qspiini nrf52/ttgo_eink_qpsi.ini --readqspi spi.hex
|
||||
objdump -s spi.hex | less
|
||||
@@ -1,6 +1,15 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.1"
|
||||
set -e
|
||||
|
||||
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.4 to be located in the"
|
||||
echo "meshtastic-device root directory if the following step fails, you should download the correct"
|
||||
echo "prebuilt binaries for your computer into nanopb-0.4.4"
|
||||
|
||||
# the nanopb tool seems to require that the .options file be in the current directory!
|
||||
cd proto
|
||||
../../nanopb-0.4.1-linux-x86/generator-bin/protoc --nanopb_out=-v:../src/mesh -I=../proto mesh.proto
|
||||
../nanopb-0.4.4/generator-bin/protoc --nanopb_out=-v:../src/mesh -I=../proto *.proto
|
||||
|
||||
echo "Regenerating protobuf documentation - if you see an error message"
|
||||
echo "you can ignore it unless doing a new protobuf release to github."
|
||||
bin/regen-docs.sh
|
||||
314
bin/uf2conv.py
Executable file
314
bin/uf2conv.py
Executable file
@@ -0,0 +1,314 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import struct
|
||||
import subprocess
|
||||
import re
|
||||
import os
|
||||
import os.path
|
||||
import argparse
|
||||
|
||||
|
||||
UF2_MAGIC_START0 = 0x0A324655 # "UF2\n"
|
||||
UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected
|
||||
UF2_MAGIC_END = 0x0AB16F30 # Ditto
|
||||
|
||||
families = {
|
||||
'SAMD21': 0x68ed2b88,
|
||||
'SAML21': 0x1851780a,
|
||||
'SAMD51': 0x55114460,
|
||||
'NRF52': 0x1b57745f,
|
||||
'STM32F0': 0x647824b6,
|
||||
'STM32F1': 0x5ee21072,
|
||||
'STM32F2': 0x5d1a0a2e,
|
||||
'STM32F3': 0x6b846188,
|
||||
'STM32F4': 0x57755a57,
|
||||
'STM32F7': 0x53b80f00,
|
||||
'STM32G0': 0x300f5633,
|
||||
'STM32G4': 0x4c71240a,
|
||||
'STM32H7': 0x6db66082,
|
||||
'STM32L0': 0x202e3a91,
|
||||
'STM32L1': 0x1e1f432d,
|
||||
'STM32L4': 0x00ff6919,
|
||||
'STM32L5': 0x04240bdf,
|
||||
'STM32WB': 0x70d16653,
|
||||
'STM32WL': 0x21460ff0,
|
||||
'ATMEGA32': 0x16573617,
|
||||
'MIMXRT10XX': 0x4FB2D5BD
|
||||
}
|
||||
|
||||
INFO_FILE = "/INFO_UF2.TXT"
|
||||
|
||||
appstartaddr = 0x2000
|
||||
familyid = 0x0
|
||||
|
||||
|
||||
def is_uf2(buf):
|
||||
w = struct.unpack("<II", buf[0:8])
|
||||
return w[0] == UF2_MAGIC_START0 and w[1] == UF2_MAGIC_START1
|
||||
|
||||
def is_hex(buf):
|
||||
try:
|
||||
w = buf[0:30].decode("utf-8")
|
||||
except UnicodeDecodeError:
|
||||
return False
|
||||
if w[0] == ':' and re.match(b"^[:0-9a-fA-F\r\n]+$", buf):
|
||||
return True
|
||||
return False
|
||||
|
||||
def convert_from_uf2(buf):
|
||||
global appstartaddr
|
||||
numblocks = len(buf) // 512
|
||||
curraddr = None
|
||||
outp = b""
|
||||
for blockno in range(numblocks):
|
||||
ptr = blockno * 512
|
||||
block = buf[ptr:ptr + 512]
|
||||
hd = struct.unpack(b"<IIIIIIII", block[0:32])
|
||||
if hd[0] != UF2_MAGIC_START0 or hd[1] != UF2_MAGIC_START1:
|
||||
print("Skipping block at " + ptr + "; bad magic")
|
||||
continue
|
||||
if hd[2] & 1:
|
||||
# NO-flash flag set; skip block
|
||||
continue
|
||||
datalen = hd[4]
|
||||
if datalen > 476:
|
||||
assert False, "Invalid UF2 data size at " + ptr
|
||||
newaddr = hd[3]
|
||||
if curraddr == None:
|
||||
appstartaddr = newaddr
|
||||
curraddr = newaddr
|
||||
padding = newaddr - curraddr
|
||||
if padding < 0:
|
||||
assert False, "Block out of order at " + ptr
|
||||
if padding > 10*1024*1024:
|
||||
assert False, "More than 10M of padding needed at " + ptr
|
||||
if padding % 4 != 0:
|
||||
assert False, "Non-word padding size at " + ptr
|
||||
while padding > 0:
|
||||
padding -= 4
|
||||
outp += b"\x00\x00\x00\x00"
|
||||
outp += block[32 : 32 + datalen]
|
||||
curraddr = newaddr + datalen
|
||||
return outp
|
||||
|
||||
def convert_to_carray(file_content):
|
||||
outp = "const unsigned char bindata[] __attribute__((aligned(16))) = {"
|
||||
for i in range(len(file_content)):
|
||||
if i % 16 == 0:
|
||||
outp += "\n"
|
||||
outp += "0x%02x, " % ord(file_content[i])
|
||||
outp += "\n};\n"
|
||||
return outp
|
||||
|
||||
def convert_to_uf2(file_content):
|
||||
global familyid
|
||||
datapadding = b""
|
||||
while len(datapadding) < 512 - 256 - 32 - 4:
|
||||
datapadding += b"\x00\x00\x00\x00"
|
||||
numblocks = (len(file_content) + 255) // 256
|
||||
outp = b""
|
||||
for blockno in range(numblocks):
|
||||
ptr = 256 * blockno
|
||||
chunk = file_content[ptr:ptr + 256]
|
||||
flags = 0x0
|
||||
if familyid:
|
||||
flags |= 0x2000
|
||||
hd = struct.pack(b"<IIIIIIII",
|
||||
UF2_MAGIC_START0, UF2_MAGIC_START1,
|
||||
flags, ptr + appstartaddr, 256, blockno, numblocks, familyid)
|
||||
while len(chunk) < 256:
|
||||
chunk += b"\x00"
|
||||
block = hd + chunk + datapadding + struct.pack(b"<I", UF2_MAGIC_END)
|
||||
assert len(block) == 512
|
||||
outp += block
|
||||
return outp
|
||||
|
||||
class Block:
|
||||
def __init__(self, addr):
|
||||
self.addr = addr
|
||||
self.bytes = bytearray(256)
|
||||
|
||||
def encode(self, blockno, numblocks):
|
||||
global familyid
|
||||
flags = 0x0
|
||||
if familyid:
|
||||
flags |= 0x2000
|
||||
hd = struct.pack("<IIIIIIII",
|
||||
UF2_MAGIC_START0, UF2_MAGIC_START1,
|
||||
flags, self.addr, 256, blockno, numblocks, familyid)
|
||||
hd += self.bytes[0:256]
|
||||
while len(hd) < 512 - 4:
|
||||
hd += b"\x00"
|
||||
hd += struct.pack("<I", UF2_MAGIC_END)
|
||||
return hd
|
||||
|
||||
def convert_from_hex_to_uf2(buf):
|
||||
global appstartaddr
|
||||
appstartaddr = None
|
||||
upper = 0
|
||||
currblock = None
|
||||
blocks = []
|
||||
for line in buf.split('\n'):
|
||||
if line[0] != ":":
|
||||
continue
|
||||
i = 1
|
||||
rec = []
|
||||
while i < len(line) - 1:
|
||||
rec.append(int(line[i:i+2], 16))
|
||||
i += 2
|
||||
tp = rec[3]
|
||||
if tp == 4:
|
||||
upper = ((rec[4] << 8) | rec[5]) << 16
|
||||
elif tp == 2:
|
||||
upper = ((rec[4] << 8) | rec[5]) << 4
|
||||
assert (upper & 0xffff) == 0
|
||||
elif tp == 1:
|
||||
break
|
||||
elif tp == 0:
|
||||
addr = upper | (rec[1] << 8) | rec[2]
|
||||
if appstartaddr == None:
|
||||
appstartaddr = addr
|
||||
i = 4
|
||||
while i < len(rec) - 1:
|
||||
if not currblock or currblock.addr & ~0xff != addr & ~0xff:
|
||||
currblock = Block(addr & ~0xff)
|
||||
blocks.append(currblock)
|
||||
currblock.bytes[addr & 0xff] = rec[i]
|
||||
addr += 1
|
||||
i += 1
|
||||
numblocks = len(blocks)
|
||||
resfile = b""
|
||||
for i in range(0, numblocks):
|
||||
resfile += blocks[i].encode(i, numblocks)
|
||||
return resfile
|
||||
|
||||
def to_str(b):
|
||||
return b.decode("utf-8")
|
||||
|
||||
def get_drives():
|
||||
drives = []
|
||||
if sys.platform == "win32":
|
||||
r = subprocess.check_output(["wmic", "PATH", "Win32_LogicalDisk",
|
||||
"get", "DeviceID,", "VolumeName,",
|
||||
"FileSystem,", "DriveType"])
|
||||
for line in to_str(r).split('\n'):
|
||||
words = re.split('\s+', line)
|
||||
if len(words) >= 3 and words[1] == "2" and words[2] == "FAT":
|
||||
drives.append(words[0])
|
||||
else:
|
||||
rootpath = "/media"
|
||||
if sys.platform == "darwin":
|
||||
rootpath = "/Volumes"
|
||||
elif sys.platform == "linux":
|
||||
tmp = rootpath + "/" + os.environ["USER"]
|
||||
if os.path.isdir(tmp):
|
||||
rootpath = tmp
|
||||
for d in os.listdir(rootpath):
|
||||
drives.append(os.path.join(rootpath, d))
|
||||
|
||||
|
||||
def has_info(d):
|
||||
try:
|
||||
return os.path.isfile(d + INFO_FILE)
|
||||
except:
|
||||
return False
|
||||
|
||||
return list(filter(has_info, drives))
|
||||
|
||||
|
||||
def board_id(path):
|
||||
with open(path + INFO_FILE, mode='r') as file:
|
||||
file_content = file.read()
|
||||
return re.search("Board-ID: ([^\r\n]*)", file_content).group(1)
|
||||
|
||||
|
||||
def list_drives():
|
||||
for d in get_drives():
|
||||
print(d, board_id(d))
|
||||
|
||||
|
||||
def write_file(name, buf):
|
||||
with open(name, "wb") as f:
|
||||
f.write(buf)
|
||||
print("Wrote %d bytes to %s" % (len(buf), name))
|
||||
|
||||
|
||||
def main():
|
||||
global appstartaddr, familyid
|
||||
def error(msg):
|
||||
print(msg)
|
||||
sys.exit(1)
|
||||
parser = argparse.ArgumentParser(description='Convert to UF2 or flash directly.')
|
||||
parser.add_argument('input', metavar='INPUT', type=str, nargs='?',
|
||||
help='input file (HEX, BIN or UF2)')
|
||||
parser.add_argument('-b' , '--base', dest='base', type=str,
|
||||
default="0x2000",
|
||||
help='set base address of application for BIN format (default: 0x2000)')
|
||||
parser.add_argument('-o' , '--output', metavar="FILE", dest='output', type=str,
|
||||
help='write output to named file; defaults to "flash.uf2" or "flash.bin" where sensible')
|
||||
parser.add_argument('-d' , '--device', dest="device_path",
|
||||
help='select a device path to flash')
|
||||
parser.add_argument('-l' , '--list', action='store_true',
|
||||
help='list connected devices')
|
||||
parser.add_argument('-c' , '--convert', action='store_true',
|
||||
help='do not flash, just convert')
|
||||
parser.add_argument('-D' , '--deploy', action='store_true',
|
||||
help='just flash, do not convert')
|
||||
parser.add_argument('-f' , '--family', dest='family', type=str,
|
||||
default="0x0",
|
||||
help='specify familyID - number or name (default: 0x0)')
|
||||
parser.add_argument('-C' , '--carray', action='store_true',
|
||||
help='convert binary file to a C array, not UF2')
|
||||
args = parser.parse_args()
|
||||
appstartaddr = int(args.base, 0)
|
||||
|
||||
if args.family.upper() in families:
|
||||
familyid = families[args.family.upper()]
|
||||
else:
|
||||
try:
|
||||
familyid = int(args.family, 0)
|
||||
except ValueError:
|
||||
error("Family ID needs to be a number or one of: " + ", ".join(families.keys()))
|
||||
|
||||
if args.list:
|
||||
list_drives()
|
||||
else:
|
||||
if not args.input:
|
||||
error("Need input file")
|
||||
with open(args.input, mode='rb') as f:
|
||||
inpbuf = f.read()
|
||||
from_uf2 = is_uf2(inpbuf)
|
||||
ext = "uf2"
|
||||
if args.deploy:
|
||||
outbuf = inpbuf
|
||||
elif from_uf2:
|
||||
outbuf = convert_from_uf2(inpbuf)
|
||||
ext = "bin"
|
||||
elif is_hex(inpbuf):
|
||||
outbuf = convert_from_hex_to_uf2(inpbuf.decode("utf-8"))
|
||||
elif args.carray:
|
||||
outbuf = convert_to_carray(inpbuf)
|
||||
ext = "h"
|
||||
else:
|
||||
outbuf = convert_to_uf2(inpbuf)
|
||||
print("Converting to %s, output size: %d, start address: 0x%x" %
|
||||
(ext, len(outbuf), appstartaddr))
|
||||
if args.convert or ext != "uf2":
|
||||
drives = []
|
||||
if args.output == None:
|
||||
args.output = "flash." + ext
|
||||
else:
|
||||
drives = get_drives()
|
||||
|
||||
if args.output:
|
||||
write_file(args.output, outbuf)
|
||||
else:
|
||||
if len(drives) == 0:
|
||||
error("No drive to deploy.")
|
||||
for d in drives:
|
||||
print("Flashing %s (%s)" % (d, board_id(d)))
|
||||
write_file(d + "/NEW.UF2", outbuf)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
4
bin/upload-to-bootloader.sh
Executable file
4
bin/upload-to-bootloader.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
|
||||
echo "Converting to uf2 for NRF52 Adafruit bootloader"
|
||||
bin/uf2conv.py .pio/build/lora-relay-v2/firmware.hex -f 0xADA52840
|
||||
# cp flash.uf2 /media/kevinh/FTH*BOOT/
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
|
||||
export VERSION=0.7.5
|
||||
2
bin/view-map.sh
Executable file
2
bin/view-map.sh
Executable file
@@ -0,0 +1,2 @@
|
||||
echo using amap tool to display memory map
|
||||
amap .pio/build/output.map
|
||||
61
boards/eink.json
Normal file
61
boards/eink.json
Normal file
@@ -0,0 +1,61 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_TTGO_EINK -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
[
|
||||
"0x239A",
|
||||
"0x4405"
|
||||
]
|
||||
],
|
||||
"usb_product": "TTGO_eink",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "eink",
|
||||
"variants_dir": "variants",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": [
|
||||
"bluetooth"
|
||||
],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"onboard_tools": [
|
||||
"jlink"
|
||||
],
|
||||
"svd_path": "nrf52840.svd"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"name": "TTGO eink (Adafruit BSP)",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "jlink",
|
||||
"protocols": [
|
||||
"jlink",
|
||||
"nrfjprog",
|
||||
"stlink"
|
||||
]
|
||||
},
|
||||
"url": "FIXME",
|
||||
"vendor": "TTGO"
|
||||
}
|
||||
46
boards/lora-relay-v1.json
Normal file
46
boards/lora-relay-v1.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_LORA_RELAY_V1 -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x239A", "0x4404"]],
|
||||
"usb_product": "LORA_RELAY",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "lora_relay_v1",
|
||||
"variants_dir": "variants",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"onboard_tools": ["jlink"],
|
||||
"svd_path": "nrf52840.svd"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "Meshtastic Lora Relay V1 (Adafruit BSP)",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "jlink",
|
||||
"protocols": ["jlink", "nrfjprog", "stlink"]
|
||||
},
|
||||
"url": "https://github.com/BigCorvus/SX1262-LoRa-BLE-Relay",
|
||||
"vendor": "BigCorvus"
|
||||
}
|
||||
46
boards/lora-relay-v2.json
Normal file
46
boards/lora-relay-v2.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_LORA_RELAY_V2 -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x239A", "0x4406"]],
|
||||
"usb_product": "LORA_RELAY",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "lora_relay_v2",
|
||||
"variants_dir": "variants",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"onboard_tools": ["jlink"],
|
||||
"svd_path": "nrf52840.svd"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "Meshtastic Lora Relay V1 (Adafruit BSP)",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "jlink",
|
||||
"protocols": ["jlink", "nrfjprog", "stlink"]
|
||||
},
|
||||
"url": "https://github.com/BigCorvus/SX1262-LoRa-BLE-Relay",
|
||||
"vendor": "BigCorvus"
|
||||
}
|
||||
47
boards/nrf52840_dk.json
Normal file
47
boards/nrf52840_dk.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_PCA10056 -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x239A", "0x4404"]],
|
||||
"usb_product": "nrf52840dk",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "pca10056",
|
||||
"variants_dir": "variants",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52840_xxAA",
|
||||
"onboard_tools": ["jlink"],
|
||||
"svd_path": "nrf52840.svd"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "A modified NRF52840-DK devboard (Adafruit BSP)",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "jlink",
|
||||
"protocols": ["jlink", "nrfjprog", "stlink"]
|
||||
},
|
||||
"url": "https://meshtastic.org/",
|
||||
"vendor": "Nordic Semi"
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52840_s140_v6.ld"
|
||||
"ldscript": "nrf52840_s113_v7.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52840_PCA10056 -DNRF52840_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x239A", "0x4404"]],
|
||||
"usb_product": "SimPPR",
|
||||
"usb_product": "nrf52840dk",
|
||||
"mcu": "nrf52840",
|
||||
"variant": "pca10056-rc-clock",
|
||||
"variants_dir": "variants",
|
||||
@@ -16,9 +16,9 @@
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS140",
|
||||
"sd_name": "s140",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_flags": "-DS113",
|
||||
"sd_name": "s113",
|
||||
"sd_version": "7.2.0",
|
||||
"sd_fwid": "0x00B6"
|
||||
},
|
||||
"bootloader": {
|
||||
|
||||
46
boards/ppr1.json
Normal file
46
boards/ppr1.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "nrf52833_s113_v7.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DARDUINO_NRF52833_PPR -DNRF52833_XXAA",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [["0x239A", "0x4406"]],
|
||||
"usb_product": "PPR",
|
||||
"mcu": "nrf52833",
|
||||
"variant": "ppr",
|
||||
"variants_dir": "variants",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS113",
|
||||
"sd_name": "s113",
|
||||
"sd_version": "7.2.0",
|
||||
"sd_fwid": "0x00b6"
|
||||
},
|
||||
"bootloader": {
|
||||
"settings_addr": "0xFF000"
|
||||
}
|
||||
},
|
||||
"connectivity": ["bluetooth"],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52833_xxAA",
|
||||
"onboard_tools": ["jlink"],
|
||||
"svd_path": "nrf52833.svd"
|
||||
},
|
||||
"frameworks": ["arduino"],
|
||||
"name": "Meshtastic PPR1 (Adafruit BSP)",
|
||||
"upload": {
|
||||
"maximum_ram_size": 248832,
|
||||
"maximum_size": 815104,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "jlink",
|
||||
"protocols": ["jlink", "nrfjprog", "stlink"]
|
||||
},
|
||||
"url": "https://meshtastic.org/",
|
||||
"vendor": "Othernet"
|
||||
}
|
||||
55
boards/rak815.json
Normal file
55
boards/rak815.json
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino":{
|
||||
"ldscript": "nrf52832_s132_v6.ld"
|
||||
},
|
||||
"core": "nRF5",
|
||||
"cpu": "cortex-m4",
|
||||
"extra_flags": "-DNRF52832_XXAA -DNRF52",
|
||||
"f_cpu": "64000000L",
|
||||
"hwids": [
|
||||
[
|
||||
"0x10c4",
|
||||
"0xea60"
|
||||
]
|
||||
],
|
||||
"usb_product": "RAK815",
|
||||
"mcu": "nrf52832",
|
||||
"variant": "rak815",
|
||||
"bsp": {
|
||||
"name": "adafruit"
|
||||
},
|
||||
"softdevice": {
|
||||
"sd_flags": "-DS132",
|
||||
"sd_name": "s132",
|
||||
"sd_version": "6.1.1",
|
||||
"sd_fwid": "0x00B7"
|
||||
}
|
||||
},
|
||||
"connectivity": [
|
||||
"bluetooth"
|
||||
],
|
||||
"debug": {
|
||||
"jlink_device": "nRF52832_xxAA",
|
||||
"svd_path": "nrf52.svd"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"name": "RAK RAK815",
|
||||
"upload": {
|
||||
"maximum_ram_size": 65536,
|
||||
"maximum_size": 524288,
|
||||
"require_upload_port": true,
|
||||
"speed": 115200,
|
||||
"protocol": "nrfutil",
|
||||
"protocols": [
|
||||
"jlink",
|
||||
"nrfjprog",
|
||||
"nrfutil",
|
||||
"stlink"
|
||||
]
|
||||
},
|
||||
"url": "https://store.rakwireless.com/products/rak815-hybrid-location-tracker",
|
||||
"vendor": "RAK"
|
||||
}
|
||||
43
data/static/basic.js
Normal file
43
data/static/basic.js
Normal file
@@ -0,0 +1,43 @@
|
||||
var meshtasticClient;
|
||||
var connectionOne;
|
||||
|
||||
|
||||
// Important: the connect action must be called from a user interaction (e.g. button press), otherwise the browsers won't allow the connect
|
||||
function connect() {
|
||||
|
||||
// Create new connection
|
||||
var httpconn = new meshtasticjs.IHTTPConnection();
|
||||
|
||||
// Set connection params
|
||||
let sslActive;
|
||||
if (window.location.protocol === 'https:') {
|
||||
sslActive = true;
|
||||
} else {
|
||||
sslActive = false;
|
||||
}
|
||||
let deviceIp = window.location.hostname; // Your devices IP here
|
||||
|
||||
|
||||
// Add event listeners that get called when a new packet is received / state of device changes
|
||||
httpconn.addEventListener('fromRadio', function (packet) { console.log(packet) });
|
||||
|
||||
// Connect to the device async, then send a text message
|
||||
httpconn.connect(deviceIp, sslActive)
|
||||
.then(result => {
|
||||
|
||||
alert('device has been configured')
|
||||
// This gets called when the connection has been established
|
||||
// -> send a message over the mesh network. If no recipient node is provided, it gets sent as a broadcast
|
||||
return httpconn.sendText('meshtastic is awesome');
|
||||
|
||||
})
|
||||
.then(result => {
|
||||
|
||||
// This gets called when the message has been sucessfully sent
|
||||
console.log('Message sent!');
|
||||
})
|
||||
|
||||
.catch(error => { console.log(error); });
|
||||
|
||||
}
|
||||
|
||||
18
data/static/index.html
Normal file
18
data/static/index.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<!doctype html>
|
||||
<html class="no-js" lang="">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title></title>
|
||||
|
||||
<script src="/static/meshtastic.js"></script>
|
||||
<script src="/static/basic.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<button id="connect_button" onclick="connect()">Connect to Meshtastic device</button>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
BIN
data/static/meshtastic.js.gz
Normal file
BIN
data/static/meshtastic.js.gz
Normal file
Binary file not shown.
@@ -28,17 +28,27 @@ Not all of these features are fully implemented yet - see **important** disclaim
|
||||
- Shows direction and distance to all members of your channel
|
||||
- Directed or broadcast text messages for channel members
|
||||
- Open and extensible codebase supporting multiple hardware vendors - no lock in to one vendor
|
||||
- Communication API for bluetooth devices (such as our Android app) to use the mesh. An iOS application is in the works. And [Meshtastic-python](https://pypi.org/project/meshtastic/) provides access from desktop computers.
|
||||
- Communication API for bluetooth devices (such as our Android app) to use the mesh. An iOS application is in the works. And [Meshtastic-python](https://pypi.org/project/meshtastic/) provides access from desktop computers.
|
||||
- Very easy sharing of private secured channels. Just share a special link or QR code with friends and they can join your encrypted mesh
|
||||
|
||||
This project is currently in beta testing but it is fairly stable and feature complete - if you have questions please [join our discussion forum](https://meshtastic.discourse.group/).
|
||||
|
||||
This software is 100% open source and developed by a group of hobbyist experimenters. No warranty is provided, if you'd like to improve it - we'd love your help. Please post in the [forum](https://meshtastic.discourse.group/).
|
||||
|
||||
### Beginner's Guide
|
||||
|
||||
For an detailed walk-through aimed at beginners, we recommend [meshtastic.letstalkthis.com](https://meshtastic.letstalkthis.com/).
|
||||
|
||||
### Related Groups
|
||||
|
||||
Telegram group for **Italy**-based users [t.me/meshtastic_italia](http://t.me/meshtastic_italia) (Italian language, unofficial).
|
||||
|
||||
# Updates
|
||||
|
||||
Note: Updates are happening almost daily, only major updates are listed below. For more details see our forum.
|
||||
|
||||
- 09/14/2020 - 1.0.0 Now with over 1700 android users, over 2000 nodes and translated into 15 languages. This project will always be a "beta" experiment, but now quite usable. We are currently selecting 1.1 features in our discussion forum.
|
||||
- 06/24/2020 - 0.7.x Now with over 1000 android users, over 600 people using the radios and translated into 22 languages. Fairly stable and we are working through bugs to get to 1.0.
|
||||
- 06/04/2020 - 0.6.7 Beta releases of both the application and the device code are released. Features are fairly solid now with a sizable number of users.
|
||||
- 04/28/2020 - 0.6.0 [Python API](https://pypi.org/project/meshtastic/) released. Makes it easy to use meshtastic devices as "zero config / just works" mesh transport adapters for other projects.
|
||||
- 04/20/2020 - 0.4.3 Pretty solid now both for the android app and the device code. Many people have donated translations and code. Probably going to call it a beta soon.
|
||||
@@ -51,7 +61,7 @@ Note: Updates are happening almost daily, only major updates are listed below. F
|
||||
|
||||
Our Android application is available here:
|
||||
|
||||
[](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dhomepage%26anid%3Dadmob)
|
||||
[](https://play.google.com/store/apps/details?id=com.geeksville.mesh&referrer=utm_source%3Dgithub-homepage)
|
||||
|
||||
The link above will return older more stable releases. We would prefer if you join our alpha-test group, because the application is rapidly improving. Three steps to opt-in to the alpha- test:
|
||||
|
||||
@@ -61,18 +71,25 @@ The link above will return older more stable releases. We would prefer if you jo
|
||||
|
||||
If you'd like to help with development, the source code is [on github](https://github.com/meshtastic/Meshtastic-Android).
|
||||
|
||||
The app is also distributed for Amazon Fire devices via the Amazon appstore: [](https://www.amazon.com/Geeksville-Industries-Meshtastic/dp/B08CY9394Q)
|
||||
|
||||
## Supported hardware
|
||||
|
||||
We currently support two brands of radios. The [TTGO T-Beam](https://www.aliexpress.com/item/4000119152086.html) and the [Heltec LoRa 32](https://heltec.org/project/wifi-lora-32/). Most people should buy the T-Beam and a 18650 battery (total cost less than \$35). Make
|
||||
sure to buy the frequency range which is legal for your country. For the USA, you should buy the 915MHz version. Getting a version that include a screen is optional, but highly recommended.
|
||||
We currently support two brands of radios. The [TTGO T-Beam](https://www.aliexpress.com/item/4001178678568.html) and the [Heltec LoRa 32](https://heltec.org/project/wifi-lora-32/). Most people should buy the T-Beam and a 18650 battery (total cost less than \$35). Also, the version of the T-Beam we link to is shipped with Meshtastic **preinstalled** by TTGO, so you don't have to install it yourself.
|
||||
|
||||
Make sure to buy the frequency range which is legal for your country. For the USA, you should buy the 915MHz version. Getting a version that include a screen is optional, but highly recommended.
|
||||
|
||||
Instructions for installing prebuilt firmware can be found [here](https://github.com/meshtastic/Meshtastic-esp32/blob/master/README.md).
|
||||
|
||||
For a nice printable cases:
|
||||
For a nice looking cases:
|
||||
|
||||
1. TTGO T-Beam V0 see this [design](https://www.thingiverse.com/thing:3773717) by [bsiege](https://www.thingiverse.com/bsiege).
|
||||
2. TTGO T_Beam V1 see this [design](https://www.thingiverse.com/thing:3830711) by [rwanrooy](https://www.thingiverse.com/rwanrooy) or this [remix](https://www.thingiverse.com/thing:3949330) by [8ung](https://www.thingiverse.com/8ung)
|
||||
3. Heltec Lora32 see this [design](https://www.thingiverse.com/thing:3125854) by [ornotermes](https://www.thingiverse.com/ornotermes).
|
||||
- 3D printable cases
|
||||
1. TTGO T-Beam V0 see this [design](https://www.thingiverse.com/thing:3773717) by [bsiege](https://www.thingiverse.com/bsiege).
|
||||
2. TTGO T_Beam V1 (SMA) see this [design](https://www.thingiverse.com/thing:3830711) by [rwanrooy](https://www.thingiverse.com/rwanrooy) or this [remix](https://www.thingiverse.com/thing:3949330) by [8ung](https://www.thingiverse.com/8ung)
|
||||
3. TTGO T_Beam V1 (IPEX) see this [design](https://www.thingiverse.com/thing:4587297) by [drewsed](https://www.thingiverse.com/drewsed)
|
||||
4. Heltec Lora32 see this [design](https://www.thingiverse.com/thing:3125854) by [ornotermes](https://www.thingiverse.com/ornotermes).
|
||||
- Laser-cut cases
|
||||
1. TTGO T_Beam V1 (SMA) see this [design](https://www.thingiverse.com/thing:4552771) by [jefish](https://www.thingiverse.com/jefish)
|
||||
|
||||
# IMPORTANT DISCLAIMERS AND FAQ
|
||||
|
||||
|
||||
8
docs/SupportedHardware.md
Normal file
8
docs/SupportedHardware.md
Normal file
@@ -0,0 +1,8 @@
|
||||
| Vendor | Product line | Version | Board labels | Notes | URL |
|
||||
|---|---|---|---|---|---|
|
||||
| TTGO | T-Beam | 0.7 | T22_V07 20180711 | LoRa 433/470MHz *OR* LoRa 868/915MHz , <br/>GPS ublox NEO-6M , <br/>battery holder for Li-Ion 18650 | [buy](https://www.aliexpress.com/item/4000574335430.html) |
|
||||
| TTGO | T-Beam | 1.0 | | | [buy](https://www.aliexpress.com/item/4001178678568.html) |
|
||||
| TTGO | T-Beam | 1.1 | T22_V11 20191212 | LoRa 433/470MHz *OR* LoRa 868/915MHz *OR* LoRa 923MHz , <br/>GPS ublox NEO-M8N , <br/>battery holder for Li-Ion 18650 | [buy](https://www.aliexpress.com/item/4001178678568.html) |
|
||||
| TTGO | Lora32 | 2.0 | *missing* | LoRa 433/470MHz *OR* LoRa 868/915MHz , <br/>OLED SSD1306 , <br/>SD card holder | [buy](https://www.aliexpress.com/item/4000211331316.html) |
|
||||
| TTGO | Lora32 | 2.1 | T3_V1.6 20180606 | LoRa 32 (V2) , <br/>SD card holder | [buy](https://www.aliexpress.com/item/4000119208093.html) |
|
||||
| Heltec | Lora 32 | V2 | V2 | LoRa 433/470MHz *OR* LoRa 868/915MHz | [buy](https://heltec.org/project/wifi-lora-32/) |
|
||||
@@ -1,7 +1,7 @@
|
||||
theme: jekyll-theme-cayman
|
||||
|
||||
title: Meshtastic
|
||||
description: An opensource hiking, pilot, skiing, Signal-App-extending GPS mesh communicator
|
||||
description: An opensource hiking, pilot, skiing, secure GPS mesh communicator
|
||||
google_analytics: G-DRZ5H5EXHV
|
||||
|
||||
include: [".well-known"]
|
||||
|
||||
@@ -4,7 +4,7 @@ This project is still pretty young but moving at a pretty good pace. Not all fea
|
||||
Most of these problems should be solved by the beta release (within three months):
|
||||
|
||||
- We don't make these devices and they haven't been tested by UL or the FCC. If you use them you are experimenting and we can't promise they won't burn your house down ;-)
|
||||
- The encryption [implementation](software/crypto.md) has not been reviewed by an expert. (Are you an expert? Please help us)
|
||||
- The encryption implementation is good but see this list of [caveats](software/crypto.md#summary-of-strengthsweaknesses-of-our-current-implementation) to determine risks you might face.
|
||||
- A number of (straightforward) software work items have to be completed before battery life matches our measurements, currently battery life is about three days. Join us on chat if you want the spreadsheet of power measurements/calculations.
|
||||
- The Android API needs to be documented better
|
||||
- No one has written an iOS app yet. But some good souls [are talking about it](https://github.com/meshtastic/Meshtastic-esp32/issues/14) ;-)
|
||||
|
||||
BIN
docs/hardware/DS_SX1261-2_V1.2.pdf
Normal file
BIN
docs/hardware/DS_SX1261-2_V1.2.pdf
Normal file
Binary file not shown.
BIN
docs/hardware/LoRa Design Guide.pdf
Normal file
BIN
docs/hardware/LoRa Design Guide.pdf
Normal file
Binary file not shown.
BIN
docs/hardware/T-SX1262.pdf
Normal file
BIN
docs/hardware/T-SX1262.pdf
Normal file
Binary file not shown.
BIN
docs/hardware/air530/Air530 GPS Manual Text English.pdf
Normal file
BIN
docs/hardware/air530/Air530 GPS Manual Text English.pdf
Normal file
Binary file not shown.
BIN
docs/hardware/air530/Air530_GPS_User_Booklet.V1.7.pdf
Normal file
BIN
docs/hardware/air530/Air530_GPS_User_Booklet.V1.7.pdf
Normal file
Binary file not shown.
35
docs/hardware/corvus.md
Normal file
35
docs/hardware/corvus.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# Notes on @BigCorvus boards
|
||||
|
||||
## Board version 1.1
|
||||
|
||||
variant name lora_relay_v1
|
||||
|
||||
### Remaining TODOs
|
||||
|
||||
- power hold for the ST7735
|
||||
- look at example sketch
|
||||
- turn on xmit boost
|
||||
|
||||
## Recommendations for future boards
|
||||
|
||||
@BigCorvus your board is **really** nice. Here's some ideas for the future:
|
||||
|
||||
- make the SWDIO header more standard (the small ARM 2x5 micro footprint?) or at least througholes so it is easy to solder a header
|
||||
|
||||
## How to program bootloader
|
||||
|
||||
Download from here: https://github.com/adafruit/Adafruit_nRF52_Bootloader/releases
|
||||
|
||||
```
|
||||
nrfjprog -f nrf52 --eraseall
|
||||
Erasing user available code and UICR flash areas.
|
||||
Applying system reset.
|
||||
|
||||
nrfjprog -f nrf52 --program feather_nrf52840_express_bootloader-0.3.2_s140_6.1.1.hex
|
||||
Parsing hex file.
|
||||
Reading flash area to program to guarantee it is erased.
|
||||
Checking that the area to write is not protected.
|
||||
Programming device.
|
||||
```
|
||||
|
||||
Then reboot the board, if all went well it now shows up as a mountable filesystem on your USB bus.
|
||||
6
docs/hardware/cubecell-TODO.md
Normal file
6
docs/hardware/cubecell-TODO.md
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
https://heltec-automation-docs.readthedocs.io/en/latest/cubecell/index.html
|
||||
|
||||
https://github.com/HelTecAutomation/ASR650x-Arduino?utm_source=platformio.org&utm_medium=docs
|
||||
|
||||
* Either portfreertos or make not theaded versions of Lock, WorkerThread, Queue (probably the latter).
|
||||
BIN
docs/hardware/heltec-wifi-lora-32-v2-915.pdf
Normal file
BIN
docs/hardware/heltec-wifi-lora-32-v2-915.pdf
Normal file
Binary file not shown.
BIN
docs/hardware/pinetab/PineTab LoRa schematic.pdf
Normal file
BIN
docs/hardware/pinetab/PineTab LoRa schematic.pdf
Normal file
Binary file not shown.
BIN
docs/hardware/pinetab/SX1302/DS_SX1302_V1.0.pdf
Normal file
BIN
docs/hardware/pinetab/SX1302/DS_SX1302_V1.0.pdf
Normal file
Binary file not shown.
BIN
docs/hardware/pinetab/SX1302/M-GW1302S 用户手册(2)(1)(1).pdf
Normal file
BIN
docs/hardware/pinetab/SX1302/M-GW1302S 用户手册(2)(1)(1).pdf
Normal file
Binary file not shown.
BIN
docs/hardware/pinetab/SX1302/M-GW1302S(射频版)硬件设计手册_V1.1.pdf
Normal file
BIN
docs/hardware/pinetab/SX1302/M-GW1302S(射频版)硬件设计手册_V1.1.pdf
Normal file
Binary file not shown.
BIN
docs/hardware/pinetab/SX1302/M-GW1302(透传版)_硬件设计手册.pdf
Normal file
BIN
docs/hardware/pinetab/SX1302/M-GW1302(透传版)_硬件设计手册.pdf
Normal file
Binary file not shown.
990
docs/hardware/pinetab/ch341h_datasheet.pdf
Normal file
990
docs/hardware/pinetab/ch341h_datasheet.pdf
Normal file
File diff suppressed because one or more lines are too long
BIN
docs/hardware/pinetab/nfnfaceblhkepdph.jpg
Normal file
BIN
docs/hardware/pinetab/nfnfaceblhkepdph.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 272 KiB |
BIN
docs/hardware/pinetab/nhndndegjjflkibg.jpg
Normal file
BIN
docs/hardware/pinetab/nhndndegjjflkibg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 417 KiB |
BIN
docs/hardware/rak815/PE4259.pdf
Normal file
BIN
docs/hardware/rak815/PE4259.pdf
Normal file
Binary file not shown.
BIN
docs/hardware/rak815/RAK813 Module Datasheet V1.0.pdf
Normal file
BIN
docs/hardware/rak815/RAK813 Module Datasheet V1.0.pdf
Normal file
Binary file not shown.
3692
docs/hardware/rak815/RAK813_BLE_LoRa_Schematic_20180322.pdf
Normal file
3692
docs/hardware/rak815/RAK813_BLE_LoRa_Schematic_20180322.pdf
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
File diff suppressed because one or more lines are too long
8249
docs/hardware/rak815/ublox max7 datasheet.pdf
Normal file
8249
docs/hardware/rak815/ublox max7 datasheet.pdf
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
38977
docs/hardware/u-blox8-M8_ReceiverDescrProtSpec_(UBX-13003221).pdf
Normal file
38977
docs/hardware/u-blox8-M8_ReceiverDescrProtSpec_(UBX-13003221).pdf
Normal file
File diff suppressed because one or more lines are too long
@@ -8,7 +8,7 @@ See [this site](https://www.rfwireless-world.com/Tutorials/LoRa-channels-list.ht
|
||||
|
||||
## LoRaWAN Europe Frequency Band
|
||||
|
||||
The maximum power allowed is +14dBM.
|
||||
The maximum power allowed is +14dBm ERP (Effective Radiated Power, see [this site](https://en.wikipedia.org/wiki/Effective_radiated_power) for more information).
|
||||
|
||||
### 433 MHz
|
||||
|
||||
@@ -24,7 +24,7 @@ Channel zero starts at 865.20 MHz
|
||||
|
||||
LoRaWAN defines 64, 125 kHz channels from 902.3 to 914.9 MHz increments.
|
||||
|
||||
The maximum output power for North America is +30 dBM.
|
||||
The maximum output power for North America is +30 dBm ERP.
|
||||
|
||||
The band is from 902 to 928 MHz. It mentions channel number and its respective channel frequency. All the 13 channels are separated by 2.16 MHz with respect to the adjacent channels.
|
||||
Channel zero starts at 903.08 MHz center frequency.
|
||||
Channel zero starts at 903.08 MHz center frequency.
|
||||
|
||||
@@ -1,37 +1,117 @@
|
||||
# High priority
|
||||
# Geeksville's current work queue
|
||||
|
||||
- why is the net so chatty now?
|
||||
- do a release
|
||||
- device wakes, turns BLE on and phone doesn't notice (while phone was sitting in auto-connect)
|
||||
- E22 bringup
|
||||
- encryption review findings writeup
|
||||
- turn on modem-sleep mode - https://github.com/espressif/arduino-esp32/issues/1142#issuecomment-512428852
|
||||
You probably don't care about this section - skip to the next one.
|
||||
|
||||
For app cleanup:
|
||||
|
||||
* DONE only do wantReplies once per packet type, if we change network settings force it again
|
||||
* update positions and nodeinfos based on packets we just merely witness on the mesh. via isPromsciousPort bool, remove sniffing
|
||||
* DONE make device build always have a valid version
|
||||
* DONE do fixed position bug https://github.com/meshtastic/Meshtastic-device/issues/536
|
||||
* DONE check build guide
|
||||
* DONE write devapi user guide
|
||||
* DONE update android code: https://developer.android.com/topic/libraries/view-binding/migration
|
||||
* DONE test GPIO watch
|
||||
* DONE set --set-chan-fast, --set-chan-default
|
||||
* writeup docs on gpio
|
||||
* DONE make python ping command
|
||||
* DONE make hello world example service
|
||||
* DONE have python tool check max packet size before sending to device
|
||||
* DONE if request was sent reliably, send reply reliably
|
||||
* DONE require a recent python api to talk to these new device loads
|
||||
* DONE require a recent android app to talk to these new device loads
|
||||
* DONE fix handleIncomingPosition
|
||||
* DONE move want_replies handling into plugins
|
||||
* DONE on android for received positions handle either old or new positions / user messages
|
||||
* DONE on android side send old or new positions as needed / user messages
|
||||
* DONE test python side handle new position/user messages
|
||||
* DONE make a gpio example. --gpiowrb 4 1, --gpiord 0x444, --gpiowatch 0x3ff
|
||||
* DONE fix position sending to use new plugin
|
||||
* DONE Add SinglePortNumPlugin - as the new most useful baseclass
|
||||
* DONE move positions into regular data packets (use new app framework)
|
||||
* DONE move user info into regular data packets (use new app framework)
|
||||
* DONE test that positions, text messages and user info still work
|
||||
* DONE test that position, text messages and user info work properly with new android app and old device code
|
||||
* do UDP tunnel
|
||||
* fix the RTC drift bug
|
||||
* move python ping functionality into device, reply with rxsnr info
|
||||
* use channels for gpio security https://github.com/meshtastic/Meshtastic-device/issues/104
|
||||
* generate autodocs
|
||||
* MeshPackets for sending should be reference counted so that API clients would have the option of checking sent status (would allow removing the nasty 30 sec timer in gpio watch sending)
|
||||
|
||||
For high speed/lots of devices/short range tasks:
|
||||
|
||||
- When guessing numhops for sending: if I've heard from many local (0 hop neighbors) decrease hopcount by 2 rather than 1.
|
||||
This should nicely help 'router' nodes do the right thing when long range, or if there are many local nodes for short range.
|
||||
- fix timeouts/delays to be based on packet length at current radio settings
|
||||
|
||||
* update faq with antennas https://meshtastic.discourse.group/t/range-test-ideas-requested/738/2
|
||||
* update faq on recommended android version and phones
|
||||
* add help link inside the app, reference a page on the wiki
|
||||
* turn on amazon reviews support
|
||||
* add a tablet layout (with map next to messages) in the android app
|
||||
|
||||
# Old docs to merge
|
||||
|
||||
MESH RADIO PROTOCOL
|
||||
|
||||
Old TODO notes on the mesh radio protocol, merge into real docs someday...
|
||||
|
||||
for each named group we have a pre-shared key known by all group members and
|
||||
wrapped around the device. you can only be in one group at a time (FIXME?!) To
|
||||
join the group we read a qr code with the preshared key and ParamsCodeEnum. that
|
||||
gets sent via bluetooth to the device. ParamsCodeEnum maps to a set of various
|
||||
radio params (regulatory region, center freq, SF, bandwidth, bitrate, power
|
||||
etc...) so all members of the mesh can have their radios set the same way.
|
||||
|
||||
once in that group, we can talk between 254 node numbers.
|
||||
to get our node number (and announce our presence in the channel) we pick a
|
||||
random node number and broadcast as that node with WANT-NODENUM(my globally
|
||||
unique name). If anyone on the channel has seen someone _else_ using that name
|
||||
within the last 24 hrs(?) they reply with DENY-NODENUM. Note: we might receive
|
||||
multiple denies. Note: this allows others to speak up for some other node that
|
||||
might be saving battery right now. Any time we hear from another node (for any
|
||||
message type), we add that node number to the unpickable list. To dramatically
|
||||
decrease the odds a node number we request is already used by someone. If no one
|
||||
denies within TBD seconds, we assume that we have that node number. As long as
|
||||
we keep talking to folks at least once every 24 hrs, others should remember we
|
||||
have it.
|
||||
|
||||
Once we have a node number we can broadcast POSITION-UPDATE(my globally unique
|
||||
name, lat, lon, alt, amt battery remaining). All receivers will use this to a)
|
||||
update the mapping of who is at what node nums, b) the time of last rx, c)
|
||||
position. If we haven't heard from that node in a while we reply to that node
|
||||
(only) with our current POSITION_UPDATE state - so that node (presumably just
|
||||
rejoined the network) can build a map of all participants.
|
||||
|
||||
We will periodically broadcast POSITION-UPDATE as needed based on distance moved
|
||||
or a periodic minimum heartbeat.
|
||||
|
||||
If user wants to send a text they can SEND_TEXT(dest user, short text message).
|
||||
Dest user is a node number, or 0xff for broadcast.
|
||||
|
||||
# Medium priority
|
||||
|
||||
Items to complete before the first beta release.
|
||||
Items to complete before 1.0.
|
||||
|
||||
- turn on watchdog timer (because lib code seems buggy)
|
||||
- show battery level as % full
|
||||
- rx signal measurements -3 marginal, -9 bad, 10 great, -10 means almost unusable. So scale this into % signal strength. preferably as a graph, with an X indicating loss of comms.
|
||||
|
||||
# Pre-beta priority
|
||||
|
||||
During the beta timeframe the following improvements 'would be nice'
|
||||
# Post 1.0 ideas
|
||||
|
||||
- finish DSR for unicast
|
||||
- check fcc rules on duty cycle. we might not need to freq hop. https://www.sunfiretesting.com/LoRa-FCC-Certification-Guide/ . Might need to add enforcement for europe though.
|
||||
- pick channel center frequency based on channel name? "dolphin" would hash to 900Mhz, "cat" to 905MHz etc? allows us to hide the concept of channel # from hte user.
|
||||
- make a no bluetooth configured yet screen - include this screen in the loop if the user hasn't yet paired
|
||||
- if radio params change fundamentally, discard the nodedb
|
||||
- re-enable the bluetooth battery level service on the T-BEAM
|
||||
- implement first cut of router mode: preferentially handle flooding, and change sleep and GPS behaviors
|
||||
- provide generalized (but slow) internet message forwarding service if one of our nodes has internet connectivity (MQTT) [ Not a requirement but a personal interest ]
|
||||
|
||||
# Low priority
|
||||
# Low priority ideas
|
||||
|
||||
Items after the first final candidate release.
|
||||
|
||||
- implement nimble battery level service
|
||||
- Nimble implement device info service remaining fields (hw version etc)
|
||||
- Turn on RPA addresses for the device side in Nimble
|
||||
- Try to teardown less of the Nimble protocol stack across sleep
|
||||
- dynamic frequency scaling could save a lot of power on ESP32, but it seems to corrupt uart (even with ref_tick set correctly)
|
||||
- Change back to using a fixed sized MemoryPool rather than MemoryDynamic (see bug #149)
|
||||
- scan to find channels with low background noise? (Use CAD mode of the RF95 to automatically find low noise channels)
|
||||
- If the phone doesn't read fromradio mailbox within X seconds, assume the phone is gone and we can stop queing location msgs
|
||||
@@ -57,9 +137,16 @@ Items after the first final candidate release.
|
||||
- split out the software update utility so other projects can use it. Have the appload specify the URL for downloads.
|
||||
- read the PMU battery fault indicators and blink/led/warn user on screen
|
||||
- discard very old nodedb records (> 1wk)
|
||||
- add a watchdog timer
|
||||
- handle millis() rollover in GPS.getTime - otherwise we will break after 50 days
|
||||
- report esp32 device code bugs back to the mothership via android
|
||||
- change BLE bonding to something more secure. see comment by pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND)
|
||||
|
||||
Changes related to wifi support on ESP32:
|
||||
|
||||
- iram space: https://esp32.com/viewtopic.php?t=8460
|
||||
- set https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/external-ram.html spi ram bss
|
||||
- figure out if iram or bluetooth classic caused ble problems
|
||||
- post bug on esp32-arduino with BLE bug findings
|
||||
|
||||
# Spinoff project ideas
|
||||
|
||||
|
||||
14
docs/software/ant.md
Normal file
14
docs/software/ant.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# ANT protocol notes
|
||||
|
||||
SD340 terms are reasonable for NRF52
|
||||
https://www.thisisant.com/developer/components/nrf52832#tab_protocol_stacks_tab
|
||||
|
||||
Profiles to implement:
|
||||
|
||||
tracker
|
||||
https://www.thisisant.com/developer/ant-plus/device-profiles/#4365_tab
|
||||
|
||||
ebike
|
||||
https://www.thisisant.com/developer/ant-plus/device-profiles/#527_tab
|
||||
|
||||
no profile for messaging?
|
||||
@@ -1,15 +1,40 @@
|
||||
# Build instructions
|
||||
|
||||
This project uses the simple PlatformIO build system. You can use the IDE, but for brevity
|
||||
in these instructions I describe use of their command line tool.
|
||||
This project uses the simple PlatformIO build system. PlatformIO is an extension to Microsoft VSCode. Workflows from building from the GUI or from the commandline are listed below.
|
||||
|
||||
1. Purchase a suitable radio (see above)
|
||||
If you encounter any problems, please post a question in [our forum](meshtastic.discourse.group). And when you learn a fix, update these instructions for the next person (i.e. edit this file and send in a [pull-request](https://opensource.com/article/19/7/create-pull-request-github) which we will eagerly merge).
|
||||
|
||||
## GUI
|
||||
|
||||
1. Purchase a suitable [radio](https://github.com/meshtastic/Meshtastic-device/wiki/Hardware-Information).
|
||||
2. Install [Python](https://www.python.org/downloads/).
|
||||
3. Install [Git](https://git-scm.com/downloads).
|
||||
4. Reboot your computer.
|
||||
5. Install [PlatformIO](https://platformio.org/platformio-ide).
|
||||
6. Click the PlatformIO icon on the side bar. 
|
||||
7. Under `Quick Access, Miscellaneous, Clone Git Project` enter the URL of the Meshtastic repo found [here](https://github.com/meshtastic/Meshtastic-device). 
|
||||
8. Select a file location to save the repo.
|
||||
9. Once loaded, open the `platformio.ini` file.
|
||||
10. At the line `default_envs` you can change it to the board type you are building for ie. `tlora-v2, tlora-v1, tlora-v2-1-1.6, tbeam, heltec, tbeam0.7` (boards are listed further down in the file).
|
||||
11. The hardware can be configured for different countries by adding a definition to the `configuration.h` file. `#define HW_VERSION_US` or `HW_VERSION_EU433, HW_VERSION_EU865, HW_VERSION_CN, HW_VERSION_JP`. Other country settings can be found in `MeshRadio.h`. The default is `HW_VERSION_US`.
|
||||
12. Click the PlatformIO icon on the side bar. Under `Project Tasks` you can now build or upload.
|
||||
|
||||
Note - To get a clean build you may have to delete the auto-generated file `./.vscode/c_cpp_properties.json`, close and re-open Visual Studio and WAIT until the file is auto-generated before compiling again.
|
||||
|
||||
## Command Line
|
||||
|
||||
1. Purchase a suitable [radio](https://github.com/meshtastic/Meshtastic-device/wiki/Hardware-Information).
|
||||
2. Install [PlatformIO](https://platformio.org/platformio-ide)
|
||||
3. Download this git repo and cd into it
|
||||
3. Download this git repo and cd into it:
|
||||
|
||||
```
|
||||
git clone https://github.com/meshtastic/Meshtastic-device.git
|
||||
cd Meshtastic-device
|
||||
```
|
||||
4. Run `git submodule update --init --recursive` to pull in dependencies this project needs.
|
||||
5. If you are outside the USA, edit [platformio.ini](/platformio.ini) to set the correct frequency range for your country. The line you need to change starts with `hw_version` and instructions are provided above that line. Options are provided for `EU433`, `EU835`, `CN`, `JP` and `US` (default). Pull-requests eagerly accepted for other countries.
|
||||
5. If you are outside the USA, run "export COUNTRY=EU865" (or whatever) to set the correct frequency range for your country. Options are provided for `EU433`, `EU865`, `CN`, `JP` and `US` (default). Pull-requests eagerly accepted for other countries.
|
||||
6. Plug the radio into your USB port
|
||||
7. Type `pio run --environment XXX -t upload` (This command will fetch dependencies, build the project and install it on the board via USB). For XXX, use the board type you have (either `tbeam`, `heltec`, `ttgo-lora32-v1`, `ttgo-lora32-v2`).
|
||||
7. Type `pio run --environment XXX -t upload` (This command will fetch dependencies, build the project and install it on the board via USB). For XXX, use the board type you have (either `tlora-v2, tlora-v1, tlora-v2-1-1.6, tbeam, heltec, tbeam0.7`).
|
||||
8. Platform IO also installs a very nice VisualStudio Code based IDE, see their [tutorial](https://docs.platformio.org/en/latest/tutorials/espressif32/arduino_debugging_unit_testing.html) if you'd like to use it.
|
||||
|
||||
## Decoding stack traces
|
||||
|
||||
@@ -5,33 +5,47 @@ the project developers are not cryptography experts. Therefore we ask two things
|
||||
|
||||
- If you are a cryptography expert, please review these notes and our questions below. Can you help us by reviewing our
|
||||
notes below and offering advice? We will happily give as much or as little credit as you wish ;-).
|
||||
- Consider our existing solution 'alpha' and probably fairly secure against a not particularly aggressive adversary. But until
|
||||
it is reviewed by someone smarter than us, assume it might have flaws.
|
||||
- Consider our existing solution 'alpha' and probably fairly secure against a not particularly aggressive adversary
|
||||
(but we can't yet make a more confident statement).
|
||||
|
||||
## Notes on implementation
|
||||
## Summary of strengths/weaknesses of our current implementation
|
||||
|
||||
Based on comments from reviewers (see below), here's some tips for usage of these radios. So you can know the level of protection offered:
|
||||
|
||||
* It is pretty likely that the AES256 security is implemented 'correctly' and an observer will not be able to decode your messages.
|
||||
* Warning: If an attacker is able to get one of the radios in their position, they could either a) extract the channel key from that device or b) use that radio to listen to new communications.
|
||||
* Warning: If an attacker is able to get the "Channel QR code/URL" that you share with others - that attacker could then be able to read any messages sent on the channel (either tomorrow or in the past - if they kept a raw copy of those broadcast packets)
|
||||
|
||||
Possible future areas of work (if there is enough interest - post in our [forum](https://meshtastic.discourse.group) if you want this):
|
||||
|
||||
1. Optionally requiring users to provide a PIN to regain access to the mesh. This could be based on: intentionally locking the device, time since last use, or any member could force all members to reauthenticate,
|
||||
2. Until a device reauthenticates, any other access via BLE or USB would be blocked (this would protect against attackers who are not prepared to write custom software to extract and reverse engineer meshtastic flash memory)
|
||||
3. Turning on read-back protection in the device fuse-bits (this would extend protection in #2 to block all but **extremely** advanced attacks involving chip disassembly)
|
||||
4. Time limiting keys used for message transmission and automatically cycling them on a schedule. This would protect past messages from being decoded even if an attacker learns the current key.
|
||||
|
||||
### Notes for reviewers
|
||||
|
||||
If you are reviewing our implementation, this is a brief statement of our method.
|
||||
|
||||
- We do all crypto at the SubPacket (payload) level only, so that all meshtastic nodes will route for others - even those channels which are encrypted with a different key.
|
||||
- Mostly based on reading [Wikipedia](<https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Counter_(CTR)>) and using the modes the ESP32 provides support for in hardware.
|
||||
- We use AES256-CTR as a stream cypher (with zero padding on the last BLOCK) because it is well supported with hardware acceleration.
|
||||
|
||||
Parameters for our CTR implementation:
|
||||
|
||||
- Our AES key is 128 or 256 bits, shared as part of the 'Channel' specification.
|
||||
- Each SubPacket will be sent as a series of 16 byte BLOCKS.
|
||||
- The node number concatenated with the packet number is used as the NONCE. This counter will be stored in flash in the device and should essentially never repeat. If the user makes a new 'Channel' (i.e. picking a new random 256 bit key), the packet number will start at zero. The packet number is sent
|
||||
in cleartext with each packet. The node number can be derived from the "from" field of each packet.
|
||||
- Each BLOCK for a packet has an incrementing COUNTER. COUNTER starts at zero for the first block of each packet.
|
||||
- The IV for each block is constructed by concatenating the NONCE as the upper 96 bits of the IV and the COUNTER as the bottom 32 bits. Note: since our packets are small counter will really never be higher than 32 (five bits).
|
||||
- The node number concatenated with the packet number is used as the NONCE. This nonce will be stored in flash in the device and should essentially never repeat. If the user makes a new 'Channel' (i.e. picking a new random 256 bit key), the packet number will start at zero.
|
||||
- The packet number is sent in cleartext with each packet. The node number can be derived from the "from" field of each packet. (Cleartext is acceptable because it merely provides IV for each encryption run)
|
||||
- Each 16 byte BLOCK for a packet has an incrementing COUNTER. COUNTER starts at zero for the first block of each packet.
|
||||
- The IV for each block is constructed by concatenating the NONCE as the upper 96 bits of the IV and the COUNTER as the bottom 32 bits. Since our packets are small counter portion will really never be higher than 32 (five bits).
|
||||
|
||||
```
|
||||
You can encrypt separate messages by dividing the nonce_counter buffer in two areas: the first one used for a per-message nonce, handled by yourself, and the second one updated by this function internally.
|
||||
For example, you might reserve the first 12 bytes for the per-message nonce, and the last 4 bytes for internal use. In that case, before calling this function on a new message you need to set the first 12 bytes of nonce_counter to your chosen nonce value, the last 4 to 0, and nc_off to 0 (which will cause stream_block to be ignored). That way, you can encrypt at most 2**96 messages of up to 2**32 blocks each with the same key.
|
||||
## Comments from reviewer #1
|
||||
|
||||
The per-message nonce (or information sufficient to reconstruct it) needs to be communicated with the ciphertext and must be unique. The recommended way to ensure uniqueness is to use a message counter. An alternative is to generate random nonces, but this limits the number of messages that can be securely encrypted: for example, with 96-bit random nonces, you should not encrypt more than 2**32 messages with the same key.
|
||||
This reviewer is a cryptography professional, but would like to remain anonymous. We thank them for their comments ;-):
|
||||
|
||||
Note that for both stategies, sizes are measured in blocks and that an AES block is 16 bytes.
|
||||
```
|
||||
I'm assuming that meshtastic is being used to hike in places where someone capable is trying to break it - like you were going to walk around DefCon using these. I spent about an hour reviewing the encryption, and have the following notes:
|
||||
|
||||
## Remaining todo
|
||||
* The write-up isn't quite as clear as the code.
|
||||
* The code is using AES-CTR mode correctly to ensure confidentiality.
|
||||
* The comment for initNonce really covers the necessary information.
|
||||
* I think the bigger encryption question is "what does the encryption need to do"? As it stands, an attacker who has yet to capture any of the devices cannot reasonably capture text or location data. An attacker who captures any device in the channel/mesh can read everything going to that device, everything stored on that device, and any other communication within the channel that they captured in encrypted form. If that capability basically matches your expectations, it is suitable for whatever adventures this was intended for, then, based on information publicly available or widely disclosed, the encryption is good. If those properties are distressing (like, device history is deliberately limited and you don't want a device captured today to endanger the information sent over the channel yesterday) we could talk about ways to achieve that (most likely synchronizing time and replacing the key with its own SHA256 every X hours, and ensuring the old key is not retained unnecessarily).
|
||||
* Two other things to keep in mind are that AES-CTR does not itself provide authenticity (e.g. an attacker can flip bits in replaying data and scramble the resulting plaintext), and that the current scheme gives some hints about transmission in the size. So, if you worry about an adversary deliberately messing-up messages or knowing the length of a text message, it looks like those might be possible.
|
||||
|
||||
- Have the app change the crypto key when the user generates a new channel
|
||||
I'm guessing that the network behaves somewhat like a store-and-forward network - or, at least, that the goal is to avoid establishing a two-way connection to transmit data. I'm afraid I haven't worked with mesh networks much, but remember studying them briefly in school about ten years ago.
|
||||
@@ -1,12 +1,28 @@
|
||||
# Bluetooth API
|
||||
# Bluetooth/serial/TCP protocol API
|
||||
|
||||
The Bluetooth API is design to have only a few characteristics and most polymorphism comes from the flexible set of Google Protocol Buffers which are sent over the wire. We use protocol buffers extensively both for the bluetooth API and for packets inside the mesh or when providing packets to other applications on the phone.
|
||||
(This document describes the protocol for external API clients using our devices. If you are interested in running your own code on the device itself, see the [on-device](plugin-api.md) documentation instead)
|
||||
|
||||
## A note on MTU sizes
|
||||
The Device API is design to have only a simple stream of ToRadio and FromRadio packets and all polymorphism comes from the flexible set of Google Protocol Buffers which are sent over the wire. We use protocol buffers extensively both for the bluetooth API and for packets inside the mesh or when providing packets to other applications on the phone.
|
||||
|
||||
This device will work with any MTU size, but it is highly recommended that you call your phone's "setMTU function to increase MTU to 512 bytes" as soon as you connect to a service. This will dramatically improve performance when reading/writing packets.
|
||||
## Streaming version
|
||||
|
||||
## MeshBluetoothService
|
||||
This protocol is **almost** identical when it is deployed over BLE, Serial/USB or TCP (our three currently supported transports for connecting to phone/PC). Most of this document is in terms of the original BLE version, but this section describes the small changes when this API is exposed over a Streaming (non datagram) transport. The streaming version has the following changes:
|
||||
|
||||
- We assume the stream is reliable (though the protocol will resynchronize if bytes are lost or corrupted). i.e. we do not include CRCs or error correction codes.
|
||||
- Packets always have a four byte header (described below) prefixed before each packet. This header provides framing characters and length.
|
||||
- The stream going towards the radio is only a series of ToRadio packets (with the extra 4 byte headers)
|
||||
- The stream going towards the PC is a stream of FromRadio packets (with the 4 byte headers), or if the receiver state machine does not see valid header bytes it can (optionally) print those bytes as the debug console from the radio. This allows the device to emit regular serial debugging messages (which can be understood by a terminal program) but also switch to a more structured set of protobufs once it sees that the PC client has sent a protobuf towards it.
|
||||
|
||||
The 4 byte header is constructed to both provide framing and to not look line 'normal' 7 bit ASCII.
|
||||
|
||||
- Byte 0: START1 (0x94)
|
||||
- Byte 1: START2 (0xc3)
|
||||
- Byte 2: MSB of protobuf length
|
||||
- Byte 3: LSB of protobuf length
|
||||
|
||||
The receiver will validate length and if >512 it will assume the packet is corrupted and return to looking for START1. While looking for START1 any other characters are printed as "debug output". For small example implementation of this reader see the meshtastic-python implementation.
|
||||
|
||||
## MeshBluetoothService (the BLE API)
|
||||
|
||||
This is the main bluetooth service for the device and provides the API your app should use to get information about the mesh, send packets or provision the radio.
|
||||
|
||||
@@ -28,7 +44,6 @@ Expected sequence for initial download:
|
||||
- Read a RadioConfig from "radio" - used to get the channel and radio settings
|
||||
- Read a User from "user" - to get the username for this node
|
||||
- Read a MyNodeInfo from "mynode" to get information about this local device
|
||||
- Write an empty record to "nodeinfo" to restart the nodeinfo reading state machine
|
||||
- Read a series of NodeInfo packets to build the phone's copy of the current NodeDB for the mesh
|
||||
- Read a endConfig packet that indicates that the entire state you need has been sent.
|
||||
- Read a series of MeshPackets until it returns empty to get any messages that arrived for this node while the phone was away
|
||||
@@ -71,16 +86,20 @@ Not all messages are kept in the fromradio queue (filtered based on SubPacket):
|
||||
- No WantNodeNum / DenyNodeNum messages are kept
|
||||
A variable keepAllPackets, if set to true will suppress this behavior and instead keep everything for forwarding to the phone (for debugging)
|
||||
|
||||
## Protobuf API
|
||||
### A note on MTU sizes
|
||||
|
||||
This device will work with any MTU size, but it is highly recommended that you call your phone's "setMTU function to increase MTU to 512 bytes" as soon as you connect to a service. This will dramatically improve performance when reading/writing packets.
|
||||
|
||||
### Protobuf API
|
||||
|
||||
On connect, you should send a want_config_id protobuf to the device. This will cause the device to send its node DB and radio config via the fromradio endpoint. After sending the full DB, the radio will send a want_config_id to indicate it is done sending the configuration.
|
||||
|
||||
## Other bluetooth services
|
||||
### Other bluetooth services
|
||||
|
||||
This document focuses on the core mesh service, but it is worth noting that the following other Bluetooth services are also
|
||||
This document focuses on the core device protocol, but it is worth noting that the following other Bluetooth services are also
|
||||
provided by the device.
|
||||
|
||||
### BluetoothSoftwareUpdate
|
||||
#### BluetoothSoftwareUpdate
|
||||
|
||||
The software update service. For a sample function that performs a software update using this API see [startUpdate](https://github.com/meshtastic/Meshtastic-Android/blob/master/app/src/main/java/com/geeksville/mesh/service/SoftwareUpdateService.kt).
|
||||
|
||||
@@ -94,14 +113,15 @@ Characteristics
|
||||
| e272ebac-d463-4b98-bc84-5cc1a39ee517 | write | data, variable sized, recommended 512 bytes, write one for each block of file |
|
||||
| 4826129c-c22a-43a3-b066-ce8f0d5bacc6 | write | crc32, write last - writing this will complete the OTA operation, now you can read result |
|
||||
| 5e134862-7411-4424-ac4a-210937432c77 | read,notify | result code, readable but will notify when the OTA operation completes |
|
||||
| 5e134862-7411-4424-ac4a-210937432c67 | write | sets the region for programming, currently only 0 (app) or 100 (spiffs) are defined, if not set app is assumed |
|
||||
| GATT_UUID_SW_VERSION_STR/0x2a28 | read | We also implement these standard GATT entries because SW update probably needs them: |
|
||||
| GATT_UUID_MANU_NAME/0x2a29 | read | |
|
||||
| GATT_UUID_HW_VERSION_STR/0x2a27 | read | |
|
||||
|
||||
### DeviceInformationService
|
||||
#### DeviceInformationService
|
||||
|
||||
Implements the standard BLE contract for this service (has software version, hardware model, serial number, etc...)
|
||||
|
||||
### BatteryLevelService
|
||||
#### BatteryLevelService
|
||||
|
||||
Implements the standard BLE contract service, provides battery level in a way that most client devices should automatically understand (i.e. it should show in the bluetooth devices screen automatically)
|
||||
23
docs/software/esp32-arduino-build-notes.md
Normal file
23
docs/software/esp32-arduino-build-notes.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# esp32-arduino build instructions
|
||||
|
||||
We build our own custom version of esp32-arduino, in order to get some fixes we've made but haven't yet been merged in master.
|
||||
|
||||
These are a set of currently unformatted notes on how to build and install them. Most developers should not care about this, because
|
||||
you'll automatically get our fixed libraries.
|
||||
|
||||
```
|
||||
last EDF release in arduino is: https://github.com/espressif/arduino-esp32/commit/1977370e6fc069e93ffd8818798fbfda27ae7d99
|
||||
IDF release/v3.3 46b12a560
|
||||
IDF release/v3.3 367c3c09c
|
||||
https://docs.espressif.com/projects/esp-idf/en/release-v3.3/get-started/linux-setup.html
|
||||
kevinh@kevin-server:~/development/meshtastic/esp32-arduino-lib-builder\$ python /home/kevinh/development/meshtastic/esp32-arduino-lib-builder/esp-idf/components/esptool*py/esptool/esptool.py --chip esp32 --port /dev/ttyUSB0 --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dout --flash_freq 40m --flash_size detect 0x1000 /home/kevinh/development/meshtastic/esp32-arduino-lib-builder/build/bootloader/bootloader.bin
|
||||
cp -a out/tools/sdk/* components/arduino/tools/sdk
|
||||
cp -ar components/arduino/* ~/.platformio/packages/framework-arduinoespressif32
|
||||
|
||||
/// @src-fba9d33740f719f712e9f8b07da6ea13/
|
||||
|
||||
or
|
||||
|
||||
cp -ar out/tools/sdk/* ~/.platformio/packages/framework-arduinoespressif32/tools/sdk
|
||||
|
||||
```
|
||||
17
docs/software/gps-todo.txt
Normal file
17
docs/software/gps-todo.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
You probably don't care about this ugly file of personal notes ;-)
|
||||
|
||||
for taiwan region:
|
||||
bin/run.sh --set region 8
|
||||
|
||||
time only mode
|
||||
./bin/run.sh --set gps_operation 3
|
||||
|
||||
ublox parsing failure
|
||||
|
||||
record power measurements and update spreadsheet
|
||||
|
||||
have loop methods return allowable sleep time (from their perspective)
|
||||
increase main cpu sleep time
|
||||
|
||||
warn people about crummy gps antennas - add to faq
|
||||
|
||||
@@ -1,5 +1,75 @@
|
||||
# Mesh broadcast algorithm
|
||||
|
||||
## Current algorithm
|
||||
|
||||
The routing protocol for Meshtastic is really quite simple (and suboptimal). It is heavily influenced by the mesh routing algorithm used in [Radiohead](https://www.airspayce.com/mikem/arduino/RadioHead/) (which was used in very early versions of this project). It has four conceptual layers.
|
||||
|
||||
### A note about protocol buffers
|
||||
|
||||
Because we want our devices to work across various vendors and implementations, we use [Protocol Buffers](https://github.com/meshtastic/Meshtastic-protobufs) pervasively. For information on how the protocol buffers are used wrt API clients see [sw-design](sw-design.md), for purposes of this document you mostly only
|
||||
need to consider the MeshPacket and Subpacket message types.
|
||||
|
||||
### Layer 1: Non reliable zero hop messaging
|
||||
|
||||
This layer is conventional non-reliable lora packet transmission. The transmitted packet has the following representation on the ether:
|
||||
|
||||
- A 32 bit LORA preamble (to allow receiving radios to synchronize clocks and start framing). We use a longer than minimum (8 bit) preamble to maximize the amount of time the LORA receivers can stay asleep, which dramatically lowers power consumption.
|
||||
|
||||
After the preamble the 16 byte packet header is transmitted. This header is described directly by the PacketHeader class in the C++ source code. But indirectly it matches the first portion of the "MeshPacket" protobuf definition. But notably: this portion of the packet is sent directly as the following 16 bytes (rather than using the protobuf encoding). We do this to both save airtime and to allow receiving radio hardware the option of filtering packets before even waking the main CPU.
|
||||
|
||||
- to (4 bytes): the unique NodeId of the destination (or 0xffffffff for NodeNum_BROADCAST)
|
||||
- from (4 bytes): the unique NodeId of the sender)
|
||||
- id (4 bytes): the unique (wrt the sending node only) packet ID number for this packet. We use a large (32 bit) packet ID to ensure there is enough unique state to protect any encrypted payload from attack.
|
||||
- flags (4 bytes): Only a few bits are are currently used - 3 bits for for the "HopLimit" (see below) and 1 bit for "WantAck"
|
||||
|
||||
After the packet header the actual packet is placed onto the the wire. These bytes are merely the encrypted packed protobuf encoding of the SubPacket protobuf. A full description of our encryption is available in [crypto](crypto.md). It is worth noting that only this SubPacket is encrypted, headers are not. Which leaves open the option of eventually allowing nodes to route packets without knowing the keys used to encrypt.
|
||||
|
||||
NodeIds are constructed from the bottom four bytes of the macaddr of the bluetooth address. Because the OUI is assigned by the IEEE and we currently only support a few CPU manufacturers, the upper byte is defacto guaranteed unique for each vendor. The bottom 3 bytes are guaranteed unique by that vendor.
|
||||
|
||||
To prevent collisions all transmitters will listen before attempting to send. If they hear some other node transmitting, they will reattempt transmission in x milliseconds. This retransmission delay is random between FIXME and FIXME (these two numbers are currently hardwired, but really should be scaled based on expected packet transmission time at current channel settings).
|
||||
|
||||
### Layer 2: Reliable zero hop messaging
|
||||
|
||||
This layer adds reliable messaging between the node and its immediate neighbors (only).
|
||||
|
||||
The default messaging provided by layer-1 is extended by setting the "want-ack" flag in the MeshPacket protobuf. If want-ack is set the following documentation from mesh.proto applies:
|
||||
|
||||
"""This packet is being sent as a reliable message, we would prefer it to arrive
|
||||
at the destination. We would like to receive a ack packet in response.
|
||||
|
||||
Broadcasts messages treat this flag specially: Since acks for broadcasts would
|
||||
rapidly flood the channel, the normal ack behavior is suppressed. Instead,
|
||||
the original sender listens to see if at least one node is rebroadcasting this
|
||||
packet (because naive flooding algorithm). If it hears that the odds (given
|
||||
typical LoRa topologies) the odds are very high that every node should
|
||||
eventually receive the message. So FloodingRouter.cpp generates an implicit
|
||||
ack which is delivered to the original sender. If after some time we don't
|
||||
hear anyone rebroadcast our packet, we will timeout and retransmit, using the
|
||||
regular resend logic."""
|
||||
|
||||
If a transmitting node does not receive an ACK (or a NAK) packet within FIXME milliseconds, it will use layer-1 to attempt a retransmission of the sent packet. A reliable packet (at this 'zero hop' level) will be resent a maximum of three times. If no ack or nak has been received by then the local node will internally generate a nak (either for local consumption or use by higher layers of the protocol).
|
||||
|
||||
### Layer 3: (Naive) flooding for multi-hop messaging
|
||||
|
||||
Given our use-case for the initial release, most of our protocol is built around [flooding](<https://en.wikipedia.org/wiki/Flooding_(computer_networking)>). The implementation is currently 'naive' - i.e. it doesn't try to optimize flooding other than abandoning retransmission once we've seen a nearby receiver has acked the packet. Therefore, for each source packet up to N retransmissions might occur (if there are N nodes in the mesh).
|
||||
|
||||
Each node in the mesh, if it sees a packet on the ether with HopLimit set to a value other than zero, it will decrement that HopLimit and attempt retransmission on behalf of the original sending node.
|
||||
|
||||
### Layer 4: DSR for multi-hop unicast messaging
|
||||
|
||||
This layer is not yet fully implemented (and not yet used). But eventually (if we stay with our own transport rather than switching to QMesh or Reticulum)
|
||||
we will use conventional DSR for unicast messaging. Currently (even when not requiring 'broadcasts') we send any multi-hop unicasts as 'broadcasts' so that we can
|
||||
leverage our (functional) flooding implementation. This is suboptimal but it is a very rare use-case, because the odds are high that most nodes (given our small networks and 'hiking' use case) are within a very small number of hops. When any node witnesses an ack for a packet, it will realize that it can abandon its own
|
||||
broadcast attempt for that packet.
|
||||
|
||||
## Misc notes on remaining tasks
|
||||
|
||||
This section is currently poorly formatted, it is mostly a mere set of todo lists and notes for @geeksville during his initial development. After release 1.0 ideas for future optimization include:
|
||||
|
||||
- Make flood-routing less naive (because we have GPS and radio signal strength as heuristics to avoid redundant retransmissions)
|
||||
- If nodes have been user marked as 'routers', preferentially do flooding via those nodes
|
||||
- Fully implement DSR to improve unicast efficiency (or switch to QMesh/Reticulum as these projects mature)
|
||||
|
||||
great source of papers and class notes: http://www.cs.jhu.edu/~cs647/
|
||||
|
||||
flood routing improvements
|
||||
@@ -19,20 +89,21 @@ reliable messaging tasks (stage one for DSR):
|
||||
- DONE once an ack comes in, remove the packet from the retry list and deliver the ack to the original sender
|
||||
- DONE after three retries, deliver a no-ack packet to the original sender (i.e. the phone app or mesh router service)
|
||||
- DONE test one hop ack/nak with the python framework
|
||||
- Do stress test with acks
|
||||
- DONE Do stress test with acks
|
||||
|
||||
dsr tasks
|
||||
|
||||
- oops I might have broken message reception
|
||||
- DONE oops I might have broken message reception
|
||||
- DONE Don't use broadcasts for the network pings (close open github issue)
|
||||
- DONE add ignoreSenders to radioconfig to allow testing different mesh topologies by refusing to see certain senders
|
||||
- test multihop delivery with the python framework
|
||||
- DONE test multihop delivery with the python framework
|
||||
|
||||
optimizations / low priority:
|
||||
|
||||
- read this [this](http://pages.cs.wisc.edu/~suman/pubs/nadv-mobihoc05.pdf) paper and others and make our naive flood routing less naive
|
||||
- read @cyclomies long email with good ideas on optimizations and reply
|
||||
- Remove NodeNum assignment algorithm (now that we use 4 byte node nums)
|
||||
- make android app warn if firmware is too old or too new to talk to
|
||||
- DONE Remove NodeNum assignment algorithm (now that we use 4 byte node nums)
|
||||
- DONE make android app warn if firmware is too old or too new to talk to
|
||||
- change nodenums and packetids in protobuf to be fixed32
|
||||
- low priority: think more careful about reliable retransmit intervals
|
||||
- make ReliableRouter.pending threadsafe
|
||||
@@ -145,23 +216,3 @@ look into the literature for this idea specifically.
|
||||
build the most recent version of reality, and if some nodes are too far, then nodes closer in will eventually forward their changes to the distributed db.
|
||||
- construct non ambigious rules for who broadcasts to request db updates. ideally the algorithm should nicely realize node X can see most other nodes, so they should just listen to all those nodes and minimize the # of broadcasts. the distributed picture of nodes rssi could be useful here?
|
||||
- possibly view the BLE protocol to the radio the same way - just a process of reconverging the node/msgdb database.
|
||||
|
||||
# Old notes
|
||||
|
||||
FIXME, merge into the above:
|
||||
|
||||
good description of batman protocol: https://www.open-mesh.org/projects/open-mesh/wiki/BATMANConcept
|
||||
|
||||
interesting paper on lora mesh: https://portal.research.lu.se/portal/files/45735775/paper.pdf
|
||||
It seems like DSR might be the algorithm used by RadioheadMesh. DSR is described in https://tools.ietf.org/html/rfc4728
|
||||
https://en.wikipedia.org/wiki/Dynamic_Source_Routing
|
||||
|
||||
broadcast solution:
|
||||
Use naive flooding at first (FIXME - do some math for a 20 node, 3 hop mesh. A single flood will require a max of 20 messages sent)
|
||||
Then move to MPR later (http://www.olsr.org/docs/report_html/node28.html). Use altitude and location as heursitics in selecting the MPR set
|
||||
|
||||
compare to db sync algorithm?
|
||||
|
||||
what about never flooding gps broadcasts. instead only have them go one hop in the common case, but if any node X is looking at the position of Y on their gui, then send a unicast to Y asking for position update. Y replies.
|
||||
|
||||
If Y were to die, at least the neighbor nodes of Y would have their last known position of Y.
|
||||
|
||||
@@ -1,12 +1,119 @@
|
||||
# NRF52 TODO
|
||||
|
||||
- Possibly switch from softdevice to Apachy Newt: https://github.com/espressif/esp-nimble
|
||||
https://github.com/apache/mynewt-core - use nimble BLE on both ESP32 and NRF52
|
||||
|
||||
## RAK815
|
||||
|
||||
### PPR1 TODO
|
||||
|
||||
* V_BK for the GPS should probably be supplied from something always on
|
||||
|
||||
* use S113 soft device 7.2.0
|
||||
* properly test charge controller config and read battery/charge status
|
||||
* fix bluetooth
|
||||
* fix LCD max contrast (currently too high, needs to be about 40?)
|
||||
* save brightness settings in flash
|
||||
* make ST7567Wire driver less ugly, move OLED stuff into a common class treee
|
||||
* add LCD power save mode for lcd per page 31 of datasheet
|
||||
* add LCD power off sequence per datasheet to lcd driver
|
||||
* leave LCD screen on most of the time (because it needs little power)
|
||||
|
||||
### general nrf52 TODO:
|
||||
|
||||
- turn off transitions on eink screens
|
||||
- change update interval on eink from 1/sec frames to one frame every 5 mins
|
||||
- enter SDS state at correct time (to protect battery or loss of phone contact)
|
||||
- show screen on eink when we enter SDS state (with app info and say sleeping)
|
||||
- require button press to pair
|
||||
|
||||
- shrink soft device RAM usage
|
||||
- get nrf52832 working again (currently OOM)
|
||||
- i2c gps comms not quite right
|
||||
- ble: AdafruitBluefruit::begin - adafruit_ble_task was assigned an invalid stack pointer. out of memory?
|
||||
- measure power draw
|
||||
|
||||
### Bootloader
|
||||
|
||||
Install our (temporarily hacked up) adafruit bootloader
|
||||
|
||||
```
|
||||
kevinh@kevin-server:~/development/meshtastic/Adafruit_nRF52_Bootloader$ make BOARD=rak815 sd flash
|
||||
LD rak815_bootloader-0.3.2-111-g9478eb7-dirty.out
|
||||
text data bss dec hex filename
|
||||
20888 1124 15006 37018 909a _build/build-rak815/rak815_bootloader-0.3.2-111-g9478eb7-dirty.out
|
||||
Create rak815_bootloader-0.3.2-111-g9478eb7-dirty.hex
|
||||
Create rak815_bootloader-0.3.2-111-g9478eb7-dirty-nosd.hex
|
||||
Flashing: rak815_bootloader-0.3.2-111-g9478eb7-dirty-nosd.hex
|
||||
nrfjprog --program _build/build-rak815/rak815_bootloader-0.3.2-111-g9478eb7-dirty-nosd.hex --sectoranduicrerase -f nrf52 --reset
|
||||
Parsing hex file.
|
||||
Erasing page at address 0x0.
|
||||
Erasing page at address 0x74000.
|
||||
Erasing page at address 0x75000.
|
||||
Erasing page at address 0x76000.
|
||||
Erasing page at address 0x77000.
|
||||
Erasing page at address 0x78000.
|
||||
Erasing page at address 0x79000.
|
||||
Erasing UICR flash area.
|
||||
Applying system reset.
|
||||
Checking that the area to write is not protected.
|
||||
Programming device.
|
||||
Applying system reset.
|
||||
Run.
|
||||
```
|
||||
|
||||
### Appload
|
||||
|
||||
tips on installing https://github.com/platformio/platform-nordicnrf52/issues/8#issuecomment-374017768
|
||||
|
||||
to see console output over jlink:
|
||||
|
||||
```
|
||||
12:17
|
||||
in one tab run "bin/nrf52832-gdbserver.sh" - leave this running the whole time while developing/debugging
|
||||
12:17
|
||||
~/development/meshtastic/meshtastic-esp32$ bin/nrf52-console.sh
|
||||
###RTT Client: ************************************************************
|
||||
###RTT Client: * SEGGER Microcontroller GmbH *
|
||||
###RTT Client: * Solutions for real time microcontroller applications *
|
||||
###RTT Client: ************************************************************
|
||||
###RTT Client: * *
|
||||
###RTT Client: * (c) 2012 - 2016 SEGGER Microcontroller GmbH *
|
||||
###RTT Client: * *
|
||||
###RTT Client: * www.segger.com Support: support@segger.com *
|
||||
###RTT Client: * *
|
||||
###RTT Client: ************************************************************
|
||||
###RTT Client: * *
|
||||
###RTT Client: * SEGGER J-Link RTT Client Compiled Apr 7 2020 15:01:22 *
|
||||
###RTT Client: * *
|
||||
###RTT Client: ************************************************************
|
||||
###RTT Client: -----------------------------------------------
|
||||
###RTT Client: Connecting to J-Link RTT Server via localhost:19021 ..............
|
||||
###RTT Client: Connected.
|
||||
SEGGER J-Link V6.70c - Real time terminal output
|
||||
SEGGER J-Link ARM V9.6, SN=69663845
|
||||
Process: JLinkGDBServerCLExein another tab run:
|
||||
12:18
|
||||
On NRF52 I've been using the jlink fake serial console. But since the rak815 has the serial port hooked up we can switch back to that once the basics are working.
|
||||
```
|
||||
|
||||
## Misc work items
|
||||
|
||||
RAM investigation.
|
||||
nRF52832-QFAA 64KB ram, 512KB flash vs
|
||||
nrf52832-QFAB 32KB ram, 512kb flash
|
||||
nrf52833 128KB RAM
|
||||
nrf52840 256KB RAM, 1MB flash
|
||||
|
||||
Manual hacks needed to build (for now):
|
||||
|
||||
kevinh@kevin-server:~/.platformio/packages/framework-arduinoadafruitnrf52/variants\$ ln -s ~/development/meshtastic/meshtastic-esp32/variants/\* .
|
||||
|
||||
## Initial work items
|
||||
|
||||
Minimum items needed to make sure hardware is good.
|
||||
|
||||
- set power UICR per https://devzone.nordicsemi.com/f/nordic-q-a/28562/nrf52840-regulator-configuration
|
||||
- DONE set power UICR per https://devzone.nordicsemi.com/f/nordic-q-a/28562/nrf52840-regulator-configuration
|
||||
- switch charge controller into / out of performance mode (see 8.3.1 in datasheet)
|
||||
- write UC1701 wrapper
|
||||
- Test hardfault handler for null ptrs (if one isn't already installed)
|
||||
@@ -109,7 +216,7 @@ Nice ideas worth considering someday...
|
||||
- DONE neg 7 error code from receive
|
||||
- DONE remove unused sx1262 lib from github
|
||||
- at boot we are starting our message IDs at 1, rather we should start them at a random number. also, seed random based on timer. this could be the cause of our first message not seen bug.
|
||||
- add a NEMA based GPS driver to test GPS
|
||||
- add a NMEA based GPS driver to test GPS
|
||||
- DONE use "variants" to get all gpio bindings
|
||||
- DONE plug in correct variants for the real board
|
||||
- turn on DFU assistance in the appload using the nordic DFU helper lib call
|
||||
|
||||
34
docs/software/pinetab.md
Normal file
34
docs/software/pinetab.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Pinetab
|
||||
|
||||
These are **preliminary** notes on support for Meshtastic in the Pinetab.
|
||||
|
||||
A RF95 is connected via a CH341 USB-SPI chip.
|
||||
|
||||
Pin assignments:
|
||||
CS0 from RF95 goes to CS0 on CH341
|
||||
DIO0 from RF95 goes to INT on CH341
|
||||
RST from RF95 goes to RST on CH341
|
||||
|
||||
This linux driver claims to provide USB-SPI support: https://github.com/gschorcht/spi-ch341-usb
|
||||
Notes here on using that driver: https://www.linuxquestions.org/questions/linux-hardware-18/ch341-usb-to-spi-adaptor-driver-doesn%27t-work-4175622736/
|
||||
|
||||
Or if **absolutely** necessary could bitbang: https://www.cnx-software.com/2018/02/16/wch-ch341-usb-to-serial-chip-gets-linux-driver-to-control-gpios-over-usb/
|
||||
|
||||
## Portduino tasks
|
||||
|
||||
* How to access spi devices via ioctl (spidev): https://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md#:~:text=Troubleshooting-,Overview,bus)%2C%20UARTs%2C%20etc.
|
||||
* access gpio via libgpiod?
|
||||
* Use dkms to distribute driver?
|
||||
* echo 100 > /sys/module/spi_ch341_usb/parameters/poll_period
|
||||
|
||||
## Task list
|
||||
|
||||
* Port meshtastic to build (under platformio) for a poxix target. spec: no screen, no gpios, sim network interface, posix threads, posix semaphores & queues, IO to the console only
|
||||
Use ARM linux: https://platformio.org/platforms/linux_arm
|
||||
And linux native: https://platformio.org/platforms/native
|
||||
|
||||
* Test cs341 driver - just test reading/writing a register and detecting interrupts, confirm can see rf95
|
||||
* Make a radiolib spi module that targets the cs341 (and builds on linux)
|
||||
* use new radiolib module to hook pinebook lora to meshtastic, confirm mesh discovery works
|
||||
* Make a subclass of StreamAPI that works as a posix TCP server
|
||||
* Use new TCP endpoint from meshtastic-python
|
||||
76
docs/software/plugin-api.md
Normal file
76
docs/software/plugin-api.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Plugin-API
|
||||
|
||||
This is a tutorial on how to write small plugins which run on the device. Plugins are bits regular 'arduino' code that can send and receive packets to other nodes/apps/PCs using our mesh.
|
||||
|
||||
## Key concepts
|
||||
|
||||
All plugins should be subclasses of MeshPlugin. By inheriting from this class and creating an instance of your new plugin your plugin will be automatically registered to receive packets.
|
||||
|
||||
Messages are sent to particular port numbers (similar to UDP networking). Your new plugin should eventually pick its own port number (see below), but at first you can simply use PRIVATE_APP (which is the default).
|
||||
|
||||
Packets can be sent/received either as raw binary structures or as [Protobufs](https://developers.google.com/protocol-buffers).
|
||||
|
||||
### Class heirarchy
|
||||
|
||||
The relevant bits of the class heirarchy are as follows
|
||||
|
||||
* [MeshPlugin](/src/mesh/MeshPlugin.h) (in src/mesh/MeshPlugin.h) - you probably don't want to use this baseclass directly
|
||||
* [SinglePortPlugin](/src/mesh/SinglePortPlugin.h) (in src/mesh/SinglePortPlugin.h) - for plugins that receive from a single port number (the normal case)
|
||||
* [ProtobufPlugin](/src/mesh/ProtobufPlugin.h) (in src/mesh/ProtobufPlugin.h) - for plugins that are sending/receiving a single particular Protobuf type. Inherit from this if you are using protocol buffers in your plugin.
|
||||
|
||||
You will typically want to inherit from either SinglePortPlugin (if you are just sending raw bytes) or ProtobufPlugin (if you are sending protobufs). You'll implement your own handleReceived/handleReceivedProtobuf - probably based on the example code.
|
||||
|
||||
If your plugin needs to perform any operations at startup you can override and implement the setup() method to run your code.
|
||||
|
||||
If you need to send a packet you can call service.sendToMesh with code like this (from the examples):
|
||||
|
||||
```
|
||||
MeshPacket *p = allocReply();
|
||||
p->to = dest;
|
||||
|
||||
service.sendToMesh(p);
|
||||
```
|
||||
|
||||
## Example plugins
|
||||
|
||||
A number of [key services](/src/plugins) are implemented using the plugin API, these plugins are as follows:
|
||||
|
||||
* [TextMessagePlugin](/src/plugins/TextMessagePlugin.h) - receives text messages and displays them on the LCD screen/stores them in the local DB
|
||||
* [NodeInfoPlugin](/src/plugins/NodeInfoPlugin.h) - receives/sends User information to other nodes so that usernames are available in the databases
|
||||
* [RemoteHardwarePlugin](/src/plugins/RemoteHardwarePlugin.h) - a plugin that provides easy remote access to device hardware (for things like turning GPIOs on or off). Intended to be a more extensive example and provide a useful feature of its own. See [remote-hardware](remote-hardware.md) for details.
|
||||
* [ReplyPlugin](/src/plugins/ReplyPlugin.h) - a simple plugin that just replies to any packet it receives (provides a 'ping' service).
|
||||
|
||||
## Getting started
|
||||
|
||||
The easiest way to get started is:
|
||||
|
||||
* [Build and install](build-instructions.md) the standard codebase from github.
|
||||
* Copy [src/plugins/ReplyPlugin.*](/src/plugins/ReplyPlugin.cpp) into src/plugins/YourPlugin.*. Then change the port number from REPLY_APP to PRIVATE_APP.
|
||||
* Rebuild with your new messaging goodness and install on the device
|
||||
* Use the [meshtastic commandline tool](https://github.com/meshtastic/Meshtastic-python) to send a packet to your board "meshtastic --dest 1234 --ping"
|
||||
|
||||
## Threading
|
||||
|
||||
It is very common that you would like your plugin to be invoked periodically.
|
||||
We use a crude/basic cooperative threading system to allow this on any of our supported platforms. Simply inherit from OSThread and implement runOnce(). See the OSThread [documentation](/src/concurrency/OSThread.h) for more details. For an example consumer of this API see RemoteHardwarePlugin::runOnce.
|
||||
|
||||
## Picking a port number
|
||||
|
||||
For any new 'apps' that run on the device or via sister apps on phones/PCs they should pick and use a unique 'portnum' for their application.
|
||||
|
||||
If you are making a new app using meshtastic, please send in a pull request to add your 'portnum' to [the master list](https://github.com/meshtastic/Meshtastic-protobufs/blob/master/portnums.proto). PortNums should be assigned in the following range:
|
||||
|
||||
* 0-63 Core Meshtastic use, do not use for third party apps
|
||||
* 64-127 Registered 3rd party apps, send in a pull request that adds a new entry to portnums.proto to register your application
|
||||
* 256-511 Use one of these portnums for your private applications that you don't want to register publically
|
||||
* 1024-66559 Are reserved for use by IP tunneling (see FIXME for more information)
|
||||
|
||||
All other values are reserved.
|
||||
|
||||
## How to add custom protocol buffers
|
||||
|
||||
If you would like to use protocol buffers to define the structures you send over the mesh (recommended), here's how to do that.
|
||||
|
||||
* Create a new .proto file in the protos directory. You can use the existing [remote_hardware.proto](https://github.com/meshtastic/Meshtastic-protobufs/blob/master/remote_hardware.proto) file as an example.
|
||||
* Run "bin/regen-protos.sh" to regenerate the C code for accessing the protocol buffers. If you don't have the required nanopb tool, follow the instructions printed by the script to get it.
|
||||
* Done! You can now use your new protobuf just like any of the existing protobufs in meshtastic.
|
||||
@@ -32,21 +32,25 @@ From lower to higher power consumption.
|
||||
onEntry: setBluetoothOn(true)
|
||||
onExit:
|
||||
|
||||
- full on (ON) - Everything is on
|
||||
onEntry: setBluetoothOn(true), screen.setOn(true)
|
||||
onExit: screen.setOn(false)
|
||||
|
||||
- serial API usage (SERIAL) - Screen is on, device doesn't sleep, bluetooth off
|
||||
onEntry: setBluetooth off, screen on
|
||||
onExit:
|
||||
|
||||
- full on (ON) - Everything is on, can eventually timeout and lower to a lower power state
|
||||
onEntry: setBluetoothOn(true), screen.setOn(true)
|
||||
onExit: screen->setOn(false)
|
||||
|
||||
- has power (POWER) - Screen is on, device doesn't sleep, bluetooth on, will stay in this state as long as we have power
|
||||
onEntry: setBluetooth off, screen on
|
||||
onExit:
|
||||
|
||||
## Behavior
|
||||
|
||||
### events that increase CPU activity
|
||||
|
||||
- At cold boot: The initial state (after setup() has run) is DARK
|
||||
- While in DARK: if we receive EVENT_BOOT, transition to ON (and show the bootscreen). This event will be sent if we detect we woke due to reset (as opposed to deep sleep)
|
||||
- While in LS: Once every position_broadcast_secs (default 15 mins) - the unit will wake into DARK mode and broadcast a "networkPing" (our position) and stay alive for wait_bluetooth_secs (default 30 seconds). This allows other nodes to have a record of our last known position if we go away and allows a paired phone to hear from us and download messages.
|
||||
- While in LS: Once every position_broadcast_secs (default 15 mins) - the unit will wake into DARK mode and broadcast a "networkPing" (our position) and stay alive for wait_bluetooth_secs (default 60 seconds). This allows other nodes to have a record of our last known position if we go away and allows a paired phone to hear from us and download messages.
|
||||
- While in LS: Every send*owner_interval (defaults to 4, i.e. one hour), when we wake to send our position we \_also* broadcast our owner. This lets new nodes on the network find out about us or correct duplicate node number assignments.
|
||||
- While in LS/NB/DARK: If the user presses a button (EVENT_PRESS) we go to full ON mode for screen_on_secs (default 30 seconds). Multiple presses keeps resetting this timeout
|
||||
- While in LS/NB/DARK: If we receive new text messages (EVENT_RECEIVED_TEXT_MSG), we go to full ON mode for screen_on_secs (same as if user pressed a button)
|
||||
@@ -56,9 +60,11 @@ From lower to higher power consumption.
|
||||
- While in NB/DARK/ON: If we receive EVENT_NODEDB_UPDATED we transition to ON (so the new screen can be shown)
|
||||
- While in DARK: While the phone talks to us over BLE (EVENT_CONTACT_FROM_PHONE) reset any sleep timers and stay in DARK (needed for bluetooth sw update and nice user experience if the user is reading/replying to texts)
|
||||
- while in LS/NB/DARK: if SERIAL_CONNECTED, go to serial
|
||||
- while in any state: if we have AC power, go to POWER
|
||||
|
||||
### events that decrease cpu activity
|
||||
|
||||
- While in POWER: if lose AC go to ON
|
||||
- While in SERIAL: if SERIAL_DISCONNECTED, go to NB
|
||||
- While in ON: If PRESS event occurs, reset screen_on_secs timer and tell the screen to handle the pess
|
||||
- While in ON: If it has been more than screen_on_secs since a press, lower to DARK
|
||||
|
||||
6
docs/software/rak815.md
Normal file
6
docs/software/rak815.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# RAK815
|
||||
|
||||
Notes on trying to get the RAK815 working with meshtastic.
|
||||
|
||||
good tutorial: https://www.hackster.io/naresh-krish/getting-started-with-rak815-tracker-module-and-arduino-1c7bc9
|
||||
(includes software serial link - possibly useful for GPS)
|
||||
202
docs/software/ramusage-nrf52.txt
Normal file
202
docs/software/ramusage-nrf52.txt
Normal file
@@ -0,0 +1,202 @@
|
||||
23K + messages
|
||||
+ heap of 70ish packets, 300ish bytes per packet: 20KB
|
||||
+ 14KB soft device RAM
|
||||
|
||||
With max length Data inside the packet
|
||||
Size of NodeInfo 104
|
||||
Size of SubPacket 272
|
||||
Size of MeshPacket 304
|
||||
|
||||
If Data was smaller: for 70 data packets we would save 7KB. We would need to make SubPacket.data and MeshPacket.encrypted into "type:FT_POINTER" - variably sized mallocs
|
||||
Size of NodeInfo 104
|
||||
Size of SubPacket 96
|
||||
Size of MeshPacket 292 (could have been much smaller but I forgot to shrink MeshPacket.encrypted)
|
||||
|
||||
therefore:
|
||||
a) we should store all ToPhone message queued messages compressed as protobufs (since they will become that anyways)
|
||||
b) shrink packet pool size because none of that storage will be used for ToPhone packets
|
||||
c) don't allocate any storage in RAM for the tophone messages we save inside device state, instead just use nanopb callbacks to save/load those
|
||||
d) a smarter MeshPacket in memory representation would save about 7KB of RAM. call pb_release before freeing each freshly malloced MeshPacket
|
||||
|
||||
- nrf52 free memory https://learn.adafruit.com/bluefruit-nrf52-feather-learning-guide/hathach-memory-map
|
||||
|
||||
2000790c 00003558 B devicestate // 16KB
|
||||
2000b53c 00001000 b _cache_buffer // 4KB flash filesystem support
|
||||
20003b1c 000006b0 B console
|
||||
2000d5f4 00000400 b vApplicationGetTimerTaskMemory::uxTimerTaskStack
|
||||
2000da04 00000400 b _acUpBuffer
|
||||
2000c558 0000036c B Bluefruit
|
||||
2000c8d8 00000358 b _cdcd_itf
|
||||
2000e54c 00000258 B _midid_itf
|
||||
2000d0dc 00000200 b ucStaticTimerQueueStorage.9390
|
||||
2000e044 00000200 b _mscd_buf
|
||||
2000e284 000001cc b _vendord_itf
|
||||
2000d410 00000190 b vApplicationGetIdleTaskMemory::uxIdleTaskStack
|
||||
2000374c 0000016c D __global_locale
|
||||
2000de48 0000012c B USBDevice
|
||||
2000afa4 00000100 b Router::send(_MeshPacket*)::bytes
|
||||
2000aea4 00000100 b Router::perhapsDecode(_MeshPacket*)::bytes
|
||||
200039b0 000000f4 B powerFSM
|
||||
20004258 000000f0 B screen
|
||||
2000cd7c 000000c4 b _dcd
|
||||
2000cc68 000000c0 b _usbd_qdef_buf
|
||||
2000b3c4 000000bc B Wire
|
||||
2000cef4 000000a8 B Serial2
|
||||
2000ce4c 000000a8 B Serial1
|
||||
2000e498 000000a8 B _SEGGER_RTT
|
||||
2000b498 000000a4 B InternalFS
|
||||
2000dfb8 0000008c b _hidd_itf
|
||||
2000b260 00000088 b meshtastic::normalFrames
|
||||
2000cfdc 00000064 b pxReadyTasksLists
|
||||
2000b340 00000060 b meshtastic::drawTextMessageFrame(OLEDDisplay*, OLEDDisplayUiState*, short, short)::tempBuf
|
||||
200036ec 00000060 d impure_data
|
||||
2000b104 00000060 B bledfu
|
||||
2000b0a4 00000060 B blebas
|
||||
20003684 00000058 D _usbd_qdef
|
||||
200038c0 00000058 d tzinfo
|
||||
2000d5a0 00000054 b vApplicationGetTimerTaskMemory::xTimerTaskTCB
|
||||
2000d3bc 00000054 b vApplicationGetIdleTaskMemory::xIdleTaskTCB
|
||||
2000d308 00000050 b xStaticTimerQueue.9389
|
||||
2000b1f4 00000050 B hrmc
|
||||
2000b1a4 00000050 B bslc
|
||||
20004360 0000004c B service
|
||||
2000d374 00000048 b m_cb
|
||||
2000df74 00000042 b _desc_str
|
||||
2000cd3c 00000040 b _usbd_ctrl_buf
|
||||
20004214 00000040 B realRouter
|
||||
2000e244 00000040 b _mscd_itf
|
||||
2000b164 00000040 B bledis
|
||||
20003634 00000038 d _InternalFSConfig
|
||||
2000cc30 00000031 b _usbd_dev
|
||||
2000398c 00000020 B periodicScheduler
|
||||
2000cfa4 00000020 b callbacksInt
|
||||
2000de10 0000001f b fw_str.13525
|
||||
20003974 00000018 b object.9934
|
||||
2000ae68 00000018 B nodeDB
|
||||
2000366c 00000018 d _cache
|
||||
2000b314 00000014 b meshtastic::drawNodeInfo(OLEDDisplay*, OLEDDisplayUiState*, short, short)::signalStr
|
||||
2000b300 00000014 b meshtastic::drawNodeInfo(OLEDDisplay*, OLEDDisplayUiState*, short, short)::lastStr
|
||||
2000b2ec 00000014 b meshtastic::drawNodeInfo(OLEDDisplay*, OLEDDisplayUiState*, short, short)::distStr
|
||||
200041e0 00000014 b getDeviceName()::name
|
||||
2000d0b8 00000014 b xTasksWaitingTermination
|
||||
2000d0a4 00000014 b xSuspendedTaskList
|
||||
2000d08c 00000014 b xPendingReadyList
|
||||
2000d06c 00000014 b xDelayedTaskList2
|
||||
2000d058 00000014 b xDelayedTaskList1
|
||||
2000d2f0 00000014 b xActiveTimerList2
|
||||
2000d2dc 00000014 b xActiveTimerList1
|
||||
2000b480 00000014 B SPI
|
||||
2000c8c4 00000014 B Serial
|
||||
2000cd28 00000014 b _ctrl_xfer
|
||||
2000de30 00000011 b serial_str.13534
|
||||
2000c544 00000010 b BLEAdvertising::_start(unsigned short, unsigned short)::gap_adv
|
||||
20003614 00000010 d meshtastic::btPIN
|
||||
2000434c 00000010 b sendOwnerPeriod
|
||||
2000ae8c 00000010 b staticPool
|
||||
2000e484 00000010 B xQueueRegistry
|
||||
20003b04 00000010 B stateSERIAL
|
||||
20003af4 00000010 B stateSDS
|
||||
20003ae4 00000010 B stateON
|
||||
20003ad4 00000010 B stateNB
|
||||
20003ac4 00000010 B stateLS
|
||||
20003ab4 00000010 B stateDARK
|
||||
20003aa4 00000010 B stateBOOT
|
||||
200041f8 00000010 B ledPeriodic
|
||||
2000b244 00000010 B hrms
|
||||
2000d9f4 00000010 b _acDownBuffer
|
||||
2000b3b8 0000000c B preflightSleep
|
||||
20004208 0000000c B powerStatus
|
||||
2000e540 0000000c B nrf_nvic_state
|
||||
2000b3ac 0000000c B notifySleep
|
||||
2000b3a0 0000000c B notifyDeepSleep
|
||||
2000e463 0000000b b __tzname_std
|
||||
2000e458 0000000b b __tzname_dst
|
||||
2000b338 00000008 b meshtastic::estimatedHeading(double, double)::oldLon
|
||||
2000b330 00000008 b meshtastic::estimatedHeading(double, double)::oldLat
|
||||
200041d0 00000008 b zeroOffsetSecs
|
||||
2000ae80 00000008 b spiSettings
|
||||
200038b8 00000008 D _tzname
|
||||
20003b14 00000008 B noopPrint
|
||||
2000cfc4 00000008 b channelMap
|
||||
2000cf9c 00000008 b callbackDeferred
|
||||
200043ac 00000006 b ourMacAddr
|
||||
2000435c 00000004 b MeshService::onGPSChanged(void*)::lastGpsSend
|
||||
2000b32c 00000004 b meshtastic::estimatedHeading(double, double)::b
|
||||
2000b328 00000004 b meshtastic::drawNodeInfo(OLEDDisplay*, OLEDDisplayUiState*, short, short)::simRadian
|
||||
2000362c 00000004 d meshtastic::Screen::setup()::bootFrames
|
||||
20003628 00000004 d meshtastic::Screen::handleStartBluetoothPinScreen(unsigned long)::btFrames
|
||||
200039ac 00000004 b onEnter()::lastPingMs
|
||||
2000ae9c 00000004 b generatePacketId()::i
|
||||
2000ae88 00000004 B RadioLibInterface::instance
|
||||
2000b2e8 00000004 b meshtastic::nodeIndex
|
||||
20003610 00000004 d meshtastic::targetFramerate
|
||||
2000c554 00000004 B BLEService::lastService
|
||||
200041cc 00000004 b timeStartMsec
|
||||
200036dc 00000004 d sbrk_heap_top
|
||||
2000d364 00000004 b _loopHandle
|
||||
2000c540 00000004 b guard variable for BLEAdvertising::_start(unsigned short, unsigned short)::gap_adv
|
||||
2000d0d0 00000004 b xYieldPending
|
||||
2000d35c 00000004 b xTimerTaskHandle
|
||||
2000d358 00000004 b xTimerQueue
|
||||
2000d0cc 00000004 b xTickCount
|
||||
2000d0a0 00000004 b xSchedulerRunning
|
||||
2000d088 00000004 b xNumOfOverflows
|
||||
2000d084 00000004 b xNextTaskUnblockTime
|
||||
2000d304 00000004 b xLastTime.9343
|
||||
2000d080 00000004 b xIdleTaskHandle
|
||||
2000d054 00000004 b uxTopReadyPriority
|
||||
2000d050 00000004 b uxTaskNumber
|
||||
2000d04c 00000004 b uxSchedulerSuspended
|
||||
2000d048 00000004 b uxPendedTicks
|
||||
2000d044 00000004 b uxDeletedTasksWaitingCleanUp
|
||||
2000d040 00000004 b uxCurrentNumberOfTasks
|
||||
2000d360 00000004 b uxCriticalNesting
|
||||
2000cc64 00000004 b _usbd_q
|
||||
2000e478 00000004 B _timezone
|
||||
200036e0 00000004 D SystemCoreClock
|
||||
2000c53c 00000004 b _sem
|
||||
2000d0d8 00000004 b pxOverflowTimerList
|
||||
2000cfd8 00000004 b pxOverflowDelayedTaskList
|
||||
2000cfd4 00000004 b pxDelayedTaskList
|
||||
2000d0d4 00000004 b pxCurrentTimerList
|
||||
2000cfd0 00000004 B pxCurrentTCB
|
||||
2000e470 00000004 b prev_tzenv
|
||||
2000360c 00000004 D preftmp
|
||||
20003608 00000004 D preffile
|
||||
2000b25c 00000004 B nrf52Bluetooth
|
||||
2000d370 00000004 b m_usbevt_handler
|
||||
2000d36c 00000004 b m_sleepevt_handler
|
||||
2000d368 00000004 b m_pofwarn_handler
|
||||
2000e454 00000004 B __malloc_sbrk_start
|
||||
2000e450 00000004 B __malloc_free_list
|
||||
2000e480 00000004 B MAIN_MonCnt
|
||||
2000e47c 00000004 b initial_env
|
||||
200036e8 00000004 D _impure_ptr
|
||||
200041d8 00000004 B gps
|
||||
2000e7a4 00000004 B errno
|
||||
20003918 00000004 D environ
|
||||
2000cfcc 00000004 b enabled
|
||||
2000ae64 00000004 B displayedNodeNum
|
||||
2000e474 00000004 B _daylight
|
||||
2000b254 00000004 B crypto
|
||||
2000ce44 00000004 B count_duration
|
||||
2000de0c 00000004 b _cb_task
|
||||
2000de08 00000004 b _cb_queue
|
||||
2000de04 00000004 b _cb_qdepth
|
||||
2000de44 00000004 B bootloaderVersion
|
||||
200041f5 00000001 b ledBlinker()::ledOn
|
||||
20003604 00000001 d loop::showingBootScreen
|
||||
200041f4 00000001 b loop::wasPressed
|
||||
2000b494 00000001 b DefaultFontTableLookup(unsigned char)::LASTCHAR
|
||||
2000aea0 00000001 b generatePacketId()::didInit
|
||||
20003624 00000001 d meshtastic::prevFrame
|
||||
2000b258 00000001 b bleOn
|
||||
200041dc 00000001 B timeSetFromGPS
|
||||
20004348 00000001 B ssd1306_found
|
||||
2000ce49 00000001 B pin_sound
|
||||
2000e494 00000001 B nrfx_power_irq_enabled
|
||||
2000ce48 00000001 B no_stop
|
||||
20003630 00000001 D neo6M
|
||||
2000ce40 00000001 b _initialized
|
||||
200036e4 00000001 D __fdlib_version
|
||||
20003970 00000001 b completed.9929
|
||||
148
docs/software/read-error.txt
Normal file
148
docs/software/read-error.txt
Normal file
@@ -0,0 +1,148 @@
|
||||
nimble stress test error (private notes for @geeksville)
|
||||
|
||||
findings:
|
||||
only happens when stress testing multiple sleepwake cycles?
|
||||
failed packets all have initial mbuflen of zero (should be 1)
|
||||
restarting the connection on phone sometimes (but not always) fixes it (is the larger config nonce pushing packet size up too large?)
|
||||
- packets >= 79 bytes (FromRadio) cause INVALID_OFFSET (7) gatt errors to be sent to the app
|
||||
- some packets are missing
|
||||
|
||||
theory:
|
||||
some sort of leak in mbuf storage during unfortunately timed sleep shutdowns
|
||||
|
||||
|
||||
device side
|
||||
|
||||
|
||||
connection updated; status=0 handle=0 our_ota_addr_type=0 our_ota_addr=00:24:62:ab:dd:df
|
||||
our_id_addr_type=0 our_id_addr=00:24:62:ab:dd:df
|
||||
peer_ota_addr_type=0 peer_ota_addr=00:7c:d9:5c:ba:2e
|
||||
peer_id_addr_type=0 peer_id_addr=00:7c:d9:5c:ba:2e
|
||||
conn_itvl=36 conn_latency=0 supervision_timeout=500 encrypted=1 authenticated=1 bonded=1
|
||||
|
||||
BLE fromRadio called
|
||||
getFromRadio, !available
|
||||
toRadioWriteCb data 0x3ffc3d72, len 4
|
||||
Trigger powerFSM 9
|
||||
Transition powerFSM transition=Contact from phone, from=DARK to=DARK
|
||||
Client wants config, nonce=6864
|
||||
Reset nodeinfo read pointer
|
||||
toRadioWriteCb data 0x3ffc3d72, len 4
|
||||
Trigger powerFSM 9
|
||||
Transition powerFSM transition=Contact from phone, from=DARK to=DARK
|
||||
Client wants config, nonce=6863
|
||||
Reset nodeinfo read pointer
|
||||
BLE fromRadio called
|
||||
getFromRadio, state=2
|
||||
encoding toPhone packet to phone variant=3, 50 bytes
|
||||
BLE fromRadio called
|
||||
getFromRadio, state=3
|
||||
encoding toPhone packet to phone variant=6, 83 bytes
|
||||
BLE fromRadio called
|
||||
getFromRadio, state=4
|
||||
Sending nodeinfo: num=0xabdddf38, lastseen=1595606850, id=!2462abdddf38, name=Bob b
|
||||
encoding toPhone packet to phone variant=4, 67 bytes
|
||||
BLE fromRadio called
|
||||
getFromRadio, state=4
|
||||
Sending nodeinfo: num=0x28b200b4, lastseen=1595606804, id=!246f28b200b4, name=Unknown 00b4
|
||||
encoding toPhone packet to phone variant=4, 80 bytes
|
||||
BLE fromRadio called
|
||||
getFromRadio, state=4
|
||||
Sending nodeinfo: num=0xabf84098, lastseen=1593680756, id=!2462abf84098, name=bx n
|
||||
encoding toPhone packet to phone variant=4, 72 bytes
|
||||
BLE fromRadio called
|
||||
getFromRadio, state=4
|
||||
Sending nodeinfo: num=0x83f0d8e5, lastseen=1594686931, id=!e8e383f0d8e5, name=Unknown d8e5
|
||||
encoding toPhone packet to phone variant=4, 64 bytes
|
||||
BLE fromRadio called
|
||||
getFromRadio, state=4
|
||||
Sending nodeinfo: num=0xd1dc7764, lastseen=1595602082, id=!f008d1dc7764, name=dg
|
||||
encoding toPhone packet to phone variant=4, 52 bytes
|
||||
BLE fromRadio called
|
||||
getFromRadio, state=4
|
||||
Sending nodeinfo: num=0xd1dc7828, lastseen=1595598298, id=!f008d1dc7828, name=ryan
|
||||
encoding toPhone packet to phone variant=4, 54 bytes
|
||||
BLE fromRadio called
|
||||
getFromRadio, state=4
|
||||
Done sending nodeinfos
|
||||
getFromRadio, state=5
|
||||
|
||||
|
||||
|
||||
phone side
|
||||
|
||||
2020-07-24 09:11:00.642 6478-6545/com.geeksville.mesh W/com.geeksville.mesh.service.BluetoothInterface: Attempting reconnect
|
||||
2020-07-24 09:11:00.642 6478-6545/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Enqueuing work: connect
|
||||
2020-07-24 09:11:00.642 6478-6545/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth$BluetoothContinuation: Starting work: connect
|
||||
2020-07-24 09:11:00.643 6478-6545/com.geeksville.mesh D/BluetoothGatt: connect() - device: 24:62:AB:DD:DF:3A, auto: false
|
||||
2020-07-24 09:11:00.643 6478-6545/com.geeksville.mesh D/BluetoothGatt: registerApp()
|
||||
2020-07-24 09:11:00.643 6478-6545/com.geeksville.mesh D/BluetoothGatt: registerApp() - UUID=026baf7f-d2de-43f1-961f-4e00e04c6fbb
|
||||
2020-07-24 09:11:00.645 6478-27868/com.geeksville.mesh D/BluetoothGatt: onClientRegistered() - status=0 clientIf=4
|
||||
2020-07-24 09:11:01.022 6478-27868/com.geeksville.mesh D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=4 device=24:62:AB:DD:DF:3A
|
||||
2020-07-24 09:11:01.022 6478-27868/com.geeksville.mesh I/com.geeksville.mesh.service.SafeBluetooth: new bluetooth connection state 2, status 0
|
||||
2020-07-24 09:11:01.023 6478-27868/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: work connect is completed, resuming status=0, res=kotlin.Unit
|
||||
2020-07-24 09:11:01.023 6478-6545/com.geeksville.mesh I/com.geeksville.mesh.service.BluetoothInterface: Connected to radio!
|
||||
2020-07-24 09:11:01.023 6478-6545/com.geeksville.mesh D/BluetoothGatt: refresh() - device: 24:62:AB:DD:DF:3A
|
||||
2020-07-24 09:11:01.526 6478-6545/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Enqueuing work: discover
|
||||
2020-07-24 09:11:01.526 6478-6545/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth$BluetoothContinuation: Starting work: discover
|
||||
2020-07-24 09:11:01.526 6478-6545/com.geeksville.mesh D/BluetoothGatt: discoverServices() - device: 24:62:AB:DD:DF:3A
|
||||
2020-07-24 09:11:01.829 6478-27868/com.geeksville.mesh D/BluetoothGatt: onConnectionUpdated() - Device=24:62:AB:DD:DF:3A interval=6 latency=0 timeout=500 status=0
|
||||
2020-07-24 09:11:02.008 6478-27868/com.geeksville.mesh D/BluetoothGatt: onSearchComplete() = Device=24:62:AB:DD:DF:3A Status=0
|
||||
2020-07-24 09:11:02.009 6478-27868/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: work discover is completed, resuming status=0, res=kotlin.Unit
|
||||
2020-07-24 09:11:02.009 6478-6545/com.geeksville.mesh D/com.geeksville.mesh.service.BluetoothInterface: Discovered services!
|
||||
2020-07-24 09:11:02.095 6478-27868/com.geeksville.mesh D/BluetoothGatt: onConnectionUpdated() - Device=24:62:AB:DD:DF:3A interval=36 latency=0 timeout=500 status=0
|
||||
2020-07-24 09:11:03.010 6478-6545/com.geeksville.mesh D/com.geeksville.mesh.service.RadioInterfaceService: Broadcasting connection=true
|
||||
2020-07-24 09:11:03.012 6478-6545/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Enqueuing work: readC 8ba2bcc2-ee02-4a55-a531-c525c5e454d5
|
||||
2020-07-24 09:11:03.012 6478-6545/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth$BluetoothContinuation: Starting work: readC 8ba2bcc2-ee02-4a55-a531-c525c5e454d5
|
||||
2020-07-24 09:11:03.012 6478-6478/com.geeksville.mesh D/com.geeksville.mesh.service.MeshService: Received broadcast com.geeksville.mesh.CONNECT_CHANGED
|
||||
2020-07-24 09:11:03.012 6478-6478/com.geeksville.mesh D/com.geeksville.mesh.service.MeshService: onConnectionChanged=CONNECTED
|
||||
2020-07-24 09:11:03.012 6478-6478/com.geeksville.mesh D/com.geeksville.mesh.service.MeshService: Starting config nonce=6878
|
||||
2020-07-24 09:11:03.013 6478-6545/com.geeksville.mesh D/com.geeksville.mesh.service.BluetoothInterface: queuing 4 bytes to f75c76d2-129e-4dad-a1dd-7866124401e7 *** sending start config
|
||||
2020-07-24 09:11:03.013 6478-6545/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Enqueuing work: writeC f75c76d2-129e-4dad-a1dd-7866124401e7
|
||||
2020-07-24 09:11:03.015 6478-6478/com.geeksville.mesh D/com.geeksville.mesh.service.MeshService: Received broadcast com.geeksville.mesh.CONNECT_CHANGED
|
||||
2020-07-24 09:11:03.015 6478-6478/com.geeksville.mesh D/com.geeksville.mesh.service.MeshService: onConnectionChanged=CONNECTED
|
||||
2020-07-24 09:11:03.015 6478-6478/com.geeksville.mesh D/com.geeksville.mesh.service.MeshService: Starting config nonce=6877
|
||||
2020-07-24 09:11:03.016 6478-6545/com.geeksville.mesh D/com.geeksville.mesh.service.MeshService: device sleep timeout cancelled
|
||||
2020-07-24 09:11:03.016 6478-6545/com.geeksville.mesh D/com.geeksville.mesh.service.BluetoothInterface: queuing 4 bytes to f75c76d2-129e-4dad-a1dd-7866124401e7
|
||||
2020-07-24 09:11:03.016 6478-6545/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Enqueuing work: writeC f75c76d2-129e-4dad-a1dd-7866124401e7
|
||||
2020-07-24 09:11:03.130 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth$BluetoothContinuation: Starting work: writeC f75c76d2-129e-4dad-a1dd-7866124401e7
|
||||
2020-07-24 09:11:03.132 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: work readC 8ba2bcc2-ee02-4a55-a531-c525c5e454d5 is completed, resuming status=0, res=android.bluetooth.BluetoothGattCharacteristic@556a315
|
||||
2020-07-24 09:11:03.132 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.BluetoothInterface: Done reading from radio, fromradio is empty
|
||||
2020-07-24 09:11:03.132 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: starting setNotify(ed9da18c-a800-4f66-a670-aa7547e34453, true) *** start notify
|
||||
2020-07-24 09:11:03.132 6478-19966/com.geeksville.mesh D/BluetoothGatt: setCharacteristicNotification() - uuid: ed9da18c-a800-4f66-a670-aa7547e34453 enable: true
|
||||
2020-07-24 09:11:03.133 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Enqueuing work: writeD
|
||||
2020-07-24 09:11:03.220 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth$BluetoothContinuation: Starting work: writeC f75c76d2-129e-4dad-a1dd-7866124401e7
|
||||
2020-07-24 09:11:03.221 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: work writeC f75c76d2-129e-4dad-a1dd-7866124401e7 is completed, resuming status=0, res=android.bluetooth.BluetoothGattCharacteristic@2d2062a
|
||||
2020-07-24 09:11:03.221 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.BluetoothInterface: write of 4 bytes completed
|
||||
2020-07-24 09:11:03.221 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Enqueuing work: readC 8ba2bcc2-ee02-4a55-a531-c525c5e454d5
|
||||
2020-07-24 09:11:03.310 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth$BluetoothContinuation: Starting work: writeD
|
||||
2020-07-24 09:11:03.311 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: work writeC f75c76d2-129e-4dad-a1dd-7866124401e7 is completed, resuming status=0, res=android.bluetooth.BluetoothGattCharacteristic@2d2062a
|
||||
2020-07-24 09:11:03.311 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.BluetoothInterface: write of 4 bytes completed
|
||||
2020-07-24 09:11:03.400 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth$BluetoothContinuation: Starting work: readC 8ba2bcc2-ee02-4a55-a531-c525c5e454d5
|
||||
2020-07-24 09:11:03.402 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: work writeD is completed, resuming status=0, res=android.bluetooth.BluetoothGattDescriptor@fc99c1b
|
||||
2020-07-24 09:11:03.402 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Notify enable=true completed
|
||||
2020-07-24 09:11:03.769 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: work readC 8ba2bcc2-ee02-4a55-a531-c525c5e454d5 is completed, resuming status=0, res=android.bluetooth.BluetoothGattCharacteristic@556a315
|
||||
2020-07-24 09:11:03.769 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.BluetoothInterface: Received 80 bytes from radio **** received an 80 byte fromradio. Why did we miss three previous reads?
|
||||
2020-07-24 09:11:03.774 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Enqueuing work: readC 8ba2bcc2-ee02-4a55-a531-c525c5e454d5
|
||||
2020-07-24 09:11:03.774 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth$BluetoothContinuation: Starting work: readC 8ba2bcc2-ee02-4a55-a531-c525c5e454d5
|
||||
2020-07-24 09:11:03.774 6478-6478/com.geeksville.mesh D/com.geeksville.mesh.service.MeshService: Received broadcast com.geeksville.mesh.RECEIVE_FROMRADIO
|
||||
2020-07-24 09:11:03.776 6478-6478/com.geeksville.mesh E/com.geeksville.mesh.service.MeshService: Invalid Protobuf from radio, len=80 (exception Protocol message had invalid UTF-8.)
|
||||
2020-07-24 09:11:03.776 6478-6478/com.geeksville.mesh D/com.geeksville.mesh.service.MeshService: Received broadcast com.geeksville.mesh.RECEIVE_FROMRADIO
|
||||
2020-07-24 09:11:03.776 6478-6478/com.geeksville.mesh E/com.geeksville.mesh.service.MeshService: Invalid Protobuf from radio, len=80 (exception Protocol message had invalid UTF-8.)
|
||||
2020-07-24 09:11:04.031 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: work readC 8ba2bcc2-ee02-4a55-a531-c525c5e454d5 is completed, resuming status=0, res=android.bluetooth.BluetoothGattCharacteristic@556a315
|
||||
2020-07-24 09:11:04.031 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.BluetoothInterface: Received 52 bytes from radio *** received 52 bytes - where did the previous two read results go?
|
||||
2020-07-24 09:11:04.033 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: Enqueuing work: readC 8ba2bcc2-ee02-4a55-a531-c525c5e454d5
|
||||
2020-07-24 09:11:04.033 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth$BluetoothContinuation: Starting work: readC 8ba2bcc2-ee02-4a55-a531-c525c5e454d5
|
||||
2020-07-24 09:11:04.034 6478-6478/com.geeksville.mesh D/com.geeksville.mesh.service.MeshService: Received broadcast com.geeksville.mesh.RECEIVE_FROMRADIO
|
||||
2020-07-24 09:11:04.035 6478-6478/com.geeksville.mesh E/com.geeksville.mesh.service.MeshService: Invalid Protobuf from radio, len=52 (exception While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either that the input has been truncated or that an embedded message misreported its own length.)
|
||||
2020-07-24 09:11:04.036 6478-6478/com.geeksville.mesh D/com.geeksville.mesh.service.MeshService: Received broadcast com.geeksville.mesh.RECEIVE_FROMRADIO
|
||||
2020-07-24 09:11:04.036 6478-6478/com.geeksville.mesh E/com.geeksville.mesh.service.MeshService: Invalid Protobuf from radio, len=52 (exception While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either that the input has been truncated or that an embedded message misreported its own length.)
|
||||
2020-07-24 09:11:04.210 6478-19966/com.geeksville.mesh D/com.geeksville.mesh.service.SafeBluetooth: work readC 8ba2bcc2-ee02-4a55-a531-c525c5e454d5 is completed, resuming status=7, res=android.bluetooth.BluetoothGattCharacteristic@556a315 *** read failed
|
||||
2020-07-24 09:11:04.211 6478-19966/com.geeksville.mesh W/com.geeksville.mesh.service.BluetoothInterface: Scheduling reconnect because error during doReadFromRadio - disconnecting, Bluetooth status=7 while doing readC 8ba2bcc2-ee02-4a55-a531-c525c5e454d5
|
||||
2020-07-24 09:11:04.211 6478-6545/com.geeksville.mesh W/com.geeksville.mesh.service.BluetoothInterface: Forcing disconnect and hopefully device will comeback (disabling forced refresh)
|
||||
2020-07-24 09:11:04.211 6478-6545/com.geeksville.mesh I/com.geeksville.mesh.service.SafeBluetooth: Closing our GATT connection
|
||||
2020-07-24 09:11:04.211 6478-6545/com.geeksville.mesh D/BluetoothGatt: cancelOpen() - device: 24:62:AB:DD:DF:3A
|
||||
2020-07-24 09:11:04.214 6478-19966/com.geeksville.mesh D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=4 device=24:62:AB:DD:DF:3A
|
||||
2020-07-24 09:11:04.215 6478-19966/com.geeksville.mesh I/com.geeksville.mesh.service.SafeBluetooth: new bluetooth connection state 0, status 0
|
||||
2020-07-24 09:11:04.215 6478-19966/com.geeksville.mesh I/com.geeksville.mesh.service.SafeBluetooth: Got disconnect because we are shutting down, closing gatt
|
||||
2020-07-24 09:11:04.215 6478-19966/com.geeksville.mesh D/BluetoothGatt: close()
|
||||
@@ -1,9 +1,10 @@
|
||||
This is a mini design doc for developing the meshtastic software.
|
||||
|
||||
* [Build instructions](build-instructions.md)
|
||||
* [On device plugin API](plugin-api.md) - a tutorial on how to write small Plugins which run on the device and can message other nodes.
|
||||
* [TODO](TODO.md) - read this if you are looking for things to do (or curious about currently missing features)
|
||||
* Our [project board](https://github.com/orgs/meshtastic/projects/1) - shows what things we are currently working on and remaining work items for the current release.
|
||||
* [Power Management](power.md)
|
||||
* [Mesh algorithm](mesh-alg.md)
|
||||
* [Bluetooth API](bluetooth-api.md) and porting guide for new clients (iOS, python, etc...)
|
||||
* [External client API](device-api.md) and porting guide for new clients (iOS, python, etc...)
|
||||
* TODO: how to port the device code to a new device.
|
||||
|
||||
BIN
images/amazon-fire-button.png
Normal file
BIN
images/amazon-fire-button.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@@ -55,7 +55,7 @@
|
||||
|
||||
/* Version of the nanopb library. Just in case you want to check it in
|
||||
* your own program. */
|
||||
#define NANOPB_VERSION nanopb-0.4.1
|
||||
#define NANOPB_VERSION nanopb-0.4.4
|
||||
|
||||
/* Include all the system headers needed by nanopb. You will need the
|
||||
* definitions of the following:
|
||||
@@ -276,17 +276,18 @@ typedef struct pb_field_iter_s pb_field_iter_t;
|
||||
/* This structure is used in auto-generated constants
|
||||
* to specify struct fields.
|
||||
*/
|
||||
PB_PACKED_STRUCT_START
|
||||
typedef struct pb_msgdesc_s pb_msgdesc_t;
|
||||
struct pb_msgdesc_s {
|
||||
pb_size_t field_count;
|
||||
const uint32_t *field_info;
|
||||
const pb_msgdesc_t * const * submsg_info;
|
||||
const pb_byte_t *default_value;
|
||||
|
||||
bool (*field_callback)(pb_istream_t *istream, pb_ostream_t *ostream, const pb_field_iter_t *field);
|
||||
} pb_packed;
|
||||
PB_PACKED_STRUCT_END
|
||||
|
||||
pb_size_t field_count;
|
||||
pb_size_t required_field_count;
|
||||
pb_size_t largest_tag;
|
||||
};
|
||||
|
||||
/* Iterator for message descriptor */
|
||||
struct pb_field_iter_s {
|
||||
@@ -469,137 +470,181 @@ struct pb_extension_s {
|
||||
}; \
|
||||
const pb_msgdesc_t structname ## _msg = \
|
||||
{ \
|
||||
0 msgname ## _FIELDLIST(PB_GEN_FIELD_COUNT, structname), \
|
||||
structname ## _field_info, \
|
||||
structname ## _submsg_info, \
|
||||
msgname ## _DEFAULT, \
|
||||
msgname ## _CALLBACK, \
|
||||
0 msgname ## _FIELDLIST(PB_GEN_FIELD_COUNT, structname), \
|
||||
0 msgname ## _FIELDLIST(PB_GEN_REQ_FIELD_COUNT, structname), \
|
||||
0 msgname ## _FIELDLIST(PB_GEN_LARGEST_TAG, structname), \
|
||||
}; \
|
||||
msgname ## _FIELDLIST(PB_GEN_FIELD_INFO_ASSERT_ ## width, structname)
|
||||
|
||||
#define PB_GEN_FIELD_COUNT(structname, atype, htype, ltype, fieldname, tag) +1
|
||||
#define PB_GEN_REQ_FIELD_COUNT(structname, atype, htype, ltype, fieldname, tag) \
|
||||
+ (PB_HTYPE_ ## htype == PB_HTYPE_REQUIRED)
|
||||
#define PB_GEN_LARGEST_TAG(structname, atype, htype, ltype, fieldname, tag) \
|
||||
* 0 + tag
|
||||
|
||||
/* X-macro for generating the entries in struct_field_info[] array. */
|
||||
#define PB_GEN_FIELD_INFO_1(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_GEN_FIELD_INFO(1, structname, atype, htype, ltype, fieldname, tag)
|
||||
PB_FIELDINFO_1(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_2(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_GEN_FIELD_INFO(2, structname, atype, htype, ltype, fieldname, tag)
|
||||
PB_FIELDINFO_2(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_4(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_GEN_FIELD_INFO(4, structname, atype, htype, ltype, fieldname, tag)
|
||||
PB_FIELDINFO_4(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_8(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_GEN_FIELD_INFO(8, structname, atype, htype, ltype, fieldname, tag)
|
||||
PB_FIELDINFO_8(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_AUTO(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_GEN_FIELD_INFO_AUTO2(PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype), structname, atype, htype, ltype, fieldname, tag)
|
||||
PB_FIELDINFO_AUTO2(PB_FIELDINFO_WIDTH_AUTO(_PB_ATYPE_ ## atype, _PB_HTYPE_ ## htype, _PB_LTYPE_ ## ltype), \
|
||||
tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_AUTO2(width, structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_GEN_FIELD_INFO(width, structname, atype, htype, ltype, fieldname, tag)
|
||||
#define PB_FIELDINFO_AUTO2(width, tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_FIELDINFO_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size)
|
||||
|
||||
#define PB_GEN_FIELD_INFO(width, structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_ ## width(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(htype, structname, fieldname))
|
||||
#define PB_FIELDINFO_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_FIELDINFO_ ## width(tag, type, data_offset, data_size, size_offset, array_size)
|
||||
|
||||
/* X-macro for generating asserts that entries fit in struct_field_info[] array.
|
||||
* The structure of macros here must match the structure above in PB_GEN_FIELD_INFO_x(),
|
||||
* but it is not easily reused because of how macro substitutions work. */
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_1(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_GEN_FIELD_INFO_ASSERT(1, structname, atype, htype, ltype, fieldname, tag)
|
||||
PB_FIELDINFO_ASSERT_1(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_2(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_GEN_FIELD_INFO_ASSERT(2, structname, atype, htype, ltype, fieldname, tag)
|
||||
PB_FIELDINFO_ASSERT_2(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_4(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_GEN_FIELD_INFO_ASSERT(4, structname, atype, htype, ltype, fieldname, tag)
|
||||
PB_FIELDINFO_ASSERT_4(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_8(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_GEN_FIELD_INFO_ASSERT(8, structname, atype, htype, ltype, fieldname, tag)
|
||||
PB_FIELDINFO_ASSERT_8(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_AUTO(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_GEN_FIELD_INFO_ASSERT_AUTO2(PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype), structname, atype, htype, ltype, fieldname, tag)
|
||||
PB_FIELDINFO_ASSERT_AUTO2(PB_FIELDINFO_WIDTH_AUTO(_PB_ATYPE_ ## atype, _PB_HTYPE_ ## htype, _PB_LTYPE_ ## ltype), \
|
||||
tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(_PB_HTYPE_ ## htype, structname, fieldname))
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT_AUTO2(width, structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_GEN_FIELD_INFO_ASSERT(width, structname, atype, htype, ltype, fieldname, tag)
|
||||
#define PB_FIELDINFO_ASSERT_AUTO2(width, tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_FIELDINFO_ASSERT_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size)
|
||||
|
||||
#define PB_GEN_FIELD_INFO_ASSERT(width, structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_FIELDINFO_ASSERT_ ## width(tag, PB_ATYPE_ ## atype | PB_HTYPE_ ## htype | PB_LTYPE_MAP_ ## ltype, \
|
||||
PB_DATA_OFFSET_ ## atype(htype, structname, fieldname), \
|
||||
PB_DATA_SIZE_ ## atype(htype, structname, fieldname), \
|
||||
PB_SIZE_OFFSET_ ## atype(htype, structname, fieldname), \
|
||||
PB_ARRAY_SIZE_ ## atype(htype, structname, fieldname))
|
||||
#define PB_FIELDINFO_ASSERT_AUTO3(width, tag, type, data_offset, data_size, size_offset, array_size) \
|
||||
PB_FIELDINFO_ASSERT_ ## width(tag, type, data_offset, data_size, size_offset, array_size)
|
||||
|
||||
#define PB_DATA_OFFSET_STATIC(htype, structname, fieldname) PB_DATA_OFFSET_ ## htype(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_POINTER(htype, structname, fieldname) PB_DATA_OFFSET_ ## htype(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_CALLBACK(htype, structname, fieldname) PB_DATA_OFFSET_ ## htype(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_REQUIRED(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_SINGULAR(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_ONEOF(structname, fieldname) offsetof(structname, PB_ONEOF_NAME(FULL, fieldname))
|
||||
#define PB_DATA_OFFSET_OPTIONAL(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_REPEATED(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_FIXARRAY(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_STATIC(htype, structname, fieldname) PB_DO ## htype(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_POINTER(htype, structname, fieldname) PB_DO ## htype(structname, fieldname)
|
||||
#define PB_DATA_OFFSET_CALLBACK(htype, structname, fieldname) PB_DO ## htype(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_REQUIRED(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_SINGULAR(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_ONEOF(structname, fieldname) offsetof(structname, PB_ONEOF_NAME(FULL, fieldname))
|
||||
#define PB_DO_PB_HTYPE_OPTIONAL(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_REPEATED(structname, fieldname) offsetof(structname, fieldname)
|
||||
#define PB_DO_PB_HTYPE_FIXARRAY(structname, fieldname) offsetof(structname, fieldname)
|
||||
|
||||
#define PB_SIZE_OFFSET_STATIC(htype, structname, fieldname) PB_SIZE_OFFSET_ ## htype(structname, fieldname)
|
||||
#define PB_SIZE_OFFSET_POINTER(htype, structname, fieldname) PB_SIZE_OFFSET_PTR_ ## htype(structname, fieldname)
|
||||
#define PB_SIZE_OFFSET_CALLBACK(htype, structname, fieldname) PB_SIZE_OFFSET_CB_ ## htype(structname, fieldname)
|
||||
#define PB_SIZE_OFFSET_REQUIRED(structname, fieldname) 0
|
||||
#define PB_SIZE_OFFSET_SINGULAR(structname, fieldname) 0
|
||||
#define PB_SIZE_OFFSET_ONEOF(structname, fieldname) PB_SIZE_OFFSET_ONEOF2(structname, PB_ONEOF_NAME(FULL, fieldname), PB_ONEOF_NAME(UNION, fieldname))
|
||||
#define PB_SIZE_OFFSET_ONEOF2(structname, fullname, unionname) PB_SIZE_OFFSET_ONEOF3(structname, fullname, unionname)
|
||||
#define PB_SIZE_OFFSET_ONEOF3(structname, fullname, unionname) pb_delta(structname, fullname, which_ ## unionname)
|
||||
#define PB_SIZE_OFFSET_OPTIONAL(structname, fieldname) pb_delta(structname, fieldname, has_ ## fieldname)
|
||||
#define PB_SIZE_OFFSET_REPEATED(structname, fieldname) pb_delta(structname, fieldname, fieldname ## _count)
|
||||
#define PB_SIZE_OFFSET_FIXARRAY(structname, fieldname) 0
|
||||
#define PB_SIZE_OFFSET_PTR_REQUIRED(structname, fieldname) 0
|
||||
#define PB_SIZE_OFFSET_PTR_SINGULAR(structname, fieldname) 0
|
||||
#define PB_SIZE_OFFSET_PTR_ONEOF(structname, fieldname) PB_SIZE_OFFSET_ONEOF(structname, fieldname)
|
||||
#define PB_SIZE_OFFSET_PTR_OPTIONAL(structname, fieldname) 0
|
||||
#define PB_SIZE_OFFSET_PTR_REPEATED(structname, fieldname) PB_SIZE_OFFSET_REPEATED(structname, fieldname)
|
||||
#define PB_SIZE_OFFSET_PTR_FIXARRAY(structname, fieldname) 0
|
||||
#define PB_SIZE_OFFSET_CB_REQUIRED(structname, fieldname) 0
|
||||
#define PB_SIZE_OFFSET_CB_SINGULAR(structname, fieldname) 0
|
||||
#define PB_SIZE_OFFSET_CB_ONEOF(structname, fieldname) PB_SIZE_OFFSET_ONEOF(structname, fieldname)
|
||||
#define PB_SIZE_OFFSET_CB_OPTIONAL(structname, fieldname) 0
|
||||
#define PB_SIZE_OFFSET_CB_REPEATED(structname, fieldname) 0
|
||||
#define PB_SIZE_OFFSET_CB_FIXARRAY(structname, fieldname) 0
|
||||
#define PB_SIZE_OFFSET_STATIC(htype, structname, fieldname) PB_SO ## htype(structname, fieldname)
|
||||
#define PB_SIZE_OFFSET_POINTER(htype, structname, fieldname) PB_SO_PTR ## htype(structname, fieldname)
|
||||
#define PB_SIZE_OFFSET_CALLBACK(htype, structname, fieldname) PB_SO_CB ## htype(structname, fieldname)
|
||||
#define PB_SO_PB_HTYPE_REQUIRED(structname, fieldname) 0
|
||||
#define PB_SO_PB_HTYPE_SINGULAR(structname, fieldname) 0
|
||||
#define PB_SO_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF2(structname, PB_ONEOF_NAME(FULL, fieldname), PB_ONEOF_NAME(UNION, fieldname))
|
||||
#define PB_SO_PB_HTYPE_ONEOF2(structname, fullname, unionname) PB_SO_PB_HTYPE_ONEOF3(structname, fullname, unionname)
|
||||
#define PB_SO_PB_HTYPE_ONEOF3(structname, fullname, unionname) pb_delta(structname, fullname, which_ ## unionname)
|
||||
#define PB_SO_PB_HTYPE_OPTIONAL(structname, fieldname) pb_delta(structname, fieldname, has_ ## fieldname)
|
||||
#define PB_SO_PB_HTYPE_REPEATED(structname, fieldname) pb_delta(structname, fieldname, fieldname ## _count)
|
||||
#define PB_SO_PB_HTYPE_FIXARRAY(structname, fieldname) 0
|
||||
#define PB_SO_PTR_PB_HTYPE_REQUIRED(structname, fieldname) 0
|
||||
#define PB_SO_PTR_PB_HTYPE_SINGULAR(structname, fieldname) 0
|
||||
#define PB_SO_PTR_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF(structname, fieldname)
|
||||
#define PB_SO_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) 0
|
||||
#define PB_SO_PTR_PB_HTYPE_REPEATED(structname, fieldname) PB_SO_PB_HTYPE_REPEATED(structname, fieldname)
|
||||
#define PB_SO_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_REQUIRED(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_SINGULAR(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_ONEOF(structname, fieldname) PB_SO_PB_HTYPE_ONEOF(structname, fieldname)
|
||||
#define PB_SO_CB_PB_HTYPE_OPTIONAL(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_REPEATED(structname, fieldname) 0
|
||||
#define PB_SO_CB_PB_HTYPE_FIXARRAY(structname, fieldname) 0
|
||||
|
||||
#define PB_ARRAY_SIZE_STATIC(htype, structname, fieldname) PB_ARRAY_SIZE_ ## htype(structname, fieldname)
|
||||
#define PB_ARRAY_SIZE_POINTER(htype, structname, fieldname) PB_ARRAY_SIZE_PTR_ ## htype(structname, fieldname)
|
||||
#define PB_ARRAY_SIZE_STATIC(htype, structname, fieldname) PB_AS ## htype(structname, fieldname)
|
||||
#define PB_ARRAY_SIZE_POINTER(htype, structname, fieldname) PB_AS_PTR ## htype(structname, fieldname)
|
||||
#define PB_ARRAY_SIZE_CALLBACK(htype, structname, fieldname) 1
|
||||
#define PB_ARRAY_SIZE_REQUIRED(structname, fieldname) 1
|
||||
#define PB_ARRAY_SIZE_SINGULAR(structname, fieldname) 1
|
||||
#define PB_ARRAY_SIZE_OPTIONAL(structname, fieldname) 1
|
||||
#define PB_ARRAY_SIZE_ONEOF(structname, fieldname) 1
|
||||
#define PB_ARRAY_SIZE_REPEATED(structname, fieldname) pb_arraysize(structname, fieldname)
|
||||
#define PB_ARRAY_SIZE_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname)
|
||||
#define PB_ARRAY_SIZE_PTR_REQUIRED(structname, fieldname) 1
|
||||
#define PB_ARRAY_SIZE_PTR_SINGULAR(structname, fieldname) 1
|
||||
#define PB_ARRAY_SIZE_PTR_OPTIONAL(structname, fieldname) 1
|
||||
#define PB_ARRAY_SIZE_PTR_ONEOF(structname, fieldname) 1
|
||||
#define PB_ARRAY_SIZE_PTR_REPEATED(structname, fieldname) 1
|
||||
#define PB_ARRAY_SIZE_PTR_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname[0])
|
||||
#define PB_AS_PB_HTYPE_REQUIRED(structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_SINGULAR(structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_OPTIONAL(structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_ONEOF(structname, fieldname) 1
|
||||
#define PB_AS_PB_HTYPE_REPEATED(structname, fieldname) pb_arraysize(structname, fieldname)
|
||||
#define PB_AS_PB_HTYPE_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname)
|
||||
#define PB_AS_PTR_PB_HTYPE_REQUIRED(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_SINGULAR(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_ONEOF(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_REPEATED(structname, fieldname) 1
|
||||
#define PB_AS_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) pb_arraysize(structname, fieldname[0])
|
||||
|
||||
#define PB_DATA_SIZE_STATIC(htype, structname, fieldname) PB_DATA_SIZE_ ## htype(structname, fieldname)
|
||||
#define PB_DATA_SIZE_POINTER(htype, structname, fieldname) PB_DATA_SIZE_PTR_ ## htype(structname, fieldname)
|
||||
#define PB_DATA_SIZE_CALLBACK(htype, structname, fieldname) PB_DATA_SIZE_CB_ ## htype(structname, fieldname)
|
||||
#define PB_DATA_SIZE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DATA_SIZE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DATA_SIZE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DATA_SIZE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname))
|
||||
#define PB_DATA_SIZE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DATA_SIZE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DATA_SIZE_PTR_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DATA_SIZE_PTR_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DATA_SIZE_PTR_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DATA_SIZE_PTR_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)[0])
|
||||
#define PB_DATA_SIZE_PTR_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DATA_SIZE_PTR_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0][0])
|
||||
#define PB_DATA_SIZE_CB_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DATA_SIZE_CB_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DATA_SIZE_CB_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DATA_SIZE_CB_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname))
|
||||
#define PB_DATA_SIZE_CB_REPEATED(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DATA_SIZE_CB_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DATA_SIZE_STATIC(htype, structname, fieldname) PB_DS ## htype(structname, fieldname)
|
||||
#define PB_DATA_SIZE_POINTER(htype, structname, fieldname) PB_DS_PTR ## htype(structname, fieldname)
|
||||
#define PB_DATA_SIZE_CALLBACK(htype, structname, fieldname) PB_DS_CB ## htype(structname, fieldname)
|
||||
#define PB_DS_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname))
|
||||
#define PB_DS_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname)[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname[0])
|
||||
#define PB_DS_PTR_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname[0][0])
|
||||
#define PB_DS_CB_PB_HTYPE_REQUIRED(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_CB_PB_HTYPE_SINGULAR(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_CB_PB_HTYPE_OPTIONAL(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_CB_PB_HTYPE_ONEOF(structname, fieldname) pb_membersize(structname, PB_ONEOF_NAME(FULL, fieldname))
|
||||
#define PB_DS_CB_PB_HTYPE_REPEATED(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
#define PB_DS_CB_PB_HTYPE_FIXARRAY(structname, fieldname) pb_membersize(structname, fieldname)
|
||||
|
||||
#define PB_ONEOF_NAME(type, tuple) PB_EXPAND(PB_ONEOF_NAME_ ## type tuple)
|
||||
#define PB_ONEOF_NAME_UNION(unionname,membername,fullname) unionname
|
||||
@@ -607,37 +652,37 @@ struct pb_extension_s {
|
||||
#define PB_ONEOF_NAME_FULL(unionname,membername,fullname) fullname
|
||||
|
||||
#define PB_GEN_SUBMSG_INFO(structname, atype, htype, ltype, fieldname, tag) \
|
||||
PB_SUBMSG_INFO_ ## htype(ltype, structname, fieldname)
|
||||
PB_SUBMSG_INFO_ ## htype(_PB_LTYPE_ ## ltype, structname, fieldname)
|
||||
|
||||
#define PB_SUBMSG_INFO_REQUIRED(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_SINGULAR(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_OPTIONAL(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_REQUIRED(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_SINGULAR(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_OPTIONAL(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_ONEOF(ltype, structname, fieldname) PB_SUBMSG_INFO_ONEOF2(ltype, structname, PB_ONEOF_NAME(UNION, fieldname), PB_ONEOF_NAME(MEMBER, fieldname))
|
||||
#define PB_SUBMSG_INFO_ONEOF2(ltype, structname, unionname, membername) PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername)
|
||||
#define PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## unionname ## _ ## membername ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_REPEATED(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_FIXARRAY(ltype, structname, fieldname) PB_SUBMSG_INFO_ ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_BOOL(t)
|
||||
#define PB_SUBMSG_INFO_BYTES(t)
|
||||
#define PB_SUBMSG_INFO_DOUBLE(t)
|
||||
#define PB_SUBMSG_INFO_ENUM(t)
|
||||
#define PB_SUBMSG_INFO_UENUM(t)
|
||||
#define PB_SUBMSG_INFO_FIXED32(t)
|
||||
#define PB_SUBMSG_INFO_FIXED64(t)
|
||||
#define PB_SUBMSG_INFO_FLOAT(t)
|
||||
#define PB_SUBMSG_INFO_INT32(t)
|
||||
#define PB_SUBMSG_INFO_INT64(t)
|
||||
#define PB_SUBMSG_INFO_MESSAGE(t) PB_SUBMSG_DESCRIPTOR(t)
|
||||
#define PB_SUBMSG_INFO_MSG_W_CB(t) PB_SUBMSG_DESCRIPTOR(t)
|
||||
#define PB_SUBMSG_INFO_SFIXED32(t)
|
||||
#define PB_SUBMSG_INFO_SFIXED64(t)
|
||||
#define PB_SUBMSG_INFO_SINT32(t)
|
||||
#define PB_SUBMSG_INFO_SINT64(t)
|
||||
#define PB_SUBMSG_INFO_STRING(t)
|
||||
#define PB_SUBMSG_INFO_UINT32(t)
|
||||
#define PB_SUBMSG_INFO_UINT64(t)
|
||||
#define PB_SUBMSG_INFO_EXTENSION(t)
|
||||
#define PB_SUBMSG_INFO_FIXED_LENGTH_BYTES(t)
|
||||
#define PB_SUBMSG_INFO_ONEOF3(ltype, structname, unionname, membername) PB_SI ## ltype(structname ## _ ## unionname ## _ ## membername ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_REPEATED(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SUBMSG_INFO_FIXARRAY(ltype, structname, fieldname) PB_SI ## ltype(structname ## _ ## fieldname ## _MSGTYPE)
|
||||
#define PB_SI_PB_LTYPE_BOOL(t)
|
||||
#define PB_SI_PB_LTYPE_BYTES(t)
|
||||
#define PB_SI_PB_LTYPE_DOUBLE(t)
|
||||
#define PB_SI_PB_LTYPE_ENUM(t)
|
||||
#define PB_SI_PB_LTYPE_UENUM(t)
|
||||
#define PB_SI_PB_LTYPE_FIXED32(t)
|
||||
#define PB_SI_PB_LTYPE_FIXED64(t)
|
||||
#define PB_SI_PB_LTYPE_FLOAT(t)
|
||||
#define PB_SI_PB_LTYPE_INT32(t)
|
||||
#define PB_SI_PB_LTYPE_INT64(t)
|
||||
#define PB_SI_PB_LTYPE_MESSAGE(t) PB_SUBMSG_DESCRIPTOR(t)
|
||||
#define PB_SI_PB_LTYPE_MSG_W_CB(t) PB_SUBMSG_DESCRIPTOR(t)
|
||||
#define PB_SI_PB_LTYPE_SFIXED32(t)
|
||||
#define PB_SI_PB_LTYPE_SFIXED64(t)
|
||||
#define PB_SI_PB_LTYPE_SINT32(t)
|
||||
#define PB_SI_PB_LTYPE_SINT64(t)
|
||||
#define PB_SI_PB_LTYPE_STRING(t)
|
||||
#define PB_SI_PB_LTYPE_UINT32(t)
|
||||
#define PB_SI_PB_LTYPE_UINT64(t)
|
||||
#define PB_SI_PB_LTYPE_EXTENSION(t)
|
||||
#define PB_SI_PB_LTYPE_FIXED_LENGTH_BYTES(t)
|
||||
#define PB_SUBMSG_DESCRIPTOR(t) &(t ## _msg),
|
||||
|
||||
/* The field descriptors use a variable width format, with width of either
|
||||
@@ -726,37 +771,37 @@ struct pb_extension_s {
|
||||
* The generator will give explicit size argument when it knows that a message
|
||||
* structure grows beyond 1-word format limits.
|
||||
*/
|
||||
#define PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype) PB_FIELDINFO_WIDTH_ ## atype(htype, ltype)
|
||||
#define PB_FIELDINFO_WIDTH_STATIC(htype, ltype) PB_FIELDINFO_WIDTH_ ## htype(ltype)
|
||||
#define PB_FIELDINFO_WIDTH_POINTER(htype, ltype) PB_FIELDINFO_WIDTH_ ## htype(ltype)
|
||||
#define PB_FIELDINFO_WIDTH_CALLBACK(htype, ltype) 2
|
||||
#define PB_FIELDINFO_WIDTH_REQUIRED(ltype) PB_FIELDINFO_WIDTH_ ## ltype
|
||||
#define PB_FIELDINFO_WIDTH_SINGULAR(ltype) PB_FIELDINFO_WIDTH_ ## ltype
|
||||
#define PB_FIELDINFO_WIDTH_OPTIONAL(ltype) PB_FIELDINFO_WIDTH_ ## ltype
|
||||
#define PB_FIELDINFO_WIDTH_ONEOF(ltype) PB_FIELDINFO_WIDTH_ ## ltype
|
||||
#define PB_FIELDINFO_WIDTH_REPEATED(ltype) 2
|
||||
#define PB_FIELDINFO_WIDTH_FIXARRAY(ltype) 2
|
||||
#define PB_FIELDINFO_WIDTH_BOOL 1
|
||||
#define PB_FIELDINFO_WIDTH_BYTES 2
|
||||
#define PB_FIELDINFO_WIDTH_DOUBLE 1
|
||||
#define PB_FIELDINFO_WIDTH_ENUM 1
|
||||
#define PB_FIELDINFO_WIDTH_UENUM 1
|
||||
#define PB_FIELDINFO_WIDTH_FIXED32 1
|
||||
#define PB_FIELDINFO_WIDTH_FIXED64 1
|
||||
#define PB_FIELDINFO_WIDTH_FLOAT 1
|
||||
#define PB_FIELDINFO_WIDTH_INT32 1
|
||||
#define PB_FIELDINFO_WIDTH_INT64 1
|
||||
#define PB_FIELDINFO_WIDTH_MESSAGE 2
|
||||
#define PB_FIELDINFO_WIDTH_MSG_W_CB 2
|
||||
#define PB_FIELDINFO_WIDTH_SFIXED32 1
|
||||
#define PB_FIELDINFO_WIDTH_SFIXED64 1
|
||||
#define PB_FIELDINFO_WIDTH_SINT32 1
|
||||
#define PB_FIELDINFO_WIDTH_SINT64 1
|
||||
#define PB_FIELDINFO_WIDTH_STRING 2
|
||||
#define PB_FIELDINFO_WIDTH_UINT32 1
|
||||
#define PB_FIELDINFO_WIDTH_UINT64 1
|
||||
#define PB_FIELDINFO_WIDTH_EXTENSION 1
|
||||
#define PB_FIELDINFO_WIDTH_FIXED_LENGTH_BYTES 2
|
||||
#define PB_FIELDINFO_WIDTH_AUTO(atype, htype, ltype) PB_FI_WIDTH ## atype(htype, ltype)
|
||||
#define PB_FI_WIDTH_PB_ATYPE_STATIC(htype, ltype) PB_FI_WIDTH ## htype(ltype)
|
||||
#define PB_FI_WIDTH_PB_ATYPE_POINTER(htype, ltype) PB_FI_WIDTH ## htype(ltype)
|
||||
#define PB_FI_WIDTH_PB_ATYPE_CALLBACK(htype, ltype) 2
|
||||
#define PB_FI_WIDTH_PB_HTYPE_REQUIRED(ltype) PB_FI_WIDTH ## ltype
|
||||
#define PB_FI_WIDTH_PB_HTYPE_SINGULAR(ltype) PB_FI_WIDTH ## ltype
|
||||
#define PB_FI_WIDTH_PB_HTYPE_OPTIONAL(ltype) PB_FI_WIDTH ## ltype
|
||||
#define PB_FI_WIDTH_PB_HTYPE_ONEOF(ltype) PB_FI_WIDTH ## ltype
|
||||
#define PB_FI_WIDTH_PB_HTYPE_REPEATED(ltype) 2
|
||||
#define PB_FI_WIDTH_PB_HTYPE_FIXARRAY(ltype) 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_BOOL 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_BYTES 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_DOUBLE 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_ENUM 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_UENUM 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_FIXED32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_FIXED64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_FLOAT 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_INT32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_INT64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_MESSAGE 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_MSG_W_CB 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_SFIXED32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_SFIXED64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_SINT32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_SINT64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_STRING 2
|
||||
#define PB_FI_WIDTH_PB_LTYPE_UINT32 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_UINT64 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_EXTENSION 1
|
||||
#define PB_FI_WIDTH_PB_LTYPE_FIXED_LENGTH_BYTES 2
|
||||
|
||||
/* The mapping from protobuf types to LTYPEs is done using these macros. */
|
||||
#define PB_LTYPE_MAP_BOOL PB_LTYPE_BOOL
|
||||
|
||||
@@ -32,6 +32,10 @@ bool pb_field_iter_next(pb_field_iter_t *iter);
|
||||
* Returns false if no such field exists. */
|
||||
bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag);
|
||||
|
||||
/* Find a field with type PB_LTYPE_EXTENSION, or return false if not found.
|
||||
* There can be only one extension range field per message. */
|
||||
bool pb_field_iter_find_extension(pb_field_iter_t *iter);
|
||||
|
||||
#ifdef PB_VALIDATE_UTF8
|
||||
/* Validate UTF-8 text string */
|
||||
bool pb_validate_utf8(const char *s);
|
||||
|
||||
@@ -113,6 +113,9 @@ bool pb_decode_ex(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_s
|
||||
* pb_decode() returns with an error, the message is already released.
|
||||
*/
|
||||
void pb_release(const pb_msgdesc_t *fields, void *dest_struct);
|
||||
#else
|
||||
/* Allocation is not supported, so release is no-op */
|
||||
#define pb_release(fields, dest_struct) PB_UNUSED(fields); PB_UNUSED(dest_struct);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -121,11 +124,14 @@ void pb_release(const pb_msgdesc_t *fields, void *dest_struct);
|
||||
**************************************/
|
||||
|
||||
/* Create an input stream for reading from a memory buffer.
|
||||
*
|
||||
* msglen should be the actual length of the message, not the full size of
|
||||
* allocated buffer.
|
||||
*
|
||||
* Alternatively, you can use a custom stream that reads directly from e.g.
|
||||
* a file or a network socket.
|
||||
*/
|
||||
pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize);
|
||||
pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t msglen);
|
||||
|
||||
/* Function to read from a pb_istream_t. You can use this if you need to
|
||||
* read some custom header data, or to read data in field callbacks.
|
||||
|
||||
@@ -132,7 +132,7 @@ bool pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count);
|
||||
* structure. Call this from the callback before writing out field contents. */
|
||||
bool pb_encode_tag_for_field(pb_ostream_t *stream, const pb_field_iter_t *field);
|
||||
|
||||
/* Encode field header by manually specifing wire type. You need to use this
|
||||
/* Encode field header by manually specifying wire type. You need to use this
|
||||
* if you want to write out packed arrays from a callback field. */
|
||||
bool pb_encode_tag(pb_ostream_t *stream, pb_wire_type_t wiretype, uint32_t field_number);
|
||||
|
||||
|
||||
@@ -9,89 +9,102 @@ static bool load_descriptor_values(pb_field_iter_t *iter)
|
||||
{
|
||||
uint32_t word0;
|
||||
uint32_t data_offset;
|
||||
uint_least8_t format;
|
||||
int_least8_t size_offset;
|
||||
|
||||
if (iter->index >= iter->descriptor->field_count)
|
||||
return false;
|
||||
|
||||
word0 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
|
||||
format = word0 & 3;
|
||||
iter->tag = (pb_size_t)((word0 >> 2) & 0x3F);
|
||||
iter->type = (pb_type_t)((word0 >> 8) & 0xFF);
|
||||
|
||||
if (format == 0)
|
||||
switch(word0 & 3)
|
||||
{
|
||||
/* 1-word format */
|
||||
iter->array_size = 1;
|
||||
size_offset = (int_least8_t)((word0 >> 24) & 0x0F);
|
||||
data_offset = (word0 >> 16) & 0xFF;
|
||||
iter->data_size = (pb_size_t)((word0 >> 28) & 0x0F);
|
||||
}
|
||||
else if (format == 1)
|
||||
{
|
||||
/* 2-word format */
|
||||
uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
|
||||
case 0: {
|
||||
/* 1-word format */
|
||||
iter->array_size = 1;
|
||||
iter->tag = (pb_size_t)((word0 >> 2) & 0x3F);
|
||||
size_offset = (int_least8_t)((word0 >> 24) & 0x0F);
|
||||
data_offset = (word0 >> 16) & 0xFF;
|
||||
iter->data_size = (pb_size_t)((word0 >> 28) & 0x0F);
|
||||
break;
|
||||
}
|
||||
|
||||
iter->array_size = (pb_size_t)((word0 >> 16) & 0x0FFF);
|
||||
iter->tag = (pb_size_t)(iter->tag | ((word1 >> 28) << 6));
|
||||
size_offset = (int_least8_t)((word0 >> 28) & 0x0F);
|
||||
data_offset = word1 & 0xFFFF;
|
||||
iter->data_size = (pb_size_t)((word1 >> 16) & 0x0FFF);
|
||||
}
|
||||
else if (format == 2)
|
||||
{
|
||||
/* 4-word format */
|
||||
uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
|
||||
uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]);
|
||||
uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]);
|
||||
case 1: {
|
||||
/* 2-word format */
|
||||
uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
|
||||
|
||||
iter->array_size = (pb_size_t)(word0 >> 16);
|
||||
iter->tag = (pb_size_t)(iter->tag | ((word1 >> 8) << 6));
|
||||
size_offset = (int_least8_t)(word1 & 0xFF);
|
||||
data_offset = word2;
|
||||
iter->data_size = (pb_size_t)word3;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 8-word format */
|
||||
uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
|
||||
uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]);
|
||||
uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]);
|
||||
uint32_t word4 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 4]);
|
||||
iter->array_size = (pb_size_t)((word0 >> 16) & 0x0FFF);
|
||||
iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 28) << 6));
|
||||
size_offset = (int_least8_t)((word0 >> 28) & 0x0F);
|
||||
data_offset = word1 & 0xFFFF;
|
||||
iter->data_size = (pb_size_t)((word1 >> 16) & 0x0FFF);
|
||||
break;
|
||||
}
|
||||
|
||||
iter->array_size = (pb_size_t)word4;
|
||||
iter->tag = (pb_size_t)(iter->tag | ((word1 >> 8) << 6));
|
||||
size_offset = (int_least8_t)(word1 & 0xFF);
|
||||
data_offset = word2;
|
||||
iter->data_size = (pb_size_t)word3;
|
||||
case 2: {
|
||||
/* 4-word format */
|
||||
uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
|
||||
uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]);
|
||||
uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]);
|
||||
|
||||
iter->array_size = (pb_size_t)(word0 >> 16);
|
||||
iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6));
|
||||
size_offset = (int_least8_t)(word1 & 0xFF);
|
||||
data_offset = word2;
|
||||
iter->data_size = (pb_size_t)word3;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
/* 8-word format */
|
||||
uint32_t word1 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 1]);
|
||||
uint32_t word2 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 2]);
|
||||
uint32_t word3 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 3]);
|
||||
uint32_t word4 = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index + 4]);
|
||||
|
||||
iter->array_size = (pb_size_t)word4;
|
||||
iter->tag = (pb_size_t)(((word0 >> 2) & 0x3F) | ((word1 >> 8) << 6));
|
||||
size_offset = (int_least8_t)(word1 & 0xFF);
|
||||
data_offset = word2;
|
||||
iter->data_size = (pb_size_t)word3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
iter->pField = (char*)iter->message + data_offset;
|
||||
|
||||
if (size_offset)
|
||||
{
|
||||
iter->pSize = (char*)iter->pField - size_offset;
|
||||
}
|
||||
else if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED &&
|
||||
(PB_ATYPE(iter->type) == PB_ATYPE_STATIC ||
|
||||
PB_ATYPE(iter->type) == PB_ATYPE_POINTER))
|
||||
{
|
||||
/* Fixed count array */
|
||||
iter->pSize = &iter->array_size;
|
||||
}
|
||||
else
|
||||
if (!iter->message)
|
||||
{
|
||||
/* Avoid doing arithmetic on null pointers, it is undefined */
|
||||
iter->pField = NULL;
|
||||
iter->pSize = NULL;
|
||||
}
|
||||
|
||||
if (PB_ATYPE(iter->type) == PB_ATYPE_POINTER && iter->pField != NULL)
|
||||
{
|
||||
iter->pData = *(void**)iter->pField;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->pData = iter->pField;
|
||||
iter->pField = (char*)iter->message + data_offset;
|
||||
|
||||
if (size_offset)
|
||||
{
|
||||
iter->pSize = (char*)iter->pField - size_offset;
|
||||
}
|
||||
else if (PB_HTYPE(iter->type) == PB_HTYPE_REPEATED &&
|
||||
(PB_ATYPE(iter->type) == PB_ATYPE_STATIC ||
|
||||
PB_ATYPE(iter->type) == PB_ATYPE_POINTER))
|
||||
{
|
||||
/* Fixed count array */
|
||||
iter->pSize = &iter->array_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->pSize = NULL;
|
||||
}
|
||||
|
||||
if (PB_ATYPE(iter->type) == PB_ATYPE_POINTER && iter->pField != NULL)
|
||||
{
|
||||
iter->pData = *(void**)iter->pField;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->pData = iter->pField;
|
||||
}
|
||||
}
|
||||
|
||||
if (PB_LTYPE_IS_SUBMSG(iter->type))
|
||||
@@ -130,17 +143,13 @@ static void advance_iterator(pb_field_iter_t *iter)
|
||||
pb_type_t prev_type = (prev_descriptor >> 8) & 0xFF;
|
||||
pb_size_t descriptor_len = (pb_size_t)(1 << (prev_descriptor & 3));
|
||||
|
||||
/* Add to fields.
|
||||
* The cast to pb_size_t is needed to avoid -Wconversion warning.
|
||||
* Because the data is is constants from generator, there is no danger of overflow.
|
||||
*/
|
||||
iter->field_info_index = (pb_size_t)(iter->field_info_index + descriptor_len);
|
||||
|
||||
if (PB_HTYPE(prev_type) == PB_HTYPE_REQUIRED)
|
||||
{
|
||||
iter->required_field_index++;
|
||||
}
|
||||
|
||||
if (PB_LTYPE_IS_SUBMSG(prev_type))
|
||||
{
|
||||
iter->submessage_index++;
|
||||
}
|
||||
iter->required_field_index = (pb_size_t)(iter->required_field_index + (PB_HTYPE(prev_type) == PB_HTYPE_REQUIRED));
|
||||
iter->submessage_index = (pb_size_t)(iter->submessage_index + PB_LTYPE_IS_SUBMSG(prev_type));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,11 +198,23 @@ bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag)
|
||||
{
|
||||
return true; /* Nothing to do, correct field already. */
|
||||
}
|
||||
else if (tag > iter->descriptor->largest_tag)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pb_size_t start = iter->index;
|
||||
uint32_t fieldinfo;
|
||||
|
||||
if (tag < iter->tag)
|
||||
{
|
||||
/* Fields are in tag number order, so we know that tag is between
|
||||
* 0 and our start position. Setting index to end forces
|
||||
* advance_iterator() call below to restart from beginning. */
|
||||
iter->index = iter->descriptor->field_count;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* Advance iterator but don't load values yet */
|
||||
@@ -222,6 +243,37 @@ bool pb_field_iter_find(pb_field_iter_t *iter, uint32_t tag)
|
||||
}
|
||||
}
|
||||
|
||||
bool pb_field_iter_find_extension(pb_field_iter_t *iter)
|
||||
{
|
||||
if (PB_LTYPE(iter->type) == PB_LTYPE_EXTENSION)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pb_size_t start = iter->index;
|
||||
uint32_t fieldinfo;
|
||||
|
||||
do
|
||||
{
|
||||
/* Advance iterator but don't load values yet */
|
||||
advance_iterator(iter);
|
||||
|
||||
/* Do fast check for field type */
|
||||
fieldinfo = PB_PROGMEM_READU32(iter->descriptor->field_info[iter->field_info_index]);
|
||||
|
||||
if (PB_LTYPE((fieldinfo >> 8) & 0xFF) == PB_LTYPE_EXTENSION)
|
||||
{
|
||||
return load_descriptor_values(iter);
|
||||
}
|
||||
} while (iter->index != start);
|
||||
|
||||
/* Searched all the way back to start, and found nothing. */
|
||||
(void)load_descriptor_values(iter);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void *pb_const_cast(const void *p)
|
||||
{
|
||||
/* Note: this casts away const, in order to use the common field iterator
|
||||
|
||||
@@ -24,19 +24,17 @@
|
||||
static bool checkreturn buf_read(pb_istream_t *stream, pb_byte_t *buf, size_t count);
|
||||
static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *dest, bool *eof);
|
||||
static bool checkreturn read_raw_value(pb_istream_t *stream, pb_wire_type_t wire_type, pb_byte_t *buf, size_t *size);
|
||||
static bool checkreturn check_wire_type(pb_wire_type_t wire_type, pb_field_iter_t *field);
|
||||
static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_field_iter_t *field);
|
||||
static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
|
||||
static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
|
||||
static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
|
||||
static bool checkreturn decode_callback_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
|
||||
static bool checkreturn decode_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field);
|
||||
static bool checkreturn default_extension_decoder(pb_istream_t *stream, pb_extension_t *extension, uint32_t tag, pb_wire_type_t wire_type);
|
||||
static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter);
|
||||
static bool checkreturn find_extension_field(pb_field_iter_t *iter);
|
||||
static bool checkreturn decode_extension(pb_istream_t *stream, uint32_t tag, pb_wire_type_t wire_type, pb_extension_t *extension);
|
||||
static bool pb_field_set_to_default(pb_field_iter_t *field);
|
||||
static bool pb_message_set_to_defaults(pb_field_iter_t *iter);
|
||||
static bool checkreturn pb_dec_bool(pb_istream_t *stream, const pb_field_iter_t *field);
|
||||
static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_t *field);
|
||||
static bool checkreturn pb_dec_fixed(pb_istream_t *stream, const pb_field_iter_t *field);
|
||||
static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t *field);
|
||||
static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_t *field);
|
||||
static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field);
|
||||
@@ -59,6 +57,8 @@ static void pb_release_single_field(pb_field_iter_t *field);
|
||||
#define pb_uint64_t uint64_t
|
||||
#endif
|
||||
|
||||
#define PB_WT_PACKED ((pb_wire_type_t)0xFF)
|
||||
|
||||
typedef struct {
|
||||
uint32_t bitfield[(PB_MAX_REQUIRED_FIELDS + 31) / 32];
|
||||
} pb_fields_seen_t;
|
||||
@@ -139,7 +139,7 @@ static bool checkreturn pb_readbyte(pb_istream_t *stream, pb_byte_t *buf)
|
||||
return true;
|
||||
}
|
||||
|
||||
pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize)
|
||||
pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t msglen)
|
||||
{
|
||||
pb_istream_t stream;
|
||||
/* Cast away the const from buf without a compiler error. We are
|
||||
@@ -156,7 +156,7 @@ pb_istream_t pb_istream_from_buffer(const pb_byte_t *buf, size_t bufsize)
|
||||
#endif
|
||||
state.c_state = buf;
|
||||
stream.state = state.state;
|
||||
stream.bytes_left = bufsize;
|
||||
stream.bytes_left = msglen;
|
||||
#ifndef PB_NO_ERRMSG
|
||||
stream.errmsg = NULL;
|
||||
#endif
|
||||
@@ -205,8 +205,10 @@ static bool checkreturn pb_decode_varint32_eof(pb_istream_t *stream, uint32_t *d
|
||||
{
|
||||
/* Note: The varint could have trailing 0x80 bytes, or 0xFF for negative. */
|
||||
pb_byte_t sign_extension = (bitpos < 63) ? 0xFF : 0x01;
|
||||
|
||||
if ((byte & 0x7F) != 0x00 && ((result >> 31) == 0 || byte != sign_extension))
|
||||
bool valid_extension = ((byte & 0x7F) == 0x00 ||
|
||||
((result >> 31) != 0 && byte == sign_extension));
|
||||
|
||||
if (bitpos >= 64 || !valid_extension)
|
||||
{
|
||||
PB_RETURN_ERROR(stream, "varint overflow");
|
||||
}
|
||||
@@ -388,61 +390,70 @@ bool checkreturn pb_close_string_substream(pb_istream_t *stream, pb_istream_t *s
|
||||
* Decode a single field *
|
||||
*************************/
|
||||
|
||||
static bool checkreturn check_wire_type(pb_wire_type_t wire_type, pb_field_iter_t *field)
|
||||
static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_wire_type_t wire_type, pb_field_iter_t *field)
|
||||
{
|
||||
switch (PB_LTYPE(field->type))
|
||||
{
|
||||
case PB_LTYPE_BOOL:
|
||||
case PB_LTYPE_VARINT:
|
||||
case PB_LTYPE_UVARINT:
|
||||
case PB_LTYPE_SVARINT:
|
||||
return wire_type == PB_WT_VARINT;
|
||||
if (wire_type != PB_WT_VARINT && wire_type != PB_WT_PACKED)
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
case PB_LTYPE_FIXED32:
|
||||
return wire_type == PB_WT_32BIT;
|
||||
|
||||
case PB_LTYPE_FIXED64:
|
||||
return wire_type == PB_WT_64BIT;
|
||||
|
||||
case PB_LTYPE_BYTES:
|
||||
case PB_LTYPE_STRING:
|
||||
case PB_LTYPE_SUBMESSAGE:
|
||||
case PB_LTYPE_SUBMSG_W_CB:
|
||||
case PB_LTYPE_FIXED_LENGTH_BYTES:
|
||||
return wire_type == PB_WT_STRING;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool checkreturn decode_basic_field(pb_istream_t *stream, pb_field_iter_t *field)
|
||||
{
|
||||
switch (PB_LTYPE(field->type))
|
||||
{
|
||||
case PB_LTYPE_BOOL:
|
||||
return pb_dec_bool(stream, field);
|
||||
|
||||
case PB_LTYPE_VARINT:
|
||||
case PB_LTYPE_UVARINT:
|
||||
case PB_LTYPE_SVARINT:
|
||||
if (wire_type != PB_WT_VARINT && wire_type != PB_WT_PACKED)
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
return pb_dec_varint(stream, field);
|
||||
|
||||
case PB_LTYPE_FIXED32:
|
||||
if (wire_type != PB_WT_32BIT && wire_type != PB_WT_PACKED)
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
return pb_decode_fixed32(stream, field->pData);
|
||||
|
||||
case PB_LTYPE_FIXED64:
|
||||
return pb_dec_fixed(stream, field);
|
||||
if (wire_type != PB_WT_64BIT && wire_type != PB_WT_PACKED)
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
if (field->data_size == sizeof(float))
|
||||
{
|
||||
return pb_decode_double_as_float(stream, (float*)field->pData);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PB_WITHOUT_64BIT
|
||||
PB_RETURN_ERROR(stream, "invalid data_size");
|
||||
#else
|
||||
return pb_decode_fixed64(stream, field->pData);
|
||||
#endif
|
||||
|
||||
case PB_LTYPE_BYTES:
|
||||
if (wire_type != PB_WT_STRING)
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
return pb_dec_bytes(stream, field);
|
||||
|
||||
case PB_LTYPE_STRING:
|
||||
if (wire_type != PB_WT_STRING)
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
return pb_dec_string(stream, field);
|
||||
|
||||
case PB_LTYPE_SUBMESSAGE:
|
||||
case PB_LTYPE_SUBMSG_W_CB:
|
||||
if (wire_type != PB_WT_STRING)
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
return pb_dec_submessage(stream, field);
|
||||
|
||||
case PB_LTYPE_FIXED_LENGTH_BYTES:
|
||||
if (wire_type != PB_WT_STRING)
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
return pb_dec_fixed_length_bytes(stream, field);
|
||||
|
||||
default:
|
||||
@@ -455,18 +466,12 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t
|
||||
switch (PB_HTYPE(field->type))
|
||||
{
|
||||
case PB_HTYPE_REQUIRED:
|
||||
if (!check_wire_type(wire_type, field))
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
return decode_basic_field(stream, field);
|
||||
return decode_basic_field(stream, wire_type, field);
|
||||
|
||||
case PB_HTYPE_OPTIONAL:
|
||||
if (!check_wire_type(wire_type, field))
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
if (field->pSize != NULL)
|
||||
*(bool*)field->pSize = true;
|
||||
return decode_basic_field(stream, field);
|
||||
return decode_basic_field(stream, wire_type, field);
|
||||
|
||||
case PB_HTYPE_REPEATED:
|
||||
if (wire_type == PB_WT_STRING
|
||||
@@ -483,7 +488,7 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t
|
||||
|
||||
while (substream.bytes_left > 0 && *size < field->array_size)
|
||||
{
|
||||
if (!decode_basic_field(&substream, field))
|
||||
if (!decode_basic_field(&substream, PB_WT_PACKED, field))
|
||||
{
|
||||
status = false;
|
||||
break;
|
||||
@@ -505,18 +510,15 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t
|
||||
pb_size_t *size = (pb_size_t*)field->pSize;
|
||||
field->pData = (char*)field->pField + field->data_size * (*size);
|
||||
|
||||
if (!check_wire_type(wire_type, field))
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
if ((*size)++ >= field->array_size)
|
||||
PB_RETURN_ERROR(stream, "array overflow");
|
||||
|
||||
return decode_basic_field(stream, field);
|
||||
return decode_basic_field(stream, wire_type, field);
|
||||
}
|
||||
|
||||
case PB_HTYPE_ONEOF:
|
||||
*(pb_size_t*)field->pSize = field->tag;
|
||||
if (PB_LTYPE_IS_SUBMSG(field->type))
|
||||
if (PB_LTYPE_IS_SUBMSG(field->type) &&
|
||||
*(pb_size_t*)field->pSize != field->tag)
|
||||
{
|
||||
/* We memset to zero so that any callbacks are set to NULL.
|
||||
* This is because the callbacks might otherwise have values
|
||||
@@ -526,12 +528,14 @@ static bool checkreturn decode_static_field(pb_istream_t *stream, pb_wire_type_t
|
||||
* that can set the fields before submessage is decoded.
|
||||
* pb_dec_submessage() will set any default values. */
|
||||
memset(field->pData, 0, (size_t)field->data_size);
|
||||
|
||||
/* Set default values for the submessage fields. */
|
||||
if (!pb_field_set_to_default(field))
|
||||
PB_RETURN_ERROR(stream, "failed to set defaults");
|
||||
}
|
||||
*(pb_size_t*)field->pSize = field->tag;
|
||||
|
||||
if (!check_wire_type(wire_type, field))
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
return decode_basic_field(stream, field);
|
||||
return decode_basic_field(stream, wire_type, field);
|
||||
|
||||
default:
|
||||
PB_RETURN_ERROR(stream, "invalid field type");
|
||||
@@ -599,14 +603,8 @@ static void initialize_pointer_field(void *pItem, pb_field_iter_t *field)
|
||||
else if (PB_LTYPE_IS_SUBMSG(field->type))
|
||||
{
|
||||
/* We memset to zero so that any callbacks are set to NULL.
|
||||
* Then set any default values. */
|
||||
pb_field_iter_t submsg_iter;
|
||||
* Default values will be set by pb_dec_submessage(). */
|
||||
memset(pItem, 0, field->data_size);
|
||||
|
||||
if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, pItem))
|
||||
{
|
||||
(void)pb_message_set_to_defaults(&submsg_iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -623,9 +621,6 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_
|
||||
case PB_HTYPE_REQUIRED:
|
||||
case PB_HTYPE_OPTIONAL:
|
||||
case PB_HTYPE_ONEOF:
|
||||
if (!check_wire_type(wire_type, field))
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
if (PB_LTYPE_IS_SUBMSG(field->type) && *(void**)field->pField != NULL)
|
||||
{
|
||||
/* Duplicate field, have to release the old allocation first. */
|
||||
@@ -643,7 +638,7 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_
|
||||
{
|
||||
/* pb_dec_string and pb_dec_bytes handle allocation themselves */
|
||||
field->pData = field->pField;
|
||||
return decode_basic_field(stream, field);
|
||||
return decode_basic_field(stream, wire_type, field);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -652,7 +647,7 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_
|
||||
|
||||
field->pData = *(void**)field->pField;
|
||||
initialize_pointer_field(field->pData, field);
|
||||
return decode_basic_field(stream, field);
|
||||
return decode_basic_field(stream, wire_type, field);
|
||||
}
|
||||
|
||||
case PB_HTYPE_REPEATED:
|
||||
@@ -700,7 +695,7 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_
|
||||
/* Decode the array entry */
|
||||
field->pData = *(char**)field->pField + field->data_size * (*size);
|
||||
initialize_pointer_field(field->pData, field);
|
||||
if (!decode_basic_field(&substream, field))
|
||||
if (!decode_basic_field(&substream, PB_WT_PACKED, field))
|
||||
{
|
||||
status = false;
|
||||
break;
|
||||
@@ -721,16 +716,13 @@ static bool checkreturn decode_pointer_field(pb_istream_t *stream, pb_wire_type_
|
||||
if (*size == PB_SIZE_MAX)
|
||||
PB_RETURN_ERROR(stream, "too many array entries");
|
||||
|
||||
if (!check_wire_type(wire_type, field))
|
||||
PB_RETURN_ERROR(stream, "wrong wire type");
|
||||
|
||||
if (!allocate_field(stream, field->pField, field->data_size, (size_t)(*size + 1)))
|
||||
return false;
|
||||
|
||||
field->pData = *(char**)field->pField + field->data_size * (*size);
|
||||
(*size)++;
|
||||
initialize_pointer_field(field->pData, field);
|
||||
return decode_basic_field(stream, field);
|
||||
return decode_basic_field(stream, wire_type, field);
|
||||
}
|
||||
|
||||
default:
|
||||
@@ -821,7 +813,7 @@ static bool checkreturn default_extension_decoder(pb_istream_t *stream,
|
||||
if (!pb_field_iter_begin_extension(&iter, extension))
|
||||
PB_RETURN_ERROR(stream, "invalid extension");
|
||||
|
||||
if (iter.tag != tag)
|
||||
if (iter.tag != tag || !iter.message)
|
||||
return true;
|
||||
|
||||
extension->found = true;
|
||||
@@ -831,9 +823,8 @@ static bool checkreturn default_extension_decoder(pb_istream_t *stream,
|
||||
/* Try to decode an unknown field as an extension field. Tries each extension
|
||||
* decoder in turn, until one of them handles the field or loop ends. */
|
||||
static bool checkreturn decode_extension(pb_istream_t *stream,
|
||||
uint32_t tag, pb_wire_type_t wire_type, pb_field_iter_t *iter)
|
||||
uint32_t tag, pb_wire_type_t wire_type, pb_extension_t *extension)
|
||||
{
|
||||
pb_extension_t *extension = *(pb_extension_t* const *)iter->pData;
|
||||
size_t pos = stream->bytes_left;
|
||||
|
||||
while (extension != NULL && pos == stream->bytes_left)
|
||||
@@ -853,22 +844,6 @@ static bool checkreturn decode_extension(pb_istream_t *stream,
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Step through the iterator until an extension field is found or until all
|
||||
* entries have been checked. There can be only one extension field per
|
||||
* message. Returns false if no extension field is found. */
|
||||
static bool checkreturn find_extension_field(pb_field_iter_t *iter)
|
||||
{
|
||||
pb_size_t start = iter->index;
|
||||
|
||||
do {
|
||||
if (PB_LTYPE(iter->type) == PB_LTYPE_EXTENSION)
|
||||
return true;
|
||||
(void)pb_field_iter_next(iter);
|
||||
} while (iter->index != start);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Initialize message fields to default values, recursively */
|
||||
static bool pb_field_set_to_default(pb_field_iter_t *field)
|
||||
{
|
||||
@@ -910,9 +885,14 @@ static bool pb_field_set_to_default(pb_field_iter_t *field)
|
||||
|
||||
if (init_data)
|
||||
{
|
||||
if (PB_LTYPE_IS_SUBMSG(field->type))
|
||||
if (PB_LTYPE_IS_SUBMSG(field->type) &&
|
||||
(field->submsg_desc->default_value != NULL ||
|
||||
field->submsg_desc->field_callback != NULL ||
|
||||
field->submsg_desc->submsg_info[0] != NULL))
|
||||
{
|
||||
/* Initialize submessage to defaults */
|
||||
/* Initialize submessage to defaults.
|
||||
* Only needed if it has default values
|
||||
* or callback/submessage fields. */
|
||||
pb_field_iter_t submsg_iter;
|
||||
if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, field->pData))
|
||||
{
|
||||
@@ -989,6 +969,7 @@ static bool pb_message_set_to_defaults(pb_field_iter_t *iter)
|
||||
static bool checkreturn pb_decode_inner(pb_istream_t *stream, const pb_msgdesc_t *fields, void *dest_struct, unsigned int flags)
|
||||
{
|
||||
uint32_t extension_range_start = 0;
|
||||
pb_extension_t *extensions = NULL;
|
||||
|
||||
/* 'fixed_count_field' and 'fixed_count_size' track position of a repeated fixed
|
||||
* count field. This can only handle _one_ repeated fixed count field that
|
||||
@@ -1040,25 +1021,31 @@ static bool checkreturn pb_decode_inner(pb_istream_t *stream, const pb_msgdesc_t
|
||||
if (!pb_field_iter_find(&iter, tag) || PB_LTYPE(iter.type) == PB_LTYPE_EXTENSION)
|
||||
{
|
||||
/* No match found, check if it matches an extension. */
|
||||
if (extension_range_start == 0)
|
||||
{
|
||||
if (pb_field_iter_find_extension(&iter))
|
||||
{
|
||||
extensions = *(pb_extension_t* const *)iter.pData;
|
||||
extension_range_start = iter.tag;
|
||||
}
|
||||
|
||||
if (!extensions)
|
||||
{
|
||||
extension_range_start = (uint32_t)-1;
|
||||
}
|
||||
}
|
||||
|
||||
if (tag >= extension_range_start)
|
||||
{
|
||||
if (!find_extension_field(&iter))
|
||||
extension_range_start = (uint32_t)-1;
|
||||
else
|
||||
extension_range_start = iter.tag;
|
||||
size_t pos = stream->bytes_left;
|
||||
|
||||
if (tag >= extension_range_start)
|
||||
if (!decode_extension(stream, tag, wire_type, extensions))
|
||||
return false;
|
||||
|
||||
if (pos != stream->bytes_left)
|
||||
{
|
||||
size_t pos = stream->bytes_left;
|
||||
|
||||
if (!decode_extension(stream, tag, wire_type, &iter))
|
||||
return false;
|
||||
|
||||
if (pos != stream->bytes_left)
|
||||
{
|
||||
/* The field was handled */
|
||||
continue;
|
||||
}
|
||||
/* The field was handled */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1112,27 +1099,15 @@ static bool checkreturn pb_decode_inner(pb_istream_t *stream, const pb_msgdesc_t
|
||||
|
||||
/* Check that all required fields were present. */
|
||||
{
|
||||
/* First figure out the number of required fields by
|
||||
* seeking to the end of the field array. Usually we
|
||||
* are already close to end after decoding.
|
||||
*/
|
||||
pb_size_t req_field_count;
|
||||
pb_type_t last_type;
|
||||
pb_size_t i;
|
||||
do {
|
||||
req_field_count = iter.required_field_index;
|
||||
last_type = iter.type;
|
||||
} while (pb_field_iter_next(&iter));
|
||||
|
||||
/* Fixup if last field was also required. */
|
||||
if (PB_HTYPE(last_type) == PB_HTYPE_REQUIRED && iter.tag != 0)
|
||||
req_field_count++;
|
||||
|
||||
if (req_field_count > PB_MAX_REQUIRED_FIELDS)
|
||||
req_field_count = PB_MAX_REQUIRED_FIELDS;
|
||||
pb_size_t req_field_count = iter.descriptor->required_field_count;
|
||||
|
||||
if (req_field_count > 0)
|
||||
{
|
||||
pb_size_t i;
|
||||
|
||||
if (req_field_count > PB_MAX_REQUIRED_FIELDS)
|
||||
req_field_count = PB_MAX_REQUIRED_FIELDS;
|
||||
|
||||
/* Check the whole words */
|
||||
for (i = 0; i < (req_field_count >> 5); i++)
|
||||
{
|
||||
@@ -1277,7 +1252,7 @@ static void pb_release_single_field(pb_field_iter_t *field)
|
||||
|
||||
if (field->pData)
|
||||
{
|
||||
while (count--)
|
||||
for (; count > 0; count--)
|
||||
{
|
||||
pb_release(field->submsg_desc, field->pData);
|
||||
field->pData = (char*)field->pData + field->data_size;
|
||||
@@ -1294,7 +1269,7 @@ static void pb_release_single_field(pb_field_iter_t *field)
|
||||
/* Release entries in repeated string or bytes array */
|
||||
void **pItem = *(void***)field->pField;
|
||||
pb_size_t count = *(pb_size_t*)field->pSize;
|
||||
while (count--)
|
||||
for (; count > 0; count--)
|
||||
{
|
||||
pb_free(*pItem);
|
||||
*pItem++ = NULL;
|
||||
@@ -1454,7 +1429,7 @@ static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_
|
||||
|
||||
/* See issue 97: Google's C++ protobuf allows negative varint values to
|
||||
* be cast as int32_t, instead of the int64_t that should be used when
|
||||
* encoding. Previous nanopb versions had a bug in encoding. In order to
|
||||
* encoding. Nanopb versions before 0.2.5 had a bug in encoding. In order to
|
||||
* not break decoding of such messages, we cast <=32 bit fields to
|
||||
* int32_t first to get the sign correct.
|
||||
*/
|
||||
@@ -1483,31 +1458,6 @@ static bool checkreturn pb_dec_varint(pb_istream_t *stream, const pb_field_iter_
|
||||
}
|
||||
}
|
||||
|
||||
static bool checkreturn pb_dec_fixed(pb_istream_t *stream, const pb_field_iter_t *field)
|
||||
{
|
||||
#ifdef PB_CONVERT_DOUBLE_FLOAT
|
||||
if (field->data_size == sizeof(float) && PB_LTYPE(field->type) == PB_LTYPE_FIXED64)
|
||||
{
|
||||
return pb_decode_double_as_float(stream, (float*)field->pData);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (field->data_size == sizeof(uint32_t))
|
||||
{
|
||||
return pb_decode_fixed32(stream, field->pData);
|
||||
}
|
||||
#ifndef PB_WITHOUT_64BIT
|
||||
else if (field->data_size == sizeof(uint64_t))
|
||||
{
|
||||
return pb_decode_fixed64(stream, field->pData);
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
PB_RETURN_ERROR(stream, "invalid data_size");
|
||||
}
|
||||
}
|
||||
|
||||
static bool checkreturn pb_dec_bytes(pb_istream_t *stream, const pb_field_iter_t *field)
|
||||
{
|
||||
uint32_t size;
|
||||
@@ -1601,6 +1551,7 @@ static bool checkreturn pb_dec_string(pb_istream_t *stream, const pb_field_iter_
|
||||
static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_iter_t *field)
|
||||
{
|
||||
bool status = true;
|
||||
bool submsg_consumed = false;
|
||||
pb_istream_t substream;
|
||||
|
||||
if (!pb_make_string_substream(stream, &substream))
|
||||
@@ -1609,19 +1560,6 @@ static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_i
|
||||
if (field->submsg_desc == NULL)
|
||||
PB_RETURN_ERROR(stream, "invalid field descriptor");
|
||||
|
||||
/* New array entries need to be initialized, while required and optional
|
||||
* submessages have already been initialized in the top-level pb_decode. */
|
||||
if (PB_HTYPE(field->type) == PB_HTYPE_REPEATED ||
|
||||
PB_HTYPE(field->type) == PB_HTYPE_ONEOF)
|
||||
{
|
||||
pb_field_iter_t submsg_iter;
|
||||
if (pb_field_iter_begin(&submsg_iter, field->submsg_desc, field->pData))
|
||||
{
|
||||
if (!pb_message_set_to_defaults(&submsg_iter))
|
||||
PB_RETURN_ERROR(stream, "failed to set defaults");
|
||||
}
|
||||
}
|
||||
|
||||
/* Submessages can have a separate message-level callback that is called
|
||||
* before decoding the message. Typically it is used to set callback fields
|
||||
* inside oneofs. */
|
||||
@@ -1632,13 +1570,28 @@ static bool checkreturn pb_dec_submessage(pb_istream_t *stream, const pb_field_i
|
||||
if (callback->funcs.decode)
|
||||
{
|
||||
status = callback->funcs.decode(&substream, field, &callback->arg);
|
||||
|
||||
if (substream.bytes_left == 0)
|
||||
{
|
||||
submsg_consumed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Now decode the submessage contents */
|
||||
if (status)
|
||||
if (status && !submsg_consumed)
|
||||
{
|
||||
status = pb_decode_inner(&substream, field->submsg_desc, field->pData, 0);
|
||||
unsigned int flags = 0;
|
||||
|
||||
/* Static required/optional fields are already initialized by top-level
|
||||
* pb_decode(), no need to initialize them again. */
|
||||
if (PB_ATYPE(field->type) == PB_ATYPE_STATIC &&
|
||||
PB_HTYPE(field->type) != PB_HTYPE_REPEATED)
|
||||
{
|
||||
flags = PB_DECODE_NOINIT;
|
||||
}
|
||||
|
||||
status = pb_decode_inner(&substream, field->submsg_desc, field->pData, flags);
|
||||
}
|
||||
|
||||
if (!pb_close_string_substream(stream, &substream))
|
||||
@@ -1692,37 +1645,41 @@ bool pb_decode_double_as_float(pb_istream_t *stream, float *dest)
|
||||
{
|
||||
/* Special value */
|
||||
exponent = 128;
|
||||
}
|
||||
else if (exponent > 127)
|
||||
{
|
||||
/* Too large, convert to infinity */
|
||||
exponent = 128;
|
||||
mantissa = 0;
|
||||
}
|
||||
else if (exponent < -150)
|
||||
{
|
||||
/* Too small, convert to zero */
|
||||
exponent = -127;
|
||||
mantissa = 0;
|
||||
}
|
||||
else if (exponent < -126)
|
||||
{
|
||||
/* Denormalized */
|
||||
mantissa |= 0x1000000;
|
||||
mantissa >>= (-126 - exponent);
|
||||
exponent = -127;
|
||||
}
|
||||
|
||||
/* Round off mantissa */
|
||||
mantissa = (mantissa + 1) >> 1;
|
||||
|
||||
/* Check if mantissa went over 2.0 */
|
||||
if (mantissa & 0x800000)
|
||||
{
|
||||
exponent += 1;
|
||||
mantissa &= 0x7FFFFF;
|
||||
mantissa >>= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (exponent > 127)
|
||||
{
|
||||
/* Too large, convert to infinity */
|
||||
exponent = 128;
|
||||
mantissa = 0;
|
||||
}
|
||||
else if (exponent < -150)
|
||||
{
|
||||
/* Too small, convert to zero */
|
||||
exponent = -127;
|
||||
mantissa = 0;
|
||||
}
|
||||
else if (exponent < -126)
|
||||
{
|
||||
/* Denormalized */
|
||||
mantissa |= 0x1000000;
|
||||
mantissa >>= (-126 - exponent);
|
||||
exponent = -127;
|
||||
}
|
||||
|
||||
/* Round off mantissa */
|
||||
mantissa = (mantissa + 1) >> 1;
|
||||
|
||||
/* Check if mantissa went over 2.0 */
|
||||
if (mantissa & 0x800000)
|
||||
{
|
||||
exponent += 1;
|
||||
mantissa &= 0x7FFFFF;
|
||||
mantissa >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Combine fields */
|
||||
out.i = mantissa;
|
||||
|
||||
@@ -82,8 +82,11 @@ bool checkreturn pb_write(pb_ostream_t *stream, const pb_byte_t *buf, size_t cou
|
||||
{
|
||||
if (count > 0 && stream->callback != NULL)
|
||||
{
|
||||
if (stream->bytes_written + count > stream->max_size)
|
||||
if (stream->bytes_written + count < stream->bytes_written ||
|
||||
stream->bytes_written + count > stream->max_size)
|
||||
{
|
||||
PB_RETURN_ERROR(stream, "stream full");
|
||||
}
|
||||
|
||||
#ifdef PB_BUFFER_ONLY
|
||||
if (!buf_write(stream, buf, count))
|
||||
@@ -262,9 +265,33 @@ static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *fie
|
||||
* submessage fields. */
|
||||
return safe_read_bool(field->pSize) == false;
|
||||
}
|
||||
else if (field->descriptor->default_value)
|
||||
{
|
||||
/* Proto3 messages do not have default values, but proto2 messages
|
||||
* can contain optional fields without has_fields (generator option 'proto3').
|
||||
* In this case they must always be encoded, to make sure that the
|
||||
* non-zero default value is overwritten.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Rest is proto3 singular fields */
|
||||
if (PB_LTYPE(type) == PB_LTYPE_BYTES)
|
||||
if (PB_LTYPE(type) <= PB_LTYPE_LAST_PACKABLE)
|
||||
{
|
||||
/* Simple integer / float fields */
|
||||
pb_size_t i;
|
||||
const char *p = (const char*)field->pData;
|
||||
for (i = 0; i < field->data_size; i++)
|
||||
{
|
||||
if (p[i] != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (PB_LTYPE(type) == PB_LTYPE_BYTES)
|
||||
{
|
||||
const pb_bytes_array_t *bytes = (const pb_bytes_array_t*)field->pData;
|
||||
return bytes->size == 0;
|
||||
@@ -302,27 +329,29 @@ static bool checkreturn pb_check_proto3_default_value(const pb_field_iter_t *fie
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
else if (PB_ATYPE(type) == PB_ATYPE_POINTER)
|
||||
{
|
||||
/* Catch-all branch that does byte-per-byte comparison for zero value.
|
||||
*
|
||||
* This is for all pointer fields, and for static PB_LTYPE_VARINT,
|
||||
* UVARINT, SVARINT, FIXED32, FIXED64, EXTENSION fields, and also
|
||||
* callback fields. These all have integer or pointer value which
|
||||
* can be compared with 0.
|
||||
*/
|
||||
pb_size_t i;
|
||||
const char *p = (const char*)field->pData;
|
||||
for (i = 0; i < field->data_size; i++)
|
||||
{
|
||||
if (p[i] != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return field->pData == NULL;
|
||||
}
|
||||
else if (PB_ATYPE(type) == PB_ATYPE_CALLBACK)
|
||||
{
|
||||
if (PB_LTYPE(type) == PB_LTYPE_EXTENSION)
|
||||
{
|
||||
const pb_extension_t *extension = *(const pb_extension_t* const *)field->pData;
|
||||
return extension == NULL;
|
||||
}
|
||||
else if (field->descriptor->field_callback == pb_default_field_callback)
|
||||
{
|
||||
pb_callback_t *pCallback = (pb_callback_t*)field->pData;
|
||||
return pCallback->funcs.encode == NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
return field->descriptor->field_callback == NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return false; /* Not typically reached, safe default for weird special cases. */
|
||||
}
|
||||
|
||||
/* Encode a field with static or pointer allocation, i.e. one whose data
|
||||
@@ -823,7 +852,7 @@ static bool checkreturn pb_enc_bytes(pb_ostream_t *stream, const pb_field_iter_t
|
||||
}
|
||||
|
||||
if (PB_ATYPE(field->type) == PB_ATYPE_STATIC &&
|
||||
PB_BYTES_ARRAY_T_ALLOCSIZE(bytes->size) > field->data_size)
|
||||
bytes->size > field->data_size - offsetof(pb_bytes_array_t, bytes))
|
||||
{
|
||||
PB_RETURN_ERROR(stream, "bytes size exceeded");
|
||||
}
|
||||
|
||||
18
linker/esp32.extram.bss.ld
Normal file
18
linker/esp32.extram.bss.ld
Normal file
@@ -0,0 +1,18 @@
|
||||
/* This section is only included if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
|
||||
is set, to link some sections to BSS in PSRAM */
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* external memory bss, from any global variable with EXT_RAM_ATTR attribute*/
|
||||
.ext_ram.bss (NOLOAD) :
|
||||
{
|
||||
_ext_ram_bss_start = ABSOLUTE(.);
|
||||
*(.ext_ram.bss*)
|
||||
*libnet80211.a:(.dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON)
|
||||
*libpp.a:(.dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON)
|
||||
*liblwip.a:(.dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON)
|
||||
*libbt.a:(EXCLUDE_FILE (libbtdm_app.a) .dynsbss .sbss .sbss.* .gnu.linkonce.sb.* .scommon .sbss2.* .gnu.linkonce.sb2.* .dynbss .bss .bss.* .share.mem .gnu.linkonce.b.* COMMON)
|
||||
. = ALIGN(4);
|
||||
_ext_ram_bss_end = ABSOLUTE(.);
|
||||
} > extern_ram_seg
|
||||
}
|
||||
46
linker/nrf52840_s140_sim832.ld
Normal file
46
linker/nrf52840_s140_sim832.ld
Normal file
@@ -0,0 +1,46 @@
|
||||
/* Linker script to configure memory regions.
|
||||
|
||||
geeksville: modified this to simulate a nrf52832 but with a sd140 soft device. So I can
|
||||
see how the memory footprint works on this lower end CPU. Note: to work with sd140 in my bootloader
|
||||
I need to start ram at 0x6000 (instead of the correct 0x3600 for sd132) - so I have less
|
||||
RAM available than on a real 832.
|
||||
*/
|
||||
|
||||
SEARCH_DIR(.)
|
||||
GROUP(-lgcc -lc -lnosys)
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0x6D000 - 0x26000
|
||||
/* FLASH (rx) : ORIGIN = 0x26000, LENGTH = 0xED000 - 0x26000 */
|
||||
|
||||
/* SRAM required by S132 depend on
|
||||
* - Attribute Table Size
|
||||
* - Vendor UUID count
|
||||
* - Max ATT MTU
|
||||
* - Concurrent connection peripheral + central + secure links
|
||||
* - Event Len, HVN queue, Write CMD queue
|
||||
*/
|
||||
/* RAM (rwx) : ORIGIN = 0x20003600, LENGTH = 0x20010000 - 0x20003600 */
|
||||
RAM (rwx) : ORIGIN = 0x20006000, LENGTH = 0x20010000 - 0x20006000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = ALIGN(4);
|
||||
.svc_data :
|
||||
{
|
||||
PROVIDE(__start_svc_data = .);
|
||||
KEEP(*(.svc_data))
|
||||
PROVIDE(__stop_svc_data = .);
|
||||
} > RAM
|
||||
|
||||
.fs_data :
|
||||
{
|
||||
PROVIDE(__start_fs_data = .);
|
||||
KEEP(*(.fs_data))
|
||||
PROVIDE(__stop_fs_data = .);
|
||||
} > RAM
|
||||
} INSERT AFTER .data;
|
||||
|
||||
INCLUDE "nrf52_common.ld"
|
||||
69
nrf52/ttgo_eink_qpsi.ini
Normal file
69
nrf52/ttgo_eink_qpsi.ini
Normal file
@@ -0,0 +1,69 @@
|
||||
; nrfjprog.exe configuration file.
|
||||
|
||||
; Note: QSPI flash is mapped into memory at address 0x12000000
|
||||
|
||||
[DEFAULT_CONFIGURATION]
|
||||
; Define the capacity of the flash memory device in bytes. Set to 0 if no external memory device is present in your board.
|
||||
; MX25R1635F is 16Mbit/2Mbyte
|
||||
MemSize = 0x200000
|
||||
|
||||
; Define the desired ReadMode. Valid options are FASTREAD, READ2O, READ2IO, READ4O and READ4IO
|
||||
ReadMode = READ2IO
|
||||
|
||||
; Define the desired WriteMode. Valid options are PP, PP2O, PP4O and PP4IO
|
||||
WriteMode = PP
|
||||
|
||||
; Define the desired AddressMode. Valid options are BIT24 and BIT32
|
||||
AddressMode = BIT24
|
||||
|
||||
; Define the desired Frequency. Valid options are M2, M4, M8, M16 and M32
|
||||
Frequency = M16
|
||||
|
||||
; Define the desired SPI mode. Valid options are MODE0 and MODE3
|
||||
SpiMode = MODE0
|
||||
|
||||
; Define the desired SckDelay. Valid options are in the range 0 to 255
|
||||
SckDelay = 0x80
|
||||
|
||||
; Define the desired IO level for DIO2 and DIO3 during a custom instruction. Valid options are LEVEL_HIGH and LEVEL_LOW
|
||||
CustomInstructionIO2Level = LEVEL_LOW
|
||||
CustomInstructionIO3Level = LEVEL_HIGH
|
||||
|
||||
; Define the assigned pins for the QSPI peripheral. Valid options are those existing in your device
|
||||
CSNPin = 15
|
||||
CSNPort = 1
|
||||
SCKPin = 14
|
||||
SCKPort = 1
|
||||
DIO0Pin = 12
|
||||
DIO0Port = 1
|
||||
DIO1Pin = 13
|
||||
DIO1Port = 1
|
||||
|
||||
;These two pins are not connected, but we must name something
|
||||
DIO2Pin = 3
|
||||
DIO2Port = 1
|
||||
DIO3Pin = 5
|
||||
DIO3Port = 1
|
||||
|
||||
; Define the Index of the Write In Progress (WIP) bit in the status register. Valid options are in the range of 0 to 7.
|
||||
WIPIndex = 0
|
||||
|
||||
; Define page size for commands. Valid sizes are PAGE256 and PAGE512.
|
||||
PPSize = PAGE256
|
||||
|
||||
; Custom instructions to send to the external memory after initialization. Format is instruction code plus data to send in between optional brakets.
|
||||
; These instructions will be executed each time the qspi peripheral is initiated by nrfjprog.
|
||||
; To improve execution speed on consecutive interations with QSPI, you can run nrfjprog once with custom initialization, and then comment out the lines below.
|
||||
; Numbers can be given in decimal, hex (starting with either 0x or 0X) and binary (starting with either 0b or 0B) formats.
|
||||
; The custom instructions will be executed in the order found.
|
||||
|
||||
; This example includes two commands, first a WREN (WRite ENable) and then a WRSR (WRite Satus Register) enabling the Quad Operation and the High Performance
|
||||
; mode for the MX25R6435F memory present in the nRF52840 DK.
|
||||
;InitializationCustomInstruction = 0x06
|
||||
;InitializationCustomInstruction = 0x01, [0x40, 0, 0x2]
|
||||
|
||||
; For MX25R1635F on TTGO board, only two data lines are connected
|
||||
; This example includes two commands, first a WREN (WRite ENable) and then a WRSR (WRite Satus Register) disabling Quad Operation and the High Performance
|
||||
; mode. For normal operation you might want low power mode instead.
|
||||
InitializationCustomInstruction = 0x06
|
||||
InitializationCustomInstruction = 0x01, [0x00, 0, 0x2]
|
||||
238
platformio.ini
238
platformio.ini
@@ -9,7 +9,8 @@
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[platformio]
|
||||
default_envs = tbeam ; Note: the github actions CI test build can't yet build NRF52 targets
|
||||
default_envs = tbeam # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
|
||||
;default_envs = heltec # lora-relay-v1 # nrf52840dk-geeksville # linux # or if you'd like to change the default to something like lora-relay-v1 put that here
|
||||
|
||||
[common]
|
||||
; common is not currently used
|
||||
@@ -17,35 +18,29 @@ default_envs = tbeam ; Note: the github actions CI test build can't yet build NR
|
||||
; REQUIRED environment variables - if not set the specified default will be sued
|
||||
; The following environment variables must be set in the shell if you'd like to override them.
|
||||
; They are used in this ini file as systenv.VARNAME, so in your shell do export "VARNAME=fish"
|
||||
; HW_VERSION (default US)
|
||||
; APP_VERSION (default emptystring)
|
||||
; COUNTRY (default US), i.e. "export COUNTRY=EU865"
|
||||
; HW_VERSION (default emptystring)
|
||||
|
||||
[env]
|
||||
|
||||
; customize the partition table
|
||||
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
|
||||
board_build.partitions = partition-table.csv
|
||||
; note: APP_VERSION now comes from bin/version.json
|
||||
extra_scripts = bin/platformio-custom.py
|
||||
|
||||
; note: we add src to our include search path so that lmic_project_config can override
|
||||
; FIXME: fix lib/BluetoothOTA dependency back on src/ so we can remove -Isrc
|
||||
build_flags = -Wno-missing-field-initializers -Isrc -Isrc/mesh -Isrc/gps -Ilib/nanopb/include -Os -Wl,-Map,.pio/build/output.map
|
||||
-DAXP_DEBUG_PORT=Serial
|
||||
build_flags = -Wno-missing-field-initializers -Isrc -Isrc/mesh -Isrc/gps -Ilib/nanopb/include -Wl,-Map,.pio/build/output.map
|
||||
-DHW_VERSION_${sysenv.COUNTRY}
|
||||
-DAPP_VERSION=${sysenv.APP_VERSION}
|
||||
-DHW_VERSION=${sysenv.HW_VERSION}
|
||||
|
||||
; not needed included in ttgo-t-beam board file
|
||||
; also to use PSRAM https://docs.platformio.org/en/latest/platforms/espressif32.html#external-ram-psram
|
||||
; -DBOARD_HAS_PSRAM
|
||||
; -mfix-esp32-psram-cache-issue
|
||||
|
||||
; -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
-DUSE_THREAD_NAMES
|
||||
-DTINYGPSPLUS_OPTION_NO_CUSTOM_FIELDS
|
||||
|
||||
; leave this commented out to avoid breaking Windows
|
||||
;upload_port = /dev/ttyUSB0
|
||||
;monitor_port = /dev/ttyUSB0
|
||||
|
||||
;upload_port = /dev/cu.SLAB_USBtoUART
|
||||
;monitor_port = /dev/cu.SLAB_USBtoUART
|
||||
|
||||
; the default is esptool
|
||||
; upload_protocol = esp-prog
|
||||
|
||||
@@ -66,77 +61,129 @@ debug_tool = jlink
|
||||
|
||||
lib_deps =
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git ; ESP8266_SSD1306
|
||||
SPI
|
||||
; 1260 ; OneButton - not used yet
|
||||
https://github.com/geeksville/OneButton.git ; OneButton library for non-blocking button debounce
|
||||
1202 ; CRC32, explicitly needed because dependency is missing in the ble ota update lib
|
||||
https://github.com/meshtastic/arduino-fsm.git#2f106146071fc7bc620e1e8d4b88dc4e0266ce39
|
||||
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git#31015a55e630a2df77d9d714669c621a5bf355ad
|
||||
https://github.com/meshtastic/RadioLib.git#8657380241bce681c33aab46598bbf13b11f876c
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#9c1d584d2469523381e077b0b9c1bf868d6c0206
|
||||
https://github.com/meshtastic/AXP202X_Library.git#8404abb6d4b486748636bc6ad72d2a47baaf5460
|
||||
Wire ; explicitly needed here because the AXP202 library forgets to add it
|
||||
https://github.com/meshtastic/arduino-fsm.git
|
||||
https://github.com/meshtastic/SparkFun_Ublox_Arduino_Library.git
|
||||
https://github.com/meshtastic/RadioLib.git
|
||||
https://github.com/meshtastic/TinyGPSPlus.git
|
||||
SPI
|
||||
https://github.com/geeksville/ArduinoThread.git#333ffd09b596977c217ba25da4258f588b462ac6
|
||||
|
||||
; Common settings for conventional (non Portduino) Ardino targets
|
||||
[arduino_base]
|
||||
|
||||
framework = arduino
|
||||
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
|
||||
build_flags = ${env.build_flags} -Os
|
||||
|
||||
src_filter = ${env.src_filter} -<portduino/>
|
||||
|
||||
; Common settings for ESP targes, mixin with extends = esp32_base
|
||||
[esp32_base]
|
||||
extends = arduino_base
|
||||
platform = espressif32
|
||||
framework = arduino
|
||||
src_filter =
|
||||
${env.src_filter} -<nrf52/>
|
||||
${arduino_base.src_filter} -<nrf52/>
|
||||
upload_speed = 921600
|
||||
debug_init_break = tbreak setup
|
||||
build_flags =
|
||||
${env.build_flags} -Wall -Wextra -Isrc/esp32
|
||||
${arduino_base.build_flags} -Wall -Wextra -Isrc/esp32 -Isrc/esp32-mfix-esp32-psram-cache-issue -lnimble -std=c++11
|
||||
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
-DAXP_DEBUG_PORT=Serial
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
https://github.com/meshtastic/esp32_https_server.git
|
||||
# Hmm - this doesn't work yet
|
||||
# board_build.ldscript = linker/esp32.extram.bss.ld
|
||||
lib_ignore = segger_rtt
|
||||
platform_packages =
|
||||
framework-arduinoespressif32 @ https://github.com/meshtastic/arduino-esp32.git
|
||||
framework-arduinoespressif32@https://github.com/meshtastic/arduino-esp32.git#2814f110aa618429bdd9a0a2d6a93c55f29f87a6
|
||||
|
||||
; The 1.0 release of the TBEAM board
|
||||
; customize the partition table
|
||||
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
|
||||
board_build.partitions = partition-table.csv
|
||||
|
||||
; not needed included in ttgo-t-beam board file
|
||||
; also to use PSRAM https://docs.platformio.org/en/latest/platforms/espressif32.html#external-ram-psram
|
||||
; -DBOARD_HAS_PSRAM
|
||||
; -mfix-esp32-psram-cache-issue
|
||||
|
||||
; -DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG -DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
|
||||
; The 1.0 release of the TBEAM board
|
||||
[env:tbeam]
|
||||
extends = esp32_base
|
||||
board = ttgo-t-beam
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
https://github.com/meshtastic/AXP202X_Library.git
|
||||
${esp32_base.lib_deps}
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TBEAM_V10
|
||||
|
||||
; The original TBEAM board without the AXP power chip and a few other changes
|
||||
; Note: I've heard reports this didn't work. Disabled until someone with a 0.7 can test and debug.
|
||||
;[env:tbeam0.7]
|
||||
;extends = esp32_base
|
||||
;board = ttgo-t-beam
|
||||
;build_flags =
|
||||
; ${esp32_base.build_flags} -D TBEAM_V07
|
||||
[env:tbeam0.7]
|
||||
extends = esp32_base
|
||||
board = ttgo-t-beam
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TBEAM_V07
|
||||
|
||||
[env:heltec]
|
||||
;build_type = debug ; to make it possible to step through our jtag debugger
|
||||
extends = esp32_base
|
||||
board = heltec_wifi_lora_32_V2
|
||||
|
||||
[env:ttgo-lora32-v1]
|
||||
[env:tlora-v1]
|
||||
extends = esp32_base
|
||||
board = ttgo-lora32-v1
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TTGO_LORA_V1
|
||||
${esp32_base.build_flags} -D TLORA_V1
|
||||
|
||||
; note: the platformio definition for lora32-v2 seems stale, it is missing a pins_arduino.h file, therefore I don't think it works
|
||||
[env:ttgo-lora32-v2]
|
||||
[env:tlora-v2]
|
||||
extends = esp32_base
|
||||
board = ttgo-lora32-v1
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TTGO_LORA_V2
|
||||
${esp32_base.build_flags} -D TLORA_V2
|
||||
|
||||
[env:tlora-v2-1-1.6]
|
||||
extends = esp32_base
|
||||
board = ttgo-lora32-v1
|
||||
build_flags =
|
||||
${esp32_base.build_flags} -D TLORA_V2_1_16
|
||||
|
||||
; The Heltec Cubecell plus
|
||||
; IMPORTANT NOTE: This target doesn't yet work and probably won't ever work. I'm keeping it around for now.
|
||||
; For more details see my post in the forum.
|
||||
[env:cubecellplus]
|
||||
platform = https://github.com/HelTecAutomation/platform-asrmicro650x.git ; we use top-of-tree because stable version has too many bugs - asrmicro650x
|
||||
board = cubecell_board_plus
|
||||
; FIXME, bug in cubecell arduino - they are supposed to set ARDUINO
|
||||
build_flags = ${arduino_base.build_flags} -DARDUINO=100 -Isrc/cubecell
|
||||
src_filter =
|
||||
${arduino_base.src_filter} -<esp32/> -<nrf52/>
|
||||
|
||||
; Common settings for NRF52 based targets
|
||||
[nrf52_base]
|
||||
platform = nordicnrf52
|
||||
framework = arduino
|
||||
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
|
||||
; platform = nordicnrf52
|
||||
platform = https://github.com/meshtastic/platform-nordicnrf52.git#1a2639a6b0f79b5df66bea3e3089f0d5285fdc63
|
||||
extends = arduino_base
|
||||
debug_tool = jlink
|
||||
build_type = debug ; I'm debugging with ICE a lot now
|
||||
; note: liboberon provides the AES256 implementation for NRF52 (though not using the hardware acceleration of the NRF52840 - FIXME)
|
||||
build_flags =
|
||||
${env.build_flags} -Wno-unused-variable -Isrc/nrf52 -Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.3
|
||||
${arduino_base.build_flags} -Wno-unused-variable
|
||||
-Isrc/nrf52
|
||||
-Isdk-nrfxlib/crypto/nrf_oberon/include -Lsdk-nrfxlib/crypto/nrf_oberon/lib/cortex-m4/hard-float/ -lliboberon_3.0.3
|
||||
;-DCFG_DEBUG=3
|
||||
src_filter =
|
||||
${env.src_filter} -<esp32/>
|
||||
${arduino_base.src_filter} -<esp32/> -<nimble/> -<meshwifi/>
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
monitor_port = /dev/ttyACM1
|
||||
@@ -153,20 +200,117 @@ debug_init_break =
|
||||
;debug_init_break = tbreak Reset_Handler
|
||||
|
||||
; The NRF52840-dk development board
|
||||
[env:nrf52dk]
|
||||
; Note: By default no lora device is created for this build - it uses a simulated interface
|
||||
[env:nrf52840dk]
|
||||
extends = nrf52_base
|
||||
board = nrf52840_dk
|
||||
|
||||
; The NRF52840-dk development board, but @geeksville's board - which has a busted oscilliator
|
||||
[env:nrf52840dk-geeksville]
|
||||
extends = nrf52_base
|
||||
board = nrf52840_dk_modified
|
||||
lib_deps =
|
||||
UC1701 ; for temp testing
|
||||
# add our variants files to the include and src paths
|
||||
build_flags = ${nrf52_base.build_flags} -Ivariants/pca10056-rc-clock
|
||||
src_filter = ${nrf52_base.src_filter} +<../variants/pca10056-rc-clock>
|
||||
|
||||
; Note: By default no lora device is created for this build - it uses a simulated interface
|
||||
[env:feather_nrf52832]
|
||||
extends = nrf52_base
|
||||
board = adafruit_feather_nrf52832
|
||||
|
||||
[env:rak815]
|
||||
extends = nrf52_base
|
||||
board = rak815
|
||||
debug_tool = jlink
|
||||
upload_protocol = jlink
|
||||
monitor_port = /dev/ttyUSB0
|
||||
; this board's serial chip can only run at 115200, not faster
|
||||
monitor_speed = 115200
|
||||
|
||||
# For experimenting with RAM sizes
|
||||
# board_build.ldscript = linker/nrf52840_s140_sim832.ld
|
||||
|
||||
; The PPR board
|
||||
[env:ppr]
|
||||
extends = nrf52_base
|
||||
board = ppr
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${arduino_base.lib_deps}
|
||||
UC1701
|
||||
https://github.com/meshtastic/BQ25703A.git
|
||||
|
||||
; The PPR board
|
||||
[env:ppr1]
|
||||
extends = nrf52_base
|
||||
board = ppr1
|
||||
build_flags = ${nrf52_base.build_flags} -Ivariants/ppr1
|
||||
src_filter = ${nrf52_base.src_filter} +<../variants/ppr1>
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
|
||||
; Prototype eink/nrf52840/sx1262 device
|
||||
[env:eink]
|
||||
extends = nrf52_base
|
||||
board = eink
|
||||
# add our variants files to the include and src paths
|
||||
# define build flags for the TFT_eSPI library
|
||||
build_flags = ${nrf52_base.build_flags} -Ivariants/eink
|
||||
-DBUSY_PIN=3 -DRST_PIN=2 -DDC_PIN=28 -DCS_PIN=30
|
||||
src_filter = ${nrf52_base.src_filter} +<../variants/eink>
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
https://github.com/geeksville/EPD_Libraries.git
|
||||
TFT_eSPI
|
||||
|
||||
; The https://github.com/BigCorvus/SX1262-LoRa-BLE-Relay board by @BigCorvus
|
||||
[env:lora-relay-v1]
|
||||
extends = nrf52_base
|
||||
board = lora-relay-v1
|
||||
# add our variants files to the include and src paths
|
||||
# define build flags for the TFT_eSPI library
|
||||
build_flags = ${nrf52_base.build_flags} -Ivariants/lora_relay_v1
|
||||
-DUSER_SETUP_LOADED
|
||||
-DTFT_WIDTH=80
|
||||
-DTFT_HEIGHT=160
|
||||
-DST7735_GREENTAB160x80
|
||||
-DST7735_DRIVER
|
||||
-DTFT_CS=ST7735_CS
|
||||
-DTFT_DC=ST7735_RS
|
||||
-DTFT_RST=ST7735_RESET
|
||||
-DSPI_FREQUENCY=27000000
|
||||
src_filter = ${nrf52_base.src_filter} +<../variants/lora_relay_v1>
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
SparkFun BQ27441 LiPo Fuel Gauge Arduino Library
|
||||
TFT_eSPI
|
||||
|
||||
; The https://github.com/BigCorvus/LoRa-BLE-Relay-v2 board by @BigCorvus
|
||||
[env:lora-relay-v2]
|
||||
extends = nrf52_base
|
||||
board = lora-relay-v2
|
||||
# add our variants files to the include and src paths
|
||||
# define build flags for the TFT_eSPI library
|
||||
build_flags = ${nrf52_base.build_flags} -Ivariants/lora_relay_v2
|
||||
-DUSER_SETUP_LOADED
|
||||
-DTFT_WIDTH=80
|
||||
-DTFT_HEIGHT=160
|
||||
-DST7735_GREENTAB160x80
|
||||
-DST7735_DRIVER
|
||||
-DTFT_CS=ST7735_CS
|
||||
-DTFT_DC=ST7735_RS
|
||||
-DTFT_RST=ST7735_RESET
|
||||
-DSPI_FREQUENCY=27000000
|
||||
-DTFT_WR=ST7735_SDA
|
||||
-DTFT_SCLK=ST7735_SCK
|
||||
src_filter = ${nrf52_base.src_filter} +<../variants/lora_relay_v2>
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
SparkFun BQ27441 LiPo Fuel Gauge Arduino Library
|
||||
TFT_eSPI
|
||||
|
||||
; The Portduino based sim environment on top of linux
|
||||
[env:linux]
|
||||
platform = https://github.com/geeksville/platform-portduino.git
|
||||
src_filter = ${env.src_filter} -<esp32/> -<nimble/> -<nrf52/> -<meshwifi/>
|
||||
build_flags = ${arduino_base.build_flags} -O0
|
||||
framework = arduino
|
||||
board = linux_x86_64
|
||||
|
||||
2
proto
2
proto
Submodule proto updated: e7f181ef6f...75078afe43
3
release/.gitignore
vendored
3
release/.gitignore
vendored
@@ -1,4 +1,5 @@
|
||||
*.elf
|
||||
*.bin
|
||||
*.map
|
||||
*.zip
|
||||
*.zip
|
||||
*.uf2
|
||||
|
||||
12
src/BluetoothCommon.cpp
Normal file
12
src/BluetoothCommon.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "BluetoothCommon.h"
|
||||
|
||||
// NRF52 wants these constants as byte arrays
|
||||
// Generated here https://yupana-engineering.com/online-uuid-to-c-array-converter - but in REVERSE BYTE ORDER
|
||||
const uint8_t MESH_SERVICE_UUID_16[16u] = {0xfd, 0xea, 0x73, 0xe2, 0xca, 0x5d, 0xa8, 0x9f,
|
||||
0x1f, 0x46, 0xa8, 0x15, 0x18, 0xb2, 0xa1, 0x6b};
|
||||
const uint8_t TORADIO_UUID_16[16u] = {0xe7, 0x01, 0x44, 0x12, 0x66, 0x78, 0xdd, 0xa1,
|
||||
0xad, 0x4d, 0x9e, 0x12, 0xd2, 0x76, 0x5c, 0xf7};
|
||||
const uint8_t FROMRADIO_UUID_16[16u] = {0xd5, 0x54, 0xe4, 0xc5, 0x25, 0xc5, 0x31, 0xa5,
|
||||
0x55, 0x4a, 0x02, 0xee, 0xc2, 0xbc, 0xa2, 0x8b};
|
||||
const uint8_t FROMNUM_UUID_16[16u] = {0x53, 0x44, 0xe3, 0x47, 0x75, 0xaa, 0x70, 0xa6,
|
||||
0x66, 0x4f, 0x00, 0xa8, 0x8c, 0xa1, 0x9d, 0xed};
|
||||
20
src/BluetoothCommon.h
Normal file
20
src/BluetoothCommon.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
/**
|
||||
* Common lib functions for all platforms that have bluetooth
|
||||
*/
|
||||
|
||||
#define MESH_SERVICE_UUID "6ba1b218-15a8-461f-9fa8-5dcae273eafd"
|
||||
|
||||
#define TORADIO_UUID "f75c76d2-129e-4dad-a1dd-7866124401e7"
|
||||
#define FROMRADIO_UUID "8ba2bcc2-ee02-4a55-a531-c525c5e454d5"
|
||||
#define FROMNUM_UUID "ed9da18c-a800-4f66-a670-aa7547e34453"
|
||||
|
||||
// NRF52 wants these constants as byte arrays
|
||||
// Generated here https://yupana-engineering.com/online-uuid-to-c-array-converter - but in REVERSE BYTE ORDER
|
||||
extern const uint8_t MESH_SERVICE_UUID_16[], TORADIO_UUID_16[16u], FROMRADIO_UUID_16[], FROMNUM_UUID_16[];
|
||||
|
||||
/// Given a level between 0-100, update the BLE attribute
|
||||
void updateBatteryLevel(uint8_t level);
|
||||
21
src/FSCommon.cpp
Normal file
21
src/FSCommon.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "FSCommon.h"
|
||||
|
||||
void fsInit()
|
||||
{
|
||||
#ifdef FS
|
||||
if (!FSBegin())
|
||||
{
|
||||
DEBUG_MSG("ERROR filesystem mount Failed\n");
|
||||
assert(0); // FIXME - report failure to phone
|
||||
}
|
||||
|
||||
DEBUG_MSG("Filesystem files:\n");
|
||||
File dir = FS.open("/");
|
||||
File f = dir.openNextFile();
|
||||
while (f) {
|
||||
DEBUG_MSG(" %s\n", f.name());
|
||||
f.close();
|
||||
f = dir.openNextFile();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
29
src/FSCommon.h
Normal file
29
src/FSCommon.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "configuration.h"
|
||||
|
||||
// Cross platform filesystem API
|
||||
|
||||
#ifdef PORTDUINO
|
||||
// Portduino version
|
||||
#include "PortduinoFS.h"
|
||||
#define FS PortduinoFS
|
||||
#define FSBegin() true
|
||||
#define FILE_O_WRITE "w"
|
||||
#define FILE_O_READ "r"
|
||||
#elif !defined(NO_ESP32)
|
||||
// ESP32 version
|
||||
#include "SPIFFS.h"
|
||||
#define FS SPIFFS
|
||||
#define FSBegin() FS.begin(true)
|
||||
#define FILE_O_WRITE "w"
|
||||
#define FILE_O_READ "r"
|
||||
#else
|
||||
// NRF52 version
|
||||
#include "InternalFileSystem.h"
|
||||
#define FS InternalFS
|
||||
#define FSBegin() FS.begin()
|
||||
using namespace Adafruit_LittleFS_Namespace;
|
||||
#endif
|
||||
|
||||
void fsInit();
|
||||
98
src/GPSStatus.h
Normal file
98
src/GPSStatus.h
Normal file
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
#include "Status.h"
|
||||
#include "configuration.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
namespace meshtastic
|
||||
{
|
||||
|
||||
/// Describes the state of the GPS system.
|
||||
class GPSStatus : public Status
|
||||
{
|
||||
|
||||
private:
|
||||
CallbackObserver<GPSStatus, const GPSStatus *> statusObserver =
|
||||
CallbackObserver<GPSStatus, const GPSStatus *>(this, &GPSStatus::updateStatus);
|
||||
|
||||
bool hasLock = false; // default to false, until we complete our first read
|
||||
bool isConnected = false; // Do we have a GPS we are talking to
|
||||
int32_t latitude = 0, longitude = 0; // as an int mult by 1e-7 to get value as double
|
||||
int32_t altitude = 0;
|
||||
uint32_t dop = 0; // Diminution of position; PDOP where possible (UBlox), HDOP otherwise (TinyGPS) in 10^2 units (needs
|
||||
// scaling before use)
|
||||
uint32_t heading = 0;
|
||||
uint32_t numSatellites = 0;
|
||||
|
||||
public:
|
||||
GPSStatus() { statusType = STATUS_TYPE_GPS; }
|
||||
GPSStatus(bool hasLock, bool isConnected, int32_t latitude, int32_t longitude, int32_t altitude, uint32_t dop,
|
||||
uint32_t heading, uint32_t numSatellites)
|
||||
: Status()
|
||||
{
|
||||
this->hasLock = hasLock;
|
||||
this->isConnected = isConnected;
|
||||
this->latitude = latitude;
|
||||
this->longitude = longitude;
|
||||
this->altitude = altitude;
|
||||
this->dop = dop;
|
||||
this->heading = heading;
|
||||
this->numSatellites = numSatellites;
|
||||
}
|
||||
GPSStatus(const GPSStatus &);
|
||||
GPSStatus &operator=(const GPSStatus &);
|
||||
|
||||
void observe(Observable<const GPSStatus *> *source) { statusObserver.observe(source); }
|
||||
|
||||
bool getHasLock() const { return hasLock; }
|
||||
|
||||
bool getIsConnected() const { return isConnected; }
|
||||
|
||||
int32_t getLatitude() const { return latitude; }
|
||||
|
||||
int32_t getLongitude() const { return longitude; }
|
||||
|
||||
int32_t getAltitude() const { return altitude; }
|
||||
|
||||
uint32_t getDOP() const { return dop; }
|
||||
|
||||
uint32_t getHeading() const { return heading; }
|
||||
|
||||
uint32_t getNumSatellites() const { return numSatellites; }
|
||||
|
||||
bool matches(const GPSStatus *newStatus) const
|
||||
{
|
||||
return (newStatus->hasLock != hasLock || newStatus->isConnected != isConnected || newStatus->latitude != latitude ||
|
||||
newStatus->longitude != longitude || newStatus->altitude != altitude || newStatus->dop != dop ||
|
||||
newStatus->heading != heading || newStatus->numSatellites != numSatellites);
|
||||
}
|
||||
int updateStatus(const GPSStatus *newStatus)
|
||||
{
|
||||
// Only update the status if values have actually changed
|
||||
bool isDirty;
|
||||
{
|
||||
isDirty = matches(newStatus);
|
||||
initialized = true;
|
||||
hasLock = newStatus->hasLock;
|
||||
isConnected = newStatus->isConnected;
|
||||
latitude = newStatus->latitude;
|
||||
longitude = newStatus->longitude;
|
||||
altitude = newStatus->altitude;
|
||||
dop = newStatus->dop;
|
||||
heading = newStatus->heading;
|
||||
numSatellites = newStatus->numSatellites;
|
||||
}
|
||||
if (isDirty) {
|
||||
if (hasLock)
|
||||
DEBUG_MSG("New GPS pos lat=%f, lon=%f, alt=%d, pdop=%f, heading=%f, sats=%d\n", latitude * 1e-7, longitude * 1e-7,
|
||||
altitude, dop * 1e-2, heading * 1e-5, numSatellites);
|
||||
else
|
||||
DEBUG_MSG("No GPS lock\n");
|
||||
onNewStatus.notifyObservers(this);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace meshtastic
|
||||
|
||||
extern meshtastic::GPSStatus *gpsStatus;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user