mirror of
https://github.com/meshtastic/firmware.git
synced 2026-01-03 08:30:45 +00:00
Compare commits
754 Commits
v1.3.45.b0
...
v2.0.11.89
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8914d1a184 | ||
|
|
1cfc7b800b | ||
|
|
cab5fcf5ae | ||
|
|
cad5c9b70c | ||
|
|
5867038abf | ||
|
|
42b24d4510 | ||
|
|
d750109d00 | ||
|
|
7f0a8d329f | ||
|
|
64895cc7eb | ||
|
|
52903f83e3 | ||
|
|
e0002ef2d5 | ||
|
|
021fc8235c | ||
|
|
0305c7394f | ||
|
|
bca70d10d0 | ||
|
|
1077846e8d | ||
|
|
63c8ca9ca5 | ||
|
|
523b132100 | ||
|
|
2d62cbe345 | ||
|
|
b55fe549e3 | ||
|
|
9a04aaa811 | ||
|
|
092a753a6f | ||
|
|
8a9af37d82 | ||
|
|
74e6eb34bd | ||
|
|
11f1508d85 | ||
|
|
19436b7d54 | ||
|
|
69ff724f0f | ||
|
|
3d3aba584e | ||
|
|
ef1fb877ba | ||
|
|
f1cdfd163d | ||
|
|
8364c2b147 | ||
|
|
8193215294 | ||
|
|
e73ae7cdac | ||
|
|
65aad62702 | ||
|
|
3eefd46ca1 | ||
|
|
115cb05d3b | ||
|
|
44d5c69ba8 | ||
|
|
5ccd66864b | ||
|
|
0b5cae5393 | ||
|
|
be91b08b3e | ||
|
|
c7c5671cca | ||
|
|
979d12d607 | ||
|
|
110c80d045 | ||
|
|
38a1315599 | ||
|
|
8ebe0edc5a | ||
|
|
a8f93d5f47 | ||
|
|
96c272d3d1 | ||
|
|
45e6e86ff9 | ||
|
|
f73b8661de | ||
|
|
3c5710e65b | ||
|
|
4e4a74379e | ||
|
|
41a1dfec79 | ||
|
|
1a949b7ca6 | ||
|
|
840079c25b | ||
|
|
887405cc08 | ||
|
|
d633212f70 | ||
|
|
02def448bc | ||
|
|
7baf30dcb8 | ||
|
|
e09b12ca58 | ||
|
|
1736dada7d | ||
|
|
7f3a624ee3 | ||
|
|
475c87b0e4 | ||
|
|
541f4aa998 | ||
|
|
ab6c4e61a6 | ||
|
|
6ea0963f4b | ||
|
|
259d442d8f | ||
|
|
b134f0bb46 | ||
|
|
63cf01223c | ||
|
|
2505bdbc21 | ||
|
|
d9d8c7eb74 | ||
|
|
3b19040590 | ||
|
|
14be4ee9f0 | ||
|
|
94cb100e3f | ||
|
|
f632933b93 | ||
|
|
e25d05689b | ||
|
|
5c859da4e4 | ||
|
|
6c5602e88d | ||
|
|
b4735f4224 | ||
|
|
3b9b33a5ee | ||
|
|
430908f5d6 | ||
|
|
6f6ca64cfd | ||
|
|
d0243d2cd0 | ||
|
|
796e58161d | ||
|
|
e56f17c658 | ||
|
|
b808ffa9ab | ||
|
|
506bae4a8b | ||
|
|
f6ee6265e6 | ||
|
|
7539d92857 | ||
|
|
21fff392b4 | ||
|
|
580ec590fa | ||
|
|
5c9996dfa1 | ||
|
|
34f9324766 | ||
|
|
3f988c8b69 | ||
|
|
2ac2b6d1b6 | ||
|
|
b8657158be | ||
|
|
70f5f8301b | ||
|
|
adb8d773d4 | ||
|
|
a289406863 | ||
|
|
1a3f2a8ab5 | ||
|
|
23d6b815f5 | ||
|
|
e1feb5eb30 | ||
|
|
cb8247559d | ||
|
|
28b954017f | ||
|
|
16d826d6c7 | ||
|
|
2f7c18303d | ||
|
|
b9df41c55f | ||
|
|
4801260440 | ||
|
|
606262e55d | ||
|
|
0064d18e64 | ||
|
|
6f5a6d5cb4 | ||
|
|
e0194528dd | ||
|
|
30240ac14b | ||
|
|
090e1660fe | ||
|
|
92c9b34d4f | ||
|
|
fb41b0f5c8 | ||
|
|
3f50371ff3 | ||
|
|
812b321154 | ||
|
|
815f9bfc5f | ||
|
|
86ff23d13c | ||
|
|
201b786f77 | ||
|
|
8074955841 | ||
|
|
0992093f4d | ||
|
|
6978e57991 | ||
|
|
755c0b7008 | ||
|
|
7396d0f241 | ||
|
|
220859d0aa | ||
|
|
941786669b | ||
|
|
4eb620d47b | ||
|
|
9794995d7a | ||
|
|
055146602a | ||
|
|
86d7860d86 | ||
|
|
0f2d0d1f07 | ||
|
|
ab6a5a5e07 | ||
|
|
44a33ed463 | ||
|
|
fab08b6451 | ||
|
|
d9cd3dd3e1 | ||
|
|
c75ea87f6b | ||
|
|
706ddf6e95 | ||
|
|
aec091e7aa | ||
|
|
cea8393a7f | ||
|
|
8f94463eac | ||
|
|
a0f5e44967 | ||
|
|
feb7181767 | ||
|
|
a0c1e9cdc6 | ||
|
|
7d1b6f63b5 | ||
|
|
ab6b6514cb | ||
|
|
0e6285edf2 | ||
|
|
8b58eaac20 | ||
|
|
8cbf292373 | ||
|
|
80d0b63c3a | ||
|
|
f5120a29ec | ||
|
|
efc3f4c0ee | ||
|
|
bd2bfd6822 | ||
|
|
e40625d2ad | ||
|
|
eae347ddac | ||
|
|
ae2ca1d89c | ||
|
|
34c73da886 | ||
|
|
88c3ab2636 | ||
|
|
6a5dd26907 | ||
|
|
4de557b4db | ||
|
|
d9eb9758e2 | ||
|
|
d566457f0c | ||
|
|
79ff0659c0 | ||
|
|
af9d4328eb | ||
|
|
8c66940b78 | ||
|
|
c577e09183 | ||
|
|
4a6f269b4b | ||
|
|
bbaeeb7ce9 | ||
|
|
54686905dc | ||
|
|
3cde75f97b | ||
|
|
6c84b3f01c | ||
|
|
68f6cfde0c | ||
|
|
1c8181dc75 | ||
|
|
270746e303 | ||
|
|
72f1416b30 | ||
|
|
a788f16e91 | ||
|
|
f2229e6977 | ||
|
|
05f81922e6 | ||
|
|
06be74ae7c | ||
|
|
72504a5e8b | ||
|
|
e8c034e988 | ||
|
|
aa19718ba4 | ||
|
|
088ab106dd | ||
|
|
110c3f619a | ||
|
|
d1cc503ca8 | ||
|
|
eae7f8a786 | ||
|
|
bb24b86018 | ||
|
|
d3b3a4c148 | ||
|
|
46f1cee2a8 | ||
|
|
0386af721d | ||
|
|
de6b752db8 | ||
|
|
92fd5511ec | ||
|
|
8507125e98 | ||
|
|
59ec7f31ab | ||
|
|
627b21f3f2 | ||
|
|
64cc6e0b91 | ||
|
|
779d2352bd | ||
|
|
0162db12b8 | ||
|
|
91ff7b9032 | ||
|
|
643f99f577 | ||
|
|
152288b4cc | ||
|
|
45b518baf2 | ||
|
|
24cc479f95 | ||
|
|
5fbc630061 | ||
|
|
0c65c73f90 | ||
|
|
95eca75336 | ||
|
|
0f0dbc3274 | ||
|
|
edb674759f | ||
|
|
e3d8c5c7a6 | ||
|
|
f3d6f26a28 | ||
|
|
1a0d51495d | ||
|
|
32d9a397aa | ||
|
|
60e6dc1134 | ||
|
|
06d34daeab | ||
|
|
a00187b97f | ||
|
|
ba1f68d758 | ||
|
|
d4c0977a70 | ||
|
|
1a19d71e95 | ||
|
|
21c10934fc | ||
|
|
13cca91097 | ||
|
|
b335b1c66b | ||
|
|
a42a9bf4fe | ||
|
|
cc2653bfb5 | ||
|
|
fc5bf5a68f | ||
|
|
0f7e6b8964 | ||
|
|
63d7338311 | ||
|
|
37f716d27b | ||
|
|
03bfdec1e1 | ||
|
|
0f2a835359 | ||
|
|
2a84d39e40 | ||
|
|
b14289e976 | ||
|
|
1fef6f0656 | ||
|
|
183ec2124f | ||
|
|
aeb9bfa063 | ||
|
|
b84c7ae49b | ||
|
|
61598c5942 | ||
|
|
a3a24e0216 | ||
|
|
31ec2da0e9 | ||
|
|
53da7cb036 | ||
|
|
911083c49d | ||
|
|
27a10b395f | ||
|
|
b1f3e117d1 | ||
|
|
7570cdbd22 | ||
|
|
28ff2efdef | ||
|
|
bb1a9192eb | ||
|
|
1787e2c775 | ||
|
|
470e711383 | ||
|
|
eb4f682ad1 | ||
|
|
4b63730efb | ||
|
|
c857474116 | ||
|
|
8ff5dacc3c | ||
|
|
fb89828990 | ||
|
|
c7529f9a3e | ||
|
|
dbefa71bc8 | ||
|
|
7907404028 | ||
|
|
72e17b558c | ||
|
|
628028475c | ||
|
|
05e992ad67 | ||
|
|
bba6bf387e | ||
|
|
4d32f7c5ad | ||
|
|
0dff05e881 | ||
|
|
f3c5a01daf | ||
|
|
7ca104cef6 | ||
|
|
fe95247d56 | ||
|
|
f1179d31ba | ||
|
|
c7681cb24d | ||
|
|
abe60b96f1 | ||
|
|
206520f179 | ||
|
|
97fd5cf2ab | ||
|
|
d13a095516 | ||
|
|
4dc7d92cf1 | ||
|
|
e7dbbeb606 | ||
|
|
3e892fc391 | ||
|
|
330ac3be68 | ||
|
|
3b1e34efa1 | ||
|
|
dfec37dfd0 | ||
|
|
b82ab34f85 | ||
|
|
18a2cfeda4 | ||
|
|
082aa07e7f | ||
|
|
a703ab4418 | ||
|
|
185ceac9df | ||
|
|
7c9cada50e | ||
|
|
a5ba3dd445 | ||
|
|
63838a1632 | ||
|
|
30d7f188e2 | ||
|
|
47a47f1e69 | ||
|
|
daac79f314 | ||
|
|
1864216e78 | ||
|
|
71c0cf9b9a | ||
|
|
ef87ddb798 | ||
|
|
711c748b44 | ||
|
|
6eff09a260 | ||
|
|
c5fe878a6f | ||
|
|
39948c76de | ||
|
|
10f14d27b7 | ||
|
|
5e9d722b7d | ||
|
|
b324c04097 | ||
|
|
84a9d95b1f | ||
|
|
cdd499f147 | ||
|
|
c45a85547e | ||
|
|
8815746006 | ||
|
|
32a1e8ef0d | ||
|
|
0dff4538f3 | ||
|
|
6507683909 | ||
|
|
c71e32970c | ||
|
|
fcf21da843 | ||
|
|
ab464fe038 | ||
|
|
fd546af2a5 | ||
|
|
acfbe202b6 | ||
|
|
29fb283daf | ||
|
|
51ef9b7fbe | ||
|
|
025d2264a2 | ||
|
|
b2284b2097 | ||
|
|
5f8267c956 | ||
|
|
cf783a5bae | ||
|
|
32e5ced814 | ||
|
|
605fadabcf | ||
|
|
e91ace7329 | ||
|
|
c87cd136d4 | ||
|
|
0d7d59609a | ||
|
|
75ed0e5906 | ||
|
|
8e3b500307 | ||
|
|
d6f77bf07e | ||
|
|
65e8209d51 | ||
|
|
aae5247caa | ||
|
|
2fedb6b774 | ||
|
|
02d18d4831 | ||
|
|
b70c2d088d | ||
|
|
b3c396683e | ||
|
|
f08874dd37 | ||
|
|
648054da9b | ||
|
|
70bf7c490c | ||
|
|
adbed5de95 | ||
|
|
fe989f0bff | ||
|
|
679e346bcb | ||
|
|
832439b336 | ||
|
|
71c2af04ec | ||
|
|
0f4261d02f | ||
|
|
23466d8eee | ||
|
|
8edbba2180 | ||
|
|
5417671332 | ||
|
|
35d7e11678 | ||
|
|
7a63ba827b | ||
|
|
71c163a8ee | ||
|
|
5d8e661807 | ||
|
|
24244e8474 | ||
|
|
fb4f9bdc40 | ||
|
|
668c46e0cf | ||
|
|
abf8fdb661 | ||
|
|
a28a04b7a0 | ||
|
|
cd9671650b | ||
|
|
00bc762bf1 | ||
|
|
9a065bce03 | ||
|
|
3b2b0bdc97 | ||
|
|
53cd6bdf15 | ||
|
|
edc97c1c07 | ||
|
|
6a24ef2263 | ||
|
|
50ba523fb4 | ||
|
|
a33325f90f | ||
|
|
a173b7159a | ||
|
|
91295d3772 | ||
|
|
9c1c04a8db | ||
|
|
51d0d0d779 | ||
|
|
9cdf627ae3 | ||
|
|
4b9c482384 | ||
|
|
b1ba807ec9 | ||
|
|
c844f153e1 | ||
|
|
4a2b02347f | ||
|
|
e8a05d1874 | ||
|
|
08c4e3fbd6 | ||
|
|
1c5292ac86 | ||
|
|
aa553ea5d8 | ||
|
|
a00bd59e27 | ||
|
|
f02c6c49ee | ||
|
|
e54e37a600 | ||
|
|
b95103cab0 | ||
|
|
9b43e49116 | ||
|
|
457538c8f6 | ||
|
|
da48f0704b | ||
|
|
cf8d953bba | ||
|
|
5f2b859e38 | ||
|
|
3187b5abda | ||
|
|
ce16b50d5f | ||
|
|
4295720770 | ||
|
|
4392df0676 | ||
|
|
4ec3b025f0 | ||
|
|
f4704181e9 | ||
|
|
0e04bea39e | ||
|
|
b54044fd00 | ||
|
|
08c69c09c8 | ||
|
|
681ea420c1 | ||
|
|
48ea54748f | ||
|
|
4b7627595a | ||
|
|
6299e5483b | ||
|
|
6118a966a6 | ||
|
|
1fac9ee1f2 | ||
|
|
1e06b2d51e | ||
|
|
f3a6ed9d61 | ||
|
|
f71cbb6f6e | ||
|
|
23ea22c741 | ||
|
|
8be65bb0ab | ||
|
|
57e2e75d24 | ||
|
|
29cd7568f5 | ||
|
|
581076a5a1 | ||
|
|
27401bb9b8 | ||
|
|
10837ce549 | ||
|
|
1dcd411d00 | ||
|
|
0533fd9227 | ||
|
|
5ce7ffc888 | ||
|
|
9e914de995 | ||
|
|
0cc653263e | ||
|
|
d2d2f278cf | ||
|
|
eb34a95ab7 | ||
|
|
eb1f6c0de6 | ||
|
|
8de79e8fb6 | ||
|
|
fe00f0c369 | ||
|
|
f9ee8583b0 | ||
|
|
a4d5f8c717 | ||
|
|
35c50f074b | ||
|
|
dcfa226509 | ||
|
|
a9fde30a58 | ||
|
|
7ceb52103e | ||
|
|
8da5d37888 | ||
|
|
95cc328b5c | ||
|
|
990c0119a7 | ||
|
|
144afee29e | ||
|
|
9665c08b59 | ||
|
|
20ee6a509d | ||
|
|
70d44b8838 | ||
|
|
b260c8b058 | ||
|
|
5991b59ba3 | ||
|
|
bc1fed0fb4 | ||
|
|
b23c364fc0 | ||
|
|
28b428c5a0 | ||
|
|
5bfc58ed64 | ||
|
|
e9a34fca7b | ||
|
|
6ce9734ddd | ||
|
|
d42797ffeb | ||
|
|
b5ebfa9cc3 | ||
|
|
79eff42c3c | ||
|
|
7022807fa3 | ||
|
|
50a301899e | ||
|
|
351db5f6ef | ||
|
|
09fe616ac5 | ||
|
|
2d7ff39ecc | ||
|
|
6e856efd0e | ||
|
|
c3c899bc85 | ||
|
|
916f3cac41 | ||
|
|
9b5f358823 | ||
|
|
22119c272d | ||
|
|
8d4c526d16 | ||
|
|
83aebb7a00 | ||
|
|
33cd5ce6c1 | ||
|
|
f22c2e768e | ||
|
|
3d7dea0606 | ||
|
|
263a421c4a | ||
|
|
401b92bdbb | ||
|
|
6a696af8f6 | ||
|
|
037d6c253b | ||
|
|
b6de79b21a | ||
|
|
52cf530356 | ||
|
|
861ded37db | ||
|
|
7a67388a97 | ||
|
|
4f60fad3f6 | ||
|
|
67efd8172a | ||
|
|
60fdf9fcb2 | ||
|
|
a606e9b7b5 | ||
|
|
65197a8e48 | ||
|
|
43f769ebac | ||
|
|
dff6eeb90e | ||
|
|
61ebdb3367 | ||
|
|
cd95d0865f | ||
|
|
b68a026627 | ||
|
|
68ccebafbf | ||
|
|
3737252d39 | ||
|
|
888a8d05c4 | ||
|
|
f25f902c20 | ||
|
|
a6ea5496b4 | ||
|
|
222424a80c | ||
|
|
74f31d7d68 | ||
|
|
5c59c8d701 | ||
|
|
30a87e3145 | ||
|
|
87f7a60f71 | ||
|
|
f7d8885257 | ||
|
|
77410dc3c3 | ||
|
|
d1acf02ee8 | ||
|
|
de0954f307 | ||
|
|
7da1e5c3e8 | ||
|
|
3c11e87197 | ||
|
|
b004706eff | ||
|
|
2247e71a52 | ||
|
|
8146e84200 | ||
|
|
1213ec2d57 | ||
|
|
30b6cca366 | ||
|
|
4dd140a887 | ||
|
|
87c555bde3 | ||
|
|
c4951b1236 | ||
|
|
0249eb1307 | ||
|
|
f0279e7f92 | ||
|
|
1a50181ace | ||
|
|
d77bc239c1 | ||
|
|
cb283f4c57 | ||
|
|
803858ab0a | ||
|
|
728fc8cbad | ||
|
|
ad05b91f89 | ||
|
|
671e6cde44 | ||
|
|
7a3ad0afba | ||
|
|
d9f1704e36 | ||
|
|
32223a818c | ||
|
|
31e13d4de3 | ||
|
|
815bd6321b | ||
|
|
9f9bd40343 | ||
|
|
2331226bb6 | ||
|
|
80ff118f0f | ||
|
|
d6eeda7136 | ||
|
|
fb92e498f0 | ||
|
|
bf8d8886fd | ||
|
|
a695726f2a | ||
|
|
6dc4172110 | ||
|
|
25a9ee8eb6 | ||
|
|
e122232761 | ||
|
|
b13eaee6b3 | ||
|
|
f0f5107a5d | ||
|
|
0832cc50a8 | ||
|
|
962a3d0c55 | ||
|
|
6934e0bce7 | ||
|
|
3492d64177 | ||
|
|
057109dcac | ||
|
|
12fa08007d | ||
|
|
3562d34555 | ||
|
|
3ca6f645d4 | ||
|
|
6694d31d07 | ||
|
|
d15edf1955 | ||
|
|
e1ce037550 | ||
|
|
f9c376a524 | ||
|
|
26a907444c | ||
|
|
5c214bf4d8 | ||
|
|
5151a5641e | ||
|
|
9513209b70 | ||
|
|
f1416ac9f7 | ||
|
|
631db56a44 | ||
|
|
7b378d36cc | ||
|
|
8ab269e1b3 | ||
|
|
7652253b8d | ||
|
|
9805319940 | ||
|
|
e1e607cba3 | ||
|
|
d74bcd3583 | ||
|
|
9c0483975c | ||
|
|
2fb85dc129 | ||
|
|
d641adc0fc | ||
|
|
a7a020f431 | ||
|
|
a08ac5a47e | ||
|
|
30e5706eaa | ||
|
|
16444c190d | ||
|
|
3d9633a56c | ||
|
|
c0e630522c | ||
|
|
9422d31f55 | ||
|
|
087c7c19af | ||
|
|
3476b35fca | ||
|
|
950d5defda | ||
|
|
c6f060a24f | ||
|
|
1716c4d6f9 | ||
|
|
cda7a60734 | ||
|
|
ed26ab801c | ||
|
|
8874a6e488 | ||
|
|
657ae44b6f | ||
|
|
01381057c5 | ||
|
|
3dc6ed5672 | ||
|
|
764b48e04a | ||
|
|
4c931967c7 | ||
|
|
a547a791ba | ||
|
|
176072801b | ||
|
|
b941c51cf7 | ||
|
|
8a9fd6846e | ||
|
|
a49355133c | ||
|
|
09cdc20440 | ||
|
|
1c0dfe47c8 | ||
|
|
66623693eb | ||
|
|
7c692444e5 | ||
|
|
4ccb4393c5 | ||
|
|
b2e540b114 | ||
|
|
a5d1165c54 | ||
|
|
aa321e06dd | ||
|
|
8b84ac8a6c | ||
|
|
6c07fbfc12 | ||
|
|
04a478a5ad | ||
|
|
acfa186d44 | ||
|
|
3db504c470 | ||
|
|
3e5955be44 | ||
|
|
f1afbf2c0f | ||
|
|
20c559382d | ||
|
|
a3f1c02347 | ||
|
|
f5945d429e | ||
|
|
a3eced53bb | ||
|
|
20686cc66a | ||
|
|
5608fa32f7 | ||
|
|
a0c5defda6 | ||
|
|
25a3a09d5f | ||
|
|
593301146e | ||
|
|
5715ddc361 | ||
|
|
09ddde177c | ||
|
|
ef18b173cd | ||
|
|
ac4e88e0d2 | ||
|
|
3e82cd7dd4 | ||
|
|
b1f2025558 | ||
|
|
57ca5fea81 | ||
|
|
0ce018cf97 | ||
|
|
15a8710e69 | ||
|
|
cae75dcb6d | ||
|
|
d5e2b70b71 | ||
|
|
05b9fd04c6 | ||
|
|
4650989774 | ||
|
|
bcc77efb88 | ||
|
|
39c1637030 | ||
|
|
6d3028f213 | ||
|
|
b2969b2faf | ||
|
|
d07350e4a4 | ||
|
|
12df55c3d4 | ||
|
|
85b541bfd9 | ||
|
|
a9c6d6a80c | ||
|
|
32ad8aaa4e | ||
|
|
3d8e6aead2 | ||
|
|
2747600a3a | ||
|
|
b7ef63230b | ||
|
|
b4d6c8f37b | ||
|
|
6a907348b4 | ||
|
|
18ab8749ff | ||
|
|
a1ed5cdffc | ||
|
|
760d463bf5 | ||
|
|
5ed2a4e8bb | ||
|
|
60e95ef3bd | ||
|
|
5b648be2a5 | ||
|
|
0149171e1a | ||
|
|
b24caa1e06 | ||
|
|
8fa71afb72 | ||
|
|
309a3d5396 | ||
|
|
afafb3ba32 | ||
|
|
311835a231 | ||
|
|
1f9db0a8fe | ||
|
|
d6c9327aef | ||
|
|
0091863888 | ||
|
|
051ce5e09f | ||
|
|
6146b773cf | ||
|
|
8a4341fec4 | ||
|
|
154b7d256c | ||
|
|
548b0d0b53 | ||
|
|
e59361425f | ||
|
|
713e0f4260 | ||
|
|
8a1bf8cd86 | ||
|
|
f474953b51 | ||
|
|
d5ded53f05 | ||
|
|
82bcd391cd | ||
|
|
058689709f | ||
|
|
23c9fa0b56 | ||
|
|
eb29f10634 | ||
|
|
d5a9e3114a | ||
|
|
7417729482 | ||
|
|
d5c407c098 | ||
|
|
a1256818d9 | ||
|
|
689cec14aa | ||
|
|
04225826f6 | ||
|
|
86787e60f3 | ||
|
|
0c3ec9254d | ||
|
|
c0770402ce | ||
|
|
d7c98062ce | ||
|
|
497c0b7a47 | ||
|
|
d588dde007 | ||
|
|
3de0a3adfc | ||
|
|
b7ebe03ca8 | ||
|
|
a7fb88e293 | ||
|
|
6e1b1e3ed7 | ||
|
|
a66538fe55 | ||
|
|
b2913be086 | ||
|
|
602e65d898 | ||
|
|
338c9c1e0c | ||
|
|
9fac57b713 | ||
|
|
761804b17a | ||
|
|
c47401d729 | ||
|
|
aab52f1e8d | ||
|
|
4d2e44d64b | ||
|
|
41267a42f7 | ||
|
|
568434d0fa | ||
|
|
2c1bbf1ac6 | ||
|
|
1e97dcbb4c | ||
|
|
103c82bc2c | ||
|
|
f3fee5f4fb | ||
|
|
564feadc0d | ||
|
|
f05e0f3a81 | ||
|
|
cb26bc3871 | ||
|
|
f6251eef27 | ||
|
|
a9d6ef5990 | ||
|
|
60da55d6dd | ||
|
|
05147c016c | ||
|
|
f7655f3abe | ||
|
|
62b3509009 | ||
|
|
d817889255 | ||
|
|
d4ddcdd91e | ||
|
|
0bda4c2f76 | ||
|
|
da2279c295 | ||
|
|
be8da851a6 | ||
|
|
d4459a48b9 | ||
|
|
197bd2c3e1 | ||
|
|
d4ea9568ac | ||
|
|
97968213ff | ||
|
|
995885962d | ||
|
|
ddc1928bbb | ||
|
|
056a93f0c9 | ||
|
|
3d9845ff6d | ||
|
|
b615463981 | ||
|
|
d3540e82ff | ||
|
|
15ec8ba6a3 | ||
|
|
db12eab083 | ||
|
|
7d8c77a4b2 | ||
|
|
7c8c479b96 | ||
|
|
e29ae1cc91 | ||
|
|
089dd5b4d7 | ||
|
|
06285b599c | ||
|
|
1b6395b4e4 | ||
|
|
2236f74a55 | ||
|
|
43c9ab1faa | ||
|
|
b56f9b3b16 | ||
|
|
303396dfc3 | ||
|
|
075a53ced0 | ||
|
|
18ccb38824 | ||
|
|
c97831963b | ||
|
|
7c3dc076d2 | ||
|
|
b859347ecd | ||
|
|
ea87193c8f | ||
|
|
c1381b9ebd | ||
|
|
227cd93e67 | ||
|
|
f68f8e5547 | ||
|
|
943e6f02d4 | ||
|
|
01298a7b01 | ||
|
|
46aee8274f | ||
|
|
f76a2eeb9e | ||
|
|
3b7c0be842 | ||
|
|
49378a9145 | ||
|
|
139f61d03e | ||
|
|
f10d04591d | ||
|
|
e65d9e8ccd | ||
|
|
1fc3c0af70 | ||
|
|
e4751e34ae | ||
|
|
e922169e72 | ||
|
|
2b851ef6ae | ||
|
|
5f4b93aba2 | ||
|
|
b66d1a5dab | ||
|
|
867525eff8 | ||
|
|
7dcc981a2c | ||
|
|
38fed8a61e | ||
|
|
31c2c8a7a3 | ||
|
|
a081d28e36 | ||
|
|
93bb4f84f9 | ||
|
|
72e04edd7f | ||
|
|
f6119639bb | ||
|
|
13e635b74e |
27
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
27
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: Feature Request
|
||||
description: Request a new feature
|
||||
title: "[Feature Request]: "
|
||||
labels: ["enhancement"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for your request this will not gurantee that we will implement it, but it will be reviewed.
|
||||
- type: dropdown
|
||||
id: soc
|
||||
attributes:
|
||||
label: Platform
|
||||
description: What device platform will support your feature?
|
||||
multiple: true
|
||||
options:
|
||||
- NRF52
|
||||
- ESP32
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: body
|
||||
attributes:
|
||||
label: Description
|
||||
description: Please provide details about your enhancement.
|
||||
validations:
|
||||
required: true
|
||||
41
.github/actions/setup-base/action.yml
vendored
Normal file
41
.github/actions/setup-base/action.yml
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
name: 'Setup Build Base Composite Action'
|
||||
description: 'Base build actions for Meshtastic Platform IO steps'
|
||||
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: "recursive"
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Install cppcheck
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get install -y cppcheck
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Cache python libs
|
||||
uses: actions/cache@v3
|
||||
id: cache-pip # needed in if test
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip
|
||||
|
||||
- name: Upgrade python tools
|
||||
shell: bash
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio adafruit-nrfutil
|
||||
pip install -U meshtastic --pre
|
||||
|
||||
- name: Upgrade platformio
|
||||
shell: bash
|
||||
run: |
|
||||
pio upgrade
|
||||
54
.github/workflows/build_esp32.yml
vendored
Normal file
54
.github/workflows/build_esp32.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
name: Build ESP32
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build-esp32:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Pull web ui
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: "meshtastic/web"
|
||||
file: "build.tar"
|
||||
target: "build.tar"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Unpack web ui
|
||||
run: |
|
||||
tar -xf build.tar -C data/static
|
||||
rm build.tar
|
||||
|
||||
- name: Build ESP32
|
||||
run: bin/build-esp32.sh ${{ inputs.board }}
|
||||
|
||||
- name: Pull OTA Firmware
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: "meshtastic/firmware-ota"
|
||||
file: "firmware.bin"
|
||||
target: "release/bleota.bin"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get release version string
|
||||
shell: bash
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||
path: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
33
.github/workflows/build_nrf52.yml
vendored
Normal file
33
.github/workflows/build_nrf52.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
name: Build NRF52
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build-nrf52:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Build NRF52
|
||||
run: bin/build-nrf52.sh ${{ inputs.board }}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||
path: |
|
||||
release/*.uf2
|
||||
release/*.elf
|
||||
release/*.zip
|
||||
32
.github/workflows/build_rpi2040.yml
vendored
Normal file
32
.github/workflows/build_rpi2040.yml
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
name: Build RPI2040
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
board:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
build-rpi2040:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Build Raspberry Pi 2040
|
||||
run: ./bin/build-rpi2040.sh ${{ inputs.board }}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: firmware-${{ inputs.board }}-${{ steps.version.outputs.version }}.zip
|
||||
path: |
|
||||
release/*.uf2
|
||||
release/*.elf
|
||||
327
.github/workflows/main_matrix.yml
vendored
327
.github/workflows/main_matrix.yml
vendored
@@ -2,14 +2,14 @@ name: CI
|
||||
on:
|
||||
# # Triggers the workflow on push but only for the master branch
|
||||
push:
|
||||
branches: [master]
|
||||
branches: [master, develop]
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- "version.properties"
|
||||
|
||||
# Note: This is different from "pull_request". Need to specify ref when doing checkouts.
|
||||
pull_request_target:
|
||||
branches: [master]
|
||||
branches: [master, develop]
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
#- "**.yml"
|
||||
@@ -23,59 +23,23 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- board: rak11200
|
||||
- board: tlora-v2
|
||||
- board: tlora-v1
|
||||
- board: tlora_v1_3
|
||||
- board: tlora-v2-1-1.6
|
||||
- board: tbeam
|
||||
- board: heltec-v1
|
||||
- board: heltec-v2.0
|
||||
- board: heltec-v2.1
|
||||
- board: tbeam0.7
|
||||
- board: meshtastic-diy-v1
|
||||
- board: rak4631
|
||||
- board: rak4631_eink
|
||||
- board: t-echo
|
||||
- board: nano-g1
|
||||
- board: station-g1
|
||||
- board: m5stack-core
|
||||
- board: m5stack-coreink
|
||||
- board: tbeam-s3-core
|
||||
# - board: pico
|
||||
- board: tlora-t3s3-v1
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: "recursive"
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Install cppcheck
|
||||
run: |
|
||||
sudo apt-get install -y cppcheck
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Cache python libs
|
||||
uses: actions/cache@v1
|
||||
id: cache-pip # needed in if test
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip
|
||||
|
||||
- name: Upgrade python tools and install platformio
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio
|
||||
|
||||
- name: Upgrade platformio
|
||||
run: |
|
||||
pio upgrade
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
- name: Check ${{ matrix.board }}
|
||||
run: bin/check-all.sh ${{ matrix.board }}
|
||||
@@ -90,84 +54,25 @@ jobs:
|
||||
- board: tlora-v1
|
||||
- board: tlora_v1_3
|
||||
- board: tlora-v2-1-1.6
|
||||
- board: tlora-v2-1-1.8
|
||||
- board: tbeam
|
||||
- board: heltec-v1
|
||||
- board: heltec-v2.0
|
||||
- board: heltec-v2.1
|
||||
- board: heltec-v3
|
||||
- board: heltec-wsl-v3
|
||||
- board: tbeam0.7
|
||||
- board: meshtastic-diy-v1
|
||||
- board: meshtastic-dr-dev
|
||||
- board: nano-g1
|
||||
- board: station-g1
|
||||
- board: m5stack-core
|
||||
- board: m5stack-coreink
|
||||
- board: tbeam-s3-core
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: "recursive"
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Cache python libs
|
||||
uses: actions/cache@v1
|
||||
id: cache-pip # needed in if test
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip
|
||||
|
||||
- name: Upgrade python tools
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio adafruit-nrfutil
|
||||
|
||||
- name: Upgrade platformio
|
||||
run: |
|
||||
pio upgrade
|
||||
|
||||
- name: Pull web ui
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: "meshtastic/meshtastic-web"
|
||||
file: "build.tar"
|
||||
target: "build.tar"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Unpack web ui
|
||||
run: |
|
||||
tar -xf build.tar -C data/static
|
||||
rm build.tar
|
||||
|
||||
- name: Build ESP32
|
||||
run: bin/build-esp32.sh ${{ matrix.board }}
|
||||
|
||||
- name: Pull OTA Firmware
|
||||
uses: dsaltares/fetch-gh-release-asset@master
|
||||
with:
|
||||
repo: "meshtastic/Meshtastic-OTA"
|
||||
file: "firmware.bin"
|
||||
target: "release/bleota.bin"
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
|
||||
path: |
|
||||
release/*.bin
|
||||
release/*.elf
|
||||
retention-days: 90
|
||||
- board: tlora-t3s3-v1
|
||||
uses: ./.github/workflows/build_esp32.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-nrf52:
|
||||
strategy:
|
||||
@@ -179,53 +84,10 @@ jobs:
|
||||
- board: rak4631_eink
|
||||
- board: t-echo
|
||||
- board: pca10059_diy_eink
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: "recursive"
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Cache python libs
|
||||
uses: actions/cache@v1
|
||||
id: cache-pip # needed in if test
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip
|
||||
|
||||
- name: Upgrade python tools
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio adafruit-nrfutil
|
||||
|
||||
- name: Upgrade platformio
|
||||
run: |
|
||||
pio upgrade
|
||||
|
||||
- name: Build NRF52
|
||||
run: bin/build-nrf52.sh ${{ matrix.board }}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
|
||||
path: |
|
||||
release/*.uf2
|
||||
release/*.elf
|
||||
release/*.zip
|
||||
retention-days: 90
|
||||
- board: feather_diy
|
||||
uses: ./.github/workflows/build_nrf52.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-rpi2040:
|
||||
strategy:
|
||||
@@ -234,84 +96,17 @@ jobs:
|
||||
matrix:
|
||||
include:
|
||||
- board: pico
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: "recursive"
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Cache python libs
|
||||
uses: actions/cache@v1
|
||||
id: cache-pip # needed in if test
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip
|
||||
|
||||
- name: Upgrade python tools
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio adafruit-nrfutil
|
||||
|
||||
- name: Upgrade platformio
|
||||
run: |
|
||||
pio upgrade
|
||||
|
||||
- name: Build Raspberry Pi 2040
|
||||
run: ./bin/build-rpi2040.sh ${{ matrix.board }}
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: firmware-${{ matrix.board }}-${{ steps.version.outputs.version }}.zip
|
||||
path: |
|
||||
release/*.uf2
|
||||
release/*.elf
|
||||
retention-days: 90
|
||||
uses: ./.github/workflows/build_rpi2040.yml
|
||||
with:
|
||||
board: ${{ matrix.board }}
|
||||
|
||||
build-native:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: "recursive"
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Cache python libs
|
||||
uses: actions/cache@v1
|
||||
id: cache-pip # needed in if test
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip
|
||||
|
||||
- name: Upgrade python tools
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -U platformio adafruit-nrfutil
|
||||
pip install -U meshtastic --pre
|
||||
|
||||
- name: Upgrade platformio
|
||||
run: |
|
||||
pio upgrade
|
||||
- uses: actions/checkout@v3
|
||||
- name: Build base
|
||||
id: base
|
||||
uses: ./.github/actions/setup-base
|
||||
|
||||
# We now run integration test before other build steps (to quickly see runtime failures)
|
||||
- name: Build for native
|
||||
@@ -327,19 +122,37 @@ jobs:
|
||||
run: bin/build-native.sh
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Store binaries as an artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: firmware-native-${{ steps.version.outputs.version }}.zip
|
||||
path: |
|
||||
release/meshtasticd_linux_amd64
|
||||
release/device-*.sh
|
||||
release/device-*.bat
|
||||
retention-days: 90
|
||||
|
||||
- name: Docker login
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: meshtastic
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
|
||||
- name: Docker setup
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
- name: Docker build and push
|
||||
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: meshtastic/device-simulator:latest
|
||||
|
||||
after-checks:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check]
|
||||
@@ -360,31 +173,30 @@ jobs:
|
||||
ref: ${{github.event.pull_request.head.ref}}
|
||||
repository: ${{github.event.pull_request.head.repo.full_name}}
|
||||
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: ./
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- name: Move files up
|
||||
run: mv -b -t ./ ./*tbeam-1*/littlefs*.bin ./*tbeam-1*/bleota.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./**/meshtasticd_linux_amd64 ./*native*/*device-*.sh ./*native*/*device-*.bat
|
||||
run: mv -b -t ./ ./*tbeam-2*/littlefs*.bin ./*tbeam-2*/bleota.bin ./**/firmware*.bin ./*t-echo*/Meshtastic_nRF52_factory_erase.uf2 ./**/firmware-*.uf2 ./**/firmware-*-ota.zip ./**/*.elf ./*native*/*device-*.sh ./*native*/*device-*.bat
|
||||
|
||||
- name: Repackage in single firmware zip
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: firmware-${{ steps.version.outputs.version }}
|
||||
path: |
|
||||
./*.bin
|
||||
./*.uf2
|
||||
./firmware-*-ota.zip
|
||||
./meshtasticd_linux_amd64
|
||||
./device-*.sh
|
||||
./device-*.bat
|
||||
retention-days: 90
|
||||
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: firmware-${{ steps.version.outputs.version }}
|
||||
path: ./output
|
||||
@@ -392,21 +204,21 @@ jobs:
|
||||
# For diagnostics
|
||||
- name: Show artifacts
|
||||
run: ls -lR
|
||||
|
||||
|
||||
- name: Device scripts permissions
|
||||
run: |
|
||||
chmod +x ./output/device-install.sh
|
||||
chmod +x ./output/device-update.sh
|
||||
|
||||
- name: Zip firmware
|
||||
run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
|
||||
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
|
||||
|
||||
- name: Repackage in single elfs zip
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||
path: ./*.elf
|
||||
retention-days: 90
|
||||
retention-days: 30
|
||||
|
||||
- name: Create request artifacts
|
||||
if: ${{ github.event_name == 'pull_request_target' || github.event_name == 'pull_request' }}
|
||||
@@ -426,37 +238,37 @@ jobs:
|
||||
needs: [gather-artifacts, after-checks]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- name: Get release version string
|
||||
run: echo "::set-output name=version::$(./bin/buildinfo.py long)"
|
||||
run: echo "version=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
|
||||
id: version
|
||||
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: firmware-${{ steps.version.outputs.version }}
|
||||
path: ./output
|
||||
|
||||
|
||||
- name: Device scripts permissions
|
||||
run: |
|
||||
chmod +x ./output/device-install.sh
|
||||
chmod +x ./output/device-update.sh
|
||||
|
||||
- name: Zip firmware
|
||||
run: zip -j -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
|
||||
run: zip -j -9 -r ./firmware-${{ steps.version.outputs.version }}.zip ./output
|
||||
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: debug-elfs-${{ steps.version.outputs.version }}.zip
|
||||
path: ./elfs
|
||||
|
||||
|
||||
- name: Zip Elfs
|
||||
run: zip -j -r ./debug-elfs-${{ steps.version.outputs.version }}.zip ./elfs
|
||||
run: zip -j -9 -r ./debug-elfs-${{ steps.version.outputs.version }}.zip ./elfs
|
||||
|
||||
# For diagnostics
|
||||
- name: Show artifacts
|
||||
@@ -468,7 +280,7 @@ jobs:
|
||||
with:
|
||||
draft: true
|
||||
prerelease: true
|
||||
release_name: Meshtastic Device ${{ steps.version.outputs.version }} alpha - Public Preview
|
||||
release_name: Meshtastic Firmware ${{ steps.version.outputs.version }}
|
||||
tag_name: v${{ steps.version.outputs.version }}
|
||||
body: |
|
||||
Autogenerated by github action, developer should edit as required before publishing...
|
||||
@@ -498,10 +310,9 @@ jobs:
|
||||
- name: Bump version.properties
|
||||
run: >-
|
||||
bin/bump_version.py
|
||||
|
||||
|
||||
- name: Create version.properties pull request
|
||||
uses: peter-evans/create-pull-request@v3
|
||||
with:
|
||||
add-paths: |
|
||||
version.properties
|
||||
|
||||
|
||||
40
.github/workflows/sec_sast_flawfinder.yml
vendored
Normal file
40
.github/workflows/sec_sast_flawfinder.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
name: Flawfinder Scan
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master, develop]
|
||||
paths-ignore:
|
||||
- "**.md"
|
||||
- "version.properties"
|
||||
|
||||
jobs:
|
||||
flawfinder:
|
||||
runs-on: ubuntu-latest
|
||||
name: Flawfinder
|
||||
|
||||
steps:
|
||||
# step 1
|
||||
- name: clone application source code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# step 2
|
||||
- name: flawfinder_scan
|
||||
uses: david-a-wheeler/flawfinder@2.0.19
|
||||
with:
|
||||
arguments: '--sarif ./'
|
||||
output: 'flawfinder_report.sarif'
|
||||
|
||||
# step 3
|
||||
- name: save report as pipeline artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: flawfinder_report.sarif
|
||||
path: flawfinder_report.sarif
|
||||
|
||||
# step 4
|
||||
- name: publish code scanning alerts
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: flawfinder_report.sarif
|
||||
category: flawfinder
|
||||
44
.github/workflows/sec_sast_semgrep_cron.yml
vendored
Normal file
44
.github/workflows/sec_sast_semgrep_cron.yml
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
---
|
||||
name: Semgrep Full Scan
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
branches:
|
||||
- master
|
||||
schedule:
|
||||
- cron: '0 1 * * 6'
|
||||
|
||||
jobs:
|
||||
|
||||
semgrep-full:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: returntocorp/semgrep
|
||||
|
||||
steps:
|
||||
|
||||
# step 1
|
||||
- name: clone application source code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# step 2
|
||||
- name: full scan
|
||||
run: |
|
||||
semgrep \
|
||||
--sarif --output report.sarif \
|
||||
--metrics=off \
|
||||
--config="p/default"
|
||||
|
||||
# step 3
|
||||
- name: save report as pipeline artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: report.sarif
|
||||
path: report.sarif
|
||||
|
||||
# step 4
|
||||
- name: publish code scanning alerts
|
||||
uses: github/codeql-action/upload-sarif@v2
|
||||
with:
|
||||
sarif_file: report.sarif
|
||||
category: semgrep
|
||||
28
.github/workflows/sec_sast_semgrep_pull.yml
vendored
Normal file
28
.github/workflows/sec_sast_semgrep_pull.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: Semgrep Differential Scan
|
||||
on:
|
||||
pull_request
|
||||
|
||||
jobs:
|
||||
|
||||
semgrep-diff:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: returntocorp/semgrep
|
||||
|
||||
steps:
|
||||
|
||||
# step 1
|
||||
- name: clone application source code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
# step 2
|
||||
- name: differential scan
|
||||
run: |
|
||||
semgrep scan \
|
||||
--error \
|
||||
--metrics=off \
|
||||
--baseline-commit ${{ github.event.pull_request.base.sha }} \
|
||||
--config="p/default"
|
||||
6
.github/workflows/update_protobufs.yml
vendored
6
.github/workflows/update_protobufs.yml
vendored
@@ -17,9 +17,9 @@ jobs:
|
||||
|
||||
- name: Download nanopb
|
||||
run: |
|
||||
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.6-linux-x86.tar.gz
|
||||
tar xvzf nanopb-0.4.6-linux-x86.tar.gz
|
||||
mv nanopb-0.4.6-linux-x86 nanopb-0.4.6
|
||||
wget https://jpa.kapsi.fi/nanopb/download/nanopb-0.4.7-linux-x86.tar.gz
|
||||
tar xvzf nanopb-0.4.7-linux-x86.tar.gz
|
||||
mv nanopb-0.4.7-linux-x86 nanopb-0.4.7
|
||||
|
||||
- name: Re-generate protocol buffers
|
||||
run: |
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -29,3 +29,4 @@ __pycache__
|
||||
|
||||
venv/
|
||||
release/
|
||||
.vscode/extensions.json
|
||||
|
||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
||||
[submodule "protobufs"]
|
||||
path = protobufs
|
||||
url = https://github.com/meshtastic/Meshtastic-protobufs.git
|
||||
url = https://github.com/meshtastic/protobufs.git
|
||||
|
||||
2
.semgrepignore
Normal file
2
.semgrepignore
Normal file
@@ -0,0 +1,2 @@
|
||||
.github/workflows/main_matrix.yml
|
||||
src/mesh/compression/unishox2.c
|
||||
41
Dockerfile
Normal file
41
Dockerfile
Normal file
@@ -0,0 +1,41 @@
|
||||
FROM debian:bullseye-slim AS builder
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
ENV TZ=Etc/UTC
|
||||
|
||||
# http://bugs.python.org/issue19846
|
||||
# > At the moment, setting "LANG=C" on a Linux system *fundamentally breaks Python 3*, and that's not OK.
|
||||
ENV LANG C.UTF-8
|
||||
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
|
||||
# Install build deps
|
||||
USER root
|
||||
RUN apt-get update && \
|
||||
apt-get -y install wget python3 g++ zip python3-venv git vim ca-certificates
|
||||
|
||||
# create a non-priveleged user & group
|
||||
RUN groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
|
||||
|
||||
USER mesh
|
||||
RUN wget https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py -qO /tmp/get-platformio.py && \
|
||||
chmod +x /tmp/get-platformio.py && \
|
||||
python3 /tmp/get-platformio.py && \
|
||||
git clone https://github.com/meshtastic/firmware --recurse-submodules /tmp/firmware && \
|
||||
cd /tmp/firmware && \
|
||||
chmod +x /tmp/firmware/bin/build-native.sh && \
|
||||
source ~/.platformio/penv/bin/activate && \
|
||||
./bin/build-native.sh
|
||||
|
||||
FROM frolvlad/alpine-glibc
|
||||
|
||||
RUN apk --update add --no-cache g++ shadow && \
|
||||
groupadd -g 1000 mesh && useradd -ml -u 1000 -g 1000 mesh
|
||||
|
||||
COPY --from=builder /tmp/firmware/release/meshtasticd_linux_amd64 /home/mesh/
|
||||
|
||||
USER mesh
|
||||
WORKDIR /home/mesh
|
||||
CMD sh -cx "./meshtasticd_linux_amd64 --hwid '$RANDOM'"
|
||||
|
||||
HEALTHCHECK NONE
|
||||
11
README.md
11
README.md
@@ -1,8 +1,8 @@
|
||||
# Meshtastic Firmware
|
||||
|
||||

|
||||
[](https://github.com/meshtastic/repo/actions/workflows/main_matrix.yml)
|
||||
[](https://cla-assistant.io/meshtastic/Meshtastic-device)
|
||||

|
||||
[](https://github.com/meshtastic/firmware/actions/workflows/ci.yml)
|
||||
[](https://cla-assistant.io/meshtastic/firmware)
|
||||
[](https://opencollective.com/meshtastic/)
|
||||
[](https://vercel.com?utm_source=meshtastic&utm_campaign=oss)
|
||||
|
||||
@@ -10,10 +10,9 @@
|
||||
|
||||
This repository contains the device firmware for the Meshtastic project.
|
||||
|
||||
|
||||
**[Building Instructions](https://meshtastic.org/docs/developers/Firmware/build)**
|
||||
**[Building Instructions](https://meshtastic.org/docs/development/firmware/build)**
|
||||
**[Flashing Instructions](https://meshtastic.org/docs/getting-started/flashing-firmware/)**
|
||||
|
||||
## Stats
|
||||
|
||||

|
||||

|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
extends = arduino_base
|
||||
platform = platformio/espressif32@^5.2.0
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040>
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/>
|
||||
upload_speed = 921600
|
||||
debug_init_break = tbreak setup
|
||||
monitor_filters = esp32_exception_decoder
|
||||
@@ -31,10 +31,10 @@ lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd
|
||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||
h2zero/NimBLE-Arduino@^1.4.0
|
||||
arduino-libraries/NTPClient@^3.1.0
|
||||
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||
caveman99/ESP32 Codec2@^1.0.1
|
||||
|
||||
lib_ignore =
|
||||
segger_rtt
|
||||
|
||||
46
arch/esp32/esp32s2.ini
Normal file
46
arch/esp32/esp32s2.ini
Normal file
@@ -0,0 +1,46 @@
|
||||
[esp32s2_base]
|
||||
extends = arduino_base
|
||||
platform = platformio/espressif32@^5.2.0
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/> -<nimble/>
|
||||
upload_speed = 961200
|
||||
monitor_speed = 115200
|
||||
debug_init_break = tbreak setup
|
||||
monitor_filters = esp32_exception_decoder
|
||||
board_build.filesystem = littlefs
|
||||
|
||||
# Remove -DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL for low level BLE logging.
|
||||
# See library directory for BLE logging possible values: .pio/libdeps/tbeam/NimBLE-Arduino/src/log_common/log_common.h
|
||||
# This overrides the BLE logging default of LOG_LEVEL_INFO (1) from: .pio/libdeps/tbeam/NimBLE-Arduino/src/esp_nimble_cfg.h
|
||||
build_flags =
|
||||
${arduino_base.build_flags}
|
||||
-Wall
|
||||
-Wextra
|
||||
-Isrc/platform/esp32
|
||||
-std=c++11
|
||||
-DLOG_LOCAL_LEVEL=ESP_LOG_DEBUG
|
||||
-DCORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG
|
||||
-DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
|
||||
-DAXP_DEBUG_PORT=Serial
|
||||
-DCONFIG_BT_NIMBLE_ENABLED
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
|
||||
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
-DHAS_BLUETOOTH=0
|
||||
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||
caveman99/ESP32 Codec2@^1.0.1
|
||||
|
||||
lib_ignore =
|
||||
segger_rtt
|
||||
ESP32 BLE Arduino
|
||||
|
||||
; customize the partition table
|
||||
; http://docs.platformio.org/en/latest/platforms/espressif32.html#partition-tables
|
||||
board_build.partitions = partition-table.csv
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
extends = arduino_base
|
||||
platform = platformio/espressif32@^5.2.0
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040>
|
||||
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2040> -<mesh/eth/>
|
||||
upload_speed = 961200
|
||||
monitor_speed = 115200
|
||||
debug_init_break = tbreak setup
|
||||
@@ -23,18 +23,18 @@ build_flags =
|
||||
-DMYNEWT_VAL_BLE_HS_LOG_LVL=LOG_LEVEL_CRITICAL
|
||||
-DAXP_DEBUG_PORT=Serial
|
||||
-DCONFIG_BT_NIMBLE_ENABLED
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
|
||||
-DCONFIG_NIMBLE_CPP_LOG_LEVEL=2
|
||||
-DCONFIG_BT_NIMBLE_MAX_CCCDS=20
|
||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
-DESP_OPENSSL_SUPPRESS_LEGACY_WARNING
|
||||
|
||||
lib_deps =
|
||||
${arduino_base.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
${environmental_base.lib_deps}
|
||||
https://github.com/meshtastic/esp32_https_server.git#657509856ce97e9dddeffb89a559f544faefd5cd
|
||||
https://github.com/meshtastic/esp32_https_server.git#23665b3adc080a311dcbb586ed5941b5f94d6ea2
|
||||
h2zero/NimBLE-Arduino@^1.4.0
|
||||
arduino-libraries/NTPClient@^3.1.0
|
||||
https://github.com/lewisxhe/XPowersLib.git#84b7373faea3118b6c37954d52f98b8a337148d6
|
||||
caveman99/ESP32 Codec2@^1.0.1
|
||||
|
||||
lib_ignore =
|
||||
segger_rtt
|
||||
|
||||
@@ -8,7 +8,7 @@ build_flags =
|
||||
${arduino_base.build_flags} -Wno-unused-variable
|
||||
-Isrc/platform/nrf52
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/rp2040>
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<platform/stm32wl> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/rp2040> -<mesh/eth/>
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
; The Portduino based sim environment on top of any host OS, all hardware will be simulated
|
||||
[portduino_base]
|
||||
platform = https://github.com/meshtastic/platform-native.git#096b3c3e9c5c8e19d4c3b6cd803fffef2a9be4c5
|
||||
framework = arduino
|
||||
build_src_filter =
|
||||
${env.build_src_filter}
|
||||
-<platform/esp32/>
|
||||
@@ -7,7 +9,8 @@ build_src_filter =
|
||||
-<platform/nrf52/>
|
||||
-<platform/stm32wl/>
|
||||
-<platform/rp2040>
|
||||
-<mesh/http/>
|
||||
-<mesh/http/>
|
||||
-<mesh/eth/>
|
||||
-<modules/esp32>
|
||||
-<modules/Telemetry>
|
||||
+<../variants/portduino>
|
||||
@@ -15,5 +18,4 @@ lib_deps =
|
||||
${env.lib_deps}
|
||||
${networking_base.lib_deps}
|
||||
rweather/Crypto@^0.4.0
|
||||
https://github.com/meshtastic/RadioLib.git#5582ac30578ff3f53f20630a00b2a8a4b8f92c74
|
||||
build_flags = ${arduino_base.build_flags} -Isrc/platform/portduino
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
; Common settings for rp2040 Processor based targets
|
||||
[rp2040_base]
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#5ce1a228e7cae453f366deb8962252b9b7356bbc
|
||||
platform = https://github.com/maxgerhardt/platform-raspberrypi.git#20c7dbfcfe6677c5305fa28ecf5e3870321cb157
|
||||
platform_packages =
|
||||
earlephilhower/toolchain-rp2040-earlephilhower@^5.100300.221223
|
||||
extends = arduino_base
|
||||
board_build.core = earlephilhower
|
||||
board_build.filesystem_size = 0.5m
|
||||
@@ -10,7 +12,7 @@ build_flags =
|
||||
-D__PLAT_RP2040__
|
||||
# -D _POSIX_THREADS
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/nrf52/> -<platform/stm32wl>
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<platform/nrf52/> -<platform/stm32wl> -<mesh/eth/>
|
||||
lib_ignore =
|
||||
BluetoothOTA
|
||||
lib_deps =
|
||||
|
||||
@@ -10,7 +10,7 @@ build_flags =
|
||||
# Arduino/PlatformIO framework-arduinoststm32 package does not presently have SUBGHZSPI support
|
||||
# -DPIN_SPI_MOSI=PINSUBGHZSPIMOSI -DPIN_SPI_MISO=PINSUBGHZSPIMISO -DPIN_SPI_SCK=PINSUBGHZSPISCK
|
||||
build_src_filter =
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
|
||||
${arduino_base.build_src_filter} -<platform/esp32/> -<nimble/> -<mesh/wifi/> -<mesh/http/> -<modules/esp32> -<mesh/eth/> -<mqtt/> -<graphics> -<input> -<buzz> -<modules/Telemetry> -<platform/nrf52> -<platform/portduino> -<platform/rp2040>
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
https://github.com/kokke/tiny-AES-c.git#f06ac37fc31dfdaca2e0d9bec83f90d5663c319b
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
VERSION=`bin/buildinfo.py long`
|
||||
SHORT_VERSION=`bin/buildinfo.py short`
|
||||
|
||||
BOARDS_ESP32="rak11200 tlora-v2 tlora-v1 tlora_v1_3 tlora-v2-1-1.6 tbeam heltec-v1 heltec-v2.0 heltec-v2.1 tbeam0.7 meshtastic-diy-v1 nano-g1 station-g1 m5stack-core m5stack-coreink"
|
||||
#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="rak4631 rak4631_eink t-echo pca10059_diy_eink"
|
||||
#BOARDS_NRF52=""
|
||||
|
||||
OUTDIR=release/latest
|
||||
|
||||
# We keep all old builds (and their map files in the archive dir)
|
||||
ARCHIVEDIR=release/archive
|
||||
|
||||
rm -f $OUTDIR/firmware*
|
||||
|
||||
mkdir -p $OUTDIR/bins $ARCHIVEDIR
|
||||
rm -r $OUTDIR/bins/* || true
|
||||
mkdir -p $OUTDIR/bins/universal $OUTDIR/elfs/universal
|
||||
|
||||
# build the named environment and copy the bins to the release directory
|
||||
function do_build() {
|
||||
BOARD=$1
|
||||
isNrf=$3
|
||||
|
||||
echo "Building for $BOARD ($isNrf) with $PLATFORMIO_BUILD_FLAGS"
|
||||
rm -f .pio/build/$BOARD/firmware.*
|
||||
|
||||
# The shell vars the build tool expects to find
|
||||
export APP_VERSION=$VERSION
|
||||
|
||||
basename=universal/firmware-$BOARD-$VERSION
|
||||
|
||||
pio run --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
|
||||
# Build universal
|
||||
echo "about to build $board $isNrf"
|
||||
do_build $board "" "$isNrf"
|
||||
done
|
||||
}
|
||||
|
||||
# Make sure our submodules are current
|
||||
git submodule update
|
||||
|
||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||
platformio lib update
|
||||
|
||||
do_boards "$BOARDS_ESP32" "false"
|
||||
do_boards "$BOARDS_NRF52" "true"
|
||||
|
||||
pio run --environment native
|
||||
cp .pio/build/native/program $OUTDIR/bins/universal/meshtasticd_linux_amd64
|
||||
|
||||
echo "Building Filesystem for ESP32 targets"
|
||||
pio run --environment tbeam -t buildfs
|
||||
cp .pio/build/tbeam/spiffs.bin $OUTDIR/bins/universal/littlefs-$VERSION.bin
|
||||
|
||||
# keep the bins in archive also
|
||||
cp $OUTDIR/bins/universal/littlefs* $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"?>
|
||||
|
||||
<!-- This file is kept in source control because it reflects the last stable
|
||||
release. It is used by the android app for forcing software updates. Do not edit.
|
||||
Generated by bin/buildall.sh -->
|
||||
|
||||
<resources>
|
||||
<string name="cur_firmware_version" translatable="false">$VERSION</string>
|
||||
<string name="short_firmware_version" translatable="false">$SHORT_VERSION</string>
|
||||
</resources>
|
||||
XML
|
||||
|
||||
echo Generating $ARCHIVEDIR/firmware-$VERSION.zip
|
||||
rm -f $ARCHIVEDIR/firmware-$VERSION.zip
|
||||
zip --junk-paths $ARCHIVEDIR/firmware-$VERSION.zip $ARCHIVEDIR/littlefs-$VERSION.bin $OUTDIR/bins/universal/firmware-*-$VERSION.* $OUTDIR/bins/universal/meshtasticd* images/system-info.bin bin/device-install.* bin/device-update.*
|
||||
echo Generating $ARCHIVEDIR/elfs-$VERSION.zip
|
||||
rm -f $ARCHIVEDIR/elfs-$VERSION.zip
|
||||
zip --junk-paths $ARCHIVEDIR/elfs-$VERSION.zip $OUTDIR/elfs/universal/firmware-*-$VERSION.*
|
||||
|
||||
echo BUILT ALL
|
||||
@@ -10,11 +10,8 @@ OUTDIR=release/
|
||||
rm -f $OUTDIR/firmware*
|
||||
rm -r $OUTDIR/* || true
|
||||
|
||||
# Make sure our submodules are current
|
||||
git submodule update
|
||||
|
||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||
platformio lib update
|
||||
platformio pkg update
|
||||
|
||||
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
||||
rm -f .pio/build/$1/firmware.*
|
||||
@@ -32,6 +29,10 @@ echo "Copying ESP32 bin file"
|
||||
SRCBIN=.pio/build/$1/firmware.factory.bin
|
||||
cp $SRCBIN $OUTDIR/$basename.bin
|
||||
|
||||
echo "Copying ESP32 update bin file"
|
||||
SRCBIN=.pio/build/$1/firmware.bin
|
||||
cp $SRCBIN $OUTDIR/$basename-update.bin
|
||||
|
||||
echo "Building Filesystem for ESP32 targets"
|
||||
pio run --environment tbeam -t buildfs
|
||||
cp .pio/build/tbeam/littlefs.bin $OUTDIR/littlefs-$VERSION.bin
|
||||
|
||||
@@ -12,11 +12,8 @@ rm -f $OUTDIR/firmware*
|
||||
mkdir -p $OUTDIR/
|
||||
rm -r $OUTDIR/* || true
|
||||
|
||||
# Make sure our submodules are current
|
||||
git submodule update
|
||||
|
||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||
platformio lib update
|
||||
platformio pkg update
|
||||
|
||||
pio run --environment native
|
||||
cp .pio/build/native/program $OUTDIR/meshtasticd_linux_amd64
|
||||
|
||||
@@ -10,11 +10,8 @@ OUTDIR=release/
|
||||
rm -f $OUTDIR/firmware*
|
||||
rm -r $OUTDIR/* || true
|
||||
|
||||
# Make sure our submodules are current
|
||||
git submodule update
|
||||
|
||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||
platformio lib update
|
||||
platformio pkg update
|
||||
|
||||
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
||||
rm -f .pio/build/$1/firmware.*
|
||||
|
||||
@@ -10,11 +10,8 @@ OUTDIR=release/
|
||||
rm -f $OUTDIR/firmware*
|
||||
rm -r $OUTDIR/* || true
|
||||
|
||||
# Make sure our submodules are current
|
||||
git submodule update
|
||||
|
||||
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
|
||||
platformio lib update
|
||||
platformio pkg update
|
||||
|
||||
echo "Building for $1 with $PLATFORMIO_BUILD_FLAGS"
|
||||
rm -f .pio/build/$1/firmware.*
|
||||
|
||||
@@ -26,7 +26,7 @@ IF "__%FILENAME%__" == "____" (
|
||||
echo "Missing FILENAME"
|
||||
goto HELP
|
||||
)
|
||||
IF EXIST %FILENAME% (
|
||||
IF EXIST %FILENAME% IF x%FILENAME:update=%==x%FILENAME% (
|
||||
echo Trying to flash update %FILENAME%, but first erasing and writing system information"
|
||||
%PYTHON% -m esptool --baud 115200 erase_flash
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
|
||||
@@ -37,6 +37,9 @@ IF EXIST %FILENAME% (
|
||||
) else (
|
||||
echo "Invalid file: %FILENAME%"
|
||||
goto HELP
|
||||
) else (
|
||||
echo "Invalid file: %FILENAME%"
|
||||
goto HELP
|
||||
)
|
||||
|
||||
:EOF
|
||||
|
||||
@@ -14,6 +14,7 @@ Flash image file to device, but first erasing and writing system information"
|
||||
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous).
|
||||
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
|
||||
-f FILENAME The .bin file to flash. Custom to your device type and region.
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -44,7 +45,7 @@ shift "$((OPTIND-1))"
|
||||
shift
|
||||
}
|
||||
|
||||
if [ -f "${FILENAME}" ]; then
|
||||
if [ -f "${FILENAME}" ] && [ ! -z "${FILENAME##*"update"*}" ]; then
|
||||
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
|
||||
"$PYTHON" -m esptool erase_flash
|
||||
"$PYTHON" -m esptool write_flash 0x00 ${FILENAME}
|
||||
@@ -52,8 +53,8 @@ if [ -f "${FILENAME}" ]; then
|
||||
"$PYTHON" -m esptool write_flash 0x300000 littlefs-*.bin
|
||||
|
||||
else
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
show_help
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -10,7 +10,7 @@ echo.
|
||||
echo -h Display this help and exit
|
||||
echo -p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous).
|
||||
echo -P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: %PYTHON%)
|
||||
echo -f FILENAME The .bin file to flash. Custom to your device type and region.
|
||||
echo -f FILENAME The *update.bin file to flash. Custom to your device type.
|
||||
goto EOF
|
||||
|
||||
:GETOPTS
|
||||
@@ -26,9 +26,12 @@ IF "__%FILENAME%__" == "____" (
|
||||
echo "Missing FILENAME"
|
||||
goto HELP
|
||||
)
|
||||
IF EXIST %FILENAME% (
|
||||
IF EXIST %FILENAME% IF NOT x%FILENAME:update=%==x%FILENAME% (
|
||||
echo Trying to flash update %FILENAME%
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x00 %FILENAME%
|
||||
%PYTHON% -m esptool --baud 115200 write_flash 0x10000 %FILENAME%
|
||||
) else (
|
||||
echo "Invalid file: %FILENAME%"
|
||||
goto HELP
|
||||
) else (
|
||||
echo "Invalid file: %FILENAME%"
|
||||
goto HELP
|
||||
|
||||
@@ -11,7 +11,8 @@ Flash image file to device, leave existing system intact."
|
||||
-h Display this help and exit
|
||||
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerrous).
|
||||
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
|
||||
-f FILENAME The .bin file to flash. Custom to your device type and region.
|
||||
-f FILENAME The *update.bin file to flash. Custom to your device type.
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -42,12 +43,12 @@ shift "$((OPTIND-1))"
|
||||
shift
|
||||
}
|
||||
|
||||
if [ -f "${FILENAME}" ]; then
|
||||
echo "Trying to flash update ${FILENAME}."
|
||||
$PYTHON -m esptool --baud 115200 write_flash 0x00 ${FILENAME}
|
||||
if [ -f "${FILENAME}" ] && [ -z "${FILENAME##*"update"*}" ]; then
|
||||
printf "Trying to flash update ${FILENAME}"
|
||||
$PYTHON -m esptool --baud 115200 write_flash 0x10000 ${FILENAME}
|
||||
else
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
show_help
|
||||
echo "Invalid file: ${FILENAME}"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
|
||||
@@ -9,9 +9,6 @@ VERSION=`bin/buildinfo.py long`
|
||||
# Must have a V prefix to trigger github
|
||||
git tag "v${VERSION}"
|
||||
|
||||
# Commented out per https://github.com/meshtastic/Meshtastic-device/issues/947
|
||||
#git push root "v${VERSION}" # push the tag
|
||||
|
||||
git push origin "v${VERSION}" # push the tag
|
||||
|
||||
echo "Tag ${VERSION} pushed to github, github actions should now be building the draft release. If it seems good, click to publish it"
|
||||
|
||||
@@ -1 +1 @@
|
||||
cd protobufs && ..\nanopb-0.4.6\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs *.proto
|
||||
cd protobufs && ..\nanopb-0.4.7\generator-bin\protoc.exe --nanopb_out=-v:..\src\mesh\generated -I=..\protobufs *.proto
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
set -e
|
||||
|
||||
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.6 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.6"
|
||||
echo "This script requires https://jpa.kapsi.fi/nanopb/download/ version 0.4.7 to be located in the"
|
||||
echo "firmware root directory if the following step fails, you should download the correct"
|
||||
echo "prebuilt binaries for your computer into nanopb-0.4.7"
|
||||
|
||||
# the nanopb tool seems to require that the .options file be in the current directory!
|
||||
cd protobufs
|
||||
../nanopb-0.4.6/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated -I=../protobufs *.proto
|
||||
../nanopb-0.4.7/generator-bin/protoc --nanopb_out=-v:../src/mesh/generated -I=../protobufs *.proto
|
||||
|
||||
#echo "Regenerating protobuf documentation - if you see an error message"
|
||||
#echo "you can ignore it unless doing a new protobuf release to github."
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino":{
|
||||
"arduino": {
|
||||
"ldscript": "esp32s3_out.ld"
|
||||
},
|
||||
"core": "esp32",
|
||||
@@ -8,9 +8,7 @@
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-DLILYGO_TBEAM_S3_CORE",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_DFU_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MSC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=1",
|
||||
"-DARDUINO_USB_MODE=0",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
@@ -45,4 +43,4 @@
|
||||
},
|
||||
"url": "http://www.lilygo.cn/",
|
||||
"vendor": "LilyGo"
|
||||
}
|
||||
}
|
||||
47
boards/tlora-t3s3-v1.json
Normal file
47
boards/tlora-t3s3-v1.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino": {
|
||||
"ldscript": "esp32s3_out.ld"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DLILYGO_T3S3_V1",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_USB_MODE=0",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "dio",
|
||||
"hwids": [
|
||||
[
|
||||
"0X303A",
|
||||
"0x1001"
|
||||
]
|
||||
],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "tlora-t3s3-v1"
|
||||
},
|
||||
"connectivity": [
|
||||
"wifi"
|
||||
],
|
||||
"debug": {
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino",
|
||||
"espidf"
|
||||
],
|
||||
"name": "LilyGo TLora-T3S3-V1",
|
||||
"upload": {
|
||||
"flash_size": "4MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 4194304,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 921600
|
||||
},
|
||||
"url": "http://www.lilygo.cn/",
|
||||
"vendor": "LilyGo"
|
||||
}
|
||||
13
docker-compose.yml
Normal file
13
docker-compose.yml
Normal file
@@ -0,0 +1,13 @@
|
||||
version: "3.7"
|
||||
|
||||
services:
|
||||
meshtastic-node:
|
||||
build: .
|
||||
deploy:
|
||||
mode: replicated
|
||||
replicas: 4
|
||||
networks:
|
||||
- mesh
|
||||
|
||||
networks:
|
||||
mesh:
|
||||
@@ -10,7 +10,6 @@
|
||||
;default_envs = heltec-v2.0
|
||||
;default_envs = heltec-v2.1
|
||||
;default_envs = tlora-v1
|
||||
;default_envs = tlora-v1
|
||||
;default_envs = tlora_v1_3
|
||||
;default_envs = tlora-v2
|
||||
;default_envs = tlora-v2-1-1.6
|
||||
@@ -22,6 +21,7 @@
|
||||
;default_envs = pca10059_diy_eink
|
||||
;default_envs = meshtastic-diy-v1
|
||||
;default_envs = meshtastic-diy-v1.1
|
||||
;default_envs = meshtastic-dr-dev
|
||||
;default_envs = m5stack-coreink
|
||||
;default_envs = rak4631
|
||||
|
||||
@@ -36,12 +36,24 @@ extra_scripts = bin/platformio-custom.py
|
||||
; note: TINYGPS_OPTION_NO_CUSTOM_FIELDS is VERY important. We don't use custom fields and somewhere in that pile
|
||||
; of code is a heap corruption bug!
|
||||
; FIXME: fix lib/BluetoothOTA dependency back on src/ so we can remove -Isrc
|
||||
; The Radiolib stuff will speed up building considerably. Exclud all the stuff we dont need.
|
||||
build_flags = -Wno-missing-field-initializers
|
||||
-Wno-format
|
||||
-Isrc -Isrc/mesh -Isrc/gps -Isrc/buzz -Wl,-Map,.pio/build/output.map
|
||||
-DUSE_THREAD_NAMES
|
||||
-DTINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
-DPB_ENABLE_MALLOC=1
|
||||
-DRADIOLIB_EXCLUDE_CC1101
|
||||
-DRADIOLIB_EXCLUDE_NRF24
|
||||
-DRADIOLIB_EXCLUDE_RF69
|
||||
-DRADIOLIB_EXCLUDE_SX1231
|
||||
-DRADIOLIB_EXCLUDE_SI443X
|
||||
-DRADIOLIB_EXCLUDE_RFM2X
|
||||
-DRADIOLIB_EXCLUDE_AFSK
|
||||
-DRADIOLIB_EXCLUDE_HELLSCHREIBER
|
||||
-DRADIOLIB_EXCLUDE_MORSE
|
||||
-DRADIOLIB_EXCLUDE_RTTY
|
||||
-DRADIOLIB_EXCLUDE_SSTV
|
||||
|
||||
monitor_speed = 115200
|
||||
|
||||
@@ -49,34 +61,38 @@ lib_deps =
|
||||
https://github.com/meshtastic/esp8266-oled-ssd1306.git#53580644255b48ebb7a737343c6b4e71c7e11cf2 ; ESP8266_SSD1306
|
||||
mathertel/OneButton@^2.0.3 ; OneButton library for non-blocking button debounce
|
||||
https://github.com/meshtastic/arduino-fsm.git#7db3702bf0cfe97b783d6c72595e3f38e0b19159
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#2f0d0528d737000043e949f4c3bdfb623cf0b902
|
||||
https://github.com/meshtastic/TinyGPSPlus.git#127ad674ef85f0201cb68a065879653ed94792c4
|
||||
https://github.com/meshtastic/ArduinoThread.git#72921ac222eed6f526ba1682023cee290d9aa1b3
|
||||
nanopb/Nanopb@^0.4.6
|
||||
erriez/ErriezCRC32@^1.0.1
|
||||
; jgromes/RadioLib@^5.5.1
|
||||
https://github.com/jgromes/RadioLib.git#395844922c5d88d5db0481a9c91479931172428d
|
||||
|
||||
; Used for the code analysis in PIO Home / Inspect
|
||||
check_tool = cppcheck
|
||||
check_skip_packages = yes
|
||||
check_flags =
|
||||
-DAPP_VERSION=1.0.0
|
||||
--suppressions-list=suppressions.txt
|
||||
--inline-suppr
|
||||
|
||||
; Common settings for conventional (non Portduino) Arduino targets
|
||||
[arduino_base]
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
; Portduino is using meshtastic fork for now
|
||||
jgromes/RadioLib@5.4.1
|
||||
https://github.com/caveman99/SparkFun_ATECCX08a_Arduino_Library.git#008e7f9d40bad66b2f7a0074aaac05b7c424339d
|
||||
mprograms/QMC5883LCompass@^1.1.1
|
||||
end2endzone/NonBlockingRTTTL@^1.3.0
|
||||
https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#52b5282639d08a8cbd4b748363089eed6102dc76
|
||||
|
||||
build_flags = ${env.build_flags} -Os
|
||||
-DRADIOLIB_SPI_PARANOID=0
|
||||
# -DRADIOLIB_GODMODE
|
||||
build_flags = ${env.build_flags} -Os -DRADIOLIB_SPI_PARANOID=0
|
||||
build_src_filter = ${env.build_src_filter} -<platform/portduino/>
|
||||
|
||||
; Common libs for communicating over TCP/IP networks such as MQTT
|
||||
[networking_base]
|
||||
lib_deps =
|
||||
knolleary/PubSubClient@^2.8
|
||||
meshtastic/json11@^1.0.2
|
||||
arduino-libraries/NTPClient@^3.1.0
|
||||
|
||||
; Common libs for environmental measurements in telemetry module
|
||||
; (not included in native / portduino)
|
||||
@@ -91,4 +107,5 @@ lib_deps =
|
||||
adafruit/Adafruit INA260 Library@^1.5.0
|
||||
adafruit/Adafruit INA219@^1.2.0
|
||||
adafruit/Adafruit SHTC3 Library@^1.0.0
|
||||
adafruit/Adafruit LPS2X@^2.0.4
|
||||
adafruit/Adafruit LPS2X@^2.0.4
|
||||
adafruit/Adafruit SHT31 Library@^2.2.0
|
||||
|
||||
Submodule protobufs updated: 0904d7f8ce...6048ecd2f8
@@ -51,6 +51,7 @@ class ButtonThread : public concurrency::OSThread
|
||||
pinMode(BUTTON_PIN, INPUT_PULLUP_SENSE);
|
||||
#endif
|
||||
userButton.attachClick(userButtonPressed);
|
||||
userButton.setClickTicks(300);
|
||||
userButton.attachDuringLongPress(userButtonPressedLong);
|
||||
userButton.attachDoubleClick(userButtonDoublePressed);
|
||||
userButton.attachMultiClick(userButtonMultiPressed);
|
||||
@@ -97,8 +98,8 @@ class ButtonThread : public concurrency::OSThread
|
||||
userButtonTouch.tick();
|
||||
canSleep &= userButtonTouch.isIdle();
|
||||
#endif
|
||||
// if (!canSleep) DEBUG_MSG("Supressing sleep!\n");
|
||||
// else DEBUG_MSG("sleep ok\n");
|
||||
// if (!canSleep) LOG_DEBUG("Supressing sleep!\n");
|
||||
// else LOG_DEBUG("sleep ok\n");
|
||||
|
||||
return 5;
|
||||
}
|
||||
@@ -107,12 +108,12 @@ class ButtonThread : public concurrency::OSThread
|
||||
static void touchPressed()
|
||||
{
|
||||
screen->forceDisplay();
|
||||
DEBUG_MSG("touch press!\n");
|
||||
LOG_DEBUG("touch press!\n");
|
||||
}
|
||||
|
||||
static void userButtonPressed()
|
||||
{
|
||||
// DEBUG_MSG("press!\n");
|
||||
// LOG_DEBUG("press!\n");
|
||||
#ifdef BUTTON_PIN
|
||||
if ((BUTTON_PIN != moduleConfig.canned_message.inputbroker_pin_press) ||
|
||||
!moduleConfig.canned_message.enabled) {
|
||||
@@ -122,7 +123,7 @@ class ButtonThread : public concurrency::OSThread
|
||||
}
|
||||
static void userButtonPressedLong()
|
||||
{
|
||||
// DEBUG_MSG("Long press!\n");
|
||||
// LOG_DEBUG("Long press!\n");
|
||||
#ifdef ARCH_ESP32
|
||||
screen->adjustBrightness();
|
||||
#endif
|
||||
@@ -138,7 +139,7 @@ class ButtonThread : public concurrency::OSThread
|
||||
// may wake the board immediatedly.
|
||||
if ((!shutdown_on_long_stop) && (millis() > 30 * 1000)) {
|
||||
screen->startShutdownScreen();
|
||||
DEBUG_MSG("Shutdown from long press");
|
||||
LOG_INFO("Shutdown from long press");
|
||||
playBeep();
|
||||
#ifdef PIN_LED1
|
||||
ledOff(PIN_LED1);
|
||||
@@ -153,33 +154,40 @@ class ButtonThread : public concurrency::OSThread
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
// DEBUG_MSG("Long press %u\n", (millis() - longPressTime));
|
||||
// LOG_DEBUG("Long press %u\n", (millis() - longPressTime));
|
||||
}
|
||||
}
|
||||
|
||||
static void userButtonDoublePressed()
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
disablePin();
|
||||
#elif defined(USE_EINK)
|
||||
#if defined(USE_EINK) && defined(PIN_EINK_EN)
|
||||
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(GPS_POWER_TOGGLE)
|
||||
if(config.position.gps_enabled)
|
||||
{
|
||||
LOG_DEBUG("Flag set to false for gps power\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG("Flag set to true to restore power\n");
|
||||
}
|
||||
config.position.gps_enabled = !(config.position.gps_enabled);
|
||||
doGPSpowersave(config.position.gps_enabled);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void userButtonMultiPressed()
|
||||
{
|
||||
#ifdef ARCH_ESP32
|
||||
clearNVS();
|
||||
#endif
|
||||
#ifdef ARCH_NRF52
|
||||
clearBonds();
|
||||
#endif
|
||||
screen->print("Sent ad-hoc ping\n");
|
||||
service.refreshMyNodeInfo();
|
||||
service.sendNetworkPing(NODENUM_BROADCAST, true);
|
||||
}
|
||||
|
||||
static void userButtonPressedLongStart()
|
||||
{
|
||||
if (millis() > 30 * 1000) {
|
||||
DEBUG_MSG("Long press start!\n");
|
||||
LOG_DEBUG("Long press start!\n");
|
||||
longPressTime = millis();
|
||||
}
|
||||
}
|
||||
@@ -187,7 +195,7 @@ class ButtonThread : public concurrency::OSThread
|
||||
static void userButtonPressedLongStop()
|
||||
{
|
||||
if (millis() > 30 * 1000) {
|
||||
DEBUG_MSG("Long press stop!\n");
|
||||
LOG_DEBUG("Long press stop!\n");
|
||||
longPressTime = 0;
|
||||
if (shutdown_on_long_stop) {
|
||||
playShutdownMelody();
|
||||
|
||||
@@ -13,17 +13,33 @@
|
||||
#define SERIAL_BAUD 115200 // Serial debug baud rate
|
||||
#endif
|
||||
|
||||
#define MESHTASTIC_LOG_LEVEL_DEBUG "DEBUG"
|
||||
#define MESHTASTIC_LOG_LEVEL_INFO "INFO "
|
||||
#define MESHTASTIC_LOG_LEVEL_WARN "WARN "
|
||||
#define MESHTASTIC_LOG_LEVEL_ERROR "ERROR"
|
||||
#define MESHTASTIC_LOG_LEVEL_TRACE "TRACE"
|
||||
|
||||
#include "SerialConsole.h"
|
||||
|
||||
#define DEBUG_PORT (*console) // Serial debug port
|
||||
|
||||
#ifdef USE_SEGGER
|
||||
#define DEBUG_MSG(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#define LOG_DEBUG(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#define LOG_INFO(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#define LOG_WARN(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#define LOG_ERROR(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#else
|
||||
#ifdef DEBUG_PORT
|
||||
#define DEBUG_MSG(...) DEBUG_PORT.logDebug(__VA_ARGS__)
|
||||
#define LOG_DEBUG(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||
#define LOG_INFO(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_INFO, __VA_ARGS__)
|
||||
#define LOG_WARN(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_WARN, __VA_ARGS__)
|
||||
#define LOG_ERROR(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_ERROR, __VA_ARGS__)
|
||||
#define LOG_TRACE(...) DEBUG_PORT.log(MESHTASTIC_LOG_TRACE, __VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_MSG(...)
|
||||
#define LOG_DEBUG(...)
|
||||
#define LOG_INFO(...)
|
||||
#define LOG_WARN(...)
|
||||
#define LOG_ERROR(...)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
#include "configuration.h"
|
||||
#include "FSCommon.h"
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
|
||||
|
||||
#ifdef SDCARD_USE_SPI1
|
||||
SPIClass SPI1(HSPI);
|
||||
#define SDHandler SPI1
|
||||
#endif
|
||||
|
||||
|
||||
#endif //HAS_SDCARD
|
||||
|
||||
bool copyFile(const char* from, const char* to)
|
||||
{
|
||||
@@ -9,13 +21,13 @@ bool copyFile(const char* from, const char* to)
|
||||
|
||||
File f1 = FSCom.open(from, FILE_O_READ);
|
||||
if (!f1){
|
||||
DEBUG_MSG("Failed to open source file %s\n", from);
|
||||
LOG_ERROR("Failed to open source file %s\n", from);
|
||||
return false;
|
||||
}
|
||||
|
||||
File f2 = FSCom.open(to, FILE_O_WRITE);
|
||||
if (!f2) {
|
||||
DEBUG_MSG("Failed to open destination file %s\n", to);
|
||||
LOG_ERROR("Failed to open destination file %s\n", to);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -67,7 +79,7 @@ void listDir(const char * dirname, uint8_t levels, boolean del = false)
|
||||
#ifdef ARCH_ESP32
|
||||
listDir(file.path(), levels -1, del);
|
||||
if(del) {
|
||||
DEBUG_MSG("Removing %s\n", file.path());
|
||||
LOG_DEBUG("Removing %s\n", file.path());
|
||||
strcpy(buffer, file.path());
|
||||
file.close();
|
||||
FSCom.rmdir(buffer);
|
||||
@@ -77,7 +89,7 @@ void listDir(const char * dirname, uint8_t levels, boolean del = false)
|
||||
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
||||
listDir(file.name(), levels -1, del);
|
||||
if(del) {
|
||||
DEBUG_MSG("Removing %s\n", file.name());
|
||||
LOG_DEBUG("Removing %s\n", file.name());
|
||||
strcpy(buffer, file.name());
|
||||
file.close();
|
||||
FSCom.rmdir(buffer);
|
||||
@@ -92,26 +104,26 @@ void listDir(const char * dirname, uint8_t levels, boolean del = false)
|
||||
} else {
|
||||
#ifdef ARCH_ESP32
|
||||
if(del) {
|
||||
DEBUG_MSG("Deleting %s\n", file.path());
|
||||
LOG_DEBUG("Deleting %s\n", file.path());
|
||||
strcpy(buffer, file.path());
|
||||
file.close();
|
||||
FSCom.remove(buffer);
|
||||
} else {
|
||||
DEBUG_MSG(" %s (%i Bytes)\n", file.path(), file.size());
|
||||
LOG_DEBUG(" %s (%i Bytes)\n", file.path(), file.size());
|
||||
file.close();
|
||||
}
|
||||
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
||||
if(del) {
|
||||
DEBUG_MSG("Deleting %s\n", file.name());
|
||||
LOG_DEBUG("Deleting %s\n", file.name());
|
||||
strcpy(buffer, file.name());
|
||||
file.close();
|
||||
FSCom.remove(buffer);
|
||||
} else {
|
||||
DEBUG_MSG(" %s (%i Bytes)\n", file.name(), file.size());
|
||||
LOG_DEBUG(" %s (%i Bytes)\n", file.name(), file.size());
|
||||
file.close();
|
||||
}
|
||||
#else
|
||||
DEBUG_MSG(" %s (%i Bytes)\n", file.name(), file.size());
|
||||
LOG_DEBUG(" %s (%i Bytes)\n", file.name(), file.size());
|
||||
file.close();
|
||||
#endif
|
||||
}
|
||||
@@ -119,7 +131,7 @@ void listDir(const char * dirname, uint8_t levels, boolean del = false)
|
||||
}
|
||||
#ifdef ARCH_ESP32
|
||||
if(del) {
|
||||
DEBUG_MSG("Removing %s\n", root.path());
|
||||
LOG_DEBUG("Removing %s\n", root.path());
|
||||
strcpy(buffer, root.path());
|
||||
root.close();
|
||||
FSCom.rmdir(buffer);
|
||||
@@ -128,7 +140,7 @@ void listDir(const char * dirname, uint8_t levels, boolean del = false)
|
||||
}
|
||||
#elif (defined(ARCH_RP2040) || defined(ARCH_PORTDUINO))
|
||||
if(del) {
|
||||
DEBUG_MSG("Removing %s\n", root.name());
|
||||
LOG_DEBUG("Removing %s\n", root.name());
|
||||
strcpy(buffer, root.name());
|
||||
root.close();
|
||||
FSCom.rmdir(buffer);
|
||||
@@ -158,14 +170,50 @@ void fsInit()
|
||||
#ifdef FSCom
|
||||
if (!FSBegin())
|
||||
{
|
||||
DEBUG_MSG("ERROR filesystem mount Failed. Formatting...\n");
|
||||
LOG_ERROR("Filesystem mount Failed. Formatting...\n");
|
||||
assert(0); // FIXME - report failure to phone
|
||||
}
|
||||
#ifdef ARCH_ESP32
|
||||
DEBUG_MSG("Filesystem files (%d/%d Bytes):\n", FSCom.usedBytes(), FSCom.totalBytes());
|
||||
LOG_DEBUG("Filesystem files (%d/%d Bytes):\n", FSCom.usedBytes(), FSCom.totalBytes());
|
||||
#else
|
||||
DEBUG_MSG("Filesystem files:\n");
|
||||
LOG_DEBUG("Filesystem files:\n");
|
||||
#endif
|
||||
listDir("/", 10);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void setupSDCard()
|
||||
{
|
||||
#ifdef HAS_SDCARD
|
||||
SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
|
||||
|
||||
if (!SD.begin(SDCARD_CS, SDHandler)) {
|
||||
LOG_DEBUG("No SD_MMC card detected\n");
|
||||
return ;
|
||||
}
|
||||
uint8_t cardType = SD.cardType();
|
||||
if (cardType == CARD_NONE) {
|
||||
LOG_DEBUG("No SD_MMC card attached\n");
|
||||
return ;
|
||||
}
|
||||
LOG_DEBUG("SD_MMC Card Type: ");
|
||||
if (cardType == CARD_MMC) {
|
||||
LOG_DEBUG("MMC\n");
|
||||
} else if (cardType == CARD_SD) {
|
||||
LOG_DEBUG("SDSC\n");
|
||||
} else if (cardType == CARD_SDHC) {
|
||||
LOG_DEBUG("SDHC\n");
|
||||
} else {
|
||||
LOG_DEBUG("UNKNOWN\n");
|
||||
}
|
||||
|
||||
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
|
||||
LOG_DEBUG("SD Card Size: %lluMB\n", cardSize);
|
||||
LOG_DEBUG("Total space: %llu MB\n", SD.totalBytes() / (1024 * 1024));
|
||||
LOG_DEBUG("Used space: %llu MB\n", SD.usedBytes() / (1024 * 1024));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -44,3 +44,4 @@ bool copyFile(const char* from, const char* to);
|
||||
bool renameFile(const char* pathFrom, const char* pathTo);
|
||||
void listDir(const char * dirname, uint8_t levels, boolean del);
|
||||
void rmDir(const char * dirname);
|
||||
void setupSDCard();
|
||||
@@ -20,32 +20,19 @@ class GPSStatus : public Status
|
||||
bool hasLock = false; // default to false, until we complete our first read
|
||||
bool isConnected = false; // Do we have a GPS we are talking to
|
||||
|
||||
bool isPowerSaving = false; //Are we in power saving state
|
||||
|
||||
Position p = Position_init_default;
|
||||
|
||||
public:
|
||||
GPSStatus() { statusType = STATUS_TYPE_GPS; }
|
||||
|
||||
// // proposed for deprecation
|
||||
// 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->p.latitude_i = latitude;
|
||||
// this->p.longitude_i = longitude;
|
||||
// this->p.altitude = altitude;
|
||||
// this->p.PDOP = dop;
|
||||
// this->p.ground_track = heading;
|
||||
// this->p.sats_in_view = numSatellites;
|
||||
// }
|
||||
|
||||
// preferred method
|
||||
GPSStatus(bool hasLock, bool isConnected, const Position &pos) : Status()
|
||||
GPSStatus(bool hasLock, bool isConnected, bool isPowerSaving, const Position &pos) : Status()
|
||||
{
|
||||
this->hasLock = hasLock;
|
||||
this->isConnected = isConnected;
|
||||
this->isPowerSaving = isPowerSaving;
|
||||
|
||||
// all-in-one struct copy
|
||||
this->p = pos;
|
||||
@@ -60,11 +47,13 @@ class GPSStatus : public Status
|
||||
|
||||
bool getIsConnected() const { return isConnected; }
|
||||
|
||||
bool getIsPowerSaving() const { return isPowerSaving;}
|
||||
|
||||
int32_t getLatitude() const
|
||||
{
|
||||
if (config.position.fixed_position) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("WARNING: Using fixed latitude\n");
|
||||
LOG_WARN("Using fixed latitude\n");
|
||||
#endif
|
||||
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
||||
return node->position.latitude_i;
|
||||
@@ -77,7 +66,7 @@ class GPSStatus : public Status
|
||||
{
|
||||
if (config.position.fixed_position) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("WARNING: Using fixed longitude\n");
|
||||
LOG_WARN("Using fixed longitude\n");
|
||||
#endif
|
||||
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
||||
return node->position.longitude_i;
|
||||
@@ -90,7 +79,7 @@ class GPSStatus : public Status
|
||||
{
|
||||
if (config.position.fixed_position) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("WARNING: Using fixed altitude\n");
|
||||
LOG_WARN("Using fixed altitude\n");
|
||||
#endif
|
||||
NodeInfo *node = nodeDB.getNode(nodeDB.getNodeNum());
|
||||
return node->position.altitude;
|
||||
@@ -108,9 +97,9 @@ class GPSStatus : public Status
|
||||
bool matches(const GPSStatus *newStatus) const
|
||||
{
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("GPSStatus.match() new pos@%x to old pos@%x\n", newStatus->p.pos_timestamp, p.pos_timestamp);
|
||||
LOG_DEBUG("GPSStatus.match() new pos@%x to old pos@%x\n", newStatus->p.pos_timestamp, p.pos_timestamp);
|
||||
#endif
|
||||
return (newStatus->hasLock != hasLock || newStatus->isConnected != isConnected ||
|
||||
return (newStatus->hasLock != hasLock || newStatus->isConnected != isConnected || newStatus->isPowerSaving !=isPowerSaving ||
|
||||
newStatus->p.latitude_i != p.latitude_i || newStatus->p.longitude_i != p.longitude_i ||
|
||||
newStatus->p.altitude != p.altitude || newStatus->p.altitude_hae != p.altitude_hae ||
|
||||
newStatus->p.PDOP != p.PDOP || newStatus->p.ground_track != p.ground_track ||
|
||||
@@ -125,7 +114,7 @@ class GPSStatus : public Status
|
||||
|
||||
if (isDirty && p.timestamp && (newStatus->p.timestamp == p.timestamp)) {
|
||||
// We can NEVER be in two locations at the same time! (also PR #886)
|
||||
DEBUG_MSG("BUG!! positional timestamp unchanged from prev solution\n");
|
||||
LOG_ERROR("BUG: Positional timestamp unchanged from prev solution\n");
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
@@ -137,11 +126,11 @@ class GPSStatus : public Status
|
||||
if (isDirty) {
|
||||
if (hasLock) {
|
||||
// In debug logs, identify position by @timestamp:stage (stage 3 = notify)
|
||||
DEBUG_MSG("New GPS pos@%x:3 lat=%f, lon=%f, alt=%d, pdop=%.2f, track=%.2f, speed=%.2f, sats=%d\n", p.timestamp,
|
||||
LOG_DEBUG("New GPS pos@%x:3 lat=%f, lon=%f, alt=%d, pdop=%.2f, track=%.2f, speed=%.2f, sats=%d\n", p.timestamp,
|
||||
p.latitude_i * 1e-7, p.longitude_i * 1e-7, p.altitude, p.PDOP * 1e-2, p.ground_track * 1e-5,
|
||||
p.ground_speed * 1e-2, p.sats_in_view);
|
||||
} else
|
||||
DEBUG_MSG("No GPS lock\n");
|
||||
LOG_DEBUG("No GPS lock\n");
|
||||
onNewStatus.notifyObservers(this);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace meshtastic {
|
||||
numTotal = newStatus->getNumTotal();
|
||||
}
|
||||
if(isDirty || newStatus->forceUpdate) {
|
||||
DEBUG_MSG("Node status update: %d online, %d total\n", numOnline, numTotal);
|
||||
LOG_DEBUG("Node status update: %d online, %d total\n", numOnline, numTotal);
|
||||
onNewStatus.notifyObservers(this);
|
||||
}
|
||||
return 0;
|
||||
|
||||
128
src/Power.cpp
128
src/Power.cpp
@@ -102,6 +102,10 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
#define ADC_MULTIPLIER 2.0
|
||||
#endif
|
||||
|
||||
#ifndef BATTERY_SENSE_SAMPLES
|
||||
#define BATTERY_SENSE_SAMPLES 30
|
||||
#endif
|
||||
|
||||
#ifdef BATTERY_PIN
|
||||
// Override variant or default ADC_MULTIPLIER if we have the override pref
|
||||
float operativeAdcMultiplier = config.power.adc_multiplier_override > 0
|
||||
@@ -112,16 +116,12 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
if (millis() - last_read_time_ms > min_read_interval) {
|
||||
last_read_time_ms = millis();
|
||||
|
||||
#ifdef BATTERY_SENSE_SAMPLES
|
||||
//Set the number of samples, it has an effect of increasing sensitivity, especially in complex electromagnetic environment.
|
||||
uint32_t raw = 0;
|
||||
for(uint32_t i=0; i<BATTERY_SENSE_SAMPLES;i++){
|
||||
for(uint32_t i=0; i<BATTERY_SENSE_SAMPLES; i++){
|
||||
raw += analogRead(BATTERY_PIN);
|
||||
}
|
||||
raw = raw/BATTERY_SENSE_SAMPLES;
|
||||
#else
|
||||
uint32_t raw = analogRead(BATTERY_PIN);
|
||||
#endif
|
||||
|
||||
float scaled;
|
||||
#ifndef VBAT_RAW_TO_SCALED
|
||||
@@ -129,7 +129,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
|
||||
#else
|
||||
scaled = VBAT_RAW_TO_SCALED(raw); // defined in variant.h
|
||||
#endif
|
||||
// DEBUG_MSG("battery gpio %d raw val=%u scaled=%u\n", BATTERY_PIN, raw, (uint32_t)(scaled));
|
||||
// LOG_DEBUG("battery gpio %d raw val=%u scaled=%u\n", BATTERY_PIN, raw, (uint32_t)(scaled));
|
||||
last_read_value = scaled;
|
||||
return scaled;
|
||||
} else {
|
||||
@@ -182,12 +182,15 @@ Power::Power() : OSThread("Power")
|
||||
{
|
||||
statusHandler = {};
|
||||
low_voltage_counter = 0;
|
||||
#ifdef DEBUG_HEAP
|
||||
lastheap = ESP.getFreeHeap();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Power::analogInit()
|
||||
{
|
||||
#ifdef BATTERY_PIN
|
||||
DEBUG_MSG("Using analog input %d for battery level\n", BATTERY_PIN);
|
||||
LOG_DEBUG("Using analog input %d for battery level\n", BATTERY_PIN);
|
||||
|
||||
// disable any internal pullups
|
||||
pinMode(BATTERY_PIN, INPUT);
|
||||
@@ -233,11 +236,14 @@ bool Power::setup()
|
||||
|
||||
void Power::shutdown()
|
||||
{
|
||||
|
||||
screen->setOn(false);
|
||||
#if defined(USE_EINK) && defined(PIN_EINK_EN)
|
||||
digitalWrite(PIN_EINK_EN, LOW); //power off backlight first
|
||||
#endif
|
||||
|
||||
#ifdef HAS_PMU
|
||||
DEBUG_MSG("Shutting down\n");
|
||||
if(PMU){
|
||||
LOG_INFO("Shutting down\n");
|
||||
if(PMU) {
|
||||
PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF);
|
||||
PMU->shutdown();
|
||||
}
|
||||
@@ -277,9 +283,25 @@ void Power::readPowerStatus()
|
||||
const PowerStatus powerStatus2 =
|
||||
PowerStatus(hasBattery ? OptTrue : OptFalse, batteryLevel->isVbusIn() ? OptTrue : OptFalse,
|
||||
batteryLevel->isCharging() ? OptTrue : OptFalse, batteryVoltageMv, batteryChargePercent);
|
||||
DEBUG_MSG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d\n", powerStatus2.getHasUSB(),
|
||||
LOG_DEBUG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d\n", powerStatus2.getHasUSB(),
|
||||
powerStatus2.getIsCharging(), powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent());
|
||||
newStatus.notifyObservers(&powerStatus2);
|
||||
#ifdef DEBUG_HEAP
|
||||
if (lastheap != ESP.getFreeHeap()) {
|
||||
LOG_DEBUG("Threads running:");
|
||||
int running = 0;
|
||||
for(int i = 0; i < MAX_THREADS; i++){
|
||||
auto thread = concurrency::mainController.get(i);
|
||||
if((thread != nullptr) && (thread->enabled)) {
|
||||
LOG_DEBUG(" %s", thread->ThreadName.c_str());
|
||||
running++;
|
||||
}
|
||||
}
|
||||
LOG_DEBUG("\n");
|
||||
LOG_DEBUG("Heap status: %d/%d bytes free (%d), running %d/%d threads\n", ESP.getFreeHeap(), ESP.getHeapSize(), ESP.getFreeHeap() - lastheap, running, concurrency::mainController.size(false));
|
||||
lastheap = ESP.getFreeHeap();
|
||||
}
|
||||
#endif
|
||||
|
||||
// If we have a battery at all and it is less than 10% full, force deep sleep if we have more than 3 low readings in a row
|
||||
// Supect fluctuating voltage on the RAK4631 to force it to deep sleep even if battery is at 85% after only a few days
|
||||
@@ -287,8 +309,12 @@ void Power::readPowerStatus()
|
||||
if (powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) {
|
||||
if (batteryLevel->getBattVoltage() < MIN_BAT_MILLIVOLTS) {
|
||||
low_voltage_counter++;
|
||||
if (low_voltage_counter > 3)
|
||||
powerFSM.trigger(EVENT_LOW_BATTERY);
|
||||
LOG_DEBUG("Warning RAK4631 Low voltage counter: %d/10\n", low_voltage_counter);
|
||||
if (low_voltage_counter > 10) {
|
||||
// We can't trigger deep sleep on NRF52, it's freezing the board
|
||||
//powerFSM.trigger(EVENT_LOW_BATTERY);
|
||||
LOG_DEBUG("Low voltage detected, but not triggering deep sleep\n");
|
||||
}
|
||||
} else {
|
||||
low_voltage_counter = 0;
|
||||
}
|
||||
@@ -312,17 +338,17 @@ int32_t Power::runOnce()
|
||||
#ifdef HAS_PMU
|
||||
// WE no longer use the IRQ line to wake the CPU (due to false wakes from sleep), but we do poll
|
||||
// the IRQ status by reading the registers over I2C
|
||||
if(PMU){
|
||||
if(PMU) {
|
||||
|
||||
PMU->getIrqStatus();
|
||||
|
||||
if(PMU->isVbusRemoveIrq()){
|
||||
DEBUG_MSG("USB unplugged\n");
|
||||
LOG_INFO("USB unplugged\n");
|
||||
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
|
||||
}
|
||||
|
||||
if (PMU->isVbusInsertIrq()) {
|
||||
DEBUG_MSG("USB plugged In\n");
|
||||
LOG_INFO("USB plugged In\n");
|
||||
powerFSM.trigger(EVENT_POWER_CONNECTED);
|
||||
}
|
||||
|
||||
@@ -330,21 +356,22 @@ int32_t Power::runOnce()
|
||||
Other things we could check if we cared...
|
||||
|
||||
if (PMU->isBatChagerStartIrq()) {
|
||||
DEBUG_MSG("Battery start charging\n");
|
||||
LOG_DEBUG("Battery start charging\n");
|
||||
}
|
||||
if (PMU->isBatChagerDoneIrq()) {
|
||||
DEBUG_MSG("Battery fully charged\n");
|
||||
LOG_DEBUG("Battery fully charged\n");
|
||||
}
|
||||
if (PMU->isBatInsertIrq()) {
|
||||
DEBUG_MSG("Battery inserted\n");
|
||||
LOG_DEBUG("Battery inserted\n");
|
||||
}
|
||||
if (PMU->isBatRemoveIrq()) {
|
||||
DEBUG_MSG("Battery removed\n");
|
||||
}
|
||||
if (PMU->isPekeyShortPressIrq()) {
|
||||
DEBUG_MSG("PEK short button press\n");
|
||||
LOG_DEBUG("Battery removed\n");
|
||||
}
|
||||
*/
|
||||
if (PMU->isPekeyLongPressIrq()) {
|
||||
LOG_DEBUG("PEK long button press\n");
|
||||
screen->setOn(false);
|
||||
}
|
||||
|
||||
PMU->clearIrqStatus();
|
||||
}
|
||||
@@ -384,22 +411,22 @@ bool Power::axpChipInit()
|
||||
if (!PMU) {
|
||||
PMU = new XPowersAXP2101(*w);
|
||||
if (!PMU->init()) {
|
||||
DEBUG_MSG("Warning: Failed to find AXP2101 power management\n");
|
||||
LOG_WARN("Failed to find AXP2101 power management\n");
|
||||
delete PMU;
|
||||
PMU = NULL;
|
||||
} else {
|
||||
DEBUG_MSG("AXP2101 PMU init succeeded, using AXP2101 PMU\n");
|
||||
LOG_INFO("AXP2101 PMU init succeeded, using AXP2101 PMU\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (!PMU) {
|
||||
PMU = new XPowersAXP192(*w);
|
||||
if (!PMU->init()) {
|
||||
DEBUG_MSG("Warning: Failed to find AXP192 power management\n");
|
||||
LOG_WARN("Failed to find AXP192 power management\n");
|
||||
delete PMU;
|
||||
PMU = NULL;
|
||||
} else {
|
||||
DEBUG_MSG("AXP192 PMU init succeeded, using AXP192 PMU\n");
|
||||
LOG_INFO("AXP192 PMU init succeeded, using AXP192 PMU\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,7 +478,9 @@ bool Power::axpChipInit()
|
||||
// Set constant current charging current
|
||||
PMU->setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_450MA);
|
||||
|
||||
|
||||
//Set up the charging voltage
|
||||
PMU->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
|
||||
|
||||
} else if (PMU->getChipModel() == XPOWERS_AXP2101) {
|
||||
|
||||
// t-beam s3 core
|
||||
@@ -504,6 +533,8 @@ bool Power::axpChipInit()
|
||||
//Set the constant current charging current of AXP2101, temporarily use 500mA by default
|
||||
PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA);
|
||||
|
||||
//Set up the charging voltage
|
||||
PMU->setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2);
|
||||
}
|
||||
|
||||
|
||||
@@ -517,53 +548,54 @@ bool Power::axpChipInit()
|
||||
PMU->enableVbusVoltageMeasure();
|
||||
PMU->enableBattVoltageMeasure();
|
||||
|
||||
DEBUG_MSG("=======================================================================\n");
|
||||
LOG_DEBUG("=======================================================================\n");
|
||||
if (PMU->isChannelAvailable(XPOWERS_DCDC1)) {
|
||||
DEBUG_MSG("DC1 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC1));
|
||||
LOG_DEBUG("DC1 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC1));
|
||||
}
|
||||
if (PMU->isChannelAvailable(XPOWERS_DCDC2)) {
|
||||
DEBUG_MSG("DC2 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC2));
|
||||
LOG_DEBUG("DC2 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC2));
|
||||
}
|
||||
if (PMU->isChannelAvailable(XPOWERS_DCDC3)) {
|
||||
DEBUG_MSG("DC3 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC3));
|
||||
LOG_DEBUG("DC3 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC3));
|
||||
}
|
||||
if (PMU->isChannelAvailable(XPOWERS_DCDC4)) {
|
||||
DEBUG_MSG("DC4 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC4));
|
||||
LOG_DEBUG("DC4 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_DCDC4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_DCDC4));
|
||||
}
|
||||
if (PMU->isChannelAvailable(XPOWERS_LDO2)) {
|
||||
DEBUG_MSG("LDO2 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO2));
|
||||
LOG_DEBUG("LDO2 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO2));
|
||||
}
|
||||
if (PMU->isChannelAvailable(XPOWERS_LDO3)) {
|
||||
DEBUG_MSG("LDO3 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO3));
|
||||
LOG_DEBUG("LDO3 : %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_LDO3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_LDO3));
|
||||
}
|
||||
if (PMU->isChannelAvailable(XPOWERS_ALDO1)) {
|
||||
DEBUG_MSG("ALDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO1));
|
||||
LOG_DEBUG("ALDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO1));
|
||||
}
|
||||
if (PMU->isChannelAvailable(XPOWERS_ALDO2)) {
|
||||
DEBUG_MSG("ALDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO2));
|
||||
LOG_DEBUG("ALDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO2));
|
||||
}
|
||||
if (PMU->isChannelAvailable(XPOWERS_ALDO3)) {
|
||||
DEBUG_MSG("ALDO3: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO3));
|
||||
LOG_DEBUG("ALDO3: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO3) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO3));
|
||||
}
|
||||
if (PMU->isChannelAvailable(XPOWERS_ALDO4)) {
|
||||
DEBUG_MSG("ALDO4: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO4));
|
||||
LOG_DEBUG("ALDO4: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_ALDO4) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_ALDO4));
|
||||
}
|
||||
if (PMU->isChannelAvailable(XPOWERS_BLDO1)) {
|
||||
DEBUG_MSG("BLDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO1));
|
||||
LOG_DEBUG("BLDO1: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO1) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO1));
|
||||
}
|
||||
if (PMU->isChannelAvailable(XPOWERS_BLDO2)) {
|
||||
DEBUG_MSG("BLDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO2));
|
||||
LOG_DEBUG("BLDO2: %s Voltage:%u mV \n", PMU->isPowerChannelEnable(XPOWERS_BLDO2) ? "+" : "-", PMU->getPowerChannelVoltage(XPOWERS_BLDO2));
|
||||
}
|
||||
DEBUG_MSG("=======================================================================\n");
|
||||
|
||||
|
||||
//Set up the charging voltage, AXP2101/AXP192 4.2V gear is the same
|
||||
// XPOWERS_AXP192_CHG_VOL_4V2 = XPOWERS_AXP2101_CHG_VOL_4V2
|
||||
PMU->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2);
|
||||
LOG_DEBUG("=======================================================================\n");
|
||||
|
||||
// We can safely ignore this approach for most (or all) boards because MCU turned off
|
||||
// earlier than battery discharged to 2.6V.
|
||||
//
|
||||
// Unfortanly for now we can't use this killswitch for RAK4630-based boards because they have a bug with
|
||||
// battery voltage measurement. Probably it sometimes drops to low values.
|
||||
#ifndef RAK4630
|
||||
// Set PMU shutdown voltage at 2.6V to maximize battery utilization
|
||||
PMU->setSysPowerDownVoltage(2600);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef PMU_IRQ
|
||||
|
||||
@@ -32,16 +32,16 @@ static bool isPowered()
|
||||
|
||||
static void sdsEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: SDS\n");
|
||||
LOG_INFO("Enter state: SDS\n");
|
||||
// FIXME - make sure GPS and LORA radio are off first - because we want close to zero current draw
|
||||
doDeepSleep(config.power.sds_secs * 1000);
|
||||
doDeepSleep(getConfiguredOrDefaultMs(config.power.sds_secs));
|
||||
}
|
||||
|
||||
extern Power *power;
|
||||
|
||||
static void shutdownEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: SHUTDOWN\n");
|
||||
LOG_INFO("Enter state: SHUTDOWN\n");
|
||||
power->shutdown();
|
||||
}
|
||||
|
||||
@@ -51,16 +51,16 @@ static uint32_t secsSlept;
|
||||
|
||||
static void lsEnter()
|
||||
{
|
||||
DEBUG_MSG("lsEnter begin, ls_secs=%u\n", config.power.ls_secs);
|
||||
LOG_INFO("lsEnter begin, ls_secs=%u\n", config.power.ls_secs);
|
||||
screen->setOn(false);
|
||||
secsSlept = 0; // How long have we been sleeping this time
|
||||
|
||||
// DEBUG_MSG("lsEnter end\n");
|
||||
// LOG_INFO("lsEnter end\n");
|
||||
}
|
||||
|
||||
static void lsIdle()
|
||||
{
|
||||
// DEBUG_MSG("lsIdle begin ls_secs=%u\n", getPref_ls_secs());
|
||||
// LOG_INFO("lsIdle begin ls_secs=%u\n", getPref_ls_secs());
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
|
||||
@@ -82,7 +82,7 @@ static void lsIdle()
|
||||
wakeCause2 = doLightSleep(1); // leave led on for 1ms
|
||||
|
||||
secsSlept += sleepTime;
|
||||
// DEBUG_MSG("sleeping, flash led!\n");
|
||||
// LOG_INFO("sleeping, flash led!\n");
|
||||
break;
|
||||
|
||||
case ESP_SLEEP_WAKEUP_UART:
|
||||
@@ -93,7 +93,7 @@ static void lsIdle()
|
||||
default:
|
||||
// We woke for some other reason (button press, device interrupt)
|
||||
// uint64_t status = esp_sleep_get_ext1_wakeup_status();
|
||||
DEBUG_MSG("wakeCause2 %d\n", wakeCause2);
|
||||
LOG_INFO("wakeCause2 %d\n", wakeCause2);
|
||||
|
||||
#ifdef BUTTON_PIN
|
||||
bool pressed = !digitalRead(BUTTON_PIN);
|
||||
@@ -117,7 +117,7 @@ static void lsIdle()
|
||||
} else {
|
||||
// Time to stop sleeping!
|
||||
setLed(false);
|
||||
DEBUG_MSG("reached ls_secs, servicing loop()\n");
|
||||
LOG_INFO("Reached ls_secs, servicing loop()\n");
|
||||
powerFSM.trigger(EVENT_WAKE_TIMER);
|
||||
}
|
||||
#endif
|
||||
@@ -125,7 +125,7 @@ static void lsIdle()
|
||||
|
||||
static void lsExit()
|
||||
{
|
||||
DEBUG_MSG("Exit state: LS\n");
|
||||
LOG_INFO("Exit state: LS\n");
|
||||
// setGPSPower(true); // restore GPS power
|
||||
if (gps)
|
||||
gps->forceWake(true);
|
||||
@@ -133,7 +133,7 @@ static void lsExit()
|
||||
|
||||
static void nbEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: NB\n");
|
||||
LOG_INFO("Enter state: NB\n");
|
||||
screen->setOn(false);
|
||||
setBluetoothEnable(false);
|
||||
|
||||
@@ -148,7 +148,7 @@ static void darkEnter()
|
||||
|
||||
static void serialEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: SERIAL\n");
|
||||
LOG_INFO("Enter state: SERIAL\n");
|
||||
setBluetoothEnable(false);
|
||||
screen->setOn(true);
|
||||
screen->print("Serial connected\n");
|
||||
@@ -161,10 +161,10 @@ static void serialExit()
|
||||
|
||||
static void powerEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: POWER\n");
|
||||
LOG_INFO("Enter state: POWER\n");
|
||||
if (!isPowered()) {
|
||||
// If we got here, we are in the wrong state - we should be in powered, let that state ahndle things
|
||||
DEBUG_MSG("Loss of power in Powered\n");
|
||||
LOG_INFO("Loss of power in Powered\n");
|
||||
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
|
||||
} else {
|
||||
screen->setOn(true);
|
||||
@@ -177,7 +177,7 @@ static void powerIdle()
|
||||
{
|
||||
if (!isPowered()) {
|
||||
// If we got here, we are in the wrong state
|
||||
DEBUG_MSG("Loss of power in Powered\n");
|
||||
LOG_INFO("Loss of power in Powered\n");
|
||||
powerFSM.trigger(EVENT_POWER_DISCONNECTED);
|
||||
}
|
||||
}
|
||||
@@ -191,7 +191,7 @@ static void powerExit()
|
||||
|
||||
static void onEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: ON\n");
|
||||
LOG_INFO("Enter state: ON\n");
|
||||
screen->setOn(true);
|
||||
setBluetoothEnable(true);
|
||||
|
||||
@@ -221,7 +221,7 @@ static void screenPress()
|
||||
|
||||
static void bootEnter()
|
||||
{
|
||||
DEBUG_MSG("Enter state: BOOT\n");
|
||||
LOG_INFO("Enter state: BOOT\n");
|
||||
}
|
||||
|
||||
State stateSHUTDOWN(shutdownEnter, NULL, NULL, "SHUTDOWN");
|
||||
@@ -240,7 +240,7 @@ void PowerFSM_setup()
|
||||
bool isRouter = (config.device.role == Config_DeviceConfig_Role_ROUTER ? 1 : 0);
|
||||
bool hasPower = isPowered();
|
||||
|
||||
DEBUG_MSG("PowerFSM init, USB power=%d\n", hasPower ? 1 : 0);
|
||||
LOG_INFO("PowerFSM init, USB power=%d\n", hasPower ? 1 : 0);
|
||||
powerFSM.add_timed_transition(&stateBOOT, hasPower ? &statePOWER : &stateON, 3 * 1000, NULL, "boot timeout");
|
||||
|
||||
// wake timer expired or a packet arrived
|
||||
@@ -324,31 +324,22 @@ void PowerFSM_setup()
|
||||
|
||||
powerFSM.add_transition(&stateDARK, &stateDARK, EVENT_CONTACT_FROM_PHONE, NULL, "Contact from phone");
|
||||
|
||||
// each time we get a new update packet make sure we are staying in the ON state so the screen stays awake (also we don't
|
||||
// shutdown bluetooth if is_router)
|
||||
powerFSM.add_transition(&stateDARK, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
||||
powerFSM.add_transition(&stateON, &stateON, EVENT_FIRMWARE_UPDATE, NULL, "Got firmware update");
|
||||
|
||||
powerFSM.add_timed_transition(&stateON, &stateDARK, getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL, "Screen-on timeout");
|
||||
|
||||
// On most boards we use light-sleep to be our main state, but on NRF52 we just stay in DARK
|
||||
State *lowPowerState = &stateLS;
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
State *lowPowerState = &stateLS;
|
||||
// We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally)
|
||||
|
||||
// See: https://github.com/meshtastic/Meshtastic-device/issues/1071
|
||||
// See: https://github.com/meshtastic/firmware/issues/1071
|
||||
if (isRouter || config.power.is_power_saving) {
|
||||
powerFSM.add_timed_transition(&stateNB, &stateLS, getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL, "Min wake timeout");
|
||||
powerFSM.add_timed_transition(&stateDARK, &stateLS, getConfiguredOrDefaultMs(config.power.wait_bluetooth_secs, default_wait_bluetooth_secs), NULL, "Bluetooth timeout");
|
||||
}
|
||||
|
||||
#elif defined (ARCH_NRF52)
|
||||
lowPowerState = &stateDARK;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (config.power.sds_secs != UINT32_MAX)
|
||||
powerFSM.add_timed_transition(lowPowerState, &stateSDS, config.power.sds_secs * 1000, NULL, "mesh timeout");
|
||||
powerFSM.add_timed_transition(lowPowerState, &stateSDS, getConfiguredOrDefaultMs(config.power.sds_secs), NULL, "mesh timeout");
|
||||
#endif
|
||||
|
||||
|
||||
powerFSM.run_machine(); // run one interation of the state machine, so we run our on enter tasks for the initial DARK state
|
||||
}
|
||||
|
||||
@@ -26,11 +26,9 @@ class PowerFSMThread : public OSThread
|
||||
|
||||
if (powerStatus->getHasUSB()) {
|
||||
timeLastPowered = millis();
|
||||
} else if (config.power.on_battery_shutdown_after_secs > 0 &&
|
||||
millis() >
|
||||
timeLastPowered +
|
||||
(1000 *
|
||||
config.power.on_battery_shutdown_after_secs)) { // shutdown after 30 minutes unpowered
|
||||
} else if (config.power.on_battery_shutdown_after_secs > 0 &&
|
||||
config.power.on_battery_shutdown_after_secs != UINT32_MAX &&
|
||||
millis() > (timeLastPowered + getConfiguredOrDefaultMs(config.power.on_battery_shutdown_after_secs))) { // shutdown after 30 minutes unpowered
|
||||
powerFSM.trigger(EVENT_SHUTDOWN);
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ class PowerStatus : public Status
|
||||
isCharging = newStatus->isCharging;
|
||||
}
|
||||
if (isDirty) {
|
||||
// DEBUG_MSG("Battery %dmV %d%%\n", batteryVoltageMv, batteryChargePercent);
|
||||
// LOG_DEBUG("Battery %dmV %d%%\n", batteryVoltageMv, batteryChargePercent);
|
||||
onNewStatus.notifyObservers(this);
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -44,16 +44,21 @@ size_t RedirectablePrint::vprintf(const char *format, va_list arg)
|
||||
static char printBuf[160];
|
||||
|
||||
va_copy(copy, arg);
|
||||
int len = vsnprintf(printBuf, sizeof(printBuf), format, copy);
|
||||
size_t len = vsnprintf(printBuf, sizeof(printBuf), format, copy);
|
||||
va_end(copy);
|
||||
|
||||
if (len < 0) return 0;
|
||||
// If the resulting string is longer than sizeof(printBuf)-1 characters, the remaining characters are still counted for the return value
|
||||
|
||||
if (len > sizeof(printBuf) - 1) {
|
||||
len = sizeof(printBuf) - 1;
|
||||
printBuf[sizeof(printBuf) - 2] = '\n';
|
||||
}
|
||||
|
||||
len = Print::write(printBuf, len);
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t RedirectablePrint::logDebug(const char *format, ...)
|
||||
size_t RedirectablePrint::log(const char *logLevel, const char *format, ...)
|
||||
{
|
||||
size_t r = 0;
|
||||
|
||||
@@ -81,9 +86,9 @@ size_t RedirectablePrint::logDebug(const char *format, ...)
|
||||
int min = (hms % SEC_PER_HOUR) / SEC_PER_MIN;
|
||||
int sec = (hms % SEC_PER_HOUR) % SEC_PER_MIN; // or hms % SEC_PER_MIN
|
||||
|
||||
r += printf("%02d:%02d:%02d %u ", hour, min, sec, millis() / 1000);
|
||||
r += printf("%s | %02d:%02d:%02d %u ", logLevel, hour, min, sec, millis() / 1000);
|
||||
} else
|
||||
r += printf("??:??:?? %u ", millis() / 1000);
|
||||
r += printf("%s | ??:??:?? %u ", logLevel, millis() / 1000);
|
||||
|
||||
auto thread = concurrency::OSThread::currentThread;
|
||||
if (thread) {
|
||||
@@ -94,7 +99,6 @@ size_t RedirectablePrint::logDebug(const char *format, ...)
|
||||
print("] ");
|
||||
}
|
||||
}
|
||||
|
||||
r += vprintf(format, arg);
|
||||
va_end(arg);
|
||||
|
||||
@@ -103,4 +107,4 @@ size_t RedirectablePrint::logDebug(const char *format, ...)
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,11 +33,8 @@ class RedirectablePrint : public Print
|
||||
* If the provide format string ends with a newline we assume it is the final print of a single
|
||||
* log message. Otherwise we assume more prints will come before the log message ends. This
|
||||
* allows you to call logDebug a few times to build up a single log message line if you wish.
|
||||
*
|
||||
* FIXME, eventually add log levels (INFO, WARN, ERROR) and subsystems. Move into
|
||||
* a different class.
|
||||
*/
|
||||
size_t logDebug(const char * format, ...) __attribute__ ((format (printf, 2, 3)));
|
||||
size_t log(const char *logLevel, const char *format, ...) __attribute__ ((format (printf, 3, 4)));
|
||||
|
||||
/** like printf but va_list based */
|
||||
size_t vprintf(const char *format, va_list arg);
|
||||
|
||||
@@ -25,7 +25,7 @@ void consolePrintf(const char *format, ...)
|
||||
#endif
|
||||
}
|
||||
|
||||
SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
|
||||
SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port), concurrency::OSThread("SerialConsole")
|
||||
{
|
||||
assert(!console);
|
||||
console = this;
|
||||
@@ -33,7 +33,7 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
|
||||
// setDestination(&noopPrint); for testing, try turning off 'all' debug output and see what leaks
|
||||
|
||||
Port.begin(SERIAL_BAUD);
|
||||
#ifdef ARCH_NRF52
|
||||
#if defined(ARCH_NRF52) || defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
time_t timeout = millis();
|
||||
while (!Port) {
|
||||
if ((millis() - timeout) < 5000) {
|
||||
@@ -46,6 +46,10 @@ SerialConsole::SerialConsole() : StreamAPI(&Port), RedirectablePrint(&Port)
|
||||
emitRebooted();
|
||||
}
|
||||
|
||||
int32_t SerialConsole::runOnce()
|
||||
{
|
||||
return runOncePart();
|
||||
}
|
||||
|
||||
// For the serial port we can't really detect if any client is on the other side, so instead just look for recent messages
|
||||
bool SerialConsole::checkIsConnected()
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs
|
||||
* (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs).
|
||||
*/
|
||||
class SerialConsole : public StreamAPI, public RedirectablePrint
|
||||
class SerialConsole : public StreamAPI, public RedirectablePrint, private concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
SerialConsole();
|
||||
@@ -24,6 +24,8 @@ class SerialConsole : public StreamAPI, public RedirectablePrint
|
||||
return RedirectablePrint::write(c);
|
||||
}
|
||||
|
||||
virtual int32_t runOnce() override;
|
||||
|
||||
protected:
|
||||
|
||||
/// Check the current underlying physical link to see if the client is currently connected
|
||||
|
||||
@@ -10,18 +10,18 @@ void AirTime::logAirtime(reportTypes reportType, uint32_t airtime_ms)
|
||||
{
|
||||
|
||||
if (reportType == TX_LOG) {
|
||||
DEBUG_MSG("AirTime - Packet transmitted : %ums\n", airtime_ms);
|
||||
LOG_DEBUG("AirTime - Packet transmitted : %ums\n", airtime_ms);
|
||||
this->airtimes.periodTX[0] = this->airtimes.periodTX[0] + airtime_ms;
|
||||
myNodeInfo.air_period_tx[0] = myNodeInfo.air_period_tx[0] + airtime_ms;
|
||||
|
||||
this->utilizationTX[this->getPeriodUtilHour()] = this->utilizationTX[this->getPeriodUtilHour()] + airtime_ms;
|
||||
|
||||
} else if (reportType == RX_LOG) {
|
||||
DEBUG_MSG("AirTime - Packet received : %ums\n", airtime_ms);
|
||||
LOG_DEBUG("AirTime - Packet received : %ums\n", airtime_ms);
|
||||
this->airtimes.periodRX[0] = this->airtimes.periodRX[0] + airtime_ms;
|
||||
myNodeInfo.air_period_rx[0] = myNodeInfo.air_period_rx[0] + airtime_ms;
|
||||
} else if (reportType == RX_ALL_LOG) {
|
||||
DEBUG_MSG("AirTime - Packet received (noise?) : %ums\n", airtime_ms);
|
||||
LOG_DEBUG("AirTime - Packet received (noise?) : %ums\n", airtime_ms);
|
||||
this->airtimes.periodRX_ALL[0] = this->airtimes.periodRX_ALL[0] + airtime_ms;
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ void AirTime::airtimeRotatePeriod()
|
||||
{
|
||||
|
||||
if (this->airtimes.lastPeriodIndex != this->currentPeriodIndex()) {
|
||||
DEBUG_MSG("Rotating airtimes to a new period = %u\n", this->currentPeriodIndex());
|
||||
LOG_DEBUG("Rotating airtimes to a new period = %u\n", this->currentPeriodIndex());
|
||||
|
||||
for (int i = PERIODS_TO_LOG - 2; i >= 0; --i) {
|
||||
this->airtimes.periodTX[i + 1] = this->airtimes.periodTX[i];
|
||||
@@ -101,7 +101,7 @@ float AirTime::channelUtilizationPercent()
|
||||
uint32_t sum = 0;
|
||||
for (uint32_t i = 0; i < CHANNEL_UTILIZATION_PERIODS; i++) {
|
||||
sum += this->channelUtilization[i];
|
||||
// DEBUG_MSG("ChanUtilArray %u %u\n", i, this->channelUtilization[i]);
|
||||
// LOG_DEBUG("ChanUtilArray %u %u\n", i, this->channelUtilization[i]);
|
||||
}
|
||||
|
||||
return (float(sum) / float(CHANNEL_UTILIZATION_PERIODS * 10 * 1000)) * 100;
|
||||
@@ -117,6 +117,20 @@ float AirTime::utilizationTXPercent()
|
||||
return (float(sum) / float(MS_IN_HOUR)) * 100;
|
||||
}
|
||||
|
||||
// Get the amount of minutes we have to be silent before we can send again
|
||||
uint8_t AirTime::getSilentMinutes(float txPercent, float dutyCycle)
|
||||
{
|
||||
float newTxPercent = txPercent;
|
||||
for (int8_t i = MINUTES_IN_HOUR-1; i >= 0; --i) {
|
||||
newTxPercent -= ((float)this->utilizationTX[i] / (MS_IN_MINUTE * MINUTES_IN_HOUR / 100));
|
||||
if (newTxPercent < dutyCycle)
|
||||
return MINUTES_IN_HOUR-1-i;
|
||||
}
|
||||
|
||||
return MINUTES_IN_HOUR;
|
||||
}
|
||||
|
||||
|
||||
AirTime::AirTime() : concurrency::OSThread("AirTime"),airtimes({}) {
|
||||
}
|
||||
|
||||
@@ -175,13 +189,13 @@ int32_t AirTime::runOnce()
|
||||
myNodeInfo.air_util_tx = airTime->utilizationTXPercent();
|
||||
}
|
||||
/*
|
||||
DEBUG_MSG("utilPeriodTX %d TX Airtime %3.2f%\n", utilPeriodTX, airTime->utilizationTXPercent());
|
||||
LOG_DEBUG("utilPeriodTX %d TX Airtime %3.2f%\n", utilPeriodTX, airTime->utilizationTXPercent());
|
||||
for (uint32_t i = 0; i < MINUTES_IN_HOUR; i++) {
|
||||
DEBUG_MSG(
|
||||
LOG_DEBUG(
|
||||
"%d,", this->utilizationTX[i]
|
||||
);
|
||||
}
|
||||
DEBUG_MSG("\n");
|
||||
LOG_DEBUG("\n");
|
||||
*/
|
||||
return (1000 * 1);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#define PERIODS_TO_LOG 8
|
||||
#define MINUTES_IN_HOUR 60
|
||||
#define SECONDS_IN_MINUTE 60
|
||||
#define MS_IN_MINUTE (SECONDS_IN_MINUTE * 1000)
|
||||
#define MS_IN_HOUR (MINUTES_IN_HOUR * SECONDS_IN_MINUTE * 1000)
|
||||
|
||||
|
||||
@@ -57,6 +58,7 @@ class AirTime : private concurrency::OSThread
|
||||
uint32_t getSecondsPerPeriod();
|
||||
uint32_t getSecondsSinceBoot();
|
||||
uint32_t *airtimeReport(reportTypes reportType);
|
||||
uint8_t getSilentMinutes(float txPercent, float dutyCycle);
|
||||
|
||||
private:
|
||||
bool firstTime = true;
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
#include "buzz.h"
|
||||
#include "configuration.h"
|
||||
#include "NodeDB.h"
|
||||
|
||||
#ifndef PIN_BUZZER
|
||||
|
||||
// Noop methods for boards w/o buzzer
|
||||
void playBeep(){};
|
||||
void playStartMelody(){};
|
||||
void playShutdownMelody(){};
|
||||
|
||||
#else
|
||||
#ifdef M5STACK
|
||||
#include "Speaker.h"
|
||||
TONE Tone;
|
||||
#else
|
||||
#if !defined(ARCH_ESP32) && !defined(ARCH_RP2040) && !defined(ARCH_PORTDUINO)
|
||||
#include "Tone.h"
|
||||
#endif
|
||||
|
||||
#if !defined(ARCH_PORTDUINO)
|
||||
extern "C" void delay(uint32_t dwMs);
|
||||
#endif
|
||||
|
||||
struct ToneDuration {
|
||||
int frequency_khz;
|
||||
@@ -42,28 +34,25 @@ const int DURATION_1_8 = 125; // 1/8 note
|
||||
const int DURATION_1_4 = 250; // 1/4 note
|
||||
|
||||
void playTones(const ToneDuration *tone_durations, int size) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
const auto &tone_duration = tone_durations[i];
|
||||
#ifdef M5STACK
|
||||
Tone.tone(tone_duration.frequency_khz);
|
||||
delay(tone_duration.duration_ms);
|
||||
Tone.mute();
|
||||
#else
|
||||
tone(PIN_BUZZER, tone_duration.frequency_khz, tone_duration.duration_ms);
|
||||
#ifdef PIN_BUZZER
|
||||
if (!config.device.buzzer_gpio)
|
||||
config.device.buzzer_gpio = PIN_BUZZER;
|
||||
#endif
|
||||
// to distinguish the notes, set a minimum time between them.
|
||||
delay(1.3 * tone_duration.duration_ms);
|
||||
if (config.device.buzzer_gpio) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
const auto &tone_duration = tone_durations[i];
|
||||
tone(config.device.buzzer_gpio, tone_duration.frequency_khz, tone_duration.duration_ms);
|
||||
// to distinguish the notes, set a minimum time between them.
|
||||
delay(1.3 * tone_duration.duration_ms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef M5STACK
|
||||
|
||||
void playBeep() {
|
||||
ToneDuration melody[] = {{NOTE_B3, DURATION_1_4}};
|
||||
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||
}
|
||||
#else
|
||||
void playBeep() { tone(PIN_BUZZER, NOTE_B3, DURATION_1_4); }
|
||||
#endif
|
||||
|
||||
void playStartMelody() {
|
||||
ToneDuration melody[] = {{NOTE_FS3, DURATION_1_8},
|
||||
@@ -72,11 +61,9 @@ void playStartMelody() {
|
||||
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||
}
|
||||
|
||||
|
||||
void playShutdownMelody() {
|
||||
ToneDuration melody[] = {{NOTE_CS4, DURATION_1_8},
|
||||
{NOTE_AS3, DURATION_1_8},
|
||||
{NOTE_FS3, DURATION_1_4}};
|
||||
playTones(melody, sizeof(melody) / sizeof(ToneDuration));
|
||||
}
|
||||
#endif
|
||||
@@ -13,12 +13,12 @@ InterruptableDelay::~InterruptableDelay() {}
|
||||
*/
|
||||
bool InterruptableDelay::delay(uint32_t msec)
|
||||
{
|
||||
// DEBUG_MSG("delay %u ", msec);
|
||||
// LOG_DEBUG("delay %u ", msec);
|
||||
|
||||
// sem take will return false if we timed out (i.e. were not interrupted)
|
||||
bool r = semaphore.take(msec);
|
||||
|
||||
// DEBUG_MSG("interrupt=%d\n", r);
|
||||
// LOG_DEBUG("interrupt=%d\n", r);
|
||||
return !r;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,11 +33,11 @@ IRAM_ATTR bool NotifiedWorkerThread::notifyCommon(uint32_t v, bool overwrite)
|
||||
|
||||
notification = v;
|
||||
if (debugNotification)
|
||||
DEBUG_MSG("setting notification %d\n", v);
|
||||
LOG_DEBUG("setting notification %d\n", v);
|
||||
return true;
|
||||
} else {
|
||||
if (debugNotification)
|
||||
DEBUG_MSG("dropping notification %d\n", v);
|
||||
LOG_DEBUG("dropping notification %d\n", v);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,7 @@ bool NotifiedWorkerThread::notifyLater(uint32_t delay, uint32_t v, bool overwrit
|
||||
if (didIt) { // If we didn't already have something queued, override the delay to be larger
|
||||
setIntervalFromNow(delay); // a new version of setInterval relative to the current time
|
||||
if (debugNotification)
|
||||
DEBUG_MSG("delaying notification %u\n", delay);
|
||||
LOG_DEBUG("delaying notification %u\n", delay);
|
||||
}
|
||||
|
||||
return didIt;
|
||||
|
||||
@@ -61,21 +61,31 @@ bool OSThread::shouldRun(unsigned long time)
|
||||
bool r = Thread::shouldRun(time);
|
||||
|
||||
if (showRun && r)
|
||||
DEBUG_MSG("Thread %s: run\n", ThreadName.c_str());
|
||||
LOG_DEBUG("Thread %s: run\n", ThreadName.c_str());
|
||||
|
||||
if (showWaiting && enabled && !r)
|
||||
DEBUG_MSG("Thread %s: wait %lu\n", ThreadName.c_str(), interval);
|
||||
LOG_DEBUG("Thread %s: wait %lu\n", ThreadName.c_str(), interval);
|
||||
|
||||
if (showDisabled && !enabled)
|
||||
DEBUG_MSG("Thread %s: disabled\n", ThreadName.c_str());
|
||||
LOG_DEBUG("Thread %s: disabled\n", ThreadName.c_str());
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
void OSThread::run()
|
||||
{
|
||||
#ifdef DEBUG_HEAP
|
||||
auto heap = ESP.getFreeHeap();
|
||||
#endif
|
||||
currentThread = this;
|
||||
auto newDelay = runOnce();
|
||||
#ifdef DEBUG_HEAP
|
||||
auto newHeap = ESP.getFreeHeap();
|
||||
if (newHeap < heap)
|
||||
LOG_DEBUG("------ Thread %s leaked heap %d -> %d (%d) ------\n", ThreadName.c_str(), heap, newHeap, newHeap - heap);
|
||||
if (heap < newHeap)
|
||||
LOG_DEBUG("++++++ Thread %s freed heap %d -> %d (%d) ++++++\n", ThreadName.c_str(), heap, newHeap, newHeap - heap);
|
||||
#endif
|
||||
|
||||
runned();
|
||||
|
||||
@@ -85,6 +95,14 @@ void OSThread::run()
|
||||
currentThread = NULL;
|
||||
}
|
||||
|
||||
int32_t OSThread::disable()
|
||||
{
|
||||
enabled = false;
|
||||
setInterval(INT32_MAX);
|
||||
|
||||
return INT32_MAX;
|
||||
}
|
||||
|
||||
/**
|
||||
* This flag is set **only** when setup() starts, to provide a way for us to check for sloppy static constructor calls.
|
||||
* Call assertIsSetup() to force a crash if someone tries to create an instance too early.
|
||||
|
||||
@@ -53,6 +53,8 @@ class OSThread : public Thread
|
||||
|
||||
static void setup();
|
||||
|
||||
int32_t disable();
|
||||
|
||||
/**
|
||||
* Wait a specified number msecs starting from the current time (rather than the last time we were run)
|
||||
*/
|
||||
|
||||
@@ -110,9 +110,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#define INA_ADDR_ALTERNATE 0x41
|
||||
#define QMC6310_ADDR 0x1C
|
||||
#define QMI8658_ADDR 0x6B
|
||||
#define QMC5883L_ADDR 0x1E
|
||||
#define SHTC3_ADDR 0x70
|
||||
#define LPS22HB_ADDR 0x5C
|
||||
#define LPS22HB_ADDR_ALT 0x5D
|
||||
#define SHT31_ADDR 0x44
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Security
|
||||
@@ -142,6 +144,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifndef HAS_WIFI
|
||||
#define HAS_WIFI 0
|
||||
#endif
|
||||
#ifndef HAS_ETHERNET
|
||||
#define HAS_ETHERNET 0
|
||||
#endif
|
||||
#ifndef HAS_SCREEN
|
||||
#define HAS_SCREEN 0
|
||||
#endif
|
||||
@@ -163,6 +168,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifndef HAS_RTC
|
||||
#define HAS_RTC 0
|
||||
#endif
|
||||
#ifndef HAS_CPU_SHUTDOWN
|
||||
#define HAS_CPU_SHUTDOWN 0
|
||||
#endif
|
||||
#ifndef HAS_BLUETOOTH
|
||||
#define HAS_BLUETOOTH 0
|
||||
#endif
|
||||
|
||||
#include "RF95Configuration.h"
|
||||
#include "DebugConfiguration.h"
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
uint32_t axpDebugRead()
|
||||
{
|
||||
axp.debugCharging();
|
||||
DEBUG_MSG("vbus current %f\n", axp.getVbusCurrent());
|
||||
DEBUG_MSG("charge current %f\n", axp.getBattChargeCurrent());
|
||||
DEBUG_MSG("bat voltage %f\n", axp.getBattVoltage());
|
||||
DEBUG_MSG("batt pct %d\n", axp.getBattPercentage());
|
||||
DEBUG_MSG("is battery connected %d\n", axp.isBatteryConnect());
|
||||
DEBUG_MSG("is USB connected %d\n", axp.isVBUSPlug());
|
||||
DEBUG_MSG("is charging %d\n", axp.isChargeing());
|
||||
LOG_DEBUG("vbus current %f\n", axp.getVbusCurrent());
|
||||
LOG_DEBUG("charge current %f\n", axp.getBattChargeCurrent());
|
||||
LOG_DEBUG("bat voltage %f\n", axp.getBattVoltage());
|
||||
LOG_DEBUG("batt pct %d\n", axp.getBattPercentage());
|
||||
LOG_DEBUG("is battery connected %d\n", axp.isBatteryConnect());
|
||||
LOG_DEBUG("is USB connected %d\n", axp.isVBUSPlug());
|
||||
LOG_DEBUG("is charging %d\n", axp.isChargeing());
|
||||
|
||||
return 30 * 1000;
|
||||
}
|
||||
|
||||
@@ -52,9 +52,9 @@ void scanEInkDevice(void)
|
||||
d_writeCommand(0x20);
|
||||
eink_found = (d_waitWhileBusy(150) > 0) ? true : false;
|
||||
if(eink_found)
|
||||
DEBUG_MSG("EInk display found\n");
|
||||
LOG_DEBUG("EInk display found\n");
|
||||
else
|
||||
DEBUG_MSG("EInk display not found\n");
|
||||
LOG_DEBUG("EInk display not found\n");
|
||||
SPI1.end();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -12,33 +12,33 @@
|
||||
|
||||
void printATECCInfo()
|
||||
{
|
||||
#ifndef ARCH_PORTDUINO
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
atecc.readConfigZone(false);
|
||||
|
||||
DEBUG_MSG("ATECC608B Serial Number: ");
|
||||
LOG_DEBUG("ATECC608B Serial Number: ");
|
||||
for (int i = 0 ; i < 9 ; i++) {
|
||||
DEBUG_MSG("%02x",atecc.serialNumber[i]);
|
||||
LOG_DEBUG("%02x",atecc.serialNumber[i]);
|
||||
}
|
||||
|
||||
DEBUG_MSG(", Rev Number: ");
|
||||
LOG_DEBUG(", Rev Number: ");
|
||||
for (int i = 0 ; i < 4 ; i++) {
|
||||
DEBUG_MSG("%02x",atecc.revisionNumber[i]);
|
||||
LOG_DEBUG("%02x",atecc.revisionNumber[i]);
|
||||
}
|
||||
DEBUG_MSG("\n");
|
||||
LOG_DEBUG("\n");
|
||||
|
||||
DEBUG_MSG("ATECC608B Config %s",atecc.configLockStatus ? "Locked" : "Unlocked");
|
||||
DEBUG_MSG(", Data %s",atecc.dataOTPLockStatus ? "Locked" : "Unlocked");
|
||||
DEBUG_MSG(", Slot 0 %s\n",atecc.slot0LockStatus ? "Locked" : "Unlocked");
|
||||
LOG_DEBUG("ATECC608B Config %s",atecc.configLockStatus ? "Locked" : "Unlocked");
|
||||
LOG_DEBUG(", Data %s",atecc.dataOTPLockStatus ? "Locked" : "Unlocked");
|
||||
LOG_DEBUG(", Slot 0 %s\n",atecc.slot0LockStatus ? "Locked" : "Unlocked");
|
||||
|
||||
if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) {
|
||||
if (atecc.generatePublicKey() == false) {
|
||||
DEBUG_MSG("ATECC608B Error generating public key\n");
|
||||
LOG_DEBUG("ATECC608B Error generating public key\n");
|
||||
} else {
|
||||
DEBUG_MSG("ATECC608B Public Key: ");
|
||||
LOG_DEBUG("ATECC608B Public Key: ");
|
||||
for (int i = 0 ; i < 64 ; i++) {
|
||||
DEBUG_MSG("%02x",atecc.publicKey64Bytes[i]);
|
||||
LOG_DEBUG("%02x",atecc.publicKey64Bytes[i]);
|
||||
}
|
||||
DEBUG_MSG("\n");
|
||||
LOG_DEBUG("\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -51,7 +51,7 @@ uint16_t getRegisterValue(uint8_t address, uint8_t reg, uint8_t length) {
|
||||
Wire.endTransmission();
|
||||
delay(20);
|
||||
Wire.requestFrom(address, length);
|
||||
DEBUG_MSG("Wire.available() = %d\n", Wire.available());
|
||||
LOG_DEBUG("Wire.available() = %d\n", Wire.available());
|
||||
if (Wire.available() == 2) {
|
||||
// Read MSB, then LSB
|
||||
value = (uint16_t)Wire.read() << 8;
|
||||
@@ -86,11 +86,11 @@ uint8_t oled_probe(byte addr)
|
||||
}
|
||||
c++;
|
||||
} while ((r != r_prev) && (c < 4));
|
||||
DEBUG_MSG("0x%x subtype probed in %i tries \n", r, c);
|
||||
LOG_DEBUG("0x%x subtype probed in %i tries \n", r, c);
|
||||
return o_probe;
|
||||
}
|
||||
|
||||
void scanI2Cdevice(void)
|
||||
void scanI2Cdevice()
|
||||
{
|
||||
byte err, addr;
|
||||
uint16_t registerValue = 0x00;
|
||||
@@ -99,28 +99,28 @@ void scanI2Cdevice(void)
|
||||
Wire.beginTransmission(addr);
|
||||
err = Wire.endTransmission();
|
||||
if (err == 0) {
|
||||
DEBUG_MSG("I2C device found at address 0x%x\n", addr);
|
||||
LOG_DEBUG("I2C device found at address 0x%x\n", addr);
|
||||
|
||||
nDevices++;
|
||||
|
||||
if (addr == SSD1306_ADDRESS) {
|
||||
screen_found = addr;
|
||||
screen_model = oled_probe(addr);
|
||||
if (screen_model == 1){
|
||||
DEBUG_MSG("ssd1306 display found\n");
|
||||
} else if (screen_model == 2){
|
||||
DEBUG_MSG("sh1106 display found\n");
|
||||
if (screen_model == 1) {
|
||||
LOG_INFO("ssd1306 display found\n");
|
||||
} else if (screen_model == 2) {
|
||||
LOG_INFO("sh1106 display found\n");
|
||||
} else {
|
||||
DEBUG_MSG("unknown display found\n");
|
||||
LOG_INFO("unknown display found\n");
|
||||
}
|
||||
}
|
||||
#ifndef ARCH_PORTDUINO
|
||||
if (addr == ATECC608B_ADDR){
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
if (addr == ATECC608B_ADDR) {
|
||||
keystore_found = addr;
|
||||
if (atecc.begin(keystore_found) == true) {
|
||||
DEBUG_MSG("ATECC608B initialized\n");
|
||||
LOG_INFO("ATECC608B initialized\n");
|
||||
} else {
|
||||
DEBUG_MSG("ATECC608B initialization failed\n");
|
||||
LOG_WARN("ATECC608B initialization failed\n");
|
||||
}
|
||||
printATECCInfo();
|
||||
}
|
||||
@@ -128,7 +128,7 @@ void scanI2Cdevice(void)
|
||||
#ifdef RV3028_RTC
|
||||
if (addr == RV3028_RTC){
|
||||
rtc_found = addr;
|
||||
DEBUG_MSG("RV3028 RTC found\n");
|
||||
LOG_INFO("RV3028 RTC found\n");
|
||||
Melopero_RV3028 rtc;
|
||||
rtc.initI2C();
|
||||
rtc.writeToRegister(0x35,0x07); // no Clkout
|
||||
@@ -138,7 +138,7 @@ void scanI2Cdevice(void)
|
||||
#ifdef PCF8563_RTC
|
||||
if (addr == PCF8563_RTC){
|
||||
rtc_found = addr;
|
||||
DEBUG_MSG("PCF8563 RTC found\n");
|
||||
LOG_INFO("PCF8563 RTC found\n");
|
||||
}
|
||||
#endif
|
||||
if (addr == CARDKB_ADDR) {
|
||||
@@ -146,77 +146,87 @@ void scanI2Cdevice(void)
|
||||
// Do we have the RAK14006 instead?
|
||||
registerValue = getRegisterValue(addr, 0x04, 1);
|
||||
if (registerValue == 0x02) { // KEYPAD_VERSION
|
||||
DEBUG_MSG("RAK14004 found\n");
|
||||
LOG_INFO("RAK14004 found\n");
|
||||
kb_model = 0x02;
|
||||
} else {
|
||||
DEBUG_MSG("m5 cardKB found\n");
|
||||
LOG_INFO("m5 cardKB found\n");
|
||||
kb_model = 0x00;
|
||||
}
|
||||
}
|
||||
if (addr == ST7567_ADDRESS) {
|
||||
screen_found = addr;
|
||||
DEBUG_MSG("st7567 display found\n");
|
||||
LOG_INFO("st7567 display found\n");
|
||||
}
|
||||
#ifdef HAS_PMU
|
||||
if (addr == XPOWERS_AXP192_AXP2101_ADDRESS) {
|
||||
pmu_found = true;
|
||||
DEBUG_MSG("axp192/axp2101 PMU found\n");
|
||||
LOG_INFO("axp192/axp2101 PMU found\n");
|
||||
}
|
||||
#endif
|
||||
if (addr == BME_ADDR || addr == BME_ADDR_ALTERNATE) {
|
||||
registerValue = getRegisterValue(addr, 0xD0, 1); // GET_ID
|
||||
if (registerValue == 0x61) {
|
||||
DEBUG_MSG("BME-680 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_BME680] = addr;
|
||||
} else if (registerValue == 0x60) {
|
||||
DEBUG_MSG("BME-280 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_BME280] = addr;
|
||||
} else {
|
||||
DEBUG_MSG("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_BMP280] = addr;
|
||||
if (addr == BME_ADDR || addr == BME_ADDR_ALTERNATE) {
|
||||
registerValue = getRegisterValue(addr, 0xD0, 1); // GET_ID
|
||||
if (registerValue == 0x61) {
|
||||
LOG_INFO("BME-680 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_BME680] = addr;
|
||||
} else if (registerValue == 0x60) {
|
||||
LOG_INFO("BME-280 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_BME280] = addr;
|
||||
} else {
|
||||
LOG_INFO("BMP-280 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_BMP280] = addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addr == INA_ADDR || addr == INA_ADDR_ALTERNATE) {
|
||||
registerValue = getRegisterValue(addr, 0xFE, 2);
|
||||
DEBUG_MSG("Register MFG_UID: 0x%x\n", registerValue);
|
||||
if (registerValue == 0x5449) {
|
||||
DEBUG_MSG("INA260 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_INA260] = addr;
|
||||
} else { // Assume INA219 if INA260 ID is not found
|
||||
DEBUG_MSG("INA219 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_INA219] = addr;
|
||||
if (addr == INA_ADDR || addr == INA_ADDR_ALTERNATE) {
|
||||
registerValue = getRegisterValue(addr, 0xFE, 2);
|
||||
LOG_DEBUG("Register MFG_UID: 0x%x\n", registerValue);
|
||||
if (registerValue == 0x5449) {
|
||||
LOG_INFO("INA260 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_INA260] = addr;
|
||||
} else { // Assume INA219 if INA260 ID is not found
|
||||
LOG_INFO("INA219 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_INA219] = addr;
|
||||
}
|
||||
}
|
||||
if (addr == MCP9808_ADDR) {
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808] = addr;
|
||||
LOG_INFO("MCP9808 sensor found\n");
|
||||
}
|
||||
if (addr == SHT31_ADDR) {
|
||||
LOG_INFO("SHT31 sensor found\n");
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_SHT31] = addr;
|
||||
}
|
||||
if (addr == SHTC3_ADDR) {
|
||||
LOG_INFO("SHTC3 sensor found\n");
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_SHTC3] = addr;
|
||||
}
|
||||
if (addr == LPS22HB_ADDR || addr == LPS22HB_ADDR_ALT) {
|
||||
LOG_INFO("LPS22HB sensor found\n");
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_LPS22] = addr;
|
||||
}
|
||||
|
||||
// High rate sensors, will be processed internally
|
||||
if (addr == QMC6310_ADDR) {
|
||||
LOG_INFO("QMC6310 Highrate 3-Axis magnetic sensor found\n");
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_QMC6310] = addr;
|
||||
}
|
||||
if (addr == QMI8658_ADDR) {
|
||||
LOG_INFO("QMI8658 Highrate 6-Axis inertial measurement sensor found\n");
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658] = addr;
|
||||
}
|
||||
if (addr == QMC5883L_ADDR) {
|
||||
LOG_INFO("QMC5883L Highrate 3-Axis magnetic sensor found\n");
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_QMC5883L] = addr;
|
||||
}
|
||||
}
|
||||
if (addr == MCP9808_ADDR) {
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_MCP9808] = addr;
|
||||
DEBUG_MSG("MCP9808 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
}
|
||||
if (addr == QMC6310_ADDR) {
|
||||
DEBUG_MSG("QMC6310 3-Axis magnetic sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_QMC6310] = addr;
|
||||
}
|
||||
if (addr == QMI8658_ADDR) {
|
||||
DEBUG_MSG("QMI8658 6-Axis inertial measurement sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658] = addr;
|
||||
}
|
||||
if (addr == SHTC3_ADDR) {
|
||||
DEBUG_MSG("SHTC3 sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_SHTC3] = addr;
|
||||
}
|
||||
if (addr == LPS22HB_ADDR || addr == LPS22HB_ADDR_ALT) {
|
||||
DEBUG_MSG("LPS22HB sensor found at address 0x%x\n", (uint8_t)addr);
|
||||
nodeTelemetrySensorsMap[TelemetrySensorType_LPS22] = addr;
|
||||
}
|
||||
} else if (err == 4) {
|
||||
DEBUG_MSG("Unknow error at address 0x%x\n", addr);
|
||||
LOG_ERROR("Unknow error at address 0x%x\n", addr);
|
||||
}
|
||||
}
|
||||
|
||||
if (nDevices == 0)
|
||||
DEBUG_MSG("No I2C devices found\n");
|
||||
LOG_INFO("No I2C devices found\n");
|
||||
else
|
||||
DEBUG_MSG("%i I2C devices found\n",nDevices);
|
||||
LOG_INFO("%i I2C devices found\n",nDevices);
|
||||
}
|
||||
#else
|
||||
void scanI2Cdevice(void) {}
|
||||
void scanI2Cdevice() {}
|
||||
#endif
|
||||
|
||||
100
src/gps/GPS.cpp
100
src/gps/GPS.cpp
@@ -150,9 +150,21 @@ bool GPS::setupGPS()
|
||||
_serial_gps->setRxBufferSize(2048); // the default is 256
|
||||
#endif
|
||||
|
||||
// if the overrides are not dialled in, set them from the board definitions, if they exist
|
||||
|
||||
#if defined(GPS_RX_PIN)
|
||||
if (!config.position.rx_gpio)
|
||||
config.position.rx_gpio = GPS_RX_PIN;
|
||||
#endif
|
||||
#if defined(GPS_TX_PIN)
|
||||
if (!config.position.tx_gpio)
|
||||
config.position.tx_gpio = GPS_TX_PIN;
|
||||
#endif
|
||||
|
||||
// ESP32 has a special set of parameters vs other arduino ports
|
||||
#if defined(GPS_RX_PIN) && defined(ARCH_ESP32)
|
||||
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, GPS_RX_PIN, GPS_TX_PIN);
|
||||
#if defined(ARCH_ESP32)
|
||||
if(config.position.rx_gpio)
|
||||
_serial_gps->begin(GPS_BAUDRATE, SERIAL_8N1, config.position.rx_gpio, config.position.tx_gpio);
|
||||
#else
|
||||
_serial_gps->begin(GPS_BAUDRATE);
|
||||
#endif
|
||||
@@ -191,7 +203,7 @@ bool GPS::setupGPS()
|
||||
0x80, 0x25, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x91, 0xAF};
|
||||
_serial_gps->write(_message_nmea, sizeof(_message_nmea));
|
||||
if (!getACK(0x06, 0x00)) {
|
||||
DEBUG_MSG("WARNING: Unable to enable NMEA Mode.\n");
|
||||
LOG_WARN("Unable to enable NMEA Mode.\n");
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
@@ -202,7 +214,7 @@ bool GPS::setupGPS()
|
||||
byte _message_GGL[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x05, 0x3A};
|
||||
_serial_gps->write(_message_GGL, sizeof(_message_GGL));
|
||||
if (!getACK(0x06, 0x01)) {
|
||||
DEBUG_MSG("WARNING: Unable to disable NMEA GGL.\n");
|
||||
LOG_WARN("Unable to disable NMEA GGL.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -210,7 +222,7 @@ bool GPS::setupGPS()
|
||||
byte _message_GSA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x06, 0x41};
|
||||
_serial_gps->write(_message_GSA, sizeof(_message_GSA));
|
||||
if (!getACK(0x06, 0x01)) {
|
||||
DEBUG_MSG("WARNING: Unable to disable NMEA GSA.\n");
|
||||
LOG_WARN("Unable to disable NMEA GSA.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -218,7 +230,7 @@ bool GPS::setupGPS()
|
||||
byte _message_GSV[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x07, 0x48};
|
||||
_serial_gps->write(_message_GSV, sizeof(_message_GSV));
|
||||
if (!getACK(0x06, 0x01)) {
|
||||
DEBUG_MSG("WARNING: Unable to disable NMEA GSV.\n");
|
||||
LOG_WARN("Unable to disable NMEA GSV.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -226,7 +238,7 @@ bool GPS::setupGPS()
|
||||
byte _message_VTG[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x09, 0x56};
|
||||
_serial_gps->write(_message_VTG, sizeof(_message_VTG));
|
||||
if (!getACK(0x06, 0x01)) {
|
||||
DEBUG_MSG("WARNING: Unable to disable NMEA VTG.\n");
|
||||
LOG_WARN("Unable to disable NMEA VTG.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -234,7 +246,7 @@ bool GPS::setupGPS()
|
||||
byte _message_RMC[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x09, 0x54};
|
||||
_serial_gps->write(_message_RMC, sizeof(_message_RMC));
|
||||
if (!getACK(0x06, 0x01)) {
|
||||
DEBUG_MSG("WARNING: Unable to enable NMEA RMC.\n");
|
||||
LOG_WARN("Unable to enable NMEA RMC.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -242,7 +254,7 @@ bool GPS::setupGPS()
|
||||
byte _message_GGA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x05, 0x38};
|
||||
_serial_gps->write(_message_GGA, sizeof(_message_GGA));
|
||||
if (!getACK(0x06, 0x01)) {
|
||||
DEBUG_MSG("WARNING: Unable to enable NMEA GGA.\n");
|
||||
LOG_WARN("Unable to enable NMEA GGA.\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -258,21 +270,30 @@ bool GPS::setup()
|
||||
pinMode(PIN_GPS_EN, OUTPUT);
|
||||
#endif
|
||||
|
||||
#ifdef HAS_PMU
|
||||
if(config.position.gps_enabled){
|
||||
setGPSPower(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PIN_GPS_RESET
|
||||
digitalWrite(PIN_GPS_RESET, 1); // assert for 10ms
|
||||
pinMode(PIN_GPS_RESET, OUTPUT);
|
||||
delay(10);
|
||||
digitalWrite(PIN_GPS_RESET, 0);
|
||||
#endif
|
||||
|
||||
setAwake(true); // Wake GPS power before doing any init
|
||||
bool ok = setupGPS();
|
||||
|
||||
if (ok) {
|
||||
notifySleepObserver.observe(¬ifySleep);
|
||||
notifyDeepSleepObserver.observe(¬ifyDeepSleep);
|
||||
notifyGPSSleepObserver.observe(¬ifyGPSSleep);
|
||||
}
|
||||
if (config.position.gps_enabled==false) {
|
||||
setAwake(false);
|
||||
doGPSpowersave(false);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -281,6 +302,7 @@ GPS::~GPS()
|
||||
// we really should unregister our sleep observer
|
||||
notifySleepObserver.unobserve(¬ifySleep);
|
||||
notifyDeepSleepObserver.unobserve(¬ifyDeepSleep);
|
||||
notifyGPSSleepObserver.observe(¬ifyGPSSleep);
|
||||
}
|
||||
|
||||
bool GPS::hasLock()
|
||||
@@ -339,12 +361,12 @@ void GPS::setNumSatellites(uint8_t n)
|
||||
void GPS::setAwake(bool on)
|
||||
{
|
||||
if (!wakeAllowed && on) {
|
||||
DEBUG_MSG("Inhibiting because !wakeAllowed\n");
|
||||
LOG_WARN("Inhibiting because !wakeAllowed\n");
|
||||
on = false;
|
||||
}
|
||||
|
||||
if (isAwake != on) {
|
||||
DEBUG_MSG("WANT GPS=%d\n", on);
|
||||
LOG_DEBUG("WANT GPS=%d\n", on);
|
||||
if (on) {
|
||||
lastWakeStartMsec = millis();
|
||||
wake();
|
||||
@@ -390,10 +412,10 @@ void GPS::publishUpdate()
|
||||
shouldPublish = false;
|
||||
|
||||
// In debug logs, identify position by @timestamp:stage (stage 2 = publish)
|
||||
DEBUG_MSG("publishing pos@%x:2, hasVal=%d, GPSlock=%d\n", p.timestamp, hasValidLocation, hasLock());
|
||||
LOG_DEBUG("publishing pos@%x:2, hasVal=%d, GPSlock=%d\n", p.timestamp, hasValidLocation, hasLock());
|
||||
|
||||
// Notify any status instances that are observing us
|
||||
const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasValidLocation, isConnected(), p);
|
||||
const meshtastic::GPSStatus status = meshtastic::GPSStatus(hasValidLocation, isConnected(), isPowerSaving(), p);
|
||||
newStatus.notifyObservers(&status);
|
||||
}
|
||||
}
|
||||
@@ -404,10 +426,10 @@ int32_t GPS::runOnce()
|
||||
// if we have received valid NMEA claim we are connected
|
||||
setConnected();
|
||||
} else {
|
||||
if(gnssModel == GNSS_MODEL_UBLOX){
|
||||
if((config.position.gps_enabled == 1) && (gnssModel == GNSS_MODEL_UBLOX)){
|
||||
// reset the GPS on next bootup
|
||||
if(devicestate.did_gps_reset && (millis() > 60000) && !hasFlow()) {
|
||||
DEBUG_MSG("GPS is not communicating, trying factory reset on next bootup.\n");
|
||||
LOG_DEBUG("GPS is not communicating, trying factory reset on next bootup.\n");
|
||||
devicestate.did_gps_reset = false;
|
||||
nodeDB.saveDeviceStateToDisk();
|
||||
}
|
||||
@@ -425,7 +447,7 @@ int32_t GPS::runOnce()
|
||||
|
||||
// While we are awake
|
||||
if (isAwake) {
|
||||
// DEBUG_MSG("looking for location\n");
|
||||
// LOG_DEBUG("looking for location\n");
|
||||
if ((now - lastWhileActiveMsec) > 5000) {
|
||||
lastWhileActiveMsec = now;
|
||||
whileActive();
|
||||
@@ -440,7 +462,7 @@ int32_t GPS::runOnce()
|
||||
|
||||
bool gotLoc = lookForLocation();
|
||||
if (gotLoc && !hasValidLocation) { // declare that we have location ASAP
|
||||
DEBUG_MSG("hasValidLocation RISING EDGE\n");
|
||||
LOG_DEBUG("hasValidLocation RISING EDGE\n");
|
||||
hasValidLocation = true;
|
||||
shouldPublish = true;
|
||||
}
|
||||
@@ -451,13 +473,13 @@ int32_t GPS::runOnce()
|
||||
bool tooLong = wakeTime != UINT32_MAX && (now - lastWakeStartMsec) > wakeTime;
|
||||
|
||||
// Once we get a location we no longer desperately want an update
|
||||
// DEBUG_MSG("gotLoc %d, tooLong %d, gotTime %d\n", gotLoc, tooLong, gotTime);
|
||||
// LOG_DEBUG("gotLoc %d, tooLong %d, gotTime %d\n", gotLoc, tooLong, gotTime);
|
||||
if ((gotLoc && gotTime) || tooLong) {
|
||||
|
||||
if (tooLong) {
|
||||
// we didn't get a location during this ack window, therefore declare loss of lock
|
||||
if (hasValidLocation) {
|
||||
DEBUG_MSG("hasValidLocation FALLING EDGE (last read: %d)\n", gotLoc);
|
||||
LOG_DEBUG("hasValidLocation FALLING EDGE (last read: %d)\n", gotLoc);
|
||||
}
|
||||
p = Position_init_default;
|
||||
hasValidLocation = false;
|
||||
@@ -479,7 +501,7 @@ int32_t GPS::runOnce()
|
||||
void GPS::forceWake(bool on)
|
||||
{
|
||||
if (on) {
|
||||
DEBUG_MSG("Allowing GPS lock\n");
|
||||
LOG_DEBUG("Allowing GPS lock\n");
|
||||
// lastSleepStartMsec = 0; // Force an update ASAP
|
||||
wakeAllowed = true;
|
||||
} else {
|
||||
@@ -494,7 +516,7 @@ void GPS::forceWake(bool on)
|
||||
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
|
||||
int GPS::prepareSleep(void *unused)
|
||||
{
|
||||
DEBUG_MSG("GPS prepare sleep!\n");
|
||||
LOG_INFO("GPS prepare sleep!\n");
|
||||
forceWake(false);
|
||||
|
||||
return 0;
|
||||
@@ -503,9 +525,10 @@ int GPS::prepareSleep(void *unused)
|
||||
/// Prepare the GPS for the cpu entering deep or light sleep, expect to be gone for at least 100s of msecs
|
||||
int GPS::prepareDeepSleep(void *unused)
|
||||
{
|
||||
DEBUG_MSG("GPS deep sleep!\n");
|
||||
LOG_INFO("GPS deep sleep!\n");
|
||||
|
||||
// For deep sleep we also want abandon any lock attempts (because we want minimum power)
|
||||
getSleepTime();
|
||||
setAwake(false);
|
||||
|
||||
return 0;
|
||||
@@ -545,7 +568,7 @@ GnssModel_t GPS::probe()
|
||||
if(index != -1){
|
||||
ver = ver.substring(index);
|
||||
if (ver.startsWith("$GPTXT,01,01,02")) {
|
||||
DEBUG_MSG("L76K GNSS init succeeded, using L76K GNSS Module\n");
|
||||
LOG_INFO("L76K GNSS init succeeded, using L76K GNSS Module\n");
|
||||
return GNSS_MODEL_MTK;
|
||||
}
|
||||
}
|
||||
@@ -557,7 +580,7 @@ GnssModel_t GPS::probe()
|
||||
_serial_gps->write(cfg_rate, sizeof(cfg_rate));
|
||||
// Check that the returned response class and message ID are correct
|
||||
if (!getAck(buffer, 256, 0x06, 0x08)) {
|
||||
DEBUG_MSG("Warning: Failed to find UBlox & MTK GNSS Module\n");
|
||||
LOG_WARN("Failed to find UBlox & MTK GNSS Module\n");
|
||||
return GNSS_MODEL_UNKONW;
|
||||
}
|
||||
|
||||
@@ -588,12 +611,12 @@ GnssModel_t GPS::probe()
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUG_MSG("Module Info : \n");
|
||||
DEBUG_MSG("Soft version: %s\n",info.swVersion);
|
||||
DEBUG_MSG("Hard version: %s\n",info.hwVersion);
|
||||
DEBUG_MSG("Extensions:%d\n",info.extensionNo);
|
||||
LOG_DEBUG("Module Info : \n");
|
||||
LOG_DEBUG("Soft version: %s\n",info.swVersion);
|
||||
LOG_DEBUG("Hard version: %s\n",info.hwVersion);
|
||||
LOG_DEBUG("Extensions:%d\n",info.extensionNo);
|
||||
for (int i = 0; i < info.extensionNo; i++) {
|
||||
DEBUG_MSG(" %s\n",info.extension[i]);
|
||||
LOG_DEBUG(" %s\n",info.extension[i]);
|
||||
}
|
||||
|
||||
memset(buffer,0,sizeof(buffer));
|
||||
@@ -602,15 +625,15 @@ GnssModel_t GPS::probe()
|
||||
for (int i = 0; i < info.extensionNo; ++i) {
|
||||
if (!strncmp(info.extension[i], "OD=", 3)) {
|
||||
strcpy((char *)buffer, &(info.extension[i][3]));
|
||||
DEBUG_MSG("GetModel:%s\n",(char *)buffer);
|
||||
LOG_DEBUG("GetModel:%s\n",(char *)buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen((char*)buffer)) {
|
||||
DEBUG_MSG("UBlox GNSS init succeeded, using UBlox %s GNSS Module\n" , buffer);
|
||||
LOG_INFO("UBlox GNSS init succeeded, using UBlox %s GNSS Module\n" , buffer);
|
||||
}else{
|
||||
DEBUG_MSG("UBlox GNSS init succeeded, using UBlox GNSS Module\n");
|
||||
LOG_INFO("UBlox GNSS init succeeded, using UBlox GNSS Module\n");
|
||||
}
|
||||
|
||||
return GNSS_MODEL_UBLOX;
|
||||
@@ -629,9 +652,9 @@ GPS *createGps()
|
||||
#else
|
||||
if (config.position.gps_enabled) {
|
||||
#ifdef GPS_ALTITUDE_HAE
|
||||
DEBUG_MSG("Using HAE altitude model\n");
|
||||
LOG_DEBUG("Using HAE altitude model\n");
|
||||
#else
|
||||
DEBUG_MSG("Using MSL altitude model\n");
|
||||
LOG_DEBUG("Using MSL altitude model\n");
|
||||
#endif
|
||||
if (GPS::_serial_gps) {
|
||||
// Some boards might have only the TX line from the GPS connected, in that case, we can't configure it at all. Just
|
||||
@@ -641,6 +664,11 @@ GPS *createGps()
|
||||
return new_gps;
|
||||
}
|
||||
}
|
||||
else{
|
||||
GPS *new_gps = new NMEAGPS();
|
||||
new_gps->setup();
|
||||
return new_gps;
|
||||
}
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ class GPS : private concurrency::OSThread
|
||||
|
||||
CallbackObserver<GPS, void *> notifySleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareSleep);
|
||||
CallbackObserver<GPS, void *> notifyDeepSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
|
||||
CallbackObserver<GPS, void *> notifyGPSSleepObserver = CallbackObserver<GPS, void *>(this, &GPS::prepareDeepSleep);
|
||||
|
||||
public:
|
||||
/** If !NULL we will use this serial port to construct our GPS */
|
||||
@@ -77,6 +78,8 @@ class GPS : private concurrency::OSThread
|
||||
/// Return true if we are connected to a GPS
|
||||
bool isConnected() const { return hasGPS; }
|
||||
|
||||
bool isPowerSaving() const { return !config.position.gps_enabled;}
|
||||
|
||||
/**
|
||||
* Restart our lock attempt - try to get and broadcast a GPS reading ASAP
|
||||
* called after the CPU wakes from light-sleep state
|
||||
|
||||
@@ -53,9 +53,9 @@ bool NMEAGPS::setupGPS()
|
||||
// see NMEAGPS.h
|
||||
gsafixtype.begin(reader, NMEA_MSG_GXGSA, 2);
|
||||
gsapdop.begin(reader, NMEA_MSG_GXGSA, 15);
|
||||
DEBUG_MSG("Using " NMEA_MSG_GXGSA " for 3DFIX and PDOP\n");
|
||||
LOG_DEBUG("Using " NMEA_MSG_GXGSA " for 3DFIX and PDOP\n");
|
||||
#else
|
||||
DEBUG_MSG("GxGSA NOT available\n");
|
||||
LOG_DEBUG("GxGSA NOT available\n");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@@ -85,7 +85,7 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s
|
||||
t.tm_year = d.year() - 1900;
|
||||
t.tm_isdst = false;
|
||||
if (t.tm_mon > -1){
|
||||
DEBUG_MSG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
|
||||
LOG_DEBUG("NMEA GPS time %02d-%02d-%02d %02d:%02d:%02d\n", d.year(), d.month(), t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
|
||||
perhapsSetRTC(RTCQualityGPS, t);
|
||||
return true;
|
||||
} else
|
||||
@@ -109,7 +109,7 @@ bool NMEAGPS::lookForLocation()
|
||||
|
||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
fixType = atoi(gsafixtype.value()); // will set to zero if no data
|
||||
DEBUG_MSG("FIX QUAL=%d, TYPE=%d\n", fixQual, fixType);
|
||||
// LOG_DEBUG("FIX QUAL=%d, TYPE=%d\n", fixQual, fixType);
|
||||
#endif
|
||||
|
||||
// check if GPS has an acceptable lock
|
||||
@@ -117,7 +117,7 @@ bool NMEAGPS::lookForLocation()
|
||||
return false;
|
||||
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("AGE: LOC=%d FIX=%d DATE=%d TIME=%d\n",
|
||||
LOG_DEBUG("AGE: LOC=%d FIX=%d DATE=%d TIME=%d\n",
|
||||
reader.location.age(),
|
||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
gsafixtype.age(),
|
||||
@@ -137,7 +137,7 @@ bool NMEAGPS::lookForLocation()
|
||||
(reader.time.age() < GPS_SOL_EXPIRY_MS) &&
|
||||
(reader.date.age() < GPS_SOL_EXPIRY_MS)))
|
||||
{
|
||||
DEBUG_MSG("SOME data is TOO OLD: LOC %u, TIME %u, DATE %u\n", reader.location.age(), reader.time.age(), reader.date.age());
|
||||
LOG_WARN("SOME data is TOO OLD: LOC %u, TIME %u, DATE %u\n", reader.location.age(), reader.time.age(), reader.date.age());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -151,13 +151,13 @@ bool NMEAGPS::lookForLocation()
|
||||
// Bail out EARLY to avoid overwriting previous good data (like #857)
|
||||
if (toDegInt(loc.lat) > 900000000) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("Bail out EARLY on LAT %i\n",toDegInt(loc.lat));
|
||||
LOG_DEBUG("Bail out EARLY on LAT %i\n",toDegInt(loc.lat));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
if (toDegInt(loc.lng) > 1800000000) {
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("Bail out EARLY on LNG %i\n",toDegInt(loc.lng));
|
||||
LOG_DEBUG("Bail out EARLY on LNG %i\n",toDegInt(loc.lng));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
@@ -168,7 +168,7 @@ bool NMEAGPS::lookForLocation()
|
||||
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
|
||||
p.HDOP = reader.hdop.value();
|
||||
p.PDOP = TinyGPSPlus::parseDecimal(gsapdop.value());
|
||||
DEBUG_MSG("PDOP=%d, HDOP=%d\n", dop, reader.hdop.value());
|
||||
// LOG_DEBUG("PDOP=%d, HDOP=%d\n", p.PDOP, p.HDOP);
|
||||
#else
|
||||
// FIXME! naive PDOP emulation (assumes VDOP==HDOP)
|
||||
// correct formula is PDOP = SQRT(HDOP^2 + VDOP^2)
|
||||
@@ -212,7 +212,7 @@ bool NMEAGPS::lookForLocation()
|
||||
if (reader.course.value() < 36000) { // sanity check
|
||||
p.ground_track = reader.course.value() * 1e3; // Scale the heading (in degrees * 10^-2) to match the expected degrees * 10^-5
|
||||
} else {
|
||||
DEBUG_MSG("BOGUS course.value() REJECTED: %d\n",
|
||||
LOG_WARN("BOGUS course.value() REJECTED: %d\n",
|
||||
reader.course.value());
|
||||
}
|
||||
}
|
||||
@@ -251,7 +251,7 @@ bool NMEAGPS::whileIdle()
|
||||
// First consume any chars that have piled up at the receiver
|
||||
while (_serial_gps->available() > 0) {
|
||||
int c = _serial_gps->read();
|
||||
// DEBUG_MSG("%c", c);
|
||||
// LOG_DEBUG("%c", c);
|
||||
isValid |= reader.encode(c);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "NMEAWPL.h"
|
||||
#include "GeoCoord.h"
|
||||
|
||||
/* -------------------------------------------
|
||||
* 1 2 3 4 5 6
|
||||
@@ -15,11 +16,19 @@
|
||||
* -------------------------------------------
|
||||
*/
|
||||
|
||||
uint printWPL(char *buf, const Position &pos, const char *name)
|
||||
uint32_t printWPL(char *buf, const Position &pos, const char *name)
|
||||
{
|
||||
uint len = sprintf(buf, "$GNWPL,%07.2f,%c,%08.2f,%c,%s", pos.latitude_i * 1e-5, pos.latitude_i < 0 ? 'S' : 'N', pos.longitude_i * 1e-5, pos.longitude_i < 0 ? 'W' : 'E', name);
|
||||
uint chk = 0;
|
||||
for (uint i = 1; i < len; i++) {
|
||||
GeoCoord geoCoord(pos.latitude_i,pos.longitude_i,pos.altitude);
|
||||
uint32_t len = sprintf(buf, "$GNWPL,%02d%07.4f,%c,%03d%07.4f,%c,%s",
|
||||
geoCoord.getDMSLatDeg(),
|
||||
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6,
|
||||
geoCoord.getDMSLatCP(),
|
||||
geoCoord.getDMSLonDeg(),
|
||||
(abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
|
||||
geoCoord.getDMSLonCP(),
|
||||
name);
|
||||
uint32_t chk = 0;
|
||||
for (uint32_t i = 1; i < len; i++) {
|
||||
chk ^= buf[i];
|
||||
}
|
||||
len += sprintf(buf + len, "*%02X\r\n", chk);
|
||||
@@ -50,25 +59,30 @@ uint printWPL(char *buf, const Position &pos, const char *name)
|
||||
* -------------------------------------------
|
||||
*/
|
||||
|
||||
uint printGGA(char *buf, const Position &pos)
|
||||
uint32_t printGGA(char *buf, const Position &pos)
|
||||
{
|
||||
uint len = sprintf(buf, "$GNGGA,%06u.%03u,%07.2f,%c,%08.2f,%c,%u,%02u,%04u,%04d,%c,%04d,%c,%d,%04d",
|
||||
GeoCoord geoCoord(pos.latitude_i,pos.longitude_i,pos.altitude);
|
||||
uint32_t len = sprintf(buf, "$GNGGA,%06u.%03u,%02d%07.4f,%c,%03d%07.4f,%c,%u,%02u,%04u,%04d,%c,%04d,%c,%d,%04d",
|
||||
pos.time / 1000,
|
||||
pos.time % 1000,
|
||||
pos.latitude_i * 1e-5, pos.latitude_i < 0 ? 'S' : 'N',
|
||||
pos.longitude_i * 1e-5, pos.longitude_i < 0 ? 'W' : 'E',
|
||||
geoCoord.getDMSLatDeg(),
|
||||
(abs(geoCoord.getLatitude()) - geoCoord.getDMSLatDeg() * 1e+7) * 6e-6,
|
||||
geoCoord.getDMSLatCP(),
|
||||
geoCoord.getDMSLonDeg(),
|
||||
(abs(geoCoord.getLongitude()) - geoCoord.getDMSLonDeg() * 1e+7) * 6e-6,
|
||||
geoCoord.getDMSLonCP(),
|
||||
pos.fix_type,
|
||||
pos.sats_in_view,
|
||||
pos.HDOP,
|
||||
pos.altitude,
|
||||
geoCoord.getAltitude(),
|
||||
'M',
|
||||
pos.altitude_geoidal_separation,
|
||||
'M',
|
||||
0,
|
||||
0);
|
||||
|
||||
uint chk = 0;
|
||||
for (uint i = 1; i < len; i++) {
|
||||
uint32_t chk = 0;
|
||||
for (uint32_t i = 1; i < len; i++) {
|
||||
chk ^= buf[i];
|
||||
}
|
||||
len += sprintf(buf + len, "*%02X\r\n", chk);
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
#include <Arduino.h>
|
||||
#include "main.h"
|
||||
|
||||
uint printWPL(char *buf, const Position &pos, const char *name);
|
||||
uint printGGA(char *buf, const Position &pos);
|
||||
uint32_t printWPL(char *buf, const Position &pos, const char *name);
|
||||
uint32_t printGGA(char *buf, const Position &pos);
|
||||
|
||||
@@ -33,7 +33,7 @@ void readFromRTC()
|
||||
t.tm_sec = rtc.getSecond();
|
||||
tv.tv_sec = mktime(&t);
|
||||
tv.tv_usec = 0;
|
||||
DEBUG_MSG("Read RTC time from RV3028 as %ld\n", tv.tv_sec);
|
||||
LOG_DEBUG("Read RTC time from RV3028 as %ld\n", tv.tv_sec);
|
||||
timeStartMsec = now;
|
||||
zeroOffsetSecs = tv.tv_sec;
|
||||
if (currentQuality == RTCQualityNone) {
|
||||
@@ -44,7 +44,11 @@ void readFromRTC()
|
||||
if(rtc_found == PCF8563_RTC) {
|
||||
uint32_t now = millis();
|
||||
PCF8563_Class rtc;
|
||||
#ifdef RTC_USE_WIRE1
|
||||
rtc.begin(Wire1);
|
||||
#else
|
||||
rtc.begin();
|
||||
#endif
|
||||
auto tc = rtc.getDateTime();
|
||||
tm t;
|
||||
t.tm_year = tc.year - 1900;
|
||||
@@ -55,7 +59,7 @@ void readFromRTC()
|
||||
t.tm_sec = tc.second;
|
||||
tv.tv_sec = mktime(&t);
|
||||
tv.tv_usec = 0;
|
||||
DEBUG_MSG("Read RTC time from PCF8563 as %ld\n", tv.tv_sec);
|
||||
LOG_DEBUG("Read RTC time from PCF8563 as %ld\n", tv.tv_sec);
|
||||
timeStartMsec = now;
|
||||
zeroOffsetSecs = tv.tv_sec;
|
||||
if (currentQuality == RTCQualityNone) {
|
||||
@@ -65,7 +69,7 @@ void readFromRTC()
|
||||
#else
|
||||
if (!gettimeofday(&tv, NULL)) {
|
||||
uint32_t now = millis();
|
||||
DEBUG_MSG("Read RTC time as %ld\n", tv.tv_sec);
|
||||
LOG_DEBUG("Read RTC time as %ld\n", tv.tv_sec);
|
||||
timeStartMsec = now;
|
||||
zeroOffsetSecs = tv.tv_sec;
|
||||
}
|
||||
@@ -82,11 +86,11 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
|
||||
if (q > currentQuality) {
|
||||
currentQuality = q;
|
||||
shouldSet = true;
|
||||
DEBUG_MSG("Upgrading time to RTC %ld secs (quality %d)\n", tv->tv_sec, q);
|
||||
LOG_DEBUG("Upgrading time to RTC %ld secs (quality %d)\n", tv->tv_sec, q);
|
||||
} else if(q == RTCQualityGPS && (now - lastSetMsec) > (12 * 60 * 60 * 1000UL)) {
|
||||
// Every 12 hrs we will slam in a new GPS time, to correct for local RTC clock drift
|
||||
shouldSet = true;
|
||||
DEBUG_MSG("Reapplying external time to correct clock drift %ld secs\n", tv->tv_sec);
|
||||
LOG_DEBUG("Reapplying external time to correct clock drift %ld secs\n", tv->tv_sec);
|
||||
}
|
||||
else
|
||||
shouldSet = false;
|
||||
@@ -105,15 +109,19 @@ bool perhapsSetRTC(RTCQuality q, const struct timeval *tv)
|
||||
rtc.initI2C();
|
||||
tm *t = localtime(&tv->tv_sec);
|
||||
rtc.setTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_wday, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
DEBUG_MSG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
|
||||
LOG_DEBUG("RV3028_RTC setTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
|
||||
}
|
||||
#elif defined(PCF8563_RTC)
|
||||
if(rtc_found == PCF8563_RTC) {
|
||||
PCF8563_Class rtc;
|
||||
rtc.begin();
|
||||
#ifdef RTC_USE_WIRE1
|
||||
rtc.begin(Wire1);
|
||||
#else
|
||||
rtc.begin();
|
||||
#endif
|
||||
tm *t = localtime(&tv->tv_sec);
|
||||
rtc.setDateTime(t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
DEBUG_MSG("PCF8563_RTC setDateTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
|
||||
LOG_DEBUG("PCF8563_RTC setDateTime %02d-%02d-%02d %02d:%02d:%02d %ld\n", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, tv->tv_sec);
|
||||
}
|
||||
#elif defined(ARCH_ESP32)
|
||||
settimeofday(tv, NULL);
|
||||
@@ -141,9 +149,9 @@ bool perhapsSetRTC(RTCQuality q, struct tm &t)
|
||||
tv.tv_sec = res;
|
||||
tv.tv_usec = 0; // time.centisecond() * (10 / 1000);
|
||||
|
||||
// DEBUG_MSG("Got time from GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
|
||||
// LOG_DEBUG("Got time from GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
|
||||
if (t.tm_year < 0 || t.tm_year >= 300) {
|
||||
// DEBUG_MSG("Ignoring invalid GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
|
||||
// LOG_DEBUG("Ignoring invalid GPS month=%d, year=%d, unixtime=%ld\n", t.tm_mon, t.tm_year, tv.tv_sec);
|
||||
return false;
|
||||
} else {
|
||||
return perhapsSetRTC(q, &tv);
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_154_D67
|
||||
#elif defined(RAK4630)
|
||||
|
||||
//GxEPD2_213_B74 - RAK14000 2.13 inch b/w 250x128
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_213_B74
|
||||
//GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122 - changed from GxEPD2_213_B74 - which was not going to give partial update support
|
||||
#define TECHO_DISPLAY_MODEL GxEPD2_213_BN
|
||||
|
||||
//4.2 inch 300x400 - GxEPD2_420_M01
|
||||
//#define TECHO_DISPLAY_MODEL GxEPD2_420_M01
|
||||
@@ -46,9 +46,9 @@ EInkDisplay::EInkDisplay(uint8_t address, int sda, int scl)
|
||||
setGeometry(GEOMETRY_RAWMODE, TECHO_DISPLAY_MODEL::WIDTH, TECHO_DISPLAY_MODEL::HEIGHT);
|
||||
#elif defined(RAK4630)
|
||||
|
||||
//GxEPD2_213_B74 - RAK14000 2.13 inch b/w 250x128
|
||||
//GxEPD2_213_BN - RAK14000 2.13 inch b/w 250x122
|
||||
setGeometry(GEOMETRY_RAWMODE, 250, 122);
|
||||
|
||||
|
||||
//GxEPD2_420_M01
|
||||
//setGeometry(GEOMETRY_RAWMODE, 300, 400);
|
||||
|
||||
@@ -103,21 +103,24 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_MSG("Updating E-Paper... ");
|
||||
LOG_DEBUG("Updating E-Paper... ");
|
||||
|
||||
#if defined(TTGO_T_ECHO)
|
||||
// ePaper.Reset(); // wake the screen from sleep
|
||||
adafruitDisplay->display(false); // FIXME, use partial update mode
|
||||
#elif defined(RAK4630)
|
||||
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
adafruitDisplay->display(false); // FIXME, use partial update mode
|
||||
//RAK14000 2.13 inch b/w 250x122 actually now does support partial updates
|
||||
|
||||
//Full update mode (slow)
|
||||
//adafruitDisplay->display(false); // FIXME, use partial update mode
|
||||
|
||||
//Only enable for e-Paper with support for partial updates and comment out above adafruitDisplay->display(false);
|
||||
// 1.54 inch 200x200 - GxEPD2_154_M09
|
||||
// 2.13 inch 250x122 - GxEPD2_213_BN
|
||||
// 2.9 inch 296x128 - GxEPD2_290_T5D
|
||||
// 4.2 inch 300x400 - GxEPD2_420_M01
|
||||
//adafruitDisplay->nextPage();
|
||||
adafruitDisplay->nextPage();
|
||||
|
||||
#elif defined(PCA10059) || defined(M5_COREINK)
|
||||
adafruitDisplay->nextPage();
|
||||
@@ -125,11 +128,11 @@ bool EInkDisplay::forceDisplay(uint32_t msecLimit)
|
||||
|
||||
// Put screen to sleep to save power (possibly not necessary because we already did poweroff inside of display)
|
||||
adafruitDisplay->hibernate();
|
||||
DEBUG_MSG("done\n");
|
||||
LOG_DEBUG("done\n");
|
||||
|
||||
return true;
|
||||
} else {
|
||||
// DEBUG_MSG("Skipping eink display\n");
|
||||
// LOG_DEBUG("Skipping eink display\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -159,7 +162,7 @@ void EInkDisplay::setDetected(uint8_t detected)
|
||||
// Connect to the display
|
||||
bool EInkDisplay::connect()
|
||||
{
|
||||
DEBUG_MSG("Doing EInk init\n");
|
||||
LOG_INFO("Doing EInk init\n");
|
||||
|
||||
#ifdef PIN_EINK_PWR_ON
|
||||
digitalWrite(PIN_EINK_PWR_ON, HIGH); // If we need to assert a pin to power external peripherals
|
||||
@@ -190,11 +193,11 @@ bool EInkDisplay::connect()
|
||||
|
||||
adafruitDisplay->init(115200, true, 10, false, SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
|
||||
|
||||
//RAK14000 2.13 inch b/w 250x122 does not support partial updates
|
||||
//RAK14000 2.13 inch b/w 250x122 does actually now support partial updates
|
||||
adafruitDisplay->setRotation(3);
|
||||
//For 1.54, 2.9 and 4.2
|
||||
//Partial update support for 1.54, 2.13 RAK14000 b/w , 2.9 and 4.2
|
||||
//adafruitDisplay->setRotation(1);
|
||||
//adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
adafruitDisplay->setPartialWindow(0, 0, displayWidth, displayHeight);
|
||||
} else {
|
||||
(void)adafruitDisplay;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "mesh/Channels.h"
|
||||
#include "mesh/generated/deviceonly.pb.h"
|
||||
#include "modules/TextMessageModule.h"
|
||||
#include "modules/ExternalNotificationModule.h"
|
||||
#include "sleep.h"
|
||||
#include "target_specific.h"
|
||||
#include "utils.h"
|
||||
@@ -42,6 +43,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifdef ARCH_ESP32
|
||||
#include "esp_task_wdt.h"
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "modules/esp32/StoreForwardModule.h"
|
||||
#endif
|
||||
|
||||
#ifdef OLED_RU
|
||||
@@ -50,8 +52,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using namespace meshtastic; /** @todo remove */
|
||||
|
||||
extern bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct);
|
||||
|
||||
namespace graphics
|
||||
{
|
||||
|
||||
@@ -67,6 +67,8 @@ namespace graphics
|
||||
static FrameCallback normalFrames[MAX_NUM_NODES + NUM_EXTRA_FRAMES];
|
||||
static uint32_t targetFramerate = IDLE_FRAMERATE;
|
||||
static char btPIN[16] = "888888";
|
||||
|
||||
uint32_t logo_timeout = 5000; // 4 seconds for EACH logo
|
||||
|
||||
// This image definition is here instead of images.h because it's modified dynamically by the drawBattery function
|
||||
uint8_t imgBattery[16] = {0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xE7, 0x3C};
|
||||
@@ -84,10 +86,6 @@ static char ourId[5];
|
||||
// GeoCoord object for the screen
|
||||
GeoCoord geoCoord;
|
||||
|
||||
// OEM Config File
|
||||
static const char *oemConfigFile = "/oem/oem.proto";
|
||||
OEMStore oemStore;
|
||||
|
||||
#ifdef SHOW_REDRAWS
|
||||
static bool heartbeat = false;
|
||||
#endif
|
||||
@@ -99,17 +97,17 @@ static uint16_t displayWidth, displayHeight;
|
||||
|
||||
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
||||
// The screen is bigger so use bigger fonts
|
||||
#define FONT_SMALL ArialMT_Plain_16
|
||||
#define FONT_MEDIUM ArialMT_Plain_24
|
||||
#define FONT_LARGE ArialMT_Plain_24
|
||||
#define FONT_SMALL ArialMT_Plain_16 // Height: 19
|
||||
#define FONT_MEDIUM ArialMT_Plain_24 // Height: 28
|
||||
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
|
||||
#else
|
||||
#ifdef OLED_RU
|
||||
#define FONT_SMALL ArialMT_Plain_10_RU
|
||||
#else
|
||||
#define FONT_SMALL ArialMT_Plain_10
|
||||
#define FONT_SMALL ArialMT_Plain_10 // Height: 13
|
||||
#endif
|
||||
#define FONT_MEDIUM ArialMT_Plain_16
|
||||
#define FONT_LARGE ArialMT_Plain_24
|
||||
#define FONT_MEDIUM ArialMT_Plain_16 // Height: 19
|
||||
#define FONT_LARGE ArialMT_Plain_24 // Height: 28
|
||||
#endif
|
||||
|
||||
#define fontHeight(font) ((font)[1] + 1) // height is position 1
|
||||
@@ -278,36 +276,36 @@ static void drawModuleFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int
|
||||
} else {
|
||||
// otherwise, just display the module frame that's aligned with the current frame
|
||||
module_frame = state->currentFrame;
|
||||
// DEBUG_MSG("Screen is not in transition. Frame: %d\n\n", module_frame);
|
||||
// LOG_DEBUG("Screen is not in transition. Frame: %d\n\n", module_frame);
|
||||
}
|
||||
// DEBUG_MSG("Drawing Module Frame %d\n\n", module_frame);
|
||||
// LOG_DEBUG("Drawing Module Frame %d\n\n", module_frame);
|
||||
MeshModule &pi = *moduleFrames.at(module_frame);
|
||||
pi.drawFrame(display, state, x, y);
|
||||
}
|
||||
|
||||
static void drawFrameBluetooth(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
{
|
||||
int x_offset = display->width() / 2;
|
||||
int y_offset = display->height() == 64 ? 0 : 32;
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
display->drawString(64 + x, y, "Bluetooth");
|
||||
display->drawString(x_offset + x, y_offset + y, "Bluetooth");
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Enter this code");
|
||||
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_MEDIUM -4 : y_offset + FONT_HEIGHT_MEDIUM + 5;
|
||||
display->drawString(x_offset + x, y_offset + y, "Enter this code");
|
||||
|
||||
display->setFont(FONT_LARGE);
|
||||
String displayPin(btPIN);
|
||||
String pin = displayPin.substring(0, 3) + " " + displayPin.substring(3, 6);
|
||||
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_SMALL - 5 : y_offset + FONT_HEIGHT_SMALL + 5;
|
||||
display->drawString(x_offset + x, y_offset + y, pin);
|
||||
|
||||
auto displayPin = new String(btPIN);
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->drawString(12 + x, 26 + y, displayPin->substring(0, 3));
|
||||
display->drawString(72 + x, 26 + y, displayPin->substring(3, 6));
|
||||
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->setFont(FONT_SMALL);
|
||||
char buf[30];
|
||||
const char *name = "Name: ";
|
||||
strcpy(buf, name);
|
||||
strcat(buf, getDeviceName());
|
||||
display->drawString(64 + x, 48 + y, buf);
|
||||
String deviceName = "Name: ";
|
||||
deviceName.concat(getDeviceName());
|
||||
y_offset = display->height() == 64 ? y_offset + FONT_HEIGHT_LARGE - 6 : y_offset + FONT_HEIGHT_LARGE + 5;
|
||||
display->drawString(x_offset + x, y_offset + y, deviceName);
|
||||
}
|
||||
|
||||
static void drawFrameShutdown(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16_t y)
|
||||
@@ -333,11 +331,8 @@ static void drawFrameFirmware(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
display->drawString(64 + x, y, "Updating");
|
||||
|
||||
display->setFont(FONT_SMALL);
|
||||
if ((millis() / 1000) % 2) {
|
||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . .");
|
||||
} else {
|
||||
display->drawString(64 + x, FONT_HEIGHT_SMALL + y + 2, "Please wait . . ");
|
||||
}
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->drawStringMaxWidth(0 + x, 2 + y + FONT_HEIGHT_SMALL *2, x + display->getWidth(), "Please be patient and do not power off.");
|
||||
}
|
||||
|
||||
/// Draw the last text message we received
|
||||
@@ -368,25 +363,30 @@ static void drawTextMessageFrame(OLEDDisplay *display, OLEDDisplayUiState *state
|
||||
{
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
// the max length of this buffer is much longer than we can possibly print
|
||||
static char tempBuf[237];
|
||||
|
||||
MeshPacket &mp = devicestate.rx_text_message;
|
||||
NodeInfo *node = nodeDB.getNode(getFrom(&mp));
|
||||
// DEBUG_MSG("drawing text message from 0x%x: %s\n", mp.from,
|
||||
// LOG_DEBUG("drawing text message from 0x%x: %s\n", mp.from,
|
||||
// mp.decoded.variant.data.decoded.bytes);
|
||||
|
||||
// Demo for drawStringMaxWidth:
|
||||
// with the third parameter you can define the width after which words will
|
||||
// be wrapped. Currently only spaces and "-" are allowed for wrapping
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
display->setFont(FONT_MEDIUM);
|
||||
String sender = (node && node->has_user) ? node->user.short_name : "???";
|
||||
display->drawString(0 + x, 0 + y, sender);
|
||||
display->setFont(FONT_SMALL);
|
||||
|
||||
// the max length of this buffer is much longer than we can possibly print
|
||||
static char tempBuf[96];
|
||||
snprintf(tempBuf, sizeof(tempBuf), " %s", mp.decoded.payload.bytes);
|
||||
|
||||
display->drawStringMaxWidth(4 + x, 10 + y, SCREEN_WIDTH - (6 + x), tempBuf);
|
||||
if (config.display.displaymode == Config_DisplayConfig_DisplayMode_INVERTED) {
|
||||
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
||||
display->setColor(BLACK);
|
||||
}
|
||||
display->drawStringf(0 + x, 0 + y, tempBuf, "From: %s", (node && node->has_user) ? node->user.short_name : "???");
|
||||
if(config.display.heading_bold) {
|
||||
display->drawStringf(1 + x, 0 + y, tempBuf, "From: %s", (node && node->has_user) ? node->user.short_name : "???");
|
||||
}
|
||||
display->setColor(WHITE);
|
||||
snprintf(tempBuf, sizeof(tempBuf), "%s", mp.decoded.payload.bytes);
|
||||
display->drawStringMaxWidth(0 + x, 0 + y + FONT_HEIGHT_SMALL, x + display->getWidth(), tempBuf);
|
||||
}
|
||||
|
||||
/// Draw a series of fields in a column, wrapping to multiple colums if needed
|
||||
@@ -399,6 +399,10 @@ static void drawColumns(OLEDDisplay *display, int16_t x, int16_t y, const char *
|
||||
int xo = x, yo = y;
|
||||
while (*f) {
|
||||
display->drawString(xo, yo, *f);
|
||||
if ((display->getColor() == BLACK) && config.display.heading_bold)
|
||||
display->drawString(xo + 1, yo, *f);
|
||||
|
||||
display->setColor(WHITE);
|
||||
yo += FONT_HEIGHT_SMALL;
|
||||
if (yo > SCREEN_HEIGHT - FONT_HEIGHT_SMALL) {
|
||||
xo += SCREEN_WIDTH / 2;
|
||||
@@ -467,8 +471,14 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, NodeStatus *no
|
||||
{
|
||||
char usersString[20];
|
||||
sprintf(usersString, "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
|
||||
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
||||
display->drawFastImage(x, y + 3, 8, 8, imgUser);
|
||||
#else
|
||||
display->drawFastImage(x, y, 8, 8, imgUser);
|
||||
#endif
|
||||
display->drawString(x + 10, y - 2, usersString);
|
||||
if(config.display.heading_bold)
|
||||
display->drawString(x + 11, y - 2, usersString);
|
||||
}
|
||||
|
||||
// Draw GPS status summary
|
||||
@@ -477,15 +487,21 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
|
||||
if (config.position.fixed_position) {
|
||||
// GPS coordinates are currently fixed
|
||||
display->drawString(x - 1, y - 2, "Fixed GPS");
|
||||
if(config.display.heading_bold)
|
||||
display->drawString(x, y - 2, "Fixed GPS");
|
||||
return;
|
||||
}
|
||||
if (!gps->getIsConnected()) {
|
||||
display->drawString(x, y - 2, "No GPS");
|
||||
if(config.display.heading_bold)
|
||||
display->drawString(x + 1, y - 2, "No GPS");
|
||||
return;
|
||||
}
|
||||
display->drawFastImage(x, y, 6, 8, gps->getHasLock() ? imgPositionSolid : imgPositionEmpty);
|
||||
if (!gps->getHasLock()) {
|
||||
display->drawString(x + 8, y - 2, "No sats");
|
||||
if(config.display.heading_bold)
|
||||
display->drawString(x + 9, y - 2, "No sats");
|
||||
return;
|
||||
} else {
|
||||
char satsString[3];
|
||||
@@ -507,9 +523,28 @@ static void drawGPS(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus
|
||||
// Draw the number of satellites
|
||||
sprintf(satsString, "%u", gps->getNumSatellites());
|
||||
display->drawString(x + 34, y - 2, satsString);
|
||||
if(config.display.heading_bold)
|
||||
display->drawString(x + 35, y - 2, satsString);
|
||||
}
|
||||
}
|
||||
|
||||
//Draw status when gps is disabled by PMU
|
||||
static void drawGPSpowerstat(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
||||
{
|
||||
#ifdef HAS_PMU
|
||||
String displayLine = "GPS disabled";
|
||||
int16_t xPos = display->getStringWidth(displayLine);
|
||||
|
||||
if (!config.position.gps_enabled){
|
||||
display->drawString(x + xPos, y, displayLine);
|
||||
#ifdef GPS_POWER_TOGGLE
|
||||
display->drawString(x + xPos, y - 2 + FONT_HEIGHT_SMALL, " by button");
|
||||
#endif
|
||||
//display->drawString(x + xPos, y + 2, displayLine);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void drawGPSAltitude(OLEDDisplay *display, int16_t x, int16_t y, const GPSStatus *gps)
|
||||
{
|
||||
String displayLine = "";
|
||||
@@ -542,9 +577,10 @@ static void drawGPScoordinates(OLEDDisplay *display, int16_t x, int16_t y, const
|
||||
display->drawString(x + (SCREEN_WIDTH - (display->getStringWidth(displayLine))) / 2, y, displayLine);
|
||||
} else {
|
||||
|
||||
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
|
||||
|
||||
if (gpsFormat != Config_DisplayConfig_GpsCoordinateFormat_DMS) {
|
||||
char coordinateLine[22];
|
||||
geoCoord.updateCoords(int32_t(gps->getLatitude()), int32_t(gps->getLongitude()), int32_t(gps->getAltitude()));
|
||||
if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_DEC) { // Decimal Degrees
|
||||
sprintf(coordinateLine, "%f %f", geoCoord.getLatitude() * 1e-7, geoCoord.getLongitude() * 1e-7);
|
||||
} else if (gpsFormat == Config_DisplayConfig_GpsCoordinateFormat_UTM) { // Universal Transverse Mercator
|
||||
@@ -671,17 +707,22 @@ static bool hasPosition(NodeInfo *n)
|
||||
static uint16_t getCompassDiam(OLEDDisplay *display)
|
||||
{
|
||||
uint16_t diam = 0;
|
||||
uint16_t offset = 0;
|
||||
|
||||
if (config.display.displaymode != Config_DisplayConfig_DisplayMode_DEFAULT)
|
||||
offset = FONT_HEIGHT_SMALL;
|
||||
|
||||
// get the smaller of the 2 dimensions and subtract 20
|
||||
if(display->getWidth() > display->getHeight()) {
|
||||
diam = display->getHeight();
|
||||
if(display->getWidth() > (display->getHeight() - offset)) {
|
||||
diam = display->getHeight() - offset;
|
||||
// if 2/3 of the other size would be smaller, use that
|
||||
if (diam > (display->getWidth() * 2 / 3)) {
|
||||
diam = display->getWidth() * 2 / 3;
|
||||
}
|
||||
} else {
|
||||
diam = display->getWidth();
|
||||
if (diam > (display->getHeight() * 2 / 3)) {
|
||||
diam = display->getHeight() * 2 / 3;
|
||||
if (diam > ((display->getHeight() - offset) * 2 / 3)) {
|
||||
diam = (display->getHeight() - offset) * 2 / 3;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -761,6 +802,10 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
// The coordinates define the left starting point of the text
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
if (config.display.displaymode == Config_DisplayConfig_DisplayMode_INVERTED) {
|
||||
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
||||
}
|
||||
|
||||
const char *username = node->has_user ? node->user.long_name : "Unknown Name";
|
||||
|
||||
static char signalStr[20];
|
||||
@@ -789,9 +834,16 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
strcpy(distStr, "? km"); // might not have location data
|
||||
NodeInfo *ourNode = nodeDB.getNode(nodeDB.getNodeNum());
|
||||
const char *fields[] = {username, distStr, signalStr, lastStr, NULL};
|
||||
int16_t compassX = 0, compassY = 0;
|
||||
|
||||
// coordinates for the center of the compass/circle
|
||||
int16_t compassX = x + SCREEN_WIDTH - getCompassDiam(display) / 2 - 5, compassY = y + SCREEN_HEIGHT / 2;
|
||||
if (config.display.displaymode == Config_DisplayConfig_DisplayMode_DEFAULT) {
|
||||
compassX = x + SCREEN_WIDTH - getCompassDiam(display) / 2 - 5;
|
||||
compassY = y + SCREEN_HEIGHT / 2;
|
||||
} else {
|
||||
compassX = x + SCREEN_WIDTH - getCompassDiam(display) / 2 - 5;
|
||||
compassY = y + FONT_HEIGHT_SMALL + (SCREEN_HEIGHT - FONT_HEIGHT_SMALL) / 2;
|
||||
}
|
||||
bool hasNodeHeading = false;
|
||||
|
||||
if (ourNode && hasPosition(ourNode)) {
|
||||
@@ -827,40 +879,21 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_
|
||||
drawNodeHeading(display, compassX, compassY, bearingToOther);
|
||||
}
|
||||
}
|
||||
if (!hasNodeHeading)
|
||||
if (!hasNodeHeading) {
|
||||
// direction to node is unknown so display question mark
|
||||
// Debug info for gps lock errors
|
||||
// DEBUG_MSG("ourNode %d, ourPos %d, theirPos %d\n", !!ourNode, ourNode && hasPosition(ourNode), hasPosition(node));
|
||||
// LOG_DEBUG("ourNode %d, ourPos %d, theirPos %d\n", !!ourNode, ourNode && hasPosition(ourNode), hasPosition(node));
|
||||
display->drawString(compassX - FONT_HEIGHT_SMALL / 4, compassY - FONT_HEIGHT_SMALL / 2, "?");
|
||||
}
|
||||
display->drawCircle(compassX, compassY, getCompassDiam(display) / 2);
|
||||
|
||||
if (config.display.displaymode == Config_DisplayConfig_DisplayMode_INVERTED) {
|
||||
display->setColor(BLACK);
|
||||
}
|
||||
// Must be after distStr is populated
|
||||
drawColumns(display, x, y, fields);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void _screen_header()
|
||||
{
|
||||
if (!disp)
|
||||
return;
|
||||
|
||||
// Message count
|
||||
//snprintf(buffer, sizeof(buffer), "#%03d", ttn_get_count() % 1000);
|
||||
//display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
//display->drawString(0, 2, buffer);
|
||||
|
||||
// Datetime
|
||||
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||
display->drawString(display->getWidth()/2, 2, gps.getTimeStr());
|
||||
|
||||
// Satellite count
|
||||
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||
char buffer[10];
|
||||
display->drawString(display->getWidth() - SATELLITE_IMAGE_WIDTH - 4, 2, itoa(gps.satellites.value(), buffer, 10));
|
||||
display->drawXbm(display->getWidth() - SATELLITE_IMAGE_WIDTH, 0, SATELLITE_IMAGE_WIDTH, SATELLITE_IMAGE_HEIGHT, SATELLITE_IMAGE);
|
||||
}
|
||||
#endif
|
||||
|
||||
// #ifdef RAK4630
|
||||
// Screen::Screen(uint8_t address, int sda, int scl) : OSThread("Screen"), cmdQueue(32), dispdev(address, sda, scl),
|
||||
// dispdev_oled(address, sda, scl), ui(&dispdev)
|
||||
@@ -903,14 +936,14 @@ void Screen::handleSetOn(bool on)
|
||||
|
||||
if (on != screenOn) {
|
||||
if (on) {
|
||||
DEBUG_MSG("Turning on screen\n");
|
||||
LOG_INFO("Turning on screen\n");
|
||||
dispdev.displayOn();
|
||||
dispdev.displayOn();
|
||||
enabled = true;
|
||||
setInterval(0); // Draw ASAP
|
||||
runASAP = true;
|
||||
} else {
|
||||
DEBUG_MSG("Turning off screen\n");
|
||||
LOG_INFO("Turning off screen\n");
|
||||
dispdev.displayOff();
|
||||
enabled = false;
|
||||
}
|
||||
@@ -928,9 +961,6 @@ void Screen::setup()
|
||||
dispdev.setDetected(screen_model);
|
||||
#endif
|
||||
|
||||
// Load OEM config from Proto file if existent
|
||||
loadProto(oemConfigFile, OEMStore_size, sizeof(oemConfigFile), OEMStore_fields, &oemStore);
|
||||
|
||||
// Initialising the UI will init the display too.
|
||||
ui.init();
|
||||
|
||||
@@ -951,6 +981,9 @@ void Screen::setup()
|
||||
// Set the utf8 conversion function
|
||||
dispdev.setFontTableLookupFunction(customFontTableLookup);
|
||||
|
||||
if (strlen(oemStore.oem_text) > 0)
|
||||
logo_timeout *= 2;
|
||||
|
||||
// Add frames.
|
||||
static FrameCallback bootFrames[] = {drawBootScreen};
|
||||
static const int bootFrameCount = sizeof(bootFrames) / sizeof(bootFrames[0]);
|
||||
@@ -1019,26 +1052,28 @@ int32_t Screen::runOnce()
|
||||
return RUN_SAME;
|
||||
}
|
||||
|
||||
// Show boot screen for first 5 seconds, then switch to normal operation.
|
||||
// Show boot screen for first logo_timeout seconds, then switch to normal operation.
|
||||
// serialSinceMsec adjusts for additional serial wait time during nRF52 bootup
|
||||
static bool showingBootScreen = true;
|
||||
if (showingBootScreen && (millis() > (5000 + serialSinceMsec))) {
|
||||
DEBUG_MSG("Done with boot screen...\n");
|
||||
if (showingBootScreen && (millis() > (logo_timeout + serialSinceMsec))) {
|
||||
LOG_INFO("Done with boot screen...\n");
|
||||
stopBootScreen();
|
||||
showingBootScreen = false;
|
||||
}
|
||||
|
||||
// If we have an OEM Boot screen, toggle after 2,5 seconds
|
||||
// If we have an OEM Boot screen, toggle after logo_timeout seconds
|
||||
if (strlen(oemStore.oem_text) > 0) {
|
||||
static bool showingOEMBootScreen = true;
|
||||
if (showingOEMBootScreen && (millis() > (2500 + serialSinceMsec))) {
|
||||
DEBUG_MSG("Switch to OEM screen...\n");
|
||||
if (showingOEMBootScreen && (millis() > ((logo_timeout / 2) + serialSinceMsec))) {
|
||||
LOG_INFO("Switch to OEM screen...\n");
|
||||
// Change frames.
|
||||
static FrameCallback bootOEMFrames[] = {drawOEMBootScreen};
|
||||
static const int bootOEMFrameCount = sizeof(bootOEMFrames) / sizeof(bootOEMFrames[0]);
|
||||
ui.setFrames(bootOEMFrames, bootOEMFrameCount);
|
||||
ui.update();
|
||||
#ifndef USE_EINK
|
||||
ui.update();
|
||||
#endif
|
||||
showingOEMBootScreen = false;
|
||||
}
|
||||
}
|
||||
@@ -1063,7 +1098,13 @@ int32_t Screen::runOnce()
|
||||
handleSetOn(false);
|
||||
break;
|
||||
case Cmd::ON_PRESS:
|
||||
handleOnPress();
|
||||
// If a nag notification is running, stop it
|
||||
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
|
||||
externalNotificationModule->stopNow();
|
||||
} else {
|
||||
// Don't advance the screen if we just wanted to switch off the nag notification
|
||||
handleOnPress();
|
||||
}
|
||||
break;
|
||||
case Cmd::START_BLUETOOTH_PIN_SCREEN:
|
||||
handleStartBluetoothPinScreen(cmd.bluetooth_pin);
|
||||
@@ -1086,7 +1127,7 @@ int32_t Screen::runOnce()
|
||||
handleRebootScreen();
|
||||
break;
|
||||
default:
|
||||
DEBUG_MSG("BUG: invalid cmd\n");
|
||||
LOG_ERROR("Invalid screen cmd\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1117,12 +1158,12 @@ int32_t Screen::runOnce()
|
||||
// standard screen loop handling here
|
||||
if (config.display.auto_screen_carousel_secs > 0 &&
|
||||
(millis() - lastScreenTransition) > (config.display.auto_screen_carousel_secs * 1000)) {
|
||||
DEBUG_MSG("LastScreenTransition exceeded %ums transitioning to next frame\n", (millis() - lastScreenTransition));
|
||||
LOG_DEBUG("LastScreenTransition exceeded %ums transitioning to next frame\n", (millis() - lastScreenTransition));
|
||||
handleOnPress();
|
||||
}
|
||||
}
|
||||
|
||||
// DEBUG_MSG("want fps %d, fixed=%d\n", targetFramerate,
|
||||
// LOG_DEBUG("want fps %d, fixed=%d\n", targetFramerate,
|
||||
// ui.getUiState()->frameState); If we are scrolling we need to be called
|
||||
// soon, otherwise just 1 fps (to save CPU) We also ask to be called twice
|
||||
// as fast as we really need so that any rounding errors still result with
|
||||
@@ -1153,7 +1194,7 @@ void Screen::drawDebugInfoWiFiTrampoline(OLEDDisplay *display, OLEDDisplayUiStat
|
||||
void Screen::setSSLFrames()
|
||||
{
|
||||
if (address_found) {
|
||||
// DEBUG_MSG("showing SSL frames\n");
|
||||
// LOG_DEBUG("showing SSL frames\n");
|
||||
static FrameCallback sslFrames[] = {drawSSLScreen};
|
||||
ui.setFrames(sslFrames, 1);
|
||||
ui.update();
|
||||
@@ -1165,7 +1206,7 @@ void Screen::setSSLFrames()
|
||||
void Screen::setWelcomeFrames()
|
||||
{
|
||||
if (address_found) {
|
||||
// DEBUG_MSG("showing Welcome frames\n");
|
||||
// LOG_DEBUG("showing Welcome frames\n");
|
||||
ui.disableAllIndicators();
|
||||
|
||||
static FrameCallback welcomeFrames[] = {drawWelcomeScreen};
|
||||
@@ -1177,13 +1218,13 @@ void Screen::setWelcomeFrames()
|
||||
// restore our regular frame list
|
||||
void Screen::setFrames()
|
||||
{
|
||||
DEBUG_MSG("showing standard frames\n");
|
||||
LOG_DEBUG("showing standard frames\n");
|
||||
showingNormalScreen = true;
|
||||
|
||||
moduleFrames = MeshModule::GetMeshModulesWithUIFrames();
|
||||
DEBUG_MSG("Showing %d module frames\n", moduleFrames.size());
|
||||
LOG_DEBUG("Showing %d module frames\n", moduleFrames.size());
|
||||
int totalFrameCount = MAX_NUM_NODES + NUM_EXTRA_FRAMES + moduleFrames.size();
|
||||
DEBUG_MSG("Total frame count: %d\n", totalFrameCount);
|
||||
LOG_DEBUG("Total frame count: %d\n", totalFrameCount);
|
||||
|
||||
// We don't show the node info our our node (if we have it yet - we should)
|
||||
size_t numnodes = nodeStatus->getNumTotal();
|
||||
@@ -1202,7 +1243,7 @@ void Screen::setFrames()
|
||||
normalFrames[numframes++] = drawModuleFrame;
|
||||
}
|
||||
|
||||
DEBUG_MSG("Added modules. numframes: %d\n", numframes);
|
||||
LOG_DEBUG("Added modules. numframes: %d\n", numframes);
|
||||
|
||||
// If we have a critical fault, show it first
|
||||
if (myNodeInfo.error_code)
|
||||
@@ -1235,7 +1276,7 @@ void Screen::setFrames()
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG_MSG("Finished building frames. numframes: %d\n", numframes);
|
||||
LOG_DEBUG("Finished building frames. numframes: %d\n", numframes);
|
||||
|
||||
ui.setFrames(normalFrames, numframes);
|
||||
ui.enableAllIndicators();
|
||||
@@ -1248,7 +1289,7 @@ void Screen::setFrames()
|
||||
|
||||
void Screen::handleStartBluetoothPinScreen(uint32_t pin)
|
||||
{
|
||||
DEBUG_MSG("showing bluetooth screen\n");
|
||||
LOG_DEBUG("showing bluetooth screen\n");
|
||||
showingNormalScreen = false;
|
||||
|
||||
static FrameCallback btFrames[] = {drawFrameBluetooth};
|
||||
@@ -1262,7 +1303,7 @@ void Screen::handleStartBluetoothPinScreen(uint32_t pin)
|
||||
|
||||
void Screen::handleShutdownScreen()
|
||||
{
|
||||
DEBUG_MSG("showing shutdown screen\n");
|
||||
LOG_DEBUG("showing shutdown screen\n");
|
||||
showingNormalScreen = false;
|
||||
|
||||
static FrameCallback shutdownFrames[] = {drawFrameShutdown};
|
||||
@@ -1274,7 +1315,7 @@ void Screen::handleShutdownScreen()
|
||||
|
||||
void Screen::handleRebootScreen()
|
||||
{
|
||||
DEBUG_MSG("showing reboot screen\n");
|
||||
LOG_DEBUG("showing reboot screen\n");
|
||||
showingNormalScreen = false;
|
||||
|
||||
static FrameCallback rebootFrames[] = {drawFrameReboot};
|
||||
@@ -1286,7 +1327,7 @@ void Screen::handleRebootScreen()
|
||||
|
||||
void Screen::handleStartFirmwareUpdateScreen()
|
||||
{
|
||||
DEBUG_MSG("showing firmware screen\n");
|
||||
LOG_DEBUG("showing firmware screen\n");
|
||||
showingNormalScreen = false;
|
||||
|
||||
static FrameCallback btFrames[] = {drawFrameFirmware};
|
||||
@@ -1317,7 +1358,7 @@ void Screen::handlePrint(const char *text)
|
||||
{
|
||||
// the string passed into us probably has a newline, but that would confuse the logging system
|
||||
// so strip it
|
||||
DEBUG_MSG("Screen: %.*s\n", strlen(text) - 1, text);
|
||||
LOG_DEBUG("Screen: %.*s\n", strlen(text) - 1, text);
|
||||
if (!useDisplay || !showingNormalScreen)
|
||||
return;
|
||||
|
||||
@@ -1358,6 +1399,11 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
// The coordinates define the left starting point of the text
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
if (config.display.displaymode == Config_DisplayConfig_DisplayMode_INVERTED) {
|
||||
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
||||
display->setColor(BLACK);
|
||||
}
|
||||
|
||||
char channelStr[20];
|
||||
{
|
||||
concurrency::LockGuard guard(&lock);
|
||||
@@ -1366,19 +1412,71 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
|
||||
}
|
||||
|
||||
// Display power status
|
||||
if (powerStatus->getHasBattery())
|
||||
drawBattery(display, x, y + 2, imgBattery, powerStatus);
|
||||
else if (powerStatus->knowsUSB())
|
||||
display->drawFastImage(x, y + 2, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower);
|
||||
if (powerStatus->getHasBattery()) {
|
||||
if (config.display.displaymode == Config_DisplayConfig_DisplayMode_DEFAULT) {
|
||||
drawBattery(display, x , y + 2, imgBattery, powerStatus);
|
||||
} else {
|
||||
drawBattery(display, x + 1, y + 3, imgBattery, powerStatus);
|
||||
}
|
||||
} else if (powerStatus->knowsUSB()) {
|
||||
if (config.display.displaymode == Config_DisplayConfig_DisplayMode_DEFAULT) {
|
||||
display->drawFastImage(x, y + 2, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower);
|
||||
} else {
|
||||
display->drawFastImage(x + 1, y + 3, 16, 8, powerStatus->getHasUSB() ? imgUSB : imgPower);
|
||||
}
|
||||
}
|
||||
// Display nodes status
|
||||
drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 2, nodeStatus);
|
||||
if (config.display.displaymode == Config_DisplayConfig_DisplayMode_DEFAULT) {
|
||||
drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 2, nodeStatus);
|
||||
} else {
|
||||
drawNodes(display, x + (SCREEN_WIDTH * 0.25), y + 3, nodeStatus);
|
||||
}
|
||||
// Display GPS status
|
||||
drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 2, gpsStatus);
|
||||
if (!config.position.gps_enabled){
|
||||
int16_t yPos = y + 2;
|
||||
#ifdef GPS_POWER_TOGGLE
|
||||
yPos = (y + 10 + FONT_HEIGHT_SMALL);
|
||||
#endif
|
||||
drawGPSpowerstat(display, x, yPos, gpsStatus);
|
||||
} else {
|
||||
if (config.display.displaymode == Config_DisplayConfig_DisplayMode_DEFAULT) {
|
||||
drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 2, gpsStatus);
|
||||
} else {
|
||||
drawGPS(display, x + (SCREEN_WIDTH * 0.63), y + 3, gpsStatus);
|
||||
}
|
||||
}
|
||||
|
||||
display->setColor(WHITE);
|
||||
// Draw the channel name
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL, channelStr);
|
||||
// Draw our hardware ID to assist with bluetooth pairing
|
||||
display->drawFastImage(x + SCREEN_WIDTH - (10) - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgInfo);
|
||||
// Draw our hardware ID to assist with bluetooth pairing. Either prefix with Info or S&F Logo
|
||||
if (moduleConfig.store_forward.enabled) {
|
||||
#ifdef ARCH_ESP32
|
||||
if (millis() - storeForwardModule->lastHeartbeat > (storeForwardModule->heartbeatInterval * 1200)) { //no heartbeat, overlap a bit
|
||||
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgQuestionL1);
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8, imgQuestionL2);
|
||||
#else
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgQuestion);
|
||||
#endif
|
||||
} else {
|
||||
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8, imgSFL1);
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 16, 8, imgSFL2);
|
||||
#else
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 13 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 11, 8, imgSF);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgInfoL1);
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8, imgInfoL2);
|
||||
#else
|
||||
display->drawFastImage(x + SCREEN_WIDTH - 10 - display->getStringWidth(ourId), y + 2 + FONT_HEIGHT_SMALL, 8, 8, imgInfo);
|
||||
#endif
|
||||
}
|
||||
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(ourId), y + FONT_HEIGHT_SMALL, ourId);
|
||||
|
||||
// Draw any log messages
|
||||
@@ -1397,7 +1495,6 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
{
|
||||
#if HAS_WIFI
|
||||
const char *wifiName = config.network.wifi_ssid;
|
||||
const char *wifiPsw = config.network.wifi_psk;
|
||||
|
||||
displayedNodeNum = 0; // Not currently showing a node pane
|
||||
|
||||
@@ -1406,19 +1503,30 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
// The coordinates define the left starting point of the text
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
if (isSoftAPForced()) {
|
||||
display->drawString(x, y, String("WiFi: Software AP (Admin)"));
|
||||
} else if (config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN) {
|
||||
display->drawString(x, y, String("WiFi: Software AP"));
|
||||
} else if (WiFi.status() != WL_CONNECTED) {
|
||||
if (config.display.displaymode == Config_DisplayConfig_DisplayMode_INVERTED) {
|
||||
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
||||
display->setColor(BLACK);
|
||||
}
|
||||
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
display->drawString(x, y, String("WiFi: Not Connected"));
|
||||
if(config.display.heading_bold)
|
||||
display->drawString(x + 1, y, String("WiFi: Not Connected"));
|
||||
} else {
|
||||
display->drawString(x, y, String("WiFi: Connected"));
|
||||
if(config.display.heading_bold)
|
||||
display->drawString(x + 1, y, String("WiFi: Connected"));
|
||||
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("RSSI " + String(WiFi.RSSI())), y,
|
||||
"RSSI " + String(WiFi.RSSI()));
|
||||
if(config.display.heading_bold) {
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("RSSI " + String(WiFi.RSSI())) - 1, y,
|
||||
"RSSI " + String(WiFi.RSSI()));
|
||||
}
|
||||
}
|
||||
|
||||
display->setColor(WHITE);
|
||||
|
||||
/*
|
||||
- WL_CONNECTED: assigned when connected to a WiFi network;
|
||||
- WL_NO_SSID_AVAIL: assigned when no SSID are available;
|
||||
@@ -1431,25 +1539,14 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
- WL_NO_SHIELD: assigned when no WiFi shield is present;
|
||||
|
||||
*/
|
||||
if (WiFi.status() == WL_CONNECTED || isSoftAPForced() || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN) {
|
||||
if (config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN || isSoftAPForced()) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.softAPIP().toString().c_str()));
|
||||
|
||||
// Number of connections to the AP. Default max for the esp32 is 4
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth("(" + String(WiFi.softAPgetStationNum()) + "/4)"),
|
||||
y + FONT_HEIGHT_SMALL * 1, "(" + String(WiFi.softAPgetStationNum()) + "/4)");
|
||||
} else {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.localIP().toString().c_str()));
|
||||
}
|
||||
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "IP: " + String(WiFi.localIP().toString().c_str()));
|
||||
} else if (WiFi.status() == WL_NO_SSID_AVAIL) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "SSID Not Found");
|
||||
} else if (WiFi.status() == WL_CONNECTION_LOST) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Lost");
|
||||
} else if (WiFi.status() == WL_CONNECT_FAILED) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Connection Failed");
|
||||
//} else if (WiFi.status() == WL_DISCONNECTED) {
|
||||
// display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Disconnected");
|
||||
} else if (WiFi.status() == WL_IDLE_STATUS) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 1, "Idle ... Reconnecting");
|
||||
} else {
|
||||
@@ -1516,24 +1613,8 @@ void DebugInfo::drawFrameWiFi(OLEDDisplay *display, OLEDDisplayUiState *state, i
|
||||
}
|
||||
}
|
||||
|
||||
if (isSoftAPForced()) {
|
||||
if ((millis() / 10000) % 2) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: meshtasticAdmin");
|
||||
} else {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "PWD: 12345678");
|
||||
}
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
|
||||
|
||||
} else {
|
||||
if (config.network.wifi_mode== Config_NetworkConfig_WiFiMode_ACCESS_POINT || config.network.wifi_mode == Config_NetworkConfig_WiFiMode_ACCESS_POINT_HIDDEN) {
|
||||
if ((millis() / 10000) % 2) {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
|
||||
} else {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "PWD: " + String(wifiPsw));
|
||||
}
|
||||
} else {
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 2, "SSID: " + String(wifiName));
|
||||
}
|
||||
}
|
||||
display->drawString(x, y + FONT_HEIGHT_SMALL * 3, "http://meshtastic.local");
|
||||
|
||||
/* Display a heartbeat pixel that blinks every time the frame is redrawn */
|
||||
@@ -1554,6 +1635,11 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
// The coordinates define the left starting point of the text
|
||||
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||
|
||||
if (config.display.displaymode == Config_DisplayConfig_DisplayMode_INVERTED) {
|
||||
display->fillRect(0 + x, 0 + y, x + display->getWidth(), y + FONT_HEIGHT_SMALL);
|
||||
display->setColor(BLACK);
|
||||
}
|
||||
|
||||
char batStr[20];
|
||||
if (powerStatus->getHasBattery()) {
|
||||
int batV = powerStatus->getBatteryVoltageMv() / 1000;
|
||||
@@ -1564,9 +1650,13 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
|
||||
// Line 1
|
||||
display->drawString(x, y, batStr);
|
||||
if(config.display.heading_bold)
|
||||
display->drawString(x + 1, y, batStr);
|
||||
} else {
|
||||
// Line 1
|
||||
display->drawString(x, y, String("USB"));
|
||||
if(config.display.heading_bold)
|
||||
display->drawString(x + 1, y, String("USB"));
|
||||
}
|
||||
|
||||
auto mode = "";
|
||||
@@ -1599,6 +1689,8 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
}
|
||||
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode), y, mode);
|
||||
if(config.display.heading_bold)
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(mode) - 1, y, mode);
|
||||
|
||||
// Line 2
|
||||
uint32_t currentMillis = millis();
|
||||
@@ -1611,6 +1703,8 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
// minutes %= 60;
|
||||
// hours %= 24;
|
||||
|
||||
display->setColor(WHITE);
|
||||
|
||||
// Show uptime as days, hours, minutes OR seconds
|
||||
String uptime;
|
||||
if (days >= 2)
|
||||
@@ -1646,7 +1740,7 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
char chUtil[13];
|
||||
sprintf(chUtil, "ChUtil %2.0f%%", airTime->channelUtilizationPercent());
|
||||
display->drawString(x + SCREEN_WIDTH - display->getStringWidth(chUtil), y + FONT_HEIGHT_SMALL * 1, chUtil);
|
||||
|
||||
if (config.position.gps_enabled) {
|
||||
// Line 3
|
||||
if (config.display.gps_format !=
|
||||
Config_DisplayConfig_GpsCoordinateFormat_DMS) // if DMS then don't draw altitude
|
||||
@@ -1654,7 +1748,9 @@ void DebugInfo::drawFrameSettings(OLEDDisplay *display, OLEDDisplayUiState *stat
|
||||
|
||||
// Line 4
|
||||
drawGPScoordinates(display, x, y + FONT_HEIGHT_SMALL * 3, gpsStatus);
|
||||
|
||||
} else {
|
||||
drawGPSpowerstat(display, x - (SCREEN_WIDTH / 4), y + FONT_HEIGHT_SMALL * 2, gpsStatus);
|
||||
}
|
||||
/* Display a heartbeat pixel that blinks every time the frame is redrawn */
|
||||
#ifdef SHOW_REDRAWS
|
||||
if (heartbeat)
|
||||
@@ -1682,7 +1778,7 @@ void Screen::adjustBrightness()
|
||||
|
||||
int Screen::handleStatusUpdate(const meshtastic::Status *arg)
|
||||
{
|
||||
// DEBUG_MSG("Screen got status update %d\n", arg->getStatusType());
|
||||
// LOG_DEBUG("Screen got status update %d\n", arg->getStatusType());
|
||||
switch (arg->getStatusType()) {
|
||||
case STATUS_TYPE_NODE:
|
||||
if (showingNormalScreen && nodeStatus->getLastNumTotal() != nodeStatus->getNumTotal()) {
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace graphics
|
||||
class Screen
|
||||
{
|
||||
public:
|
||||
Screen(char){}
|
||||
explicit Screen(char){}
|
||||
void onPress() {}
|
||||
void setup() {}
|
||||
void setOn(bool) {}
|
||||
@@ -21,6 +21,7 @@ class Screen
|
||||
void startBluetoothPinScreen(uint32_t pin) {}
|
||||
void stopBluetoothPinScreen() {}
|
||||
void startRebootScreen() {}
|
||||
void startFirmwareUpdateScreen() {}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -131,8 +132,7 @@ class Screen : public concurrency::OSThread
|
||||
void setOn(bool on)
|
||||
{
|
||||
if (!on)
|
||||
handleSetOn(
|
||||
false); // We handle off commands immediately, because they might be called because the CPU is shutting down
|
||||
handleSetOn(false); // We handle off commands immediately, because they might be called because the CPU is shutting down
|
||||
else
|
||||
enqueueCmd(ScreenCmd{.cmd = on ? Cmd::SET_ON : Cmd::SET_OFF});
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ void TFTDisplay::setDetected(uint8_t detected)
|
||||
bool TFTDisplay::connect()
|
||||
{
|
||||
concurrency::LockGuard g(spiLock);
|
||||
DEBUG_MSG("Doing TFT init\n");
|
||||
LOG_INFO("Doing TFT init\n");
|
||||
|
||||
#ifdef TFT_BL
|
||||
digitalWrite(TFT_BL, HIGH);
|
||||
|
||||
@@ -12,36 +12,18 @@ const uint8_t imgPower[] PROGMEM = { 0x40, 0x40, 0x40, 0x58, 0x48, 0x08,
|
||||
const uint8_t imgUser[] PROGMEM = { 0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3C };
|
||||
const uint8_t imgPositionEmpty[] PROGMEM = { 0x20, 0x30, 0x28, 0x24, 0x42, 0xFF };
|
||||
const uint8_t imgPositionSolid[] PROGMEM = { 0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF };
|
||||
const uint8_t imgInfo[] PROGMEM = { 0xFF, 0x81, 0x81, 0xB5, 0xB5, 0x81, 0x81, 0xFF };
|
||||
|
||||
#include "img/icon.xbm"
|
||||
|
||||
// We now programmatically draw our compass
|
||||
#if 0
|
||||
const
|
||||
#include "img/compass.xbm"
|
||||
#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS)
|
||||
const uint8_t imgQuestionL1[] PROGMEM = { 0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff };
|
||||
const uint8_t imgQuestionL2[] PROGMEM = { 0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f };
|
||||
const uint8_t imgInfoL1[] PROGMEM = { 0xff, 0x01, 0x01, 0x01, 0x1e, 0x7f, 0x1e, 0x01, 0x01, 0x01, 0x01, 0xff };
|
||||
const uint8_t imgInfoL2[] PROGMEM = { 0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f };
|
||||
const uint8_t imgSFL1[] PROGMEM = { 0xb6, 0x8f, 0x19, 0x11, 0x31, 0xe3, 0xc2, 0x01, 0x01, 0xf9, 0xf9, 0x89, 0x89, 0x89, 0x09, 0xeb};
|
||||
const uint8_t imgSFL2[] PROGMEM = { 0x0e, 0x09, 0x09, 0x09, 0x09, 0x09, 0x08, 0x08, 0x00, 0x0f, 0x0f, 0x00, 0x08, 0x08, 0x08, 0x0f};
|
||||
#else
|
||||
const uint8_t imgInfo[] PROGMEM = { 0xff, 0x81, 0x00, 0xfb, 0xfb, 0x00, 0x81, 0xff };
|
||||
const uint8_t imgQuestion[] PROGMEM = { 0xbf, 0x41, 0xc0, 0x8b, 0xdb, 0x70, 0xa1, 0xdf };
|
||||
const uint8_t imgSF[] PROGMEM = { 0xd2, 0xb7, 0xad, 0xbb, 0x92, 0x01, 0xfd, 0xfd, 0x15, 0x85, 0xf5};
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
const uint8_t activeSymbol[] PROGMEM = {
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00011000,
|
||||
B00100100,
|
||||
B01000010,
|
||||
B01000010,
|
||||
B00100100,
|
||||
B00011000
|
||||
};
|
||||
|
||||
const uint8_t inactiveSymbol[] PROGMEM = {
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00000000,
|
||||
B00011000,
|
||||
B00011000,
|
||||
B00000000,
|
||||
B00000000
|
||||
};
|
||||
#endif
|
||||
#include "img/icon.xbm"
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
#define compass_width 48
|
||||
#define compass_height 48
|
||||
static char compass_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x01, 0x00,
|
||||
0x00, 0xC0, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00,
|
||||
0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xFC, 0x07, 0xE0, 0x3F, 0x00,
|
||||
0x00, 0xFE, 0x01, 0x80, 0x7F, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7F, 0x00,
|
||||
0x00, 0x7F, 0x00, 0x00, 0xFE, 0x00, 0x80, 0x3F, 0x00, 0x00, 0xFC, 0x01,
|
||||
0x80, 0x1F, 0x00, 0x00, 0xF8, 0x01, 0x80, 0x0F, 0x00, 0x00, 0xF0, 0x01,
|
||||
0xC0, 0x0F, 0x00, 0x00, 0xF0, 0x03, 0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03,
|
||||
0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03,
|
||||
0xFC, 0x07, 0x00, 0x00, 0xE0, 0x3F, 0xFC, 0x07, 0x00, 0x00, 0xE0, 0x3F,
|
||||
0xFC, 0x07, 0x00, 0x00, 0xE0, 0x3F, 0xFC, 0x07, 0x00, 0x00, 0xE0, 0x3F,
|
||||
0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03,
|
||||
0xC0, 0x07, 0x00, 0x00, 0xE0, 0x03, 0xC0, 0x0F, 0x00, 0x00, 0xF0, 0x03,
|
||||
0x80, 0x0F, 0x00, 0x00, 0xF0, 0x01, 0x80, 0x1F, 0x00, 0x00, 0xF8, 0x01,
|
||||
0x80, 0x3F, 0x00, 0x00, 0xFC, 0x01, 0x00, 0x7F, 0x00, 0x00, 0xFE, 0x00,
|
||||
0x00, 0xFE, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xFE, 0x01, 0x80, 0x7F, 0x00,
|
||||
0x00, 0xFC, 0x07, 0xE0, 0x3F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00,
|
||||
0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0x03, 0x00,
|
||||
0x00, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00,
|
||||
0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
#define pin_width 13
|
||||
#define pin_height 13
|
||||
static char pin_bits[] = {
|
||||
0x00, 0x00, 0xF0, 0x01, 0xF8, 0x03, 0xFC, 0x07, 0xBC, 0x07, 0xBC, 0x07,
|
||||
0xFC, 0x07, 0xF8, 0x03, 0xF8, 0x03, 0xF0, 0x01, 0xE0, 0x00, 0xE0, 0x00,
|
||||
0x00, 0x00, };
|
||||
@@ -28,7 +28,7 @@ void RotaryEncoderInterruptBase::init(
|
||||
|
||||
this->rotaryLevelA = digitalRead(this->_pinA);
|
||||
this->rotaryLevelB = digitalRead(this->_pinB);
|
||||
DEBUG_MSG("Rotary initialized (%d, %d, %d)\n", this->_pinA, this->_pinB, pinPress);
|
||||
LOG_INFO("Rotary initialized (%d, %d, %d)\n", this->_pinA, this->_pinB, pinPress);
|
||||
}
|
||||
|
||||
int32_t RotaryEncoderInterruptBase::runOnce()
|
||||
@@ -38,13 +38,13 @@ int32_t RotaryEncoderInterruptBase::runOnce()
|
||||
e.source = this->_originName;
|
||||
|
||||
if (this->action == ROTARY_ACTION_PRESSED) {
|
||||
DEBUG_MSG("Rotary event Press\n");
|
||||
LOG_DEBUG("Rotary event Press\n");
|
||||
e.inputEvent = this->_eventPressed;
|
||||
} else if (this->action == ROTARY_ACTION_CW) {
|
||||
DEBUG_MSG("Rotary event CW\n");
|
||||
LOG_DEBUG("Rotary event CW\n");
|
||||
e.inputEvent = this->_eventCw;
|
||||
} else if (this->action == ROTARY_ACTION_CCW) {
|
||||
DEBUG_MSG("Rotary event CCW\n");
|
||||
LOG_DEBUG("Rotary event CCW\n");
|
||||
e.inputEvent = this->_eventCcw;
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ int32_t RotaryEncoderInterruptBase::runOnce()
|
||||
|
||||
this->action = ROTARY_ACTION_NONE;
|
||||
|
||||
return 30000; // TODO: technically this can be MAX_INT
|
||||
return INT32_MAX;
|
||||
}
|
||||
|
||||
void RotaryEncoderInterruptBase::intPressHandler()
|
||||
@@ -104,7 +104,7 @@ RotaryEncoderInterruptBaseStateType RotaryEncoderInterruptBase::intHandler(bool
|
||||
newState = ROTARY_EVENT_OCCURRED;
|
||||
if ((this->action != ROTARY_ACTION_PRESSED) && (this->action != action)) {
|
||||
this->action = action;
|
||||
DEBUG_MSG("Rotary action\n");
|
||||
LOG_DEBUG("Rotary action\n");
|
||||
}
|
||||
}
|
||||
} else if (!actualPinRaising && (otherPinLevel == HIGH)) {
|
||||
|
||||
@@ -7,7 +7,7 @@ enum RotaryEncoderInterruptBaseStateType { ROTARY_EVENT_OCCURRED, ROTARY_EVENT_C
|
||||
|
||||
enum RotaryEncoderInterruptBaseActionType { ROTARY_ACTION_NONE, ROTARY_ACTION_PRESSED, ROTARY_ACTION_CW, ROTARY_ACTION_CCW };
|
||||
|
||||
class RotaryEncoderInterruptBase : public Observable<const InputEvent *>, private concurrency::OSThread
|
||||
class RotaryEncoderInterruptBase : public Observable<const InputEvent *>, public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
explicit RotaryEncoderInterruptBase(const char *name);
|
||||
|
||||
@@ -9,6 +9,7 @@ void RotaryEncoderInterruptImpl1::init()
|
||||
{
|
||||
if (!moduleConfig.canned_message.rotary1_enabled) {
|
||||
// Input device is disabled.
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ void UpDownInterruptBase::init(
|
||||
attachInterrupt(this->_pinDown, onIntDown, RISING);
|
||||
attachInterrupt(this->_pinUp, onIntUp, RISING);
|
||||
|
||||
DEBUG_MSG("GPIO initialized (%d, %d, %d)\n",
|
||||
LOG_DEBUG("GPIO initialized (%d, %d, %d)\n",
|
||||
this->_pinDown, this->_pinUp, pinPress);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ void UpDownInterruptBase::intPressHandler()
|
||||
{
|
||||
InputEvent e;
|
||||
e.source = this->_originName;
|
||||
DEBUG_MSG("GPIO event Press\n");
|
||||
LOG_DEBUG("GPIO event Press\n");
|
||||
e.inputEvent = this->_eventPressed;
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
@@ -43,7 +43,7 @@ void UpDownInterruptBase::intDownHandler()
|
||||
{
|
||||
InputEvent e;
|
||||
e.source = this->_originName;
|
||||
DEBUG_MSG("GPIO event Down\n");
|
||||
LOG_DEBUG("GPIO event Down\n");
|
||||
e.inputEvent = this->_eventDown;
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
@@ -52,7 +52,7 @@ void UpDownInterruptBase::intUpHandler()
|
||||
{
|
||||
InputEvent e;
|
||||
e.source = this->_originName;
|
||||
DEBUG_MSG("GPIO event Up\n");
|
||||
LOG_DEBUG("GPIO event Up\n");
|
||||
e.inputEvent = this->_eventUp;
|
||||
this->notifyObservers(&e);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ void CardKbI2cImpl::init()
|
||||
{
|
||||
if (cardkb_found != CARDKB_ADDR)
|
||||
{
|
||||
// Input device is not detected.
|
||||
disable();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ int32_t KbI2cBase::runOnce()
|
||||
}
|
||||
}
|
||||
if (PrintDataBuf != 0) {
|
||||
DEBUG_MSG("RAK14004 key 0x%x pressed\n", PrintDataBuf);
|
||||
LOG_DEBUG("RAK14004 key 0x%x pressed\n", PrintDataBuf);
|
||||
InputEvent e;
|
||||
e.inputEvent = MATRIXKEY;
|
||||
e.source = this->_originName;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
class KbI2cBase :
|
||||
public Observable<const InputEvent *>,
|
||||
private concurrency::OSThread
|
||||
public concurrency::OSThread
|
||||
{
|
||||
public:
|
||||
explicit KbI2cBase(const char *name);
|
||||
|
||||
142
src/main.cpp
142
src/main.cpp
@@ -8,8 +8,6 @@
|
||||
#include "configuration.h"
|
||||
#include "error.h"
|
||||
#include "power.h"
|
||||
// #include "rom/rtc.h"
|
||||
//#include "DSRRouter.h"
|
||||
#include "ReliableRouter.h"
|
||||
// #include "debug.h"
|
||||
#include "FSCommon.h"
|
||||
@@ -30,21 +28,28 @@
|
||||
// #include <driver/rtc_io.h>
|
||||
|
||||
#include "mesh/http/WiFiAPClient.h"
|
||||
#include "mesh/eth/ethClient.h"
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
#include "mesh/http/WebServer.h"
|
||||
#include "nimble/NimbleBluetooth.h"
|
||||
#endif
|
||||
|
||||
#if HAS_WIFI || defined(ARCH_PORTDUINO)
|
||||
#if HAS_WIFI
|
||||
#include "mesh/wifi/WiFiServerAPI.h"
|
||||
#include "mqtt/MQTT.h"
|
||||
#endif
|
||||
|
||||
#if HAS_ETHERNET
|
||||
#include "mesh/eth/ethServerAPI.h"
|
||||
#include "mqtt/MQTT.h"
|
||||
#endif
|
||||
|
||||
#include "LLCC68Interface.h"
|
||||
#include "RF95Interface.h"
|
||||
#include "SX1262Interface.h"
|
||||
#include "SX1268Interface.h"
|
||||
#include "SX1280Interface.h"
|
||||
#if !HAS_RADIO && defined(ARCH_PORTDUINO)
|
||||
#include "platform/portduino/SimRadio.h"
|
||||
#endif
|
||||
@@ -93,7 +98,7 @@ uint32_t serialSinceMsec;
|
||||
bool pmu_found;
|
||||
|
||||
// Array map of sensor types (as array index) and i2c address as value we'll find in the i2c scan
|
||||
uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658+1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
uint8_t nodeTelemetrySensorsMap[_TelemetrySensorType_MAX + 1] = { 0 }; // one is enough, missing elements will be initialized to 0 anyway.
|
||||
|
||||
Router *router = NULL; // Users of router don't care what sort of subclass implements that API
|
||||
|
||||
@@ -133,8 +138,9 @@ bool ButtonThread::shutdown_on_long_stop = false;
|
||||
#endif
|
||||
|
||||
static Periodic *ledPeriodic;
|
||||
static OSThread *powerFSMthread, *buttonThread;
|
||||
static OSThread *powerFSMthread;
|
||||
#if HAS_BUTTON
|
||||
static OSThread *buttonThread;
|
||||
uint32_t ButtonThread::longPressTime = 0;
|
||||
#endif
|
||||
|
||||
@@ -168,7 +174,7 @@ void setup()
|
||||
|
||||
serialSinceMsec = millis();
|
||||
|
||||
DEBUG_MSG("\n\n//\\ E S H T /\\ S T / C\n\n");
|
||||
LOG_INFO("\n\n//\\ E S H T /\\ S T / C\n\n");
|
||||
|
||||
initDeepSleep();
|
||||
|
||||
@@ -188,8 +194,6 @@ void setup()
|
||||
digitalWrite(RESET_OLED, 1);
|
||||
#endif
|
||||
|
||||
bool forceSoftAP = 0;
|
||||
|
||||
#ifdef BUTTON_PIN
|
||||
#ifdef ARCH_ESP32
|
||||
|
||||
@@ -202,12 +206,6 @@ void setup()
|
||||
delay(10);
|
||||
#endif
|
||||
|
||||
// BUTTON_PIN is pulled high by a 12k resistor.
|
||||
if (!digitalRead(BUTTON_PIN)) {
|
||||
forceSoftAP = 1;
|
||||
DEBUG_MSG("Setting forceSoftAP = 1\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -217,7 +215,6 @@ void setup()
|
||||
|
||||
fsInit();
|
||||
|
||||
// router = new DSRRouter();
|
||||
router = new ReliableRouter();
|
||||
|
||||
#ifdef I2C_SDA1
|
||||
@@ -239,8 +236,37 @@ void setup()
|
||||
delay(1);
|
||||
#endif
|
||||
|
||||
#ifdef RAK4630
|
||||
// We need to enable 3.3V periphery in order to scan it
|
||||
pinMode(PIN_3V3_EN, OUTPUT);
|
||||
digitalWrite(PIN_3V3_EN, 1);
|
||||
#endif
|
||||
|
||||
// Currently only the tbeam has a PMU
|
||||
// PMU initialization needs to be placed before scanI2Cdevice
|
||||
power = new Power();
|
||||
power->setStatusHandler(powerStatus);
|
||||
powerStatus->observe(&power->newStatus);
|
||||
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
|
||||
|
||||
|
||||
#ifdef LILYGO_TBEAM_S3_CORE
|
||||
// In T-Beam-S3-core, the I2C device cannot be scanned before power initialization, otherwise the device will be stuck
|
||||
// PCF8563 RTC in tbeam-s3 uses Wire1 to share I2C bus
|
||||
Wire1.beginTransmission(PCF8563_RTC);
|
||||
if (Wire1.endTransmission() == 0){
|
||||
rtc_found = PCF8563_RTC;
|
||||
LOG_INFO("PCF8563 RTC found\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
// We need to scan here to decide if we have a screen for nodeDB.init()
|
||||
scanI2Cdevice();
|
||||
|
||||
#ifdef HAS_SDCARD
|
||||
setupSDCard();
|
||||
#endif
|
||||
|
||||
#ifdef RAK4630
|
||||
// scanEInkDevice();
|
||||
#endif
|
||||
@@ -256,7 +282,7 @@ void setup()
|
||||
#endif
|
||||
|
||||
// Hello
|
||||
DEBUG_MSG("Meshtastic hwvendor=%d, swver=%s\n", HW_VENDOR, optstr(APP_VERSION));
|
||||
LOG_INFO("Meshtastic hwvendor=%d, swver=%s\n", HW_VENDOR, optstr(APP_VERSION));
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// Don't init display if we don't have one or we are waking headless due to a timer event
|
||||
@@ -269,23 +295,16 @@ void setup()
|
||||
#ifdef ARCH_NRF52
|
||||
nrf52Setup();
|
||||
#endif
|
||||
playStartMelody();
|
||||
// We do this as early as possible because this loads preferences from flash
|
||||
// but we need to do this after main cpu iniot (esp32setup), because we need the random seed set
|
||||
nodeDB.init();
|
||||
|
||||
// Currently only the tbeam has a PMU
|
||||
power = new Power();
|
||||
power->setStatusHandler(powerStatus);
|
||||
powerStatus->observe(&power->newStatus);
|
||||
power->setup(); // Must be after status handler is installed, so that handler gets notified of the initial configuration
|
||||
playStartMelody();
|
||||
|
||||
// fixed screen override?
|
||||
if (config.display.oled != Config_DisplayConfig_OledType_OLED_AUTO)
|
||||
screen_model = config.display.oled;
|
||||
|
||||
/*
|
||||
* Repeat the scanning for I2C devices after power initialization or look for 'latecomers'.
|
||||
* Boards with an PMU need to be powered on to correctly scan to the device address, such as t-beam-s3-core
|
||||
*/
|
||||
scanI2Cdevice();
|
||||
|
||||
// Init our SPI controller (must be before screen and lora)
|
||||
initSPI();
|
||||
#ifndef ARCH_ESP32
|
||||
@@ -306,7 +325,7 @@ void setup()
|
||||
if (gps)
|
||||
gpsStatus->observe(&gps->newStatus);
|
||||
else
|
||||
DEBUG_MSG("Warning: No GPS found - running without GPS\n");
|
||||
LOG_WARN("No GPS found - running without GPS\n");
|
||||
|
||||
nodeStatus->observe(&nodeDB.newStatus);
|
||||
|
||||
@@ -336,7 +355,7 @@ void setup()
|
||||
|
||||
// ONCE we will factory reset the GPS for bug #327
|
||||
if (gps && !devicestate.did_gps_reset) {
|
||||
DEBUG_MSG("GPS FactoryReset requested\n");
|
||||
LOG_WARN("GPS FactoryReset requested\n");
|
||||
if (gps->factoryReset()) { // If we don't succeed try again next time
|
||||
devicestate.did_gps_reset = true;
|
||||
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
|
||||
@@ -355,11 +374,24 @@ void setup()
|
||||
if (!rIf) {
|
||||
rIf = new RF95Interface(RF95_NSS, RF95_IRQ, RF95_RESET, SPI);
|
||||
if (!rIf->init()) {
|
||||
DEBUG_MSG("Warning: Failed to find RF95 radio\n");
|
||||
LOG_WARN("Failed to find RF95 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
DEBUG_MSG("RF95 Radio init succeeded, using RF95 radio\n");
|
||||
LOG_INFO("RF95 Radio init succeeded, using RF95 radio\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_SX1280)
|
||||
if (!rIf) {
|
||||
rIf = new SX1280Interface(SX128X_CS, SX128X_DIO1, SX128X_RESET, SX128X_BUSY, SPI);
|
||||
if (!rIf->init()) {
|
||||
LOG_WARN("Failed to find SX1280 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
LOG_INFO("SX1280 Radio init succeeded, using SX1280 radio\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -368,11 +400,11 @@ void setup()
|
||||
if (!rIf) {
|
||||
rIf = new SX1262Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
|
||||
if (!rIf->init()) {
|
||||
DEBUG_MSG("Warning: Failed to find SX1262 radio\n");
|
||||
LOG_WARN("Failed to find SX1262 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
DEBUG_MSG("SX1262 Radio init succeeded, using SX1262 radio\n");
|
||||
LOG_INFO("SX1262 Radio init succeeded, using SX1262 radio\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -381,11 +413,11 @@ void setup()
|
||||
if (!rIf) {
|
||||
rIf = new SX1268Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
|
||||
if (!rIf->init()) {
|
||||
DEBUG_MSG("Warning: Failed to find SX1268 radio\n");
|
||||
LOG_WARN("Failed to find SX1268 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
DEBUG_MSG("SX1268 Radio init succeeded, using SX1268 radio\n");
|
||||
LOG_INFO("SX1268 Radio init succeeded, using SX1268 radio\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -394,11 +426,11 @@ void setup()
|
||||
if (!rIf) {
|
||||
rIf = new LLCC68Interface(SX126X_CS, SX126X_DIO1, SX126X_RESET, SX126X_BUSY, SPI);
|
||||
if (!rIf->init()) {
|
||||
DEBUG_MSG("Warning: Failed to find LLCC68 radio\n");
|
||||
LOG_WARN("Failed to find LLCC68 radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
DEBUG_MSG("LLCC68 Radio init succeeded, using LLCC68 radio\n");
|
||||
LOG_INFO("LLCC68 Radio init succeeded, using LLCC68 radio\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -407,21 +439,39 @@ void setup()
|
||||
if (!rIf) {
|
||||
rIf = new SimRadio;
|
||||
if (!rIf->init()) {
|
||||
DEBUG_MSG("Warning: Failed to find simulated radio\n");
|
||||
LOG_WARN("Failed to find simulated radio\n");
|
||||
delete rIf;
|
||||
rIf = NULL;
|
||||
} else {
|
||||
DEBUG_MSG("Using SIMULATED radio!\n");
|
||||
LOG_INFO("Using SIMULATED radio!\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAS_WIFI
|
||||
// check if the radio chip matches the selected region
|
||||
|
||||
if((config.lora.region == Config_LoRaConfig_RegionCode_LORA_24) && (!rIf->wideLora())){
|
||||
LOG_WARN("Radio chip does not support 2.4GHz LoRa. Reverting to unset.\n");
|
||||
config.lora.region = Config_LoRaConfig_RegionCode_UNSET;
|
||||
nodeDB.saveToDisk(SEGMENT_CONFIG);
|
||||
if(!rIf->reconfigure()) {
|
||||
LOG_WARN("Reconfigure failed, rebooting\n");
|
||||
screen->startRebootScreen();
|
||||
rebootAtMsec = millis() + 5000;
|
||||
}
|
||||
}
|
||||
|
||||
#if HAS_WIFI || HAS_ETHERNET
|
||||
mqttInit();
|
||||
#endif
|
||||
|
||||
#ifndef ARCH_PORTDUINO
|
||||
// Initialize Wifi
|
||||
initWifi(forceSoftAP);
|
||||
initWifi();
|
||||
|
||||
// Initialize Ethernet
|
||||
initEthernet();
|
||||
#endif
|
||||
|
||||
#ifdef ARCH_ESP32
|
||||
// Start web server thread.
|
||||
@@ -443,7 +493,7 @@ void setup()
|
||||
// Calculate and save the bit rate to myNodeInfo
|
||||
// TODO: This needs to be added what ever method changes the channel from the phone.
|
||||
myNodeInfo.bitrate = (float(Constants_DATA_PAYLOAD_LEN) / (float(rIf->getPacketTime(Constants_DATA_PAYLOAD_LEN)))) * 1000;
|
||||
DEBUG_MSG("myNodeInfo.bitrate = %f bytes / sec\n", myNodeInfo.bitrate);
|
||||
LOG_DEBUG("myNodeInfo.bitrate = %f bytes / sec\n", myNodeInfo.bitrate);
|
||||
}
|
||||
|
||||
// This must be _after_ service.init because we need our preferences loaded from flash to have proper timeout values
|
||||
@@ -496,13 +546,13 @@ void loop()
|
||||
long delayMsec = mainController.runOrDelay();
|
||||
|
||||
/* if (mainController.nextThread && delayMsec)
|
||||
DEBUG_MSG("Next %s in %ld\n", mainController.nextThread->ThreadName.c_str(),
|
||||
LOG_DEBUG("Next %s in %ld\n", mainController.nextThread->ThreadName.c_str(),
|
||||
mainController.nextThread->tillRun(millis())); */
|
||||
|
||||
// We want to sleep as long as possible here - because it saves power
|
||||
if (!runASAP && loopCanSleep()) {
|
||||
// if(delayMsec > 100) DEBUG_MSG("sleeping %ld\n", delayMsec);
|
||||
// if(delayMsec > 100) LOG_DEBUG("sleeping %ld\n", delayMsec);
|
||||
mainDelay.delay(delayMsec);
|
||||
}
|
||||
// if (didWake) DEBUG_MSG("wake!\n");
|
||||
// if (didWake) LOG_DEBUG("wake!\n");
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "PowerStatus.h"
|
||||
#include "graphics/Screen.h"
|
||||
#include "mesh/generated/telemetry.pb.h"
|
||||
#ifndef ARCH_PORTDUINO
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
#include <SparkFun_ATECCX08a_Arduino_Library.h>
|
||||
#endif
|
||||
|
||||
@@ -22,11 +22,11 @@ extern bool pmu_found;
|
||||
extern bool isCharging;
|
||||
extern bool isUSBPowered;
|
||||
|
||||
#ifndef ARCH_PORTDUINO
|
||||
#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
|
||||
extern ATECCX08A atecc;
|
||||
#endif
|
||||
|
||||
extern uint8_t nodeTelemetrySensorsMap[TelemetrySensorType_QMI8658+1];
|
||||
extern uint8_t nodeTelemetrySensorsMap[_TelemetrySensorType_MAX + 1];
|
||||
|
||||
extern int TCPPort; // set by Portduino
|
||||
|
||||
|
||||
@@ -255,10 +255,10 @@ static int mem_test(uint32_t *_start, size_t len, bool doRead = true, bool doWri
|
||||
int rcode = 0;
|
||||
incr = 1;
|
||||
|
||||
//DEBUG_MSG("memtest read=%d, write=%d\n", doRead, doWrite);
|
||||
//LOG_DEBUG("memtest read=%d, write=%d\n", doRead, doWrite);
|
||||
|
||||
if (doWrite) {
|
||||
//DEBUG_MSG("writing\n");
|
||||
//LOG_DEBUG("writing\n");
|
||||
for (addr = start, val = pattern; addr < end; addr++) {
|
||||
*addr = val;
|
||||
val += incr;
|
||||
@@ -266,11 +266,11 @@ static int mem_test(uint32_t *_start, size_t len, bool doRead = true, bool doWri
|
||||
}
|
||||
|
||||
if (doRead) {
|
||||
//DEBUG_MSG("reading\n");
|
||||
//LOG_DEBUG("reading\n");
|
||||
for (addr = start, val = pattern; addr < end; addr++) {
|
||||
readback = *addr;
|
||||
if (readback != val) {
|
||||
DEBUG_MSG("Mem error @ 0x%08X: "
|
||||
LOG_ERROR("Mem error @ 0x%08X: "
|
||||
"found 0x%08lX, expected 0x%08lX\n",
|
||||
addr, readback, val);
|
||||
rcode++;
|
||||
|
||||
@@ -62,13 +62,6 @@ Channel &Channels::fixupChannel(ChannelIndex chIndex)
|
||||
// Convert the old string "Default" to our new short representation
|
||||
if (strcmp(channelSettings.name, "Default") == 0)
|
||||
*channelSettings.name = '\0';
|
||||
|
||||
/* Convert any old usage of the defaultpsk into our new short representation.
|
||||
if (channelSettings.psk.size == sizeof(defaultpsk) &&
|
||||
memcmp(channelSettings.psk.bytes, defaultpsk, sizeof(defaultpsk)) == 0) {
|
||||
*channelSettings.psk.bytes = 1;
|
||||
channelSettings.psk.size = 1;
|
||||
} */
|
||||
}
|
||||
|
||||
hashes[chIndex] = generateHash(chIndex);
|
||||
@@ -86,7 +79,7 @@ void Channels::initDefaultChannel(ChannelIndex chIndex)
|
||||
Config_LoRaConfig &loraConfig = config.lora;
|
||||
|
||||
loraConfig.modem_preset = Config_LoRaConfig_ModemPreset_LONG_FAST; // Default to Long Range & Fast
|
||||
|
||||
loraConfig.use_preset = true;
|
||||
loraConfig.tx_power = 0; // default
|
||||
uint8_t defaultpskIndex = 1;
|
||||
channelSettings.psk.bytes[0] = defaultpskIndex;
|
||||
@@ -113,18 +106,33 @@ CryptoKey Channels::getKey(ChannelIndex chIndex)
|
||||
k.length = channelSettings.psk.size;
|
||||
if (k.length == 0) {
|
||||
if (ch.role == Channel_Role_SECONDARY) {
|
||||
DEBUG_MSG("Unset PSK for secondary channel %s. using primary key\n", ch.settings.name);
|
||||
LOG_DEBUG("Unset PSK for secondary channel %s. using primary key\n", ch.settings.name);
|
||||
k = getKey(primaryIndex);
|
||||
} else
|
||||
DEBUG_MSG("Warning: User disabled encryption\n");
|
||||
LOG_WARN("User disabled encryption\n");
|
||||
} else if (k.length == 1) {
|
||||
// Convert the short single byte variants of psk into variant that can be used more generally
|
||||
|
||||
uint8_t pskIndex = k.bytes[0];
|
||||
DEBUG_MSG("Expanding short PSK #%d\n", pskIndex);
|
||||
LOG_DEBUG("Expanding short PSK #%d\n", pskIndex);
|
||||
if (pskIndex == 0)
|
||||
k.length = 0; // Turn off encryption
|
||||
else {
|
||||
else if (oemStore.oem_aes_key.size > 1) {
|
||||
// Use the OEM key
|
||||
LOG_DEBUG("Using OEM Key with %d bytes\n", oemStore.oem_aes_key.size);
|
||||
memcpy(k.bytes, oemStore.oem_aes_key.bytes , oemStore.oem_aes_key.size);
|
||||
k.length = oemStore.oem_aes_key.size;
|
||||
// Bump up the last byte of PSK as needed
|
||||
uint8_t *last = k.bytes + oemStore.oem_aes_key.size - 1;
|
||||
*last = *last + pskIndex - 1; // index of 1 means no change vs defaultPSK
|
||||
if (k.length < 16) {
|
||||
LOG_WARN("OEM provided a too short AES128 key - padding\n");
|
||||
k.length = 16;
|
||||
} else if (k.length < 32 && k.length != 16) {
|
||||
LOG_WARN("OEM provided a too short AES256 key - padding\n");
|
||||
k.length = 32;
|
||||
}
|
||||
} else {
|
||||
memcpy(k.bytes, defaultpsk, sizeof(defaultpsk));
|
||||
k.length = sizeof(defaultpsk);
|
||||
// Bump up the last byte of PSK as needed
|
||||
@@ -134,12 +142,12 @@ CryptoKey Channels::getKey(ChannelIndex chIndex)
|
||||
} else if (k.length < 16) {
|
||||
// Error! The user specified only the first few bits of an AES128 key. So by convention we just pad the rest of the
|
||||
// key with zeros
|
||||
DEBUG_MSG("Warning: User provided a too short AES128 key - padding\n");
|
||||
LOG_WARN("User provided a too short AES128 key - padding\n");
|
||||
k.length = 16;
|
||||
} else if (k.length < 32 && k.length != 16) {
|
||||
// Error! The user specified only the first few bits of an AES256 key. So by convention we just pad the rest of the
|
||||
// key with zeros
|
||||
DEBUG_MSG("Warning: User provided a too short AES256 key - padding\n");
|
||||
LOG_WARN("User provided a too short AES256 key - padding\n");
|
||||
k.length = 32;
|
||||
}
|
||||
}
|
||||
@@ -188,6 +196,17 @@ Channel &Channels::getByIndex(ChannelIndex chIndex)
|
||||
return *ch;
|
||||
}
|
||||
|
||||
Channel &Channels::getByName(const char* chName)
|
||||
{
|
||||
for (ChannelIndex i = 0; i < getNumChannels(); i++) {
|
||||
if (strcasecmp(channelFile.channels[i].settings.name, chName) == 0) {
|
||||
return channelFile.channels[i];
|
||||
}
|
||||
}
|
||||
|
||||
return getByIndex(getPrimaryIndex());
|
||||
}
|
||||
|
||||
void Channels::setChannel(const Channel &c)
|
||||
{
|
||||
Channel &old = getByIndex(c.index);
|
||||
@@ -210,9 +229,7 @@ const char *Channels::getName(size_t chIndex)
|
||||
// Per mesh.proto spec, if bandwidth is specified we must ignore modemPreset enum, we assume that in that case
|
||||
// the app fucked up and forgot to set channelSettings.name
|
||||
|
||||
if (config.lora.bandwidth != 0)
|
||||
channelName = "Custom";
|
||||
else
|
||||
if (config.lora.use_preset) {
|
||||
switch (config.lora.modem_preset) {
|
||||
case Config_LoRaConfig_ModemPreset_SHORT_SLOW:
|
||||
channelName = "ShortSlow";
|
||||
@@ -239,6 +256,10 @@ const char *Channels::getName(size_t chIndex)
|
||||
channelName = "Invalid";
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
channelName = "Custom";
|
||||
}
|
||||
}
|
||||
|
||||
return channelName;
|
||||
@@ -257,7 +278,7 @@ their nodes
|
||||
*
|
||||
* This function will also need to be implemented in GUI apps that talk to the radio.
|
||||
*
|
||||
* https://github.com/meshtastic/Meshtastic-device/issues/269
|
||||
* https://github.com/meshtastic/firmware/issues/269
|
||||
*/
|
||||
const char *Channels::getPrimaryName()
|
||||
{
|
||||
@@ -287,11 +308,11 @@ const char *Channels::getPrimaryName()
|
||||
bool Channels::decryptForHash(ChannelIndex chIndex, ChannelHash channelHash)
|
||||
{
|
||||
if (chIndex > getNumChannels() || getHash(chIndex) != channelHash) {
|
||||
// DEBUG_MSG("Skipping channel %d (hash %x) due to invalid hash/index, want=%x\n", chIndex, getHash(chIndex),
|
||||
// LOG_DEBUG("Skipping channel %d (hash %x) due to invalid hash/index, want=%x\n", chIndex, getHash(chIndex),
|
||||
// channelHash);
|
||||
return false;
|
||||
} else {
|
||||
DEBUG_MSG("Using channel %d (hash 0x%x)\n", chIndex, channelHash);
|
||||
LOG_DEBUG("Using channel %d (hash 0x%x)\n", chIndex, channelHash);
|
||||
setCrypto(chIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,9 @@ class Channels
|
||||
/** Return the Channel for a specified index */
|
||||
Channel &getByIndex(ChannelIndex chIndex);
|
||||
|
||||
/** Return the Channel for a specified name, return primary if not found. */
|
||||
Channel &getByName(const char* chName);
|
||||
|
||||
/** Using the index inside the channel, update the specified channel's settings and role. If this channel is being promoted
|
||||
* to be primary, force all other channels to be secondary.
|
||||
*/
|
||||
@@ -74,7 +77,7 @@ class Channels
|
||||
*
|
||||
* This function will also need to be implemented in GUI apps that talk to the radio.
|
||||
*
|
||||
* https://github.com/meshtastic/Meshtastic-device/issues/269
|
||||
* https://github.com/meshtastic/firmware/issues/269
|
||||
*/
|
||||
const char *getPrimaryName();
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
void CryptoEngine::setKey(const CryptoKey &k)
|
||||
{
|
||||
DEBUG_MSG("Using AES%d key!\n", k.length * 8);
|
||||
LOG_DEBUG("Using AES%d key!\n", k.length * 8);
|
||||
key = k;
|
||||
}
|
||||
|
||||
@@ -14,12 +14,12 @@ void CryptoEngine::setKey(const CryptoKey &k)
|
||||
*/
|
||||
void CryptoEngine::encrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes)
|
||||
{
|
||||
DEBUG_MSG("WARNING: noop encryption!\n");
|
||||
LOG_WARN("noop encryption!\n");
|
||||
}
|
||||
|
||||
void CryptoEngine::decrypt(uint32_t fromNode, uint64_t packetId, size_t numBytes, uint8_t *bytes)
|
||||
{
|
||||
DEBUG_MSG("WARNING: noop decryption!\n");
|
||||
LOG_WARN("noop decryption!\n");
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ ErrorCode FloodingRouter::send(MeshPacket *p)
|
||||
return Router::send(p);
|
||||
}
|
||||
|
||||
bool FloodingRouter::shouldFilterReceived(MeshPacket *p)
|
||||
bool FloodingRouter::shouldFilterReceived(const MeshPacket *p)
|
||||
{
|
||||
if (wasSeenRecently(p)) { // Note: this will also add a recent packet record
|
||||
printPacket("Ignoring incoming msg, because we've already seen it", p);
|
||||
@@ -29,29 +29,35 @@ bool FloodingRouter::shouldFilterReceived(MeshPacket *p)
|
||||
|
||||
void FloodingRouter::sniffReceived(const MeshPacket *p, const Routing *c)
|
||||
{
|
||||
PacketId ackId = ((c && c->error_reason == Routing_Error_NONE) || !c) ? p->decoded.request_id : 0;
|
||||
if (ackId && p->to != getNodeNum()) {
|
||||
bool isAck = ((c && c->error_reason == Routing_Error_NONE)); // consider only ROUTING_APP message without error as ACK
|
||||
if (isAck && p->to != getNodeNum()) {
|
||||
// do not flood direct message that is ACKed
|
||||
DEBUG_MSG("Receiving an ACK not for me, but don't need to rebroadcast this direct message anymore.\n");
|
||||
LOG_DEBUG("Receiving an ACK not for me, but don't need to rebroadcast this direct message anymore.\n");
|
||||
Router::cancelSending(p->to, p->decoded.request_id); // cancel rebroadcast for this DM
|
||||
} else if ((p->to != getNodeNum()) && (p->hop_limit > 0) && (getFrom(p) != getNodeNum())) {
|
||||
}
|
||||
if ((p->to != getNodeNum()) && (p->hop_limit > 0) && (getFrom(p) != getNodeNum())) {
|
||||
if (p->id != 0) {
|
||||
if (config.device.role != Config_DeviceConfig_Role_CLIENT_MUTE) {
|
||||
MeshPacket *tosend = packetPool.allocCopy(*p); // keep a copy because we will be sending it
|
||||
|
||||
tosend->hop_limit--; // bump down the hop count
|
||||
|
||||
printPacket("Rebroadcasting received floodmsg to neighbors", p);
|
||||
// If it is a traceRoute request, update the route that it went via me
|
||||
if (p->which_payload_variant == MeshPacket_decoded_tag && traceRouteModule->wantPacket(p)) {
|
||||
traceRouteModule->updateRoute(tosend);
|
||||
}
|
||||
|
||||
LOG_INFO("Rebroadcasting received floodmsg to neighbors", p);
|
||||
// Note: we are careful to resend using the original senders node id
|
||||
// We are careful not to call our hooked version of send() - because we don't want to check this again
|
||||
Router::send(tosend);
|
||||
|
||||
} else {
|
||||
DEBUG_MSG("Not rebroadcasting. Role = Role_ClientMute\n");
|
||||
LOG_DEBUG("Not rebroadcasting. Role = Role_ClientMute\n");
|
||||
}
|
||||
|
||||
} else {
|
||||
DEBUG_MSG("Ignoring a simple (0 id) broadcast\n");
|
||||
LOG_DEBUG("Ignoring a simple (0 id) broadcast\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "PacketHistory.h"
|
||||
#include "Router.h"
|
||||
#include "modules/TraceRouteModule.h"
|
||||
|
||||
/**
|
||||
* This is a mixin that extends Router with the ability to do Naive Flooding (in the standard mesh protocol sense)
|
||||
@@ -50,7 +51,7 @@ class FloodingRouter : public Router, protected PacketHistory
|
||||
* Called immedately on receiption, before any further processing.
|
||||
* @return true to abandon the packet
|
||||
*/
|
||||
virtual bool shouldFilterReceived(MeshPacket *p) override;
|
||||
virtual bool shouldFilterReceived(const MeshPacket *p) override;
|
||||
|
||||
/**
|
||||
* Look for broadcasts we need to rebroadcast
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#include "SX126xInterface.h"
|
||||
#include "SX126xInterface.cpp"
|
||||
#include "SX128xInterface.h"
|
||||
#include "SX128xInterface.cpp"
|
||||
|
||||
// We need this declaration for proper linking in derived classes
|
||||
template class SX126xInterface<SX1262>;
|
||||
template class SX126xInterface<SX1268>;
|
||||
template class SX126xInterface<LLCC68>;
|
||||
template class SX126xInterface<LLCC68>;
|
||||
template class SX128xInterface<SX1280>;
|
||||
|
||||
@@ -44,15 +44,15 @@ MeshPacket *MeshModule::allocAckNak(Routing_Error err, NodeNum to, PacketId idFr
|
||||
// auto p = allocDataProtobuf(c);
|
||||
MeshPacket *p = router->allocForSending();
|
||||
p->decoded.portnum = PortNum_ROUTING_APP;
|
||||
p->decoded.payload.size = pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), Routing_fields, &c);
|
||||
p->decoded.payload.size = pb_encode_to_bytes(p->decoded.payload.bytes, sizeof(p->decoded.payload.bytes), &Routing_msg, &c);
|
||||
|
||||
p->priority = MeshPacket_Priority_ACK;
|
||||
|
||||
p->hop_limit = 0; // Assume just immediate neighbors for now
|
||||
p->hop_limit = config.lora.hop_limit; // Flood ACK back to original sender
|
||||
p->to = to;
|
||||
p->decoded.request_id = idFrom;
|
||||
p->channel = chIndex;
|
||||
DEBUG_MSG("Alloc an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id);
|
||||
LOG_ERROR("Alloc an err=%d,to=0x%x,idFrom=0x%x,id=0x%x\n", err, to, idFrom, p->id);
|
||||
|
||||
return p;
|
||||
}
|
||||
@@ -68,7 +68,7 @@ MeshPacket *MeshModule::allocErrorResponse(Routing_Error err, const MeshPacket *
|
||||
|
||||
void MeshModule::callPlugins(const MeshPacket &mp, RxSource src)
|
||||
{
|
||||
// DEBUG_MSG("In call modules\n");
|
||||
// LOG_DEBUG("In call modules\n");
|
||||
bool moduleFound = false;
|
||||
|
||||
// We now allow **encrypted** packets to pass through the modules
|
||||
@@ -96,7 +96,7 @@ void MeshModule::callPlugins(const MeshPacket &mp, RxSource src)
|
||||
assert(!pi.myReply); // If it is !null it means we have a bug, because it should have been sent the previous time
|
||||
|
||||
if (wantsPacket) {
|
||||
DEBUG_MSG("Module '%s' wantsPacket=%d\n", pi.name, wantsPacket);
|
||||
LOG_DEBUG("Module '%s' wantsPacket=%d\n", pi.name, wantsPacket);
|
||||
|
||||
moduleFound = true;
|
||||
|
||||
@@ -109,10 +109,7 @@ void MeshModule::callPlugins(const MeshPacket &mp, RxSource src)
|
||||
/// Also: if a packet comes in on the local PC interface, we don't check for bound channels, because it is TRUSTED and it needs to
|
||||
/// to be able to fetch the initial admin packets without yet knowing any channels.
|
||||
|
||||
bool rxChannelOk = !pi.boundChannel || (mp.from == 0) ||
|
||||
!ch ||
|
||||
strlen(ch->settings.name) > 0 ||
|
||||
(strcasecmp(ch->settings.name, pi.boundChannel) == 0);
|
||||
bool rxChannelOk = !pi.boundChannel || (mp.from == 0) || (strcasecmp(ch->settings.name, pi.boundChannel) == 0);
|
||||
|
||||
if (!rxChannelOk) {
|
||||
// no one should have already replied!
|
||||
@@ -137,20 +134,20 @@ void MeshModule::callPlugins(const MeshPacket &mp, RxSource src)
|
||||
// any other node.
|
||||
if (mp.decoded.want_response && toUs && (getFrom(&mp) != ourNodeNum || mp.to == ourNodeNum) && !currentReply) {
|
||||
pi.sendResponse(mp);
|
||||
DEBUG_MSG("Module '%s' sent a response\n", pi.name);
|
||||
LOG_INFO("Module '%s' sent a response\n", pi.name);
|
||||
} else {
|
||||
DEBUG_MSG("Module '%s' considered\n", pi.name);
|
||||
LOG_DEBUG("Module '%s' considered\n", pi.name);
|
||||
}
|
||||
|
||||
// If the requester didn't ask for a response we might need to discard unused replies to prevent memory leaks
|
||||
if (pi.myReply) {
|
||||
DEBUG_MSG("Discarding an unneeded response\n");
|
||||
LOG_DEBUG("Discarding an unneeded response\n");
|
||||
packetPool.release(pi.myReply);
|
||||
pi.myReply = NULL;
|
||||
}
|
||||
|
||||
if (handled == ProcessMessage::STOP) {
|
||||
DEBUG_MSG("Module '%s' handled and skipped other processing\n", pi.name);
|
||||
LOG_DEBUG("Module '%s' handled and skipped other processing\n", pi.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -168,7 +165,7 @@ void MeshModule::callPlugins(const MeshPacket &mp, RxSource src)
|
||||
// Note: if the message started with the local node we don't want to send a no response reply
|
||||
|
||||
// No one wanted to reply to this requst, tell the requster that happened
|
||||
DEBUG_MSG("No one responded, send a nak\n");
|
||||
LOG_DEBUG("No one responded, send a nak\n");
|
||||
|
||||
// SECURITY NOTE! I considered sending back a different error code if we didn't find the psk (i.e. !isDecoded)
|
||||
// but opted NOT TO. Because it is not a good idea to let remote nodes 'probe' to find out which PSKs were "good" vs
|
||||
@@ -178,7 +175,7 @@ void MeshModule::callPlugins(const MeshPacket &mp, RxSource src)
|
||||
}
|
||||
|
||||
if (!moduleFound)
|
||||
DEBUG_MSG("No modules interested in portnum=%d, src=%s\n",
|
||||
LOG_DEBUG("No modules interested in portnum=%d, src=%s\n",
|
||||
mp.decoded.portnum,
|
||||
(src == RX_SRC_LOCAL) ? "LOCAL":"REMOTE");
|
||||
}
|
||||
@@ -202,7 +199,7 @@ void MeshModule::sendResponse(const MeshPacket &req)
|
||||
currentReply = r;
|
||||
} else {
|
||||
// Ignore - this is now expected behavior for routing module (because it ignores some replies)
|
||||
// DEBUG_MSG("WARNING: Client requested response but this module did not provide\n");
|
||||
// LOG_WARN("Client requested response but this module did not provide\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +227,7 @@ std::vector<MeshModule *> MeshModule::GetMeshModulesWithUIFrames()
|
||||
for (auto i = modules->begin(); i != modules->end(); ++i) {
|
||||
auto &pi = **i;
|
||||
if (pi.wantUIFrame()) {
|
||||
DEBUG_MSG("Module wants a UI Frame\n");
|
||||
LOG_DEBUG("Module wants a UI Frame\n");
|
||||
modulesWithUIFrames.push_back(&pi);
|
||||
}
|
||||
}
|
||||
@@ -247,7 +244,7 @@ void MeshModule::observeUIEvents(
|
||||
Observable<const UIFrameEvent *> *observable =
|
||||
pi.getUIFrameObservable();
|
||||
if (observable != NULL) {
|
||||
DEBUG_MSG("Module wants a UI Frame\n");
|
||||
LOG_DEBUG("Module wants a UI Frame\n");
|
||||
observer->observe(observable);
|
||||
}
|
||||
}
|
||||
@@ -264,7 +261,7 @@ AdminMessageHandleResult MeshModule::handleAdminMessageForAllPlugins(const MeshP
|
||||
if (h == AdminMessageHandleResult::HANDLED_WITH_RESPONSE)
|
||||
{
|
||||
// In case we have a response it always has priority.
|
||||
DEBUG_MSG("Reply prepared by module '%s' of variant: %d\n",
|
||||
LOG_DEBUG("Reply prepared by module '%s' of variant: %d\n",
|
||||
pi.name,
|
||||
response->which_payload_variant);
|
||||
handled = h;
|
||||
|
||||
@@ -15,6 +15,7 @@ struct RegionInfo {
|
||||
uint8_t powerLimit; // Or zero for not set
|
||||
bool audioPermitted;
|
||||
bool freqSwitching;
|
||||
bool wideLora;
|
||||
const char *name; // EU433 etc
|
||||
};
|
||||
|
||||
|
||||
@@ -104,16 +104,17 @@ bool MeshService::reloadConfig(int saveWhat)
|
||||
}
|
||||
|
||||
/// The owner User record just got updated, update our node DB and broadcast the info into the mesh
|
||||
void MeshService::reloadOwner()
|
||||
void MeshService::reloadOwner(bool shouldSave)
|
||||
{
|
||||
// DEBUG_MSG("reloadOwner()\n");
|
||||
// LOG_DEBUG("reloadOwner()\n");
|
||||
// update our local data directly
|
||||
nodeDB.updateUser(nodeDB.getNodeNum(), owner);
|
||||
assert(nodeInfoModule);
|
||||
// update everyone else
|
||||
if (nodeInfoModule)
|
||||
// update everyone else and save to disk
|
||||
if (nodeInfoModule && shouldSave) {
|
||||
nodeInfoModule->sendOurNodeInfo();
|
||||
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
|
||||
nodeDB.saveToDisk(SEGMENT_DEVICESTATE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,7 +140,7 @@ void MeshService::handleToRadio(MeshPacket &p)
|
||||
// Switch the port from PortNum_SIMULATOR_APP back to the original PortNum
|
||||
p.decoded.portnum = decoded->portnum;
|
||||
} else
|
||||
DEBUG_MSG("Error decoding protobuf for simulator message!\n");
|
||||
LOG_ERROR("Error decoding protobuf for simulator message!\n");
|
||||
}
|
||||
// Let SimRadio receive as if it did via its LoRa chip
|
||||
SimRadio::instance->startReceive(&p);
|
||||
@@ -147,7 +148,7 @@ void MeshService::handleToRadio(MeshPacket &p)
|
||||
}
|
||||
#endif
|
||||
if (p.from != 0) { // We don't let phones assign nodenums to their sent messages
|
||||
DEBUG_MSG("Warning: phone tried to pick a nodenum, we don't allow that.\n");
|
||||
LOG_WARN("phone tried to pick a nodenum, we don't allow that.\n");
|
||||
p.from = 0;
|
||||
} else {
|
||||
// p.from = nodeDB.getNodeNum();
|
||||
@@ -197,12 +198,12 @@ void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
|
||||
|
||||
if (node->has_position && (node->position.latitude_i != 0 || node->position.longitude_i != 0)) {
|
||||
if (positionModule) {
|
||||
DEBUG_MSG("Sending position ping to 0x%x, wantReplies=%d\n", dest, wantReplies);
|
||||
LOG_INFO("Sending position ping to 0x%x, wantReplies=%d\n", dest, wantReplies);
|
||||
positionModule->sendOurPosition(dest, wantReplies);
|
||||
}
|
||||
} else {
|
||||
if (nodeInfoModule) {
|
||||
DEBUG_MSG("Sending nodeinfo ping to 0x%x, wantReplies=%d\n", dest, wantReplies);
|
||||
LOG_INFO("Sending nodeinfo ping to 0x%x, wantReplies=%d\n", dest, wantReplies);
|
||||
nodeInfoModule->sendOurNodeInfo(dest, wantReplies);
|
||||
}
|
||||
}
|
||||
@@ -211,7 +212,7 @@ void MeshService::sendNetworkPing(NodeNum dest, bool wantReplies)
|
||||
void MeshService::sendToPhone(MeshPacket *p)
|
||||
{
|
||||
if (toPhoneQueue.numFree() == 0) {
|
||||
DEBUG_MSG("NOTE: tophone queue is full, discarding oldest\n");
|
||||
LOG_WARN("ToPhone queue is full, discarding oldest\n");
|
||||
MeshPacket *d = toPhoneQueue.dequeuePtr(0);
|
||||
if (d)
|
||||
releaseToPool(d);
|
||||
@@ -261,10 +262,10 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
|
||||
// The GPS has lost lock, if we are fixed position we should just keep using
|
||||
// the old position
|
||||
#ifdef GPS_EXTRAVERBOSE
|
||||
DEBUG_MSG("onGPSchanged() - lost validLocation\n");
|
||||
LOG_DEBUG("onGPSchanged() - lost validLocation\n");
|
||||
#endif
|
||||
if (config.position.fixed_position) {
|
||||
DEBUG_MSG("WARNING: Using fixed position\n");
|
||||
LOG_WARN("Using fixed position\n");
|
||||
pos = node->position;
|
||||
}
|
||||
}
|
||||
@@ -275,7 +276,7 @@ int MeshService::onGPSChanged(const meshtastic::GPSStatus *newStatus)
|
||||
pos.time = getValidTime(RTCQualityGPS);
|
||||
|
||||
// In debug logs, identify position by @timestamp:stage (stage 4 = nodeDB)
|
||||
DEBUG_MSG("onGPSChanged() pos@%x, time=%u, lat=%d, lon=%d, alt=%d\n", pos.timestamp, pos.time, pos.latitude_i,
|
||||
LOG_DEBUG("onGPSChanged() pos@%x, time=%u, lat=%d, lon=%d, alt=%d\n", pos.timestamp, pos.time, pos.latitude_i,
|
||||
pos.longitude_i, pos.altitude);
|
||||
|
||||
// Update our current position in the local DB
|
||||
|
||||
@@ -69,7 +69,7 @@ class MeshService
|
||||
bool reloadConfig(int saveWhat=SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS);
|
||||
|
||||
/// The owner User record just got updated, update our node DB and broadcast the info into the mesh
|
||||
void reloadOwner();
|
||||
void reloadOwner(bool shouldSave = true);
|
||||
|
||||
/// Called when the user wakes up our GUI, normally sends our latest location to the mesh (if we have it), otherwise at least
|
||||
/// sends our owner
|
||||
|
||||
@@ -38,6 +38,7 @@ MyNodeInfo &myNodeInfo = devicestate.my_node;
|
||||
LocalConfig config;
|
||||
LocalModuleConfig moduleConfig;
|
||||
ChannelFile channelFile;
|
||||
OEMStore oemStore;
|
||||
|
||||
/** The current change # for radio settings. Starts at 0 on boot and any time the radio settings
|
||||
* might have changed is incremented. Allows others to detect they might now be on a new channel.
|
||||
@@ -85,7 +86,7 @@ bool NodeDB::resetRadioConfig(bool factory_reset)
|
||||
}
|
||||
|
||||
if (channelFile.channels_count != MAX_NUM_CHANNELS) {
|
||||
DEBUG_MSG("Setting default channel and radio preferences!\n");
|
||||
LOG_INFO("Setting default channel and radio preferences!\n");
|
||||
|
||||
channels.initDefaults();
|
||||
}
|
||||
@@ -95,7 +96,7 @@ bool NodeDB::resetRadioConfig(bool factory_reset)
|
||||
// temp hack for quicker testing
|
||||
// devicestate.no_save = true;
|
||||
if (devicestate.no_save) {
|
||||
DEBUG_MSG("***** DEVELOPMENT MODE - DO NOT RELEASE *****\n");
|
||||
LOG_DEBUG("***** DEVELOPMENT MODE - DO NOT RELEASE *****\n");
|
||||
|
||||
// Sleep quite frequently to stress test the BLE comms, broadcast position every 6 mins
|
||||
config.display.screen_on_secs = 10;
|
||||
@@ -113,7 +114,7 @@ bool NodeDB::resetRadioConfig(bool factory_reset)
|
||||
initRegion();
|
||||
|
||||
if (didFactoryReset) {
|
||||
DEBUG_MSG("Rebooting due to factory reset");
|
||||
LOG_INFO("Rebooting due to factory reset");
|
||||
screen->startRebootScreen();
|
||||
rebootAtMsec = millis() + (5 * 1000);
|
||||
}
|
||||
@@ -123,12 +124,14 @@ bool NodeDB::resetRadioConfig(bool factory_reset)
|
||||
|
||||
bool NodeDB::factoryReset()
|
||||
{
|
||||
DEBUG_MSG("Performing factory reset!\n");
|
||||
LOG_INFO("Performing factory reset!\n");
|
||||
// first, remove the "/prefs" (this removes most prefs)
|
||||
rmDir("/prefs");
|
||||
// second, install default state (this will deal with the duplicate mac address issue)
|
||||
installDefaultDeviceState();
|
||||
installDefaultConfig();
|
||||
installDefaultModuleConfig();
|
||||
installDefaultChannels();
|
||||
// third, write everything to disk
|
||||
saveToDisk();
|
||||
#ifdef ARCH_ESP32
|
||||
@@ -137,7 +140,7 @@ bool NodeDB::factoryReset()
|
||||
#endif
|
||||
#ifdef ARCH_NRF52
|
||||
Bluefruit.begin();
|
||||
DEBUG_MSG("Clearing bluetooth bonds!\n");
|
||||
LOG_INFO("Clearing bluetooth bonds!\n");
|
||||
bond_print_list(BLE_GAP_ROLE_PERIPH);
|
||||
bond_print_list(BLE_GAP_ROLE_CENTRAL);
|
||||
Bluefruit.Periph.clearBonds();
|
||||
@@ -148,7 +151,7 @@ bool NodeDB::factoryReset()
|
||||
|
||||
void NodeDB::installDefaultConfig()
|
||||
{
|
||||
DEBUG_MSG("Installing default LocalConfig\n");
|
||||
LOG_INFO("Installing default LocalConfig\n");
|
||||
memset(&config, 0, sizeof(LocalConfig));
|
||||
config.version = DEVICESTATE_CUR_VER;
|
||||
config.has_device = true;
|
||||
@@ -159,6 +162,7 @@ void NodeDB::installDefaultConfig()
|
||||
config.has_network = true;
|
||||
config.has_bluetooth = true;
|
||||
config.lora.tx_enabled = true; // FIXME: maybe false in the future, and setting region to enable it. (unset region forces it off)
|
||||
config.lora.override_duty_cycle = false;
|
||||
config.lora.region = Config_LoRaConfig_RegionCode_UNSET;
|
||||
config.lora.modem_preset = Config_LoRaConfig_ModemPreset_LONG_FAST;
|
||||
config.lora.hop_limit = HOP_RELIABLE;
|
||||
@@ -199,8 +203,9 @@ void NodeDB::initConfigIntervals()
|
||||
|
||||
void NodeDB::installDefaultModuleConfig()
|
||||
{
|
||||
DEBUG_MSG("Installing default ModuleConfig\n");
|
||||
LOG_INFO("Installing default ModuleConfig\n");
|
||||
memset(&moduleConfig, 0, sizeof(ModuleConfig));
|
||||
|
||||
moduleConfig.version = DEVICESTATE_CUR_VER;
|
||||
moduleConfig.has_mqtt = true;
|
||||
moduleConfig.has_range_test = true;
|
||||
@@ -210,6 +215,10 @@ void NodeDB::installDefaultModuleConfig()
|
||||
moduleConfig.has_external_notification = true;
|
||||
moduleConfig.has_canned_message = true;
|
||||
|
||||
strncpy(moduleConfig.mqtt.address, default_mqtt_address, sizeof(moduleConfig.mqtt.address));
|
||||
strncpy(moduleConfig.mqtt.username, default_mqtt_username, sizeof(moduleConfig.mqtt.username));
|
||||
strncpy(moduleConfig.mqtt.password, default_mqtt_password, sizeof(moduleConfig.mqtt.password));
|
||||
|
||||
initModuleConfigIntervals();
|
||||
}
|
||||
|
||||
@@ -221,7 +230,7 @@ void NodeDB::initModuleConfigIntervals()
|
||||
|
||||
void NodeDB::installDefaultChannels()
|
||||
{
|
||||
DEBUG_MSG("Installing default ChannelFile\n");
|
||||
LOG_INFO("Installing default ChannelFile\n");
|
||||
memset(&channelFile, 0, sizeof(ChannelFile));
|
||||
channelFile.version = DEVICESTATE_CUR_VER;
|
||||
}
|
||||
@@ -235,7 +244,7 @@ void NodeDB::resetNodes()
|
||||
|
||||
void NodeDB::installDefaultDeviceState()
|
||||
{
|
||||
DEBUG_MSG("Installing default DeviceState\n");
|
||||
LOG_INFO("Installing default DeviceState\n");
|
||||
memset(&devicestate, 0, sizeof(DeviceState));
|
||||
|
||||
*numNodes = 0;
|
||||
@@ -266,7 +275,7 @@ void NodeDB::installDefaultDeviceState()
|
||||
|
||||
void NodeDB::init()
|
||||
{
|
||||
DEBUG_MSG("Initializing NodeDB\n");
|
||||
LOG_INFO("Initializing NodeDB\n");
|
||||
loadFromDisk();
|
||||
|
||||
uint32_t devicestateCRC = crc32Buffer(&devicestate, sizeof(devicestate));
|
||||
@@ -302,7 +311,7 @@ void NodeDB::init()
|
||||
preferences.begin("meshtastic", false);
|
||||
myNodeInfo.reboot_count = preferences.getUInt("rebootCounter", 0);
|
||||
preferences.end();
|
||||
DEBUG_MSG("Number of Device Reboots: %d\n", myNodeInfo.reboot_count);
|
||||
LOG_DEBUG("Number of Device Reboots: %d\n", myNodeInfo.reboot_count);
|
||||
|
||||
/* The ESP32 has a wifi radio. This will need to be modified at some point so
|
||||
* the test isn't so simplistic.
|
||||
@@ -311,7 +320,7 @@ void NodeDB::init()
|
||||
#endif
|
||||
|
||||
resetRadioConfig(); // If bogus settings got saved, then fix them
|
||||
DEBUG_MSG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numNodes);
|
||||
LOG_DEBUG("region=%d, NODENUM=0x%x, dbsize=%d\n", config.lora.region, myNodeInfo.my_node_num, *numNodes);
|
||||
|
||||
if (devicestateCRC != crc32Buffer(&devicestate, sizeof(devicestate)))
|
||||
saveWhat |= SEGMENT_DEVICESTATE;
|
||||
@@ -343,7 +352,7 @@ void NodeDB::pickNewNodeNum()
|
||||
NodeInfo *found;
|
||||
while ((found = getNode(r)) && memcmp(found->user.macaddr, owner.macaddr, sizeof(owner.macaddr))) {
|
||||
NodeNum n = random(NUM_RESERVED, NODENUM_BROADCAST); // try a new random choice
|
||||
DEBUG_MSG("NOTE! Our desired nodenum 0x%x is in use, so trying for 0x%x\n", r, n);
|
||||
LOG_DEBUG("NOTE! Our desired nodenum 0x%x is in use, so trying for 0x%x\n", r, n);
|
||||
r = n;
|
||||
}
|
||||
|
||||
@@ -354,9 +363,11 @@ static const char *prefFileName = "/prefs/db.proto";
|
||||
static const char *configFileName = "/prefs/config.proto";
|
||||
static const char *moduleConfigFileName = "/prefs/module.proto";
|
||||
static const char *channelFileName = "/prefs/channels.proto";
|
||||
static const char *oemConfigFile = "/oem/oem.proto";
|
||||
|
||||
|
||||
/** Load a protobuf from a file, return true for success */
|
||||
bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct)
|
||||
bool NodeDB::loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct)
|
||||
{
|
||||
bool okay = false;
|
||||
#ifdef FSCom
|
||||
@@ -365,24 +376,24 @@ bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_
|
||||
auto f = FSCom.open(filename, FILE_O_READ);
|
||||
|
||||
if (f) {
|
||||
DEBUG_MSG("Loading %s\n", filename);
|
||||
LOG_INFO("Loading %s\n", filename);
|
||||
pb_istream_t stream = {&readcb, &f, protoSize};
|
||||
|
||||
// DEBUG_MSG("Preload channel name=%s\n", channelSettings.name);
|
||||
// LOG_DEBUG("Preload channel name=%s\n", channelSettings.name);
|
||||
|
||||
memset(dest_struct, 0, objSize);
|
||||
if (!pb_decode(&stream, fields, dest_struct)) {
|
||||
DEBUG_MSG("Error: can't decode protobuf %s\n", PB_GET_ERROR(&stream));
|
||||
LOG_ERROR("Error: can't decode protobuf %s\n", PB_GET_ERROR(&stream));
|
||||
} else {
|
||||
okay = true;
|
||||
}
|
||||
|
||||
f.close();
|
||||
} else {
|
||||
DEBUG_MSG("No %s preferences found\n", filename);
|
||||
LOG_INFO("No %s preferences found\n", filename);
|
||||
}
|
||||
#else
|
||||
DEBUG_MSG("ERROR: Filesystem not implemented\n");
|
||||
LOG_ERROR("ERROR: Filesystem not implemented\n");
|
||||
#endif
|
||||
return okay;
|
||||
}
|
||||
@@ -390,53 +401,56 @@ bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_
|
||||
void NodeDB::loadFromDisk()
|
||||
{
|
||||
// static DeviceState scratch; We no longer read into a tempbuf because this structure is 15KB of valuable RAM
|
||||
if (!loadProto(prefFileName, DeviceState_size, sizeof(devicestate), DeviceState_fields, &devicestate)) {
|
||||
if (!loadProto(prefFileName, DeviceState_size, sizeof(DeviceState), &DeviceState_msg, &devicestate)) {
|
||||
installDefaultDeviceState(); // Our in RAM copy might now be corrupt
|
||||
} else {
|
||||
if (devicestate.version < DEVICESTATE_MIN_VER) {
|
||||
DEBUG_MSG("Warn: devicestate %d is old, discarding\n", devicestate.version);
|
||||
LOG_WARN("Devicestate %d is old, discarding\n", devicestate.version);
|
||||
factoryReset();
|
||||
} else {
|
||||
DEBUG_MSG("Loaded saved devicestate version %d\n", devicestate.version);
|
||||
LOG_INFO("Loaded saved devicestate version %d\n", devicestate.version);
|
||||
}
|
||||
}
|
||||
|
||||
if (!loadProto(configFileName, LocalConfig_size, sizeof(LocalConfig), LocalConfig_fields, &config)) {
|
||||
if (!loadProto(configFileName, LocalConfig_size, sizeof(LocalConfig), &LocalConfig_msg, &config)) {
|
||||
installDefaultConfig(); // Our in RAM copy might now be corrupt
|
||||
} else {
|
||||
if (config.version < DEVICESTATE_MIN_VER) {
|
||||
DEBUG_MSG("Warn: config %d is old, discarding\n", config.version);
|
||||
LOG_WARN("config %d is old, discarding\n", config.version);
|
||||
installDefaultConfig();
|
||||
} else {
|
||||
DEBUG_MSG("Loaded saved config version %d\n", config.version);
|
||||
LOG_INFO("Loaded saved config version %d\n", config.version);
|
||||
}
|
||||
}
|
||||
|
||||
if (!loadProto(moduleConfigFileName, LocalModuleConfig_size, sizeof(LocalModuleConfig), LocalModuleConfig_fields, &moduleConfig)) {
|
||||
if (!loadProto(moduleConfigFileName, LocalModuleConfig_size, sizeof(LocalModuleConfig), &LocalModuleConfig_msg, &moduleConfig)) {
|
||||
installDefaultModuleConfig(); // Our in RAM copy might now be corrupt
|
||||
} else {
|
||||
if (moduleConfig.version < DEVICESTATE_MIN_VER) {
|
||||
DEBUG_MSG("Warn: moduleConfig %d is old, discarding\n", moduleConfig.version);
|
||||
LOG_WARN("moduleConfig %d is old, discarding\n", moduleConfig.version);
|
||||
installDefaultModuleConfig();
|
||||
} else {
|
||||
DEBUG_MSG("Loaded saved moduleConfig version %d\n", moduleConfig.version);
|
||||
LOG_INFO("Loaded saved moduleConfig version %d\n", moduleConfig.version);
|
||||
}
|
||||
}
|
||||
|
||||
if (!loadProto(channelFileName, ChannelFile_size, sizeof(ChannelFile), ChannelFile_fields, &channelFile)) {
|
||||
if (!loadProto(channelFileName, ChannelFile_size, sizeof(ChannelFile), &ChannelFile_msg, &channelFile)) {
|
||||
installDefaultChannels(); // Our in RAM copy might now be corrupt
|
||||
} else {
|
||||
if (channelFile.version < DEVICESTATE_MIN_VER) {
|
||||
DEBUG_MSG("Warn: channelFile %d is old, discarding\n", channelFile.version);
|
||||
LOG_WARN("channelFile %d is old, discarding\n", channelFile.version);
|
||||
installDefaultChannels();
|
||||
} else {
|
||||
DEBUG_MSG("Loaded saved channelFile version %d\n", channelFile.version);
|
||||
LOG_INFO("Loaded saved channelFile version %d\n", channelFile.version);
|
||||
}
|
||||
}
|
||||
|
||||
if (loadProto(oemConfigFile, OEMStore_size, sizeof(OEMStore), &OEMStore_msg, &oemStore))
|
||||
LOG_INFO("Loaded OEMStore\n");
|
||||
}
|
||||
|
||||
/** Save a protobuf from a file, return true for success */
|
||||
bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, const void *dest_struct)
|
||||
bool NodeDB::saveProto(const char *filename, size_t protoSize, const pb_msgdesc_t *fields, const void *dest_struct)
|
||||
{
|
||||
bool okay = false;
|
||||
#ifdef FSCom
|
||||
@@ -445,11 +459,11 @@ bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_
|
||||
filenameTmp += ".tmp";
|
||||
auto f = FSCom.open(filenameTmp.c_str(), FILE_O_WRITE);
|
||||
if (f) {
|
||||
DEBUG_MSG("Saving %s\n", filename);
|
||||
LOG_INFO("Saving %s\n", filename);
|
||||
pb_ostream_t stream = {&writecb, &f, protoSize};
|
||||
|
||||
if (!pb_encode(&stream, fields, dest_struct)) {
|
||||
DEBUG_MSG("Error: can't encode protobuf %s\n", PB_GET_ERROR(&stream));
|
||||
LOG_ERROR("Error: can't encode protobuf %s\n", PB_GET_ERROR(&stream));
|
||||
} else {
|
||||
okay = true;
|
||||
}
|
||||
@@ -457,14 +471,23 @@ bool saveProto(const char *filename, size_t protoSize, size_t objSize, const pb_
|
||||
|
||||
// brief window of risk here ;-)
|
||||
if (FSCom.exists(filename) && !FSCom.remove(filename))
|
||||
DEBUG_MSG("Warning: Can't remove old pref file\n");
|
||||
LOG_WARN("Can't remove old pref file\n");
|
||||
if (!renameFile(filenameTmp.c_str(), filename))
|
||||
DEBUG_MSG("Error: can't rename new pref file\n");
|
||||
LOG_ERROR("Error: can't rename new pref file\n");
|
||||
} else {
|
||||
DEBUG_MSG("Can't write prefs\n");
|
||||
LOG_ERROR("Can't write prefs\n");
|
||||
#ifdef ARCH_NRF52
|
||||
static uint8_t failedCounter = 0;
|
||||
failedCounter++;
|
||||
if(failedCounter >= 2){
|
||||
FSCom.format();
|
||||
//After formatting, the device needs to be restarted
|
||||
nodeDB.resetRadioConfig(true);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
DEBUG_MSG("ERROR: Filesystem not implemented\n");
|
||||
LOG_ERROR("ERROR: Filesystem not implemented\n");
|
||||
#endif
|
||||
return okay;
|
||||
}
|
||||
@@ -475,7 +498,7 @@ void NodeDB::saveChannelsToDisk()
|
||||
#ifdef FSCom
|
||||
FSCom.mkdir("/prefs");
|
||||
#endif
|
||||
saveProto(channelFileName, ChannelFile_size, sizeof(channelFile), ChannelFile_fields, &channelFile);
|
||||
saveProto(channelFileName, ChannelFile_size, &ChannelFile_msg, &channelFile);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -485,7 +508,7 @@ void NodeDB::saveDeviceStateToDisk()
|
||||
#ifdef FSCom
|
||||
FSCom.mkdir("/prefs");
|
||||
#endif
|
||||
saveProto(prefFileName, DeviceState_size, sizeof(devicestate), DeviceState_fields, &devicestate);
|
||||
saveProto(prefFileName, DeviceState_size, &DeviceState_msg, &devicestate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,7 +530,7 @@ void NodeDB::saveToDisk(int saveWhat)
|
||||
config.has_power = true;
|
||||
config.has_network = true;
|
||||
config.has_bluetooth = true;
|
||||
saveProto(configFileName, LocalConfig_size, sizeof(config), LocalConfig_fields, &config);
|
||||
saveProto(configFileName, LocalConfig_size, &LocalConfig_msg, &config);
|
||||
}
|
||||
|
||||
if (saveWhat & SEGMENT_MODULECONFIG) {
|
||||
@@ -518,14 +541,14 @@ void NodeDB::saveToDisk(int saveWhat)
|
||||
moduleConfig.has_serial = true;
|
||||
moduleConfig.has_store_forward = true;
|
||||
moduleConfig.has_telemetry = true;
|
||||
saveProto(moduleConfigFileName, LocalModuleConfig_size, sizeof(moduleConfig), LocalModuleConfig_fields, &moduleConfig);
|
||||
saveProto(moduleConfigFileName, LocalModuleConfig_size, &LocalModuleConfig_msg, &moduleConfig);
|
||||
}
|
||||
|
||||
if (saveWhat & SEGMENT_CHANNELS) {
|
||||
saveChannelsToDisk();
|
||||
}
|
||||
} else {
|
||||
DEBUG_MSG("***** DEVELOPMENT MODE - DO NOT RELEASE - not saving to flash *****\n");
|
||||
LOG_DEBUG("***** DEVELOPMENT MODE - DO NOT RELEASE - not saving to flash *****\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -576,14 +599,14 @@ void NodeDB::updatePosition(uint32_t nodeId, const Position &p, RxSource src)
|
||||
|
||||
if (src == RX_SRC_LOCAL) {
|
||||
// Local packet, fully authoritative
|
||||
DEBUG_MSG("updatePosition LOCAL pos@%x, time=%u, latI=%d, lonI=%d, alt=%d\n", p.timestamp, p.time, p.latitude_i,
|
||||
LOG_INFO("updatePosition LOCAL pos@%x, time=%u, latI=%d, lonI=%d, alt=%d\n", p.timestamp, p.time, p.latitude_i,
|
||||
p.longitude_i, p.altitude);
|
||||
info->position = p;
|
||||
|
||||
} else if ((p.time > 0) && !p.latitude_i && !p.longitude_i && !p.timestamp && !p.location_source) {
|
||||
// FIXME SPECIAL TIME SETTING PACKET FROM EUD TO RADIO
|
||||
// (stop-gap fix for issue #900)
|
||||
DEBUG_MSG("updatePosition SPECIAL time setting time=%u\n", p.time);
|
||||
LOG_DEBUG("updatePosition SPECIAL time setting time=%u\n", p.time);
|
||||
info->position.time = p.time;
|
||||
|
||||
} else {
|
||||
@@ -592,7 +615,7 @@ void NodeDB::updatePosition(uint32_t nodeId, const Position &p, RxSource src)
|
||||
// recorded based on the packet rxTime
|
||||
//
|
||||
// FIXME perhaps handle RX_SRC_USER separately?
|
||||
DEBUG_MSG("updatePosition REMOTE node=0x%x time=%u, latI=%d, lonI=%d\n", nodeId, p.time, p.latitude_i, p.longitude_i);
|
||||
LOG_INFO("updatePosition REMOTE node=0x%x time=%u, latI=%d, lonI=%d\n", nodeId, p.time, p.latitude_i, p.longitude_i);
|
||||
|
||||
// First, back up fields that we want to protect from overwrite
|
||||
uint32_t tmp_time = info->position.time;
|
||||
@@ -622,9 +645,9 @@ void NodeDB::updateTelemetry(uint32_t nodeId, const Telemetry &t, RxSource src)
|
||||
|
||||
if (src == RX_SRC_LOCAL) {
|
||||
// Local packet, fully authoritative
|
||||
DEBUG_MSG("updateTelemetry LOCAL\n");
|
||||
LOG_DEBUG("updateTelemetry LOCAL\n");
|
||||
} else {
|
||||
DEBUG_MSG("updateTelemetry REMOTE node=0x%x \n", nodeId);
|
||||
LOG_DEBUG("updateTelemetry REMOTE node=0x%x \n", nodeId);
|
||||
}
|
||||
info->device_metrics = t.variant.device_metrics;
|
||||
info->has_device_metrics = true;
|
||||
@@ -641,13 +664,13 @@ void NodeDB::updateUser(uint32_t nodeId, const User &p)
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_MSG("old user %s/%s/%s\n", info->user.id, info->user.long_name, info->user.short_name);
|
||||
LOG_DEBUG("old user %s/%s/%s\n", info->user.id, info->user.long_name, info->user.short_name);
|
||||
|
||||
bool changed = memcmp(&info->user, &p,
|
||||
sizeof(info->user)); // Both of these blocks start as filled with zero so I think this is okay
|
||||
|
||||
info->user = p;
|
||||
DEBUG_MSG("updating changed=%d user %s/%s/%s\n", changed, info->user.id, info->user.long_name, info->user.short_name);
|
||||
LOG_DEBUG("updating changed=%d user %s/%s/%s\n", changed, info->user.id, info->user.long_name, info->user.short_name);
|
||||
info->has_user = true;
|
||||
|
||||
if (changed) {
|
||||
@@ -666,7 +689,7 @@ void NodeDB::updateUser(uint32_t nodeId, const User &p)
|
||||
void NodeDB::updateFrom(const MeshPacket &mp)
|
||||
{
|
||||
if (mp.which_payload_variant == MeshPacket_decoded_tag && mp.from) {
|
||||
DEBUG_MSG("Update DB node 0x%x, rx_time=%u\n", mp.from, mp.rx_time);
|
||||
LOG_DEBUG("Update DB node 0x%x, rx_time=%u\n", mp.from, mp.rx_time);
|
||||
|
||||
NodeInfo *info = getOrCreateNode(getFrom(&mp));
|
||||
if (!info) {
|
||||
@@ -733,9 +756,9 @@ void recordCriticalError(CriticalErrorCode code, uint32_t address, const char *f
|
||||
String lcd = String("Critical error ") + code + "!\n";
|
||||
screen->print(lcd.c_str());
|
||||
if (filename)
|
||||
DEBUG_MSG("NOTE! Recording critical error %d at %s:%lx\n", code, filename, address);
|
||||
LOG_ERROR("NOTE! Recording critical error %d at %s:%lu\n", code, filename, address);
|
||||
else
|
||||
DEBUG_MSG("NOTE! Recording critical error %d, address=%lx\n", code, address);
|
||||
LOG_ERROR("NOTE! Recording critical error %d, address=0x%lx\n", code, address);
|
||||
|
||||
// Record error to DB
|
||||
myNodeInfo.error_code = code;
|
||||
@@ -744,7 +767,7 @@ void recordCriticalError(CriticalErrorCode code, uint32_t address, const char *f
|
||||
|
||||
// Currently portuino is mostly used for simulation. Make sue the user notices something really bad happend
|
||||
#ifdef ARCH_PORTDUINO
|
||||
DEBUG_MSG("A critical failure occurred, portduino is exiting...");
|
||||
LOG_ERROR("A critical failure occurred, portduino is exiting...");
|
||||
exit(2);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ DeviceState versions used to be defined in the .proto file but really only this
|
||||
#define SEGMENT_DEVICESTATE 4
|
||||
#define SEGMENT_CHANNELS 8
|
||||
|
||||
#define DEVICESTATE_CUR_VER 19
|
||||
#define DEVICESTATE_CUR_VER 20
|
||||
#define DEVICESTATE_MIN_VER DEVICESTATE_CUR_VER
|
||||
|
||||
extern DeviceState devicestate;
|
||||
@@ -26,6 +26,7 @@ extern ChannelFile channelFile;
|
||||
extern MyNodeInfo &myNodeInfo;
|
||||
extern LocalConfig config;
|
||||
extern LocalModuleConfig moduleConfig;
|
||||
extern OEMStore oemStore;
|
||||
extern User &owner;
|
||||
|
||||
/// Given a node, return how many seconds in the past (vs now) that we last heard from it
|
||||
@@ -57,7 +58,7 @@ class NodeDB
|
||||
void init();
|
||||
|
||||
/// write to flash
|
||||
void saveToDisk(int saveWhat=SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS), saveChannelsToDisk(), saveDeviceStateToDisk();
|
||||
void saveToDisk(int saveWhat = SEGMENT_CONFIG | SEGMENT_MODULECONFIG | SEGMENT_DEVICESTATE | SEGMENT_CHANNELS), saveChannelsToDisk(), saveDeviceStateToDisk();
|
||||
|
||||
/** Reinit radio config if needed, because either:
|
||||
* a) sometimes a buggy android app might send us bogus settings or
|
||||
@@ -124,6 +125,9 @@ class NodeDB
|
||||
|
||||
bool factoryReset();
|
||||
|
||||
bool loadProto(const char *filename, size_t protoSize, size_t objSize, const pb_msgdesc_t *fields, void *dest_struct);
|
||||
bool saveProto(const char *filename, size_t protoSize, const pb_msgdesc_t *fields, const void *dest_struct);
|
||||
|
||||
private:
|
||||
/// Find a node in our DB, create an empty NodeInfo if missing
|
||||
NodeInfo *getOrCreateNode(NodeNum n);
|
||||
@@ -193,6 +197,10 @@ extern NodeDB nodeDB;
|
||||
#define default_min_wake_secs 10
|
||||
#define default_screen_on_secs 60 * 10
|
||||
|
||||
#define default_mqtt_address "mqtt.meshtastic.org"
|
||||
#define default_mqtt_username "meshdev"
|
||||
#define default_mqtt_password "large4cats"
|
||||
|
||||
inline uint32_t getConfiguredOrDefaultMs(uint32_t configuredInterval)
|
||||
{
|
||||
if (configuredInterval > 0) return configuredInterval * 1000;
|
||||
|
||||
@@ -14,7 +14,7 @@ PacketHistory::PacketHistory()
|
||||
bool PacketHistory::wasSeenRecently(const MeshPacket *p, bool withUpdate)
|
||||
{
|
||||
if (p->id == 0) {
|
||||
DEBUG_MSG("Ignoring message with zero id\n");
|
||||
LOG_DEBUG("Ignoring message with zero id\n");
|
||||
return false; // Not a floodable message ID, so we don't care
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ bool PacketHistory::wasSeenRecently(const MeshPacket *p, bool withUpdate)
|
||||
}
|
||||
|
||||
if (seenRecently) {
|
||||
DEBUG_MSG("Found existing packet record for fr=0x%x,to=0x%x,id=0x%x\n", p->from, p->to, p->id);
|
||||
LOG_DEBUG("Found existing packet record for fr=0x%x,to=0x%x,id=0x%x\n", p->from, p->to, p->id);
|
||||
}
|
||||
|
||||
if (withUpdate) {
|
||||
@@ -61,7 +61,7 @@ bool PacketHistory::wasSeenRecently(const MeshPacket *p, bool withUpdate)
|
||||
void PacketHistory::clearExpiredRecentPackets() {
|
||||
uint32_t now = millis();
|
||||
|
||||
DEBUG_MSG("recentPackets size=%ld\n", recentPackets.size());
|
||||
LOG_DEBUG("recentPackets size=%ld\n", recentPackets.size());
|
||||
|
||||
for (auto it = recentPackets.begin(); it != recentPackets.end(); ) {
|
||||
if ((now - it->rxTimeMsec) >= FLOOD_EXPIRE_TIME) {
|
||||
@@ -71,5 +71,5 @@ void PacketHistory::clearExpiredRecentPackets() {
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_MSG("recentPackets size=%ld (after clearing expired packets)\n", recentPackets.size());
|
||||
LOG_DEBUG("recentPackets size=%ld (after clearing expired packets)\n", recentPackets.size());
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user